9

Overview

I follwed Google's tutorial on using SyncAdapter without using ContentProvider, Authenticator..etc. It works perfectly when I call onPerformSync(...) when I need to do an "upload" to the server via de SyncAdapter.

Now, as you can imagine, I need to do downloads from the server as well (yes I understand that it would be better to use Google's Cloud Messaing system, but this is the set up I was given, and I can't change that). For that, instead of doing periodical syncs, I want to make use of the "Network tickle" Android system carries out when there is a network available. For that I state the following:

ContentResolver.setIsSyncable(accounts[0], AUTHORITY, 1);
ContentResolver.setSyncAutomatically(accounts[0], AUTHORITY, true); 

But my SyncAdapter is just not getting called. Looking into other stackOverFlow questions, there seem to be a problem if targetting API 10 or below with SyncAdapter and that you must add an account explicitly before calling the before methods. So I ended up with this:

AccountManager accountManager = (AccountManager) context.getSystemService(ACCOUNT_SERVICE);

    Account[] accounts = accountManager.getAccounts();
    if(accounts.length == 0){ //ADD DUMMY ACCOUNT
        Account newAccount = new Account(ACCOUNT, ACCOUNT_TYPE);
        ContentResolver.setIsSyncable(accounts[0], AUTHORITY, 1);
        ContentResolver.setSyncAutomatically(accounts[0], AUTHORITY, true); 
        accountManager.addAccountExplicitly(newAccount, null, null);
    }else{
         accounts = accountManager.getAccounts();
        ContentResolver.setIsSyncable(accounts[0], AUTHORITY, 1);   
        ContentResolver.setSyncAutomatically(accounts[0], AUTHORITY, true); 
    }

Now this code gets executed when the user signs in, or if the application was killed and is started up again. I am wondering, should I call setIsSyncable and setSyncAutomatically only when I add the dummyAccount the very first time?

Also, part of the "goodiness" of the SyncAdapter is that it will keep on making the calls in case of an exception. But I don't quite understand how this goes about, so instead I have this:

private void profileUpdate(){       
TableAccounts db = TableAccounts.getInstance(getContext());
boolean isRecordDirty = db.isRecordDirty(signedInUser);   

if(isRecordDirty){
   if(server.upDateUserProfile(signedInUser)){
       db.cleanDirtyRecord(signedInUser);
       turnOffPeriodicSync();
   }else{
       this.turnOnPeriodicSync(this.sync_bundle);   
   }
}else
     turnOffPeriodicSync();

}

As you can see, depending on the result of my upload to the server, I turn on or off a periodic sync.

Chayemor
  • 3,577
  • 4
  • 31
  • 54
  • Are you suggesting that there is a way to emulate Google's Cloud Messaging using your own server instead of Google's, such that either a long-running push connection can be maintained (how, since any app holding the connection could get killed at any time?) or there is some API which will create an Intent to start my service when a TCP connection or message arrives? – Michael Oct 31 '14 at 02:06
  • GCM is by far the best choice, but my setup was this, and I tried to do the best "by the documents", though it didn´t work as documentation stated. The docs at the time stated that you could use incorporated "Network Tickle", that means when there is a good internet connection, the system would execute app's SyncAdapter and have them perform whatever they need. If all went well, they wouldn´t be called again. Which is what I wanted instead of constantly pulling/pushing to the server. But I never got that "Network Tickle" to properly work on Android 2.3.6 and below. – Chayemor Nov 03 '14 at 10:15
  • Any solution? please reply – Rushi M Thakker May 12 '17 at 08:51

2 Answers2

0

Since the accountManager.getAccounts[] return every account on the device, I think nothing guarantee that the account[0] is your app's account (aka, has the ACCOUNT_TYPE of your package name). -- You could call addAccountExplicitly() in any case, if it is existed, then nothing happens.

    Account account = new Account(ACCOUNT, ACCOUNT_TYPE);

    AccountManager accountManager = (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
    accountManager.addAccountExplicitly(account, null, null)
    context.getContentResolver().setSyncAutomatically(account, AUTHORITY, true);
Tin Tran
  • 2,265
  • 1
  • 14
  • 17
0

Disclaimer: I might be mistaken.

On top everything you did, you also have to call ContentResolver.requestSync() from within your app every time you need a sync to run. The sync will not run immediately though, because Android is trying to cluster network activity.

Or you can use Googles Cloud Messaging API to request a sync, but I don't know a whole lot about that.

Konstantin Schubert
  • 3,242
  • 1
  • 31
  • 46