SDK for iOS app

Download the iOS Telematics SDK and install it in your environment

Introduction

Here you can find a short video guide, how to add Telematics SDK to your iOS app:

To utilize our telematics environment in your iOS app, you should integrate the Telematics SDK iOS framework into your app.
While you could manually add the framework, we strongly recommend using the CocoaPods dependency manager. If your project already uses other CocoaPods, continue after this first step:

Adding the SDK to your project

Swift Package Manager

in Package.swift add the following:

dependencies: [
  // Dependencies declare other packages that this package depends on.
  // .package(url: /* package url */, from: "1.0.0"),
  .package(url: "https://github.com/Mobile-Telematics/telematicsSDK-iOS-SPM", from: "6.0.5")
],
targets: [
  .target(
    name: "MyProject",
    dependencies: [..., "RaxelPulse"]
  )
  ...
]

Install CocoaPods

  • open a terminal window in the main project folder
  • run the following commands to install CocoaPods and create a "Podfile":
$ sudo gem install cocoapods
$ pod init

Add the SDK to your Podfile

  • locate 'Podfile' in the main project folder
  • using your preferred text editor, add the following line to your Podfile:
pod 'RaxelPulse'
  • open a terminal window in the main project folder
  • run the following commands in a terminal window to re-evaluate the Podfile, and add the RaxelPulse library to your project
$ pod install

Setting up the SDK

Please check RaxelPulse target in pod Always Embed Swift Standard Libraries: NO

Use this in your project target
Always Embed Swift Standard Libraries: YES

Enable capabilities

Configure the information property list file (Info.plist) with an XML snippet that contains data about your app.
Right-click info.plist, and choose Open As Source Code. Add capabilities for privacy, motion usage etc.

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>Your explanation.</string>
<key>NSLocationAlwaysUsageDescription</key>
    <string>Your explanation.</string>
<key>NSLocationWhenInUseUsageDescription</key>
    <string>Your explanation.</string>
<key>NSMotionUsageDescription</key>
    <string>Your explanation.</string>

Background location

<key>UIBackgroundModes</key>
    <array>
        <string>fetch</string>
        <string>location</string>
        <string>remote-notification</string>
    </array>

📘

Background location request explanation for users and Apple inc.

The most popular explanation is: We're using location services to determine your driving style.

Enable and Schedule Background Tasks

Starting from version 5.12 and new:

We use Background Tasks to improve upload recorded tracks, and send Heartbeats.

To configure your app to allow background tasks, enable the background capabilities that you need, and then create a list of unique identifiers for each task.
There are two types of background tasks: BGAppRefreshTask and BGProcessingTask. BGAppRefreshTask is for short-duration tasks that expect quick results, such as downloading a stock quote. BGProcessingTask is for tasks that might be time-consuming, such as downloading a large file or synchronizing data. Your app can use one or both of these.
To add the capabilities:

  • Open the project editor and select the desired target.
  • Click Signing & Capabilities.
  • Expand the Background Modes section. If the target doesn’t have a Background Modes section, click + Capability, and then select Background Modes.
  • If you’re using BGAppRefreshTask, select ”Background fetch.“
  • If you’re using BGProcessingTask, select ”Background processing.“

You control which tasks run in the background by registering a list of permitted task identifiers.

To create this list, add the identifiers to the Info.plist file.

  • Open the project navigator and select your target.
  • Click Info and expand Custom iOS Target Properties.
  • Add a new item to the list and choose ”Permitted background task scheduler identifiers,“ which corresponds to the BGTaskSchedulerPermittedIdentifiers array.
  • Add the string for each authorized task identifier as a separate item in the array.

In iOS 13 and later, adding a BGTaskSchedulerPermittedIdentifiers key to the Info.plist disables the application:performFetchWithCompletionHandler: and setMinimumBackgroundFetchInterval: methods.

<key>BGTaskSchedulerPermittedIdentifiers</key>
		<array>
    	<string>sdk.damoov.apprefreshtaskid</string>
    	<string>sdk.damoov.appprocessingtaskid</string>
		</array>

SDK Initialization

First, initialize a new RPEntry class instance with a specified device ID. This method must be the first method calling from RaxelPulse SDK in application didFinishLaunchingWithOptions method.

RPEntry.initialize(withRequestingPermissions: false)
[RPEntry initializeWithRequestingPermissions:NO]

App delegate

[Important] Starting from version 6.0.1

- (void)applicationWillEnterForeground:(UIApplication *)application {
  [RPEntry applicationWillEnterForeground:application];
}
func applicationWillEnterForeground(_ application: UIApplication) {
    RPEntry.applicationWillEnterForeground(application)
}

Important notifications

Note that these notifications are customized, you can use your own text.
Low power mode

@interface AppDelegate () <RPLowPowerModeDelegate> {
    [RPEntry instance].lowPowerModeDelegate = self;
}
class AppDelegate: RPLowPowerModeDelegate {
    RPEntry.instance().lowPowerModeDelegate = self
}

Delegate method:

- (void)lowPowerMode:(Boolean)state {
    if (state) {
        // You can create push in this place and fire about this, as example 
        
        UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
        content.title = @"Low Power Mode";
        content.body = [NSString stringWithFormat:@"Your trips may be not recorded. Please, follow to Settings=>Battery=>Low Power"];
        UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
        UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"overspeed" content:content trigger:trigger];

        [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil]; 
    }
}
func lowPowerMode(_ state: Bool) {
        if (state) {
            self.showNotification(title: "Low Power Mode", body: "Your trips may be not recorded. Please, follow to Settings=>Battery=>Low Power")
        }
}

func showNotification(title: String, body: String) {
	let content = UNMutableNotificationContent()
        content.title = title
        content.subtitle = body
        content.sound = UNNotificationSound.default

        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
        let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request)
}

