Mulai menggunakan Driver SDK untuk Android

Anda dapat menggunakan Driver SDK untuk memberikan navigasi dan pelacakan yang ditingkatkan ke aplikasi Perjalanan dan Progres Pesanan. Driver SDK menyediakan pembaruan lokasi dan tugas kendaraan untuk Fleet Engine Solusi Perjalanan dan Pengiriman On-demand.

Driver SDK membuat layanan Fleet Engine dan layanan kustom Anda mengetahui lokasi dan status kendaraan. Misalnya, kendaraan dapat berupa ONLINE atau OFFLINE, dan lokasi kendaraan berubah seiring berjalannya perjalanan.

Persyaratan sistem minimum

Perangkat seluler harus menjalankan Android 6.0 (level API 23) atau yang lebih baru.

Konfigurasi build dan dependensi

Driver SDK versi 4.99 dan yang lebih baru tersedia dari repositori Maven Google.

Gradle

Tambahkan baris berikut ke file build.gradle Anda:

repositories {
    ...
    google()
}

Maven

Tambahkan baris berikut ke file pom.xml Anda:

<project>
  ...
  <repositories>
    <repository>
      <id>google-maven-repository</id>
      <url>https://maven.google.com</url>
    </repository>
  </repositories>
  ...
</project>

Konfigurasi Project

Untuk menggunakan Driver SDK, aplikasi Anda harus menargetkan minSdkVersion 23 atau yang lebih tinggi.

Untuk menjalankan aplikasi yang dibuat dengan Driver SDK, perangkat Android harus menginstal layanan Google Play.

Menyiapkan project pengembangan

Untuk menyiapkan project pengembangan Anda dan mendapatkan kunci API untuk project tersebut di Konsol Google Cloud:

  1. Buat project Konsol Google Cloud baru, atau pilih project yang sudah ada, untuk digunakan dengan Driver SDK. Tunggu beberapa menit hingga project baru terlihat di Konsol Google Cloud.

  2. Untuk menjalankan aplikasi demo, project Anda harus memiliki akses ke Maps SDK for Android. Di Konsol Google Cloud, pilih APIs & Services > Library, lalu telusuri dan aktifkan Maps SDK for Android.

  3. Dapatkan kunci API untuk project dengan memilih APIs & Services > Credentials > Create credentials > API key. Untuk informasi selengkapnya tentang mendapatkan kunci API, lihat Mendapatkan kunci API.

Menambahkan Driver SDK ke aplikasi

Driver SDK tersedia dari repositori Maven Google. Repositori ini mencakup file Project Object Model (.pom) SDK dan Javadocs. Untuk menambahkan Driver SDK ke aplikasi Anda:

  1. Tambahkan dependensi berikut ke konfigurasi Gradle atau Maven Anda, dengan mengganti placeholder VERSION_NUMBER dengan versi Driver SDK yang diinginkan.

    Gradle

    Tambahkan kode berikut ke build.gradle Anda:

    dependencies {
      ...
      implementation 'com.google.android.libraries.mapsplatform.transportation:transportation-driver:VERSION_NUMBER'
    }
    

    Maven

    Tambahkan kode berikut ke pom.xml Anda:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation</groupId>
        <artifactId>transportation-driver</artifactId>
        <version>VERSION_NUMBER</version>
      </dependency>
    </dependencies>
    
  2. Driver SDK bergantung pada Navigation SDK, dependensi ini dikonfigurasi sedemikian rupa sehingga jika versi Navigation SDK tertentu diperlukan, dependensi harus secara eksplisit ditentukan dalam file konfigurasi build seperti berikut. Menghapus blok kode yang disebutkan akan memungkinkan project untuk selalu mendownload versi terbaru Navigation SDK dalam versi rilis utama. Perhatikan bahwa perilaku gabungan dari Driver SDK dan Navigation SDK versi terbaru telah melalui pengujian ketat sebelum dirilis.

    Atur konfigurasi dependensi lingkungan pengembangan dan rilis Anda sesuai kebutuhan.

    Gradle

    Tambahkan kode berikut ke build.gradle Anda:

    dependencies {
      ...
      implementation 'com.google.android.libraries.navigation:navigation:5.0.0'
    }
    

    Maven

    Tambahkan kode berikut ke pom.xml Anda:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.navigation</groupId>
        <artifactId>navigation</artifactId>
        <version>5.0.0</version>
      </dependency>
    </dependencies>
    

