2015-11-10 43 views
5

Sto provando a scrivere un adattatore di sincronizzazione con 'StubProvider' e 'StubAuthenticator', ho seguito le linee guida ufficiali, il mio codice è in esecuzione senza errori ma 'onPerformSync()' NON viene chiamato, ho provato tutto ma non uso.ContentResolver.requestSync in Sync Adapter non funziona su Android

mio progetto completo può essere scaricato dal https://www.dropbox.com/s/48bgj3wweehaieu/MyApplication.zip?dl=0

Ecco le classi Sto usando:

Classe MainActivity

public class MainActivity extends FragmentActivity implements View.OnClickListener { 

    // Constants 
    // The authority for the sync adapter's content provider 
    public static final String AUTHORITY = "com.syncadaptertest.StubProvider"; 
    // An account type, in the form of a domain name 
    public static final String ACCOUNT_TYPE = "com.syncadaptertest"; 
    // The account name 
    public static final String ACCOUNT = "dummyaccount"; 
    // Instance fields 
    Account mAccount; 

    private ImageButton mRefreshBtn = null; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.activity_main); 

     mRefreshBtn = (ImageButton) findViewById(R.id.refreshBtn); 
     mRefreshBtn.setOnClickListener(this); 

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


    @Override 
    public void onClick(View v){ 

     onRefreshButtonClick(v); 
    } 



    /** 
    * Respond to a button click by calling requestSync(). This is an 
    * asynchronous operation. 
    * 
    * This method is attached to the refresh button in the layout 
    * XML file 
    * 
    * @param v The View associated with the method call, 
    * in this case a Button 
    */ 
    public void onRefreshButtonClick(View v) { 

     // Pass the settings flags by inserting them in a bundle 
     Bundle settingsBundle = new Bundle(); 
     settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); 
     settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true); 
     /* 
     * Request the sync for the default account, authority, and 
     * manual sync settings 
     */ 
     ContentResolver.setIsSyncable(mAccount, AUTHORITY, 1); 
     ContentResolver.requestSync(mAccount, AUTHORITY, settingsBundle); 

     if(ContentResolver.isSyncActive(mAccount, AUTHORITY)) 
     { 
      Log.d("testing1","testttt"); 
     } 
     if(ContentResolver.isSyncPending(mAccount, AUTHORITY)) 
     { 
      Log.d("testing2","testttt2"); 
     } 

     List<SyncInfo> myList = ContentResolver.getCurrentSyncs(); 

    } 

} 

Class Per Stub Authenticator

public class Authenticator extends AbstractAccountAuthenticator { 
    // Simple constructor 
    public Authenticator(Context context) { 
     super(context); 
    } 
    // Editing properties is not supported 
    @Override 
    public Bundle editProperties(
      AccountAuthenticatorResponse r, String s) { 
     throw new UnsupportedOperationException(); 
    } 
    // Don't add additional accounts 
    @Override 
    public Bundle addAccount(
      AccountAuthenticatorResponse r, 
      String s, 
      String s2, 
      String[] strings, 
      Bundle bundle) throws NetworkErrorException { 
     return null; 
    } 
    // Ignore attempts to confirm credentials 
    @Override 
    public Bundle confirmCredentials(
      AccountAuthenticatorResponse r, 
      Account account, 
      Bundle bundle) throws NetworkErrorException { 
     return null; 
    } 
    // Getting an authentication token is not supported 
    @Override 
    public Bundle getAuthToken(
      AccountAuthenticatorResponse r, 
      Account account, 
      String s, 
      Bundle bundle) throws NetworkErrorException { 
     throw new UnsupportedOperationException(); 
    } 
    // Getting a label for the auth token is not supported 
    @Override 
    public String getAuthTokenLabel(String s) { 
     throw new UnsupportedOperationException(); 
    } 
    // Updating user credentials is not supported 
    @Override 
    public Bundle updateCredentials(
      AccountAuthenticatorResponse r, 
      Account account, 
      String s, Bundle bundle) throws NetworkErrorException { 
     throw new UnsupportedOperationException(); 
    } 
    // Checking features for the account is not supported 
    @Override 
    public Bundle hasFeatures(
      AccountAuthenticatorResponse r, 
      Account account, String[] strings) throws NetworkErrorException { 
     throw new UnsupportedOperationException(); 
    } 
} 

Classe AuthenticatorService

