Account Transfer API

사용자는 탭앤고를 사용하여 Google 계정과 데이터를 기존 Android 지원 기기에서 새 Android 지원 기기로 복사할 수 있습니다. 사용자가 AbstractAccountAuthenticator를 사용하여 구현하고 AccountManager와 통합된 맞춤 계정의 사용자 인증 정보도 복사하도록 하려면 Account Transfer API를 사용하면 됩니다. 시스템은 새 기기에서 실행되는 탭앤고 설정 마법사에서 Account Transfer API를 호출합니다. 또한 시스템은 Account Transfer API를 호출하여 케이블을 통해 Android 휴대전화에서 Pixel로 데이터를 전송합니다.

탭앤고 시작 화면 데이터 소스를 선택하는 탭앤고 화면

그림 1. Account Transfer API는 새 기기에서 실행되는 탭앤고 설정 마법사에서 호출됨

맞춤 계정 전송 지원을 추가하려면 앱에 Account Transfer API를 통합하세요. 그러면 Google Play 서비스가 기존 기기(소스 기기라고도 함)와 새 기기(대상 기기라고도 함) 사이에 양방향 암호화된 채널을 설정하여 그림 2와 같이 계정 데이터를 전송할 수 있습니다. 암호화된 채널은 전송을 완료하기 위해 서드 파티 서버에 연결하는 데 의존하지 않습니다.

Account Transfer API를 앱에 통합할 때 다음 요구사항을 고려해야 합니다.

  • 소스 기기는 Android 4.0.1(API 수준 14) 이상을 실행해야 합니다.
  • 대상 기기는 Android 8.0(API 수준 26) 이상을 실행해야 합니다.
  • 소스 및 대상 기기 모두 Google Play 서비스 버전 11.2.0 이상을 실행해야 합니다.
  • Google Play 서비스 SDK 버전 11.2.0 이상을 사용하여 앱을 빌드해야 합니다.

소스에서 대상 기기로 계정을 전송하는 그림

그림 2. 전송은 Google Play 서비스가 소스 기기와 대상 기기 간에 설정하는 암호화된 채널을 통해 이루어집니다.

프로젝트에 Account Transfer API 추가

프로젝트에서 Account Transfer API를 사용하려면 먼저 Google Play 서비스 SDK로 프로젝트를 설정해야 합니다. Google Play 서비스 SDK 설정에 관한 자세한 내용은 Google Play 서비스 설정을 참고하세요.

Google Account Transfer API를 앱에 선택적으로 컴파일하려면 애플리케이션 모듈 디렉터리 내 build.gradle 파일에 있는 dependencies 블록에 다음 빌드 규칙을 추가합니다.

Groovy

plugins {
  id 'com.android.application'
}
...
dependencies {
    // VERSION_NUMBER must be equal to or higher than 11.2.0.
    implementation 'com.google.android.gms:play-services-auth:<VERSION_NUMBER>'
}

Kotlin

plugins {
    id("com.android.application")
}
...
dependencies {
    // VERSION_NUMBER must be equal to or higher than 11.2.0.
    implementation("com.google.android.gms:play-services-auth:<VERSION_NUMBER>")
}

맞춤 계정을 전송하기 위한 지원을 추가하려면 다음과 같이 앱 매니페스트에 인증자 서비스의 START_ACCOUNT_EXPORT broadcast receiver를 선언해야 합니다.

<receiver android:name=".MyBroadcastReceiver"  android:exported="true">
    <intent-filter>
        <action android:name="com.google.android.gms.auth.START_ACCOUNT_EXPORT"/>
        ...
    </intent-filter>
</receiver>

앱이 OEM 시스템 이미지에 설치되어 있지 않고 OEM 시스템 이미지에 앱을 포함할 계획이 없다면 위에서 설명한 대로 계정 데이터를 내보내려면 소스 기기에서 ACTION_START_ACCOUNT_EXPORT 브로드캐스트를 수신 대기하도록 등록해야 합니다.

OEM 시스템 이미지에 앱을 설치한다면 다음 브로드캐스트에도 등록해야 합니다.

계정 데이터 전송