Menambahkan kunci API ke aplikasi

Setelah menambahkan Driver SDK ke aplikasi Anda, tambahkan kunci API ke aplikasi Anda. Anda harus menggunakan kunci API project yang diperoleh saat menyiapkan project pengembangan Anda.

Bagian ini menjelaskan cara menyimpan kunci API sehingga dapat dirujuk dengan lebih aman oleh aplikasi Anda. Anda tidak boleh memasukkan kunci API ke sistem kontrol versi Anda. File tersebut harus disimpan dalam file local.properties, yang berada di direktori utama project Anda. Untuk informasi selengkapnya tentang file local.properties, lihat file properti Gradle.

Untuk menyederhanakan tugas ini, Anda dapat menggunakan Plugin Secrets Gradle untuk Android.

Untuk menginstal plugin dan menyimpan kunci API Anda:

  1. Buka file build.gradle tingkat root dan tambahkan kode berikut ke elemen dependencies di bagian buildscript.

    Groovy

    buildscript {
        dependencies {
            // ...
            classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.0"
        }
    }
    

    Kotlin

    buildscript {
        dependencies {
            // ...
            classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.0")
        }
    }
    
  2. Buka file build.gradle tingkat aplikasi dan tambahkan kode berikut ke elemen plugins.

    Groovy

    id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
    

    Kotlin

    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
    
  3. Jika Anda menggunakan Android Studio, sinkronkan project Anda dengan Gradle.

  4. Buka local.properties pada direktori tingkat project, lalu tambahkan kode berikut. Ganti YOUR_API_KEY dengan kunci API Anda.

    MAPS_API_KEY=YOUR_API_KEY
    
  5. Dalam file AndroidManifest.xml Anda, buka com.google.android.geo.API_KEY dan perbarui atribut android:value sebagai berikut:

    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="${MAPS_API_KEY}" />
    

Contoh berikut menunjukkan manifes lengkap untuk aplikasi contoh:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.driverapidemo">
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/_AppTheme">

        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="${MAPS_API_KEY}" />

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Menyertakan atribusi yang diperlukan dalam aplikasi Anda

Jika menggunakan Driver SDK di aplikasi, Anda harus menyertakan teks atribusi dan lisensi open source sebagai bagian dari bagian pemberitahuan hukum aplikasi Anda. Sebaiknya sertakan atribusi sebagai item menu independen atau sebagai bagian dari item menu Tentang.

Informasi lisensi dapat ditemukan di file "third_party_licenses.txt" dalam file AAR yang tidak diarsipkan.

Lihat https://developers.google.com/android/guides/opensource tentang cara menyertakan pemberitahuan open source.

Dependensi

Jika menggunakan ProGuard untuk mengoptimalkan build, Anda mungkin perlu menambahkan baris berikut ke file konfigurasi ProGuard:

-dontwarn com.google.**
-dontwarn okio.**

API level minimum yang didukung adalah 23.

Menginisialisasi SDK

ID penyedia (biasanya Project ID Google Cloud) diperlukan untuk menginisialisasi objek DriverContext. Untuk mengetahui detail selengkapnya tentang cara menyiapkan Project Google Cloud, lihat Autentikasi dan Otorisasi.

