2015-11-10 12 views
5

Ich versuche, einen Sync-Adapter mit "StubProvider" und "StubAuthenticator" zu schreiben, ich folgte den offiziellen Richtlinien, mein Code läuft ohne Fehler aber "onPerformSync()" wird nicht angerufen, ich habe alles versucht, aber keine Verwendung.ContentResolver.requestSync in Sync-Adapter funktioniert nicht in Android

Mein vollständige Projekt kann von https://www.dropbox.com/s/48bgj3wweehaieu/MyApplication.zip?dl=0

hier heruntergeladen werden werden die Klassen Ich verwende:

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

    } 

} 

Klasse für 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(); 
    } 
} 

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

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

Klasse 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; 
    } 
} 

Klasse 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

Sie liefern eine Menge Code, aber was genau funktioniert nicht? Beschreiben Sie, was Sie erreichen möchten, was das erwartete Ergebnis ist und was das tatsächliche Ergebnis ist. –

+0

Wenn 'onPerformSync' aufgerufen wird, was ist also Ihr Problem? – pskink

+1

dumme mich, ich habe gerade bearbeitet .... 'onPerformSync' wird nicht aufgerufen. – Kazmi

Antwort

0

Haben Sie Ihr account_type auf der Metadaten-XML des Sync-Adapter angeben?

Ihre xml discriptor wie diese

<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"/> 

Und vor allem sein sollte sollte es auf Ihrem AndroidManifest

<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

sicher Sind Sie Datei deklariert werden, es funktioniert nicht?

Denken Sie daran, dass Sync Adapter auf einem Bound Service ausgeführt wird, der nicht im selben Prozess ist, so dass Ihr Log.d() in onPerformSync() nicht im LogCat unter Ihrem App-Hauptprozess angezeigt wird Sync Adapter verwendet.

Versuchen Sie, den Filter im LogCat zu entfernen: statt "Nur ausgewählte Anwendung anzeigen" wählen Sie "Keine Filter".

+1

Dies löste wirklich meine 2 Tage alten Kopfschmerzen. Danke :) –

+1

Das gleiche ist mir passiert. Vielen Dank: D –

+0

Wow, nach stundenlangen Debugging war das der goldene Anhaltspunkt. Nachdem ich "Keine Filter" ausgewählt hatte, sah ich die Protokolle und erkannte, dass ich keine dynamische Berechtigungsbehandlung implementiert hatte. Vielen Dank! – saltandpepper