Pakiet SDK dla klientów indywidualnych na Androida

Za pomocą pakietu Consumer SDK możesz utworzyć i uruchomić podstawową aplikację zintegrowaną z usługami backendu przejazdów i rozwiązań dostarczanych na żądanie. Możesz utworzyć aplikacje Podróż i Postępy zamówienia, które będą mogły wyświetlać aktywną podróż, odpowiadać na jej aktualizacje i naprawiać 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, oraz integrować je z własnymi interfejsami API, usługami backendu udostępnianymi przez Fleet Engine i dodatkowymi interfejsami API Google Maps Platform.

Minimalne wymagania systemowe

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

Konfiguracja Maven

Pakiet Consumer SDK w wersji 1.99.0 i nowszych jest dostępny w repozytorium Google Maven.

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 można było używać pakietu Consumer SDK na Androida, Twoja aplikacja musi być kierowana na minSdkVersion w wersji 23 lub nowszej.

Aby 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ć jego 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ą, projekt musi mieć dostęp do pakietu Maps SDK 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 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.

Dodawanie do aplikacji pakietu Consumer SDK

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

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

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

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

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

    Gradle

    Dodaj do konta build.gradle:

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

    Maven

    Dodaj do konta pom.xml:

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation</groupId>
        <artifactId>transportation-consumer</artifactId>
        <version>VERSION_NUMBER</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 uzyskanego podczas konfigurowania projektu programistycznego.

Z tej sekcji dowiesz się, jak przechowywać klucz interfejsu API, aby można było bezpieczniej się do niego odwoływać w aplikacji. Nie sprawdzaj klucza interfejsu API w systemie kontroli wersji. Powinien 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 Pliki właściwości Gradle.

Aby ułatwić sobie to zadanie, możesz użyć wtyczki do obsługi obiektów tajnych w Gradle na Androida.

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

  1. Otwórz plik build.gradle głównego poziomu i dodaj ten kod do elementu dependencies w obszarze 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 do elementu plugins podany niżej kod.

    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 projekt z Gradle.

  4. Otwórz local.properties w katalogu na poziomie projektu, a następnie 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 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 przedstawia 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 wymagane informacje o atrybucji w aplikacji

Jeśli korzystasz w aplikacji z pakietu SDK dla konsumentów, w sekcji informacji prawnych dotyczących aplikacji musisz umieścić tekst źródła oraz licencje open source. Informacje o autorach najlepiej dodać jako niezależne pozycje w menu lub pozycję Informacje.

Wymagany tekst źródła i licencje open source znajdziesz w pliku ZIP z Ridesharing Consumer SDK:

  • NOTICE.txt
  • LICENSES.txt

Uwierzytelnianie pakietu Consumer SDK

Pakiet SDK Consumer SDK zapewnia uwierzytelnianie za pomocą tokenów sieciowych JSON. Token internetowy JSON (JWT) to token dostępu w bazie 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. Może on następnie użyć tego tokena, aby udowodnić, że jest zalogowany jako administrator.

Pakiet Consumer SDK komunikuje się z Fleet Engine za pomocą tokena internetowego JSON udostępnionego przez aplikację. Więcej informacji znajdziesz w artykule Uwierzytelnianie i autoryzacja Fleet Engine.

Token autoryzacji zapewnia dostęp do tych usługFleet Engine:

  • TripService – daje pakietowi SDK konsumentów dostęp do szczegółów podróży, w tym do pozycji pojazdu, trasy i szacowanego czasu dotarcia. Tokeny autoryzacji dla usługi podróży muszą zawierać żądanie tripid:TRIP_ID w nagłówku authorization tokena, gdzie TRIP_ID to identyfikator podróży.
  • VehicleService – przekazuje pakietowi SDK dla konsumentów informacje o niewyraźnym lokalizacji pojazdu na potrzeby wyświetlania warstwy gęstości pojazdów i szacowania szacowanego czasu dotarcia na miejsce w punkcie odbioru. Pakiet SDK dla konsumentów używa tylko lokalizacji zamazanych, dlatego tokeny autoryzacji usługi pojazdu nie wymagają żądania vehicleid.

