การเริ่มต้นใช้งาน Driver SDK สําหรับ Android

คุณสามารถใช้ SDK ไดรเวอร์เพื่อให้การนำทางและการติดตามขั้นสูงไปยังแอปพลิเคชันความคืบหน้าในการเดินทางและคำสั่งซื้อ Driver SDK จะให้ข้อมูลอัปเดตตำแหน่งของยานพาหนะและงานสำหรับ Fleet Engine โซลูชันการโดยสารและการนำส่งแบบออนดีมานด์

Driver SDK จะทำให้บริการ Fleet Engine และบริการที่คุณกำหนดเองทราบถึงตำแหน่งและสถานะของรถ ตัวอย่างเช่น ยานพาหนะอาจเป็น ONLINE หรือ OFFLINE และตำแหน่งยานพาหนะจะเปลี่ยนไปตามการเดินทาง

ข้อกำหนดขั้นต่ำของระบบ

อุปกรณ์เคลื่อนที่ต้องใช้ Android 5.0 (API ระดับ 21) ขึ้นไป

การกำหนดค่า Maven

Driver SDK เวอร์ชัน 4.99 ขึ้นไปจะพร้อมใช้งานผ่านที่เก็บ Google Maven

Gradle

เพิ่มโค้ดต่อไปนี้ในไฟล์ build.gradle

repositories {
    ...
    google()
}

Maven

เพิ่มโค้ดต่อไปนี้ในไฟล์ pom.xml

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

การกำหนดค่าโปรเจ็กต์

หากต้องการใช้ Driver SDK แอปของคุณต้องกำหนดเป้าหมายเป็น minSdkVersion 21 ขึ้นไป

หากต้องการเรียกใช้แอปที่สร้างด้วย Driver SDK อุปกรณ์ Android ต้องติดตั้ง บริการ Google Play ไว้แล้ว

ตั้งค่าโปรเจ็กต์การพัฒนาของคุณ

หากต้องการตั้งค่าโปรเจ็กต์การพัฒนาและรับคีย์ API สำหรับโปรเจ็กต์ใน Google Cloud Console ให้ทำดังนี้

  1. สร้างโปรเจ็กต์ Google Cloud Console ใหม่หรือเลือกโปรเจ็กต์ที่มีอยู่เพื่อใช้กับ Driver SDK รอสักครู่จนกว่าโปรเจ็กต์ใหม่จะแสดงใน Google Cloud Console

  2. หากต้องการเรียกใช้แอปเดโม โปรเจ็กต์ต้องมีสิทธิ์เข้าถึง Maps SDK สำหรับ Android ใน Google Cloud Console ให้เลือก API และบริการ > ไลบรารี จากนั้นค้นหาและเปิดใช้ Maps SDK สำหรับ Android

  3. รับคีย์ API สำหรับโปรเจ็กต์โดยเลือก API และบริการ > ข้อมูลเข้าสู่ระบบ > สร้างข้อมูลเข้าสู่ระบบ > คีย์ API ดูข้อมูลเพิ่มเติมเกี่ยวกับการรับคีย์ API ได้ที่รับคีย์ API

เพิ่ม Driver SDK ในแอปของคุณ

Driver SDK พร้อมให้ใช้งานผ่านที่เก็บ Maven ส่วนตัว ที่เก็บประกอบด้วยไฟล์ Project Object Model (.pom) และ Javadocs ของ SDK วิธีเพิ่ม Driver SDK ลงในแอป

  1. เพิ่มทรัพยากร Dependency ต่อไปนี้ในการกำหนดค่า Gradle หรือ Maven ของคุณ โดยแทนที่ตัวยึดตำแหน่ง VERSION_NUMBER สำหรับเวอร์ชัน SDK ของไดรเวอร์ที่ต้องการ

    Gradle

    เพิ่มข้อมูลต่อไปนี้ลงใน build.gradle

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

    Maven

    เพิ่มข้อมูลต่อไปนี้ลงใน pom.xml

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation</groupId>
        <artifactId>transportation-driver</artifactId>
        <version>VERSION_NUMBER</version>
      </dependency>
    </dependencies>
    

เพิ่มคีย์ API ลงในแอป