사용자가 기존 기기에서 콘텐츠를 복원하도록 선택하면 시스템은 ACTION_START_ACCOUNT_EXPORT 브로드캐스트를 소스 기기의 관련 계정과 연결된 패키지로 전송합니다.

계정 데이터 전송

계정 데이터를 전송하려면 서비스에서 ACTION_START_ACCOUNT_EXPORT 브로드캐스트를 수신한 후에 소스 기기에서 인증자 서비스를 시작하고 sendData()를 호출하면 됩니다. getAccountTransferClient(Context) 또는 getAccountTransferClient(Activity)를 호출하여 AccountTransferClient 객체의 참조를 가져올 수 있습니다. 다음 코드 스니펫은 소스 기기에서 데이터를 전송하는 방법을 보여줍니다.

Kotlin

val client: AccountTransferClient = AccountTransfer.getAccountTransferClient(this)
val exportTask: Task<Void> = client.sendData(ACCOUNT_TYPE, transferBytes)
try {
    // Wait for the task to either complete or provide the callback.
    Tasks.await(exportTask, TIMEOUT_API, TIME_UNIT)
} catch (e: Exception) {
    when(e) {
        is ExecutionException, is InterruptedException, is TimeoutException -> {
            client.notifyCompletion(ACCOUNT_TYPE,
                    AuthenticatorTransferCompletionStatus.COMPLETED_FAILURE)
            return
        }
        else -> throw e
    }
}

Java

AccountTransferClient client = AccountTransfer.getAccountTransferClient(this);
Task<Void> exportTask = client.sendData(ACCOUNT_TYPE, transferBytes);
try {
  // Wait for the task to either complete or provide the callback.
  Tasks.await(exportTask, TIMEOUT_API, TIME_UNIT);
} catch (ExecutionException | InterruptedException | TimeoutException e) {
  client.notifyCompletion(ACCOUNT_TYPE,AuthenticatorTransferCompletionStatus.COMPLETED_FAILURE);
  return;
}

대상 기기의 설정 마법사에서 계정 데이터를 수신합니다.

계정 데이터 수신

동일한 인증자 서비스가 이 기기에 설치되어 있고 ACTION_ACCOUNT_IMPORT_DATA_AVAILABLE 브로드캐스트를 수신 대기하여 관심을 등록한 경우 타겟 기기는 ACTION_ACCOUNT_IMPORT_DATA_AVAILABLE 브로드캐스트를 상응하는 패키지로 전송합니다.

ACTION_ACCOUNT_IMPORT_DATA_AVAILABLE 브로드캐스트를 수신하면 대상 기기에서 서비스를 시작하고 retrieveData()를 호출하여 소스 기기에서 전송된 데이터를 가져옵니다. 다음 코드 스니펫은 대상 기기에서 데이터를 검색하는 방법을 보여줍니다.

Kotlin

val client: AccountTransferClient = AccountTransfer.getAccountTransferClient(this)
val transportTask: Task<Void> = client.retrieveData(ACCOUNT_TYPE)
try {
    val transferBytes: ByteArray = Tasks.await(transferTask, TIMEOUT_API, TIME_UNIT)
    // Add the transferred account(s) to AccountManager to register with the framework.
} catch (e: Exception) {
    when(e) {
        is ExecutionException, is InterruptedException, is TimeoutException -> {
            client.notifyCompletion(ACCOUNT_TYPE,
                    AuthenticatorTransferCompletionStatus.COMPLETED_FAILURE)
            return
        }
        else -> throw e
    }
 }
client.notifyCompletion(ACCOUNT_TYPE, AuthenticatorTransferCompletionStatus.COMPLETED_SUCCESS)

Java

AccountTransferClient client = AccountTransfer.getAccountTransferClient(this);
Task<Void> transferTask = client.retrieveData(ACCOUNT_TYPE);
try {
  byte[] transferBytes = Tasks.await(transferTask, TIMEOUT_API, TIME_UNIT);
  // Add the transferred account(s) to AccountManager to register with the framework.
} catch (ExecutionException | InterruptedException | TimeoutException e) {
  client.notifyCompletion(ACCOUNT_TYPE, AuthenticatorTransferCompletionStatus.COMPLETED_FAILURE);
  return;
}
client.notifyCompletion(ACCOUNT_TYPE, AuthenticatorTransferCompletionStatus.COMPLETED_SUCCESS);

