Assets for iOS app

Telematics SDK Wizard screen customization

The permission wizard contains a set of screens that can be used in the host app. These Wizard screens are implemented in the Telematics SDK for your convenience and you need to display them from your app to the user in order to get permissions to record trips.

📱 UI overview

The Wizard is a set of user-friendly screens with a step-by-step description of each required permission and the button 'Proceed " to call a permission request.

1440

🎨 Page customization

To customize any page of the wizard, please, call RPSettings instance by returnInstance and use the following property:

  • wizardBgColor - background color of screen view
  • wizardMaintextColor - main text color
  • wizardAlertTextColor - main text color in example alert
  • wizardAlertButtonColor - button text color in alert
  • wizardAlertActiveButtonColor - active button text color in alert
  • wizardAlertActiveButtonBgColor - active button background color in alert
  • wizardAlertCorners - alert corner radius in CGFloat

Default Values for iOS .White scheme:

[[RPCSettings returnInstance] setWizardNextButtonBgColor:[UIColor redColor]];
[[RPCSettings returnInstance] setWizardMaintextColor:[UIColor blackColor]];
[[RPCSettings returnInstance] setWizardAlertBackgroundColor:[UIColor whiteColor]];
[[RPCSettings returnInstance] setWizardAlertTextColor:[UIColor greenColor]];
[[RPCSettings returnInstance] setWizardAlertButtonTextColor:[UIColor blueColor]];
[[RPCSettings returnInstance] setWizardAlertActiveButtonTextColor:[UIColor redColor]];
[[RPCSettings returnInstance] setWizardAlertActiveButtonBgColor:[UIColor greyColor]];
[[RPCSettings returnInstance] setWizardAlertCorners:[UIColor purpleColor]];
[[RPCSettings returnInstance] setAppName:@"TelematicsApp"];
RPSettings.returnInstance().wizardNextButtonBgColor = UIColor.red
RPSettings.returnInstance().wizardMaintextColor = UIColor.black
RPSettings.returnInstance().wizardAlertBackgroundColor = UIColor.white
RPSettings.returnInstance().wizardAlertTextColor = UIColor.green
RPSettings.returnInstance().wizardAlertButtonTextColor = UIColor.blue
RPSettings.returnInstance().wizardAlertActiveButtonTextColor = UIColor.red
RPSettings.returnInstance().wizardAlertActiveButtonBgColor = UIColor.gray
RPSettings.returnInstance().appName = "TelematicsApp"

Default Values for iOS .Dark scheme:

🚧

.Dark scheme limitations

.Dark can be used only without customising following alert colors:

  • wizardAlertBackgroundColor
  • wizardAlertTextColor
  • wizardAlertActiveButtonBgColor
[[RPCSettings returnInstance] setWizardAlertBackgroundColor:[UIColor whiteColor]];
[[RPCSettings returnInstance] setWizardAlertTextColor:[UIColor whiteColor]];
[[RPCSettings returnInstance] setWizardAlertButtonTextColor:[UIColor whiteColor]];
[[RPCSettings returnInstance] setWizardAlertActiveButtonTextColor:[UIColor whiteColor]];
[[RPCSettings returnInstance] setWizardAlertActiveButtonBgColor:[UIColor whiteColor]];
RPSettings.returnInstance().wizardAlertBackgroundColor = UIColor.white
RPSettings.returnInstance().wizardAlertTextColor = UIColor.white
RPSettings.returnInstance().wizardAlertButtonTextColor = UIColor.white
RPSettings.returnInstance().wizardAlertActiveButtonTextColor = UIColor.white
RPSettings.returnInstance().wizardAlertActiveButtonBgColor = UIColor.white

Example on wizardAlertActiveButtonBgColor customization

[RPSettings returnInstance].wizardAlertActiveButtonBgColor = 
  [UIColor colorWithRed: 0.79 
           green       : 0.22 
           blue        : 0.17 
           alpha       : 1.0];
RPSettings.returnInstance.wizardAlertActiveButtonBgColor = UIColor.red

Example on text customization

NSMutableAttributedString *firstButton = [[NSMutableAttributedString alloc] initWithString:@"Ok"];

NSMutableAttributedString *secondButton = [[NSMutableAttributedString alloc] initWithString:@"Cancel"];

NSArray<NSMutableAttributedString *> *buttonsList = [[NSArray alloc] initWithObjects:firstButton, secondButton, nil];