public class AuthenticatorService extends Service { 

    // Instance field that stores the authenticator object 
    private Authenticator mAuthenticator; 
    @Override 
    public void onCreate() { 
     // Create a new authenticator object 
     mAuthenticator = new Authenticator(this); 
    } 
    /* 
    * When the system binds to this Service to make the RPC call 
    * return the authenticator's IBinder. 
    */ 
    @Override 
    public IBinder onBind(Intent intent) { 
     return mAuthenticator.getIBinder(); 
    } 
} 

Classe SyncService

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(); 
    } 
} 

Classe StubProvider

public class StubProvider extends ContentProvider { 
    /* 
    * Always return true, indicating that the 
    * provider loaded correctly. 
    */ 
    @Override 
    public boolean onCreate() { 
     return true; 
    } 
    /* 
    * Return no type for MIME type 
    */ 
    @Override 
    public String getType(Uri uri) { 
     return null; 
    } 
    /* 
    * query() always returns no results 
    * 
    */ 
    @Override 
    public Cursor query(
      Uri uri, 
      String[] projection, 
      String selection, 
      String[] selectionArgs, 
      String sortOrder) { 
     return null; 
    } 
    /* 
    * insert() always returns null (no URI) 
    */ 
    @Override 
    public Uri insert(Uri uri, ContentValues values) { 
     return null; 
    } 
    /* 
    * delete() always returns "no rows affected" (0) 
    */ 
    @Override 
    public int delete(Uri uri, String selection, String[] selectionArgs) { 
     return 0; 
    } 
    /* 
    * update() always returns "no rows affected" (0) 
    */ 
    public int update(
      Uri uri, 
      ContentValues values, 
      String selection, 
      String[] selectionArgs) { 
     return 0; 
    } 
} 

Classe SyncAdapter

public class SyncAdapter extends AbstractThreadedSyncAdapter { 
    private final AccountManager mAccountManager; 

    public SyncAdapter(Context context, boolean autoInitialize) { 
     super(context, autoInitialize); 
     mAccountManager = AccountManager.get(context); 
    } 

    @Override 
    public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) { 
     Log.d("udinic", "onPerformSync for account[" + account.name + "]"); 
     try { 
      // TODO Updating local tv shows 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

Stai fornendo molto codice, ma cosa non funziona esattamente? Descrivi cosa stai cercando di ottenere, qual è il risultato atteso e qual è il risultato reale. –

+0

se viene richiamato 'onPerformSync', qual è il tuo problema? – pskink

+1

sciocco, ho appena modificato .... 'onPerformSync' NON viene chiamato. – Kazmi

risposta

0

stata specificata la tua ACCOUNT_TYPE sulla xml metadati della scheda di sincronizzazione?

tuo xml discriptor dovrebbe essere così

<sync-adapter 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:contentAuthority="com.android.contacts" 
    android:accountType="com.syncadaptertest" 
    android:userVisible="true" 
    android:supportsUploading="false" 
    android:allowParallelSyncs="false" 
    android:isAlwaysSyncable="true"/> 

E cosa più importante che dovrebbe essere dichiarato sul AndroidManifest il file

<service 
     android:name=".sync.ContactSyncService" 
     android:exported="true"> 
     <intent-filter> 
      <action android:name="android.content.SyncAdapter" /> 
     </intent-filter> 
     <meta-data 
      android:name="android.content.SyncAdapter" 
      android:resource="@xml/sync_contact" /> 
    </service> 
24

Sei sicuro che non funziona?

Ricordare che l'adattatore di sincronizzazione viene eseguito su un servizio associato che non è nello stesso processo, pertanto il log.d() in onPerformSync() non verrà visualizzato nel logCat nel processo principale dell'app ma nel processo in cui il L'adattatore di sincronizzazione sta usando.

Provare a rimuovere il filtro nel LogCat: anziché "Mostra solo applicazione selezionata" selezionare "Nessun filtro".

+1

Questo davvero risolto il mio mal di testa da 2 giorni. Grazie :) –

+1

La stessa cosa è successa a me. Grazie mille: D –

+0

Wow, dopo ore e ore di debug questo è stato l'indizio d'oro. Dopo aver selezionato "Nessun filtro", ho visto i log e mi sono reso conto che non avevo implementato la gestione dinamica delle autorizzazioni. Grazie mille! – saltandpepper