Skip to content

Commit

Permalink
Update IA SDK to 3.2.1 (#44)
Browse files Browse the repository at this point in the history
Add geofence and POI support.
  • Loading branch information
gitjuba committed Mar 27, 2020
1 parent 5df0321 commit 3012d88
Show file tree
Hide file tree
Showing 17 changed files with 755 additions and 88 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,8 @@
Version 3.2.1 - March 2020
----------------
* Add geofence and POI support
* Update IndoorAtlas SDKs to 3.2.1

Version 3.1.4 - February 2020
----------------
* Update IndoorAtlas SDKs to 3.1.4
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-indooratlas",
"version": "3.1.4",
"version": "3.2.1",
"description": "Cordova plugin using IndoorAtlas SDK.",
"cordova": {
"id": "cordova-plugin-indooratlas",
Expand Down
16 changes: 7 additions & 9 deletions plugin.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
id="cordova-plugin-indooratlas"
version="3.1.4">
version="3.2.1">

<name>IndoorAtlas</name>
<description>IndoorAtlas Cordova Plugin.</description>
Expand Down Expand Up @@ -41,6 +41,12 @@
<js-module src="www/Route.js" name="Route">
<clobbers target="IndoorAtlas.Route"/>
</js-module>
<js-module src="www/Geofence.js" name="Geofence">
<clobbers target="IndoorAtlas.Geofence"/>
</js-module>
<js-module src="www/POI.js" name="POI">
<clobbers target="IndoorAtlas.POI"/>
</js-module>
<js-module src="www/IndoorAtlas.js" name="IndoorAtlas">
<merges target="IndoorAtlas"/>
</js-module>
Expand All @@ -50,14 +56,6 @@
<config-file target="*-Info.plist" parent="NSLocationWhenInUseUsageDescription">
<string>Platform location requested for better indoor positioning experience.</string>
</config-file>
<config-file target="*-Info.plist" parent="IAWrapper">
<dict>
<key>name</key>
<string>cordova</string>
<key>version</key>
<string>3.0.2</string>
</dict>
</config-file>
<framework src="CFNetwork.framework"/>
<framework src="CoreLocation.framework"/>
<framework src="CoreMotion.framework"/>
Expand Down
102 changes: 102 additions & 0 deletions src/android/IALocationPlugin.java
@@ -1,5 +1,10 @@
package com.ialocation.plugin;

import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.Collections;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
Expand All @@ -15,6 +20,8 @@
import com.indooratlas.android.sdk.IAOrientationRequest;
import com.indooratlas.android.sdk.IAOrientationListener;
import com.indooratlas.android.sdk.IAWayfindingRequest;
import com.indooratlas.android.sdk.IAGeofence;
import com.indooratlas.android.sdk.IAGeofenceRequest;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
Expand Down Expand Up @@ -191,6 +198,16 @@ public boolean execute(String action, JSONArray args, CallbackContext callbackCo
requestWayfindingUpdates(lat, lon, floor, callbackContext);
} else if ("removeWayfindingUpdates".equals(action)) {
removeWayfindingUpdates();
} else if ("watchGeofences".equals(action)) {
watchGeofences(callbackContext);
} else if ("clearGeofenceWatch".equals(action)) {
clearGeofenceWatch();
} else if ("addDynamicGeofence".equals(action)) {
JSONObject geofence = args.getJSONObject(0);
addDynamicGeofence(geofence);
} else if ("removeDynamicGeofence".equals(action)) {
JSONObject geofence = args.getJSONObject(0);
removeDynamicGeofence(geofence);
} else if ("lockFloor".equals(action)) {
int floorNumber = args.getInt(0);
lockFloor(floorNumber);
Expand Down Expand Up @@ -370,6 +387,91 @@ public void run() {
});
}

private IAGeofence geofenceFromJsonObject(JSONObject geoJson) {
try {
List<double[]> iaEdges = new ArrayList<>();
JSONObject geometry = geoJson.getJSONObject("geometry");
JSONObject properties = geoJson.getJSONObject("properties");
JSONArray coordinates = geometry.getJSONArray("coordinates");
JSONArray linearRing = coordinates.getJSONArray(0);
for (int i = 0; i < linearRing.length(); i++) {
JSONArray vertex = linearRing.getJSONArray(i);
iaEdges.add(new double[] {vertex.getDouble(1), vertex.getDouble(0)});
}
JSONObject payload = new JSONObject();
if (properties.has("payload")) {
payload = properties.getJSONObject("payload");
}
IAGeofence iaGeofence = new IAGeofence.Builder()
.withId(geoJson.getString("id"))
.withName(properties.getString("name"))
.withFloor(properties.getInt("floor"))
.withPayload(payload)
.withEdges(iaEdges)
.build();
return iaGeofence;
} catch (JSONException e) {
Log.e(TAG, "error reading geofence geojson: " + e.getMessage());
throw new IllegalStateException(e.getMessage());
}
}

private void watchGeofences(CallbackContext callbackContext) {
getListener(this).addGeofences(callbackContext);
cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mLocationManager.addGeofences(
new IAGeofenceRequest.Builder()
.withCloudGeofences(true)
.build(),
getListener(IALocationPlugin.this)
);
}
});
}

