ContentResolver.requestSync in sync adapter not working in Android

I'm trying to write a synchronization adapter with "StubProvider" and "StubAuthenticator", I followed the official recommendations, my code works without any errors, but "onPerformSync ()" DOES NOT receive the call, I tried everything but did not use it.

My full project can be downloaded from https://www.dropbox.com/s/48bgj3wweehaieu/MyApplication.zip?dl=0

Here are the classes I use:

Class MainActivity

public class MainActivity extends FragmentActivity implements View.OnClickListener { // Constants // The authority for the sync adapter 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 for authentication stubs

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

Class 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 IBinder. */ @Override public IBinder onBind(Intent intent) { return mAuthenticator.getIBinder(); } } 

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

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

SyncAdapter Class

 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(); } } } 
+5
source share
2 answers

Are you sure it doesn't work?

Remember that the synchronization adapter is running in the Bound Service, which is not in the same process, so your Log.d () in onPerformSync () will not appear in LogCat in the main process of your application, but the adapter is used in the Sync synchronization process.

Try removing the filter in LogCat: instead of "Show only the selected application," select "No filters."

+24
source

Have you entered your account in the xml metadata of the sync adapter?

Your xml descriptor should look like this

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

And most importantly it should be declared in your AndroidManifest 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> 
0
source

Source: https://habr.com/ru/post/1235607/


All Articles