Sebelum menggunakan Driver SDK, Anda harus melakukan inisialisasi Navigation SDK terlebih dahulu. Untuk menginisialisasi SDK:

  1. Dapatkan objek Navigator dari NavigationApi.

    Java

    NavigationApi.getNavigator(
        this, // Activity
        new NavigationApi.NavigatorListener() {
          @Override
          public void onNavigatorReady(Navigator navigator) {
            // Keep a reference to the Navigator (used to configure and start nav)
            this.navigator = navigator;
          }
        }
    );
    

    Kotlin

    NavigationApi.getNavigator(
      this, // Activity
      object : NavigatorListener() {
        override fun onNavigatorReady(navigator: Navigator) {
          // Keep a reference to the Navigator (used to configure and start nav)
          this@myActivity.navigator = navigator
        }
      },
    )
    
  2. Buat objek DriverContext, yang akan mengisi kolom wajib diisi.

    Java

    DriverContext driverContext = DriverContext.builder(application)
        .setProviderId(providerId)
        .setVehicleId(vehicleId)
        .setAuthTokenFactory(authTokenFactory)
        .setNavigator(navigator)
        .setRoadSnappedLocationProvider(
            NavigationApi.getRoadSnappedLocationProvider(application))
        .build();
    

    Kotlin

    val driverContext =
      DriverContext.builder(application)
        .setProviderId(providerId)
        .setVehicleId(vehicleId)
        .setAuthTokenFactory(authTokenFactory)
        .setNavigator(navigator)
        .setRoadSnappedLocationProvider(NavigationApi.getRoadSnappedLocationProvider(application))
        .build()
    
  3. Gunakan objek DriverContext untuk melakukan inisialisasi *DriverApi.

    Java

    RidesharingDriverApi ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext);
    

    Kotlin

    val ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext)
    
  4. Dapatkan RidesharingVehicleReporter dari objek API. (*VehicleReporter memperluas NavigationVehicleReporter.)

    Java

    RidesharingVehicleReporter vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter();
    

    Kotlin

    val vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter()
    

Mengautentikasi dengan AuthTokenFactory

Saat menghasilkan update lokasi, Driver SDK harus mengirimkan update ini ke server Fleet Engine. Untuk mengautentikasi permintaan ini, Driver SDK akan memanggil instance AuthTokenFactory yang disediakan pemanggil. Factory bertanggung jawab untuk membuat token autentikasi pada waktu pembaruan lokasi.

Cara token dibuat akan berbeda-beda untuk setiap situasi developer. Namun, implementasi tersebut mungkin perlu:

  • mengambil token autentikasi, yang mungkin dalam format JSON, dari server HTTPS
  • mengurai dan meng-cache token
  • memuat ulang token saat masa berlakunya habis

Untuk mengetahui detail token yang diharapkan oleh server Fleet Engine, lihat Membuat Token Web JSON (JWT) untuk otorisasi.

Berikut adalah implementasi kerangka AuthTokenFactory:

Java

class JsonAuthTokenFactory implements AuthTokenFactory {
  private String token;  // initially null
  private long expiryTimeMs = 0;

  // This method is called on a thread whose only responsibility is to send
  // location updates. Blocking is OK, but just know that no location updates
  // can occur until this method returns.
  @Override
  public String getToken(AuthTokenContext authTokenContext) {
    if (System.currentTimeMillis() > expiryTimeMs) {
      // The token has expired, go get a new one.
      fetchNewToken(authTokenContext.getVehicleId());
    }
    return token;
  }

  private void fetchNewToken(String vehicleId) {
    String url =
        new Uri.Builder()
            .scheme("https")
            .authority("yourauthserver.example")
            .appendPath("token")
            .appendQueryParameter("vehicleId", vehicleId)
            .build()
            .toString();

    try (Reader r = new InputStreamReader(new URL(url).openStream())) {
      com.google.gson.JsonObject obj
          = com.google.gson.JsonParser.parseReader(r).getAsJsonObject();
      token = obj.get("Token").getAsString();
      expiryTimeMs = obj.get("TokenExpiryMs").getAsLong();

      // The expiry time could be an hour from now, but just to try and avoid
      // passing expired tokens, we subtract 10 minutes from that time.
      expiryTimeMs -= 10 * 60 * 1000;
    } catch (IOException e) {
      // It's OK to throw exceptions here. The StatusListener you passed to
      // create the DriverContext class will be notified and passed along the failed
      // update warning.
      throw new RuntimeException("Could not get auth token", e);
    }
  }
}

