Bắt đầu với SDK người tiêu dùng dành cho Android

Bạn có thể sử dụng SDK người tiêu dùng để tạo và chạy một ứng dụng cơ bản dành cho người dùng thông thường, tích hợp với các dịch vụ phụ trợ Giải pháp gọi xe và giao hàng theo yêu cầu. Bạn có thể tạo ứng dụng Tiến trình đặt hàng và Chuyến đi có thể hiển thị một chuyến đi đang diễn ra, phản hồi thông tin cập nhật về chuyến đi và xử lý các lỗi về chuyến đi.

Vì SDK người tiêu dùng có cấu trúc mô-đun, nên bạn có thể sử dụng các phần của API mà bạn muốn dùng cho ứng dụng cụ thể của mình và tích hợp những phần đó với API riêng, các dịch vụ phụ trợ do Fleet Engine cung cấp và API bổ sung của Nền tảng Google Maps.

Yêu cầu tối thiểu về hệ thống

Thiết bị di động phải chạy Android 6.0 (API cấp 23) trở lên.

Cấu hình bản dựng và phần phụ thuộc

Bạn có thể sử dụng SDK người dùng phiên bản 1.99.0 trở lên trong kho lưu trữ Google Maven. Kênh kho lưu trữ riêng tư được sử dụng trước đây không còn được dùng nữa.

Gradle

Thêm đoạn mã sau vào tệp build.gradle của bạn:

repositories {
    ...
    google()
}

Maven

Thêm đoạn mã sau vào tệp pom.xml của bạn:

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

Cấu hình dự án

Để sử dụng SDK người tiêu dùng cho Android, ứng dụng của bạn phải nhắm đến minSdkVersion 23 trở lên.

Để chạy một ứng dụng tạo bằng SDK người tiêu dùng, thiết bị Android phải cài đặt Dịch vụ Google Play.

Thiết lập dự án phát triển

Cách thiết lập dự án phát triển và nhận khoá API cho dự án trên Google Cloud Console:

  1. Tạo một dự án mới trên Google Cloud Console hoặc chọn một dự án hiện có để sử dụng với SDK người tiêu dùng. Hãy chờ vài phút cho đến khi dự án mới xuất hiện trên Google Cloud Console.

  2. Để chạy ứng dụng minh hoạ, dự án của bạn phải có quyền truy cập vào SDK bản đồ dành cho Android. Trong Google Cloud Console, hãy chọn API và Dịch vụ > Thư viện, sau đó tìm và bật SDK Maps cho Android.

  3. Lấy khoá API cho dự án bằng cách chọn API và Dịch vụ > Thông tin xác thực > Tạo thông tin xác thực > Khoá API. Để biết thêm thông tin về cách tải khoá API, hãy xem phần Tải khoá API.

Thêm SDK người tiêu dùng vào ứng dụng

SDK Người tiêu dùng có sẵn thông qua một kho lưu trữ Maven riêng tư. Kho lưu trữ bao gồm các tệp Mô hình đối tượng dự án (.pom) của SDK và Javadocs. Cách thêm SDK người tiêu dùng vào ứng dụng:

  1. Thiết lập môi trường để truy cập vào kho lưu trữ Maven của máy chủ như mô tả trong phần trước.

    Nếu bạn đã khai báo cấu hình quản lý phần phụ thuộc ở một nơi tập trung trong settings.gradle, hãy tắt cấu hình đó như sau.

    • Xoá khối mã dưới đây trong settings.gradle:

      import org.gradle.api.initialization.resolve.RepositoriesMode
      dependencyResolutionManagement {
          repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
          repositories {
              google()
              mavenCentral()
          }
      }
      
  2. Thêm phần phụ thuộc sau vào cấu hình Gradle hoặc Maven, thay thế phần giữ chỗ VERSION_NUMBER cho phiên bản SDK người tiêu dùng mong muốn.

    Gradle

    Thêm phần sau vào build.gradle:

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

    Maven

    Thêm phần sau vào pom.xml:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation</groupId>
        <artifactId>transportation-consumer</artifactId>
        <version>VERSION_NUMBER</version>
      </dependency>
    </dependencies>
    
  3. SDK người tiêu dùng phụ thuộc vào SDK Maps. Phần phụ thuộc này được định cấu hình theo cách mà nếu phiên bản SDK Maps không được xác định rõ ràng trong tệp cấu hình bản dựng như sau, thì khi phiên bản mới của SDK Maps được phát hành, SDK người tiêu dùng sẽ tiếp tục sử dụng phiên bản SDK Maps tối thiểu được hỗ trợ mà SDK đó yêu cầu.

    Gradle

    Thêm phần sau vào build.gradle:

    dependencies {
      ...
      implementation 'com.google.android.gms:play-services-maps:18.1.0'
    }
    

    Maven

    Thêm phần sau vào pom.xml:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.gms</groupId>
        <artifactId>play-services-maps</artifactId>
        <version>18.1.0</version>
      </dependency>
    </dependencies>
    

