Pakiet SDK dla klientów indywidualnych na Androida

Możesz użyć pakietu Consumer SDK, aby utworzyć i uruchomić podstawową aplikację zintegrowaną z usługami backendu w usłudze Przejazdy na żądanie i usługi dostawy. Możesz utworzyć aplikację, która wyświetla aktywną podróż, odpowiada na jej aktualizacje i obsługuje błędy.

Pakiet Consumer SDK ma architekturę modułową, dzięki czemu możesz używać części interfejsu API, których chcesz używać w konkretnej aplikacji, i integrować je z własnymi interfejsami API, usługami backendu udostępnianymi przez Fleet Engine i dodatkowymi interfejsami API z Google Maps Platform.

Minimalne wymagania systemowe

Na urządzeniu mobilnym musi być zainstalowany Android 6.0 (poziom interfejsu API 23) lub nowszy.

Konfiguracja kompilacji i zależności

Pakiet SDK dla klientów indywidualnych w wersji 1.99.0 lub nowszej jest dostępny w repozytorium Google Maven. Używany wcześniej kanał repozytorium prywatnego został wycofany.

Gradle

Dodaj do pliku build.gradle te informacje:

repositories {
    ...
    google()
}

Maven

Dodaj do pliku pom.xml te informacje:

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

Konfiguracja projektu

Aby korzystać z pakietu Consumer SDK na Androida, Twoja aplikacja musi być kierowana na system minSdkVersion w wersji 23 lub nowszej.

Aby można było uruchomić aplikację utworzoną za pomocą pakietu Consumer SDK, na urządzeniu z Androidem muszą być zainstalowane Usługi Google Play.

Konfigurowanie projektu programistycznego

Aby skonfigurować projekt programistyczny i uzyskać dla niego klucz interfejsu API w konsoli Google Cloud:

  1. Utwórz nowy projekt Google Cloud Console lub wybierz istniejący projekt do użycia z pakietem Consumer SDK. Zaczekaj kilka minut, aż nowy projekt pojawi się w konsoli Google Cloud.

  2. Aby uruchomić aplikację demonstracyjną, Twój projekt musi mieć dostęp do pakietu SDK Map Google na Androida. W konsoli Google Cloud wybierz Interfejsy API i usługi > Biblioteka, a następnie wyszukaj i włącz pakiet SDK Map Google na Androida.

  3. Aby uzyskać klucz interfejsu API dla projektu, wybierz Interfejsy API i usługi > Dane logowania > Utwórz dane logowania > Klucz interfejsu API. Więcej informacji o uzyskiwaniu klucza interfejsu API znajdziesz w artykule Uzyskiwanie klucza interfejsu API.

Dodaj do aplikacji pakiet SDK dla konsumentów

Pakiet Consumer SDK jest dostępny w prywatnym repozytorium Maven. Repozytorium zawiera pliki modelu obiektu projektu (.pom) pakietu SDK i dokumenty Javadocs. Aby dodać do aplikacji pakiet SDK dla konsumentów:

  1. Skonfiguruj środowisko tak, aby uzyskać dostęp do repozytorium Maven hosta zgodnie z opisem w poprzedniej sekcji.

    Jeśli masz scentralizowaną konfigurację zarządzania zależnościami zadeklarowaną w zadaniu settings.gradle, wyłącz ją w ten sposób.

    • Usuń w pliku settings.gradle ten blok kodu:

      import org.gradle.api.initialization.resolve.RepositoriesMode
      dependencyResolutionManagement {
          repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
          repositories {
              google()
              mavenCentral()
          }
      }
      
  2. Dodaj podaną niżej zależność do konfiguracji Gradle lub Maven, zastępując zmienną VERSION_NUMBER odpowiednią wersją pakietu SDK klienta.

    Gradle

    Dodaj do elementu build.gradle:

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

    Maven

    Dodaj do elementu pom.xml:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation</groupId>
        <artifactId>transportation-consumer</artifactId>
        <version>VERSION_NUMBER</version>
      </dependency>
    </dependencies>
    
  3. Pakiet Consumer SDK korzysta z pakietu SDK Map Google. Ta zależność jest skonfigurowana w taki sposób, że jeśli wersja pakietu SDK Map Google nie jest wyraźnie określona w pliku konfiguracji kompilacji (jak poniżej), po opublikowaniu nowej wersji tego pakietu będzie on nadal korzystać z najmniejszej obsługiwanej wersji pakietu SDK Map Google.

    Gradle

    Dodaj do elementu build.gradle:

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

    Maven

    Dodaj do elementu pom.xml:

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