เมื่อเพิ่ม Driver SDK ในแอปแล้ว ให้เพิ่มคีย์ API ลงในแอป คุณต้องใช้คีย์ API ของโปรเจ็กต์ที่ได้มาเมื่อตั้งค่าโปรเจ็กต์การพัฒนาซอฟต์แวร์

ส่วนนี้อธิบายวิธีจัดเก็บคีย์ API เพื่อให้แอปอ้างอิงได้อย่างปลอดภัยยิ่งขึ้น คุณไม่ควรตรวจสอบคีย์ API ในระบบควบคุมเวอร์ชัน ซึ่งควรจัดเก็บไฟล์ไว้ในไฟล์ local.properties ซึ่งอยู่ในไดเรกทอรีรากของโปรเจ็กต์ ดูข้อมูลเพิ่มเติมเกี่ยวกับไฟล์ local.properties ได้ที่ไฟล์พร็อพเพอร์ตี้ Gradle

หากต้องการปรับปรุงงานนี้ ให้ใช้ปลั๊กอินข้อมูลลับ Gradle สำหรับ Android

วิธีติดตั้งปลั๊กอินและจัดเก็บคีย์ API

  1. เปิดไฟล์ build.gradle ระดับราก และเพิ่มโค้ดต่อไปนี้ลงในองค์ประกอบ dependencies ใต้ buildscript

    ดึงดูด

    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. เปิดไฟล์ build.gradle ระดับแอปและเพิ่มโค้ดต่อไปนี้ลงในองค์ประกอบ plugins

    ดึงดูด

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

    Kotlin

    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
    
  3. หากใช้ Android Studio ให้ซิงค์โปรเจ็กต์กับ Gradle

  4. เปิด local.properties ในไดเรกทอรีระดับโปรเจ็กต์ แล้วเพิ่มโค้ดต่อไปนี้ แทนที่ YOUR_API_KEY ด้วยคีย์ API

    MAPS_API_KEY=YOUR_API_KEY
    
  5. ในไฟล์ AndroidManifest.xml ให้ไปที่ com.google.android.geo.API_KEY และอัปเดตแอตทริบิวต์ android:value ดังนี้

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

ตัวอย่างต่อไปนี้แสดงไฟล์ Manifest ที่สมบูรณ์สำหรับแอปตัวอย่าง

<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>

ใส่แอตทริบิวต์ที่จำเป็นในแอป

หากใช้ Driver SDK ในแอป คุณต้องใส่ข้อความระบุแหล่งที่มาและใบอนุญาตโอเพนซอร์สเป็นส่วนหนึ่งของส่วนประกาศทางกฎหมายของแอป คุณควรรวมการระบุแหล่งที่มาเป็นรายการในเมนูอิสระหรือเป็นส่วนหนึ่งของรายการในเมนูเกี่ยวกับ

คุณสามารถดูข้อความระบุแหล่งที่มาและใบอนุญาตโอเพนซอร์สที่ต้องการในไฟล์ ZIP ของ Driver SDK ดังนี้

  • NOTICE.txt
  • LICENSES.txt

การอ้างอิง

หากคุณใช้ ProGuard เพื่อเพิ่มประสิทธิภาพบิลด์ คุณอาจต้องเพิ่มบรรทัดต่อไปนี้ลงในไฟล์การกำหนดค่า ProGuard

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

ระดับ API ขั้นต่ำที่รองรับคือ 21

การเริ่มต้น SDK

คุณต้องระบุรหัสผู้ให้บริการ (โดยปกติจะเป็นรหัสโปรเจ็กต์ Google Cloud) เพื่อเริ่มต้นออบเจ็กต์ DriverContext ดูรายละเอียดเพิ่มเติมเกี่ยวกับการตั้งค่าโปรเจ็กต์ Google Cloud ได้ที่การตรวจสอบสิทธิ์และการให้สิทธิ์

ก่อนที่จะใช้ Driver SDK ขั้นแรก คุณต้องเริ่มต้น Navigation SDK ก่อน วิธีเริ่มต้น SDK

  1. รับออบเจ็กต์ Navigator จาก 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. สร้างออบเจ็กต์ DriverContext กำลังกรอกข้อมูลในช่องที่ต้องกรอก

    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. ใช้ออบเจ็กต์ DriverContext เพื่อเริ่มต้น *DriverApi

    Java

    RidesharingDriverApi ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext);
    

    Kotlin

    val ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext)
    
  4. รับ RidesharingVehicleReporter จากออบเจ็กต์ API (*VehicleReporter ขยายเวลา NavigationVehicleReporter)

    Java

    RidesharingVehicleReporter vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter();
    

    Kotlin

    val vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter()
    

