AbstractThreadedSyncAdapter使用

android.content.AbstractThreadedSyncAdapter 是一个虚类,它主要用于执行Account相关内容(比如Contact)的同步操作。它是对   Account的内容(比如contact)进行同步操作的适配器。     AbstractThreadedSyncAdapter收到同步请求后,将生产一个线程来进行Account指定内容的同步处理。当   AbstractThreadedSyncAdapter  收到 startSync() 请求,如果此时并不是正在进行同步操作,那么将启动一个线程,通过在该线程中调用 AbstractThreadedSyncAdapter   onPerformSync(Account, Bundle, String, ContentProviderClient, SyncResult)   方法来执行同步操作。如果正在进行同步操作时,     AbstractThreadedSyncAdapter 收到 cancelSync() 请求,那么同步操作将被中断,以达到取消同步操作的目的。
    android.content.AbstractThreadedSyncAdapter 是一个虚类,我们必须新建一个继续于它的新类,并重写 onPerformSync(Account, Bundle, String, ContentProviderClient, SyncResult)才能使用。
   AbstractThreadedSyncAdapte 里面有个继承于 ISyncAdapter.Stub 的内部类,以用来对 AbstractThreadedSyncAdapte 的远程接口调用进行包装。我们可以通过 AbstractThreadedSyncAdapte getIBinder() 方法,返回内部类的IBinder形式,以便对 AbstractThreadedSyncAdapte 进行远程调用。
   为了能让系统找到我们自己的对Account内容(比如contact)进行同步操作的适配器 AbstractThreadedSyncAdapte  ,我们需要如下定义一个能接受 action为  android.content.SyncAdapter 的Intent的Service,并在Service的 onBind(android.content.Intent) 中调 AbstractThreadedSyncAdapte getSyncAdapterBinder()  返回其用于远程调用的 IBinde r 接口形式
示例1
  <intent-filter>
     <action android:name="android.content.SyncAdapter" />
   </intent-filter>
   <meta-data android:name="android.content.SyncAdapter"
             android:resource="@xml/syncadapter" />
 
