Getting started on iOS
Installation
Note: You can get an older version of the SDK in the Downloads section.
Project setup
INSITEO 's modules are provided as an iOS framework
. To use them, you will need to link it with your application project. Under Xcode
, you have to select your project in the left panel and click on the Build Phases
tab on the right. Then you will need to add all the wanted frameworks in the Link Binary With Libraries
panel. Please also check the framework dependencies below and add any additional required framework.
Requirements
InsiteoAPI.framework
requires the following frameworks and libraries:
- Our ProtocolBuffers.framework
- Apple
CoreLocation.framework
- Apple
CoreMotion.framework
- Apple
CoreBluetooth.framework
- Apple
QuartzCore.framework
- Apple
OpenAL.framework
- Apple
OpenGLES.framework
- Apple
CoreGraphics.framework
- Apple
Foundation.framework
- Apple
UIKit.framework
- Apple
CoreText.framework
- Apple
CoreTelephony.framework
- Apple
Security.framework
- Apple
libz.dylib
- Apple
libsqlite3.dylib
Note:
-
Please also set the
C++ Standard Library
parameter tolibstdc++
in theBuild Settings
panel of your target. -
The architecture to use is
armv7
and theBuild Active Architecture Only
parameter can be set toNO
.
Important: The Insiteo framework do not use ARC.
Initialization
Start the API
Before using any INSITEO class, you have to initialize ISInitProvider
singleton: we will give you information to interact with our servers. A SITE_ID
, a LANGUAGE
and an APPLICATION_VERSION
will be generated in order to identify your application, a SERVER_URL
will be created to communicate with our server. Using this information, you will be able to initialize the API.
Note:
-
The
ISInitProvider
also requires aISEServerType
parameter. This can take the following valuesDEV_SERVER
,TEST_SERVER
andPROD_SERVER
and is used to store the packages at the appropriate location on the device. Please make sure to use the proper value according to the URL server that was provided. - You will need to set an API key that you can found in your INSITEO account.
Important: Before starting the API you have to set the API key that you can found in your INSITEO account. To do so
use: setAPIKey
.
This must be done before calling startAPIWithServerUrl
.
To initialize API, you must call startAPIWithServerUrl
, with an id<ISPInitListener>
passed as parameter. The onInitDone
method will be called back on your listener when initialization is finished.
ISInitProvider
as below:
//Set your API key
[ISInitProvider setAPIKey:@"MY-API-KEY"];
//And start the API
id<ISPCancelable> initTask = [[ISInitProvider instance] startAPIWithServerUrl:SERVER_URL andSiteId:SITE_ID andApplicationVersion:APPLICATION_VERSION andLanguage:LANGUAGE andForceDownload:NO andInitListener:aListener andServerType:PROD_SERVER andAnalyticsAutoStart:YES];
//The initTask object could be used to cancel the API initialization (see ISPCancelable protocol documentation).
(...)
//In your init listener:
- (void)onInitDone:(ISEInitAPIResult)result andError:(ISInsiteoError *)error {
switch(result){
case SUCCESS :
//Init is ok
break;
case SUCCESS_NEW_DATA :
//Init is ok and new packages are available
break;
case FAIL :
//Init failed.
//More information in error (see ISInsiteoError documentation)
break;
default:
break;
}
}
Note: startAPIWithServerUrl
method is asynchronous. Be sure to provide a valid id<ISPInitListener>
, to be notified of init ending.
If startAPIWithServerUrl
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 theupdatePackagesWithInitListener
method on theISInitProvider
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 usinghasPackageWithPackageType:andServerType
onISInitProvider
singleton.
Handle data updates
ISInitProvider
as below:
//Notifications will be sent through following callbacks
id<ISPCancelable> initTask = [[ISInitProvider instance] updatePackagesWithInitListener:aListener];
//The initTask object could be used to cancel the API update (see ISPCancelable protocol documentation)
(...)
//Notifications will be sent to the listener through following callbacks:
- (void)onDownloadProgressWithProgress:(int)progress andTotal:(int)total {
(...)
}
- (void)onInstallProgressWithProgress:(int)progress andTotal:(int)total {
(...)
}
- (void)onDownloadPackageWillStart:(ISPackageType)packageType {
(...)
}
- (void)onDataUpdateDone:(Boolean)success andError:(ISInsiteoError *)error {
(...)
}
Note: updatePackagesWithInitListener
method is asynchronous. Be sure to provide a valid id<ISPInitListener>
, to be notified of initialization events.
When updating packages, the id<ISPInitListener>
will receive notifications for packages download progress, and then for packages install progress (on UI thread). Once the update is finished, the id<ISPInitListener>
will receive an onDataUpdateDone event.
When calling updatePackagesWithInitListener
, an id<ISPCancelable>
is returned. Call cancel on this object to cancel the current update.
Map
Note: Be aware that you need to have installed at least the following packages:
-
A
MAP_DATA_PACKAGE
package, which contains maps information such as zoom levels and scales. -
And a
TILES_PACKAGE
package, which contains.3cm
files that will be displayed.
[InitProvider hasPackageWithPackageType:MAP_DATA_PACKAGE andServerType:SERVER]
.
Adding graphical objects on map
An ISMapView
is provided and can be used to display a specific 2D map with specific interactive areas. The framework also provides advanced features such as additional rendering layouts management (promotional, special areas etc…) or specific events handling.
By default, the ISMapView
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 id<ISPRTO>
protocol.
The ISMapView
will first draw the tiled map, and then will loop on all its renderers, calling invalidateWithLayer
on each one. Each renderer owns a list of id<ISPRTO>
. In its invalidateWithLayer
method, the renderer will loop on this list, and call invalidateWithLayer
on each id<ISPRTO>
.
The ISMapView
will also detect touches, and dispatch them to all id<ISPRTO>
. A listener can be set on the map controller, to be notified of clicks on specific id<ISPRTO>
class (see ISMapViewController
) class documentation.
MapAPI
, you will need to instantiate an ISMapViewController
:
//ISMapViewController initialization
ISMapViewController * mapViewController = [[ISMapViewController alloc] initWithMapListener:aListener andContentView:aContentView];
Note:
- You will need to initialize
id<ISInitProvider>
before getting anISMapViewController
. - You will need to provide an
id<ISPMapListener>
to be notified ofISMapViewController
events. -
You could also specify a content
UIView
in order to add theISMapView
on this view.
Create your own ISPRenderer
A renderer is a class that defines drawing behavior for a certain type of id<ISPRTO>
. If you want to use your own customized renderer, you will need to create a class that implements the id<ISPRenderer>
protocol. Then you will be able to specify the renderer behavior through the invalidateWithLayer
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 (Renderer with highest priority will appear on top of the map).
//How to add a custom renderer
[mapViewController addRenderer:aRenderer]];
Note: All id<ISPRTO>
of class corresponding to the custom renderer class, when added via ISMapViewController
, will be put in custom renderer. See "Use your own ISPRTO" chapter below.
You will also need to implement an exhaustive list of functions described in the protocol. See the complete documentation for more details.
Create your own ISPRTO
id<ISPRTO>
protocol. 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
- (void)invalidateWithLayer:(ISLayer *)layer andRatio:(double)ratio andOffset:(CGPoint)offset andAngle:(float)angle andPriority:(int)priority;
//The method you will need to override in order to manually manage touch down events
- (ISETouchObjectResult)onTouchDown:(ISTouch *)touch;
ISMapViewController
, using the following methods:
//Methods you will need to call in order to add an RTO on the map
- (Boolean)addRTO:(id<ISPRTO>)rto;
- (Boolean)addRTO:(id<ISPRTO>)rto inZone:(int)zoneId;
id<ISPMapListener>
following callback:
//The method you will need to override handle touch events on interactive zones
- (void)onZoneClickedWithZone:(int)idZone andActionType:(int)actionType andActionParameter:(NSString *)actionParameter;
You can then add your id<ISPRTO>
that will be displayed in this area.
Link with external content
With the Insiteo framework, 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 framework.
Insiteo Interactive maps - 2 minutes tutorialISDBHelperMap
class like so:
//Get all Zone/POI assocations for a given external identifier
NSArray * zonesPois = [ISDBHelperMap getExternalZonePoisForExtIdPoi:externalPoiId];
Note: An array is returned, because you can link a POI to several zones and a zone can contains several POIs.
ISDBHelperMap
class like so:
//Get all external Zone/POI assocations for a given zone identifier
NSArray * zonesPois = [ISDBHelperMap getZonePoisForIdZone:zoneId andExternal:YES];
Each method returns an ISZonePoi
object which contains a position in meters and an offset (if specified) in order to place your on id<ISPRTO>
on our map.
Note:
- You can decide to use this offset or not.
-
If you decide to use this offset, it's up to you to use it in your
invalidateWithLayer
method.
id<ISPRTO>
to our map like so:
//Add an RTO in the zone center
[mapViewController addRTO:myRto inZone:zonePoi.zoneId];
Best pratices
//Cocos2d
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[CCDirector sharedDirector] stopAnimation];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
[[CCDirector sharedDirector] startAnimation];
}
- (void)applicationWillResignActive:(UIApplication *)application {
[[CCDirector sharedDirector] pause];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[CCDirector sharedDirector] resume];
}
//Insiteo
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[mapViewController startRendering];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[mapViewController stopRendering];
}
Location
Note: 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 hasPackageWithPackageType:LOCATION_PACKAGE andServerType:SERVER]
.
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 ISLocationProvider
instance (or ISGfxLocationProvider
instance if you want the location to be displayed automatically on the map).
To receive location, you will need to start the ISLocationProvider
, with location flags (indicating location behavior) and a id<ISPLocationListener>
:
//Instanciate the location provider
ISGfxLocationProvider * locProvider = [[ISGfxLocationProvider alloc] init];
//And start it
[locProvider startLocation:(COMPASS|BLE|MEMS) andLocationListener:aListener];
//Add location renderer to the ISMapViewController, thus location is displayed on map
[mapViewController addRenderer:[locProvider renderer]];
Important: Please contact us to get the appropriate location settings.
Note:
- 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:
-
LBS_MODULE_ITINERARY
: this module computes the route between an arrival point, and a departure point (could be the user current location). -
LBS_MODULE_GEOFENCING
: this module detects when user location is in "active" areas, and notify the application that the user entered/stayed in/left these areas.
Note: To use them, you have to request them from ISLocationProvider
with the getLbsModule
method. Be aware that a new module is created for each call of getLbsModule
.
Itinerary
Note: 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 hasPackageWithPackageType:ITINERARY_PACKAGE andServerType:SERVER]
.
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 below:
//Get the itinerary provider
ISGfxItineraryProvider * itineraryProvider = (ISGfxItineraryProvider *)[locProvider getLbsModule:LBS_MODULE_ITINERARY];
//Get itinerary renderer linked to provider
ISItineraryRenderer * itineraryRenderer = [itineraryProvider renderer];
//Register for itinerary rendering user interaction (such as clicks).
[itineraryRenderer setRenderListener:listener];
//Add renderer so itinerary is displayed on map
[map2DView addRenderer:itineraryRenderer];
Request an itinerary between two points
//Request an itinerary between two points (A on map "1", the other on map "2")
ISItineraryRequest * request = [itineraryProvider requestItineraryWithStartPoint:CGPointMake(50, 50) andStartMapId:1 andEndPoint:CGPointMake(200, 100) andEndMapId:2 andListener:itineraryListener andPMR:NO];
Note: An ISItineraryRequest
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 A
ISItineraryRequest * request = [itineraryProvider requestItineraryFromCurrentLocationWithEndPoint:CGPointMake(200, 100) andEndMapId:2 andListener:itineraryListener andPMR:NO];
Request an optimized route
//Request an optimized route between several waypoints (an ISItineraryOptimizedRequest is returned)
ISItineraryOptimizedRequest * optimizedRequest = [itineraryProvider requestOptimizedItineraryWithWaypoints:waypoints andOptimMode:ISEOptimizationModeNearestNeighbourShortestPath andKeepFirstPosition:YES andKeepLastPosition:NO andListener:itineraryListener andPMR:NO];
Note: You can specify if you want to keep the first position, last position, or both.
Note: There are multiple optimization modes available but we highly recommend to keep ISEOptimizationModeNearestNeighbourShortestPath
as the default one.
Recomputation
//Method called on the main thread
- (void)mainRecomputeItinerary {
//Request an itinerary from the user current location
[itineraryProvider requestItineraryFromCurrentLocationWithEndPoint:CGPointMake(200, 100) andEndMapId:2 andListener:itineraryListener andPMR:NO];
}
//Method called when the user position changed
- (void)onItineraryChangedWithRequest:(ISItineraryBaseRequest *)request andDistanceToItinerary:(float)distanceToItinerary {
//You can check if the distance between the user location and the computed itineray needs a recomputation
if (distanceToItinerary > MAX_RECOMPUTATION_DISTANCE) {
//The recomputation needs to be done on the main thread
[self performSelectorOnMainThread:@selector(mainRecomputeItinerary) withObject:nil waitUntilDone:NO];
}
}
Note: We usually use 5.0
meters as MAX_RECOMPUTATION_DISTANCE
.
Geofencing
Note: If you intend to use the 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 hasPackageWithPackageType:GEOFENCING_PACKAGE andServerType:SERVER]
.
Start the Geofencing module
Geofencing
module, simply do like so:
//Get the geofencing module from the location provider
ISGeofenceProvider * geofenceProvider = [[m_locationProvider getLbsModule:LBS_MODULE_GEOFENCING] retain];
//"Start" geofencing
[geofenceProvider setListener:listener];
Understand geonotifications
ISGeoFenceZone
.
- 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.
//Method alled when geofencing module has new data available
- (void)onGeofenceDataUpdateWithEnteredZones:(NSArray *)enteredZones andStayedZones:(NSArray *)stayedZones andLeftZones:(NSArray *)leftZones {
//Entered zones
for (ISGeofenceZone * geoZone in enteredZones) {
NSLog(@"User entered zone %@", geoZone.GUID);
}
//Stayed zones
for (ISGeofenceZone * geoZone in stayedZones) {
NSLog(@"User still is in zone %@", geoZone.GUID);
}
//Left zones
for (ISGeofenceZone * geoZone in leftZones) {
NSLog(@"User has left zone %@", geoZone.GUID);
}
}