Add broadcast receiver to push to gtasks on save

pull/413/head
Alex Baker 10 years ago
parent 27c9e021b8
commit 17672c1e2e

@ -60,6 +60,13 @@
android:name=".scheduling.GtasksBackgroundService" android:name=".scheduling.GtasksBackgroundService"
android:exported="false" /> android:exported="false" />
<receiver android:name=".receivers.GoogleTaskPushReceiver">
<intent-filter>
<action android:name="org.tasks.TASK_SAVED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<!-- Google Analytics --> <!-- Google Analytics -->
<receiver <receiver

@ -8,8 +8,6 @@ package com.todoroo.astrid.gtasks.sync;
import android.content.ContentValues; import android.content.ContentValues;
import android.text.TextUtils; import android.text.TextUtils;
import com.todoroo.andlib.data.DatabaseDao.ModelUpdateListener;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.dao.MetadataDao; import com.todoroo.astrid.dao.MetadataDao;
@ -24,7 +22,6 @@ import com.todoroo.astrid.gtasks.api.GtasksApiUtilities;
import com.todoroo.astrid.gtasks.api.GtasksInvoker; import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import com.todoroo.astrid.gtasks.api.HttpNotFoundException; import com.todoroo.astrid.gtasks.api.HttpNotFoundException;
import com.todoroo.astrid.gtasks.api.MoveRequest; import com.todoroo.astrid.gtasks.api.MoveRequest;
import com.todoroo.astrid.service.TaskService;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
@ -58,30 +55,14 @@ public class GtasksSyncService {
this.gtasksPreferenceService = gtasksPreferenceService; this.gtasksPreferenceService = gtasksPreferenceService;
this.gtasksMetadataFactory = gtasksMetadataFactory; this.gtasksMetadataFactory = gtasksMetadataFactory;
this.gtasksInvoker = gtasksInvoker; this.gtasksInvoker = gtasksInvoker;
new OperationPushThread(operationQueue).start();
} }
private abstract class SyncOnSaveOperation { public interface SyncOnSaveOperation {
abstract public void op(GtasksInvoker invoker) throws IOException; void op(GtasksInvoker invoker) throws IOException;
} }
private class TaskPushOp extends SyncOnSaveOperation { private class MoveOp implements SyncOnSaveOperation {
protected Task model;
protected long creationDate = DateUtilities.now();
public TaskPushOp(Task model) {
this.model = model;
}
@Override
public void op(GtasksInvoker invoker) throws IOException {
if(DateUtilities.now() - creationDate < 1000) {
AndroidUtilities.sleepDeep(1000 - (DateUtilities.now() - creationDate));
}
pushTaskOnSave(model, model.getMergedValues(), invoker);
}
}
private class MoveOp extends SyncOnSaveOperation {
protected Metadata metadata; protected Metadata metadata;
public MoveOp(Metadata metadata) { public MoveOp(Metadata metadata) {
@ -94,7 +75,7 @@ public class GtasksSyncService {
} }
} }
private class ClearOp extends SyncOnSaveOperation { private class ClearOp implements SyncOnSaveOperation {
private final String listId; private final String listId;
public ClearOp(String listId) { public ClearOp(String listId) {
@ -107,7 +88,7 @@ public class GtasksSyncService {
} }
} }
private class NotifyOp extends SyncOnSaveOperation { private class NotifyOp implements SyncOnSaveOperation {
private final Semaphore sema; private final Semaphore sema;
public NotifyOp(Semaphore sema) { public NotifyOp(Semaphore sema) {
@ -120,30 +101,8 @@ public class GtasksSyncService {
} }
} }
public void initialize() { public void enqueue(SyncOnSaveOperation operation) {
new OperationPushThread(operationQueue).start(); operationQueue.offer(operation);
taskDao.addListener(new ModelUpdateListener<Task>() {
@Override
public void onModelUpdated(final Task model) {
if(model.checkAndClearTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC)) {
return;
}
if (gtasksPreferenceService.isOngoing() && !model.checkTransitory(TaskService.TRANS_REPEAT_COMPLETE)) { //Don't try and sync changes that occur during a normal sync
return;
}
final ContentValues setValues = model.getSetValues();
if(setValues == null || !checkForToken()) {
return;
}
if (!checkValuesForProperties(setValues, TASK_PROPERTIES)) { //None of the properties we sync were updated
return;
}
Task toPush = taskDao.fetch(model.getId(), TASK_PROPERTIES);
operationQueue.offer(new TaskPushOp(toPush));
}
});
} }
private class OperationPushThread extends Thread { private class OperationPushThread extends Thread {
@ -183,22 +142,6 @@ public class GtasksSyncService {
} }
} }
private static final Property<?>[] TASK_PROPERTIES = { Task.ID, Task.TITLE,
Task.NOTES, Task.DUE_DATE, Task.COMPLETION_DATE, Task.DELETION_DATE };
/**
* Checks to see if any of the values changed are among the properties we sync
* @return false if none of the properties we sync were changed, true otherwise
*/
private boolean checkValuesForProperties(ContentValues values, Property<?>[] properties) {
for (Property<?> property : properties) {
if (property != Task.ID && values.containsKey(property.name)) {
return true;
}
}
return false;
}
public void clearCompleted(String listId) { public void clearCompleted(String listId) {
operationQueue.offer(new ClearOp(listId)); operationQueue.offer(new ClearOp(listId));
} }

@ -2,7 +2,6 @@ package org.tasks;
import com.todoroo.astrid.gtasks.GtasksPreferenceService; import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.GtasksTaskListUpdater; import com.todoroo.astrid.gtasks.GtasksTaskListUpdater;
import com.todoroo.astrid.gtasks.sync.GtasksSyncService;
import org.tasks.billing.InventoryHelper; import org.tasks.billing.InventoryHelper;
import org.tasks.billing.PurchaseHelper; import org.tasks.billing.PurchaseHelper;
@ -14,19 +13,16 @@ import javax.inject.Inject;
public class FlavorSetup { public class FlavorSetup {
private final Preferences preferences; private final Preferences preferences;
private final GtasksSyncService gtasksSyncService;
private final GtasksPreferenceService gtasksPreferenceService; private final GtasksPreferenceService gtasksPreferenceService;
private final TeslaUnreadReceiver teslaUnreadReceiver; private final TeslaUnreadReceiver teslaUnreadReceiver;
private final InventoryHelper inventoryHelper; private final InventoryHelper inventoryHelper;
@Inject @Inject
public FlavorSetup(Preferences preferences, public FlavorSetup(Preferences preferences, GtasksPreferenceService gtasksPreferenceService,
@SuppressWarnings("UnusedParameters") GtasksTaskListUpdater gtasksTaskListUpdater, @SuppressWarnings("UnusedParameters") GtasksTaskListUpdater gtasksTaskListUpdater,
@SuppressWarnings("UnusedParameters") PurchaseHelper purchaseHelper, @SuppressWarnings("UnusedParameters") PurchaseHelper purchaseHelper,
GtasksSyncService gtasksSyncService, GtasksPreferenceService gtasksPreferenceService,
TeslaUnreadReceiver teslaUnreadReceiver, InventoryHelper inventoryHelper) { TeslaUnreadReceiver teslaUnreadReceiver, InventoryHelper inventoryHelper) {
this.preferences = preferences; this.preferences = preferences;
this.gtasksSyncService = gtasksSyncService;
this.gtasksPreferenceService = gtasksPreferenceService; this.gtasksPreferenceService = gtasksPreferenceService;
this.teslaUnreadReceiver = teslaUnreadReceiver; this.teslaUnreadReceiver = teslaUnreadReceiver;
this.inventoryHelper = inventoryHelper; this.inventoryHelper = inventoryHelper;
@ -36,6 +32,5 @@ public class FlavorSetup {
inventoryHelper.initialize(); inventoryHelper.initialize();
teslaUnreadReceiver.setEnabled(preferences.getBoolean(R.string.p_tesla_unread_enabled, false)); teslaUnreadReceiver.setEnabled(preferences.getBoolean(R.string.p_tesla_unread_enabled, false));
gtasksPreferenceService.stopOngoing(); // if sync ongoing flag was set, clear it gtasksPreferenceService.stopOngoing(); // if sync ongoing flag was set, clear it
gtasksSyncService.initialize();
} }
} }

@ -1,6 +1,7 @@
package org.tasks.injection; package org.tasks.injection;
import org.tasks.locale.receiver.FireReceiver; import org.tasks.locale.receiver.FireReceiver;
import org.tasks.receivers.GoogleTaskPushReceiver;
import org.tasks.receivers.TeslaUnreadReceiver; import org.tasks.receivers.TeslaUnreadReceiver;
import dagger.Subcomponent; import dagger.Subcomponent;
@ -10,4 +11,6 @@ public interface BroadcastComponent extends BaseBroadcastComponent {
void inject(TeslaUnreadReceiver teslaUnreadReceiver); void inject(TeslaUnreadReceiver teslaUnreadReceiver);
void inject(FireReceiver fireReceiver); void inject(FireReceiver fireReceiver);
void inject(GoogleTaskPushReceiver forceSyncReceiver);
} }

@ -0,0 +1,92 @@
package org.tasks.receivers;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.SyncFlags;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import com.todoroo.astrid.gtasks.sync.GtasksSyncService;
import com.todoroo.astrid.service.TaskService;
import org.tasks.injection.BroadcastComponent;
import org.tasks.injection.InjectingBroadcastReceiver;
import java.io.IOException;
import javax.inject.Inject;
public class GoogleTaskPushReceiver extends InjectingBroadcastReceiver {
private static final Property<?>[] TASK_PROPERTIES = { Task.ID, Task.TITLE,
Task.NOTES, Task.DUE_DATE, Task.COMPLETION_DATE, Task.DELETION_DATE };
@Inject GtasksPreferenceService gtasksPreferenceService;
@Inject GtasksSyncService gtasksSyncService;
@Inject TaskDao taskDao;
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
Task model = intent.getParcelableExtra(AstridApiConstants.EXTRAS_TASK);
if(model.checkAndClearTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC)) {
return;
}
if (gtasksPreferenceService.isOngoing() && !model.checkTransitory(TaskService.TRANS_REPEAT_COMPLETE)) { //Don't try and sync changes that occur during a normal sync
return;
}
final ContentValues setValues = model.getSetValues();
if(setValues == null || !gtasksPreferenceService.isLoggedIn()) {
return;
}
if (!checkValuesForProperties(setValues, TASK_PROPERTIES)) { //None of the properties we sync were updated
return;
}
Task toPush = taskDao.fetch(model.getId(), TASK_PROPERTIES);
gtasksSyncService.enqueue(new TaskPushOp(toPush));
}
@Override
protected void inject(BroadcastComponent component) {
component.inject(this);
}
private class TaskPushOp implements GtasksSyncService.SyncOnSaveOperation {
protected Task model;
protected long creationDate = DateUtilities.now();
public TaskPushOp(Task model) {
this.model = model;
}
@Override
public void op(GtasksInvoker invoker) throws IOException {
if(DateUtilities.now() - creationDate < 1000) {
AndroidUtilities.sleepDeep(1000 - (DateUtilities.now() - creationDate));
}
gtasksSyncService.pushTaskOnSave(model, model.getMergedValues(), invoker);
}
}
/**
* Checks to see if any of the values changed are among the properties we sync
* @return false if none of the properties we sync were changed, true otherwise
*/
private boolean checkValuesForProperties(ContentValues values, Property<?>[] properties) {
for (Property<?> property : properties) {
if (property != Task.ID && values.containsKey(property.name)) {
return true;
}
}
return false;
}
}

