동기화 어댑터 만들기

참고: 대부분의 백그라운드 처리 사용 사례에 권장되는 솔루션인 WorkManager를 사용하는 것이 좋습니다. 어떤 솔루션이 가장 적합한지 알아보려면 백그라운드 처리 가이드를 참조하세요.

앱의 동기화 어댑터 구성요소에서는 기기와 서버 간에 데이터를 전송하는 작업의 코드를 캡슐화합니다. 동기화 어댑터 프레임워크는 앱에서 제공하는 예약 및 트리거에 따라 동기화 어댑터 구성요소에서 코드를 실행합니다. 앱에 동기화 어댑터 구성요소를 추가하려면 다음 부분을 추가해야 합니다.

동기화 어댑터 클래스
동기화 어댑터 프레임워크와 호환되는 인터페이스에서 데이터 전송 코드를 래핑하는 클래스입니다.
바인드된 Service
동기화 어댑터 프레임워크가 동기화 어댑터 클래스에서 코드를 실행하도록 허용하는 구성요소입니다.
동기화 어댑터 XML 메타데이터 파일
동기화 어댑터에 관한 정보가 포함된 파일입니다. 프레임워크에서는 이 파일을 읽어 데이터 전송을 로드하고 예약하는 방법을 알아냅니다.
앱 매니페스트 선언
바인드된 서비스를 선언하고 동기화 어댑터별 메타데이터를 가리키는 XML입니다.

이 학습 과정에서는 이러한 요소를 정의하는 방법을 안내합니다.

동기화 어댑터 클래스 만들기

이 단원에서는 데이터 전송 코드를 캡슐화하는 동기화 어댑터 클래스를 만드는 방법을 알아봅니다. 클래스를 만드는 과정에는 동기화 어댑터 기본 클래스 확장, 클래스의 생성자 정의, 데이터 전송 작업을 정의하는 메서드 구현이 포함됩니다.

기본 동기화 어댑터 클래스 확장

동기화 어댑터 구성요소를 만들려면 AbstractThreadedSyncAdapter를 확장하고 그 생성자를 작성하는 것부터 시작하세요. Activity.onCreate()를 사용하여 활동을 설정하는 것과 마찬가지로 동기화 어댑터 구성요소를 처음부터 만들 때마다 생성자를 사용하여 설정 작업을 실행합니다. 예를 들어 앱에서 콘텐츠 제공업체를 사용하여 데이터를 저장한다면 생성자를 사용하여 ContentResolver 인스턴스를 가져옵니다. parallelSyncs 인수를 지원하기 위해 두 번째 형식의 생성자가 Android 플랫폼 버전 3.0에 추가되었으므로 두 가지 형식의 생성자를 만들어 호환성을 유지해야 합니다.

참고: 동기화 어댑터 프레임워크는 싱글톤 인스턴스인 동기화 어댑터 구성요소와 함께 작동하도록 설계되었습니다. 동기화 어댑터 구성요소의 인스턴스화는 동기화 어댑터를 프레임워크에 바인딩 섹션에서 자세히 설명합니다.

다음 예에서는 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) {
        ...
    }
    

자바

    /**
     * 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 객체입니다. 서버에서 계정을 사용하지 않는다면 이 객체의 정보를 사용할 필요가 없습니다.
Extras
동기화 어댑터를 트리거한 이벤트에서 전송한 플래그가 포함된 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.
         */
    }
    

자바

    /*
     * 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()에 추가해야 합니다. 이 메서드에 모든 네트워크 작업을 집중하면 네트워크 인터페이스를 시작하고 중지하는 데 필요한 배터리 전력이 절약됩니다. 네트워크에 더욱 효율적으로 액세스하는 방법에 관한 자세한 내용은 배터리 소모 없이 데이터 전송을 참조하세요. 이 교육 과정에서는 데이터 전송 코드에 포함할 수 있는 여러 네트워크 액세스 작업을 설명합니다.

동기화 어댑터를 프레임워크에 바인딩

데이터 전송 코드를 동기화 어댑터 구성요소에 캡슐화하기는 했지만 코드에 액세스할 수 있는 권한을 프레임워크에 제공해야 합니다. 이렇게 하려면 동기화 어댑터 구성요소에서 프레임워크로 특수 Android 바인더 객체를 전달하는 바인드된 Service를 만들어야 합니다. 이 바인더 객체로 프레임워크에서는 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()
        }
    }
    

자바

    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 = "dummyaccount"
    ...
    class MainActivity : FragmentActivity() {

        // Instance fields
        private lateinit var mAccount: Account
        ...
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
           ...
            // Create the dummy account
            mAccount = createSyncAccount()
           ...
        }
        ...
        /**
         * Create a new dummy 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.
                     */
                }
            }
        }
        ...
    }
    

