Начало работы с Consumer SDK для Android

Вы можете использовать Consumer SDK для создания и запуска базового потребительского приложения, интегрированного с серверными службами решения On-demand Rides and Delivery Solution. Вы можете создать приложение «Прогресс поездки и заказа», которое может отображать активную поездку, реагировать на обновления поездки и обрабатывать ошибки поездки.

Поскольку Consumer SDK имеет модульную архитектуру, вы можете использовать части API, которые хотите использовать для своего конкретного приложения, и интегрировать их со своими собственными API, серверными службами, предоставляемыми Fleet Engine, а также дополнительными API платформы Google Maps. .

Минимальные системные требования

Мобильное устройство должно работать под управлением Android 6.0 (уровень API 23) или более поздней версии.

Конфигурация сборки и зависимостей

Потребительский SDK версии 1.99.0 и более поздних доступен в репозитории Google Maven. Ранее использовавшийся канал частного репозитория устарел.

Градл

Добавьте в файл build.gradle следующее:

repositories {
    ...
    google()
}

Мавен

Добавьте в файл pom.xml следующее:

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

Конфигурация проекта

Чтобы использовать Consumer SDK для Android, ваше приложение должно быть нацелено на minSdkVersion 23 или выше.

Чтобы запустить приложение, созданное с помощью Consumer SDK, на устройстве Android должны быть установлены службы Google Play .

Настройте свой проект разработки

Чтобы настроить проект разработки и получить ключ API для проекта в Google Cloud Console:

  1. Создайте новый проект Google Cloud Console или выберите существующий проект для использования с Consumer SDK. Подождите несколько минут, пока новый проект не появится в Google Cloud Console.

  2. Чтобы запустить демонстрационное приложение, у вашего проекта должен быть доступ к Maps SDK для Android. В Google Cloud Console выберите API и службы > Библиотека , затем найдите и включите Maps SDK для Android.

  3. Получите ключ API для проекта, выбрав API и службы > Учетные данные > Создать учетные данные > Ключ API . Дополнительную информацию о получении ключа API см. в разделе Получение ключа API .

Добавьте Consumer SDK в свое приложение

Consumer SDK доступен через частный репозиторий Maven. Репозиторий включает файлы объектной модели проекта SDK (.pom) и документацию Javadocs. Чтобы добавить Consumer SDK в ваше приложение:

  1. Настройте свою среду для доступа к хост-репозиторию Maven, как описано в предыдущем разделе.

    Если у вас есть конфигурация централизованного управления зависимостями, объявленная в settings.gradle , отключите ее следующим образом.

    • Удалите следующий блок кода в settings.gradle :

      import org.gradle.api.initialization.resolve.RepositoriesMode
      dependencyResolutionManagement {
          repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
          repositories {
              google()
              mavenCentral()
          }
      }
      
  2. Добавьте следующую зависимость в вашу конфигурацию Gradle или Maven, заменив заполнитель VERSION_NUMBER на нужную версию Consumer SDK.

    Градл

    Добавьте в свой build.gradle следующее:

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

    Мавен

    Добавьте следующее в ваш pom.xml :

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation</groupId>
        <artifactId>transportation-consumer</artifactId>
        <version>VERSION_NUMBER</version>
      </dependency>
    </dependencies>
    
  3. Consumer SDK зависит от Maps SDK. Эта зависимость настроена таким образом, что если версия Maps SDK не определена явно в файле конфигурации сборки, как показано ниже, при выпуске новой версии Maps SDK Consumer SDK продолжит использовать минимальную поддерживаемую версию Maps SDK. требуемое им.

    Градл

    Добавьте в свой build.gradle следующее:

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

    Мавен

    Добавьте следующее в ваш pom.xml :

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

Добавьте ключ API в свое приложение

Добавив Consumer SDK в свое приложение, добавьте в свое приложение ключ API. Вы должны использовать ключ API проекта, полученный при настройке проекта разработки .

В этом разделе описывается, как хранить ключ API, чтобы ваше приложение могло более безопасно ссылаться на него. Вам не следует проверять свой ключ API в системе контроля версий. Он должен храниться в файле local.properties , который находится в корневом каталоге вашего проекта. Дополнительные сведения о файле local.properties см. в разделе Файлы свойств Gradle .

Чтобы упростить эту задачу, вы можете использовать плагин Secrets Gradle для Android .

