Enable Zendrive SDK

This section describes how to integrate Zendrive SDK with your application, and includes the following topics:

Enable Zendrive SDK

Enable Zendrive SDK

1.0. Add Zendrive SDK Dependencies

Refer to the following code snippet to know how to integrate using cocoapods:

pod 'ZendriveSDKSwift', :git => 'https://bitbucket.org/zendrive-root/zendrive_cocoapod.git', :tag => '9.1.0'

2.0. Set Up Zendrive SDK

In order to set-up Zendrive SDK, create a ZendriveManager class to keep the Zendrive integration code in one place.

2.1. Create Zendrive Manager Class

class ZendriveManager: NSObject {
    let core = IQLRef.sharedInstance
sw
    func setup(onSuccess: (() -> Void)? = nil) {
        if let userId = core.loginRepository.currentUser?.driverId {
            let sdkKey = core.sdkKeys.zendriveSdkKey
            DDLogDebug("Zendrive setup sdk key - \(sdkKey)")
            let driverId = userId
            let config = Configuration()
            config.applicationKey = sdkKey
            config.driverId = driverId
            config.managesLocationPermission = false
            config.driverAttributes = DriverAttributes()
            _ = config.driverAttributes?.setCustomAttribute("IQL Reference", forKey: "Application Used")

            if let primaryAlias = primaryAlias {
                _ = config.driverAttributes?.setAlias(primaryAlias)
            }

            Zendrive.setup(with: config, delegate: self) { (succeeded, error) in
                if succeeded {
                    DDLogDebug("Zendrive setup succeeded")
                    onSuccess?()
                } else {
                    DDLogError("Zendrive setup failed \(String(describing: error))")
                }
            }
        } else {
            DDLogDebug("User not available, not setting up zendrive")
        }
    }

    var primaryAlias: String? {
        let currentUser = IQLRef.sharedInstance.loginRepository.currentUser
        return currentUser?.email
    }
}

When thesetupZendrive() method is called, it will create a driver entry in the Zendrive backend, if one doesn’t already exist.

2.2. Set Up Zendrive SDK At Opt-in Stage

To set up the Zendrive Manager class SDK, call thesetupZendriveManager method from the following code snippet, when the user chooses to opt- in for the IQL program. Do this before obtaining permissions.

class ExplainerViewController: BaseViewController {
    ...
    ...
    func setupView() {
        ...
        ...
        activateBtn.onTap = self.navigateToPermissions
    ...
    ...
    }
    
    func navigateToPermissions() {
        IQLRef.sharedInstance.setupZendriveManager()


    }
    ...
    ...
}

2.3. Set Up Zendrive SDK At Application Launch Stage

If the user is already logged in, call the setupZendriveManager method within the didFinishWithLaunchingOptions class, to make sure that Zendrive SDK is configured correctly.

class AppDelegate {

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  let config = IQLConfig(versionName: versionName ?? "",
                               versionCode: versionCode ?? 0,
                               googleMapsKey: Environment.googleMapsKey,
                               apiBaseUrl: Environment.apiBaseUrl.absoluteString)
        IQLRef.sharedInstance.setup(with: config)
return true
}
class IQLRef {
    var zendriveManager: ZendriveManager!
.......

    func setup(with config: IQLConfig) {
        self.config = config
        api = API(baseUrl: config.apiBaseUrl, clientKey: "", on401: on401)
        initializeDependencies()
    }

  func initializeDependencies() {
        setupZendriveManager()
    }


     func setupZendriveManager() {
        zendriveManager.setup()
    }
}

2.4. Call ZendriveSDK resume API When Application Becomes Active

When the application becomes active, you will need to resume Zendrive SDK to start tracking trips. The resume API provides a convenient method to start Zendrive SDK after the initial set up. Call the resume method within the applicationDidBecomeActive method to resume Zendrive SDK, with the correct parameters. The following code snippet provides a reference for calling the resume API:

class AppDelegate {
  ......
  func applicationDidBecomeActive(_ application: UIApplication) {
    IQLRef.sharedInstance.resume()
  }
  ......
}
class IQLRef {
  var zendriveManager: ZendriveManager!
  .......
   func resume() {
    zendriveManager.resume()
  }
  .....
}

2.5. Integrate Zendrive SDK Heartbeat Service

Create a new endpoint similar to the Silent Push webhook and configure it with the IQL backend. The IQL backend will call this endpoint for each driver for whom the heartbeat data is not received for a given number of hours.

Using the driver's details, send a silent push notification to their device to wake up the application. The Zendrive SDK automatically collects a heartbeat once the application is woken up.

@api_view(['POST'])
def heartbeat_webhook(request):
   try:
       driver_id = request.data['info']['driver_id']
       driver = User.objects.get(driver_id=driver_id)
       push_service = PushService()
       push_service.send_heartbeat_push(driver)

       return Response(status=status.HTTP_200_OK)

   except User.DoesNotExist:
       logger.error(
           "Missing heartbeat web-hook was sent for a non-existent user " +
           driver_id)
       return Response(status=status.HTTP_400_BAD_REQUEST)
   except PushService.Error as e:
       logger.exception(e)
       return Response(status=status.HTTP_424_FAILED_DEPENDENCY)

2.6. Set Up Zendrive SDK and Send Heartbeat Update

This section includes the information required to set up Zendrive SDK and send the heartbeat update to Zendrive backend.

2.6.1. Background Fetch

private extension BackgroundFetchManager {


    func handleAppRefresh(_ task: BGTask) {


        logSDKHealthData()
    }

    func logSDKHealthData() {
        Zendrive.logSDKHealth(.backgroundProcessing) { error in
            if let error = error {
                DDLogError("Failed to log SDK health with error: \(error.localizedDescription)")
            } else {
                DDLogInfo("Logged SDK Health Successfully")
            }
        }
    }
}

2.6.2. Silent Push Notifications

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {



    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        DDLogInfo("Received remote notification with userInfo: \(userInfo)")
 if let data = userInfo["data"] as? [String: Any],
                  data["type"] as! String == "heartbeat" {
            Zendrive.logSDKHealth(.silentPushNotification) { error in
                if let error = error {
                    DDLogError("Failed to log SDK health with error: \(error.localizedDescription)")
                } else {
                    DDLogInfo("Logged SDK Health Successfully")
                }
            }
        }
    }
}