示例2(来自 SampleSyncAdapter
        <service
            android:name=".syncadapter.SyncService"
            android:exported="true">
            <intent-filter>
                <action
                    android:name="android.content.SyncAdapter" />
            </intent-filter>
            <meta-data
                android:name="android.content.SyncAdapter"
                android:resource="@xml/syncadapter" />
            <meta-data
                android:name="android.provider.CONTACTS_STRUCTURE"
                android:resource="@xml/contacts" />
        </service>
The  android:resource  attribute must point to a resource that looks like:
Service应该有个名为 android.content.SyncAdapter meta-data ,该 meta-data resource 属性所指向的 xml 文件应该说明该Account内容同步适配器 AbstractThreadedSyncAdapter 基本显示信息,其语法如下:
 <sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
    android:contentAuthority="authority"
    android:accountType="accountType"
    android:userVisible="true|false"
    android:supportsUploading="true|false"
    android:allowParallelSyncs="true|false"
    android:isAlwaysSyncable="true|false"
    android:syncAdapterSettingsAction="ACTION_OF_SETTINGS_ACTIVITY"
 />
 
示例3 (来自 SampleSyncAdapter
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
    android:contentAuthority="com.android.contacts"
    android:accountType="com.example.android.samplesync"
    android:supportsUploading="false"
/>
 
  • The android:contentAuthority and android:accountType attributes indicate which content authority and for which account types this sync adapter serves.android:contentAuthority表示授权进行同步的内容的类型。比如com.android.contactsandroid:accountType表示授权同步的账号的类型。比如示例3中的"com.example.android.samplesync"。又比如,对于google账号是, android:accountType 为“ com.google ”,关于此可以参照《Account简介》。ContentProvider在其AndroidManifest.xml文件中有个android:authorities属性,比如,在ContactsProvider中,是android:authorities="contacts;com.android.contacts"。这里的android:authoritiesAbstractThreadedSyncAdapteandroid:contentAuthority属性应该相对应。
  • android:userVisible defaults to true and controls whether or not this sync adapter shows up in the Sync Settings screen.
  • android:supportsUploading defaults to true and if true an upload-only sync will be requested for all syncadapters associated with an authority whenever that authority's content provider does a notifyChange(android.net.Uri, android.database.ContentObserver, boolean) with syncToNetwork set to true.默认值为true,当我们调用 notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) 时  upload-only sync ,如果 syncToNetwork参数为true的话,将被请求。 
  • android:allowParallelSyncs defaults to false and if true indicates that the sync adapter can handle syncs for multiple accounts at the same time. Otherwise the SyncManager will wait until the sync adapter is not in use before requesting that it sync an account's data.默认为false,用于表示该同步适配器是否支持多个账号同时进行同步,如果不支持, SyncManager只有等一个同步完成后才进行一个账号的同步
  • android:isAlwaysSyncable defaults to false and if true tells the SyncManager to intialize the isSyncable state to 1 for that sync adapter for each account that is added.
  • android:syncAdapterSettingsAction defaults to null and if supplied it specifies an Intent action of an activity that can be used to adjust the sync adapter's sync settings. The activity must live in the same package as the sync adapter.该属性可以用于指定一个用于对同步操作进行设定的Activity进行启动的intent.注意该activity应该和 SyncAdapter 位于同一个apk包中.
结束。
主要函数
Public Methods
Context getContext()
final  IBinder getSyncAdapterBinder()
abstract void onPerformSync( Account account,  Bundle extras,  String authority,  ContentProviderClient provider,  SyncResult syncResult)
Perform a sync for this account.
void onSyncCanceled( Thread thread)
Indicates that a sync operation has been canceled.
void onSyncCanceled()
Indicates that a sync operation has been canceled.
AbstractThreadedSyncAdapter源码如下:

package android.content;

import android.accounts.Account;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;

import java.util.concurrent.atomic.AtomicInteger;

public abstract class   AbstractThreadedSyncAdapter  {
    /**
     * Kernel event log tag.  Also listed in data/etc/event-log-tags.
     * @deprecated Private constant.  May go away in the next release.
     */
    @Deprecated
    public static final int LOG_SYNC_DETAILS = 2743;

    private final Context mContext;
    private final AtomicInteger mNumSyncStarts;
    private final ISyncAdapterImpl mISyncAdapterImpl;

    // all accesses to this member variable must be synchronized on mSyncThreadLock
    private SyncThread mSyncThread;
    private final Object mSyncThreadLock = new Object();

    private final boolean mAutoInitialize;

    /**
     * Creates an {@link AbstractThreadedSyncAdapter}.
     * @param context the {@link android.content.Context} that this is running within.
     * @param autoInitialize if true then sync requests that have
     * {@link ContentResolver#SYNC_EXTRAS_INITIALIZE} set will be internally handled by
     * {@link AbstractThreadedSyncAdapter} by calling
     * {@link ContentResolver#setIsSyncable(android.accounts.Account, String, int)} with 1 if it
     * is currently set to <0.
     */
    public  AbstractThreadedSyncAdapter (Context context, boolean autoInitialize) {
        mContext = context;
        mISyncAdapterImpl = new ISyncAdapterImpl();
        mNumSyncStarts = new AtomicInteger(0);
        mSyncThread = null;
        mAutoInitialize = autoInitialize;
    }

    public Context getContext() {
        return mContext;
    }

     private class  ISyncAdapterImpl  extends   ISyncAdapter.Stub  {
         public void  startSync (ISyncContext syncContext, String authority, Account account,
                Bundle extras) {
            final SyncContext syncContextClient = new SyncContext(syncContext);

            boolean alreadyInProgress;
            // synchronize to make sure that mSyncThread doesn't change between when we
            // check it and when we use it
            synchronized (mSyncThreadLock) {
                 if  (mSyncThread == null) {
                    if (mAutoInitialize
                            && extras != null
                            && extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false)) {
                         if  (ContentResolver.getIsSyncable(account, authority) < 0) {
                            ContentResolver.setIsSyncable(account, authority, 1);
                        }
                        syncContextClient.onFinished(new SyncResult());
                         return ;
                    }
                    mSyncThread = new SyncThread(
                            "SyncAdapterThread-" + mNumSyncStarts.incrementAndGet(),
                            syncContextClient, authority, account, extras);
                    mSyncThread.start();
                    alreadyInProgress = false;
                }  else  {
                    alreadyInProgress = true;
                }
            }

            // do this outside since we don't want to call back into the syncContext while
            // holding the synchronization lock
             if  (alreadyInProgress) {
                syncContextClient.onFinished(SyncResult.ALREADY_IN_PROGRESS);
            }
        }

         public void   cancelSync (ISyncContext syncContext) {
            // synchronize to make sure that mSyncThread doesn't change between when we
            // check it and when we use it
            final SyncThread syncThread;
             synchronized  (mSyncThreadLock) {
                syncThread = mSyncThread;
            }
             if  (syncThread != null
                    && syncThread.mSyncContext.getSyncContextBinder() == syncContext.asBinder()) {
                onSyncCanceled();
            }
        }

         public void   initialize (Account account, String authority) throws RemoteException {
            Bundle extras = new Bundle();
            extras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true);
            startSync(null, authority, account, extras);
        }
    }

    /**
     * The thread that invokes {@link AbstractThreadedSyncAdapter#onPerformSync}. It also acquires
     * the provider for this sync before calling onPerformSync and releases it afterwards. Cancel
     * this thread in order to cancel the sync.
     */
     private class   SyncThread   extends  Thread {
        private final SyncContext mSyncContext;
        private final String mAuthority;
        private final Account mAccount;
        private final Bundle mExtras;

        private SyncThread(String name, SyncContext syncContext, String authority,
                Account account, Bundle extras) {
            super(name);
            mSyncContext = syncContext;
            mAuthority = authority;
            mAccount = account;
            mExtras = extras;
        }

        public void run() {
            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

            if (isCanceled()) {
                return;
            }

            SyncResult syncResult = new SyncResult();
            ContentProviderClient provider = null;
             try  {
                provider = mContext.getContentResolver().acquireContentProviderClient(mAuthority);
                if (provider != null) {
                    AbstractThreadedSyncAdapter.this.onPerformSync(mAccount, mExtras,
                            mAuthority, provider, syncResult);
                }  else  {
                    syncResult.databaseError = true;
                }
            }  finally  {
                if (provider != null) {
                    provider.release();
                }
                if (!isCanceled()) {
                    mSyncContext.onFinished(syncResult);
                }
                // synchronize so that the assignment will be seen by other threads
                // that also synchronize accesses to mSyncThread
                synchronized (mSyncThreadLock) {
                    mSyncThread = null;
                }
            }
        }

         private boolean  isCanceled() {
             return  Thread.currentThread().isInterrupted();
        }
    }

    /**
     * @return a reference to the IBinder of the SyncAdapter service.
     */
     public final  IBinder getSyncAdapterBinder() {
         return  mISyncAdapterImpl.asBinder();
    }

    /**
     * Perform a sync for this account. SyncAdapter-specific parameters may
     * be specified in extras, which is guaranteed to not be null. Invocations
     * of this method are guaranteed to be serialized.
     *
     * @param account the account that should be synced
     * @param extras SyncAdapter-specific parameters
     * @param authority the authority of this sync request
     * @param provider a ContentProviderClient that points to the ContentProvider for this
     *   authority
     * @param syncResult SyncAdapter-specific parameters
     */
    public abstract void onPerformSync(Account account, Bundle extras,
            String authority, ContentProviderClient provider, SyncResult syncResult);

    /**
     * Indicates that a sync operation has been canceled. This will be invoked on a separate
     * thread than the sync thread and so you must consider the multi-threaded implications
     * of the work that you do in this method.
     *
     */
     public void  onSyncCanceled() {
        final SyncThread syncThread;
        synchronized (mSyncThreadLock) {
            syncThread = mSyncThread;
        }
         if  (syncThread != null) {
            syncThread.interrupt();
        }
    }
}
最后,关于  AbstractThreadedSyncAdapte  的使用请参照google官方的示例程 SampleSyncAdapter


原文:http://blog.csdn.net/hudashi/article/details/7350020
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值