Low accuracy

@interface AppDelegate () <RPAccuracyAuthorizationDelegate> {
    [RPEntry instance].accuracyAuthorizationDelegate = self;
}
class AppDelegate: RPAccuracyAuthorizationDelegate {
    RPEntry.instance().accuracyAuthorizationDelegate = self
}

Delegate method:

- (void)wrongAccuracyAuthorization {
    // You can create push in this place and fire about this, as example 
        
    UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
    content.title = @"Precise Location is off";
    content.body = [NSString stringWithFormat:@"Your trips may be not recorded. Please, follow to App Settings=>Location=>Precise Location"];
    UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"overspeed" content:content trigger:trigger];

    [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil];

}
func wrongAccuracyAuthorization() {
        self.showNotification(title: "Precise Location is off", body: "Your trips may be not recorded. Please, follow to App Settings=>Location=>Precise Location")
}

func showNotification(title: String, body: String) {
	let content = UNMutableNotificationContent()
        content.title = title
        content.subtitle = body
        content.sound = UNNotificationSound.default

        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
        let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request)
}

Permissions wizard

Note that the SDK has a built-in Permissions Wizard and a Permissions Dialog that are fully customizable. Wizard for iOS app

Without these permissions, SDK can not be enabled.

Here you can find an example with the correct Permissions Wizard flow:
Permissions in iOS

Setting up the permissions wizard
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[RPPermissionsWizard returnInstance] launchWithFinish:^(BOOL showWizzard) {
        [RPEntry initializeWithRequestingPermissions:YES]; // Yes, if you don’t want to implement requesting by yourself

        [RPEntry instance].disableTracking = NO;
        [RPEntry application:application didFinishLaunchingWithOptions:launchOptions];
    }];
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    RPPermissionsWizard.returnInstance().launch(finish: { _ in
        RPEntry.initialize(withRequestingPermissions: true)
        let token = NSString(string: "Please, enter your Token")
        RPEntry.instance().virtualDeviceToken = token
        let options = launchOptions ?? [:]
        RPEntry.application(application, didFinishLaunchingWithOptions: options)
    })
    return true
}
App delegate methods
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(nonnull NSString *)identifier completionHandler:(nonnull void (^)(void))completionHandler {
    [RPEntry application:application handleEventsForBackgroundURLSession:identifier completionHandler:completionHandler];
}

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    [RPEntry applicationDidReceiveMemoryWarning:application];
}

- (void)applicationWillTerminate:(UIApplication *)application {
    [RPEntry applicationWillTerminate:application];
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    [RPEntry applicationDidEnterBackground:application];
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    [RPEntry applicationDidBecomeActive:application];
}

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    [RPEntry application:application performFetchWithCompletionHandler:^{
        completionHandler(UIBackgroundFetchResultNewData);
    }];
}
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
    RPEntry.application(application, handleEventsForBackgroundURLSession: identifier, completionHandler: completionHandler)
}

func applicationDidReceiveMemoryWarning(_ application: UIApplication) {
    RPEntry.applicationDidReceiveMemoryWarning(application)
}

func applicationWillTerminate(_ application: UIApplication) {
    RPEntry.applicationWillTerminate(application)
}

func applicationDidEnterBackground(_ application: UIApplication) {
    RPEntry.applicationDidEnterBackground(application)
}

func applicationDidBecomeActive(_ application: UIApplication) {
    RPEntry.applicationDidBecomeActive(application)
}

func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    RPEntry.application(application) {
        completionHandler(.newData)
    }
}

Enable high-frequency data collection (HF)

📘

We strongly recommend keeping it enabled by default

Enable high-frequency data collection to accurate and persistent dataset

[RPEntry enableHF:true];
RPEntry.enableHF(true)

Enable Accident detection.

Accident detection is disabled by default. You can enable detection.
In order for accident detection to work, you need to enable high-frequency data collection

[RPEntry enableAccidents:true];
RPEntry.enableAccidents(true)

Enable SDK

Set a DeviceToken to SDK to enable it / SDK Log in.

🚧

DeviceToken

Empty or nil DeviceToken is not allowed.
To get a unique deviceToken for each user, you need to

[RPEntry instance].virtualDeviceToken = @"VIRTUAL_DEVICE_TOKEN";
let token = NSString(string: "VIRTUAL_DEVICE_TOKEN") //REQUIRED!
RPEntry.instance().virtualDeviceToken = token

Log out SDK

[[RPEntry instance] removeVirtualDeviceToken];
RPEntry.instance().removeVirtualDeviceToken()

Usage example for log in/ log out to follow the host app

if ([self userIsAuthenticated]) {
    [RPEntry instance].virtualDeviceToken = [self getDeviceToken];
} else {
    /// empty device token is not allowed
    /// Use removeVirtualDeviceToken method for log out from the host app.
    [[RPEntry instance] removeVirtualDeviceToken];
}
if (userIsAuthenticated) {
    let token = NSString(string: "VIRTUAL_DEVICE_TOKEN") //REQUIRED!
    RPEntry.instance().virtualDeviceToken = token
} else {
    /// empty device token is not allowed
    /// Use removeVirtualDeviceToken method for log out from the host app.
    RPEntry.instance().removeVirtualDeviceToken()
}

Update SDK

Regularly update SDK

We regularly make announcement emails for all registered in DataHub users about new critical SDK updates.
Stay in touch with the help of our detailed Changelog: https://docs.telematicssdk.com/changelog/sdk-for-ios

  • open a terminal window in the main project folder
  • run the following command in a terminal window
$ pod update

Update SDK to a specific version

In order to update to a specific version, you need to write in the PodFile:

pod 'RaxelPulse', '5.12'

where 5.12 - number of specific version