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

يمكن للمستخدمين نسخ حسابات 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 في تطبيقك:

  • يجب أن يعمل الجهاز المصدر بنظام التشغيل Android 4.0.1 (المستوى 14 لواجهة برمجة التطبيقات) أو إصدارات أحدث.
  • يجب أن يعمل الجهاز المستهدف بالإصدار Android 8.0 (المستوى 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

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