Thêm khoá API vào ứng dụng của bạn

Sau khi thêm SDK người tiêu dùng vào ứng dụng, hãy thêm khoá API vào ứng dụng. Bạn phải sử dụng khoá API của dự án nhận được khi thiết lập dự án phát triển.

Phần này mô tả cách lưu trữ khoá API để ứng dụng của bạn có thể tham chiếu khoá API đó một cách an toàn hơn. Bạn không nên kiểm tra khoá API trong hệ thống quản lý phiên bản. Bạn nên lưu trữ tệp này trong tệp local.properties, nằm trong thư mục gốc của dự án. Để biết thêm thông tin về tệp local.properties, hãy xem các tệp thuộc tính Gradle.

Để đơn giản hoá tác vụ này, bạn có thể sử dụng Trình bổ trợ Secrets Gradle cho Android.

Cách cài đặt trình bổ trợ và lưu trữ khoá API:

  1. Mở tệp build.gradle ở cấp cơ sở và thêm mã sau vào phần tử dependencies trong 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. Mở tệp build.gradle ở cấp ứng dụng và thêm mã sau vào phần tử plugins.

    Groovy

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

    Kotlin

    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
    
  3. Nếu bạn sử dụng Android Studio, hãy đồng bộ hoá dự án với Gradle.

  4. Mở local.properties trong thư mục cấp dự án rồi thêm đoạn mã sau. Thay thế YOUR_API_KEY bằng khoá API.

    MAPS_API_KEY=YOUR_API_KEY
    
  5. Trong tệp AndroidManifest.xml, hãy chuyển đến com.google.android.geo.API_KEY rồi cập nhật thuộc tính android:value như sau:

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

Ví dụ sau đây trình bày một tệp kê khai hoàn chỉnh cho một ứng dụng mẫu:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.consumerapidemo">
    <uses-permission android:name="android.permission.ACCESS_FINE_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>

Đưa các thuộc tính bắt buộc vào ứng dụng của bạn

Nếu sử dụng SDK người tiêu dùng trong ứng dụng của mình, thì bạn phải đưa văn bản phân bổ và giấy phép nguồn mở vào mục thông báo pháp lý của ứng dụng. Bạn nên thêm các thông tin phân bổ dưới dạng một mục trong trình đơn độc lập hoặc trong một mục trong trình đơn Giới thiệu.

Bạn có thể tìm thấy thông tin về giấy phép tại tệp "third_party_ tảng.txt" trong tệp AAR đã huỷ lưu trữ.

Hãy tham khảo https://developers.google.com/android/guides/opensource để biết cách thêm thông báo nguồn mở.

Xác thực SDK người tiêu dùng

SDK người tiêu dùng cung cấp tính năng xác thực bằng Mã thông báo web JSON. Mã thông báo web JSON (JWT) là mã truy cập cơ sở JSON cung cấp một hoặc nhiều thông báo xác nhận quyền sở hữu đối với một dịch vụ. Ví dụ: máy chủ có thể tạo một mã thông báo có thông báo xác nhận quyền sở hữu "đã đăng nhập với tư cách quản trị viên" và cung cấp mã đó cho ứng dụng khách. Sau đó, ứng dụng có thể sử dụng mã thông báo đó để chứng minh rằng mình đăng nhập với tư cách quản trị viên.

SDK người tiêu dùng sử dụng Mã thông báo web JSON do ứng dụng cung cấp để giao tiếp với Fleet Engine. Tham khảo phần Xác thực và uỷ quyền cho Fleet Engine để biết thêm thông tin.

