0

I'm running a sync adapter that periodically check if there are new data available at the remote server. If there is a new data I want to create a notification about it. It seems that the whole mechanism works fine but not EVERY time. Sometimes I don't get a notification. And sometimes it works flawless. I can't figure out why. Maybe I miss some crucial knowledge about a syncadapter implementation in android?

My SyncAdapter onPerformSync function:

@Override
public void onPerformSync(Account account, Bundle extras, String authority,
                          ContentProviderClient contentProviderClient, SyncResult syncResult) {

    SyncResult result = new SyncResult();
    try {
        Log.w("APPP", "HERE SYNC!!!!!");
        isNewPrivateMessageWasReceivedInCurrentUpdate=false;
        receiveMessages(contentProviderClient);
        deleteMessages(contentProviderClient);


    } catch (RemoteException | IOException e) {
        syncResult.hasHardError();
    }
    finally {
        if(isNewMessageWasReceivedInCurrentUpdate) {
            MainActivity ma = (MainActivity) MainActivity.GetContext();
            ma.startNotification("New messages", "", true);
        }

    }

isNewMessageWasReceivedInCurrentUpdate variable gets updated it receiveMessages function.

startNotification function

public void startNotification(String contentTitle, String contentText, Boolean isChat) {
    notification = new NotificationCompat.Builder(MainActivity.this);
    notification.setAutoCancel(true);
    notification.setContentTitle(contentTitle);
    notification.setContentText(contentText);
    notification.setTicker("New Messages!");
    notification.setSmallIcon(R.drawable.ic_launcher);
    Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    notification.setSound(alarmSound);
    stackBuilder = TaskStackBuilder.create(MainActivity.this);
    stackBuilder.addParentStack(MainActivity.class);

    resultIntent = new Intent(MainActivity.this, MainActivity.class);
    if (isChat) {
        resultIntent.putExtra(TAB_TO_SHOW, TAB_CHATS);
    } 


    stackBuilder.addNextIntent(resultIntent);
    pIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
    notification.setContentIntent(pIntent);
    manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    if (isChat) {
        manager.notify(NotificationID.MESSAGES.ordinal(), notification.build());
    }


}

SyncAdapter initialization in MainActivity

    newAccountPrivate = new Account("Private", getResources().getString(R.string.account_name));
   ContentResolver.setSyncAutomatically(
            newAccountPrivate, MainActivity.PROVIDER_NAME, true);
    ContentResolver.addPeriodicSync(newAccountPrivate, MainActivity.PROVIDER_NAME, Bundle.EMPTY, 300);//SYNC_INTERVAL);
    ContentResolver.setIsSyncable(newAccountPrivate, MainActivity.PROVIDER_NAME, 1);
    ContentResolver.setMasterSyncAutomatically(true);
    AccountManager accountManagerPrivate = AccountManager.get(this);
    accountManagerPrivate.addAccountExplicitly(newAccountPrivate, null, null);

Manifest file

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

  <service android:name=".AuthenticatorService"
        android:exported="true"
        android:process=":auth">>
        <intent-filter>
            <action android:name="android.accounts.AccountAuthenticator" />
        </intent-filter>
        <meta-data
            android:name="android.accounts.AccountAuthenticator"
            android:resource="@xml/authenticator" />
    </service>

    <provider
        android:name=".DataContentProvider"
        android:authorities="authority.provider"
        android:exported="false"
        android:multiprocess="true"
        android:syncable="true"/>

    <service
        android:name=".SyncService"
        android:exported="true">
        <intent-filter>
            <action android:name="android.content.SyncAdapter" />
        </intent-filter>
        <meta-data
            android:name="android.content.SyncAdapter"
            android:resource="@xml/syncadapter" />
    </service>

    <meta-data android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />

SyncService

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;


public class SyncService extends Service {
private static SyncAdapter syncAdapter = null;
// Object to use as a thread-safe lock
private static final Object syncAdapterLock = new Object();

public SyncService() {
    super();
}
@Override
public void onCreate() {
    super.onCreate();
/*
 * Create the sync adapter as a singleton.
 * Set the sync adapter as syncable
 * Disallow parallel syncs
 */
    synchronized (syncAdapterLock) {
        if (syncAdapter == null) {
            syncAdapter = 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 syncAdapter.getSyncAdapterBinder();
}
}

SyncAdapter.xml

<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"

android:contentAuthority="authority.provider"
android:accountType="@string/account_name"
android:userVisible="true"
android:allowParallelSyncs="false"
android:isAlwaysSyncable="true"/>

Thank you!

Alexander
  • 35
  • 1
  • 8
  • 5
    omg `MainActivity.GetContext()` please dont tell me that it is a static method which returns Activity instance ... you dont need myactivity instance you just need some context ... – Selvin Mar 17 '15 at 22:21
  • Yes, it's a static method which returns Activity instance.. I use fragments in my application and I use GetContext a lot.. Is this a bad solution?? Please explain me. Which context is available in SyncService that I can use instead? – Alexander Mar 17 '15 at 22:25
  • 2
    very bad solution ... fragments have already method for getting parent activity .... also AbstractThreadedSyncAdapter has a method for getting context ... just check the android sdk documentation (names of those methods are obvious) – Selvin Mar 17 '15 at 22:28
  • Ok. I''ll check it. I have two more questions:1.Why it is a bad solution? 2. Is this a reason for the problem I described? – Alexander Mar 17 '15 at 22:36
  • 2
    1. have you heard about activity's leaks or activity's life cycle 2. i don't know ... you did not describe the problem at all ... (seriously, "it works sometimes and sometimes not" is not a real description of the problem) – Selvin Mar 17 '15 at 22:42
  • 1. I'm familiar with activity's life cycle principle. Can you explain how what I did affects the activity's leaks? 2. Practically this is the problem.. Let's put it this way : Can you see any problem (besides what you already mentioned) in my implementation that can lead to faults in the desired functionality - triggering notification from my SyncAdapter? – Alexander Mar 17 '15 at 22:50
  • I did my homework and understood the issue. Hope it will resolve the problem I tried to describe here. Thanks Selvin – Alexander Mar 18 '15 at 07:19

0 Answers0