Account Transfer API

使用者可以利用一觸即通功能,將 Google 帳戶和資料從現有的 Android 裝置複製到新的 Android 裝置。使用 Account Transfer API,讓使用者也能複製使用 AbstractAccountAuthenticator 實作的自訂帳戶憑證,並與 AccountManager 整合。系統會透過新裝置上執行的「一觸即通」設定精靈叫用 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 廣播接收器:

<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

這個指令會啟動活動並顯示設定精靈,準備將測試裝置與另一部裝置配對。裝置之間建立連線後,您就可以開始進行帳戶轉移程序。