إنشاء تطبيق مصادقة للكعب

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

حتى إذا كان تطبيقك لا يستخدم الحسابات، سيظل عليك توفير مكوّن مصادقة. إذا كنت لا تستخدم الحسابات أو تسجيل الدخول إلى الخادم، سيتم تجاهل المعلومات التي يعالجها برنامج المصادقة، وذلك حتى تتمكّن من توفير مكوّن مصادقة يتضمّن عمليات تنفيذ طريقة steb. وعليك أيضًا توفير Service مرتبط يسمح لإطار عمل محوِّل المزامنة باستدعاء طُرق برنامج المصادقة.

يشرح هذا الدرس كيفية تحديد جميع أجزاء برنامج مصادقة التردّدات التي تحتاجها لاستيفاء متطلبات إطار عمل محوّل المزامنة. إذا كنت بحاجة إلى توفير برنامج مصادقة حقيقي يتولّى معالجة حسابات المستخدمين، يُرجى قراءة المستندات المرجعية حول AbstractAccountAuthenticator.

إضافة مكوِّن مصادقة التنويع الموجز

لإضافة مكوِّن مصادقة بيانات غير مرغوب فيها إلى تطبيقك، أنشِئ فئة تتضمّن AbstractAccountAuthenticator، ثم استبعِد الطرق المطلوبة، إما عن طريق عرض علامة null أو عن طريق طرح استثناء.

يعرض المقتطف التالي مثالاً لفئة مصادقة بيانات التوكيد:

Kotlin

/*
 * Implement AbstractAccountAuthenticator and stub out all
 * of its methods
 */
class Authenticator(context: Context) // Simple constructor
    : AbstractAccountAuthenticator(context) {

    // Editing properties is not supported
    override fun editProperties(r: AccountAuthenticatorResponse, s: String): Bundle {
        throw UnsupportedOperationException()
    }

    // Don't add additional accounts
    @Throws(NetworkErrorException::class)
    override fun addAccount(
            r: AccountAuthenticatorResponse,
            s: String,
            s2: String,
            strings: Array<String>,
            bundle: Bundle
    ): Bundle?  = null

    // Ignore attempts to confirm credentials
    @Throws(NetworkErrorException::class)
    override fun confirmCredentials(
            r: AccountAuthenticatorResponse,
            account: Account,
            bundle: Bundle
    ): Bundle?  = null

    // Getting an authentication token is not supported
    @Throws(NetworkErrorException::class)
    override fun getAuthToken(
            r: AccountAuthenticatorResponse,
            account: Account,
            s: String,
            bundle: Bundle
    ): Bundle {
        throw UnsupportedOperationException()
    }

    // Getting a label for the auth token is not supported
    override fun getAuthTokenLabel(s: String): String {
        throw UnsupportedOperationException()
    }

    // Updating user credentials is not supported
    @Throws(NetworkErrorException::class)
    override fun updateCredentials(
            r: AccountAuthenticatorResponse,
            account: Account,
            s: String,
            bundle: Bundle
    ): Bundle {
        throw UnsupportedOperationException()
    }

    // Checking features for the account is not supported
    @Throws(NetworkErrorException::class)
    override fun hasFeatures(
            r: AccountAuthenticatorResponse,
            account: Account,
            strings: Array<String>
    ): Bundle {
        throw UnsupportedOperationException()
    }
}

Java

/*
 * Implement AbstractAccountAuthenticator and stub out all
 * of its methods
 */
public class Authenticator extends AbstractAccountAuthenticator {
    // Simple constructor
    public Authenticator(Context context) {
        super(context);
    }
    // Editing properties is not supported
    @Override
    public Bundle editProperties(
            AccountAuthenticatorResponse r, String s) {
        throw new UnsupportedOperationException();
    }
    // Don't add additional accounts
    @Override
    public Bundle addAccount(
            AccountAuthenticatorResponse r,
            String s,
            String s2,
            String[] strings,
            Bundle bundle) throws NetworkErrorException {
        return null;
    }
    // Ignore attempts to confirm credentials
    @Override
    public Bundle confirmCredentials(
            AccountAuthenticatorResponse r,
            Account account,
            Bundle bundle) throws NetworkErrorException {
        return null;
    }
    // Getting an authentication token is not supported
    @Override
    public Bundle getAuthToken(
            AccountAuthenticatorResponse r,
            Account account,
            String s,
            Bundle bundle) throws NetworkErrorException {
        throw new UnsupportedOperationException();
    }
    // Getting a label for the auth token is not supported
    @Override
    public String getAuthTokenLabel(String s) {
        throw new UnsupportedOperationException();
    }
    // Updating user credentials is not supported
    @Override
    public Bundle updateCredentials(
            AccountAuthenticatorResponse r,
            Account account,
            String s, Bundle bundle) throws NetworkErrorException {
        throw new UnsupportedOperationException();
    }
    // Checking features for the account is not supported
    @Override
    public Bundle hasFeatures(
        AccountAuthenticatorResponse r,
        Account account, String[] strings) throws NetworkErrorException {
        throw new UnsupportedOperationException();
    }
}

ربط برنامج المصادقة بإطار العمل

للتمكّن من وصول إطار عمل محوّل المزامنة إلى برنامج المصادقة، يجب إنشاء خدمة مرتبطة به. توفّر هذه الخدمة عنصر ربط على Android يسمح لإطار العمل بطلب برنامج المصادقة وتمرير البيانات بين برنامج المصادقة وإطار العمل.

يوضّح لك المقتطف التالي كيفية تحديد Service المرتبط:

Kotlin

