إنشاء محوّل مزامنة

ملاحظة: ننصح باستخدام WorkManager كحلّ مقترَح لمعظم حالات استخدام المعالجة في الخلفية. يُرجى الرجوع إلى دليل المعالجة في الخلفية لمعرفة الحلّ الأنسب لك.

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

فئة محوِّل المزامنة.
فئة تتضمن رمز نقل البيانات في واجهة متوافقة مع إطار عمل محوّل المزامنة.
يجب أن تكون القيمة مرتبطة بـ Service.
مكوِّن يسمح لإطار عمل محوّل المزامنة بتشغيل الرمز في فئة محوِّل المزامنة.
ملف البيانات الوصفية بتنسيق XML لمحوّل المزامنة.
ملف يحتوي على معلومات عن محوّل المزامنة. يقرأ إطار العمل هذا الملف لمعرفة كيفية تحميل عملية نقل البيانات وجدولتها.
نماذج البيان في بيان التطبيق
ملف XML الذي يوضِّح الخدمة المرتبطة ويوجّه البيانات الوصفية الخاصة بالمحوّل.

يوضح لك هذا الدرس كيفية تحديد هذه العناصر.

إنشاء فئة لمحوّل المزامنة

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

تمديد فئة محوِّل المزامنة الأساسية

لإنشاء مكوِّن محوِّل المزامنة، ابدأ بتوسيع AbstractThreadedSyncAdapter وكتابة التركيبات البرمجية له. يمكنك استخدام البُنى الإنشائية لتشغيل مهام الإعداد في كل مرة يتم فيها إنشاء مكوّن محوِّل المزامنة من البداية، تمامًا مثلما تستخدم Activity.onCreate() لإعداد نشاط. على سبيل المثال، إذا كان تطبيقك يستخدم موفّر محتوى لتخزين البيانات، استخدِم المنشئات للحصول على مثيل ContentResolver. بما أنّه تمت إضافة نموذج ثانٍ من الدالة الإنشائية إلى الإصدار 3.0 من نظام Android الأساسي لإتاحة الوسيطة parallelSyncs، عليك إنشاء شكلَين من الدالة الإنشائية للحفاظ على التوافق.

ملاحظة: تم تصميم إطار عمل محوِّل المزامنة للعمل مع مكوّنات محوِّلات المزامنة التي تمثّل مثيلات فردية. ويتضمّن القسم ربط محوِّل المزامنة بإطار العمل مزيدًا من التفاصيل عن إنشاء مثيل مكوّن محوِّل المزامنة.

يوضِّح لك المثال التالي كيفية تطبيق السمة AbstractThreadedSyncAdapterووجهات إنشاءها:

Kotlin

/**
 * Handle the transfer of data between a server and an
 * app, using the Android sync adapter framework.
 */
class SyncAdapter @JvmOverloads constructor(
        context: Context,
        autoInitialize: Boolean,
        /**
         * Using a default argument along with @JvmOverloads
         * generates constructor for both method signatures to maintain compatibility
         * with Android 3.0 and later platform versions
         */
        allowParallelSyncs: Boolean = false,
        /*
         * If your app uses a content resolver, get an instance of it
         * from the incoming Context
         */
        val mContentResolver: ContentResolver = context.contentResolver
) : AbstractThreadedSyncAdapter(context, autoInitialize, allowParallelSyncs) {
    ...
}

Java

/**
 * Handle the transfer of data between a server and an
 * app, using the Android sync adapter framework.
 */