Чтобы установить плагин и сохранить ключ API:

  1. Откройте файл build.gradle корневого уровня и добавьте следующий код в элемент dependencies в buildscript .

    классный

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

    Котлин

    buildscript {
        dependencies {
            // ...
            classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.0")
        }
    }
    
  2. Откройте файл build.gradle уровня приложения и добавьте следующий код в элемент plugins .

    классный

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

    Котлин

    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
    
  3. Если вы используете Android Studio, синхронизируйте свой проект с Gradle .

  4. Откройте local.properties в каталоге уровня вашего проекта, а затем добавьте следующий код. Замените YOUR_API_KEY своим ключом API.

    MAPS_API_KEY=YOUR_API_KEY
    
  5. В файле AndroidManifest.xml перейдите по адресу com.google.android.geo.API_KEY и обновите атрибут android:value следующим образом:

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

В следующем примере показан полный манифест примера приложения:

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

Включите необходимую атрибуцию в свое приложение

Если вы используете Consumer SDK в своем приложении, вы должны включить текст указания авторства и лицензии с открытым исходным кодом в раздел юридических уведомлений вашего приложения. Лучше всего включить атрибуцию как независимый пункт меню или как часть пункта меню «О программе» .

Информацию о лицензиях можно найти в файле Third_party_licenses.txt в разархивированном файле AAR.

Инструкции по включению уведомлений об открытом исходном коде см. на странице https://developers.google.com/android/guides/opensource .

Аутентификация потребительского SDK

Consumer SDK обеспечивает аутентификацию с использованием веб-токенов JSON. Веб-токен JSON (JWT) — это токен доступа на основе JSON, который предоставляет одно или несколько утверждений к службе. Например, сервер может сгенерировать токен с утверждением «вошел в систему как администратор» и предоставить его клиенту. Затем клиент может использовать этот токен, чтобы доказать, что он вошел в систему как администратор.

Consumer SDK использует веб-токен JSON, предоставленный приложением, для связи с Fleet Engine. Дополнительную информацию см. в разделе «Аутентификация и авторизация Fleet Engine» .

Токен авторизации должен включать утверждение tripid:TRIP_ID в заголовок authorization токена, где TRIP_ID — это идентификатор поездки. Это дает Consumer SDK доступ к деталям поездки, включая положение транспортного средства, маршрут и расчетное время прибытия.

Обратные вызовы JSON Web Token

Consumer SDK регистрирует обратный вызов токена авторизации в приложении во время инициализации. SDK вызывает приложение, чтобы получить токен для всех сетевых запросов, требующих авторизации.

Мы настоятельно рекомендуем кэшировать токены авторизации реализации обратного вызова и обновлять их только по истечении срока expiry . Токены должны выпускаться со сроком действия один час.

Обратный вызов токена авторизации указывает, какой токен службы необходим для службы TripService . Он также предоставляет необходимый tripId для контекста.

В следующем примере кода показано, как реализовать обратный вызов токена авторизации.

Джава

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

Котлин

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

Инициализировать API

Прежде чем выполнять эти процедуры, предполагается, что вы включили соответствующие службы и Consumer SDK.

Получить экземпляр ConsumerApi

Чтобы использовать Consumer SDK, вашему приложению необходимо асинхронно инициализировать ConsumerApi . API является одноэлементным. Метод инициализации принимает AuthTokenFactory . При необходимости фабрика генерирует для пользователя новые токены JWT.

providerId — это идентификатор вашего проекта Google Cloud. Дополнительную информацию о создании проекта см. в руководстве пользователя Fleet Engine .

Ваше приложение должно реализовать AuthTokenFactory , как описано в разделе «Аутентификация Consumer SDK» .

Джава

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

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

Котлин

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

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

Инициализируйте Maps SDK для запроса предпочтительного средства визуализации

Consumer SDK версии 2.0.0 поддерживает Maps SDK для Android версии 18.1.0 и более поздних версий. Он поддерживает запросы с указанием предпочтительного средства визуализации Google Maps. Подробную информацию см. в разделе «Новый модуль визуализации карт» (подписка) .

Добавьте Maps SDK в качестве зависимости

Градл

Добавьте в свой build.gradle следующее:

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

Мавен

Добавьте следующее в ваш pom.xml :

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

Инициализируйте Maps SDK перед инициализацией Consumer SDK

В классе Application или запуска Activity вызовите MapsInitializer.initialize() и дождитесь результата запроса средства визуализации, прежде чем инициализировать Consumer SDK.

Джава

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

Котлин

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

Создайте пользовательский интерфейс