@ -43,8 +43,9 @@ public class AstridApiConstants {
/** /**
* Extras name for task id * Extras name for task id
*/ */
public static final String EXTRAS_TASK_ID = "task"; public static final String EXTRAS_TASK_ID = "task_id";
public static final String EXTRAS_TASK = "task";
/** /**
* Extras name for old task due date * Extras name for old task due date
*/ */
@ -76,6 +77,8 @@ public class AstridApiConstants {
*/ */
public static final String BROADCAST_EVENT_TASK_REPEATED = BuildConfig.APPLICATION_ID + ".TASK_REPEATED"; public static final String BROADCAST_EVENT_TASK_REPEATED = BuildConfig.APPLICATION_ID + ".TASK_REPEATED";
public static final String BROADCAST_EVENT_TASK_SAVED = BuildConfig.APPLICATION_ID + ".TASK_SAVED";
/** /**
* Action name for broadcast intent notifying that tag was deleted * Action name for broadcast intent notifying that tag was deleted
*/ */

@ -57,11 +57,17 @@ public class TaskDao {
private GeofenceService geofenceService; private GeofenceService geofenceService;
@Inject @Inject
public TaskDao(Database database, MetadataDao metadataDao, Broadcaster broadcaster, public TaskDao(Database database, MetadataDao metadataDao, final Broadcaster broadcaster,
ReminderService reminderService, NotificationManager notificationManager, ReminderService reminderService, NotificationManager notificationManager,
Preferences preferences, GeofenceService geofenceService) { Preferences preferences, GeofenceService geofenceService) {
this.geofenceService = geofenceService; this.geofenceService = geofenceService;
dao = new RemoteModelDao<>(database, Task.class); dao = new RemoteModelDao<>(database, Task.class);
dao.addListener(new DatabaseDao.ModelUpdateListener<Task>() {
@Override
public void onModelUpdated(Task model) {
broadcaster.taskUpdated(model);
}
});
this.preferences = preferences; this.preferences = preferences;
this.metadataDao = metadataDao; this.metadataDao = metadataDao;
this.broadcaster = broadcaster; this.broadcaster = broadcaster;
@ -107,10 +113,6 @@ public class TaskDao {
return dao.deleteWhere(criterion); return dao.deleteWhere(criterion);
} }
public void addListener(DatabaseDao.ModelUpdateListener<Task> modelUpdateListener) {
dao.addListener(modelUpdateListener);
}
public List<Task> toList(Query query) { public List<Task> toList(Query query) {
return dao.toList(query); return dao.toList(query);
} }
@ -126,11 +128,6 @@ public class TaskDao {
*/ */
public static class TaskCriteria { public static class TaskCriteria {
/** @return tasks by id */
public static Criterion byId(long id) {
return Task.ID.eq(id);
}
/** @return tasks that were not deleted */ /** @return tasks that were not deleted */
public static Criterion notDeleted() { public static Criterion notDeleted() {
return Task.DELETION_DATE.eq(0); return Task.DELETION_DATE.eq(0);

@ -4,6 +4,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.data.Task;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
import org.tasks.receivers.CompleteTaskReceiver; import org.tasks.receivers.CompleteTaskReceiver;
@ -47,6 +48,12 @@ public class Broadcaster {
context.sendBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH)); context.sendBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH));
} }
public void taskUpdated(final Task task) {
context.sendBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_TASK_SAVED) {{
putExtra(AstridApiConstants.EXTRAS_TASK, task);
}});
}
private void sendOrderedBroadcast(Intent intent) { private void sendOrderedBroadcast(Intent intent) {
sendOrderedBroadcast(intent, null); sendOrderedBroadcast(intent, null);
} }

Loading…
Cancel
Save