자바

    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 = "dummyaccount";
        // Instance fields
        Account mAccount;
        ...
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ...
            // Create the dummy account
            mAccount = CreateSyncAccount(this);
            ...
        }
        ...
        /**
         * Create a new dummy 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.
                 */
            }
        }
        ...
    }
    

동기화 어댑터 메타데이터 파일 추가

동기화 어댑터 구성요소를 프레임워크에 플러그인하려면 구성요소를 설명하고 추가 플래그를 제공하는 메타데이터를 프레임워크에 제공해야 합니다. 메타데이터에서는 동기화 어댑터에 생성한 계정 유형을 지정하고, 앱과 관련된 콘텐츠 제공업체 권한을 선언하고, 동기화 어댑터와 관련된 시스템 사용자 인터페이스의 일부를 제어하고, 다른 동기화 관련 플래그를 선언합니다. 이 메타데이터를 앱 프로젝트의 /res/xml/ 디렉터리에 저장된 특수 XML 파일로 선언합니다. 파일은 어떤 이름이든 가능하지만 일반적으로는 syncadapter.xml입니다.

이 XML 파일에는 다음 속성을 지닌 단일 XML 요소 <sync-adapter>가 포함되어 있습니다.

android:contentAuthority
콘텐츠 제공업체의 URI 권한입니다. 이전 과정 스터브 콘텐츠 제공업체 만들기에서 앱에 스터브 콘텐츠 제공업체를 만들었다면 앱 매니페스트에 추가한 <provider> 요소의 속성 android:authorities에 지정한 값을 사용합니다. 이 속성은 매니페스트에서 제공업체 선언 섹션에 자세히 설명되어 있습니다.
동기화 어댑터를 사용하여 콘텐츠 제공업체에서 서버로 데이터를 전송하는 경우 이 값은 데이터에 사용하는 콘텐츠 URI 권한과 동일해야 합니다. 이 값은 앱 매니페스트에서 제공업체를 선언하는 <provider> 요소의 android:authorities 속성에서 지정하는 권한 중 하나이기도 합니다.
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를 선언해야 합니다.

동기화 어댑터 구성요소는 네트워크와 기기 간에 데이터를 전송하는 코드를 실행하므로 인터넷에 액세스할 수 있는 권한을 요청해야 합니다. 또한 앱에서 동기화 어댑터 설정을 읽고 쓰는 권한을 요청해야 하므로 앱의 다른 구성요소에서 프로그래매틱 방식으로 동기화 어댑터를 제어할 수 있습니다. 스터브 인증자 만들기 과정에서 만든 인증자 구성요소를 앱에서 사용할 수 있는 특수 권한도 요청해야 합니다.

이러한 권한을 요청하려면 앱 매니페스트에 다음을 <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="true"
                    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="true"를 사용하면 앱 이외의 프로세스(시스템 포함)에서 Service에 액세스할 수 있습니다. 속성 android:process=":sync"sync라는 전역 공유 프로세스에서 Service를 실행하라고 시스템에 지시합니다. 앱에 동기화 어댑터가 여러 개 있다면 이 프로세스를 공유하여 오버헤드를 줄일 수 있습니다.

<meta-data> 요소는 이전에 만든 동기화 어댑터 메타데이터 XML 파일의 이름을 제공합니다. android:name 속성은 이 메타데이터가 동기화 어댑터 프레임워크용인 것을 나타냅니다. android:resource 요소는 메타데이터 파일의 이름을 지정합니다.

이제 동기화 어댑터의 모든 구성요소를 갖추었습니다. 다음 과정에서는 이벤트에 대한 응답으로 또는 정기적으로 동기화 어댑터를 실행하도록 동기화 어댑터 프레임워크에 지시하는 방법을 안내합니다.