Вы можете использовать ConsumerMapFragment или ConsumerMapView для создания пользовательского интерфейса для вашего приложения. ConsumerMapFragment позволяет вам определить карту с помощью Fragment , а ConsumerMapView позволяет использовать View . Функциональность совместного использования поездок одинакова как в ConsumerMapView , так и в ConsumerMapFragment , поэтому вы можете выбрать один из них в зависимости от того, какой View или Fragment лучше подходит для вашего приложения.

Добавлена ​​поддержка API 19 (KitKat) и векторных изображений.

Если дизайн вашего приложения требует поддержки устройств API 19 (KitKat) и векторных изображений, добавьте следующий код в свою активность. Этот код расширяет AppCompatActivity для использования векторных рисунков в Consumer SDK.

Джава

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

// ...

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

Котлин

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

// ...

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

Добавьте фрагмент карты или вид

Вы создаете карту для отображения совместного путешествия либо во фрагменте Android, либо в представлении, которое вы определяете в XML-файле макета приложения (расположенном в /res/layout ). Затем фрагмент (или представление) предоставляет доступ к карте совместного путешествия, к которой ваше приложение может обращаться и изменять. Карта также предоставляет дескриптор ConsumerController , который позволяет вашему приложению контролировать и настраивать процесс обмена информацией о путешествии.

Карта совместного использования путешествий и контроллер

Вы определяете карту совместного использования пути либо как фрагмент (с помощью ConsumerMapFragment ), либо как представление (с помощью ConsumerMapView ), как показано в следующем примере кода. Затем ваш метод onCreate() должен вызвать getConsumerGoogleMapAsync(callback) , который асинхронно возвращает ConsumerGoogleMap в обратном вызове. Затем вы используете ConsumerGoogleMap для отображения информации о поездках, и ее можно обновлять по мере необходимости вашего приложения.

ПотребительКартаФрагмент

Вы определяете этот фрагмент в XML-файле макета приложения, как показано в следующем примере кода.

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

Вызов getConsumerGoogleMapAsync() должен исходить из метода onCreate() .

Джава

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

}

Котлин

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

Представление можно использовать либо во фрагменте, либо в действии, как определено в вашем 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" />

Вызов getConsumerGoogleMapAsync() должен происходить из onCreate() . В дополнение к параметру обратного вызова требуется содержащее действие или фрагмент и GoogleMapOptions (который может иметь значение null), содержащий атрибуты конфигурации для MapView . Базовый класс активности или фрагмента должен быть либо FragmentActivity , либо вспомогательным Fragment (соответственно), поскольку они обеспечивают доступ к его жизненному циклу.

Джава

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

}

Котлин

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 во фрагменте аналогичен приведенному выше примеру для MapView в действии, за исключением того, что фрагмент раздувает макет, который включает MapView в методе onCreateView() фрагмента.

Джава

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

}

Котлин

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

Настройка масштаба камеры, чтобы сосредоточиться на путешествии

Кнопка «Мое местоположение» по умолчанию, встроенная в Maps SDK, центрирует камеру по местоположению устройства.

Если существует активный сеанс обмена информацией о путешествии, вы можете отцентрировать камеру, чтобы сфокусироваться на путешествии, а не на местоположении устройства.

Потребительский SDK для встроенного решения Android: AutoCamera

Чтобы вы могли сосредоточиться на путешествии, а не на местоположении устройства, Consumer SDK предоставляет функцию AutoCamera, которая включена по умолчанию. Камера масштабируется, чтобы сфокусироваться на маршруте совместного путешествия и следующей путевой точке.

АвтоКамера

Настройка поведения камеры

Если вам требуется больший контроль над поведением камеры, вы можете отключить или включить автокамеру с помощью ConsumerController.setAutoCameraEnabled() .

ConsumerController.getCameraUpdate() возвращает рекомендуемые границы камеры на данный момент. Затем вы можете предоставить этот CameraUpdate в качестве аргумента GoogleMap.moveCamera() или GoogleMap.animateCamera() .

Доступ к совместному использованию поездок и картам

Для поддержки совместного использования поездок и взаимодействия с картами в вашем приложении вам необходим доступ к ConsumerGoogleMap и ConsumerController . ConsumerMapFragment и ConsumerMapView асинхронно возвращают ConsumerGoogleMap в ConsumerMapReadyCallback . ConsumerGoogleMap возвращает ConsumerController из getConsumerController() . Вы можете получить доступ к ConsumerGoogleMap и ConsumerController следующим образом.