Mã thông báo uỷ quyền phải bao gồm thông báo xác nhận quyền sở hữu tripid:TRIP_ID trong tiêu đề authorization của mã thông báo, trong đó TRIP_ID là mã chuyến đi. Việc này cho phép SDK người tiêu dùng truy cập vào thông tin chi tiết về chuyến đi, bao gồm cả vị trí của xe, tuyến đường và giờ đến dự kiến.

Lệnh gọi lại Mã thông báo web JSON

SDK người tiêu dùng đăng ký lệnh gọi lại mã thông báo uỷ quyền với ứng dụng trong quá trình khởi chạy. SDK gọi ứng dụng để lấy mã thông báo cho tất cả các yêu cầu mạng yêu cầu uỷ quyền.

Bạn nên sử dụng mã thông báo uỷ quyền bộ nhớ đệm triển khai lệnh gọi lại và chỉ làm mới các mã đó khi đã trôi qua thời gian expiry. Mã thông báo phải được phát hành có thời hạn là một giờ.

Lệnh gọi lại mã thông báo uỷ quyền chỉ định mã thông báo dịch vụ cần thiết cho dịch vụ TripService. Mã này cũng cung cấp tripId bắt buộc cho ngữ cảnh.

Ví dụ về mã sau đây minh hoạ cách triển khai lệnh gọi lại mã thông báo uỷ quyền.

Java

class JsonAuthTokenFactory implements AuthTokenFactory {

  private static final String TOKEN_URL =
      "https://yourauthserver.example/token";

  private static class CachedToken {
    String tokenValue;
    long expiryTimeMs;
    String tripId;
  }

  private CachedToken token;

  /*
  * This method is called on a background thread. Blocking is OK. However, be
  * aware that no information can be obtained from Fleet Engine until this
  * method returns.
  */
  @Override
  public String getToken(AuthTokenContext context) {
    // If there is no existing token or token has expired, go get a new one.
    String tripId = context.getTripId();
    if (tripId == null) {
      throw new RuntimeException("Trip ID is missing from AuthTokenContext");
    }
    if (token == null || System.currentTimeMillis() > token.expiryTimeMs ||
        !tripId.equals(token.tripId)) {
      token = fetchNewToken(tripId);
    }
    return token.tokenValue;
  }

  private static CachedToken fetchNewToken(String tripId) {
    String url = TOKEN_URL + "/" + tripId;
    CachedToken token = new CachedToken();

    try (Reader r = new InputStreamReader(new URL(url).openStream())) {
      com.google.gson.JsonObject obj
          = com.google.gson.JsonParser.parseReader(r).getAsJsonObject();

      token.tokenValue = obj.get("ServiceToken").getAsString();
      token.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 5 minutes from that time.
      */
      token.expiryTimeMs -= 5 * 60 * 1000;
    } catch (IOException e) {
      /*
      * It's OK to throw exceptions here. The error listeners will receive the
      * error thrown here.
      */
      throw new RuntimeException("Could not get auth token", e);
    }
    token.tripId = tripId;

    return token;
  }
}

Kotlin

class JsonAuthTokenFactory : AuthTokenFactory() {

  private var token: CachedToken? = null

  /*
  * This method is called on a background thread. Blocking is OK. However, be
  * aware that no information can be obtained from Fleet Engine until this
  * method returns.
  */
  override fun getToken(context: AuthTokenContext): String {
    // If there is no existing token or token has expired, go get a new one.
    val tripId = 
      context.getTripId() ?: 
        throw RuntimeException("Trip ID is missing from AuthTokenContext")

    if (token == null || System.currentTimeMillis() > token.expiryTimeMs ||
        tripId != token.tripId) {
      token = fetchNewToken(tripId)
    }

    return token.tokenValue
  }

  class CachedToken(
    var tokenValue: String? = "", 
    var expiryTimeMs: Long = 0,
    var tripId: String? = "",
  )

  private companion object {
    const val TOKEN_URL = "https://yourauthserver.example/token"

    fun fetchNewToken(tripId: String) {
      val url = "$TOKEN_URL/$tripId"
      val token = CachedToken()

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

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

          token.tokenValue = obj.get("ServiceToken").getAsString()
          token.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 5 minutes from that time.
          */
          token.expiryTimeMs -= 5 * 60 * 1000
        }
      } catch (e: IOException) {
        /*
        * It's OK to throw exceptions here. The error listeners will receive the
        * error thrown here.
        */
        throw RuntimeException("Could not get auth token", e)
      }

      token.tripId = tripId

      return token
    }
  }
}