RPPageTexts *whileInUsePage = [[RPPageTexts alloc] initWithPageText:[[NSMutableAttributedString alloc] initWithString:@"Attention Required!\n\nYou will receive a popup shortly. This popup will aks you for access to your location even when you are not using the app.\n\nPlease, choose “Always While Using App” for <appName> to automatically detect when you start a trip."] alertText:[[NSMutableAttributedString alloc] initWithString:@"Allow <appName> to access your location?\n\nWe use location service for evaluating your driving manner. Be enabling “Always While Using App” on location, the app will be able to automatically determine when you have started and ended a drive"] buttonsText:buttonsList selected:1];

RPPageTexts *motionPage = [[RPPageTexts alloc] initWithPageText:[[NSMutableAttributedString alloc] initWithString:@"Attention Required!\n\nThen, You will receive a popup to grant us access to your Motion & Fitness activity. We need this information to create a driving score.\n\nPlease, choose “OK” for <appName> to grant us access to Motion & Fitness activity."] alertText:[[NSMutableAttributedString alloc] initWithString:@"<appName> Would Like to Access Your Motion & Fitness Activity\n\nWe use motion sensors for evaluating your driving manner"] buttonsText:buttonsList selected:1];

RPPageTexts *pushPage = [[RPPageTexts alloc] initWithPageText:[[NSMutableAttributedString alloc] initWithString:@"Attention Required!\n\nAs the next step, You will receive a popup to grant us rights to send you important notifications. You are always able to turn off notifications by categories in the App settings menu.\n\nPlease, choose “Allow” for <appName> to keep you informed on important events."] alertText:[[NSMutableAttributedString alloc] initWithString:@"<appName> Would Like to Send You Notifications\n\nNotifications may include alerts, sounds and icon badges. These can be configured in Settings"] buttonsText:buttonsList selected:1];

RPPageTexts *alwaysPage = [[RPPageTexts alloc] initWithPageText:[[NSMutableAttributedString alloc] initWithString:@"Attention Required!\n\nYou will receive a popup shortly for <appName> to have access to your location even when you are not using the app.\n\nFor the app to work properly\n“Change to Always Allow”"] alertText:[[NSMutableAttributedString alloc] initWithString:@"Allow <appName> to also access your location even when you are not using the app?\n\nWe use location service for generating a driving score. Be enabling “Always” on location, the app will be able to automatically determine when you have started and ended a drive"] buttonsText:buttonsList selected:1];

NSArray<RPPageTexts *> *customPages = [[NSArray alloc] initWithObjects:whileInUsePage, motionPage, pushPage, alwaysPage, nil];