Джава

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

Котлин

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

ПотребительGoogleКарта

ConsumerGoogleMap — это класс-оболочка для класса GoogleMap . Он предоставляет вашему приложению возможность взаимодействовать с картой с помощью API, эквивалентного GoogleMap . Использование карты потребителя позволяет вашему приложению и сервису совместного использования поездок беспрепятственно взаимодействовать с одной и той же базовой картой GoogleMap. Например, GoogleMap допускает только одну регистрацию обратного вызова, а ConsumerGoogleMap поддерживает двойные зарегистрированные обратные вызовы. Эти обратные вызовы позволяют вашему приложению и совместному использованию поездок регистрировать обратные вызовы, которые вызываются последовательно.

ПотребительКонтроллер

ConsumerController предоставляет доступ к функциям совместного использования поездок, таким как мониторинг поездок, контроль статуса поездки и настройка местоположения.

Настройте совместное путешествие

После того как серверная часть сопоставила потребителя с транспортным средством, используйте JourneySharingSession , чтобы запустить пользовательский интерфейс совместного использования поездок. Функция обмена информацией о поездках показывает местоположение и маршрут соответствующего автомобиля. После внедрения SDK в свое приложение вы можете добавить функции мониторинга поездок, прослушивания обновлений и обработки ошибок. Следующие процедуры предполагают, что серверные службы установлены и ваши службы по сопоставлению потребителей с транспортными средствами работают.

  1. Зарегистрируйте прослушиватель для объекта TripModel , чтобы получать подробные сведения о поездке, такие как ETA (расчетное время прибытия) и расстояние, которое транспортному средству необходимо преодолеть до прибытия.

    Джава

    // 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) {
        // ...
      }
    
      // ...
    });
    

    Котлин

    // 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. Настройте свою поездку с помощью TripModelOptions .

    Джава

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

    Котлин

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

Прекратить делиться поездками

Обязательно прекращайте делиться поездками, когда в них больше нет необходимости, например, когда активность хоста уничтожена. Прекращение совместного использования маршрутов также останавливает сетевые запросы к Fleet Engine и предотвращает утечки памяти.

В следующем примере кода показано, как прекратить совместное использование поездок.

Джава

public class MainActivity extends AppCompatActivity
    implements ConsumerViewModel.JourneySharingListener  {

  // Class implementation

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

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

Котлин

class SampleAppActivity : AppCompatActivity(), ConsumerViewModel.JourneySharingListener {

  // Class implementation

  override fun onDestroy() {
    super.onDestroy()

    journeySharingSession?.stop()
  }
}

Обработка ошибок в поездках

Метод onTripRefreshError выявляет ошибки, возникающие во время мониторинга поездки. Сопоставление ошибок Consumer SDK соответствует тем же правилам HTTP/RPC, что и для Google Cloud Platform . К частым ошибкам, возникающим во время мониторинга поездки, относятся следующие:

HTTP ПКП Описание
400 НЕДЕЙСТВИТЕЛЬНЫМ АРГУМЕНТ Клиент указал неверное название поездки. Название поездки должно иметь формат providers/{provider_id}/trips/{trip_id} . Provider_id должен быть идентификатором облачного проекта, принадлежащего поставщику услуг.
401 НЕ АУТЕНТИФИЦИРОВАННЫЙ Запрос не аутентифицирован из-за недействительного токена JWT. Эта ошибка произойдет, если токен JWT подписан без идентификатора поездки или срок действия токена JWT истек.
403 ДОСТУП ЗАПРЕЩЕН Клиент не имеет достаточного разрешения. Эта ошибка возникает, если токен JWT недействителен, у клиента нет разрешения или API не включен для клиентского проекта. Токен JWT может отсутствовать или токен подписан с идентификатором поездки, который не соответствует запрошенному идентификатору поездки.
429 RESOURCE_EXHAUSTED Квота ресурса равна нулю или скорость трафика превышает лимит.
503 НЕДОСТУПЕН Сервис недоступен. Обычно сервер не работает.
504 DEADLINE_EXCEEDED Срок запроса истек. Это произойдет только в том случае, если вызывающая сторона установит крайний срок, который короче, чем крайний срок метода по умолчанию (т. е. запрошенного крайнего срока недостаточно для того, чтобы сервер обработал запрос), и запрос не был завершен в течение установленного срока.

Дополнительные сведения см. в разделе Обработка ошибок Consumer SDK .