Dodawanie klucza interfejsu API do aplikacji

Po dodaniu pakietu SDK dla konsumentów do aplikacji dodaj do niej klucz interfejsu API. Musisz użyć klucza interfejsu API projektu, który udało Ci się uzyskać podczas konfigurowania projektu programistycznego.

Ta sekcja zawiera informacje o tym, jak przechowywać klucz interfejsu API, aby aplikacja mogła bezpieczniej się do niego odwoływać. Nie sprawdzaj klucza interfejsu API w systemie kontroli wersji. Powinna znajdować się w pliku local.properties, który znajduje się w katalogu głównym projektu. Więcej informacji o pliku local.properties znajdziesz w artykule o plikach właściwości Gradle.

Aby uprościć to zadanie, możesz użyć wtyczki Gradle obiektów tajnych na Androida.

Aby zainstalować wtyczkę i zapisać klucz interfejsu API:

  1. Otwórz plik build.gradle najwyższego poziomu i dodaj poniższy kod do elementu dependencies w sekcji buildscript.

    Zakręcony

    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. Otwórz plik build.gradle na poziomie aplikacji i dodaj poniższy kod do elementu plugins.

    Zakręcony

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

    Kotlin

    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
    
  3. Jeśli używasz Android Studio, zsynchronizuj swój projekt z Gradle.

  4. Otwórz local.properties w katalogu na poziomie projektu, a potem dodaj ten kod. Zastąp YOUR_API_KEY swoim kluczem interfejsu API.

    MAPS_API_KEY=YOUR_API_KEY
    
  5. W pliku AndroidManifest.xml przejdź do sekcji com.google.android.geo.API_KEY i zaktualizuj atrybut android:value w ten sposób:

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

Ten przykład zawiera pełny plik manifestu przykładowej aplikacji:

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

Uwzględnij w aplikacji wymagane informacje o źródłach

Jeśli korzystasz w aplikacji z pakietu SDK dla klientów indywidualnych, w sekcji informacji prawnych dotyczących aplikacji musisz umieścić tekst opisu i licencje open source. Informacje o źródłach powinny być dodawane jako niezależne pozycje menu lub jako część menu Informacje.

Informacje o licencjach znajdziesz w pliku „third_party_licenses.txt” w niezarchiwizowanym pliku AAR.

Informacje o tym, jak dodać powiadomienia o otwartym kodzie źródłowym, znajdziesz na stronie https://developers.google.com/android/guides/opensource.

Uwierzytelnianie SDK klienta

Pakiet SDK klienta zapewnia uwierzytelnianie przy użyciu tokenów sieciowych JSON. Token internetowy JSON (JWT) to token dostępu bazy danych JSON, który udostępnia co najmniej 1 deklarację w usłudze. Serwer może na przykład wygenerować token z deklaracją „zalogowany jako administrator” i przekazać go klientowi. Klient może następnie użyć tego tokena, aby udowodnić, że jest zalogowany jako administrator.

Pakiet SDK klienta używa tokena internetowego JSON udostępnionego przez aplikację do komunikacji z Fleet Engine. Więcej informacji znajdziesz w artykule na temat uwierzytelniania i autoryzacji Fleet Engine.

Token autoryzacji musi zawierać deklarację tripid:TRIP_ID w nagłówku authorization tokena, gdzie TRIP_ID to identyfikator podróży. Zapewnia to pakietowi SDK konsumenckiemu dostęp do informacji o podróży, w tym do pozycji pojazdu, trasy i szacowanego czasu dotarcia.

