Enable Test Drive

This section describes the basic test drive experience, which allows users to view their driving performance summary. This section comprises the following topics:

Enable Test Drive

Enable Test Drive

Enable Test Drive

Enable Test Drive

1.0. Integrate the driverStatus API

This section describes how to integrate the driverStatus API into your application.

1.1. Create a Wrapper for the IQL driverStatus API

Use the following code snippet to create a wrapper for the IQL driverStatus API in the application's backend.

@api_view(['GET'])
def get_status(request, *args, **kwargs):
    api_key = settings.IQL_API_KEY
    try:
        driver_id = kwargs['driver_id']
        driver = User.objects.get(driver_id=driver_id)
        authenticate(driver, request)
        iql_response = requests.get(
            IQL_STATUS_ENDPOINT.format(driver_id),
            params=request.GET,
            headers={'Authorization': 'APIKEY {}'.format(api_key)})

        return get_response(iql_response)

    except User.DoesNotExist:
        return Response({'message': 'This driver does not exist'},
                        status=status.HTTP_400_BAD_REQUEST)
    except Exception as e:
        return Response({'message': e.detail}, status=e.status_code)

1.2. Fetch the Latest Status Using driverStatus API

Add the driverStatus endpoint and fetch the latest driver status using the following code snippet:

 interface ApiService { 
 @GET("/iql/v1/driver/{driver_id}/status/") 
  fun getDriverStatus( 
 @Path("driver_id") driverId: String 
  ): Call<IQLDriverStatus> 
 ... 
 } 
 
 class Api(private val apiService: ApiService) 
 {  
 ... 
 ... 
 
suspend fun getDriverStatus(driverId: String): ApiResponse<IQLDriverStatus> = 
 suspendCancellableCoroutine { cont -> 
 cont.invokeOnCancellation { 
 if (!apiService.getDriverStatus(driverId).isCanceled) 
 {  apiService.getDriverStatus(driverId).cancel() 
  } 
 } 
 apiService.getDriverStatus(driverId).enqueue
 (  object : Callback<IQLDriverStatus> { 
 override fun onResponse( 
 call: Call<IQLDriverStatus>, 
 response: Response<IQLDriverStatus> 
  ) { 
 if (response.isSuccessful) { 
 
cont.resume(ApiResponse.Success(response.body()!!)) 
 } else { 
val contentType = response.headers()["Content 
 
Type"] 
 
if (contentType != null && contentType == 
"application/json") { 
 cont.resume( 
  ApiResponse.Failure( 
 FailureResponse( 
  response.code().toString() 
  ) 
 ) 
 ) 
 } else { 
 Timber.e(response.errorBody()?.string()) 
  cont.resume( 
 ApiResponse.Failure( 
  FailureResponse( 
   response.code().toString()  
   ) 
 ) 
 ) 
 } 
 } 
 } 
 
override fun onFailure(call: Call<IQLDriverStatus>, t: 
 
Throwable) { 
 cont.resume(ApiResponse.Error(t)) 
  } 
 } 
 ) 
 } 
 ... 
 ... 
 } 
 
 class IQLApisRepository( 
 database: IQLDatabase, 
 val api: Api 
 ) { 
 ... 
 ... 
 suspend fun refreshDriverStatusFromNetwork(driverId: String): Boolean 
 {  return when (val apiResponse = api.getDriverStatus(driverId)) 
 {  is ApiResponse.Success -> {
 
Timber.d("Fetch driver status response successful 
${apiResponse.data.driverId} ${apiResponse.data}") 
 settingDao.saveIqlDriverStatusDetails(apiResponse.data) 
  true 
 } 
 is ApiResponse.Failure -> { 
 
Timber.e("Fetch driver status response failed for user 
$driverId ${apiResponse.failure}") 
 false 
 } 
 is ApiResponse.Error -> { 
 
Timber.e(apiResponse.throwable, "Fetch driver status response error for user") 
 false 
 } 
 } 
 } 
 ... 
 ... 
 } 
 // Worker class to fetch driver status 
 
class FetchIQLDriverStatusWorker(context: Context, workerParams: WorkerParameters) : 
 CoroutineWorker(context, workerParams) { 
 
 private val loginRepository = ZWLCore.loginRepository() 
  private val iqlApisRepository = ZWLCore.iqlApisRepository() 
   
 override suspend fun doWork(): Result = withContext(AppDispatchers.IO) 
 {  Timber.d("Start fetch IQL Driver Status Work ") 
 try { 
 loginRepository.getDriverIdFromPreferences()?.let { driverId -> iqlApisRepository.refreshDriverStatusFromNetwork(driverId) 
  } 
 } catch (e: Exception) { 
 Timber.e(e, "Fetch IQL Driver Status Work failed") 
  } 
 Timber.d("End Fetch IQL Driver Status Work") 
 return@withContext Result.success() 
 }
 } 
 object ZWLWorkManager { 
 ... 
 ... 
 fun enqueueFetchIQLDriverStatus(context: Context) { 
 Timber.d("Enqueue work to fetch IQL Driver Status") 
  val work1 = OneTimeWorkRequestBuilder<FetchIQLDriverStatusWorker>()
   .setConstraints( 
 
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
  ) 
 .build() 
 WorkManager.getInstance(context) 
 .enqueueUniqueWork( 
 FETCH_IQL_DRIVER_STATUS, 
 ExistingWorkPolicy.REPLACE, 
 work1 
 ) 
 } 
 ... 
 ... 
 } 
 
 
class HomeViewModel(application: Application) : AndroidViewModel(application) 
 
{ 
 ... 
 ... 
 fun getDriverStatus() { 
 ZWLWorkManager.enqueueFetchIQLDriverStatus(ZWLCore.context()) 
  } 
 
 ... 
 ... 
 fun checkAndExecuteDriverStatusAPI() { 
executeApiUsingTimeStamps(previousApiTimeStamp = driverStatusApiTimeStamp) 
 
{ 
 executeApi( 141 calendar = it,
 onTimeChanged = { 
 driverStatusApiTimeStamp = it 

 
Timber.d("Driver Status Api New Time Stamp 
$driverStatusApiTimeStamp") 

 }, 
 onExecute = { 
 getDriverStatus() 
 }, 
 log = "Driver Status Api called at") 
 } 
 } 
 ... 
 ... 
 } 
 
 // Fetch latest driver status on app launch 
 class HomeActivity : AppBaseActivity(), PopupMenu.OnMenuItemClickListener {  private lateinit var binding: ActivityHomeBinding 
 private val viewModel: HomeViewModel by viewModels() 
 ... 
 ... 
 override fun onResume() { 
 super.onResume() 
 val recentTrips = viewModel.trips.value 
 if (recentTrips != null && recentTrips.isNotEmpty()) { 

 
val imageAvailable = 
viewModel.isThumbnailGeneratedForAllTrips(recentTrips) 

 if (!imageAvailable) { 
 viewModel.scheduleTripMapGenerateTask()  
 } else { 
 viewModel.shutDownScheduler() 
  } 
 } 
 viewModel.checkAndExecuteDriverStatusAPI()  
 } 
 }

2.0. Build a Driver Performance Experience

Create a driving performance UI experience as shown in the UX design below, use the following code snippet to populate the application's UI with the latest driver status.

3.0. IQL Reference Application UX Design

Here is the overall design implementation for the IQL Reference Application:

4.0. Publisher Integration Testing Checklist

Use the following testing checklist to test the 'Enable Test Drive' process on your application:

  • Trip: After the user onboarding is complete, ensure that Zendrive SDK is working as expected by taking a few trips. All trips taken by the user should be recorded.

  • Dashboard: Ensure that any program-related data, such as progress %, driving days, miles driven, trips takenand so on, is accurately presented in the application, and matches the values coming from driverStatus API.

  • Refresh: Ensure that any data shown in the application is updated whenever the program screen is loaded. This will ensure that only the latest data is presented to the users.