전송 완료

필요하다면 sendData()를 호출하여 대상 기기의 인증자 서비스에서 소스 기기로 다시 데이터를 전송할 수도 있습니다.

소스 기기에서 데이터를 수신하려면 인증자 서비스가 ACTION_ACCOUNT_EXPORT_DATA_AVAILABLE 브로드캐스트를 수신 대기해야 합니다. 마찬가지로 소스 기기의 인증자 서비스는 대상 기기에 추가 메시지를 전송할 수 있습니다.

전송이 완료되면 인증자 서비스는 적절한 완료 상태와 함께 notifyCompletion()을 호출해야 합니다.

추가 보안이 필요하다면 소스 또는 대상 기기에서 사용자에게 표시되는 인증 질문을 사용할 수 있습니다. 먼저 getDeviceMetaData()를 호출하고 결과를 검사하여 문제를 표시할 수 있는지 확인합니다. 대상 기기의 인증자 서비스가 보안 질문을 지원하면 showUserChallenge()를 호출하여 보안 질문을 표시합니다.

전송 시 필요한 인증자 서비스가 대상 기기에 설치되어 있지 않다면 시스템은 전송된 데이터를 임시 로컬 저장소에 저장합니다. 앱을 처음 설치해서 열 때 앱은 retrieveData()를 호출하여 임시 로컬 저장소에 사용 가능한 데이터가 있는지 확인할 수 있습니다. 사용 가능한 데이터가 있으면 Account Transfer API는 그 데이터를 반환하고 사용할 수 있는 데이터가 없으면 호출이 실패합니다. 임시 로컬 저장소에 사용할 수 있는 데이터가 없다면 데이터를 가져오려는 추가적인 시도가 실패할 수 있습니다. 실패할 수 있으므로 notifyCompletion()를 호출하지 마세요.

임시 로컬 저장소에 전송된 데이터를 저장하는 대상 기기 그림

그림 3. 필수 인증자 서비스가 대상 기기에 설치되어 있지 않으면 시스템은 전송된 데이터를 임시 로컬 저장소에 저장함

계정 전송 테스트

설정 마법사는 새 기기를 설정할 때 실행됩니다. 기기의 설정과 계정 전송을 테스트하기 위해 정기적으로 기기를 초기화하면 지루하고 시간이 오래 걸립니다. 대신, 설정 마법사 흐름의 하위 집합을 실행하여 한 기기에서 다른 기기로 사용자 계정을 전송하도록 테스트할 수 있습니다.

테스트를 시작하기 전에 최소한 하나의 맞춤 계정이 소스 기기에 있는지 확인해야 합니다. 또한 대상 기기가 맞춤 계정으로 로그인되지 않았는지 확인합니다. 설정 마법사를 실행할 때 이미 대상 기기가 맞춤 계정으로 로그인되어 있다면 시스템이 AccountManager.addAccountExplicitly() 메서드를 호출할 때 동일한 계정을 추가하려는 시도는 실패합니다.

테스트 목적이라면 Android 8.0(API 수준 26) 이상을 실행하는 기기를 대상 기기로 사용해야 합니다.

Android 4.0.1(API 수준 14) 이상 및 Google Play 서비스 버전 11.2.0 이상을 실행하는 기기를 소스 기기로 사용해야 합니다. 테스트할 APK를 빌드하려면 Google Play 서비스 SDK 버전 11.2.0 이상을 사용해야 합니다.

설정 마법사의 흐름을 테스트하려면 대상 기기에서 다음 명령어를 실행합니다.

$ adb shell am start -a android.intent.action.MAIN -n com.google.android.gms/.smartdevice.d2d.ui.TargetActivity

명령어는 활동을 시작하고 설정 마법사를 표시하여 테스트 기기와 다른 기기의 페어링을 준비합니다. 기기 연결이 설정된 후 계정 전송 프로세스를 시작할 수 있습니다.