Getting started on iOS
Installation
Looking for an older version?
You can get an older version of the SDK in the Downloads section.
Project setup
INSITEO 's modules are provided as an iOS library
and an iOS bundle
. To use them, you will need to link it with your application project. To do that, simply add the InsiteoAPI
folder to you project.
Note: If you plan to use our 3D features, don't forget to add the glsl
folder in your application resources.
Frameworks dependencies
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. The InsiteoAPI library
requires the following frameworks and libraries:
- Apple
CoreBluetooth.framework
for location purposes - Apple
CoreGraphics.framework
for rendering purposes - Apple
CoreLocation.framework
for location purposes - Apple
CoreMotion.framework
for location purposes - Apple
CoreTelephony.framework
for analytics purposes - Apple
CoreText.framework
for rendering purposes - Apple
Foundation.framework
- Apple
OpenAL.framework
for rendering purposes - Apple
OpenGLES.framework
for rendering purposes - Apple
QuartzCore.framework
for rendering purposes - Apple
Security.framework
- Apple
UIKit.framework
- Apple
libc++.dylib
- Apple
libz.dylib
- Apple
libsqlite3.dylib
Requirements
- The INSITEO
library
requiresiOS 5.1.1
or later. - The library is now optimized for
armv7
andarm64
. - Please set
C++ Standard Library
aslibstdc++
in your project settings
Objective-C++
When using some classes such as ISLocationProvider, ISItineraryProvider or ISMap3DView, you will need to tag your implementor as Objective-C++ class (*.mm extension OR specific compiler settings).
Initialization
Start and update the API
Don't forget to set your API key
Before any interaction with Insiteo's API you must set your API KEY via setAPIKey
. 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 ISInitProvider
singleton. This will be done with the startAPIWithServerType
and we will give you the data to pass (ie the ISEServerType
, the site identifier and the language).
Use the appropriate server type
The initialization process requires a ISEServerType
that can take the following values: ISEServerTypeDev
, ISEServerTypeTest
or ISEServerTypeProd
. Depending on its values the downloaded data will be stored under the appropriate folder (respectively 'dev', 'test' and 'release').
Choose your render mode
In order to get ready to use our map module, you will need to specify the render mode you plan to use. You can choose between ISERenderMode2D
and ISERenderMode3D
. Please note that the default mode is ISERenderMode2D
.
You can now safely start Insiteo API by calling startWithServerType
.
You will be then notified of API initialization through block handlers you specified.
//Initialization parameters
int SITE_ID = 365;
NSString * LANGUAGE = @"fr";
//Set your API key
[ISInitProvider setAPIKey:@"MY-API-KEY"];
//And start the API
id<ISPCancelable> initTask = [[ISInitProvider instance] startWithServerType:ISEServerTypeProd andSiteId:YOUR_SITE_IDandLanguage:YOUR_LANGUAGE
andStartHandler:^NSArray * (ISInsiteoError * error, NSArray * newPackages) {
//Check init status
if (error == nil) {
//Success!
//Return all packages to update all data
return newPackages;
} else {
//An error occured
//[1] 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 using hasPackageWithPackageType:andServerType on ISInitProvider singleton.
return nil;
}
}
andUpdateHandler:^(ISInsiteoError * error) {
//Check update status
if (error == nil) {
//Success! You can now launch your application with all up to date data.
} else {
//An error occured, same as [1]
}
}
andUpdateProgressHandler:^(ISPackageType packageType, Boolean download, int progress, int total) {
//Here you get the current treated package type and you can know if we are currently downloading or installing it
//And you can compute total progress to update your loading view for example
float totalProgress = (float)progress / (float)total;
}
andRenderMode:YOUR_RENDER_MODE];
//Note: The initTask object could be used to cancel the API initialization (see ISPCancelable protocol documentation).
Handle the initialization process in background
The startWithServerType
method is asynchronous. Be sure to provide a valid block handler to be notified of init ending.
You can also choose to not update the API automatically, for example if you want to ask the user if he wants to download the new data.
In this case, simply returns nil on the initialization handler and don't pass update block handlers. Just call the update method when you are ready. For more information, please check our sample application.
Map
Map3DView now available!
In the 3.3.0
version, you can now use the ISMap3DView class. Be aware, that you can't use both 2D and 3D in the same running application.
Don't forget to add the glsl
folder in your application resources, otherwise the 3D engine won't work.
Packages dependencies
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. -
2D A
TILES_PACKAGE
package, which contains.3cm
files that will be displayed. -
3D A
MAP_3D_PACKAGE
package, which contains all 3D files.
[[ISInitProvider instance] hasPackageWithPackageType:MAP_DATA_PACKAGE andServerType:SERVER]
.
Display a MapView
A ISMapView
is provided and can be used to display a 2D/3D map component with specific interactive areas. The API also provides advanced features such as additional rendering layouts management (promotional, special areas etc …) or specific events handling. To use this component you have to make sure that you have downloaded all the required packages.
The ISMapView
will display a 2D tiled map or 3D plane of the site (depending on your ISERenderMode
), and provide common map interaction (such as move, center, and pinch to zoom), animation and more. It also handle the ISZone
rendering and touch behavior.
The ISMap2DView
uses the Cocos2D
Objective-C 2D engine and you can refer to its documentation here.
The ISMap3DView
uses the Cocos3D
Objective-C 3D engine (based on Cocos2D) and you can refer to its documentation here.
MapAPI
, you will need to get an ISMapView
:
//ISMap2DView initialization
[ISMap2DView getMap2DViewWithFrame:self.mapContentView.frame andMapListener:self andHandler:^(ISMap2DView * map2DView) {
//At this point, the map view is correctly initialized
[self.view addSubView:map2DView];
}];
//ISMap3DView initialization
[ISMap3DView getMap3DViewWithFrame:self.mapContentView.frame andMapListener:self andHandler:^(ISMap3DView * map3DView) {
//At this point, the map view is correctly initialized
[self.view addSubView:map3DView];
}];
Prerequisites
-
You will need to initialize
ISInitProvider
before instantiatingISMapView
. -
ISMapView
events will be notified via theid<ISPMapListener>
protocol.
Adding graphical objects on map
The ISMapView
also allows you to display custom interactive objects. This can be done by implementing the renderer interface id<ISPRenderer>
and the Render Touch Object interface id<ISPRTO>
or by simply extending the ISGenericRenderer
and ISGenericRTO
that already provide common behavior (icon and label rendering, touch handling and so on, you can check their behavior in our SampleApp).
The ISMapView
will also detect touches, and dispatch them to all id<ISPRTO>
. A listener can be set on the map view, to be notified of clicks on specific id<ISPRTO>
class (see ISMapView
class documentation).
ISGenericRTO
to the ISMapView
and listening for their events:
//This method will add the rto at a given position
ISGenericRTO * rto = [[ISGenericRTO alloc] initWithName:@"My RTO name" andLabel:@"My RTO" andMetersPosition:givenPosition andWindowDisplayed:YES andLabelDisplayed:YES];
[m_mapView addRTO:rto];
[rto release];
//And to remove it
[m_mapView removeRTO:rto];
//This method will add the rto to the given zone
ISGenericRTO * rto = [[ISGenericRTO alloc] initWithName:zonePoi.externalPoiId andLabel:@"My RTO" andMetersPosition:nil andWindowDisplayed:YES andLabelDisplayed:YES];
[m_mapView addRTO:rto inZone:zonePoi.zoneId];
[rto release];
//And to remove it
[m_mapView removeRTO:rto fromZone:zoneId];
//Add a listener for this type of IRTO
[m_mapView setRTOListener:rtoListener withRTOClass:[GfxRTO class]];
Create your own ISPRenderer
A renderer is a class that defines drawing and touch behavior for a certain type of id<ISPRTO>
. Once added to the ISMapView
a renderer will have its render2D
or render3D
method call by the map rendering loop to enable to do its rendering operation and it will also be notify when to handle touch events (onTouchDown
, onTouchMove
, onTouchUp
). If you want to use your own customized renderer, you will need to create a class that implements the id<ISPRenderer>
interface. Then you will be able to specify your own renderering and touch behavior.
id<ISPRenderer>
uses a priority value that will define it's 2D rendering and touch order. Highest priority renderered last (so on the top) and notify by touch first.
//How to add a custom renderer
[mapView addRenderer:aRenderer]];
Create your own ISPRTO
ISPRTO
that use CC3Billboard
and support iPhone 6 plus resolution, you will need to scale the object by 0.75.
id<ISPRTO>
interface. Then you will be able to specify your object's behavior through methods like:
//The 2D method you will need to override in order to manually manage your object rendering
- (void)render2DWithLayer:(CCLayer *)layer andRatio:(double)ratio andOffset:(CGPoint)offset andAngle:(float)angle andPriority:(int)priority;
//The 3D method you will need to override in order to manually manage your object rendering
- (void)render3DWithScene:(CC3Scene *)scene andLayer:(CC3Node *)layer andCurrentMap:(ISMap *)map andRatio:(float)ratio andAngle:(float)angle andPriority:(int)priority;
//Because once added to the world a 3D object will always be drawn it is up to you to remove the object from the world when required
- (void)remove3DFromLayer:(CC3Node *)layer;
//Method that gets called when the IRTO have to handle a touch down event
- (ISETouchObjectResult)onTouchDown:(ISTouch *)touch;
Where to find my ISPRTO?
All id<ISPRTO>
of class corresponding to the custom renderer class, when added via ISMapView
, will be put in custom renderer. If you add an id<ISPRTO>
and there are no id<ISPRenderer>
defined for that specific class, the ISMapView
will automatically create a ISGenericRenderer
to handle it. So creating your own id<ISPRTO>
does not mean that you necessarily have to create you own id<ISPRenderer>
.
Zone offsets in 3D
In 3D, you can specify an offset through the z axis still by using the following method addRTO:inZone:withOffset:
.
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.
Zone/Poi associations offsets
If you want an offset to be used when drawing an id<ISPRTO>
in a ISZone
you have to explicitly set it we adding the id<ISPRTO>
to the ISMapView
.
Best pratices
//Insiteo
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[mapView startRendering];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[mapView stopRendering];
}
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: [[ISInitProvider instance] hasPackageWithPackageType:LOCATION_PACKAGE andServerType:SERVER]
.
iOS 8 compatibility
In order to be iOS 8 fully compatible, you will need to add the NSLocationWhenInUseUsageDescription
key in your .plist
. You can leave the corresponding value empty or specify a custom message that will be displayed the first time the SDK will ask to use the location service.
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.
To receive location, you will need to start the ISLocationProvider
, with location flags (indicating location behavior) and a id<ISPLocationListener>
:
//Start location
[[ISLocationProvider sharedInstance] startLocation:(COMPASS|BLE|MEMS) andLocationListener:aListener];
//Add location renderer to the ISMapView, thus location is displayed on map
[mapView addRenderer:[locProvider renderer]];
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:
-
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.
Get a specific LBS module
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
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: [[ISInitProvider instance] 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
[mapView 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 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) {
//Recompute the itinerary
[request recompute];
}
}
Note: We usually use 10.0
meters as MAX_RECOMPUTATION_DISTANCE
.
Geofencing
Packages dependencies
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: [[ISInitProvider instance] 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];
//"Start" geofencing
[geofenceProvider setListener:listener];
Understand geonotifications
ISGeoFenceArea
.
- 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)onGeofenceDataUpdateWithEnteredAreas:(NSArray *)enteredAreas andStayedAreas:(NSArray *)stayedAreas andLeftAreas:(NSArray *)leftAreas {
//Entered areas
for (ISGeofenceArea * geoArea in enteredAreas) {
NSLog(@"User entered area %@", geoArea.GUID);
}
//Stayed areas
for (ISGeofenceArea * geoArea in stayedAreas) {
NSLog(@"User still is in area %@", geoArea.GUID);
}
//Left areas
for (ISGeofenceArea * geoArea in leftAreas) {
NSLog(@"User has left area %@", geoArea.GUID);
}
}
Dynamic geofencing
In the last version of our API, geopush content can be added to the ISGeofenceProvider
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
ISGeofenceArea
's polygon will be based on the specificISZone
parameters that have to be provided in the back office. -
If the
ISGeofenceArea
parameters (ie width, enteredTime, enteredEnabled ... ) are not set they will be fetched from the configuration file. This configuration file defines those parameters byISMap
and not byISZone
. -
If the creation succeeded the
ISGeofenceArea
will be automatically added to theISGeofenceProvider
.
Adding content to a specific zone or for a specific zone/poi association
ISZone
or ISZonePoi
, you can use the methods shown below.
A polygon based on the ISZone parameters and the provided ISGeofenceArea
width will be created and this ISGeofenceArea
will be automatically added to the ISGeofenceProvider
.
//For a ISZone
- (ISGeofenceArea *)addGeofenceAreaWithZoneId:(int)zoneId andLabel:(NSString *)label andMessage:(NSString *)message;
- (ISGeofenceArea *)addGeofenceAreaWithZoneId:(int)zoneId andPolygon:(NSMutableArray *)polygon andLabel:(NSString *)label andMessage:(NSString *)message;
...
//For a ISZonePoi association
- (ISGeofenceArea *)addGeofenceAreaWithZonePoi:(ISZonePoi *)zonePoi andLabel:(NSString *)label andMessage:(NSString *)message;
- (ISGeofenceArea *)addGeofenceAreaWithZonePoi:(ISZonePoi *)zonePoi andPolygon:(NSMutableArray *)polygon andLabel:(NSString *)label andMessage:(NSString *)message;
...
Adding content for a given position
ISPosition
, 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.
- (ISGeofenceArea *)addGeofenceAreaWithGUID:(NSString *)guid andCenter:(ISPosition *)center andLabel:(NSString *)label andMessage:(NSString *)message;
- (ISGeofenceArea *)addGeofenceAreaWithGUID:(NSString *)guid andCenter:(ISPosition *)center andLabel:(NSString *)label andMessage:(NSString *)message andEventTime:(float)eventTime;
...
Removing a dynamic geofence area
ISGeofenceArea
from the ISGeofenceProvider
call the appropriate remove method based on how it was added.
- (void)removeGeofenceAreaWithGuid:(NSString *)guid;
- (void)removeGeofenceAreaWithZoneId:(int)zoneId;
- (void)removeGeofenceAreaWithZonePoi:(ISZonePoi *)zonePoi;
- (void)removeGeofenceAreaWithArea:(ISGeofenceArea *)area;
Geofencing rendering
You can now view your ISGeofenceArea
on your ISMapView
. Like all other LBS services, you will have to retrieve its id<ISPRenderer>
and pass it to the ISMapView
. 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 the 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: [[ISInitProvider instance] hasPackageWithPackageType:ANALYTICS_PACKAGE andServerType:SERVER]
.
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
[ISCommonConstants getDebugMode]
.
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
ISAnalyticsGenericEvent
. This event
enables you to add up to 2 NSString, 2 int, 2 double, 2 ISPosition
and a label to match most cases.
ISAnalyticsGenericEvent
to the ISAnalyticsManager
.
ISAnalyticsGenericEvent * zoneEvent = [[ISAnalyticsGenericEvent alloc] initWithEventType:@"generic_event"];
[zoneEvent setSParam1:@"product a"];
[zoneEvent setPositions:[NSArray arrayWithObject:aLocation.position]];
[[ISAnalyticsManager instance] addGenericEvent:zoneEvent];
Insiteo's API already trace some basic events among them:
- Location start and stop
- Geofence entered, stayed and left
-
Map changes, zone clicks and
id<ISPRTO>
added withISZonePoi
- Itinerary requests
Tracking products displayed on map
If you want to trace when a product is added to the map you can use
addRTO:inZonePoi:
.
This will generate a ISAnalyticsGenericEvent
with the String1 set with the external id of the Poi defined in the
ISZonePoi
.
Completing a generic event
In can be useful in some cases to add information to a
ISAnalyticsGenericEvent
for that you must set a
ISPAnalyticsListener
that will be notified everytime a new generic
event is added. Returning false in this method will dismiss the event.