Kotlin

class JsonAuthTokenFactory : AuthTokenFactory() {

  private var token: String = ""
  private var expiryTimeMs: Long = 0

  // This method is called on a thread whose only responsibility is to send
  // location updates. Blocking is OK, but just know that no location updates
  // can occur until this method returns.
  override fun getToken(context: AuthTokenContext): String {
    if (System.currentTimeMillis() > expiryTimeMs) {
      // The token has expired, go get a new one.
      fetchNewToken(authTokenContext.getVehicleId())
    }
     return token
  }

  fun fetchNewToken(vehicleId: String) {
    val url =
      Uri.Builder()
        .scheme("https")
        .authority("yourauthserver.example")
        .appendPath("token")
        .appendQueryParameter("vehicleId", vehicleId)
        .build()
        .toString()

    try {
      val reader = InputStreamReader(URL(url).openStream())

      reader.use {
        val obj = com.google.gson.JsonParser.parseReader(r).getAsJsonObject()

        token = obj.get("ServiceToken").getAsString()
        expiryTimeMs = obj.get("TokenExpiryMs").getAsLong()

        // The expiry time could be an hour from now, but just to try and avoid
        // passing expired tokens, we subtract 10 minutes from that time.
        expiryTimeMs -= 10 * 60 * 1000
      }
    } catch (e: IOException) {
      // It's OK to throw exceptions here. The StatusListener you passed to
      // create the DriverContext class will be notified and passed along the failed
      // update warning.
      throw RuntimeException("Could not get auth token", e)
    }
  }
}

Implementasi khusus ini menggunakan klien HTTP Java bawaan untuk mengambil token dalam format JSON dari server autentikasi developer. Token disimpan untuk digunakan kembali. Token diambil ulang jika token lama berada dalam waktu 10 menit dari waktu habis masa berlakunya.

Implementasi Anda mungkin melakukan sesuatu yang berbeda, seperti menggunakan thread latar belakang untuk token refresh.

Pengecualian dalam AuthTokenFactory akan diperlakukan sebagai sementara kecuali jika terjadi berulang kali. Setelah beberapa kali percobaan, Driver SDK akan menganggap bahwa error bersifat permanen dan akan berhenti mencoba mengirim update.

Status dan Error Reporting dengan StatusListener

Karena Driver SDK melakukan tindakan di latar belakang, gunakan StatusListener untuk memicu notifikasi saat peristiwa tertentu terjadi, seperti error, peringatan, atau pesan debug. Error mungkin bersifat sementara (seperti BACKEND_CONNECTIVITY_ERROR), atau dapat menyebabkan update lokasi dihentikan secara permanen (seperti VEHICLE_NOT_FOUND, yang menunjukkan error konfigurasi).

Anda memberikan implementasi StatusListener opsional seperti berikut:

Java

class MyStatusListener implements StatusListener {
  /** Called when background status is updated, during actions such as location reporting. */
  @Override
  public void updateStatus(
      StatusLevel statusLevel, StatusCode statusCode, String statusMsg) {
    // Status handling stuff goes here.
    // StatusLevel may be DEBUG, INFO, WARNING, or ERROR.
    // StatusCode may be DEFAULT, UNKNOWN_ERROR, VEHICLE_NOT_FOUND,
    // BACKEND_CONNECTIVITY_ERROR, or PERMISSION_DENIED.
  }
}

Kotlin