public class SyncAdapter extends AbstractThreadedSyncAdapter {
    ...
    // Global variables
    // Define a variable to contain a content resolver instance
    ContentResolver contentResolver;
    /**
     * Set up the sync adapter
     */
    public SyncAdapter(Context context, boolean autoInitialize) {
        super(context, autoInitialize);
        /*
         * If your app uses a content resolver, get an instance of it
         * from the incoming Context
         */
        contentResolver = context.getContentResolver();
    }
    ...
    /**
     * Set up the sync adapter. This form of the
     * constructor maintains compatibility with Android 3.0
     * and later platform versions
     */
    public SyncAdapter(
            Context context,
            boolean autoInitialize,
            boolean allowParallelSyncs) {
        super(context, autoInitialize, allowParallelSyncs);
        /*
         * If your app uses a content resolver, get an instance of it
         * from the incoming Context
         */
        contentResolver = context.getContentResolver();
        ...
    }

إضافة رمز نقل البيانات

لا يجري مكوّن محوّل المزامنة نقل البيانات تلقائيًا. وبدلاً من ذلك، يتم تضمين رمز نقل البيانات لكي يتمكّن إطار عمل محوّل المزامنة من تنفيذ عملية نقل البيانات في الخلفية بدون أي تدخّل من تطبيقك. وعندما يكون إطار العمل جاهزًا لمزامنة بيانات تطبيقك، يستدعي تنفيذ الطريقة onPerformSync().

لتسهيل نقل البيانات من رمز التطبيق الرئيسي إلى مكوّن محوِّل المزامنة، يطلب إطار عمل محوِّل المزامنة onPerformSync() مع الوسيطات التالية:

الحساب
عنصر Account مرتبط بالحدث الذي أدّى إلى تشغيل محوّل المزامنة. إذا كان خادمك لا يستخدم الحسابات، لن تحتاج إلى استخدام المعلومات في هذا الكائن.
محتوى إضافي
Bundle يحتوي على علامات تم إرسالها من خلال الحدث الذي أدّى إلى تشغيل محوِّل المزامنة.
الجهة
تفويض موفّر المحتوى في النظام يجب أن يتمكن تطبيقك من الوصول إلى مقدّم الخدمة هذا. عادةً ما تتوافق السلطة مع موفّر المحتوى في تطبيقك.
عميل موفّر المحتوى
العلامة ContentProviderClient لموفّر المحتوى المُشار إليها من خلال وسيطة المرجع. ContentProviderClient هي واجهة بسيطة وعامة لموفّر محتوى. ويشتمل على الوظائف الأساسية نفسها التي يتضمّنها ContentResolver. إذا كنت تستخدم موفّر محتوى لتخزين بيانات تطبيقك، يمكنك الاتصال بالموفّر باستخدام هذا الكائن. وبخلاف ذلك، يمكنك تجاهله.
نتيجة المزامنة
عنصر SyncResult تستخدمه لإرسال المعلومات إلى إطار عمل محوّل المزامنة.

يعرض المقتطف التالي البنية العامة للسمة onPerformSync():

Kotlin

/*
 * Specify the code you want to run in the sync adapter. The entire
 * sync adapter runs in a background thread, so you don't have to set
 * up your own background processing.
 */
override fun onPerformSync(
        account: Account,
        extras: Bundle,
        authority: String,
        provider: ContentProviderClient,
        syncResult: SyncResult
) {
    /*
     * Put the data transfer code here.
     */
}

Java

/*
 * Specify the code you want to run in the sync adapter. The entire
 * sync adapter runs in a background thread, so you don't have to set
 * up your own background processing.
 */
@Override
public void onPerformSync(
        Account account,
        Bundle extras,
        String authority,
        ContentProviderClient provider,
        SyncResult syncResult) {
    /*
     * Put the data transfer code here.
     */
}

مع أنّ التنفيذ الفعلي لـ onPerformSync() يقتصر على متطلبات مزامنة البيانات في تطبيقك وبروتوكولات الاتصال بالخادم، هناك بعض المهام العامة التي يجب أن تؤديها عملية التنفيذ:

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

ملاحظة: يعمل إطار عمل محوّل المزامنة على تشغيل onPerformSync() على سلسلة محادثات في الخلفية، لذلك لن تحتاج إلى إعداد إعدادات المعالجة في الخلفية بنفسك.

بالإضافة إلى المهام ذات الصلة بالمزامنة، يجب محاولة دمج المهام العادية المرتبطة بالشبكة وإضافتها إلى "onPerformSync()". ومن خلال تركيز جميع مهام الشبكة على هذه الطريقة، يتم توفير طاقة البطارية اللازمة لبدء تشغيل واجهات الشبكة وإيقافها. لمعرفة مزيد من المعلومات حول تعزيز كفاءة الوصول إلى الشبكة، راجِع فئة التدريب نقل البيانات بدون استنزاف البطارية التي تصف العديد من مهام الوصول إلى الشبكة التي يمكنك تضمينها في رمز نقل البيانات.

ربط محوِّل المزامنة بإطار العمل

لديك الآن رمز نقل البيانات مضمَّن في مكوّن محوِّل المزامنة، ولكن عليك منح إطار العمل إمكانية الوصول إلى الرمز. لإجراء ذلك، عليك إنشاء Service مرتبط يمرّر كائن مجلد Android خاصًا من مكوّن محوِّل المزامنة إلى إطار العمل. باستخدام كائن الصنف Binder هذا، يمكن لإطار العمل استدعاء طريقة onPerformSync() وتمرير البيانات إليها.

إنشاء مثيل لمكوِّن محوِّل المزامنة كوحدة مفردة في طريقة onCreate() للخدمة. من خلال إنشاء مثيل للمكوِّن في onCreate()، يمكنك تأجيل إنشائه حتى بدء الخدمة، ويحدث ذلك عندما يحاول إطار العمل نقل البيانات للمرة الأولى. تحتاج إلى إنشاء مثيل للمكوِّن بطريقة آمنة لسلسلة المحادثات، إذا كان إطار عمل محوِّل المزامنة يضع عمليات تنفيذ متعددة لمحوِّل المزامنة استجابةً للعوامل المُشغِّلة أو الجدولة.

على سبيل المثال، يوضّح لك المقتطف التالي طريقة إنشاء فئة تطبّق Service المرتبط، وتنشئ مثيلاً لمكوِّن محوِّل المزامنة، وتحصل على كائن برنامج الربط على Android:

Kotlin

package com.example.android.syncadapter
/**
 * Define a Service that returns an [android.os.IBinder] for the
 * sync adapter class, allowing the sync adapter framework to call
 * onPerformSync().
 */
class SyncService : Service() {
    /*
     * Instantiate the sync adapter object.
     */
    override fun onCreate() {
        /*
         * Create the sync adapter as a singleton.
         * Set the sync adapter as syncable
         * Disallow parallel syncs
         */
        synchronized(sSyncAdapterLock) {
            sSyncAdapter = sSyncAdapter ?: SyncAdapter(applicationContext, true)
        }
    }

