واجهة برمجة التطبيقات لنقل الحسابات

يمكن للمستخدمين نسخ حسابات Google وبياناتها من جهاز حالي يعمل بنظام التشغيل Android إلى جهاز جديد يعمل بنظام التشغيل Android باستخدام النقر والذهاب. استخدِم واجهة برمجة تطبيقات "نقل الحساب" للسماح للمستخدمين أيضًا بنسخ بيانات اعتماد الحسابات المخصّصة التي تم تنفيذها باستخدام AbstractAccountAuthenticator والمدمجة مع AccountManager. يستدعي النظام واجهة برمجة التطبيقات Account Transfer API من معالج إعداد Tap & Go الذي يعمل على الجهاز الجديد. يستدعي النظام أيضًا Account Transfer API لنقل البيانات من هاتف Android إلى هاتف Pixel باستخدام الكابل.

شاشة الترحيب بالنقر والذهاب شاشة "النقر والانتقال" لتحديد مصدر بيانات

الشكل 1. يتم استدعاء Account Transfer API من معالج إعداد Tap & Go الذي يعمل على جهاز جديد.

لإتاحة إمكانية نقل الحسابات المخصّصة، يجب دمج واجهة برمجة التطبيقات Account Transfer في تطبيقك. ويمكن لـ "خدمات Google Play" بعد ذلك إنشاء قناة مشفّرة ثنائية الاتجاه بين الجهاز الحالي، الذي يُعرف أيضًا باسم الجهاز المصدر، والجهاز الجديد، الذي يُعرف أيضًا باسم الجهاز المستهدف، لنقل بيانات الحساب، كما هو موضّح في الشكل 2. لا تعتمد القناة المشفرة على الاتصال بخوادم تابعة لجهات خارجية لإكمال عملية النقل.

يجب مراعاة المتطلبات التالية عند دمج واجهة برمجة التطبيقات Account Transfer API في تطبيقك:

  • يجب أن يعمل الجهاز المصدر بالإصدار 4.0.1 من نظام التشغيل Android (المستوى 14 لواجهة برمجة التطبيقات) أو بإصدار أحدث.
  • يجب أن يعمل الجهاز المستهدف بالإصدار 8.0 من نظام التشغيل Android (المستوى 26 لواجهة برمجة التطبيقات) أو بإصدار أحدث.
  • يجب أن يستخدم كل من الأجهزة المصدر والهدف الإصدار 11.2.0 أو الإصدارات الأحدث من "خدمات Google Play".
  • يجب عليك إنشاء تطبيقك باستخدام الإصدار 11.2.0 أو الإصدارات الأحدث من حزمة SDK لخدمات Google Play.

صورة توضيحية تُظهر عملية نقل الحساب من الجهاز المصدر إلى الجهاز المستهدَف

الشكل 2. وتتم عملية النقل عبر قناة مشفّرة تنشئها "خدمات Google Play" بين الأجهزة المصدر والهدف.

إضافة واجهة برمجة التطبيقات Account Transfer API إلى مشروعك

لاستخدام واجهة برمجة التطبيقات Account Transfer API في مشروعك، عليك أولاً إعداد مشروعك باستخدام حزمة SDK لخدمات Google Play. للحصول على تعليمات تفصيلية حول إعداد حزمة SDK لخدمات Google Play، يُرجى الاطّلاع على إعداد خدمات Google Play.

إذا أردت تجميع Google Account Transfer API بشكل انتقائي في تطبيقك، أضِف قاعدة التصميم التالية إلى المجموعة dependencies في ملف build.gradle ضِمن دليل وحدة التطبيق:

رائع

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>

إذا لم يكن تطبيقك مثبّتًا في صورة نظام المصنّع الأصلي للجهاز ولا تريد وضعه في صورة نظام المصنّع الأصلي للجهاز، تأكَّد من التسجيل للاستماع إلى بث ACTION_START_ACCOUNT_EXPORT على الجهاز المصدر لتصدير بيانات الحساب كما هو موضّح أعلاه.

إذا ثبّت التطبيق على صورة نظام مُصنّع أصلي، عليك أيضًا التسجيل في عمليات البث التالية:

نقل بيانات الحساب

بعد أن يختار المستخدم استعادة المحتوى من جهازه الحالي، يُرسِل النظام بث ACTION_START_ACCOUNT_EXPORT إلى الحِزم المرتبطة بالحسابات ذات الصلة على الجهاز المصدر.

إرسال بيانات الحساب

لإرسال بيانات الحساب، ابدأ خدمة المصادقة على الجهاز المصدر واتصل sendData() بعد أن تتلقّى الخدمة بث ACTION_START_ACCOUNT_EXPORT. يمكنك الحصول على إشارة إلى عنصر AccountTransferClient من خلال طلب إما getAccountTransferClient(Context) أو getAccountTransferClient(Activity). يوضِّح مقتطف الرمز التالي كيفية إرسال البيانات من الجهاز المصدر:

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 (المستوى 26 من واجهة برمجة التطبيقات) أو إصدار أحدث كجهاز مستهدف.

يمكنك استخدام جهاز يعمل بالإصدار 4.0.1 من نظام التشغيل Android (المستوى 14 لواجهة برمجة التطبيقات) أو بإصدار أحدث، بالإضافة إلى الإصدار 11.2.0 من "خدمات Google Play" أو الإصدارات الأحدث، كجهاز مصدر. لإنشاء ملف APK الذي تختبره، يجب استخدام الإصدار 11.2.0 من حزمة SDK لخدمات Google Play أو إصدار أحدث.

لاختبار مسار معالج الإعداد، شغِّل الأمر التالي على جهازك المستهدف:

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

يؤدي الأمر إلى بدء نشاط وعرض معالج الإعداد، وهو جاهز لإقران جهاز الاختبار بجهاز آخر. بعد إنشاء الأجهزة للاتصال، يمكنك بدء عملية نقل الحساب.