class MyStatusListener : StatusListener() {
  /** Called when background status is updated, during actions such as location reporting. */
  override fun updateStatus(statusLevel: StatusLevel, statusCode: StatusCode, statusMsg: String) {
    // Status handling stuff goes here.
    // StatusLevel may be DEBUG, INFO, WARNING, or ERROR.
    // StatusCode may be DEFAULT, UNKNOWN_ERROR, VEHICLE_NOT_FOUND,
    // BACKEND_CONNECTIVITY_ERROR, or PERMISSION_DENIED.
  }
}

Catatan tentang SSL/TLS

Secara internal, implementasi Driver SDK menggunakan SSL/TLS untuk berkomunikasi secara aman dengan server Fleet Engine. Android versi lama (API versi 19 atau yang lebih lama) mungkin memerlukan patch SecurityProvider agar dapat berkomunikasi dengan server. Sebaiknya lihat artikel ini untuk mengetahui informasi selengkapnya tentang cara menggunakan SSL di Android. Artikel ini juga berisi contoh kode untuk mem-patch penyedia keamanan.

Mengaktifkan pembaruan lokasi

Setelah Anda memiliki instance *VehicleReporter, mengaktifkan pembaruan lokasi dapat langsung dilakukan:

Java

RidesharingVehicleReporter reporter = ...;

reporter.enableLocationTracking();

Kotlin

val reporter = ...

reporter.enableLocationTracking()

Pembaruan lokasi dikirim pada interval reguler saat kendaraan berstatus ONLINE. Perhatikan bahwa memanggil reporter.enableLocationTracking() tidak secara otomatis menetapkan status kendaraan ke ONLINE. Anda harus menetapkan status kendaraan secara eksplisit.

Secara default, interval pelaporan adalah 10 detik. Interval pelaporan dapat diubah dengan reporter.setLocationReportingInterval(long, TimeUnit). Interval update minimum yang didukung adalah 5 detik. Update yang lebih sering dapat menghasilkan permintaan dan error yang lebih lambat.

Menonaktifkan pembaruan lokasi

Saat perpindahan pengemudi selesai, pembaruan lokasi dapat dihentikan dan kendaraan ditandai sebagai offline dengan memanggil DeliveryVehicleReporter.disableLocationTracking atau RidesharingVehicleReporter.disableLocationTracking.

Panggilan ini akan menyebabkan satu update terakhir dijadwalkan untuk pengiriman langsung, yang menunjukkan bahwa kendaraan sedang offline. Pembaruan ini tidak akan berisi lokasi pengguna.

Menetapkan status kendaraan

Saat pembaruan lokasi diaktifkan, menetapkan status kendaraan ke ONLINE akan membuat kendaraan tersedia untuk kueri SearchVehicles; demikian pula, menandai kendaraan sebagai OFFLINE akan menandai kendaraan sebagai tidak tersedia.

Anda memiliki opsi untuk menetapkan status kendaraan di sisi server (lihat Mengupdate Kendaraan), atau langsung di Driver SDK:

Java

RidesharingVehicleReporter reporter = ...;

reporter.enableLocationTracking();
reporter.setVehicleState(VehicleState.ONLINE);

Kotlin

val reporter = ...

reporter.enableLocationTracking()
reporter.setVehicleState(VehicleState.ONLINE)

Saat pembaruan lokasi diaktifkan, panggilan ke setVehicleState akan diterapkan pada pembaruan lokasi berikutnya.

Menandai kendaraan sebagai ONLINE saat pelacakan lokasi tidak diaktifkan akan menghasilkan IllegalStateException. Kendaraan dapat ditandai sebagai OFFLINE jika pelacakan lokasi belum diaktifkan atau dinonaktifkan secara eksplisit. Tindakan ini akan menghasilkan update langsung. Panggilan ke RidesharingVehicleReporter.disableLocationTracking() akan menetapkan status kendaraan ke OFFLINE.

Perhatikan bahwa setVehicleState segera ditampilkan, dan update dilakukan di thread update lokasi. Serupa dengan penanganan error untuk pembaruan lokasi, error yang memperbarui status kendaraan disebarkan menggunakan StatusListener yang disediakan secara opsional yang disetel di DriverContext.