2

I am trying to create SyncAdapter running background operation (without foreground notification).

It is working, except the case when activity (task) which triggered ContentResolver.requestSync(...) is swiped away from recent applications. In that case process is killed and onPerformSync(...) is not finished.

I know, this is expected Android behavior, but in regular Service I would set

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);

    return START_REDELIVER_INTENT;
}

or maybe use

@Override
public void onTaskRemoved(Intent rootIntent) {
    super.onTaskRemoved(rootIntent);

    restartSynchronization();
}

to retry synchronization, but this is not working in the SyncAdapterService.

How can I ensure synchronization continues/retry after activity is swiped away from recent applications?

Thank you in advance.

Jan Pintr
  • 21
  • 2
  • I found out, that `onStartCommand()` is not called for `SyncAdapterService` which makes sense due to this service is just for returning `Binder`. But still I would expect `onTaskRemoved()` is. – Jan Pintr Aug 01 '14 at 07:20

1 Answers1

0

After some reseach I found out, that onTaskRemoved(...) is called only when startService(...) is called and not when someone only binds to it.

So I did work around by starting service in onBind(...) and stopping it and its process in onUnbind(...) methods.

This is final code:

public class SyncAdapterService extends Service {
private static final Object sSyncAdapterLock = new Object();
private static MySyncAdapter sSyncAdapter = null;

@Override
public void onCreate() {
    super.onCreate();

    synchronized (sSyncAdapterLock) {
        if (sSyncAdapter == null) {
            sSyncAdapter = new MySyncAdapter(getApplicationContext());
        }
    }
}

@Override
public void onTaskRemoved(Intent rootIntent) {
    super.onTaskRemoved(rootIntent);

    /*
     * Rescheduling sync due to running one is killed on removing from recent applications.
     */
    SyncHelper.requestSyncNow(this);
}

@Override
public IBinder onBind(Intent intent) {
    /*
     * Start service to watch {@link @onTaskRemoved(Intent)}
     */
    startService(new Intent(this, SyncAdapterService.class));

    return sSyncAdapter.getSyncAdapterBinder();
}

@Override
public boolean onUnbind(Intent intent) {
    /*
     * No more need watch task removes.
     */
    stopSelf();

    /*
     * Stops current process, it's not necessarily required. Assumes sync process is different
     * application one. (<service android:process=":sync" /> for example).
     */
    Process.killProcess(Process.myPid());

    return super.onUnbind(intent);
}
}
Jan Pintr
  • 21
  • 2