Khởi chạy API

Trước khi làm theo các quy trình này, giả định rằng bạn đã bật các dịch vụ thích hợp và SDK dành cho người tiêu dùng.

Tải thực thể ConsumerApi

Để sử dụng SDK người tiêu dùng, ứng dụng của bạn cần khởi chạy ConsumerApi một cách không đồng bộ. API này là một singleton. Phương thức khởi chạy sẽ lấy AuthTokenFactory. Nhà máy sẽ tạo mã thông báo JWT mới cho người dùng khi cần thiết.

providerIdMã dự án của dự án trên Google Cloud. Vui lòng xem Hướng dẫn sử dụng Fleet Engine để biết thêm thông tin về cách tạo dự án.

Ứng dụng của bạn nên triển khai AuthTokenFactory như mô tả trong phần Xác thực SDK người tiêu dùng.

Java

Task<ConsumerApi> consumerApiTask = ConsumerApi.initialize(
    this, "myProviderId", authTokenFactory);

consumerApiTask.addOnSuccessListener(
  consumerApi -> this.consumerApi = consumerApi);

Kotlin

val consumerApiTask =
  ConsumerApi.initialize(this, "myProviderId", authTokenFactory)

consumerApiTask?.addOnSuccessListener { consumerApi: ConsumerApi ->
  this@YourActivity.consumerApi = consumerApi
}

SDK Maps và trình kết xuất bản đồ

SDK người tiêu dùng phiên bản 2.x.x hỗ trợ SDK Maps dành cho Android phiên bản 18.1.0 trở lên. Bảng dưới đây tóm tắt trình kết xuất mặc định theo phiên bản SDK Maps và khả năng hỗ trợ của cả hai trình kết xuất. Bạn nên sử dụng trình kết xuất mới nhất. Tuy nhiên, nếu cần sử dụng trình kết xuất cũ thì bạn có thể chỉ định rõ ràng bằng cách sử dụng MapsInitializer.initialize().

Phiên bản SDK Maps Hỗ trợ trình kết xuất đồ hoạ mới nhất Hỗ trợ trình kết xuất đồ hoạ cũ Trình kết xuất đồ hoạ mặc định
Phiên bản 18.1.0 trở xuống Kế thừa*
V18.2.0 Mới nhất

* Với việc phát hành Trình kết xuất Maps mới, trình kết xuất đồ hoạ mới nhất sẽ được đặt mặc định.

Thêm SDK Maps làm phần phụ thuộc

Gradle

Thêm phần sau vào build.gradle:

dependencies {
  //...
  implementation "com.google.android.gms:play-services-maps:VERSION_NUMBER"
}

Maven

Thêm phần sau vào pom.xml:

 <dependencies>
   ...
   <dependency>
     <groupId>com.google.android.gms</groupId>
     <artifactId>play-services-maps</artifactId>
     <version>18.1.0</version>
   </dependency>
 </dependencies>

Chạy SDK Maps trước khi khởi chạy SDK người tiêu dùng

Trong lớp Application hoặc Activity khởi động, hãy gọi MapsInitializer.initialize() và đợi kết quả yêu cầu trình kết xuất trước khi khởi chạy SDK tiêu dùng.

java

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  initViews();

  MapsInitializer.initialize(getApplicationContext(), Renderer.LATEST,
      new OnMapsSdkInitializedCallback() {
        @Override
        public void onMapsSdkInitialized(Renderer renderer) {
          switch (renderer) {
            case LATEST:
              Log.i("maps_renderer", "LATEST renderer");
              break;
            case LEGACY:
              Log.i("maps_renderer", "LEGACY renderer");
              break;
          }

          initializeConsumerSdk();
        }
      });
}

Kotlin

fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.main)
  initViews()

  MapsInitializer.initialize(
    getApplicationContext(), Renderer.LATEST,
    object : OnMapsSdkInitializedCallback() {
      fun onMapsSdkInitialized(renderer: Renderer?) {
        when (renderer) {
          LATEST -> Log.i("maps_renderer", "LATEST renderer")
          LEGACY -> Log.i("maps_renderer", "LEGACY renderer")
        }
        initializeConsumerSdk()
      }
    })
  }

Tạo giao diện người dùng