Wywołania zwrotne tokena internetowego JSON

Podczas inicjowania pakiet SDK klienta rejestruje wywołanie zwrotne tokena autoryzacji w aplikacji. SDK wywołuje aplikację, aby uzyskać token na potrzeby wszystkich żądań sieciowych, które wymagają autoryzacji.

Zdecydowanie zalecamy, aby tokeny autoryzacji pamięci podręcznej implementacji wywołań zwrotnych w pamięci podręcznej były odświeżane tylko po upływie czasu expiry. Tokeny powinny być wydawane z terminem ważności wynoszącym 1 godzinę.

Wywołanie zwrotne tokena autoryzacji określa, który token usługi jest potrzebny na potrzeby usługi TripService. Zapewnia też wymagane tripId w kontekście.

Poniższy przykładowy kod pokazuje, jak wdrożyć wywołanie zwrotne tokena autoryzacji.

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

Inicjowanie interfejsu API

Przed wykonaniem tych procedur zakładamy, że masz włączone odpowiednie usługi i pakiet SDK dla klientów indywidualnych.

Pobieranie instancji ConsumerApi

Aby można było korzystać z pakietu SDK klienta, aplikacja musi zainicjować ConsumerApi asynchronicznie. Interfejs API to single. Metoda inicjowania wymaga metody AuthTokenFactory. W razie potrzeby fabryka wygeneruje nowe tokeny JWT dla użytkownika.

providerId to identyfikator projektu Twojego projektu Google Cloud. Więcej informacji o tworzeniu projektu znajdziesz w przewodniku użytkownika Fleet Engine.

Aplikacja powinna implementować AuthTokenFactory zgodnie z opisem w sekcji Uwierzytelnianie pakietu SDK klienta.

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
}

Zainicjuj pakiet SDK Map Google, aby zażądać preferowanego mechanizmu renderowania

Pakiet SDK dla klientów indywidualnych w wersji 2.0.0 obsługuje pakiet SDK Map Google na Androida w wersji 18.1.0 i nowszych. Obsługuje żądania z określaniem preferowanego mechanizmu renderowania Map Google. Szczegółowe informacje znajdziesz w sekcji Nowy mechanizm renderowania map(akceptacja).

Dodaj pakiet SDK Map Google jako zależność

Gradle

Dodaj do elementu build.gradle:

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

Maven

Dodaj do elementu pom.xml:

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

Zainicjuj pakiet SDK Map Google przed zainicjowaniem pakietu Consumer SDK

W klasie Application lub startowej Activity wywołaj MapsInitializer.initialize() i poczekaj na wynik żądania mechanizmu renderowania, zanim zainicjujesz pakiet SDK klienta.

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()
      }
    })
  }

Tworzenie interfejsu

Aby utworzyć interfejs aplikacji, możesz użyć ConsumerMapFragment lub ConsumerMapView. ConsumerMapFragment pozwala zdefiniować mapę za pomocą Fragment, a ConsumerMapViewView. Funkcje wspólnego przejazdu są takie same w usługach ConsumerMapView i ConsumerMapFragment, więc możesz wybrać jedną z nich w zależności od tego, która z tych funkcji jest lepsza dla Twojej aplikacji: View czy Fragment.

Dodano obsługę interfejsu API 19 (KitKat) i elementów rysowalnych wektorowych

Jeśli projekt Twojej aplikacji wymaga obsługi urządzeń z interfejsem API 19 (KitKat) i elementów rysowanych w formacie wektorowym, dodaj do aktywności ten kod. Ten kod rozszerza uprawnienia AppCompatActivity o elementy rysowane w formacie wektorowym w pakiecie SDK klienta.

Java

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

// ...

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

Kotlin

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

// ...

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

Dodawanie fragmentu lub widoku mapy