    /**
     * Return an object that allows the system to invoke
     * the sync adapter.
     *
     */
    override fun onBind(intent: Intent): IBinder {
        /*
         * Get the object that allows external processes
         * to call onPerformSync(). The object is created
         * in the base class code when the SyncAdapter
         * constructors call super()
         *
         * We should never be in a position where this is called before
         * onCreate() so the exception should never be thrown
         */
        return sSyncAdapter?.syncAdapterBinder ?: throw IllegalStateException()
    }

    companion object {
        // Storage for an instance of the sync adapter
        private var sSyncAdapter: SyncAdapter? = null
        // Object to use as a thread-safe lock
        private val sSyncAdapterLock = Any()
    }
}

Java

package com.example.android.syncadapter;
/**
 * Define a Service that returns an <code><a href="/reference/android/os/IBinder.html">IBinder</a></code> for the
 * sync adapter class, allowing the sync adapter framework to call
 * onPerformSync().
 */
public class SyncService extends Service {
    // Storage for an instance of the sync adapter
    private static SyncAdapter sSyncAdapter = null;
    // Object to use as a thread-safe lock
    private static final Object sSyncAdapterLock = new Object();
    /*
     * Instantiate the sync adapter object.
     */
    @Override
    public void onCreate() {
        /*
         * Create the sync adapter as a singleton.
         * Set the sync adapter as syncable
         * Disallow parallel syncs
         */
        synchronized (sSyncAdapterLock) {
            if (sSyncAdapter == null) {
                sSyncAdapter = new SyncAdapter(getApplicationContext(), true);
            }
        }
    }
    /**
     * Return an object that allows the system to invoke
     * the sync adapter.
     *
     */
    @Override
    public IBinder onBind(Intent intent) {
        /*
         * Get the object that allows external processes
         * to call onPerformSync(). The object is created
         * in the base class code when the SyncAdapter
         * constructors call super()
         */
        return sSyncAdapter.getSyncAdapterBinder();
    }
}

ملاحظة: للاطّلاع على مثال أكثر تفصيلاً على خدمة مرتبطة لمحوّل مزامنة، يُرجى الاطّلاع على نموذج التطبيق.

إضافة الحساب الذي يتطلبه إطار العمل

يتطلب إطار عمل محوّل المزامنة أن يكون لكل محوّل مزامنة نوع حساب. لقد أعلنت قيمة نوع الحساب في القسم إضافة ملف البيانات الوصفية لأداة المصادقة. عليك الآن إعداد نوع الحساب هذا في نظام Android. لإعداد نوع الحساب، أضِف حسابًا نائبًا يستخدم نوع الحساب من خلال طلب الرقم addAccountExplicitly().

وأفضل مكان لاستدعاء الطريقة هو طريقة onCreate() لنشاط فتح تطبيقك. ويوضح مقتطف الرمز التالي كيفية إجراء ذلك:

Kotlin

...
// Constants
// The authority for the sync adapter's content provider
const val AUTHORITY = "com.example.android.datasync.provider"
// An account type, in the form of a domain name
const val ACCOUNT_TYPE = "example.com"
// The account name
const val ACCOUNT = "placeholderaccount"
...
class MainActivity : FragmentActivity() {