Bạn có thể dùng ConsumerMapFragment hoặc ConsumerMapView để tạo giao diện người dùng cho ứng dụng. ConsumerMapFragment cho phép bạn xác định bản đồ của mình bằng cách sử dụng Fragment trong khi ConsumerMapView cho phép bạn sử dụng View. Chức năng chia sẻ chuyến đi trong cả ConsumerMapViewConsumerMapFragment đều giống nhau. Vì vậy, bạn có thể chọn một tính năng dựa trên việc View hay Fragment phù hợp hơn với ứng dụng của bạn.

Thêm tính năng hỗ trợ cho API 19 (KitKat) và Vectơ vẽ được

Nếu thiết kế ứng dụng của bạn cần hỗ trợ các thiết bị API 19 (KitKat) và vectơ vẽ được, hãy thêm mã sau vào Hoạt động của bạn. Mã này mở rộng AppCompatActivity để sử dụng các vectơ vẽ được trong SDK người tiêu dùng.

Java

// ...
import android.support.v7.app.AppCompatActivity;

// ...

public class ConsumerTestActivity extends AppCompatActivity {
  // ...
}

Kotlin

// ...
import android.support.v7.app.AppCompatActivity

// ...

class ConsumerTestActivity : AppCompatActivity() {
  // ...
}

Thêm mảnh bản đồ hoặc chế độ xem

Bạn tạo bản đồ để hiển thị hoạt động chia sẻ hành trình trong một mảnh Android hoặc một khung hiển thị mà bạn xác định trong tệp XML bố cục ứng dụng (nằm trong /res/layout). Sau đó, mảnh (hoặc khung hiển thị) cung cấp quyền truy cập vào bản đồ chia sẻ hành trình mà ứng dụng của bạn có thể truy cập và sửa đổi. Bản đồ này cũng cung cấp tên người dùng cho ConsumerController, cho phép ứng dụng của bạn kiểm soát và tuỳ chỉnh trải nghiệm chia sẻ hành trình.

Bản đồ và bộ điều khiển chia sẻ hành trình

Bạn xác định bản đồ chia sẻ hành trình dưới dạng một mảnh (sử dụng ConsumerMapFragment) hoặc dưới dạng khung hiển thị (sử dụng ConsumerMapView), như trong mã ví dụ sau đây. Khi đó, phương thức onCreate() của bạn sẽ gọi getConsumerGoogleMapAsync(callback) để trả về ConsumerGoogleMap một cách không đồng bộ trong lệnh gọi lại. Sau đó, bạn có thể sử dụng ConsumerGoogleMap để hiển thị tính năng chia sẻ hành trình và có thể cập nhật tính năng này nếu cần.

ConsumerMapFragment

Bạn xác định mảnh trong tệp XML bố cục ứng dụng, như minh hoạ trong mã ví dụ sau.

<fragment
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:name="com.google.android.libraries.mapsplatform.transportation.consumer.view.ConsumerMapFragment"
    android:id="@+id/consumer_map_fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Lệnh gọi đến getConsumerGoogleMapAsync() phải đến từ phương thức onCreate().

Java

public class SampleAppActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {

    // Find the ConsumerMapFragment.
    ConsumerMapFragment consumerMapFragment =
        (ConsumerMapFragment) fragmentManager.findFragmentById(R.id.consumer_map_fragment);

    // Initiate the callback that returns the map.
    if (consumerMapFragment != null) {
      consumerMapFragment.getConsumerGoogleMapAsync(
          new ConsumerMapReadyCallback() {
            // The map returned in the callback is used to access the ConsumerController.
            @Override
            public void onConsumerMapReady(@NonNull ConsumerGoogleMap consumerGoogleMap) {
              ConsumerController consumerController = consumerGoogleMap.getConsumerController();
            }
          });
    }
  }

}

Kotlin

class SampleAppActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    // Find the ConsumerMapFragment.
    val consumerMapFragment =
      fragmentManager.findFragmentById(R.id.consumer_map_fragment) as ConsumerMapFragment

    consumerMapFragment.getConsumerGoogleMapAsync(
      object : ConsumerMapReadyCallback() {
        override fun onConsumerMapReady(consumerGoogleMap: ConsumerGoogleMap) {
          val consumerController = consumerGoogleMap.getConsumerController()!!
        }
      }
    )
  }
}
ConsumerMapView

Bạn có thể sử dụng thành phần hiển thị trong một mảnh hoặc trong một hoạt động, như được xác định trong tệp XML.

