7

正如我從文檔中所瞭解的,SyncService中定義的一個SyncAdapter僅限於接收一個ContentProvider授權。在SyncAdapter中使用ContentResolver代替ContentProviderClient

但是,與此同時,它可以訪問ContentResolver,它也允許在其他ContentProviders上運行查詢。如果開發人員需要向SyncAdapter提供單一內容權限,並且無論她有權訪問哪個ContentProvider,她都可以做任何她想做的事情,我不理解這種特定的設計概念。我的問題是:忽略onPerformSync參數有什麼後果:字符串權限和ContentProviderClient提供程序,並使用純粹的ContentResolver?

我的應用程序(實際上它SyncService)的想法很簡單:查詢日曆服務器(OwnCloud在我的情況),以得到的不僅是事件(與com.android.calendar同步),而且還VTODOS,然後將其分配在各種任務管理應用程序之間,我可以獲得源代碼和/或ContentProviderContract。我還想到了自己的「Hub」ContentProvider,它具有基本的VTODO/Task結構,並且是與服務器相比唯一的一個。它應該能夠與任務管理應用的不同內容提供者2路同步,然後與服務器同步。

我已閱讀using ContentProviderClient vs ContentResolver to access content provider,我想我明白其中的差別。我現在感到困惑,爲什麼android SDK有如此強大的建議以在單個SyncAdapter中使用單個ContentProvider,但是您可以使用ContentResolver繞過該限制。

我花了一整天的時間來解決這個問題,並搜索了數百個關於此事的SO/Google資源(其中有些是多次)。我也看到了有關使用一個SyncAdapter來同步多個ContentProvider的問題,但沒有一個答案接近暗示使用ContentResolver。

回答

2

當從SyncAdapter的上下文中使用時,對ContentResolver的API沒有特別的限制。恕我直言,爲什麼框架通過ContentProviderClientauthorityonPerformSync()唯一原因是方便和種類的暗示開發人員如何SyncAdapter預期的工作。

這其實是在源代碼中很容易看到的AbstractThreadedSyncAdapter.SyncThread - 傳遞給onPerformSync()ContentProviderClient以標準方式獲得:

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

     // Trace this sync instance. Note, conceptually this should be in 
     // SyncStorageEngine.insertStartSyncEvent(), but the trace functions require unique 
     // threads in order to track overlapping operations, so we'll do it here for now. 
     Trace.traceBegin(Trace.TRACE_TAG_SYNC_MANAGER, mAuthority); 

     SyncResult syncResult = new SyncResult(); 
     ContentProviderClient provider = null; 
     try { 
      if (isCanceled()) { 
       return; 
      } 
      provider = mContext.getContentResolver().acquireContentProviderClient(mAuthority); 
      if (provider != null) { 
       AbstractThreadedSyncAdapter.this.onPerformSync(mAccount, mExtras, 
         mAuthority, provider, syncResult); 
      } else { 
       syncResult.databaseError = true; 
      } 
     } finally { 
      Trace.traceEnd(Trace.TRACE_TAG_SYNC_MANAGER); 

      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 mSyncThreads 
      synchronized (mSyncThreadLock) { 
       mSyncThreads.remove(mThreadsKey); 
      } 
     } 
    } 

因此,bootom線:您可以在SyncAdapter使用ContentResolver你希望 - 只需撥打getContext().getContentResolver()並訪問任何導出的ContentProvider