Getting started on Android
Installation
IDE integration
The Android API integration is fully supported in Eclipse ADT. Android Studio/Gradle integration is possible but will not be described in the following article. Integrate at your own risk.
Looking for an older version?
You can get an older version of the SDK in the Downloads section.
Project setup
Insiteo's API is provided as an Eclipse Android library project. To use it, you will need to link your application project to our library. To do so under Eclipse, you have to select your project in the package explorer panel and right click -> Properties -> Android -> Add ... and select the corresponding project InsiteoAPI_Lib.
Requirements
Furthermore in order to grant all required access to our API you will need to add the following permissions to your android AndroidManifest.xml
between the <manifest> <manifest/>
tag :
// Required by CommonAPI_Lib
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
// Required by LocationAPI_Lib for GPS, WIFI and BLE scan
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
In order to use our location service you also have to add its declaration to your android AndroidManifest.xml
between the
<application> <application/>
tag :
// CAUTION: make sure to declare the location service.
<service android:name="com.insiteo.lbs.location.LocationService" />
Supported architecture and OS
Our library is compatible from Android API 9
(ie Android 2.3) and up to recent one and supports the following
architecture: armeabi
, armeabi-v7a
and x86
.
Initialization
Start the API
Don't forget your API key
Before any interaction with Insiteo's API you must set your API KEY via InitProvider.getInstance().setAPIKey(API_KEY);
. This key can be found in your INSITEO account on the back office.
The first step to access Insiteo's services, is to initialize our API via the InitProvider
singleton. This will be done with the startAPI
and we will give you the data to pass (ie the EServerType, the site identifier and the language).
Use the appropriate server type
The initialization process requires a EServerType that can take the following values :
EServerType.DEV
,
EServerType.TEST
or
EServerType.PROD
. Depending on its values the downloaded data will be stored under the appropriate folder on the SD Card (respectively 'insiteo/dev', 'insiteo/test' and 'insiteo/release').
You can now safely start Insiteo API by calling startAPI(...)
,
with an IInitListener
passed as parameter.
The onInitDone
method will be called on your listener when initialization is finished.
int SITE_ID = 300;
String SITE_LANG = "fr";
EServerType SERVER = EServerType.TEST;
private void initAPI() {
final InitProvider initProvider = InitProvider.getInstance();
// Set the Insiteo API key in order to use the SDK
initProvider.setAPIKey(MY-API-KEY);
// Launch the initialization process, the returned ICancelable can be used to cancel
// the initialization task.
ICancelable mInitTask = initProvider.startAPI(activity, SERVER, SITE_ID, SITE_LANG, listener);
(...)
}
/**
* Callback received on API server initialization
*/
@Override
public void onInitDone(final EInitResult aInitRes, final InsiteoError aError) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mInitProgress.dismiss();
switch (aInitRes) {
case FAIL:
/**
* Initialization failed, you can check the InsiteoError for further
* information. In this case the API can still be used if the packages
* were already downloaded but some services such as Meetme will not
* be functional.
*/
break;
case SUCCESS:
/**
* Initialization succeeded and no new data are required to be download.
* The Application can use all the LBS services as they are.
*/
break;
case SUCCESS_WITH_NEW_DATA:
/**
* Initialization succeeded and new data are available. If the
* application is launched for the first time the data will be
* required for the application to work (for example to download
* the map tiles) so the download process must be triggered.
* Otherwise those data are optional.
*/
break;
}
}
});
}
Handle the initialization process in background
startAPI(...)
method is asynchronous.
Be sure to provide a valid IInitListener
, to be notified of init ending.
If startAPI(...)
returns:
-
SUCCESS
, you can use INSITEO APIs straight away. -
SUCCESS_NEW_DATA
, it means that new data packages are available on INSITEO servers. You can then call theupdatePackages
method on theInitProvider
singleton in order to download and install new data (update is asynchronous, thus its result will be send to the listener, through theonDataUpdateDone
callback). -
FAIL
, it means that INSITEO servers could not be reached. If you want to use an INSITEO module, you have to check if your application has enough data to run. This can be done usinghasPackage
.
Handle data updates
InitProvider
as below:
// Trigger the package update. Like the initialization the
// ICancelable task can be used to be cancel the update.
ICancelable mUpdateTask = InitProvider.getInstance().updatePackages(activity, listener, false);
// The following callbacks will be notified.
/**
* Callback received when the download of new data is processing.
* Those data can be used to notified the user.
*/
@Override
public void onDownloadProgress(long aDownloadedBytes, long aTotalBytes) {
}
/**
* Callback received when a new package is starting being downloaded
*/
@Override
public void onPackageDowloadBegin(EPackageType aPkgType) {
}
/**
* Callback received when the installation of new data is processing.
* Those data can be used to notified the user.
*/
@Override
public void onInstallProgress(long aCurrentFile, long aTotalFiles) {
}
/**
* Callback received when the entire process of data update is done
*/
@Override
public void onDataUpdateDone(final boolean aSuccess, final InsiteoError aError) {
}
Update only what you need
You can also call the update method with a list of specific package to update but they must be at least in the list of getPackagesToUpdate().
Handle the update process in background
updatePackages
method is asynchronous.
Be sure to provide a valid IInitListener
, to be notified of initialization events.
When updating packages, the IInitListener
will receive notifications for packages download progress, and then for packages install progress. Once the update is finished, the
IInitListener
will receive an onDataUpdateDone
event.
When calling updatePackages
, an
ICancelable
is returned. Call cancel on this object to cancel the current update.
Deleting your local data
If your want to delete all the package data that were downloaded you have to remove the 'delete_me' and 'insiteo/{server}/{site_id}' directories from you SD card.
Map
Packages dependencies
Be aware that you need to have installed at least the following packages:
-
A
MAPDATA
package, which contains maps information such as zoom levels and scales. -
And a
TILES
package, which contains.3cm
files that will be displayed.
InitProvider.getInstance().hasPackage(EPackageType.MAP_DATA);
.
Adding graphical objects on map
An Map2DView
is provided and can be used to display a specific 2D map with specific interactive areas. The API also provides advanced features such as additional rendering layouts management (promotional,
special areas etc …) or specific events handling.
By default, the Map2DView
will display a tiled map of the site, and provide basic functions on this map (such as move, center, and pinch to zoom). But it also allows you to display custom interactive objects on
this map. This will be done using custom renderers and custom render touch objects using the IRTO
listener.
The Map2DView
will handle the drawing of the map and all objects. It will loop over all the renderers and call their draw method.
Each renderer owns a list of IRTO
. In its draw method, the renderer will loop on this list, and call draw on each IRTO
.
The Map2DView
will also detect touches, and dispatch them to all IRTO
.
A listener can be set on the map view, to be notified of clicks on specific IRTO
class (see MapView
class documentation).
The Map2DView
will also detect touches, and dispatch them to all IRTO
. A listener can be set on the map controller, to be notified of clicks on specific IRTO
class (see Map2DView
class documentation).
Your Activity
using the Map2DView
will also have to implements the IMapListener
MapAPI
, you will need to get an Map2DView
instance:
//MapView initialization in JAVA
Map2DView mMapView = new Map2DView(getActivity());
// or in xml
<com.insiteo.map.Map2DView
android:id="@+id/insiteo_map"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
Prerequisites
-
You will need to initialize
InitProvider
before instantiatingMap2DView
. -
Map2DView
events will be notified via theIMapListener
interface. The singleIMapListener
associated to the map is by default theContext
that created it (theActivity
in most cases) but can be change with theMapView#setListener(IMapListener aListener)
method (useful when your using theMap2DView
in aFragment
).
Create your own IRenderer
A renderer is a class that defines drawing behavior for a certain type of IRTO
. If you want to use your own customized renderer, you will need to create a
class that implements the IRenderer
interface. Then you will be able to specify the renderer behavior through the draw method for example. You will also have
to set a priority to your renderer that will define the order in which they will be drawn (highest priority will appear on top of the map).
To register a new renderer as a map's renderer, simply do like this:
//How to add a custom renderer
mMapView.addRenderer(mCustomRenderer);
Where to find my IRTO?
All IRTO
of class corresponding to the custom renderer class, when added via Map2DView
, will be put in custom renderer. See "Use your own IRTO"
chapter below.
You will also need to implement an exhaustive list of functions described in the listener. See the complete documentation for more details.
Create your own IRTO
IRTO
listener. Then you will be able to specify your object's behavior through methods like:
//The method you will need to override in order to manually manage your object rendering
public void draw(Canvas aCanvas, double aRatio, Point aOffset, float aAngle){
}
Use existing components
You can now also extends the GenericRTO
.
Most of the basic features that are required for a IRTO
are implemented in this example.
//The method you will need to override in order to manually manage touch down events
public ETouchObjectResult onTouchDown(Touch aTouch){
}
Map2DView
, using the following methods:
//Methods you will need to call in order to add an RTO on the map
public boolean addRTO(IRTO aObject);
public boolean addRTOInZone(int aZoneID, IRTO aObject);
IMapListener
following callback:
//The method you will need to override handle touch events on interactive zones
public void onZoneClicked(int aZoneID, EZoneAction aActionType, String aActionParam);
You can then add your IRTO
that will be displayed in this area.
Link with external content
With the Insiteo API, you can link your content to our zone based system. To do that you will have to register this content through our back office. For example you can link a shop to one of our zone and then, get back this content in your application, simply by requesting our API.
Insiteo Interactive maps - 2 minutes tutorialMapDBHelper
class like so:
// Get all Zone/POI assocations for a given external identifier
List<ZonePoiAssoc> zonePois = MapDBHelper.getZoneAssocFromExtPoi(extPoiID);
Important
An list is returned, because you can link a POI to several zones and a zone can contains several POIs.
MapDBHelper
class like so:
//Get all external Zone/POI assocations for a given zone identifier
List<ZonePoiAssoc> zonePois = MapDBHelper.getPoiAssocFromZone(zoneId, isExternal);
Each method returns an ZonePoiAssoc
object which contains a position in meters and an offset (if specified) in order to place your on
IRTO
on our map.
Zone/Poi associations offsets
-
If you want an offset to be used when drawing an
IRTO
in aZone
you have to explicitly set it we adding theIRTO
to theMapView
.
IRTO
to our map like so:
// Add an RTO in the zone center
mMapView.addRTOInZone(zoneId, myRTO);
Location
Packages dependencies
If you intend to use the this service you have to make sure that the location
package have been properly downloaded.
You can easily check if the package is available on the device with the following method:
InitProvider.getInstance().hasPackage(EPackageType.LOCATION);
.
Location process
Get your first location
You can use our LocationAPI
to obtain location information. The LocationAPI
needs initialization information in order to communicate with our servers. You can easily link this library to the INSITEO map, so the location can be displayed on it.
LocationAPI
, you will need to create an LocationProvider
instance . To receive location, you will need to start the
LocationProvider
,
with a context and an ILocationListener
. This listener will receive location events. You also have to set flags indicating location behavior, and a default map identifier:
// Retrieve the LocationProvider singleton
LocationProvider locProvider = LocationProvider.getInstance();
// And start the location process with the required flags.
locProvider.start(getActivity(), this, InsiteoConf.LOCATION_FLAGS);
// Add location renderer to the MapView so that location is automatically displayed.
mMapView.addRenderer((LocationRenderer)LocationProvider.getInstance().getRenderer(getResources()););
Which flags to use
Please contact us to get the appropriate location settings.
Prerequisites
- The API needs to be initialized.
- You can now be notified when no registered beacons were detected, which probably means that the user started the location whereas he is not on site.
Available services
Available location-based services are:
-
ELocationModule.ITINERARY
: this module computes the route between an arrival point, and a departure point (could be the user current location). -
ELocationModule.GEOFENCING
: this module detects when user location is in "active" areas, and notify the application that the user entered/stayed in/left these areas.
Get a specific LBS module
To use them, you have to request them from LocationProvider
with the
getModule
method.
Be aware that a new module is created for each call of getModule
.
Itinerary
Packages dependencies
If you intend to use the this service you have to make sure that the itinerary
package have been properly downloaded.
You can easily check if the package is available on the device with the following method: InitProvider.getInstance().hasPackage(EPackageType.ITINERARY);
.
Enable itinerary rendering
Itinerary
or Geofencing
you have to get the module from the location provider. If you want it to be displayed on an INSITEO map, do as follow:
// Retrieve the itinerary module from the LocationProvider
mItineraryProvider = (ItineraryProvider) LocationProvider.getInstance().getModule(ELocationModule.ITINERARY);
// get itinerary renderer linked to provider
mItineraryRenderer = (ItineraryRenderer) mItineraryProvider.getRenderer(getResources());
mItineraryRenderer.setPriority(10);
// Add this renderer to the map renderers list
mMapView.addRenderer(mItineraryRenderer);
// Register for itinerary rendering user interaction (such as clicks).
mItineraryRenderer.setListener(this);
Request an itinerary between two points
// Request an itinerary between two points.
Position departure = new Position(startMapId, 40, 40);
Position arrival = new Position(destMapId, 168, 100);
mItineraryProvider.requestItinerary(departure, arrival, this, PMR_ENABLED);
Retrieve itinerary requests
An ItineraryRequest
is returned in order to identify sender through callbacks.
Request an itinerary from user location
// Request an itinerary from the user location to a point arrival.
// With USE_LAST_LOC, you can decide to use the last location or wait for a new one.
// With PMR_ENABLED, you can set the itinerary to use only path for disabled persons.
Position arrival = new Position(mapID, 168, 100);
mItineraryProvider.requestItineraryFromCurrentLocation(arrival, USE_LAST_LOC, this, PMR_ENABLED);
Request an optimized route
// Request an optimized route between several positions (an OptimizeRequest is returned)
mItineraryProvider.requestOptimizedItinerary(pos, EOptimizationMode.EOptimizationModeNearestNeighbourShortestPath, true, false, this, false);
Request parameters
You can specify if you want to keep the first position, last position, or both.
Otpimization modes
There are multiple optimization modes available but we highly recommend to keep
EOptimizationMode.EOptimizationModeNearestNeighbourShortestPath
as the default one.
Recomputation
/**
* Callback fired when the itinerary of the last request changed (when location is updated for example).
* This method can be used to ask for a new itinerary if the user is now too far from the itinerary (we usually recompute
* the itinerary over a distance of 5 meters).
* @param aRequest the related request
* @param aDistanceToIti the distance between the user location and the itinerary (in meter)
*/
@Override
public void onItineraryChanged(BaseRequest aRequest, float aDistanceToIti) {
if (aRequest instanceof ItineraryRequest && LocationProvider.getInstance().isStarted()) {
if (aDistanceToIti > MAX_RECOMPUTATION_DISTANCE || aDistanceToIti == -1) {
aRequest.recompute();
}
}
}
Prerequisites
Make sure to have the dynamic mode to true
to have the onItineraryChanged
triggered (see ItineraryProvider.setDynamicMode(boolean enabled)
).
When to recompute?
We usually use 5.0
meters as MAX_RECOMPUTATION_DISTANCE
.
Geofencing
Packages dependencies
If you intend to use this service you have to make sure that the geofencing
package have been properly downloaded.
You can easily check if the package is available on the device with the following method: InitProvider.getInstance().hasPackage(EPackageType.GEOFENCING);
.
Start the Geofencing module
Geofencing
module, you just have to retrieve the instance from the LocationProvider and register as a IGeofenceListener.
// Retrieve the geofencing module
mGeofenceProvider = (GeofenceProvider) LocationProvider.getInstance().getModule(ELocationModule.GEOFENCING);
// Register as a IGeofenceListener
mGeofenceProvider.setListener(this);
Understand geonotifications
GeofenceZone
.
- The first one contains all zones the user just entered
- The second one contains all zones where the user still is and has spent a certain time .
- The third one contains all zones the user just left.
/**
* Called when geofencing module has new data available.
* @param aEnteredZones list of zones that location has just entered
* @param aStayedZones list of zones where location has stayed for a certain amount of time
* @param aLeftZones list of zones that location has just left
*/
@Override
public void onGeofenceUpdate(List aEnteredZones, List aStayedZones, List aLeftZones) {
Log.d("Geofencing", "onGeofenceUpdate " + aEnteredZones.size() + " "
+ aStayedZones.size() + " " + aLeftZones.size());
}
Dynamic Geopush
In the last version of our API, geopush content can be added to the GeofenceProvider
directly from your application in addition to the one fetched from the server. This enables, for example, your content to be more accurate to a specific user's behaviour or using context.
-
The created
GeofenceArea
's polygon will be based on the specific Zone parameters that have to be provided in the back office. -
If the
GeofenceArea
parameters (ie width, enteredTime, enteredEnabled ... ) are not set they will be fetched from the configuration file. This configuration file defines those parameters by Map and not by Zone. -
If the creation succeeded the
GeofenceArea
will be automatically added to the GeofenceProvider.
Adding content to a specific Zone
or for a specific ZonePoi
GeofenceArea
width will be created and this GeofenceArea
will be automatically added to the GeofenceProvider
// For a Zone
public GeofenceArea addGeofenceArea(int zoneId, String content);
public GeofenceArea addGeofenceArea(int zoneId, String content, long eventTime);
public GeofenceArea addGeofenceArea(int zoneId, String content, boolean enteredEnabled, long enteredTime, boolean stayedEnabled, long stayedTime, boolean leaveEnabled, long leaveTime, float width);
// For a ZonePoi association
public GeofenceArea addGeofenceArea(ZonePoi zonePoi, String content);
public GeofenceArea addGeofenceArea(ZonePoi zonePoi, String content, long eventTime);
public GeofenceArea addGeofenceArea(ZonePoi zonePoi, String content, boolean enteredEnabled, long enteredTime, boolean stayedEnabled, long stayedTime, boolean leaveEnabled, long leaveTime, float width);
Adding content for at a Position
Position
, you can use the methods shown below.
A square of size the on the given in parameter (or by default 4 time the size defined in the configuration file) and center on the given position will be created.
public GeofenceArea addGeofenceArea(String guid, Position center, String content);
public GeofenceArea addGeofenceArea(String guid, Position center, String content, long eventTime);
public GeofenceArea addGeofenceArea(String guid, Position center, String content, boolean enteredEnabled, long enteredTime, boolean stayedEnabled, long stayedTime, boolean leaveEnabled, long leaveTime);
public GeofenceArea addGeofenceArea(String guid, Position center, float size, String content);
public GeofenceArea addGeofenceArea(String guid, Position center, float size, String content, long eventTime);
public GeofenceArea addGeofenceArea(String guid, Position center, float size, String content, boolean enteredEnabled, long enteredTime, boolean stayedEnabled, long stayedTime, boolean leaveEnabled, long leaveTime);
Removing a dynamic GeofenceArea
GeofenceArea
from the GeofenceProvider
call the appropriate remove method based on how it was added.
public void removeGeofenceArea(String guid);
public void removeGeofenceArea(int zoneId);
public void removeGeofenceArea(ZonePoi zonePoi);
public void removeGeofenceArea(GeofenceArea area);
Geofencing rendering :
In this new version 3.2.2
you can now view your GeofenceArea
on you MapView. Like all other LBS services, you will have to retrieve its IRenderer
and pass it to the MapView. All the geofencing zone will be displayed ie the one define on the back office that one created dynamically.
Analytics
Packages dependencies
If you intend to use this service you have to make sure that the analytics
package have been properly downloaded.
You can easily check if the package is available on the device with the following method: InitProvider.getInstance().hasPackage(EPackageType.ANALYTICS);
.
Production vs Development
In order to be able to differentiate data from an application in a testing environment from a release one Insiteo's SDK uses the
CommonConstants.DEBUG
.
You should make sure to set this tag to false for your release version.
Starting the Analytics service
In order to use the analytics service you have to make sure it gets started during the API initialization. If you did not specify the analytics behavior in the API initialization method the service will be started automatically if the packages depedencies prerequisite is met. Otherwise this will depends on the value passed as the analyticsAutoStart as true will try to start it and false will keep it turned off and no data will be stored during the session.
Location events
If you have decided to use the analytics service then the user's location will be automatically sent for datamining analysis. In order to avoid internet requests overload location will be aggregated according to a given frequency that can be set in the back office.
Generic events
For any other type of events you would like to keep track of you can use the
AnalyticsGenericEvent
. This event
enables you to add up to 2 Strings, 2 Integers, 2 Doubles, 2 Positions
and a label to match most cases.
AnalyticsGenericEvent
to the AnalyticsManager
.
AnalyticsGenericEvent event = new AnalyticsGenericEvent("generic_event");
zoneEvent.setString1("product a");
zoneEvent.setPos1(aLocation.getPosition());
AnalyticsManager.getInstance().addGenericEvent(event);
Insiteo's API already trace some basic events among them:
- Location start and stop
- Geofence entered, stayed and left
-
Map changes, zone clicks and
IRTO
added withZonePoi
- Itinerary requests
Tracking products displayed on map
If you want to trace when a product is added to the map you can use
addRTOInZone(IRTO, ZonePoi)
.
This will generate a AnalyticsGenericEvent
with the String1 set with the external id of the Poi defined in the
ZonePoi
.
Completing a generic event
In can be useful in some cases to add information to a
AnalyticsGenericEvent
for that you must set a
IAnalyticsListener
that will be notified everytime a new generic
event is added. Returning false in this method will dismiss the event.