    // Instance fields
    private lateinit var mAccount: Account
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
       ...
        // Create the placeholder account
        mAccount = createSyncAccount()
       ...
    }
    ...
    /**
     * Create a new placeholder account for the sync adapter
     */
    private fun createSyncAccount(): Account {
        val accountManager = getSystemService(Context.ACCOUNT_SERVICE) as AccountManager
        return Account(ACCOUNT, ACCOUNT_TYPE).also { newAccount ->
            /*
             * Add the account and account type, no password or user data
             * If successful, return the Account object, otherwise report an error.
             */
            if (accountManager.addAccountExplicitly(newAccount, null, null)) {
                /*
                 * If you don't set android:syncable="true" in
                 * in your <provider> element in the manifest,
                 * then call context.setIsSyncable(account, AUTHORITY, 1)
                 * here.
                 */
            } else {
                /*
                 * The account exists or some other error occurred. Log this, report it,
                 * or handle it internally.
                 */
            }
        }
    }
    ...
}

Java

public class MainActivity extends FragmentActivity {
    ...
    ...
    // Constants
    // The authority for the sync adapter's content provider
    public static final String AUTHORITY = "com.example.android.datasync.provider";
    // An account type, in the form of a domain name
    public static final String ACCOUNT_TYPE = "example.com";
    // The account name
    public static final String ACCOUNT = "placeholderaccount";
    // Instance fields
    Account mAccount;
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        // Create the placeholder account
        mAccount = CreateSyncAccount(this);
        ...
    }
    ...
    /**
     * Create a new placeholder account for the sync adapter
     *
     * @param context The application context
     */
    public static Account CreateSyncAccount(Context context) {
        // Create the account type and default account
        Account newAccount = new Account(
                ACCOUNT, ACCOUNT_TYPE);
        // Get an instance of the Android account manager
        AccountManager accountManager =
                (AccountManager) context.getSystemService(
                        ACCOUNT_SERVICE);
        /*
         * Add the account and account type, no password or user data
         * If successful, return the Account object, otherwise report an error.
         */
        if (accountManager.addAccountExplicitly(newAccount, null, null)) {
            /*
             * If you don't set android:syncable="true" in
             * in your <provider> element in the manifest,
             * then call context.setIsSyncable(account, AUTHORITY, 1)
             * here.
             */
        } else {
            /*
             * The account exists or some other error occurred. Log this, report it,
             * or handle it internally.
             */
        }
    }
    ...
}

