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:
1.0. Integrate the driverStatus
API
driverStatus
APIThis 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
driverStatus
APIAdd 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 taken
and 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.