Introduction
Azuga ELD provides a powerful and comprehensive solution for managing the movements and activities of mobile workers in general, and drivers subject to federal “hours of service” regulations in particular.
The full solution comprises a front-end app typically running on a tablet form-factor device, an administrative portal providing access to information about a fleet of vehicles, and a “back-end” cloud-resident platform that monitors and manages the real-time information transmitted from the tablets and other telematics devices.
This document focuses specifically on adding our front-end application to an existing application. This is provided by incorporating four android libraries into the application. An android library is a way of bundling code fragments into an easily accessible format.1
Prerequisites
Download http://developer.vistracks.com/wp-content/uploads/2022/09/VistracksApplicationIntegration.zip
Release Notes:
- vtlib-release.aar
Version: 3.0.2212.220905
Refer changes on application from http://eld.azuga.com/releaseNotes/September2022_android_app_release_notes.pdf
- pt-sdk-release.aar
Version: 6.6.0
- wvalib-release.aar
Version: 1.0
- EldBleLib-release.aar
Version: 1.0.15
- hos-mobile-interface.aar
Version: 3.0.210610
- vehicle-interface.aar
Version: 1.3.0
- suntech-api.aar
Version: 2.1
- terminalio-debug.aar
Version: 3.2
Note: Dependencies versions updated (please review the steps)
How to Integrate Our Application
Step 1. In your project build.gradle file, add these repositories and dependencies
repositories { google() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:7.0.4' classpath 'com.google.gms:google-services:4.3.10' classpath 'com.google.firebase:perf-plugin:1.4.0' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.0' classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10' classpath 'org.jetbrains.kotlin:kotlin-serialization:1.6.10' // Your other dependencies here }
Step 2. Add these values to your project build.gradle after your buildscript {…} tag as follows. This ensures that the application is receiving the correct versions of it’s dependencies
buildscript {...} allprojects { repositories { google() maven { url 'https://jitpack.io' } mavenCentral() jcenter() // Currently still needed because of expandableRecyclerviewVersion } } // Version numbers in single place ext.v = [ // SDK and tools minSdkVersion : 21, targetSdkVersion : 31, compiledSdkVersion : 31, // App dependencies androidXActivityVersion : '1.4.0', androidXAppCompatVersion : '1.4.0', androidXCoreVersion : '1.7.0', androidXEspressoVersion : '3.4.0', androidXFragmentVersion : '1.4.0', androidXLifecycleVersion : '2.4.0', androidXPreferenceVersion : '1.1.1', androidXRecyclerViewVersion: '1.2.1', androidXSqliteVersion : '2.1.0', androidXTestVersion : '1.4.0', androidXTestExtJUnitVersion: '1.1.3', androidXTransitionVersion : '1.4.1', androidXVersion : '1.0.0', coilVersion : '1.3.2', commonsNetVersion : '3.6', constraintLayoutVersion : '2.1.2', daggerVersion : '2.38.1', espressoVersion : '3.3.0', exifinterfaceVersion : '1.3.3', expandableRecyclerviewVersion: '1.3', fabVersion : '1.6.4', firebaseAnalyticsVersion : '20.0.0', firebaseCrashlyticsVersion : '18.2.4', firebaseMessagingVersion : '23.0.0', firebasePerfMonVersion : '20.0.3', flexBoxVersion : '3.0.0', geometrisVersion : '1.0.8', grpcVersion : '1.34.0', gsonVersion : '2.8.6', guavaVersion : '24.1-jre', httpmimeVersion : '4.2.2', jodaTimeVersion : '2.10.6', jtsVersion : '1.13', junitJupiterVersion : '5.7.0', junitVersion : '4.13.1', klockVersion : '2.2.2', kotlinxVersion : '1.6.10', kotlinxDateTimeVersion : '0.3.1', kotlinSerializationVersion : '1.2.2', kotlinCoroutinesVersion : '1.5.1', materialVersion : '1.4.0', mockitoVersion : '3.7.7', multidexVersion : '2.0.1', nordicsemiLogVersion : '2.2.0', nordicsemiScannerVersion : '1.4.2', nordicsemiBleVersion : '2.2.4', obdJavaApiVersion : '1.0', okHttpVersion : '4.9.1', okIoVersion : '2.10.0', pdfBoxVersion : '2.0.3.0', playServicesMapsVersion : '18.0.0', playServicesLocationVersion: '18.0.0', reactiveStreamsVersion : '1.0.3', roboElectricVersion : '4.5.1', roomVersion : '2.3.0', rxAndroidVersion : '3.0.0', rxBindingVersion : '4.0.0', rxJavaVersion : '3.0.13', securityCryptoVersion : '1.1.0-alpha03', squareOkHttpVersion : '2.0.0', truetimeVersion : '3.5', workVersion : '2.7.1' ]
Step 3. In your app module build.gradle file, add
apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.firebase.firebase-perf' apply plugin: 'com.google.firebase.crashlytics' apply plugin: 'kotlin-kapt' apply plugin: 'kotlinx-serialization' android { compileSdkVersion v.compiledSdkVersion buildToolsVersion v.buildToolsVersion defaultConfig { applicationId [your application id] minSdkVersion v.minSdkVersion targetSdkVersion v.targetSdkVersion versionCode 540 // Have your other configuration code here } buildTypes { release { multiDexEnabled true // Have your other configuration code here } } compileOptions { coreLibraryDesugaringEnabled true sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } buildFeatures { viewBinding true } }
Step 4. Add these configurations and dependencies in your application module
configurations.all { resolutionStrategy { force "org.reactivestreams:reactive-streams:${v.reactiveStreamsVersion}" } } dependencies { // includes all jar files in libs directory implementation fileTree(dir: 'libs', include: '*.jar') implementation fileTree(dir: 'libs', include: '*.aar') coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1' // required here to avoid a warning complaining about the firebase or play services version not being specified. api "com.google.firebase:firebase-analytics-ktx:${v.firebaseAnalyticsVersion}" implementation "com.google.firebase:firebase-perf-ktx:${v.firebasePerfMonVersion}" // for wvalib implementation "com.squareup.okhttp:okhttp:${v.squareOkHttpVersion}" // Required to avoid build error similar to "Duplicate class com.google.common.util.concurrent.ListenableFuture found in modules jetified-guava-26.0-android.jar (com.google.guava:guava:26.0-android) and jetified-listenablefuture-1.0.jar (com.google.guava:listenablefuture:1.0)" // https://github.com/firebase/firebase-android-sdk/issues/1320#issuecomment-601159166 implementation "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" // for pacific track sdk implementation "no.nordicsemi.android:log:${v.nordicsemiLogVersion}" implementation "no.nordicsemi.android.support.v18:scanner:${v.nordicsemiScannerVersion}" implementation "no.nordicsemi.android:ble-common:${v.nordicsemiBleVersion}" implementation "commons-net:commons-net:${v.commonsNetVersion}" implementation "com.google.guava:guava:${v.guavaVersion}" //Geometris sdk implementation "com.github.geometris:GeometrisMobile:${v.geometrisVersion}" //Barcode Scanning implementation 'com.google.zxing:android-integration:3.3.0' //RxJava implementation "com.jakewharton.rxbinding4:rxbinding:${v.rxBindingVersion}" implementation "io.reactivex.rxjava3:rxandroid:${v.rxAndroidVersion}" implementation "io.reactivex.rxjava3:rxjava:${v.rxJavaVersion}" // dagger annotationProcessor "com.google.dagger:dagger-compiler:${v.daggerVersion}" annotationProcessor "com.google.dagger:dagger-android-processor:${v.daggerVersion}" kapt "com.google.dagger:dagger-compiler:${v.daggerVersion}" kapt "com.google.dagger:dagger-android-processor:${v.daggerVersion}" implementation "com.google.dagger:dagger:${v.daggerVersion}" implementation "com.google.dagger:dagger-android-support:${v.daggerVersion}" compileOnly 'javax.annotation:jsr250-api:1.0' // OkHttp implementation "com.squareup.okhttp3:okhttp:${v.okHttpVersion}" implementation "com.squareup.okhttp3:logging-interceptor:${v.okHttpVersion}" implementation "com.squareup.okio:okio:${v.okIoVersion}" // androidx libraries api "androidx.appcompat:appcompat:${v.androidXAppCompatVersion}" implementation "androidx.multidex:multidex:${v.multidexVersion}" implementation "androidx.work:work-runtime-ktx:${v.workVersion}" implementation "androidx.work:work-gcm:${v.workVersion}" implementation "androidx.core:core-ktx:${v.androidXCoreVersion}" implementation "androidx.activity:activity-ktx:${v.androidXActivityVersion}" implementation "androidx.fragment:fragment-ktx:${v.androidXFragmentVersion}" implementation "androidx.sqlite:sqlite-ktx:${v.androidXSqliteVersion}" implementation "androidx.cardview:cardview:${v.androidXVersion}" implementation "androidx.gridlayout:gridlayout:${v.androidXVersion}" implementation "androidx.preference:preference-ktx:${v.androidXPreferenceVersion}" implementation "androidx.recyclerview:recyclerview:${v.androidXRecyclerViewVersion}" implementation "androidx.transition:transition-ktx:${v.androidXTransitionVersion}" implementation "androidx.constraintlayout:constraintlayout:${v.constraintLayoutVersion}" implementation "androidx.exifinterface:exifinterface:${v.exifinterfaceVersion}" api "com.google.android.material:material:${v.materialVersion}" // architecture components implementation "androidx.lifecycle:lifecycle-common-java8:${v.androidXLifecycleVersion}" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:${v.androidXLifecycleVersion}" implementation "androidx.lifecycle:lifecycle-runtime-ktx:${v.androidXLifecycleVersion}" implementation "androidx.lifecycle:lifecycle-livedata-ktx:${v.androidXLifecycleVersion}" api "androidx.lifecycle:lifecycle-reactivestreams-ktx:${v.androidXLifecycleVersion}" // room implementation "androidx.room:room-runtime:${v.roomVersion}" kapt "androidx.room:room-compiler:${v.roomVersion}" // Kotlin Extensions and Coroutines support for Room implementation "androidx.room:room-ktx:${v.roomVersion}" testImplementation "androidx.room:room-testing:${v.roomVersion}" // used for fancier floating button that shows more options when pressed. implementation "com.github.clans:fab:${v.fabVersion}" // google play services implementation "com.google.android.gms:play-services-maps:${v.playServicesMapsVersion}" implementation "com.google.android.gms:play-services-location:${v.playServicesLocationVersion}" api "com.google.firebase:firebase-analytics-ktx:${v.firebaseAnalyticsVersion}" api "com.google.firebase:firebase-messaging-ktx:${v.firebaseMessagingVersion}" implementation("com.google.firebase:firebase-crashlytics-ktx:${v.firebaseCrashlyticsVersion}") { transitive = true } api "com.google.code.gson:gson:${v.gsonVersion}" implementation "joda-time:joda-time:${v.jodaTimeVersion}" implementation "com.github.pires:obd-java-api:${v.obdJavaApiVersion}" api "com.google.android.flexbox:flexbox:${v.flexBoxVersion}" api "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${v.kotlinxVersion}" implementation "org.jetbrains.kotlinx:kotlinx-datetime:${v.kotlinxDateTimeVersion}" implementation 'co.touchlab:stately-common:1.2.0' //coroutines implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${v.kotlinCoroutinesVersion}" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${v.kotlinCoroutinesVersion}" testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:${v.kotlinCoroutinesVersion}" // serialization implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:${v.kotlinSerializationVersion}" // Testing libraries testImplementation "junit:junit:${v.junitVersion}" testImplementation "org.junit.jupiter:junit-jupiter:$v.junitJupiterVersion" testImplementation "org.mockito:mockito-core:${v.mockitoVersion}" // Needed to mock certain classes // https://stackoverflow.com/questions/14292863/how-to-mock-a-final-class-with-mockito/40018295#40018295 testImplementation "org.mockito:mockito-inline:${v.mockitoVersion}" testImplementation "com.squareup.okhttp3:mockwebserver:${v.okHttpVersion}" // Used to provide an implementation of the android logger for now testImplementation "org.robolectric:robolectric:${v.robolectricVersion}" // StriKt Assertion Library testImplementation "io.strikt:strikt-core:0.31.0" // Geospatial library api 'com.vividsolutions:jts:1.13' //ExpandableRecyclerView implementation "com.thoughtbot:expandablerecyclerview:${v.expandableRecyclerviewVersion}" //Truetime for Timing Compliance Malfunctions implementation "com.github.instacart.truetime-android:library-extension-rx:${v.truetimeVersion}" //Instrumented tests androidTestImplementation "androidx.test.ext:junit:${v.androidXTestExtJUnitVersion}" implementation "com.soywiz.korlibs.klock:klock-android:${v.klockVersion}" // For PDF validation implementation "com.tom-roush:pdfbox-android:${v.pdfBoxVersion}" // grpc implementation "io.grpc:grpc-core:${v.grpcVersion}" implementation "io.grpc:grpc-api:${v.grpcVersion}" implementation "io.grpc:grpc-netty-shaded:${v.grpcVersion}" implementation "io.grpc:grpc-okhttp:${v.grpcVersion}" implementation "io.grpc:grpc-protobuf-lite:${v.grpcVersion}" implementation "io.grpc:grpc-stub:${v.grpcVersion}" // gRPC uses these annotations implementation 'javax.annotation:javax.annotation-api:1.3.2' // Timber (logging) api 'com.jakewharton.timber:timber:4.7.1' // Coil implementation to abstract and optimize bitmap processing implementation("io.coil-kt:coil-base:$v.coilVersion") // For encrypting files implementation "androidx.security:security-crypto:$v.securityCryptoVersion" }
Step 5. Import all .aar files as new modules from an AAR.
Then add them as dependencies in your app module build.gradle
dependencies {
// Previous dependencies here
implementation project(':vtlib-release')
implementation project(':EldBleLib-release')
implementation project(':hos-mobile-interface')
implementation project(':suntech-api')
implementation project(':terminalio-debug')
implementation project(':vehicle-interface')
implementation project(':pt-sdk-release')
implementation project(':wvalib-release')
}
Step 6. Have your application class extend VtApplication.
import com.azugaeld.vtlib.app.VtApplication; public class TestApplication extends VtApplication { // Insert your application code here }
Step 6.5 Add tools:replace=“android:name” in your application tag in your manifest
Step 7. Add this code snippet which adds AppTheme to your styles.xml (Typically found at [Root]/src/main/res/values/styles.xml). App theme must not extend *.NoActionBar or some activities will fail to launch.
<!-- Customized theme for branding --> <style name="AppTheme" parent="AppBaseTheme"> <!-- Colors --> <item name="colorPrimary">@color/default_colorPrimary</item> <item name="colorPrimaryDark">@color/default_colorPrimaryDark</item> <item name="colorAccent">@color/default_colorAccent</item> <item name="colorLight">@color/blue50</item> <item name="colorButtonNormal">@color/grey300</item> <item name="colorPrimaryButton">?attr/colorPrimary</item> <item name="colorGeneralNotificationBar">@color/default_colorAccent</item> <item name="colorGridHosLine">@color/default_colorPrimary</item> <item name="colorGridHosLineDark">@color/default_colorPrimaryDark</item> <item name="logsHeaderSectionColor">@color/default_colorPrimaryDark</item> <item name="dayNightTintColor">@color/grey600</item> <item name="hosBigButtonThemeOverlay">@null</item> <item name="searchViewBackground">@drawable/search_bar_rounded</item> <item name="dvirSummaryNightText">@color/grey700</item> <!-- Default font style sizes --> <item name="font_small">@dimen/appbase_text_size_small_material</item> <item name="font_medium">@dimen/appbase_text_size_medium_material</item> <item name="font_large">@dimen/appbase_text_size_large_material</item> <item name="font_xlarge">@dimen/appbase_text_size_headline_material</item> <item name="font_display3">@dimen/appbase_text_size_display_1_material</item> <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item> </style>
Step 8. If you are using an app theme, or want to integrate your theme with our’s or want to customize the default theme, have that theme extend AppTheme.
Step 9. Add this code snippet on your AndroidManifest.xml to replace the launcher activity of HOS app. Also add the provider inside application tag to replace workmanager.
<!-- Replace launcher from library --> <activity android:name="com.azugaeld.vtlib.authentication.StartMainActivity" android:label="@string/app_name" android:exported="true" tools:node="replace"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> </intent-filter> <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/accessory_filter" /> </activity> <provider tools:replace="android:authorities" android:name="androidx.work.impl.WorkManagerInitializer" android:authorities="[your application id].work_manager.provider.v1" android:enabled="false" />
Step 10. Make sure to add this DeveloperAPI.setHosAsLibrary(true) on your application to prevent exiting appliction when logging out from HOS screen.
Step 11. Use the DeveloperAPI.getVtApplication(Context c) to get the context for our application. Start it from an activity to launch our application.
Activity Classes
Job Sites | JobSiteListActivity.class | Intent i = new Intent(context, JobSiteListActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i); |
Work Orders | WorkOrderListActivity.class | Intent i = new Intent(context, WorkOrderListActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i); |
Roadside Inspection | RoadsideInspectionStartActivity.class | Intent i = new Intent(context, RoadsideInspectionStartActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i); |
Documents | DriverDocumentListActivity.class | Intent i = new Intent(context, DriverDocumentListActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i); |
Fuel Receipts | DriverDocumentListActivity.class | Intent i = new Intent(context, DriverDocumentListActivity.class); i.putExtra(DriverDocumentListFragment.ARG_IS_FUEL_RECEIPT, true); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i); |
Settings | AppPreferencesActivity.class | Intent i = new Intent(context, AppPreferencesActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i); |
Help & Support | UserHelpActivity.class | Intent i = new Intent(context, UserHelpActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i); |