Начало работы с 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 .