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

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

Driver SDK информирует службы Fleet Engine и ваши таможенные службы о местонахождении и состоянии транспортного средства. Например, транспортное средство может находиться ONLINE или OFFLINE , а местоположение автомобиля меняется по ходу поездки.

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

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

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

Driver SDK версии 4.99 и более поздних версий доступен в репозитории 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>

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

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

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

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

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

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

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

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

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

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

  1. Добавьте следующую зависимость в конфигурацию Gradle или Maven, заменив заполнитель VERSION_NUMBER на нужную версию Driver SDK.

    Градл

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

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

    Мавен

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

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.mapsplatform.transportation</groupId>
        <artifactId>transportation-driver</artifactId>
        <version>VERSION_NUMBER</version>
      </dependency>
    </dependencies>
    
  2. Driver SDK зависит от Navigation SDK. Эта зависимость настроена таким образом, что если требуется конкретная версия Navigation SDK, ее необходимо явно определить в файле конфигурации сборки, как показано ниже. Пропуск упомянутого блока кода включит проект чтобы всегда загружать последнюю версию Navigation SDK в рамках основной версии. Обратите внимание, что совместное поведение последних версий Driver SDK и Navigation SDK прошло тщательное тестирование перед их выпуском.

    Соответствующим образом организуйте конфигурацию зависимостей вашей среды разработки и выпуска.

    Градл

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

    dependencies {
      ...
      implementation 'com.google.android.libraries.navigation:navigation:5.0.0'
    }
    

    Мавен

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

    <dependencies>
      ...
      <dependency>
        <groupId>com.google.android.libraries.navigation</groupId>
        <artifactId>navigation</artifactId>
        <version>5.0.0</version>
      </dependency>
    </dependencies>
    

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

Добавив Driver 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.driverapidemo">
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/_AppTheme">

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

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

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

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

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

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

Зависимости

Если вы используете ProGuard для оптимизации своих сборок, вам может потребоваться добавить следующие строки в файл конфигурации ProGuard:

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

Минимальный поддерживаемый уровень API — 23.

Инициализация SDK

Идентификатор поставщика (обычно идентификатор проекта Google Cloud) необходим для инициализации объекта DriverContext . Более подробную информацию о настройке проекта Google Cloud см. в разделе Аутентификация и авторизация .

Перед использованием Driver SDK необходимо сначала инициализировать Navigation SDK. Чтобы инициализировать SDK:

  1. Получите объект Navigator из NavigationApi .

    Джава

    NavigationApi.getNavigator(
        this, // Activity
        new NavigationApi.NavigatorListener() {
          @Override
          public void onNavigatorReady(Navigator navigator) {
            // Keep a reference to the Navigator (used to configure and start nav)
            this.navigator = navigator;
          }
        }
    );
    

    Котлин

    NavigationApi.getNavigator(
      this, // Activity
      object : NavigatorListener() {
        override fun onNavigatorReady(navigator: Navigator) {
          // Keep a reference to the Navigator (used to configure and start nav)
          this@myActivity.navigator = navigator
        }
      },
    )
    
  2. Создайте объект DriverContext , заполнив необходимые поля.

    Джава

    DriverContext driverContext = DriverContext.builder(application)
        .setProviderId(providerId)
        .setVehicleId(vehicleId)
        .setAuthTokenFactory(authTokenFactory)
        .setNavigator(navigator)
        .setRoadSnappedLocationProvider(
            NavigationApi.getRoadSnappedLocationProvider(application))
        .build();
    

    Котлин

    val driverContext =
      DriverContext.builder(application)
        .setProviderId(providerId)
        .setVehicleId(vehicleId)
        .setAuthTokenFactory(authTokenFactory)
        .setNavigator(navigator)
        .setRoadSnappedLocationProvider(NavigationApi.getRoadSnappedLocationProvider(application))
        .build()
    
  3. Используйте объект DriverContext для инициализации *DriverApi .

    Джава

    RidesharingDriverApi ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext);
    

    Котлин

    val ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext)
    
  4. Получите RidesharingVehicleReporter из объекта API. ( *VehicleReporter расширяет NavigationVehicleReporter .)

    Джава

    RidesharingVehicleReporter vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter();
    

    Котлин

    val vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter()
    

Аутентификация с помощью AuthTokenFactory

