Skip to content

Commit

Permalink
Added sync background service
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Su committed Sep 29, 2010
1 parent 9eb1ab6 commit 42dcb79
Showing 1 changed file with 150 additions and 0 deletions.
150 changes: 150 additions & 0 deletions src/com/todoroo/astrid/sync/SyncBackgroundService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package com.todoroo.astrid.sync;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.service.ExceptionService;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.andlib.utility.Preferences;

/**
* Performs synchronization service logic in background service to avoid
* ANR (application not responding) messages.
* <p>
* Starting this service
* schedules a repeating alarm which handles
* synchronization with your serv
*
* @author Tim Su
*
*/
abstract public class SyncBackgroundService extends Service {

/** Minimum time before an auto-sync */
private static final long AUTO_SYNC_MIN_OFFSET = 5*60*1000L;

/** alarm identifier */
public static final String SYNC_ACTION = "sync"; //$NON-NLS-1$

@Autowired private ExceptionService exceptionService;

// --- abstract methods

abstract protected SyncProvider<?> getSyncProvider();

abstract protected SyncProviderUtilities getSyncUtilities();

// --- implementation

public SyncBackgroundService() {
DependencyInjectionService.getInstance().inject(this);
}

/** Receive the alarm - start the synchronize service! */
@Override
public void onStart(Intent intent, int startId) {
try {
if(intent != null && SYNC_ACTION.equals(intent.getAction()))
startSynchronization(this);
} catch (Exception e) {
exceptionService.reportError(getSyncUtilities().getIdentifier() + "-bg-sync", e); //$NON-NLS-1$
}
}

/** Start the actual synchronization */
private void startSynchronization(Context context) {
if(context == null || context.getResources() == null)
return;

ContextManager.setContext(context);

if(!getSyncUtilities().isLoggedIn())
return;

getSyncProvider().synchronize(context);
}


@Override
public IBinder onBind(Intent intent) {
return null;
}

// --- alarm management

/**
* Schedules repeating alarm for auto-synchronization
*/
public void scheduleService() {
int syncFrequencySeconds = Preferences.getIntegerFromString(
getSyncUtilities().getSyncIntervalKey(), -1);
Context context = ContextManager.getContext();
if(syncFrequencySeconds <= 0) {
unscheduleService(context);
return;
}

// figure out synchronization frequency
long interval = 1000L * syncFrequencySeconds;
long offset = computeNextSyncOffset(interval);

// give a little padding
offset = Math.max(offset, AUTO_SYNC_MIN_OFFSET);

AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getService(context, 0,
createAlarmIntent(context), PendingIntent.FLAG_UPDATE_CURRENT);

Log.i("Astrid", "Autosync set for " + offset / 1000 //$NON-NLS-1$ //$NON-NLS-2$
+ " seconds repeating every " + syncFrequencySeconds); //$NON-NLS-1$

// cancel all existing
am.cancel(pendingIntent);

// schedule new
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + offset,
interval, pendingIntent);
}


/**
* Removes repeating alarm for auto-synchronization
*/
private void unscheduleService(Context context) {
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getService(context, 0,
createAlarmIntent(context), PendingIntent.FLAG_UPDATE_CURRENT);
am.cancel(pendingIntent);
}

/** Create the alarm intent */
private Intent createAlarmIntent(Context context) {
Intent intent = new Intent(context, getClass());
intent.setAction(SYNC_ACTION);
return intent;
}

// --- utility methods


private long computeNextSyncOffset(long interval) {
// figure out last synchronize time
long lastSyncDate = getSyncUtilities().getLastSyncDate();

// if user never synchronized, give them a full offset period before bg sync
if(lastSyncDate != 0)
return Math.max(0, lastSyncDate + interval - DateUtilities.now());
else
return interval;
}


}

0 comments on commit 42dcb79

Please sign in to comment.