Fix for a couple synchronization issues, created producteev background service

pull/14/head
Tim Su 14 years ago
parent adbc132c02
commit a3e2738d91

@ -302,6 +302,7 @@
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<service android:name="com.todoroo.astrid.producteev.ProducteevBackgroundService"/>
<!-- rmilk -->
<receiver android:name="com.todoroo.astrid.rmilk.MilkFilterExposer">

@ -230,6 +230,11 @@ public abstract class SyncProvider<TYPE extends TaskContainer> {
remote = pull(remote);
remote.task.setId(local.task.getId());
data.remoteUpdated.set(remoteIndex, remote);
// if remote is deleted, undelete it, since we just created
if(remote.task.isDeleted())
remote.task.setValue(Task.DELETION_DATE, 0L);
} else {
create(local);
}

@ -0,0 +1,128 @@
package com.todoroo.astrid.producteev;
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.timsu.astrid.R;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.producteev.sync.ProducteevSyncProvider;
import com.todoroo.astrid.utility.Preferences;
/**
* SynchronizationService is the service that performs Astrid's background
* synchronization with online task managers. Starting this service
* schedules a repeating alarm which handles the synchronization
*
* @author Tim Su
*
*/
public class ProducteevBackgroundService 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$
// --- BroadcastReceiver abstract methods
/** Receive the alarm - start the synchronize service! */
@Override
public void onStart(Intent intent, int startId) {
if(SYNC_ACTION.equals(intent.getAction()))
startSynchronization(this);
}
/** Start the actual synchronization */
private void startSynchronization(Context context) {
if(context == null || context.getResources() == null)
return;
ContextManager.setContext(context);
if(ProducteevUtilities.INSTANCE.isOngoing())
return;
new ProducteevSyncProvider().synchronize(context);
}
// --- alarm management
/**
* Schedules repeating alarm for auto-synchronization
*/
public static void scheduleService() {
int syncFrequencySeconds = Preferences.getIntegerFromString(
R.string.producteev_PPr_interval_key, -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 static 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 static Intent createAlarmIntent(Context context) {
Intent intent = new Intent(context, ProducteevBackgroundService.class);
intent.setAction(SYNC_ACTION);
return intent;
}
// --- utility methods
private static long computeNextSyncOffset(long interval) {
// figure out last synchronize time
long lastSyncDate = ProducteevUtilities.INSTANCE.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;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

@ -1,5 +1,7 @@
package com.todoroo.astrid.producteev;
import android.content.Intent;
import com.timsu.astrid.R;
import com.todoroo.astrid.common.SyncProviderPreferences;
import com.todoroo.astrid.common.SyncProviderUtilities;
@ -21,7 +23,8 @@ public class ProducteevPreferences extends SyncProviderPreferences {
@Override
public void startSync() {
new ProducteevSyncProvider().synchronize(this);
startService(new Intent(ProducteevBackgroundService.SYNC_ACTION, null,
this, ProducteevBackgroundService.class));
}
@Override

@ -69,6 +69,7 @@ public final class ProducteevDataService {
*/
public void clearMetadata() {
metadataDao.deleteWhere(Metadata.KEY.eq(ProducteevTask.METADATA_KEY));
metadataDao.deleteWhere(Metadata.KEY.eq(ProducteevNote.METADATA_KEY));
}
/**

@ -254,22 +254,22 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
// ----------------------------------------------------------------------
@Override
protected void create(ProducteevTaskContainer task) throws IOException {
Task local = task.task;
protected void create(ProducteevTaskContainer local) throws IOException {
Task localTask = local.task;
long dashboard = defaultDashboard;
if(task.pdvTask.containsNonNullValue(ProducteevTask.DASHBOARD_ID))
dashboard = task.pdvTask.getValue(ProducteevTask.DASHBOARD_ID);
JSONObject response = invoker.tasksCreate(local.getValue(Task.TITLE),
null, dashboard, createDeadline(local), createReminder(local),
local.isCompleted() ? 2 : 1, createStars(local));
if(local.pdvTask.containsNonNullValue(ProducteevTask.DASHBOARD_ID))
dashboard = local.pdvTask.getValue(ProducteevTask.DASHBOARD_ID);
JSONObject response = invoker.tasksCreate(localTask.getValue(Task.TITLE),
null, dashboard, createDeadline(localTask), createReminder(localTask),
localTask.isCompleted() ? 2 : 1, createStars(localTask));
ProducteevTaskContainer newRemoteTask;
try {
newRemoteTask = parseRemoteTask(response);
} catch (JSONException e) {
throw new ApiResponseParseException(e);
}
transferIdentifiers(newRemoteTask, task);
push(task, newRemoteTask);
transferIdentifiers(newRemoteTask, local);
push(local, newRemoteTask);
}
/** Create a task container for the given RtmTaskSeries

@ -46,7 +46,7 @@ public class ProducteevTaskContainer extends TaskContainer {
if(ProducteevTask.METADATA_KEY.equals(item.getValue(Metadata.KEY))) {
pdvTask = item;
iterator.remove();
break;
// don't break, could be multiple
}
}
if(this.pdvTask == null) {

@ -39,6 +39,8 @@ public final class ReminderService {
private static final Property<?>[] PROPERTIES = new Property<?>[] {
Task.ID,
Task.COMPLETION_DATE,
Task.DELETION_DATE,
Task.DUE_DATE,
Task.REMINDER_FLAGS,
Task.REMINDER_PERIOD,
@ -155,6 +157,9 @@ public final class ReminderService {
}
}
if(task.isCompleted() || task.isDeleted())
return;
// random reminders
long whenRandom = calculateNextRandomReminder(task);

@ -17,7 +17,7 @@
android:title="@string/rmilk_MPr_group_options">
<ListPreference
android:key="@string/rmilk_MPr_interval_key"
android:key="@string/producteev_PPr_interval_key"
android:entries="@array/rmilk_MPr_interval_entries"
android:entryValues="@array/rmilk_MPr_interval_values"
android:title="@string/rmilk_MPr_interval_title" />

@ -7,15 +7,18 @@ import java.util.Map.Entry;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.os.Bundle;
import android.os.IBinder;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
@ -62,9 +65,11 @@ import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
import com.todoroo.astrid.model.Metadata;
import com.todoroo.astrid.model.Task;
import com.todoroo.astrid.producteev.ProducteevBackgroundService;
import com.todoroo.astrid.reminders.Notifications;
import com.todoroo.astrid.reminders.ReminderService;
import com.todoroo.astrid.reminders.ReminderService.AlarmScheduler;
import com.todoroo.astrid.rmilk.MilkBackgroundService;
import com.todoroo.astrid.rmilk.MilkPreferences;
import com.todoroo.astrid.service.AddOnService;
import com.todoroo.astrid.service.MetadataService;
@ -177,6 +182,9 @@ public class TaskListActivity extends ListActivity implements OnScrollListener {
loadContextMenuIntents();
}
}).start();
// bind to services that require task list refreshing
bindServices();
}
/**
@ -330,51 +338,22 @@ public class TaskListActivity extends ListActivity implements OnScrollListener {
}
/**
* Quick-add a new task
* @param title
* @return
*/
@SuppressWarnings("nls")
protected Task quickAddTask(String title, boolean selectNewTask) {
try {
Task task = new Task();
task.setValue(Task.TITLE, title.trim());
ContentValues forMetadata = null;
if(filter.valuesForNewTasks != null && filter.valuesForNewTasks.size() > 0) {
ContentValues forTask = new ContentValues();
forMetadata = new ContentValues();
for(Entry<String, Object> item : filter.valuesForNewTasks.valueSet()) {
if(Long.valueOf(Filter.VALUE_NOW).equals(item.getValue()))
item.setValue(DateUtilities.now());
if(item.getKey().startsWith(Task.TABLE.name))
AndroidUtilities.putInto(forTask, item.getKey(), item.getValue());
else
AndroidUtilities.putInto(forMetadata, item.getKey(), item.getValue());
}
task.mergeWith(forTask);
}
taskService.save(task, false);
if(forMetadata != null && forMetadata.size() > 0) {
Metadata metadata = new Metadata();
metadata.setValue(Metadata.TASK, task.getId());
metadata.mergeWith(forMetadata);
metadataService.save(metadata);
public void bindServices() {
ServiceConnection refreshConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.err.println("connected to service " + name);
//
}
TextView quickAdd = (TextView)findViewById(R.id.quickAddText);
quickAdd.setText(""); //$NON-NLS-1$
if(selectNewTask) {
@Override
public void onServiceDisconnected(ComponentName name) {
// service disconnected, let's refresh
System.err.println("your junk was done, refreshing");
loadTaskListContent(true);
selectCustomId(task.getId());
}
return task;
} catch (Exception e) {
exceptionService.displayAndReportError(this, "quick-add-task", e);
return new Task();
}
};
bindService(new Intent(this, MilkBackgroundService.class), refreshConnection, 0);
bindService(new Intent(this, ProducteevBackgroundService.class), refreshConnection, 0);
}
/* ======================================================================
@ -589,6 +568,53 @@ public class TaskListActivity extends ListActivity implements OnScrollListener {
* ============================================================== actions
* ====================================================================== */
/**
* Quick-add a new task
* @param title
* @return
*/
@SuppressWarnings("nls")
protected Task quickAddTask(String title, boolean selectNewTask) {
try {
Task task = new Task();
task.setValue(Task.TITLE, title.trim());
ContentValues forMetadata = null;
if(filter.valuesForNewTasks != null && filter.valuesForNewTasks.size() > 0) {
ContentValues forTask = new ContentValues();
forMetadata = new ContentValues();
for(Entry<String, Object> item : filter.valuesForNewTasks.valueSet()) {
if(Long.valueOf(Filter.VALUE_NOW).equals(item.getValue()))
item.setValue(DateUtilities.now());
if(item.getKey().startsWith(Task.TABLE.name))
AndroidUtilities.putInto(forTask, item.getKey(), item.getValue());
else
AndroidUtilities.putInto(forMetadata, item.getKey(), item.getValue());
}
task.mergeWith(forTask);
}
taskService.save(task, false);
if(forMetadata != null && forMetadata.size() > 0) {
Metadata metadata = new Metadata();
metadata.setValue(Metadata.TASK, task.getId());
metadata.mergeWith(forMetadata);
metadataService.save(metadata);
}
TextView quickAdd = (TextView)findViewById(R.id.quickAddText);
quickAdd.setText(""); //$NON-NLS-1$
if(selectNewTask) {
loadTaskListContent(true);
selectCustomId(task.getId());
}
return task;
} catch (Exception e) {
exceptionService.displayAndReportError(this, "quick-add-task", e);
return new Task();
}
}
protected Pair<CharSequence, Intent>[] contextMenuItemCache = null;
protected void loadContextMenuIntents() {

Loading…
Cancel
Save