กำลังตรวจสอบสิทธิ์กับ AuthTokenFactory

เมื่อ Driver SDK สร้างการอัปเดตตำแหน่ง จะต้องส่งการอัปเดตเหล่านี้ไปยังเซิร์ฟเวอร์ Fleet Engine ในการตรวจสอบสิทธิ์คำขอเหล่านี้ Driver SDK จะเรียกใช้อินสแตนซ์ AuthTokenFactory จากผู้โทร โรงงานมีหน้าที่สร้างโทเค็นการตรวจสอบสิทธิ์ ณ เวลาอัปเดตตำแหน่ง

วิธีสร้างโทเค็นจะแตกต่างกันไปตามสถานการณ์ของนักพัฒนาซอฟต์แวร์แต่ละราย อย่างไรก็ตาม อาจต้องดำเนินการต่อไปนี้

  • เรียกโทเค็นการตรวจสอบสิทธิ์ซึ่งอาจอยู่ในรูปแบบ JSON จากเซิร์ฟเวอร์ HTTPS
  • แยกวิเคราะห์และแคชโทเค็น
  • รีเฟรชโทเค็นเมื่อหมดอายุ

โปรดดูรายละเอียดของโทเค็นที่เซิร์ฟเวอร์ Fleet Engine คาดหวังที่หัวข้อการสร้างโทเค็นเว็บ JSON (JWT) สำหรับการให้สิทธิ์

โครงสร้างของ 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)
    }
  }
}

การใช้งานเฉพาะนี้ใช้ไคลเอ็นต์ Java HTTP ในตัวเพื่อดึงข้อมูลโทเค็นในรูปแบบ JSON จากเซิร์ฟเวอร์การตรวจสอบสิทธิ์ของนักพัฒนาซอฟต์แวร์ รวมถึงบันทึกโทเค็น เพื่อนำมาใช้ซ้ำได้ด้วย ระบบจะดึงข้อมูลโทเค็นอีกครั้งถ้าโทเค็นเดิมอยู่ภายในช่วง 10 นาทีก่อนหมดอายุ

การใช้งานอาจดำเนินการต่างออกไป เช่น การใช้ชุดข้อความในพื้นหลังเพื่อรีเฟรชโทเค็น

ข้อยกเว้นใน AuthTokenFactory จะถือว่าเป็นชั่วคราว เว้นแต่จะเกิดขึ้นซ้ำ หลังจากพยายามหลายครั้ง SDK ไดรเวอร์จะสันนิษฐานว่าข้อผิดพลาดนี้เป็นแบบถาวรและจะหยุดพยายามส่งการอัปเดต

การรายงานสถานะและข้อผิดพลาดกับ StatusListener

เนื่องจาก SDK ไดรเวอร์ดำเนินการต่างๆ ในเบื้องหลัง ให้ใช้ StatusListener เพื่อเรียกใช้การแจ้งเตือนเมื่อเกิดเหตุการณ์บางอย่าง เช่น ข้อผิดพลาด คำเตือน หรือข้อความแก้ไขข้อบกพร่อง ข้อผิดพลาดอาจเกิดขึ้นชั่วคราว (เช่น BACKEND_CONNECTIVITY_ERROR) หรืออาจทำให้การอัปเดตตำแหน่งหยุดลงอย่างถาวร (เช่น VEHICLE_NOT_FOUND ซึ่งบ่งชี้ถึงข้อผิดพลาดในการกำหนดค่า)

คุณระบุการติดตั้งใช้งาน StatusListener (ไม่บังคับ) ดังตัวอย่างต่อไปนี้

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.
  }
}

หมายเหตุเกี่ยวกับ SSL/TLS

การใช้ Driver SDK ภายในจะใช้ SSL/TLS เพื่อสื่อสารกับเซิร์ฟเวอร์ Fleet Engine อย่างปลอดภัย เวอร์ชันเก่าของ Android (API เวอร์ชัน 19 หรือต่ำกว่า) อาจต้องใช้แพตช์ SecurityProvider เพื่อสื่อสารกับเซิร์ฟเวอร์ได้ โปรดดูบทความนี้สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการทำงานกับ SSL ใน Android บทความนี้ยังมีตัวอย่างโค้ดสำหรับการแพตช์ผู้ให้บริการด้านความปลอดภัยด้วย