private void clearGeofenceWatch() {
getListener(this).removeGeofenceUpdates();
cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mLocationManager.removeGeofenceUpdates(getListener(IALocationPlugin.this));
}
});
}

private void addDynamicGeofence(JSONObject geoJson) {
IAGeofence iaGeofence = geofenceFromJsonObject(geoJson);
cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mLocationManager.addGeofences(
new IAGeofenceRequest.Builder()
.withGeofence(iaGeofence)
.withCloudGeofences(true)
.build(),
getListener(IALocationPlugin.this)
);
}
});
}

private void removeDynamicGeofence(JSONObject geoJson) {
List<String> geofenceIds = new ArrayList<>();
try {
geofenceIds.add(geoJson.getString("id"));
} catch (JSONException e) {
throw new IllegalStateException(e.getMessage());
}
cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mLocationManager.removeGeofences(geofenceIds);
}
});
}

private void lockFloor(final int floorNumber) {
cordova.getActivity().runOnUiThread(new Runnable() {
@Override
Expand Down
120 changes: 119 additions & 1 deletion src/android/IndoorLocationListener.java
Expand Up @@ -10,6 +10,10 @@
import com.indooratlas.android.sdk.IARoute;
import com.indooratlas.android.sdk.IAOrientationListener;
import com.indooratlas.android.sdk.IAWayfindingListener;
import com.indooratlas.android.sdk.IAGeofence;
import com.indooratlas.android.sdk.IAGeofenceEvent;
import com.indooratlas.android.sdk.IAGeofenceListener;
import com.indooratlas.android.sdk.IAPOI;
import com.indooratlas.android.sdk.resources.IAFloorPlan;
import com.indooratlas.android.sdk.resources.IALatLng;
import com.indooratlas.android.sdk.resources.IAVenue;
Expand All @@ -26,7 +30,8 @@
/**
* Handles events from IALocationListener and IARegion.Listener and relays them to Javascript callbacks.
*/
public class IndoorLocationListener implements IALocationListener, IARegion.Listener, IAOrientationListener, IAWayfindingListener {
public class IndoorLocationListener implements IALocationListener, IARegion.Listener, IAOrientationListener,
IAWayfindingListener, IAGeofenceListener {
private static final String TAG = "IndoorLocationListener";

private static final int TRANSITION_TYPE_UNKNOWN = 0;
Expand All @@ -39,6 +44,7 @@ public class IndoorLocationListener implements IALocationListener, IARegion.List
private CallbackContext headingUpdateCallbackContext;
private CallbackContext statusUpdateCallbackContext;
private CallbackContext wayfindingUpdateCallbackContext;
private CallbackContext geofenceCallbackContext;
private ArrayList<CallbackContext> mCallbacks = new ArrayList<CallbackContext>();
private CallbackContext mCallbackContext;
public IALocation lastKnownLocation = null;
Expand Down Expand Up @@ -134,6 +140,14 @@ public void requestWayfindingUpdates(CallbackContext callbackContext) {
wayfindingUpdateCallbackContext = callbackContext;
}

public void addGeofences(CallbackContext callbackContext) {
geofenceCallbackContext = callbackContext;
}

public void removeGeofenceUpdates() {
geofenceCallbackContext = null;
}

/**
* Returns the sum of the all callback collections
* @return
Expand Down Expand Up @@ -269,6 +283,16 @@ private JSONObject getRegionJSONFromIARegion(IARegion iaRegion, int transitionTy
venueFloorPlans.put(getFloorPlanJSONFromIAFloorPlan(venueFloorPlan));
}
venueData.put("floorPlans", venueFloorPlans);
JSONArray venueGeofences = new JSONArray();
for (IAGeofence geofence : venue.getGeofences()) {
venueGeofences.put(getGeojsonFromIaGeofence(geofence));
}
venueData.put("geofences", venueGeofences);
JSONArray venuePois = new JSONArray();
for (IAPOI poi : venue.getPOIs()) {
venuePois.put(getPoiJsonFromIaPoi(poi));
}
venueData.put("pois", venuePois);
regionData.put("venue", venueData);
}

Expand Down Expand Up @@ -565,4 +589,98 @@ public void onWayfindingUpdate(IARoute route) {
wayfindingUpdateCallbackContext.sendPluginResult(pluginResult);
}
}

private JSONObject getGeojsonFromIaGeofence(IAGeofence iaGeofence) {
try {
JSONObject geoJson = new JSONObject();

JSONObject properties = new JSONObject();
properties.put("name", iaGeofence.getName());
properties.put("floor", iaGeofence.getFloor());
properties.put("payload", iaGeofence.getPayload());
geoJson.put("properties", properties);

JSONObject geometry = new JSONObject();
JSONArray coordinates = new JSONArray();
JSONArray linearRing = new JSONArray();
for (double[] iaEdge : iaGeofence.getEdges()) {
JSONArray vertex = new JSONArray();
vertex.put(iaEdge[1]);
vertex.put(iaEdge[0]);
linearRing.put(vertex);
}
geometry.put("type", "Polygon");
coordinates.put(linearRing);
geometry.put("coordinates", coordinates);

geoJson.put("type", "Feature");
geoJson.put("id", iaGeofence.getId());
geoJson.put("geometry", geometry);

return geoJson;
} catch (JSONException e) {
throw new IllegalStateException(e.getMessage());
}
}

private JSONObject getPoiJsonFromIaPoi(IAPOI iaPoi) {
try {
JSONObject poi = new JSONObject();

JSONObject properties = new JSONObject();
properties.put("name", iaPoi.getName());
properties.put("floor", iaPoi.getFloor());
properties.put("payload", iaPoi.getPayload());
poi.put("properties", properties);

JSONObject geometry = new JSONObject();
JSONArray coordinates = new JSONArray();
coordinates.put(iaPoi.getLocation().longitude);
coordinates.put(iaPoi.getLocation().latitude);
geometry.put("type", "Point");
geometry.put("coordinates", coordinates);

poi.put("type", "Feature");
poi.put("id", iaPoi.getId());
poi.put("geometry", geometry);

return poi;
} catch (JSONException e) {
throw new IllegalStateException(e.getMessage());
}
}

// Cordova plugin uses string literals "ENTER" and "EXIT" instead of enums.
private String geofenceToRegionTransitionType(int geofenceTransitionType) {
if (geofenceTransitionType == IAGeofence.GEOFENCE_TRANSITION_ENTER) {
return "ENTER";
} else if (geofenceTransitionType == IAGeofence.GEOFENCE_TRANSITION_EXIT) {
return "EXIT";
} else {
return "UNKNOWN";
}
}

@Override
public void onGeofencesTriggered(IAGeofenceEvent event) {
if (geofenceCallbackContext != null) {
for (IAGeofence iaGeofence : event.getTriggeringGeofences()) {
try {
String transitionType = geofenceToRegionTransitionType(event.getGeofenceTransition());
JSONObject geoJson = getGeojsonFromIaGeofence(iaGeofence);
JSONObject result = new JSONObject();
result.put("transitionType", transitionType);
result.put("geoJson", geoJson);
PluginResult pluginResult = new PluginResult(
PluginResult.Status.OK,
result
);
pluginResult.setKeepCallback(true);
geofenceCallbackContext.sendPluginResult(pluginResult);
} catch (JSONException e) {
throw new IllegalStateException(e.getMessage());
}
}
}
}
}
7 changes: 2 additions & 5 deletions src/android/indooratlas.gradle
Expand Up @@ -3,12 +3,9 @@ repositories {
maven {
url "https://indooratlas-ltd.bintray.com/mvn-public/"
}
maven {
url "https://indooratlas-ltd.bintray.com/mvn-public-beta/"
}
}

dependencies {
compile 'com.android.support:appcompat-v7:27.0.2'
compile 'com.indooratlas.android:indooratlas-android-sdk:3.1.4'
implementation 'com.android.support:appcompat-v7:27.0.2'
implementation 'com.indooratlas.android:indooratlas-android-sdk:3.2.1'
}

0 comments on commit 3012d88

Please sign in to comment.