Mapę do wyświetlania udostępniania przejazdów możesz utworzyć we fragmencie Androida lub widoku, który zdefiniujesz w pliku XML układu aplikacji (w pliku /res/layout). Fragment (lub widok) umożliwia dostęp do mapy udostępniania przejazdu, którą aplikacja może przeglądać i modyfikować. Mapa zawiera też uchwyt ConsumerController, dzięki któremu aplikacja może kontrolować i dostosowywać udostępnianie trasy.

Udostępnianie mapy i kontroler przejazdu

Mapę udostępniania przejazdu definiujesz jako fragment (za pomocą ConsumerMapFragment) lub jako widok (za pomocą ConsumerMapView), jak w tym przykładzie kodu. Twoja metoda onCreate() powinna następnie wywołać metodę getConsumerGoogleMapAsync(callback), która asynchronicznie zwraca w wywołaniu zwrotnym wartość ConsumerGoogleMap. Następnie w sekcji ConsumerGoogleMap wyświetla się udostępnianie trasy. W razie potrzeby aplikacja może je aktualizować.

ConsumerMapFragment

Definiujesz fragment w pliku XML układu aplikacji, tak jak w poniższym przykładzie kodu.

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

Wywołanie getConsumerGoogleMapAsync() powinno pochodzić z metody 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

Widok może być używany we fragmencie lub w działaniu, zgodnie z definicją w pliku 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" />

Odwołanie do getConsumerGoogleMapAsync() powinno pochodzić z adresu onCreate(). Oprócz parametru wywołania zwrotnego wymaga on działania lub fragmentu zawierającego aktywność oraz elementu GoogleMapOptions (który może mieć wartość null) zawierającego atrybuty konfiguracji MapView. Klasa bazowa aktywności lub fragmentu musi być klasą bazową typu FragmentActivity lub pomocą Fragment, ponieważ zapewnia dostęp do jej cyklu życia.

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,
    )
  }
}

Element MapView we fragmencie jest taki sam jak w przykładzie powyżej w przypadku elementu MapView w aktywności. Jedyna różnica jest taka, że fragment rozszerza układ, który obejmuje właściwość MapView we fragmencie onCreateView().

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

Dostosowuję powiększenie aparatu, aby skupić się na podróży

Domyślny przycisk Moja lokalizacja, wbudowany w pakiet SDK Map Google, wyśrodkowuje kamerę na lokalizacji urządzenia.

Jeśli masz aktywną sesję udostępniania trasy, możesz wyśrodkować aparat, aby skupić się na podróży, a nie na lokalizacji urządzenia.

Wbudowane rozwiązanie SDK dla klientów indywidualnych na Androida: AutoCamera

Aby umożliwić Ci skupienie się na ścieżce, a nie na lokalizacji urządzenia, pakiet SDK klienta udostępnia funkcję automatycznego aparatu, która jest domyślnie włączona. Kamera robi powiększenie, aby skupić się na udostępnianiu trasy i następnym punkcie w drodze.

AutoCamera

Dostosowywanie działania kamery

Jeśli chcesz mieć większą kontrolę nad działaniem kamery, możesz ją wyłączyć lub włączyć za pomocą funkcji ConsumerController.setAutoCameraEnabled().

ConsumerController.getCameraUpdate() zwraca zalecane wartości graniczne kamery w danym momencie. Następnie możesz podać ten argument CameraUpdate jako argument do GoogleMap.moveCamera() lub GoogleMap.animateCamera().

Korzystaj z opcji wspólnych przejazdów i map

Aby móc obsługiwać wspólne przejazdy i interakcje z mapami w aplikacji, musisz mieć dostęp do usług ConsumerGoogleMap i ConsumerController. Działanie ConsumerMapFragment i ConsumerMapView asynchronicznie zwracają parametr ConsumerGoogleMap w parametrze ConsumerMapReadyCallback. ConsumerGoogleMap zwraca ConsumerController od sprzedawcy getConsumerController(). Dostęp do usług ConsumerGoogleMap i ConsumerController możesz uzyskać w ten sposób.

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 to klasa otoki klasy GoogleMap. Umożliwia aplikacji interakcję z mapą za pomocą interfejsu API odpowiednika interfejsu GoogleMap. Korzystanie z mapy dla klientów umożliwia bezproblemową interakcję aplikacji i przejazdów z tą samą mapą Google. Na przykład GoogleMap umożliwia tylko jedną rejestrację wywołania zwrotnego, a ConsumerGoogleMap obsługuje podwójne zarejestrowane wywołania zwrotne. Dzięki tym wywołaniam zwrotnym Twoja aplikacja i udostępnianie przejazdów mogą rejestrować wywołania zwrotne, które są wywoływane po kolei.