Когда Driver SDK генерирует обновления местоположения, он должен отправлять эти обновления на сервер Fleet Engine. Для аутентификации этих запросов Driver SDK обращается к экземпляру AuthTokenFactory , предоставленному вызывающей стороной. Фабрика отвечает за создание токенов аутентификации во время обновления местоположения.

То, как именно генерируются токены, будет зависеть от ситуации каждого разработчика. Однако реализация, вероятно, потребует:

  • получить токен аутентификации, возможно, в формате JSON, с HTTPS-сервера
  • проанализировать и кэшировать токен
  • обновить токен по истечении срока его действия

Подробную информацию о токенах, ожидаемых сервером Fleet Engine, см. в разделе Создание веб-токена JSON (JWT) для авторизации .

Вот скелет реализации AuthTokenFactory :

Джава

class JsonAuthTokenFactory implements AuthTokenFactory {
  private String token;  // initially null
  private long expiryTimeMs = 0;

  // This method is called on a thread whose only responsibility is to send
  // location updates. Blocking is OK, but just know that no location updates
  // can occur until this method returns.
  @Override
  public String getToken(AuthTokenContext authTokenContext) {
    if (System.currentTimeMillis() > expiryTimeMs) {
      // The token has expired, go get a new one.
      fetchNewToken(authTokenContext.getVehicleId());
    }
    return token;
  }

  private void fetchNewToken(String vehicleId) {
    String url =
        new Uri.Builder()
            .scheme("https")
            .authority("yourauthserver.example")
            .appendPath("token")
            .appendQueryParameter("vehicleId", vehicleId)
            .build()
            .toString();

    try (Reader r = new InputStreamReader(new URL(url).openStream())) {
      com.google.gson.JsonObject obj
          = com.google.gson.JsonParser.parseReader(r).getAsJsonObject();
      token = obj.get("Token").getAsString();
      expiryTimeMs = obj.get("TokenExpiryMs").getAsLong();

      // The expiry time could be an hour from now, but just to try and avoid
      // passing expired tokens, we subtract 10 minutes from that time.
      expiryTimeMs -= 10 * 60 * 1000;
    } catch (IOException e) {
      // It's OK to throw exceptions here. The StatusListener you passed to
      // create the DriverContext class will be notified and passed along the failed
      // update warning.
      throw new RuntimeException("Could not get auth token", e);
    }
  }
}

Котлин

class JsonAuthTokenFactory : AuthTokenFactory() {

  private var token: String = ""
  private var expiryTimeMs: Long = 0

  // This method is called on a thread whose only responsibility is to send
  // location updates. Blocking is OK, but just know that no location updates
  // can occur until this method returns.
  override fun getToken(context: AuthTokenContext): String {
    if (System.currentTimeMillis() > expiryTimeMs) {
      // The token has expired, go get a new one.
      fetchNewToken(authTokenContext.getVehicleId())
    }
     return token
  }

  fun fetchNewToken(vehicleId: String) {
    val url =
      Uri.Builder()
        .scheme("https")
        .authority("yourauthserver.example")
        .appendPath("token")
        .appendQueryParameter("vehicleId", vehicleId)
        .build()
        .toString()

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

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

        token = obj.get("ServiceToken").getAsString()
        expiryTimeMs = obj.get("TokenExpiryMs").getAsLong()

        // The expiry time could be an hour from now, but just to try and avoid
        // passing expired tokens, we subtract 10 minutes from that time.
        expiryTimeMs -= 10 * 60 * 1000
      }
    } catch (e: IOException) {
      // It's OK to throw exceptions here. The StatusListener you passed to
      // create the DriverContext class will be notified and passed along the failed
      // update warning.
      throw RuntimeException("Could not get auth token", e)
    }
  }
}

В этой конкретной реализации используется встроенный HTTP-клиент Java для получения токена в формате JSON с сервера аутентификации разработчика. Токен сохраняется для повторного использования. Токен извлекается повторно, если срок действия старого токена истекает в течение 10 минут.

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

Исключения в AuthTokenFactory будут рассматриваться как временные, если они не происходят повторно. После нескольких попыток Driver SDK посчитает ошибку постоянной и прекратит попытки отправлять обновления.

Отчеты о статусе и ошибках с помощью StatusListener