إضافة ملف البيانات الوصفية لمحوّل المزامنة

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

يحتوي ملف XML هذا على عنصر XML واحد <sync-adapter> يحتوي على السمات التالية:

android:contentAuthority
مرجع معرّف الموارد المنتظم (URI) لموفّر المحتوى إذا أنشأت موفّر محتوى الترنات الخاملة لتطبيقك في الدرس السابق إنشاء موفِّر محتوى صور غير مرغوب فيها، استخدِم القيمة التي حددتها للسمة android:authorities في العنصر <provider> الذي أضفته إلى بيان التطبيق. يتم توضيح هذه السمة بمزيد من التفصيل في القسم تعريف الموفّر في البيان.
في حال نقل البيانات من موفّر محتوى إلى خادم يحتوي على محوّل المزامنة، يجب أن تكون هذه القيمة مطابقة لمرجع معرّف الموارد المنتظم للمحتوى الذي تستخدمه لهذه البيانات. هذه القيمة هي أيضًا إحدى القيم المرجعية التي تحدّدها في السمة android:authorities في العنصر <provider>، والتي تشير إلى مقدّم الخدمة في بيان التطبيق.
android:accountType
نوع الحساب الذي يطلبه إطار عمل محوّل المزامنة. يجب أن تكون القيمة هي نفسها قيمة نوع الحساب التي قدّمتها عند إنشاء ملف البيانات الوصفية لأداة المصادقة، كما هو موضّح في القسم إضافة ملف البيانات الوصفية لأداة المصادقة. وهي أيضًا القيمة التي حدّدتها لـ ACCOUNT_TYPE الثابت في مقتطف الرمز في القسم إضافة الحساب مطلوب بواسطة إطار العمل.
سمات الإعدادات
android:userVisible
لضبط إذن الوصول إلى نوع حساب محوِّل المزامنة. بشكل تلقائي، يظهر رمز الحساب وتصنيفه المرتبطان بنوع الحساب في قسم الحسابات في تطبيق إعدادات النظام، لذا يجب أن تجعل محوّل المزامنة غير مرئي ما لم يكن لديك نوع حساب أو نطاق يمكن ربطه بسهولة بتطبيقك. وإذا أخفيت نوع حسابك غير المرئي، سيظل بإمكانك السماح للمستخدمين بالتحكّم في محوّل المزامنة من خلال واجهة مستخدم في أحد أنشطة تطبيقك.
android:supportsUploading
يتيح لك تحميل البيانات إلى السحابة الإلكترونية. يجب ضبط القيمة على false إذا كان تطبيقك ينزّل البيانات فقط.
android:allowParallelSyncs
يسمح بتشغيل نُسخ متعددة من مكوّن محوِّل المزامنة في الوقت نفسه. استخدِم هذا الخيار إذا كان تطبيقك يتيح استخدام حسابات مستخدمين متعددة وكنت تريد السماح لعدة مستخدمين بنقل البيانات بالتوازي. ليس لهذه العلامة أي تأثير في حال عدم تنفيذ عدة عمليات نقل بيانات مطلقًا.
android:isAlwaysSyncable
تشير إلى إطار عمل محوّل المزامنة الذي يمكنه تشغيل محوّل المزامنة في أي وقت تحدّده. إذا كنت تريد التحكم آليًا في وقت تشغيل محوّل المزامنة، اضبط هذه العلامة على false، ثم اطلب requestSync() لتشغيل محوّل المزامنة. لمعرفة المزيد من المعلومات حول تشغيل محوِّل المزامنة، يُرجى الاطّلاع على الدرس تشغيل محوِّل المزامنة

