동기화 어댑터 만들기

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

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

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

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 객체입니다. 서버에서 계정을 사용하지 않으면 이 객체의 정보를 사용할 필요가 없습니다.
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.
     */
}

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

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

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

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.
             */
        }
    }
    ...
}

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

동기화 어댑터 구성요소를 프레임워크에 플러그인하려면 구성요소를 설명하고 추가 플래그를 제공하는 메타데이터를 프레임워크에 제공해야 합니다. 메타데이터는 동기화 어댑터용으로 만든 계정 유형을 지정하고, 앱과 연결된 콘텐츠 제공업체 권한을 선언하고, 동기화 어댑터와 관련된 시스템 사용자 인터페이스의 일부를 제어하고, 기타 동기화 관련 플래그를 선언합니다. 이 메타데이터를 앱 프로젝트의 /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="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" 속성은 sync라는 전역 공유 프로세스에서 Service를 실행하도록 시스템에 지시합니다. 앱에 동기화 어댑터가 여러 개 있는 경우 이 프로세스를 공유하여 오버헤드를 줄일 수 있습니다.

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

이제 동기화 어댑터의 모든 구성요소를 갖추었습니다. 다음 과정에서는 이벤트에 응답하거나 정기적인 일정에 따라 동기화 어댑터를 실행하도록 동기화 어댑터 프레임워크에 지시하는 방법을 보여줍니다.