Wywołania zwrotne tokena internetowego JSON

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

Zdecydowanie zalecamy, aby tokeny autoryzacji bufora w implementacji wywołania zwrotnego były przechowywane w pamięci podręcznej i odświeżały je dopiero po upływie czasu expiry. Tokeny powinny być wydawane z datą ważności wynoszącą godzinę.

Wywołanie zwrotne tokena autoryzacji określa, który token usługi jest wymagany przez usługę TripService. Dostarcza też element tripId wymagany w tym 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 Consumer SDK.

Pobieranie instancji ConsumerApi

Aby można było używać pakietu Consumer SDK, aplikacja musi zainicjować ConsumerApi asynchronicznie. Interfejs API jest typu singleton. Metoda inicjowania wymaga metody AuthTokenFactory. W razie potrzeby fabryka generuje nowe tokeny JWT dla użytkownika.

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

Aplikacja powinna implementować AuthTokenFactory w sposób opisany w artykule Uwierzytelnianie 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ślonym preferowanym mechanizmem renderowania Map Google. Szczegółowe informacje znajdziesz w sekcji Nowy mechanizm renderowania map(włącz).

Dodaj pakiet SDK Map Google jako zależność

Gradle

Dodaj do konta build.gradle:

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

Maven

Dodaj do konta 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 uruchamiającej Activity wywołaj metodę 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 użytkownika

Interfejs aplikacji możesz utworzyć, korzystając z ConsumerMapFragment lub ConsumerMapView. ConsumerMapFragment pozwala zdefiniować mapę za pomocą Fragment, a ConsumerMapViewView. Funkcje wspólnych przejazdów są takie same w ConsumerMapView i ConsumerMapFragment, więc możesz wybrać tę, która lepiej odpowiada Twojej aplikacji View lub 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 wektorowych, dodaj do aktywności poniższy kod. Ten kod rozszerza zakres AppCompatActivity o elementy rysowane wektorowe w pakiecie Consumer SDK.

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 podróży tworzysz we fragmencie Androida lub widoku, który definiujesz w pliku XML układu aplikacji (znajdującym się w lokalizacji /res/layout). Fragment (lub widok) umożliwia dostęp do mapy udostępniania przejazdu, którą aplikacja może otwierać i modyfikować. Mapa zawiera też uchwyt ConsumerController, dzięki któremu aplikacja może kontrolować i dostosowywać udostępnianie trasy.

Udostępnianie mapy i kontrolera podczas podróży

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 ConsumerGoogleMap w wywołaniu zwrotnym. Następnie możesz używać ConsumerGoogleMap do wyświetlania informacji o udostępnianiu trasy. Aplikacja może go aktualizować.

ConsumerMapFragment

Fragment definiujesz w pliku XML układu aplikacji, jak pokazano 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()!!
        }
      }
    )
  }
}
Widok mapy klienta

Widok można wykorzystać we fragmencie lub aktywności, 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" />

Połączenie z numerem getConsumerGoogleMapAsync() powinno pochodzić od: onCreate(). Oprócz parametru wywołania zwrotnego wymaga on działania lub fragmentu zawierającego ciąg oraz parametru GoogleMapOptions (który może mieć wartość null) zawierającego atrybuty konfiguracji dla MapView. Klasa bazowa działania lub fragmentu musi mieć typ FragmentActivity lub pomocniczą 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 metodę 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)
  }
}

Dostosowanie powiększenia aparatu, aby skupić się na podróży

Domyślny przycisk Moja lokalizacja wbudowany w pakiet SDK Map Google ustawia kamerę zgodnie z lokalizacją urządzenia.

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

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

Aby umożliwić Ci skupienie się na podróży, a nie na lokalizacji urządzenia, pakiet SDK klienta zapewnia funkcję automatycznego aparatu, która jest domyślnie włączona. Kamera powiększa obraz, żeby skupić się na udostępnianiu trasy i następnym punkcie na trasie.

