드라이버 SDK를 사용하여 경로 및 주문 진행 애플리케이션에 향상된 탐색 및 추적을 제공할 수 있습니다. 드라이버 SDK는 주문형 차량 공유 및 배송 차량에 차량 위치 및 작업 업데이트를 제공합니다.
운전자 SDK는 Fleet Engine 서비스와 커스텀 서비스에서 차량의 위치와 상태를 인식합니다. 예를 들어 차량은 ONLINE
또는 OFFLINE
일 수 있으며 이동이 진행됨에 따라 차량 위치가 변경됩니다.
최소 시스템 요구사항
휴대기기는 Android 5.0 (API 수준 21) 이상을 실행해야 합니다.
기본 요건
운송 및 물류 Android SDK는 Artifact Registry Maven 저장소에 게시됩니다. 저장소에는 SDK의 프로젝트 객체 모델 (.pom) 파일과 오프라인 Javadocs가 포함됩니다.
액세스하기
Google Workspace 고객인 경우 온보딩 중에 google-maps-platform-sdk-users@workspacedomain.com
같은 작업공간 그룹을 만들고 Google에 이름을 제공합니다. 이것이 권장 방법입니다.
그러면 Workspace 그룹이 Maven 저장소 gmp-artifacts/transportation
에 대한 액세스 권한을 부여하는 허용 목록에 추가됩니다.
액세스 권한이 필요한 사용자 이메일 및 서비스 계정 이메일이 이 목록에 포함되어 있는지 확인합니다.
조직에서 Workspace 그룹을 만들 수 없는 경우 이러한 아티팩트에 액세스해야 하는 사용자 및 서비스 계정 이메일 목록을 Google에 전송합니다.
로컬 개발
로컬 개발의 경우 Cloud SDK로 로그인해도 됩니다.
gcloud
gcloud auth login
로그인에 사용되는 이메일은 Workspace 그룹의 구성원이어야 합니다.
자동화 (빌드 시스템 또는 지속적 통합)
권장사항에 따라 자동화 호스트를 설정합니다.
프로세스가 Google Cloud 환경 내에서 실행되는 경우 자동 사용자 인증 정보 감지를 사용합니다.
그렇지 않으면 서비스 계정 키 파일을 호스트 파일 시스템의 안전한 위치에 저장하고 GOOGLE_APPLICATION_CREDENTIALS 환경 변수를 적절하게 설정합니다.
사용자 인증 정보와 관련된 서비스 계정 이메일은 작업공간 그룹의 구성원이어야 합니다.
구성
Maven 또는 Gradle을 구성하여 사용자 또는 서비스 사용자 인증 정보를 자동으로 감지합니다.
Gradle
프로젝트 루트 모듈 build.gradle
파일이 아니라 앱 모듈의 build.gradle
파일에 다음을 추가합니다.
plugins {
id "com.google.cloud.artifactregistry.gradle-plugin" version "2.1.5"
}
repositories {
maven {
url "artifactregistry://us-west2-maven.pkg.dev/gmp-artifacts/transportation"
}
}
Maven
pom.xml
에 다음을 추가합니다.
<repositories>
<repository>
<id>gmp-artifacts</id>
<url>artifactregistry://us-west2-maven.pkg.dev/gmp-artifacts/transportation</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<build>
<extensions>
<extension>
<groupId>com.google.cloud.artifactregistry</groupId>
<artifactId>artifactregistry-maven-wagon</artifactId>
<version>2.1.0</version>
</extension>
</extensions>
</build>
액세스 확인에 대한 자세한 내용은 자바 패키지 관리를 참조하세요.
프로젝트 구성
드라이버 SDK를 사용하려면 앱에서 minSdkVersion
21 이상을 타겟팅해야 합니다.
Driver SDK로 빌드된 앱을 실행하려면 Android 기기에 Google Play 서비스가 설치되어 있어야 합니다.
개발 프로젝트 설정
Google Cloud Console에서 개발 프로젝트를 설정하고 프로젝트의 API 키를 가져오려면 다음 안내를 따르세요.
드라이버 SDK에서 사용할 새 Google Cloud Console 프로젝트를 만들거나 기존 프로젝트를 선택합니다. 새 프로젝트가 Google Cloud Console에 표시될 때까지 몇 분 정도 기다립니다.
데모 앱을 실행하려면 프로젝트에 Android용 Maps SDK 액세스 권한이 있어야 합니다. Google Cloud Console에서 API 및 서비스 > 라이브러리를 선택한 다음 Android용 Maps SDK를 검색하고 사용 설정합니다.
API 및 서비스 > 사용자 인증 정보 > 사용자 인증 정보 만들기 > API 키를 선택하여 프로젝트의 API 키를 가져옵니다. API 키 가져오기에 대한 자세한 내용은 API 키 가져오기를 참조하세요.
앱에 드라이버 SDK 추가
드라이버 SDK는 비공개 Maven 저장소를 통해 사용할 수 있습니다. 저장소에는 SDK의 프로젝트 객체 모델 (.pom) 파일 및 Javadoc이 포함되어 있습니다. 앱에 드라이버 SDK를 추가하려면 다음 단계를 따르세요.
- 액세스 권한 받기에 설명된 대로 호스트 Maven 저장소에 액세스할 수 있는 환경을 설정합니다.
Gradle 또는 Maven 구성에 다음 종속 항목을 추가하고
VERSION_NUMBER
자리표시자를 원하는 버전의 SDK로 대체합니다.Gradle
build.gradle
에 다음을 추가합니다.dependencies { ... implementation 'com.google.android.libraries.mapsplatform.transportation:transportation-driver:VERSION_NUMBER' }
Maven
pom.xml
에 다음을 추가합니다.<dependencies> ... <dependency> <groupId>com.google.android.libraries.mapsplatform.transportation</groupId> <artifactId>transportation-driver</artifactId> <version>VERSION_NUMBER</version> </dependency> </dependencies>
앱에 API 키 추가
드라이버 SDK를 앱에 추가한 후 API 키를 앱에 추가합니다. 개발 프로젝트를 설정할 때 얻은 프로젝트 API 키를 사용해야 합니다.
이 섹션에서는 앱에서 더욱 안전하게 참조할 수 있도록 API 키를 저장하는 방법을 설명합니다. API 키는 버전 제어 시스템에 등록하면 안 됩니다. 이 파일은 프로젝트의 루트 디렉터리에 있는 local.properties
파일에 저장해야 합니다. local.properties
파일에 관한 자세한 내용은 Gradle 속성 파일을 참고하세요.
이 작업을 간단히 진행하고 싶다면 Android용 Secrets Gradle Plugin을 사용하세요.
플러그인을 설치하여 API 키를 저장하는 방법은 다음과 같습니다.
루트 수준
build.gradle
파일을 열고buildscript
아래의dependencies
요소에 다음 코드를 추가합니다.Groovy
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") } }
앱 수준
build.gradle
파일을 열고plugins
요소에 다음 코드를 추가합니다.Groovy
id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
Kotlin
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
Android 스튜디오를 사용하는 경우 프로젝트를 Gradle과 동기화합니다.
프로젝트 수준 디렉터리에서
local.properties
를 열고 다음 코드를 추가합니다.YOUR_API_KEY
를 API 키로 변경합니다.MAPS_API_KEY=YOUR_API_KEY
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>
앱에 필수 기여 분석 포함
앱에서 드라이버 SDK를 사용하는 경우 저작자 표시 텍스트와 오픈소스 라이선스를 앱의 법적 고지 섹션에 포함해야 합니다. 속성은 독립적인 메뉴 항목 또는 정보 메뉴 항목의 일부로 포함하는 것이 가장 좋습니다.
Attribution SDK ZIP 파일에서 필요한 저작자 표시 텍스트와 오픈소스 라이선스를 찾을 수 있습니다.
NOTICE.txt
LICENSES.txt
종속 항목
ProGuard를 사용하여 빌드를 최적화하는 경우 ProGuard 구성 파일에 다음 줄을 추가해야 할 수도 있습니다.
-dontwarn com.google.**
-dontwarn okio.**
지원되는 최소 API 수준은 21입니다.
SDK 초기화
DriverContext
객체를 초기화하려면 제공업체 ID (일반적으로 Google Cloud 프로젝트 ID)가 필요합니다. Google Cloud 프로젝트 설정에 대한 자세한 내용은 인증 및 승인을 참조하세요.
드라이버 SDK를 사용하려면 먼저 Navigation SDK를 초기화해야 합니다. SDK를 초기화하려면 다음 안내를 따르세요.
NavigationApi
에서Navigator
객체를 가져옵니다.자바
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; } } );
Kotlin
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 } }, )
DriverContext
객체를 만들어 필수 필드를 채웁니다.자바
DriverContext driverContext = DriverContext.builder(application) .setProviderId(providerId) .setVehicleId(vehicleId) .setAuthTokenFactory(authTokenFactory) .setNavigator(navigator) .setRoadSnappedLocationProvider( NavigationApi.getRoadSnappedLocationProvider(application)) .build();
Kotlin
val driverContext = DriverContext.builder(application) .setProviderId(providerId) .setVehicleId(vehicleId) .setAuthTokenFactory(authTokenFactory) .setNavigator(navigator) .setRoadSnappedLocationProvider(NavigationApi.getRoadSnappedLocationProvider(application)) .build()
DriverContext
객체를 사용하여*DriverApi
를 초기화합니다.자바
RidesharingDriverApi ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext);
Kotlin
val ridesharingDriverApi = RidesharingDriverApi.createInstance(driverContext)
API 객체에서
RidesharingVehicleReporter
를 가져옵니다. (*VehicleReporter
는NavigationVehicleReporter
를 확장합니다.)자바
RidesharingVehicleReporter vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter();
Kotlin
val vehicleReporter = ridesharingDriverApi.getRidesharingVehicleReporter()
AuthTokenFactory
(으)로 인증하는 중
드라이버 SDK가 위치 업데이트를 생성할 때 Fleet Engine 서버에 이러한 업데이트를 전송해야 합니다. 이러한 요청을 인증하기 위해 드라이버 SDK는 호출자가 제공한 AuthTokenFactory
인스턴스를 호출합니다.
팩토리는 위치 업데이트 시 인증 토큰을 생성합니다.
토큰이 생성되는 정확한 방식은 각 개발자의 상황에 따라 다릅니다. 하지만 구현 시 다음을 따라야 할 수 있습니다.
- HTTPS 서버에서 인증 토큰(JSON 형식)을 가져올 수 있습니다.
- 토큰 파싱 및 캐시
- 토큰이 만료되면 토큰 갱신
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);
}
}
}
Kotlin
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 클라이언트를 사용하여 개발자의 인증 서버에서 JSON 형식의 토큰을 가져옵니다. 토큰은 재사용을 위해 저장됩니다. 이전 토큰이 만료 시간 10분 이내인 경우 토큰을 다시 가져옵니다.
구현 시 다른 작업을 수행할 수 있습니다(예: 백그라운드 스레드를 사용하여 토큰 새로고침).
AuthTokenFactory
의 예외는 반복적으로 발생하지 않는 한 일시적인 것으로 간주됩니다. 여러 번 시도하면 드라이버 SDK에서 오류가 영구적이라고 가정하고 업데이트 전송을 중지합니다.
StatusListener
를 사용한 상태 및 Error Reporting
드라이버 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.
}
}
Kotlin
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에 대한 참고사항
내부적으로 드라이버 SDK 구현은 SSL/TLS를 사용하여 Fleet Engine 서버와 안전하게 통신합니다. 이전 버전의 Android (API 버전 19 이하)는 서버와 통신할 수 있도록 SecurityProvider
패치가 필요할 수 있습니다. Android에서 SSL을 사용하는 방법에 관한 자세한 내용은 이 도움말을 참고하세요. 보안 제공자에 패치를 적용하기 위한 코드 샘플도 포함되어 있습니다.
위치 업데이트 사용 설정 중
*VehicleReporter
인스턴스가 있으면 위치 업데이트를 간단하게 사용 설정할 수 있습니다.
자바
RidesharingVehicleReporter reporter = ...;
reporter.enableLocationTracking();
Kotlin
val reporter = ...
reporter.enableLocationTracking()
차량 상태가 ONLINE
인 경우 위치 업데이트가 일정한 간격으로 전송됩니다. reporter.enableLocationTracking()
를 호출해도 차량 상태가 ONLINE
로 자동 설정되지는 않습니다. 명시적으로 차량 상태를 설정해야 합니다.
기본적으로 보고 간격은 10초입니다. 보고 간격은 reporter.setLocationReportingInterval(long, TimeUnit)
를 사용하여 변경할 수 있습니다. 지원되는 최소 업데이트 간격은 5초입니다. 업데이트를 더 자주 실행하면 요청 및 오류가 느려질 수 있습니다.
위치 업데이트 사용 중지
운전자의 이동이 끝나면 위치 업데이트를 중지하고 DeliveryVehicleReporter.disableLocationTracking
또는 RidesharingVehicleReporter.disableLocationTracking
를 호출하여 차량을 오프라인으로 표시할 수 있습니다.
이 호출로 인해 최종 업데이트가 즉시 전송되도록 예약되어 차량이 오프라인 상태임을 나타냅니다. 이 업데이트에는 사용자 위치가 포함되지 않습니다.
차량 상태 설정
위치 업데이트가 사용 설정된 경우 차량 상태를 ONLINE
로 설정하면 차량에서 SearchVehicles
쿼리를 사용할 수 있습니다. 마찬가지로 차량을 OFFLINE
로 표시하면 차량이 사용 불가로 표시됩니다.
서버 측에서 차량 상태를 설정하거나 (차량 업데이트 참고) 드라이버 SDK에서 직접 설정할 수 있습니다.
자바
RidesharingVehicleReporter reporter = ...;
reporter.enableLocationTracking();
reporter.setVehicleState(VehicleState.ONLINE);
Kotlin
val reporter = ...
reporter.enableLocationTracking()
reporter.setVehicleState(VehicleState.ONLINE)
위치 업데이트가 사용 설정되면 다음 위치 업데이트 시 setVehicleState
호출이 전파됩니다.
위치 추적을 사용 설정하지 않았을 때 차량을 ONLINE
로 표시하면
IllegalStateException
이 발생합니다. 위치 추적이 아직 사용 설정되지 않았거나 명시적으로 사용 중지된 경우 차량을 OFFLINE
로 표시할 수 있습니다. 그러면 즉시 업데이트됩니다. RidesharingVehicleReporter.disableLocationTracking()
를 호출하면 차량 상태가 OFFLINE
로 설정됩니다.
setVehicleState
는 즉시 반환되며 업데이트는 위치 업데이트 스레드에서 실행됩니다. 위치 업데이트의 오류 처리와 마찬가지로 차량 상태를 업데이트하는 오류는 DriverContext
에 설정된 StatusListener
(선택사항)을 사용하여 전파됩니다.