[RPSettings returnInstance].wizardPages = customPages;
let whileInUsePage = RPPageTexts(pageText: NSMutableAttributedString(string: "Attention Required!\n\nYou will receive a popup shortly. This popup will aks you for access to your location even when you are not using the app.\n\nPlease, choose “Always While Using App” for <appName> to automatically detect when you start a trip."), alertText: NSMutableAttributedString(string: "Allow <appName> to access your location?\n\nWe use location service for evaluating your driving manner. Be enabling “Always While Using App” on location, the app will be able to automatically determine when you have started and ended a drive"), buttonsText: [NSMutableAttributedString(string: "Always While Using App”), NSMutableAttributedString(string: "Allow Once”), NSMutableAttributedString(string: "Don’t Allow”)], selected: 0)

let motionPage = RPPageTexts(pageText: NSMutableAttributedString(string: "Attention Required!\n\nThen, You will receive a popup to grant us access to your Motion & Fitness activity. We need this information to create a driving score.\n\nPlease, choose “OK” for <appName> to grant us access to Motion & Fitness activity."), alertText: NSMutableAttributedString(string: "<appName> Would Like to Access Your Motion & Fitness Activity\n\nWe use motion sensors for evaluating your driving manner"), buttonsText: [NSMutableAttributedString(string: "Don’t Allow”), NSMutableAttributedString(string: "OK”)], selected: 1)

let pushPage = RPPageTexts(pageText: NSMutableAttributedString(string: "Attention Required!\n\nAs the next step, You will receive a popup to grant us rights to send you important notifications. You are always able to turn off notifications by categories in the App settings menu.\n\nPlease, choose “Allow” for <appName> to keep you informed on important events."), alertText: NSMutableAttributedString(string: "<appName> Would Like to Send You Notifications\n\nNotifications may include alerts, sounds and icon badges. These can be configured in Settings"), buttonsText: [NSMutableAttributedString(string: "Don’t Allow”), NSMutableAttributedString(string: "Allow”)], selected: 1)

let alwaysPage = RPPageTexts(pageText: NSMutableAttributedString(string: "Attention Required!\n\nYou will receive a popup shortly for <appName> to have access to your location even when you are not using the app.\n\nFor the app to work properly\n“Change to Always Allow”"), alertText: NSMutableAttributedString(string: "Allow <appName> to also access your location even when you are not using the app?\n\nWe use location service for generating a driving score. Be enabling “Always” on location, the app will be able to automatically determine when you have started and ended a drive"), buttonsText: [NSMutableAttributedString(string: "Keep Only While Using”), NSMutableAttributedString(string: "Change to Always Allow”)], selected: 1)

RPSettings.returnInstance().wizardPages = [whileInUsePage, motionPage, pushPage, alwaysPage]

General Permissions Popup

In order for all user trips to be recorded correctly, our Open-source App uses a custom "General Permissions Popup" that tells the user about the necessary permissions.

❗️

Remember

Set Location Always - REQUIRED!
Enable Motions - REQUIRED!

1018

If the user sets the wrong permissions, clicking on any of the buttons will open the system settings window of your app.
You can find the implementation for the design change in this GeneralPermissionsPopup class.

1474

To edit the title/message/buttons text's, open the "GeneralPermissionsPopupDelegate.m" file and make changes.

1570

With the help of "GeneralPermissionsPopupProtocol" you can add some lines in any ViewController of your app to show/hide the popup.

750

We usually check two base values ​​(Location Always & Enable Motions) with a special helper class "WiFiGPSChecker" which is also available in Open-source App. With it, we can always get the answer "YES" or "NO".

BOOL isGPSAuthorizedAlways = [[WiFiGPSChecker sharedChecker] gpsAvailable];
BOOL isMotionEnabled = [[WiFiGPSChecker sharedChecker] motionAvailable];
BOOL isGPSAuthorizedAlways = WiFiGPSChecker.sharedChecker.gpsAvailable()
BOOL isMotionEnabled = WiFiGPSChecker.sharedChecker.motionAvailable()

On receiving the value "NO", we can show our Permissions popup:

[permissionPopup showPopup];
permissionPopup.showPopup()

To hide popup when the value is "YES" use this method:

[permissionPopup hidePopup];
permissionPopup.hidePopup()

If necessary, you can also check for user permissions to send Push-notifications, but this is not a basic requirement and depends on the type of your business. All full popup customization is available for you in our Open-source App.

Low Power Mode for iOS UserNotificationCenter

If a user turns on "Power Saving Mode" on iOS, their trips may not be recorded correctly.
Telematics SDK has a special delegate that will show a system Push-notification at the top of the screen.

567
@interface AppDelegate () <RPAccuracyAuthorizationDelegate, RPLowPowerModeDelegate>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [RPEntry instance].lowPowerModeDelegate = self;
    [RPEntry instance].accuracyAuthorizationDelegate = self;
}

- (void)lowPowerMode:(Boolean)state {
    if (state) {
        UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
        content.title = localizeString(@"Low Power Mode");
        content.body = [NSString stringWithFormat:@"%@", localizeString(@"Your trips may be not recorded. Please, follow to Settings=>Battery=>Low Power")];
        UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
        UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"wrongLowPower" 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)
}

Precise Location for iOS UserNotificationCenter

The same delegate exists for Precise location. If the user gives out an "approximate" location, his trips will not be recorded.
It is also necessary to notify the user about this with a system Push-notification.

@interface AppDelegate () <RPAccuracyAuthorizationDelegate, RPLowPowerModeDelegate>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [RPEntry instance].lowPowerModeDelegate = self;
    [RPEntry instance].accuracyAuthorizationDelegate = self;
}

- (void)wrongAccuracyAuthorization {
    UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
    content.title = localizeString(@"Precise Location is off");
    content.body = [NSString stringWithFormat:@"%@", localizeString(@"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:@"wrongAccuracy" content:content trigger:trigger];

    [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil];
}
func wrongAccuracyAuthorization() {
	self.showAccuracyNotification(title: "Precise Location is off", body: "Your trips may be not recorded. Please, follow to App Settings=>Location=>Precise Location")
}
    
func showAccuracyNotification(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)
}