<com.google.android.libraries.mapsplatform.transportation.consumer.view.ConsumerMapView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/consumer_map_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Lệnh gọi đến getConsumerGoogleMapAsync() phải từ onCreate(). Ngoài tham số gọi lại, tham số này yêu cầu hoạt động hoặc mảnh chứa hoạt động và GoogleMapOptions (có thể rỗng) chứa các thuộc tính cấu hình cho MapView. Lớp cơ sở của hoạt động hoặc mảnh phải là FragmentActivity hoặc Fragment hỗ trợ (tương ứng), vì các lớp này cung cấp quyền truy cập vào vòng đời của nó.

Java

public class SampleAppActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    ConsumerMapView mapView = findViewById(R.id.consumer_map_view);

    if (mapView != null) {
      mapView.getConsumerGoogleMapAsync(
          new ConsumerMapReadyCallback() {
            // The map returned in the callback is used to access the ConsumerController.
            @Override
            public void onConsumerMapReady(@NonNull ConsumerGoogleMap consumerGoogleMap) {
              ConsumerController consumerController = consumerGoogleMap.getConsumerController();
            }
          }, this, null);
    }
  }

}

Kotlin

class SampleAppActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    val mapView = findViewById(R.id.consumer_map_view) as ConsumerMapView

    mapView.getConsumerGoogleMapAsync(
      object : ConsumerMapReadyCallback() {
        // The map returned in the callback is used to access the ConsumerController.
        override fun onConsumerMapReady(consumerGoogleMap: ConsumerGoogleMap) {
          val consumerController = consumerGoogleMap.getConsumerController()!!
        }
      },
      /* fragmentActivity= */ this,
      /* googleMapOptions= */ null,
    )
  }
}

MapView trong một mảnh giống như ví dụ trên cho MapView trong một hoạt động, ngoại trừ việc mảnh tăng cường bố cục có chứa MapView trong phương thức onCreateView() của mảnh.

Java

public class MapViewInFragment extends Fragment {

  @Override
  public View onCreateView(
      @NonNull LayoutInflater layoutInflater,
      @Nullable ViewGroup viewGroup,
      @Nullable Bundle bundle) {
    return layoutInflater.inflate(R.layout.consumer_map_view, viewGroup, false);
  }

}

Kotlin

class MapViewInFragment : Fragment() {
  override fun onCreateView(
    layoutInflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?,
  ): View {
    return layoutInflater.inflate(R.layout.consumer_map_view, viewGroup, false)
  }
}

Điều chỉnh mức thu phóng của máy ảnh để tập trung vào một hành trình

Nút Vị trí của tôi mặc định được tích hợp trong SDK Maps đặt máy ảnh vào giữa vị trí thiết bị.

Nếu có một phiên Chia sẻ hành trình đang hoạt động, bạn nên đặt camera vào giữa để tập trung vào hành trình thay vì vị trí của thiết bị.

SDK người dùng dành cho giải pháp tích hợp Android: AutoCamera

Để cho phép bạn tập trung vào hành trình thay vì vị trí thiết bị, SDK tiêu dùng sẽ cung cấp một tính năng AutoCamera được bật theo mặc định. Máy ảnh sẽ thu phóng để tập trung vào tuyến đường chia sẻ hành trình và điểm tham chiếu tiếp theo.

AutoCamera

Tuỳ chỉnh hoạt động của máy ảnh

Nếu cần kiểm soát nhiều hơn hành vi của máy ảnh, bạn có thể tắt hoặc bật máy ảnh tự động bằng ConsumerController.setAutoCameraEnabled().

ConsumerController.getCameraUpdate() sẽ trả về giới hạn máy ảnh được đề xuất tại thời điểm đó. Sau đó, bạn có thể cung cấp CameraUpdate này làm một đối số cho GoogleMap.moveCamera() hoặc GoogleMap.animateCamera().

Truy cập tính năng đi chung xe và bản đồ

Để hỗ trợ tính năng đi chung xe và tương tác trên bản đồ trong ứng dụng, bạn cần có quyền truy cập vào ConsumerGoogleMapConsumerController. ConsumerMapFragmentConsumerMapView đều trả về không đồng bộ ConsumerGoogleMap trong ConsumerMapReadyCallback. ConsumerGoogleMap trả về ConsumerController từ getConsumerController(). Bạn có thể truy cập ConsumerGoogleMapConsumerController như sau.

Java