Aparat automatyczny

Dostosowywanie działania kamery

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

ConsumerController.getCameraUpdate() zwraca zalecane granice kamery w danym momencie. Następnie możesz podać ten argument CameraUpdate jako argument funkcji GoogleMap.moveCamera() lub GoogleMap.animateCamera().

Korzystaj ze wspólnych przejazdów i map

Aby obsługiwać wspólne przejazdy i interakcję z mapami w aplikacji, musisz mieć dostęp do ConsumerGoogleMap i ConsumerController. Funkcje ConsumerMapFragment i ConsumerMapView asynchronicznie zwracają wartość ConsumerGoogleMap w parametrze ConsumerMapReadyCallback. ConsumerGoogleMap zwraca ConsumerController od getConsumerController(). Dostęp do 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,
  }
)

MapaGoogle dla klientów

ConsumerGoogleMap to klasa opakowująca klasy GoogleMap. Umożliwia aplikacji interakcję z mapą za pomocą interfejsu API równoważnego z GoogleMap. Korzystanie z mapy klientów umożliwia bezproblemową interakcję aplikacji i przejazdów z tą samą bazową Mapą Google. Na przykład GoogleMap zezwala na tylko 1 rejestrację wywołania zwrotnego, ale ConsumerGoogleMap obsługuje podwójne zarejestrowane wywołania zwrotne. Dzięki tym wywołaniam zwrotnym aplikacja i udostępnianie przejazdów mogą rejestrować wywołania zwrotne, które są wywoływane sekwencyjnie.

Kontrola klienta

ConsumerController zapewnia dostęp do funkcji wspólnych przejazdów, takich jak monitorowanie podróży, kontrolowanie jej stanu i ustawianie lokalizacji.

Skonfiguruj udostępnianie przejazdów

Gdy backend dopasuje klienta do pojazdu, użyj JourneySharingSession, aby uruchomić interfejs udostępniania podróży. Udostępnianie trasy dojazdu pokazuje dopasowaną lokalizację pojazdu i trasę. Po zaimplementowaniu pakietu SDK w aplikacji możesz dodać funkcję monitorowania podróży, nasłuchiwania aktualizacji i obsługi błędów. W poniższych procedurach założono, że usługi backendu są dostępne i że usługi dopasowywania konsumenta do pojazdów działają.

  1. Zarejestruj detektor na obiekcie TripModel, aby otrzymywać 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óż za pomocą 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ę

Zatrzymuj udostępnianie przejazdów, 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.

Poniższy przykładowy kod pokazuje, jak zatrzymać udostępnianie przejazdów.

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

Obsługa błędów w 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 dotyczącymi protokołu HTTP/RPC obowiązującymi w przypadku Google Cloud Platform. Do częstych błędów zgłaszanych podczas monitorowania podróży należą:

HTTP RPC Opis
400 NIEPRAWIDŁOWY_ARG 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 w chmurze należącego do dostawcy usług.
401 NIE UWIERZYTELNIOWA Żądanie nie zostało uwierzytelnione z powodu nieprawidłowego tokena JWT. Ten błąd występuje, jeśli token JWT jest podpisany bez identyfikatora podróży lub token JWT wygasł.
403 UPRAWNIENIA_ODRZUCONO 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 jest on podpisany identyfikatorem podróży, który nie pasuje do żądanego identyfikatora podróży.
429 MATERIAŁY WYKRYWANE Limit zasobów wynosi zero lub tempo ruchu przekracza limit.
503 PRODUKT NIEDOSTĘPNY Usługa niedostępna Zazwyczaj serwer nie działa.
504 PRZEKROCZONO_TERMIN Przekroczono limit czasu żądania. Dzieje się tak tylko wtedy, gdy wywołujący ustawi termin krótszy niż domyślny termin w przypadku metody (tj. żądany termin nie wystarcza, aby serwer mógł przetworzyć żądanie), a żądanie nie zostało zrealizowane w wyznaczonym terminie.

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