การเปิดใช้การอัปเดตตำแหน่ง

เมื่อคุณมีอินสแตนซ์ *VehicleReporter การเปิดใช้การอัปเดตตำแหน่งจะมีผลดังนี้

Java

RidesharingVehicleReporter reporter = ...;

reporter.enableLocationTracking();

Kotlin

val reporter = ...

reporter.enableLocationTracking()

ระบบจะส่งการอัปเดตตำแหน่งตามช่วงเวลาปกติเมื่อสถานะของรถคือ ONLINE โปรดทราบว่าการเรียก reporter.enableLocationTracking() จะไม่ตั้งค่าสถานะรถเป็น ONLINE โดยอัตโนมัติ คุณต้องตั้งค่าสถานะรถยนต์อย่างชัดแจ้ง

โดยค่าเริ่มต้น ระยะเวลาการรายงานคือ 10 วินาที คุณเปลี่ยนแปลงช่วงเวลาการรายงานได้ด้วย reporter.setLocationReportingInterval(long, TimeUnit) ช่วงเวลาการอัปเดตขั้นต่ำที่รองรับคือ 5 วินาที การอัปเดตบ่อยขึ้นอาจทำให้คำขอและข้อผิดพลาดช้าลง

การปิดใช้งานการอัปเดตตำแหน่ง

เมื่อเปลี่ยนกะของผู้ขับเสร็จสิ้น คุณสามารถหยุดการอัปเดตตำแหน่งได้ และทำเครื่องหมายยานพาหนะแบบออฟไลน์ได้โดยโทรหา DeliveryVehicleReporter.disableLocationTracking หรือ RidesharingVehicleReporter.disableLocationTracking

การโทรครั้งนี้จะทำให้มีกำหนดเวลาอัปเดตครั้งสุดท้าย 1 ครั้งเพื่อให้นำส่งได้ทันที ซึ่งหมายความว่ารถยนต์ออฟไลน์อยู่ การอัปเดตนี้จะไม่มีตำแหน่งของผู้ใช้

การตั้งค่าสถานะของรถ

เมื่อเปิดใช้การอัปเดตตำแหน่ง การตั้งค่าสถานะของรถเป็น ONLINE จะทำให้ยานพาหนะพร้อมใช้งานสำหรับการค้นหา SearchVehicles ในทำนองเดียวกัน การทำเครื่องหมายยานพาหนะเป็น OFFLINE จะทำเครื่องหมายยานพาหนะว่าไม่พร้อมใช้งาน

คุณมีตัวเลือกในการตั้งค่าสถานะรถยนต์ที่ฝั่งเซิร์ฟเวอร์ (ดูอัปเดตยานพาหนะ) หรือใน Driver SDK โดยตรง

Java

RidesharingVehicleReporter reporter = ...;

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

Kotlin

val reporter = ...

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

เมื่อเปิดใช้งานการอัปเดตตำแหน่ง การเรียกไปยัง setVehicleState จะเผยแพร่ในการอัปเดตตำแหน่งครั้งถัดไป

การทำเครื่องหมายยานพาหนะเป็น ONLINE เมื่อไม่ได้เปิดใช้การติดตามตำแหน่งจะส่งผลให้เกิด IllegalStateException รถยนต์อาจทำเครื่องหมายเป็น OFFLINE ได้แม้จะยังไม่เปิดใช้หรือปิดใช้การติดตามตำแหน่งอย่างชัดเจน ซึ่งจะส่งผลให้มีการอัปเดตทันที การเรียกไปยัง RidesharingVehicleReporter.disableLocationTracking() จะตั้งค่าสถานะรถเป็น OFFLINE

โปรดทราบว่า setVehicleState จะส่งคืนทันทีและระบบจะอัปเดตในชุดข้อความการอัปเดตตำแหน่ง เช่นเดียวกับการจัดการข้อผิดพลาดเกี่ยวกับการอัปเดตตำแหน่ง ข้อผิดพลาดในการอัปเดตสถานะของรถจะถูกเผยแพร่โดยใช้ StatusListener ที่ไม่บังคับซึ่งตั้งค่าใน DriverContext