private ConsumerGoogleMap consumerGoogleMap;
private ConsumerController consumerController;
private ConsumerMapView consumerMapView;

consumerMapView.getConsumerGoogleMapAsync(
    new ConsumerMapReadyCallback() {
      @Override
      public void onConsumerMapReady(@NonNull ConsumerGoogleMap consumerMap) {
        consumerGoogleMap = consumerMap;
        consumerController = consumerMap.getConsumerController();
      }
    },
    this, null);

Kotlin

var consumerGoogleMap: ConsumerGoogleMap
var consumerController: ConsumerController
val consumerMapView = findViewById(R.id.consumer_map_view) as ConsumerMapView

consumerMapView.getConsumerGoogleMapAsync(
  object : ConsumerMapReadyCallback() {
    override fun onConsumerMapReady(consumerMap: ConsumerGoogleMap) {
      consumerGoogleMap = consumerMap
      consumerController = consumerMap.getConsumerController()
    },
    /* fragmentActivity= */ this,
    /* googleMapOptions= */ null,
  }
)

ConsumerGoogleMap

ConsumerGoogleMap là một lớp trình bao bọc cho lớp GoogleMap. API này cung cấp cho ứng dụng của bạn khả năng tương tác với bản đồ bằng một API tương đương với GoogleMap. Việc sử dụng bản đồ dành cho người tiêu dùng cho phép ứng dụng và tính năng chia sẻ chuyến đi của bạn tương tác liền mạch với cùng một GoogleMap cơ bản. Ví dụ: GoogleMap chỉ cho phép đăng ký một lệnh gọi lại, nhưng ConsumerGoogleMap có hỗ trợ các lệnh gọi lại được đăng ký kép. Các lệnh gọi lại này cho phép ứng dụng và tính năng chia sẻ chuyến đi đăng ký các lệnh gọi lại được gọi tuần tự.

ConsumerController

ConsumerController cung cấp quyền truy cập vào chức năng chia sẻ chuyến đi như giám sát chuyến đi, kiểm soát trạng thái chuyến đi và đặt vị trí.

Thiết lập tính năng chia sẻ hành trình

Sau khi phần phụ trợ đã khớp người tiêu dùng với xe, hãy sử dụng JourneySharingSession để bắt đầu giao diện người dùng chia sẻ hành trình. Tính năng Chia sẻ hành trình cho biết vị trí và tuyến đường của xe trùng khớp. Sau khi triển khai SDK trong ứng dụng của mình, bạn có thể thêm chức năng để theo dõi các chuyến đi, theo dõi thông tin cập nhật và xử lý lỗi. Các quy trình sau đây giả định rằng các dịch vụ phụ trợ đã có sẵn và các dịch vụ của bạn để so khớp người tiêu dùng với xe đang hoạt động.

  1. Đăng ký trình nghe trên đối tượng TripModel để biết thông tin chi tiết về chuyến đi, chẳng hạn như ETA (Thời gian đến ước tính) và quãng đường mà xe cần di chuyển trước khi đến.

    Java

    // Create a TripModel instance for listening to updates to the trip specified by this trip name.
    String tripName = ...;
    TripModelManager tripModelManager = consumerApi.getTripModelManager();
    TripModel tripModel = tripModelManager.getTripModel(tripName);
    
    // Create a JourneySharingSession instance based on the TripModel.
    JourneySharingSession session = JourneySharingSession.createInstance(tripModel);
    
    // Add the JourneySharingSession instance on the map for updating the UI.
    consumerController.showSession(session);
    
    // Register for trip update events.
    tripModel.registerTripCallback(new TripModelCallback() {
      @Override
      public void onTripETAToNextWaypointUpdated(
          TripInfo tripInfo, @Nullable Long timestampMillis) {
        // ...
      }
    
      @Override
      public void onTripActiveRouteRemainingDistanceUpdated(
          TripInfo tripInfo, @Nullable Integer distanceMeters) {
        // ...
      }
    
      // ...
    });
    

    Kotlin

    // Create a TripModel instance for listening to updates to the trip specified by this trip name.
    val tripName = "tripName"
    val tripModelManager = consumerApi.getTripModelManager()
    val tripModel = tripModelManager.getTripModel(tripName)
    
    // Create a JourneySharingSession instance based on the TripModel.
    val session = JourneySharingSession.createInstance(tripModel)
    
    // Add the JourneySharingSession instance on the map for updating the UI.
    consumerController.showSession(session)
    
    // Register for trip update events.
    tripModel.registerTripCallback(
      object : TripModelCallback() {
        override fun onTripETAToNextWaypointUpdated(
          tripInfo: TripInfo,
          timestampMillis: Long?,
        ) {
          // ...
        }
    
        override fun onTripActiveRouteRemainingDistanceUpdated(
          tripInfo: TripInfo,
          distanceMeters: Int?,
        ) {
          // ...
        }
    
      // ...
    })
    
  2. Thiết lập chuyến đi của bạn bằng TripModelOptions.

    Java

    // Set refresh interval to 2 seconds.
    TripModelOptions tripOptions =
        TripModelOptions.builder().setRefreshIntervalMillis(2000).build();
    tripModel.setTripModelOptions(tripOptions);
    

    Kotlin

    // Set refresh interval to 2 seconds.
    val tripOptions = TripModelOptions.builder().setRefreshIntervalMillis(2000).build()
    tripModel.setTripModelOptions(tripOptions)
    