/**
* A bound Service that instantiates the authenticator
* when started.
*/
class AuthenticatorService : Service() {

    // Instance field that stores the authenticator object
    private lateinit var mAuthenticator: Authenticator

    override fun onCreate() {
        // Create a new authenticator object
        mAuthenticator = Authenticator(getApplicationContext())
    }

    /*
     * When the system binds to this Service to make the RPC call
     * return the authenticator's IBinder.
     */
    override fun onBind(intent: Intent?): IBinder = mAuthenticator.iBinder
}

Java

/**
 * A bound Service that instantiates the authenticator
 * when started.
 */
public class AuthenticatorService extends Service {
    ...
    // Instance field that stores the authenticator object
    private Authenticator mAuthenticator;
    @Override
    public void onCreate() {
        // Create a new authenticator object
        mAuthenticator = new Authenticator(getApplicationContext());
    }
    /*
     * When the system binds to this Service to make the RPC call
     * return the authenticator's IBinder.
     */
    @Override
    public IBinder onBind(Intent intent) {
        return mAuthenticator.getIBinder();
    }
}

إضافة ملف البيانات الوصفية لأداة المصادقة

لتوصيل مكوّن المصادقة بإطارَي عمل الحساب ومحوّل المزامنة، يجب تزويد إطار العمل هذا ببيانات وصفية تصف المكوّن. تشير هذه البيانات الوصفية إلى نوع الحساب الذي أنشأته لمحوّل المزامنة وتوضّح عناصر واجهة المستخدم التي يعرضها النظام إذا كنت تريد إظهار نوع حسابك للمستخدم. يُرجى تعريف هذه البيانات الوصفية في ملف XML مخزَّن في دليل /res/xml/ في مشروع تطبيقك. يمكنك تسمية الملف بأي اسم، على الرغم من أن هذا الاسم عادةً ما يكون authenticator.xml.

يحتوي ملف XML هذا على عنصر <account-authenticator> واحد يتضمّن السمات التالية:

android:accountType
يتطلّب إطار عمل محوّل المزامنة أن يكون لكل محوّل مزامنة نوع حساب، على شكل اسم نطاق. ويستخدم إطار العمل نوع الحساب كجزء من التعريف الداخلي لمحوّل المزامنة. بالنسبة إلى الخوادم التي تتطلب تسجيل الدخول، يتم إرسال نوع الحساب مع حساب المستخدم إلى الخادم كجزء من بيانات اعتماد تسجيل الدخول.

إذا كان الخادم لا يتطلب تسجيل الدخول، لا يزال عليك تقديم نوع الحساب. بالنسبة إلى القيمة، استخدِم اسم نطاق تتحكم فيه. ومع أنّ إطار العمل يستخدمه لإدارة محوّل المزامنة، لا يتم إرسال القيمة إلى الخادم.

android:icon
أشِر إلى مورد قابل للرسم يحتوي على رمز. إذا جعلت محوّل المزامنة مرئيًا من خلال تحديد السمة android:userVisible="true" في res/xml/syncadapter.xml، يجب تقديم مورد الرمز هذا. يظهر هذا الحساب في قسم الحسابات ضمن تطبيق "الإعدادات" على النظام.
android:smallIcon
أشِر إلى مورد قابل للرسم يحتوي على نسخة صغيرة من الرمز. يمكن استخدام هذا المورد بدلاً من android:icon في قسم الحسابات ضمن تطبيق "الإعدادات" بالنظام بناءً على حجم الشاشة.
android:label
سلسلة قابلة للترجمة تحدد نوع الحساب للمستخدمين. إذا جعلت محوّل المزامنة مرئيًا من خلال تحديد السمة android:userVisible="true" في res/xml/syncadapter.xml، عليك تقديم هذه السلسلة. ويظهر في قسم الحسابات ضمن تطبيق الإعدادات في النظام، بجانب الرمز الذي تحدّده لأداة المصادقة.

يعرض المقتطف التالي ملف XML لبرنامج المصادقة الذي أنشأته سابقًا:

<?xml version="1.0" encoding="utf-8"?>
<account-authenticator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:accountType="example.com"
        android:icon="@drawable/ic_launcher"
        android:smallIcon="@drawable/ic_launcher"
        android:label="@string/app_name"/>

تعريف برنامج المصادقة في البيان

في خطوة سابقة، أنشأت Service مرتبط يربط برنامج المصادقة بإطار عمل محوّل المزامنة. لتعريف النظام بهذه الخدمة، يجب تعريفها في بيان التطبيق عن طريق إضافة عنصر <service> التالي كعنصر ثانوي في <application>:

    <service
            android:name="com.example.android.syncadapter.AuthenticatorService">
        <intent-filter>
            <action android:name="android.accounts.AccountAuthenticator"/>
        </intent-filter>
        <meta-data
            android:name="android.accounts.AccountAuthenticator"
            android:resource="@xml/authenticator" />
    </service>

يضبط العنصر <intent-filter> فلترًا يتم تشغيله من خلال إجراء الغرض android.accounts.AccountAuthenticator، والذي يرسله النظام لتشغيل برنامج المصادقة. عند تشغيل الفلتر، يبدأ النظام في تشغيل AuthenticatorService، أي قيمة Service المرتبطة التي قدّمتها لالتفاف أداة المصادقة.

يعلن العنصر <meta-data> عن البيانات الوصفية لبرنامج المصادقة. وتربط السمة android:nameالبيانات الوصفية بإطار عمل المصادقة. يحدد العنصر android:resource اسم ملف البيانات الوصفية لأداة المصادقة الذي أنشأته سابقًا.

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