<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                SyncManager的構造函數的代碼較長,可分段來看。下面先來介紹第一段的代碼。 1. SyncManager介紹 **SyncManager.java::SyncManager** ~~~ public SyncManager(Context context, booleanfactoryTest) { mContext= context; //SyncManager中的幾位重要成員登場。見下文的解釋 SyncStorageEngine.init(context); mSyncStorageEngine =SyncStorageEngine.getSingleton(); mSyncAdapters = newSyncAdaptersCache(mContext); mSyncQueue = newSyncQueue(mSyncStorageEngine, mSyncAdapters); HandlerThread syncThread = newHandlerThread("SyncHandlerThread", Process.THREAD_PRIORITY_BACKGROUND); syncThread.start(); mSyncHandler = new SyncHandler(syncThread.getLooper()); mMainHandler = new Handler(mContext.getMainLooper()); /* mSyncAdapters類似AccountManagerService中的AccountAuthenticatorCache, 它用于管理系統中和SyncService相關的服務信息。下邊的函數為mSyncAdapters增加一個 監聽對象,一旦系統中的SyncService發生變化(例如安裝了一個提供同步服務的APK包),則 SyncManager需要針對該服務發起一次同步請求。同步請求由scheduleSync函數發送, 后文再分析此函數 */ mSyncAdapters.setListener(new RegisteredServicesCacheListener<SyncAdapterType>() { public void onServiceChanged(SyncAdapterType type, boolean removed) { if (!removed) { scheduleSync(null, type.authority, null, 0,false); } } },mSyncHandler); ~~~ 在以上代碼中,首先見到的是SyncManager的幾位重要成員,它們之間的關系如圖8-11所示。 :-: ![](http://img.blog.csdn.net/20150803131622061?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖8-11 SyncManager成員類圖 由圖8-11可知, SyncManager的這幾位成員的功能大體可分為3部分: - 左上角是SyncAdaptersCache類,從功能和派生關系上看,它和AccountManagerService中的AccountAuthenticatorCaches類似。SyncAdaptersCache用于管理系統中SyncService服務的信息。在SyncManager中,SyncService的信息用SyncAdapterType類來表示。 - 左下角是SyncQueue和SyncOperation類,SyncOperation代表一次正在執行或等待執行的同步操作,而SyncQueue通過mOperationsMap保存系統中存在的SyncOperation。 - 右半部分是SyncStorageEngine,由于同步操作涉及,重要數據的傳輸,加之可能耗時較長,所以SyncStorageEngine提供了一些內部類來保存同步操作中的一些信息。例如PendingOperation代表保存在從本地文件中的那些還沒有執行完的同步操作的信息。另外,SyncStrorageEngine還需要對同步操作進行一些統計,例如耗電量統計等。SyncStorageEngine包含的內容較多,讀者學習完本章后可自行研究相關內容。 SyncManager家族成員的責任分工比較細,后續分析時再具體討論它們的作用。先接著看SyncManager的構造函數: **SyncManager.java::SyncManager** ~~~ ...... //創建一個用于廣播發送的PendingIntent,該PendingIntent用于和 //AlarmManagerService交互 mSyncAlarmIntent= PendingIntent.getBroadcast( mContext, 0, new Intent(ACTION_SYNC_ALARM),0); //注冊CONNECTIVITY_ACTION廣播監聽對象,用于同步操作需要使用網絡,所以 //此處需要監聽和網絡相關的廣播 IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); context.registerReceiver(mConnectivityIntentReceiver, intentFilter); if(!factoryTest) { //監聽BOOT_COMPLETED廣播 intentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED); context.registerReceiver(mBootCompletedReceiver, intentFilter); } //監聽BACKGROUND_DATA_SETTING_CHANGED廣播。該廣播與是否允許后臺傳輸數據有關, //用戶可在Settings應用程序中設置對應選項 intentFilter = new IntentFilter(ConnectivityManager. ACTION_BACKGROUND_DATA_SETTING_CHANGED); context.registerReceiver(mBackgroundDataSettingChanged, intentFilter); //監視設備存儲空間狀態廣播。由于SyncStorageEngine會保存同步時的一些信息到存儲 //設備中,所以此處需要監視存儲設備的狀態 intentFilter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW); intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK); context.registerReceiver(mStorageIntentReceiver, intentFilter); //監聽SHUTDOWN廣播。此處設置優先級為100,即優先接收此廣播 intentFilter = new IntentFilter(Intent.ACTION_SHUTDOWN); intentFilter.setPriority(100); context.registerReceiver(mShutdownIntentReceiver, intentFilter); if(!factoryTest) {//和通知服務交互,用于在狀態欄上提示用戶 mNotificationMgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); //注意,以下函數注冊的廣播將針對前面創建的mSyncAlarmIntent context.registerReceiver(new SyncAlarmIntentReceiver(), newIntentFilter(ACTION_SYNC_ALARM)); }...... mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); //創建WakeLock,防止同步過程中掉電 mHandleAlarmWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, HANDLE_SYNC_ALARM_WAKE_LOCK); mHandleAlarmWakeLock.setReferenceCounted(false); mSyncManagerWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, SYNC_LOOP_WAKE_LOCK); mSyncManagerWakeLock.setReferenceCounted(false); //知識點一:監聽SyncStorageEngine的狀態變化,如下文解釋 mSyncStorageEngine.addStatusChangeListener( ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, newISyncStatusObserver.Stub() { public void onStatusChanged(int which) { sendCheckAlarmsMessage(); } }); //知識點二:監視賬戶的變化。如果用戶添加或刪除了某個賬戶,則需要做相應處理。 //如下文解釋 if(!factoryTest) { AccountManager.get(mContext).addOnAccountsUpdatedListener( SyncManager.this, mSyncHandler, false); onAccountsUpdated(AccountManager.get(mContext).getAccounts()); } } ~~~ 在以上代碼中,有兩個重要知識點。 - 第一, SyncManager為SyncStorageEngine設置了一個狀態監聽對象。根據前文的描述,在SyncManager家族中,SyncStorageEngine專門負責管理和保存同步服務中絕大部分的信息,所以當外界修改了這些信息時,SyncStorageEngine需要通知狀態監聽對象。我們可以通過一個例子了解其中的工作流程。下面的setSyncAutomatically函數的作用是設置是否自動同步某個賬戶的某項數據,代碼如下: **ContentService.java::setSyncAutomatically** ~~~ public void setSyncAutomatically(Account account,String providerName, booleansync) { ......//檢查WRITE_SYNC_SETTINGS權限 longidentityToken = clearCallingIdentity(); try { SyncManager syncManager = getSyncManager(); if(syncManager != null) { /* 通過SyncManager找到SyncStorageEngine,并調用它的 setSyncAutomatically函數。在其內部會修改對應賬戶的同步服務信息,然后通知 監聽者,而這個監聽者就是SyncManager設置的那個狀態監聽對象 */ syncManager.getSyncStorageEngine().setSyncAutomatically( account, providerName,sync); } }finally { restoreCallingIdentity(identityToken); } } ~~~ 在以上代碼中,最終調用的是SyncStorageEngine的函數,但SyncManager也會因狀態監聽對象被觸發而做出相應動作。實際上,ContentService中大部分設置同步服務參數的API,其內部實現就是先直接調用SyncStorageEngine的函數,然后再由SyncStorageEngine通知監聽對象。讀者在閱讀代碼時,仔細一些就可明白這一關系。 - 第二,SyncManager將為AccountManager設置一個賬戶更新監聽對象(注意,此處是AccountManager,而不是AccountManagerService。AccountManager這部分功能的代碼不是很簡單,讀者有必要反復研究)。在Android平臺上,數據同步和賬戶的關系非常緊密,并且同一個賬戶可以對應不同的數據項。例如在EasAuthenticator的addAccount實現中,讀者會發現一個Exchange賬戶可以對應Contacts、Calendar和Email三種不同的數據項。在添加Exchange賬戶時,還可以選擇是否同步其中的某項數據(通過判斷實現addAccount時傳遞的options是否含有對應的同步選項,例如同步郵件數據時需要設置的OPTIONS_EMAIL_SYNC_ENABLED選項)。由于SyncManager和賬戶之間的這種緊密關系的存在,SyncManager就必須監聽手機中賬戶的變化情況。 * * * * * **提示**:上述兩個知識點涉及的內容都是一些非常細節的問題,本章擬將它們作為小任務,讀者可自行研究它們。 * * * * * 下面來認識一下SyncManager家族中的幾位主要成員,首先是SyncStorageEngine。 2. SyncStorageEngine介紹 SyncStorageEngine負責整個同步系統中信息管理方面的工作。先看其init函數代碼: **SyncStorageEngine.java::init** ~~~ public static void init(Context context) { if(sSyncStorageEngine != null) return; /* 得到系統中加密文件系統的路徑,如果手機中沒有加密的文件系統(根據系統屬性 “persist.security.efs.enabled”的值來判斷),則返回的路徑為/data, 目前的Android手機大部分都沒有加密文件系統,故dataDir為/data */ FiledataDir = Environment.getSecureDataDirectory(); //創建SyncStorageEngine對象 sSyncStorageEngine = new SyncStorageEngine(context, dataDir); } ~~~ 而SyncStorageEngine的構造函數代碼為: **SyncStorageEngine.java::SyncStorageEngine** ~~~ private SyncStorageEngine(Context context, FiledataDir) { mContext= context; sSyncStorageEngine = this; mCal =Calendar.getInstance(TimeZone.getTimeZone("GMT+0")); FilesystemDir = new File(dataDir, "system"); FilesyncDir = new File(systemDir, "sync"); syncDir.mkdirs(); //mAccountInfoFile指向/data/system/sync/accounts.xml mAccountInfoFile = new AtomicFile(new File(syncDir,"accounts.xml")); //mStatusFile指向/data/system/sync/status.bin,該文件記錄 //一些和同步服務相關的狀態信息 mStatusFile = new AtomicFile(new File(syncDir, "status.bin")); //mStatusFile指向/data/system/sync/pending.bin,該文件記錄了當前處于pending //狀態的同步請求 mPendingFile = new AtomicFile(new File(syncDir,"pending.bin")); //mStatusFile指向/data/system/sync/stats.bin,該文件記錄同步服務管理運行過程 //中的一些統計信息 mStatisticsFile = new AtomicFile(new File(syncDir,"stats.bin")); /* 解析上述四個文件,從下面的代碼看,似乎是先讀(readXXX)后寫(writeXXX),這是怎么 回事?答案在于AtomicFile,它內部實際包含兩個文件,其中一個用于備份,防止數據丟失。 感興趣的讀者可以研究AtomicFile類,其實現非常簡單 */ readAccountInfoLocked(); readStatusLocked(); readPendingOperationsLocked(); readStatisticsLocked(); readAndDeleteLegacyAccountInfoLocked(); writeAccountInfoLocked(); writeStatusLocked(); writePendingOperationsLocked(); writeStatisticsLocked(); } ~~~ 上述init和SyncStorage的構造函數都比較簡單,故不再詳述。下面將討論一些有關accounts.xml的故事。以下是一個真實機器上的accounts.xml文件,如圖8-12所示。 :-: ![](http://img.blog.csdn.net/20150803131638857?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖8-12 accounts.xml內容展示 圖8-12所示為筆者KindleFire(CM9的ROM)機器中accounts.xml文件的內容,其中兩個黑框中內容的作用如下: - 第一個框中的listen-for-tickles,該標簽和Android平臺中的Master Sync有關。Master Sync用于控制手機中是否所有賬戶對應的所有數據項都自動同步。用戶可通過ContentResolver setMasterSyncAutomatically進行設置。 - 第二個框代表一個AuthorityInfo。AuthorityInfo記錄了賬戶和SyncService相關的一些信息。此框中的account為筆者的郵箱,type為“com.google”。另外,從圖8-12中還可發現,一個賬戶(包含account和type兩個屬性)可以對應多種類型的數據項,例如此框中對應的數據項是“com.android.email.provider”,而此框前面一個AuthorityInfo對應的數據項是“com.google.android.apps.books”。AuthorityInfo中的periodicSync用于控制周期同步的時間,單位是秒,默認是86400秒,也就是1天。另外,AuthorityInfo中還有一個重要屬性syncable,它的可選值為true、false或unknown(在代碼中,這3個值分別對應整型值1、0和-1)。 syncable的unknown狀態是個較難理解的概念,它和參數SYNC_EXTRAS_INITIALIZE有關,官方的解釋如下: ~~~ /** Set by theSyncManager to request that the SyncAdapter initialize itself for the givenaccount/authority pair. One required initialization step is to ensure thatsetIsSyncable()has been called with a >= 0 value. When thisflag is set the SyncAdapter does not need to do a full sync, though itis allowed to do so. */ publicstatic final String SYNC_EXTRAS_INITIALIZE = "initialize"; ~~~ 由以上解釋可知,如果某個SyncService的狀態為unknown,那么在啟動它時必須傳遞一個SYNC_EXTRAS_INITIALIZE選項,SyncService解析該選項后即可知自己尚未被初始化。當它完成初始化后,需要調用setIsSyncable函數設置syncable的狀態為1。另外,SyncService初始化完成后,是否可接著執行同步請求呢?目前的設計是,它們并不會立即執行同步,需要用戶再次發起請求。讀者在后續小節中會看到與此相關的處理。 此處先來看setIsSyncable的使用示例,前面分析的EasAuthenticator addAccount中有如下的函數調用: ~~~ //添加完賬戶后,將設置對應的同步服務狀態為1 ContentResolver.setIsSyncable(account,EmailContent.AUTHORITY, 1); ContentResolver.setSyncAutomatically(account,EmailContent.AUTHORITY, syncEmail); ~~~ 在EasAuthenticator中,一旦添加了賬戶,就會設置對應SyncService的syncable狀態為1。SyncManager將根據這個狀態做一些處理,例如立即發起一次同步操作。 * * * * * **注意**:是否設置syncable狀態和具體應用有關,圖8-12第二個框中的gmail郵件同步服務就沒有因為筆者添加了賬戶而設置syncable為1。 * * * * * 3. SyncAdaptersCache介紹 再看SyncAdaptersCache,其構造函數代碼如下: **SyncAdaptersCache.java::SyncAdaptersCache** ~~~ SyncAdaptersCache(Context context) { /* 調用基類RegisteredServicesCache的構造函數,其中SERVICE_INTERFACE和 和SERVICE_META_DATA的值為“android.content.SyncAdapter”, ATTRIBUTES_NAME為字符串"sync-adapter" */ super(context, SERVICE_INTERFACE, SERVICE_META_DATA, ATTRIBUTES_NAME, sSerializer); } ~~~ SyncAdaptersCache的基類是RegisteredServicesCache。8.3.1節已經分析過RegisteredServicesCache了,此處不再贅述。下面展示一個實際的例子,如圖8-13所示。 :-: ![](http://img.blog.csdn.net/20150803131658964?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖8-13 android.content.SyncAdapter.xml 圖8-13列出了筆者KindleFire上安裝的同步服務,其中黑框列出的是“om.android.exchange”,該項服務和Android中Exchange應用有關。Exchange的AndroidManifest.xml文件的信息如圖8-14所示。 :-: ![](http://img.blog.csdn.net/20150803131712854?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖8-14 Exchange AndroidManifest.xml示意 圖8-14列出了Exchange應用所支持的針對郵件提供的同步服務,即EmailSyncAdapterService。該服務會通過meta-data中的resource來描述自己,這部分內容如圖8-15所示。 :-: ![](http://img.blog.csdn.net/20150803131725373?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖8-15 syncadapter_email.xml內容展示 圖8-15告訴我們,EmailSyncAdapterService對應的賬戶類型是“com.android.exchange”,需要同步的郵件數據地址由contentAuthority表示,即本例中的“com.android.email.provider”。注意,EmailSyncAdapterService只支持從網絡服務端同步數據到本機,故supportsUploading為false。 再看SyncManager家族中最后一位成員SyncQueue。 4. SyncQueue介紹 SyncQueue用于管理同步操作對象SyncOperation。SyncQueue的構造函數代碼為: **SyncQueue.java::SyncQueue** ~~~ public SyncQueue(SyncStorageEnginesyncStorageEngine, finalSyncAdaptersCache syncAdapters) { mSyncStorageEngine = syncStorageEngine; //從SyncStorageEngine中取出上次沒有完成的同步操作信息,這類信息由 //PendingOperations表示 ArrayList<SyncStorageEngine.PendingOperation> ops = mSyncStorageEngine.getPendingOperations(); final intN = ops.size(); for (inti=0; i<N; i++) { SyncStorageEngine.PendingOperation op = ops.get(i); //從SyncStorageEngine中取出該同步操作的backoff信息 finalPair<Long, Long> backoff = syncStorageEngine.getBackoff(op.account,op.authority); //從SyncAdaptersCache中取出該同步操作對應的同步服務信息,如果同步服務已經不存在, //則無須執行后面的流程 finalRegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo= syncAdapters.getServiceInfo( SyncAdapterType.newKey(op.authority, op.account.type)); if (syncAdapterInfo == null) continue; //構造一個SyncOperation對象 SyncOperation syncOperation = newSyncOperation( op.account, op.syncSource, op.authority, op.extras, 0, backoff != null ? backoff.first : 0, syncStorageEngine.getDelayUntilTime(op.account, op.authority), syncAdapterInfo.type.allowParallelSyncs()); syncOperation.expedited = op.expedited; syncOperation.pendingOperation = op; //將SyncOperation對象保存到mOperationsMap變量中 add(syncOperation, op); } } ~~~ SyncQueue比較簡單,其中一個比較難理解的概念是backoff,后文再對此作解釋。 至此,SyncManager及相關家族成員已介紹完畢。下面將通過實例分析同步服務的工作流程。在本例中,將同步Email數據,目標同步服務為EmailSyncAdapterService。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看