Ngừng chia sẻ hành trình

Đảm bảo rằng bạn ngừng chia sẻ hành trình khi không còn cần đến, chẳng hạn như khi hoạt động của máy chủ lưu trữ bị huỷ. Việc dừng tính năng chia sẻ hành trình cũng ngăn không cho các yêu cầu mạng gửi đến Fleet Engine, và tránh rò rỉ bộ nhớ.

Mã mẫu sau đây minh hoạ cách ngừng chia sẻ hành trình.

Java

public class MainActivity extends AppCompatActivity
    implements ConsumerViewModel.JourneySharingListener  {

  // Class implementation

  @Override
  protected void onDestroy() {
    super.onDestroy();

    if (journeySharingSession != null) {
      journeySharingSession.stop();
    }
  }
}

Kotlin

class SampleAppActivity : AppCompatActivity(), ConsumerViewModel.JourneySharingListener {

  // Class implementation

  override fun onDestroy() {
    super.onDestroy()

    journeySharingSession?.stop()
  }
}

Xử lý lỗi về chuyến đi

Phương thức onTripRefreshError cho thấy các lỗi xảy ra trong quá trình theo dõi chuyến đi. Việc liên kết cho các lỗi SDK của người tiêu dùng tuân theo các nguyên tắc HTTP/RPC tương tự đã thiết lập cho Google Cloud Platform. Sau đây là một số lỗi thường gặp trong quá trình theo dõi chuyến đi:

HTTP RPC Nội dung mô tả
400 INVALID_ARGUMENT Khách hàng đã chỉ định tên chuyến đi không hợp lệ. Tên chuyến đi phải tuân theo định dạng providers/{provider_id}/trips/{trip_id}. provider_id phải là mã nhận dạng của Dự án trên đám mây do nhà cung cấp dịch vụ sở hữu.
401 KHÔNG XÁC THỰC Yêu cầu chưa được xác thực do mã thông báo JWT không hợp lệ. Lỗi này sẽ xảy ra nếu mã thông báo JWT được ký mà không có mã chuyến đi hoặc mã thông báo JWT đã hết hạn.
403 PERMISSION_DENIED Ứng dụng không có đủ quyền. Lỗi này xảy ra nếu mã thông báo JWT không hợp lệ, ứng dụng không có quyền hoặc API chưa được bật cho dự án ứng dụng. Mã thông báo JWT có thể bị thiếu hoặc mã thông báo được ký bằng mã chuyến đi không khớp với mã chuyến đi đã yêu cầu.
429 RESOURCE_EXHAUSTED Hạn mức tài nguyên bằng 0 hoặc tốc độ lưu lượng truy cập vượt quá giới hạn.
503 KHÔNG CÓ Dịch vụ hiện không hoạt động. Thông thường, máy chủ không hoạt động.
504 DEADLINE_EXCEEDED Đã vượt quá thời hạn yêu cầu. Điều này sẽ chỉ xảy ra nếu phương thức gọi đặt thời hạn ngắn hơn thời hạn mặc định của phương thức (tức là thời hạn đã yêu cầu không đủ để máy chủ xử lý yêu cầu) và yêu cầu không kết thúc trong thời hạn đó.

Để biết thêm thông tin, hãy xem bài viết Xử lý lỗi SDK dành cho người tiêu dùng.