يوضّح المثال التالي ملف XML لمحوّل مزامنة يستخدم حسابًا واحدًا نائبًا ويُجري عمليات التنزيل فقط.

<?xml version="1.0" encoding="utf-8"?>
<sync-adapter
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:contentAuthority="com.example.android.datasync.provider"
        android:accountType="com.android.example.datasync"
        android:userVisible="false"
        android:supportsUploading="false"
        android:allowParallelSyncs="false"
        android:isAlwaysSyncable="true"/>

تعريف محوِّل المزامنة في البيان

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

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

لطلب هذه الأذونات، أضِف ما يلي إلى بيان التطبيق كعناصر فرعية من <manifest>:

android.permission.INTERNET
يسمح هذا الإذن لرمز محول المزامنة بالوصول إلى الإنترنت حتى يتمكّن من تنزيل البيانات أو تحميلها من الجهاز إلى خادم. ولن تحتاج إلى إضافة هذا الإذن مرة أخرى إذا كنت تطلبه في السابق.
android.permission.READ_SYNC_SETTINGS
يسمح هذا الإذن لتطبيقك بقراءة الإعدادات الحالية لمحوّل المزامنة. على سبيل المثال، يجب أن يكون لديك هذا الإذن لطلب الاتصال بـ getIsSyncable().
android.permission.WRITE_SYNC_SETTINGS
يسمح هذا الإذن للتطبيق بالتحكّم في إعدادات محوّل المزامنة. عليك الحصول على هذا الإذن لضبط عمليات تشغيل محوّل المزامنة الدورية باستخدام addPeriodicSync(). هذا الإذن غير مطلوب لاستدعاء "requestSync()". لمعرفة المزيد من المعلومات حول تشغيل محوِّل المزامنة، يُرجى الاطّلاع على تشغيل محوِّل المزامنة.

ويوضّح المقتطف التالي كيفية إضافة الأذونات:

<manifest>
...
    <uses-permission
            android:name="android.permission.INTERNET"/>
    <uses-permission
            android:name="android.permission.READ_SYNC_SETTINGS"/>
    <uses-permission
            android:name="android.permission.WRITE_SYNC_SETTINGS"/>
    <uses-permission
            android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
...
</manifest>

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

        <service
                android:name="com.example.android.datasync.SyncService"
                android:exported="false"
                android:process=":sync">
            <intent-filter>
                <action android:name="android.content.SyncAdapter"/>
            </intent-filter>
            <meta-data android:name="android.content.SyncAdapter"
                    android:resource="@xml/syncadapter" />
        </service>

يُعدّ العنصر <intent-filter> فلترًا يتم تشغيله من خلال إجراء الغرض android.content.SyncAdapter، ويرسله النظام لتشغيل محوّل المزامنة. عند تشغيل الفلتر، يبدأ النظام خدمة الربط التي أنشأتها، وهي الخدمة SyncService في هذا المثال. تسمح السمة android:exported="false" لتطبيقك والنظام فقط بالوصول إلى Service. تطلب السمة android:process=":sync" من النظام تشغيل Service في عملية مشتركة عامة تُسمى sync. إذا كان لديك عدة محوّلات مزامنة في تطبيقك، يمكن لهذه المحوّلات مشاركة هذه العملية، ما يقلل النفقات العامة.

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

لديك الآن جميع مكونات محوّل المزامنة. يوضّح الدرس التالي كيفية إعلام إطار عمل محوّل المزامنة بتشغيل محوّل المزامنة، إما استجابةً لحدث أو وفقًا لجدول زمني منتظم.