ConsumerController

ConsumerController umożliwia udostępnianie przejazdów, takich jak monitorowanie podróży, kontrolowanie stanu podróży i ustawianie lokalizacji.

Skonfiguruj udostępnianie trasy

Gdy backend dopasuje klienta do pojazdu, użyj JourneySharingSession, aby uruchomić interfejs udostępniania ścieżki. Udostępnianie trasy pokazuje dopasowaną lokalizację pojazdu i trasę. Po zaimplementowaniu pakietu SDK w aplikacji możesz dodać funkcje monitorowania podróży, nasłuchiwania aktualizacji i obsługi błędów. W poniższych procedurach przyjęto, że istnieją usługi backendu, a Twoje usługi dopasowywania klientów do pojazdów działają.

  1. Zarejestruj detektor w obiekcie TripModel, aby uzyskać szczegółowe informacje o podróży, takie jak szacowany czas przyjazdu i odległość, jaką musi pokonać pojazd przed przyjazdem.

    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. Skonfiguruj podróż w aplikacji 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)
    

Przestań udostępniać trasę

Zatrzymaj udostępnianie ścieżki, gdy nie jest już potrzebne, na przykład po zniszczeniu aktywności hosta. Zatrzymanie udostępniania ścieżki zatrzymuje też żądania sieciowe wysyłane do Fleet Engine i zapobiega wyciekom pamięci.

Ten przykładowy kod pokazuje, jak zatrzymać udostępnianie ścieżki.

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()
  }
}

Postępowanie w przypadku błędów dotyczących podróży

Metoda onTripRefreshError wyświetla błędy, które występują podczas monitorowania podróży. Mapowanie błędów w pakiecie Consumer SDK jest zgodne z wytycznymi HTTP/RPC co Google Cloud Platform. Typowe błędy pojawiające się podczas monitorowania podróży to:

HTTP RPC Opis
400 INVALID_ARGUMENT Klient podał nieprawidłową nazwę podróży. Nazwa podróży musi mieć format providers/{provider_id}/trips/{trip_id}. Parametr provider_id musi być identyfikatorem projektu Cloud należącego do dostawcy usług.
401 NIEUWIERZYTELNIONE Żądanie nie zostało uwierzytelnione z powodu nieprawidłowego tokena JWT. Ten błąd występuje, jeśli token JWT zostanie podpisany bez identyfikatora podróży lub token JWT wygasł.
403 PERMISSION_DENIED Klient nie ma wystarczających uprawnień. Ten błąd występuje, jeśli token JWT jest nieprawidłowy, klient nie ma uprawnień lub interfejs API nie jest włączony w projekcie klienta. Być może brakuje tokena JWT lub token jest podpisany identyfikatorem podróży, który nie jest zgodny z żądanym identyfikatorem podróży.
429 RESOURCE_EXHAUSTED Limit zasobów jest równy zero lub tempo ruchu przekracza limit.
503 UNAVAILABLE Usługa niedostępna Zazwyczaj serwer nie działa.
504 DEADLINE_EXCEEDED Przekroczono termin przesłania prośby. Dzieje się tak tylko wtedy, gdy wywołujący ustawi termin krótszy niż domyślny termin metody (np. żądany termin nie wystarczy, aby serwer mógł przetworzyć żądanie) i żądanie nie zostało ukończone w wyznaczonym terminie.

Więcej informacji znajdziesz w artykule Obsługa błędów pakietu SDK klienta.