Поскольку Driver SDK выполняет действия в фоновом режиме, используйте StatusListener для запуска уведомлений при возникновении определенных событий, таких как ошибки, предупреждения или сообщения отладки. Ошибки могут быть временными по своей природе (например, BACKEND_CONNECTIVITY_ERROR ) или могут привести к постоянной остановке обновления местоположения (например, VEHICLE_NOT_FOUND , что указывает на ошибку конфигурации).

Вы предоставляете дополнительную реализацию StatusListener подобную следующей:

Джава

class MyStatusListener implements StatusListener {
  /** Called when background status is updated, during actions such as location reporting. */
  @Override
  public void updateStatus(
      StatusLevel statusLevel, StatusCode statusCode, String statusMsg) {
    // Status handling stuff goes here.
    // StatusLevel may be DEBUG, INFO, WARNING, or ERROR.
    // StatusCode may be DEFAULT, UNKNOWN_ERROR, VEHICLE_NOT_FOUND,
    // BACKEND_CONNECTIVITY_ERROR, or PERMISSION_DENIED.
  }
}

Котлин

class MyStatusListener : StatusListener() {
  /** Called when background status is updated, during actions such as location reporting. */
  override fun updateStatus(statusLevel: StatusLevel, statusCode: StatusCode, statusMsg: String) {
    // Status handling stuff goes here.
    // StatusLevel may be DEBUG, INFO, WARNING, or ERROR.
    // StatusCode may be DEFAULT, UNKNOWN_ERROR, VEHICLE_NOT_FOUND,
    // BACKEND_CONNECTIVITY_ERROR, or PERMISSION_DENIED.
  }
}

Примечания по SSL/TLS

Внутри реализация Driver SDK использует SSL/TLS для безопасного взаимодействия с сервером Fleet Engine. Для более старых версий Android (версии API 19 или ниже) может потребоваться исправление SecurityProvider для связи с сервером. Вам следует прочитать эту статью для получения дополнительной информации о работе с SSL в Android. Статья также содержит примеры кода для исправления поставщика безопасности.

Включение обновлений местоположения

Если у вас есть экземпляр *VehicleReporter , включить обновление местоположения очень просто:

Джава

RidesharingVehicleReporter reporter = ...;

reporter.enableLocationTracking();

Котлин

val reporter = ...

reporter.enableLocationTracking()

Обновления местоположения отправляются через регулярные промежутки времени, когда транспортное средство находится в режиме ONLINE . Обратите внимание, что вызов reporter.enableLocationTracking() не устанавливает автоматически состояние транспортного средства в ONLINE . Вы должны явно указать состояние транспортного средства .

По умолчанию интервал отчетов составляет 10 секунд. Интервал отчетности можно изменить с помощью reporter.setLocationReportingInterval(long, TimeUnit) . Минимальный поддерживаемый интервал обновления составляет 5 секунд. Более частые обновления могут привести к замедлению запросов и ошибкам.

Отключение обновления местоположения

Когда смена водителя завершена, обновление местоположения можно остановить и пометить транспортное средство как отключенное от сети, вызвав DeliveryVehicleReporter.disableLocationTracking или RidesharingVehicleReporter.disableLocationTracking .

Этот вызов приведет к тому, что одно последнее обновление будет запланировано для немедленной доставки, что указывает на то, что автомобиль отключен от сети. Это обновление не будет содержать местоположение пользователя.

Настройка состояния автомобиля

Если обновление местоположения включено, установка состояния автомобиля в ONLINE сделает автомобиль доступным для запросов SearchVehicles ; Аналогичным образом, пометка транспортного средства как OFFLINE пометит его как недоступное.

У вас есть возможность установить состояние автомобиля на стороне сервера (см. «Обновление автомобиля ») или непосредственно в Driver SDK:

Джава

RidesharingVehicleReporter reporter = ...;

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

Котлин

val reporter = ...

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

Если обновление местоположения включено, вызов setVehicleState будет распространяться при следующем обновлении местоположения.

Пометка транспортного средства как ONLINE , когда отслеживание местоположения не включено, приведет к возникновению IllegalStateException . Транспортное средство может быть помечено как OFFLINE если отслеживание местоположения еще не включено или явно отключено. Это приведет к немедленному обновлению. Вызов RidesharingVehicleReporter.disableLocationTracking() установит состояние транспортного средства в OFFLINE .

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