From 74019d7cb189805174fb889efc65eb44703a3430 Mon Sep 17 00:00:00 2001 From: Sam Bosley Date: Wed, 12 Dec 2012 15:26:45 -0800 Subject: [PATCH 1/5] Started refactoring to use GCM instead of C2DM --- astrid/.classpath | 1 + astrid/AndroidManifest.xml | 18 +++- astrid/libs/gcm-src.jar | Bin 0 -> 12814 bytes astrid/libs/gcm.jar | Bin 0 -> 13662 bytes .../com/timsu/astrid/C2DMReceiver.java | 82 +------------- .../com/timsu/astrid/GCMIntentService.java | 102 ++++++++++++++++++ .../astrid/actfm/ActFmLoginActivity.java | 9 +- .../astrid/actfm/sync/ActFmSyncService.java | 16 +++ .../actfm/sync/ActFmSyncV2Provider.java | 8 +- 9 files changed, 144 insertions(+), 92 deletions(-) create mode 100644 astrid/libs/gcm-src.jar create mode 100644 astrid/libs/gcm.jar create mode 100644 astrid/plugin-src/com/timsu/astrid/GCMIntentService.java diff --git a/astrid/.classpath b/astrid/.classpath index a20a47fca..20e839511 100644 --- a/astrid/.classpath +++ b/astrid/.classpath @@ -31,5 +31,6 @@ + diff --git a/astrid/AndroidManifest.xml b/astrid/AndroidManifest.xml index 94d5cd719..4482d9033 100644 --- a/astrid/AndroidManifest.xml +++ b/astrid/AndroidManifest.xml @@ -45,6 +45,9 @@ + + + @@ -415,12 +418,17 @@ - - - - - + + + + + + + + + + wSUzNQdiSe+~`+VD&l|`aPb1 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 KAZ7gH>Hh##xH#$n literal 0 HcmV?d00001 diff --git a/astrid/libs/gcm.jar b/astrid/libs/gcm.jar new file mode 100644 index 0000000000000000000000000000000000000000..ac109a830ebe95e89e1456e23328212ad70576dc GIT binary patch literal 13662 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 K2s`$_e*GU@T3ng{ literal 0 HcmV?d00001 diff --git a/astrid/plugin-src/com/timsu/astrid/C2DMReceiver.java b/astrid/plugin-src/com/timsu/astrid/C2DMReceiver.java index 493fb582b..d3dd2d14a 100644 --- a/astrid/plugin-src/com/timsu/astrid/C2DMReceiver.java +++ b/astrid/plugin-src/com/timsu/astrid/C2DMReceiver.java @@ -15,8 +15,6 @@ import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.os.Build; -import android.provider.Settings.Secure; import android.text.TextUtils; import android.util.Log; @@ -28,7 +26,6 @@ import com.todoroo.andlib.service.NotificationManager; import com.todoroo.andlib.service.NotificationManager.AndroidNotificationManager; import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.sql.QueryTemplate; -import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.Preferences; import com.todoroo.astrid.actfm.TagViewFragment; @@ -81,33 +78,14 @@ public class C2DMReceiver extends BroadcastReceiver { } }; - private static String getDeviceID() { - String id = Secure.getString(ContextManager.getContext().getContentResolver(), Secure.ANDROID_ID);; - if(AndroidUtilities.getSdkVersion() > 8) { //Gingerbread and above - - //the following uses relection to get android.os.Build.SERIAL to avoid having to build with Gingerbread - try { - if(!Build.UNKNOWN.equals(Build.SERIAL)) - id = Build.SERIAL; - } catch(Exception e) { - // Ah well - } - } - - if (TextUtils.isEmpty(id) || "9774d56d682e549c".equals(id)) { // check for failure or devices affected by the "9774d56d682e549c" bug - return null; - } - - return id; - } - @Override public void onReceive(Context context, final Intent intent) { + if (Preferences.getStringValue(GCMIntentService.PREF_REGISTRATION) != null) // GCM takes precedence + return; + ContextManager.setContext(context); DependencyInjectionService.getInstance().inject(this); - if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) { - handleRegistration(intent); - } else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) { + if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) { new Thread(new Runnable() { @Override public void run() { @@ -419,56 +397,4 @@ public class C2DMReceiver extends BroadcastReceiver { return true; } - private void handleRegistration(Intent intent) { - final String registration = intent.getStringExtra("registration_id"); - if (intent.getStringExtra("error") != null) { - Log.w("astrid-actfm", "error-c2dm: " + intent.getStringExtra("error")); - } else if (intent.getStringExtra("unregistered") != null) { - // un-registration done - } else if (registration != null) { - DependencyInjectionService.getInstance().inject(this); - new Thread() { - @Override - public void run() { - try { - String deviceId = getDeviceID(); - if (deviceId != null) - actFmSyncService.invoke("user_set_c2dm", "c2dm", registration, "device_id", deviceId); - else - actFmSyncService.invoke("user_set_c2dm", "c2dm", registration); - Preferences.setString(PREF_REGISTRATION, registration); - } catch (IOException e) { - Log.e("astrid-actfm", "error-c2dm-transfer", e); - } - } - }.start(); - } - } - - /** try to request registration from c2dm service */ - public static void register() { - if(Preferences.getStringValue(PREF_REGISTRATION) != null) - return; - - new Thread() { - @Override - public void run() { - Context context = ContextManager.getContext(); - Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER"); - registrationIntent.putExtra("app", PendingIntent.getBroadcast(context, 0, new Intent(), 0)); // boilerplate - registrationIntent.putExtra("sender", C2DM_SENDER); - context.startService(registrationIntent); - } - }.start(); - } - - /** unregister with c2dm service */ - public static void unregister() { - Preferences.setString(PREF_REGISTRATION, null); - Context context = ContextManager.getContext(); - Intent unregIntent = new Intent("com.google.android.c2dm.intent.UNREGISTER"); - unregIntent.putExtra("app", PendingIntent.getBroadcast(context, 0, new Intent(), 0)); - context.startService(unregIntent); - } - } diff --git a/astrid/plugin-src/com/timsu/astrid/GCMIntentService.java b/astrid/plugin-src/com/timsu/astrid/GCMIntentService.java new file mode 100644 index 000000000..e9a2f0ab2 --- /dev/null +++ b/astrid/plugin-src/com/timsu/astrid/GCMIntentService.java @@ -0,0 +1,102 @@ +package com.timsu.astrid; + +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.provider.Settings.Secure; +import android.text.TextUtils; +import android.util.Log; + +import com.google.android.gcm.GCMBaseIntentService; +import com.google.android.gcm.GCMRegistrar; +import com.todoroo.andlib.service.Autowired; +import com.todoroo.andlib.service.ContextManager; +import com.todoroo.andlib.service.DependencyInjectionService; +import com.todoroo.andlib.utility.AndroidUtilities; +import com.todoroo.astrid.actfm.sync.ActFmSyncService; + +@SuppressWarnings("nls") +public class GCMIntentService extends GCMBaseIntentService { + + public static final String SENDER_ID = "gcm@astrid.com"; //$NON-NLS-1$ + public static final String PREF_REGISTRATION = "gcm_id"; + public static final String PREF_NEEDS_REGISTRATION = "gcm_needs_reg"; + + public static String getDeviceID() { + String id = Secure.getString(ContextManager.getContext().getContentResolver(), Secure.ANDROID_ID);; + if(AndroidUtilities.getSdkVersion() > 8) { //Gingerbread and above + //the following uses relection to get android.os.Build.SERIAL to avoid having to build with Gingerbread + try { + if(!Build.UNKNOWN.equals(Build.SERIAL)) + id = Build.SERIAL; + } catch(Exception e) { + // Ah well + } + } + + if (TextUtils.isEmpty(id) || "9774d56d682e549c".equals(id)) { // check for failure or devices affected by the "9774d56d682e549c" bug + return null; + } + + return id; + } + + @Autowired + private ActFmSyncService actFmSyncService; + + public GCMIntentService() { + super(); + DependencyInjectionService.getInstance().inject(this); + } + + @Override + protected void onRegistered(Context context, String registrationId) { + actFmSyncService.setGCMRegistration(registrationId); + } + + @Override + protected void onUnregistered(Context context, String registrationId) { + // Server will unregister automatically next time it tries to send a message + } + + + @Override + protected void onError(Context context, String intent) { + // Unrecoverable + } + + @Override + protected void onMessage(Context context, Intent intent) { + // Intent extras are the keys in the server message's "data" object + } + + public static final void register(Context context) { + try { + if (AndroidUtilities.getSdkVersion() >= 8) { + GCMRegistrar.checkDevice(context); + GCMRegistrar.checkManifest(context); + final String regId = GCMRegistrar.getRegistrationId(context); + if ("".equals(regId)) { + GCMRegistrar.register(context, GCMIntentService.SENDER_ID); + } else { + // TODO: Already registered--do something? + } + } + } catch (Exception e) { + // phone may not support gcm + Log.e("actfm-sync", "gcm-register", e); + } + } + + public static final void unregister(Context context) { + try { + if (AndroidUtilities.getSdkVersion() >= 8) { + GCMRegistrar.checkDevice(context); + GCMRegistrar.unregister(context); + } + } catch (Exception e) { + Log.e("actfm-sync", "gcm-unregister", e); + } + } + +} diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/ActFmLoginActivity.java b/astrid/plugin-src/com/todoroo/astrid/actfm/ActFmLoginActivity.java index 66311dd59..ee961ec23 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/ActFmLoginActivity.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/ActFmLoginActivity.java @@ -50,7 +50,7 @@ import com.facebook.android.LoginButton; import com.facebook.android.Util; import com.google.android.googlelogin.GoogleLoginServiceConstants; import com.google.android.googlelogin.GoogleLoginServiceHelper; -import com.timsu.astrid.C2DMReceiver; +import com.timsu.astrid.GCMIntentService; import com.timsu.astrid.R; import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.ContextManager; @@ -572,12 +572,7 @@ public class ActFmLoginActivity extends FragmentActivity implements AuthListener setResult(RESULT_OK); finish(); - try { - C2DMReceiver.register(); - } catch (Exception e) { - // phone may not support c2dm - exceptionService.reportError("error-c2dm-register", e); - } + GCMIntentService.register(this); } @SuppressWarnings("nls") diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java index e9ca994cc..71e8ffaca 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java @@ -32,6 +32,7 @@ import android.os.ConditionVariable; import android.text.TextUtils; import android.util.Log; +import com.timsu.astrid.GCMIntentService; import com.timsu.astrid.R; import com.todoroo.andlib.data.AbstractModel; import com.todoroo.andlib.data.DatabaseDao; @@ -1232,6 +1233,21 @@ public final class ActFmSyncService { } } + public void setGCMRegistration(String regId) { + try { + String deviceId = GCMIntentService.getDeviceID(); + if (deviceId != null) + invoke("user_set_gcm", "c2dm", regId, "device_id", deviceId); + else + invoke("user_set_gcm", "c2dm", regId); + Preferences.setString(GCMIntentService.PREF_REGISTRATION, regId); + Preferences.setString(GCMIntentService.PREF_NEEDS_REGISTRATION, null); + } catch (IOException e) { + Preferences.setString(GCMIntentService.PREF_NEEDS_REGISTRATION, regId); + Log.e("gcm", "error-gcm-register", e); + } + } + private void pushQueuedUpdatesForTag(TagData tagData) { Criterion criterion = null; if (tagData.getValue(TagData.REMOTE_ID) < 1) { diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncV2Provider.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncV2Provider.java index 156e7b404..20db3519e 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncV2Provider.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncV2Provider.java @@ -14,7 +14,7 @@ import java.util.concurrent.atomic.AtomicInteger; import org.json.JSONException; import org.json.JSONObject; -import com.timsu.astrid.C2DMReceiver; +import com.timsu.astrid.GCMIntentService; import com.timsu.astrid.R; import com.todoroo.andlib.data.AbstractModel; import com.todoroo.andlib.data.TodorooCursor; @@ -147,7 +147,7 @@ public class ActFmSyncV2Provider extends SyncV2Provider { actFmPreferenceService.setToken(null); actFmPreferenceService.clearLastSyncDate(); ActFmPreferenceService.premiumLogout(); - C2DMReceiver.unregister(); + GCMIntentService.unregister(ContextManager.getContext()); } @Override @@ -196,6 +196,10 @@ public class ActFmSyncV2Provider extends SyncV2Provider { /** fetch user status hash*/ @SuppressWarnings("nls") public void updateUserStatus() { + if (Preferences.getStringValue(GCMIntentService.PREF_NEEDS_REGISTRATION) != null) { + actFmSyncService.setGCMRegistration(Preferences.getStringValue(GCMIntentService.PREF_NEEDS_REGISTRATION)); + } + if (Preferences.getBoolean(BillingConstants.PREF_NEEDS_SERVER_UPDATE, false)) { actFmSyncService.updateUserSubscriptionStatus(null, null, null); } From 5a2b65d5154020a6883d6f1a34a60e5cab5e64b3 Mon Sep 17 00:00:00 2001 From: Sam Bosley Date: Wed, 12 Dec 2012 19:04:08 -0800 Subject: [PATCH 2/5] Minor params update --- .../com/todoroo/astrid/actfm/sync/ActFmSyncService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java index 71e8ffaca..17bc0ca36 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java @@ -1237,9 +1237,9 @@ public final class ActFmSyncService { try { String deviceId = GCMIntentService.getDeviceID(); if (deviceId != null) - invoke("user_set_gcm", "c2dm", regId, "device_id", deviceId); + invoke("user_set_gcm", "gcm", regId, "device_id", deviceId); else - invoke("user_set_gcm", "c2dm", regId); + invoke("user_set_gcm", "gcm", regId); Preferences.setString(GCMIntentService.PREF_REGISTRATION, regId); Preferences.setString(GCMIntentService.PREF_NEEDS_REGISTRATION, null); } catch (IOException e) { From bb877b57e8c298cf33351d2a7490a7be9af77bba Mon Sep 17 00:00:00 2001 From: Sam Bosley Date: Thu, 13 Dec 2012 14:49:20 -0800 Subject: [PATCH 3/5] Use real style GCM sender id, remove C2DM receiver from the manifest --- astrid/AndroidManifest.xml | 9 +-------- astrid/plugin-src/com/timsu/astrid/GCMIntentService.java | 2 +- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/astrid/AndroidManifest.xml b/astrid/AndroidManifest.xml index 4482d9033..f5df82329 100644 --- a/astrid/AndroidManifest.xml +++ b/astrid/AndroidManifest.xml @@ -411,14 +411,7 @@ android:windowSoftInputMode="stateHidden" android:theme="@style/Theme.Dialog"/> - - - - - - - + android:windowSoftInputMode="stateHidden"/> diff --git a/astrid/plugin-src/com/timsu/astrid/GCMIntentService.java b/astrid/plugin-src/com/timsu/astrid/GCMIntentService.java index e9a2f0ab2..2d03b232a 100644 --- a/astrid/plugin-src/com/timsu/astrid/GCMIntentService.java +++ b/astrid/plugin-src/com/timsu/astrid/GCMIntentService.java @@ -18,7 +18,7 @@ import com.todoroo.astrid.actfm.sync.ActFmSyncService; @SuppressWarnings("nls") public class GCMIntentService extends GCMBaseIntentService { - public static final String SENDER_ID = "gcm@astrid.com"; //$NON-NLS-1$ + public static final String SENDER_ID = "1003855277730"; //$NON-NLS-1$ public static final String PREF_REGISTRATION = "gcm_id"; public static final String PREF_NEEDS_REGISTRATION = "gcm_needs_reg"; From f2d1fa7dcf3355b128062b906b10664eba81cf31 Mon Sep 17 00:00:00 2001 From: Sam Bosley Date: Thu, 13 Dec 2012 15:56:23 -0800 Subject: [PATCH 4/5] Move everything into GCMIntentService and kill C2DMReceiver --- .../com/timsu/astrid/C2DMReceiver.java | 400 ----------------- .../com/timsu/astrid/GCMIntentService.java | 408 +++++++++++++++++- .../astrid/actfm/sync/ActFmSyncService.java | 18 +- .../astrid/service/UpgradeService.java | 7 +- 4 files changed, 416 insertions(+), 417 deletions(-) delete mode 100644 astrid/plugin-src/com/timsu/astrid/C2DMReceiver.java diff --git a/astrid/plugin-src/com/timsu/astrid/C2DMReceiver.java b/astrid/plugin-src/com/timsu/astrid/C2DMReceiver.java deleted file mode 100644 index d3dd2d14a..000000000 --- a/astrid/plugin-src/com/timsu/astrid/C2DMReceiver.java +++ /dev/null @@ -1,400 +0,0 @@ -/** - * Copyright (c) 2012 Todoroo Inc - * - * See the file "LICENSE" for the full license governing this code. - */ -package com.timsu.astrid; - -import java.io.IOException; - -import org.json.JSONException; -import org.json.JSONObject; - -import android.app.Notification; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.text.TextUtils; -import android.util.Log; - -import com.todoroo.andlib.data.TodorooCursor; -import com.todoroo.andlib.service.Autowired; -import com.todoroo.andlib.service.ContextManager; -import com.todoroo.andlib.service.DependencyInjectionService; -import com.todoroo.andlib.service.NotificationManager; -import com.todoroo.andlib.service.NotificationManager.AndroidNotificationManager; -import com.todoroo.andlib.sql.Query; -import com.todoroo.andlib.sql.QueryTemplate; -import com.todoroo.andlib.utility.DateUtilities; -import com.todoroo.andlib.utility.Preferences; -import com.todoroo.astrid.actfm.TagViewFragment; -import com.todoroo.astrid.actfm.sync.ActFmPreferenceService; -import com.todoroo.astrid.actfm.sync.ActFmSyncService; -import com.todoroo.astrid.actfm.sync.ActFmSyncV2Provider; -import com.todoroo.astrid.activity.ShortcutActivity; -import com.todoroo.astrid.activity.TaskListActivity; -import com.todoroo.astrid.activity.TaskListFragment; -import com.todoroo.astrid.api.AstridApiConstants; -import com.todoroo.astrid.api.Filter; -import com.todoroo.astrid.api.FilterWithCustomIntent; -import com.todoroo.astrid.dao.UpdateDao; -import com.todoroo.astrid.data.SyncFlags; -import com.todoroo.astrid.data.TagData; -import com.todoroo.astrid.data.Task; -import com.todoroo.astrid.data.Update; -import com.todoroo.astrid.reminders.Notifications; -import com.todoroo.astrid.service.AstridDependencyInjector; -import com.todoroo.astrid.service.TagDataService; -import com.todoroo.astrid.service.TaskService; -import com.todoroo.astrid.sync.SyncResultCallbackAdapter; -import com.todoroo.astrid.tags.TagFilterExposer; -import com.todoroo.astrid.utility.Constants; - -@SuppressWarnings("nls") -public class C2DMReceiver extends BroadcastReceiver { - - public static final String C2DM_SENDER = "c2dm@astrid.com"; //$NON-NLS-1$ - - private static final String PREF_REGISTRATION = "c2dm_key"; - private static final String PREF_LAST_C2DM = "c2dm_last"; - - private static final long MIN_MILLIS_BETWEEN_FULL_SYNCS = DateUtilities.ONE_HOUR; - - @Autowired TaskService taskService; - @Autowired TagDataService tagDataService; - @Autowired UpdateDao updateDao; - @Autowired ActFmPreferenceService actFmPreferenceService; - @Autowired ActFmSyncService actFmSyncService; - - static { - AstridDependencyInjector.initialize(); - } - - private final SyncResultCallbackAdapter refreshOnlyCallback = new SyncResultCallbackAdapter() { - @Override - public void finished() { - ContextManager.getContext().sendBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH)); - } - }; - - @Override - public void onReceive(Context context, final Intent intent) { - if (Preferences.getStringValue(GCMIntentService.PREF_REGISTRATION) != null) // GCM takes precedence - return; - - ContextManager.setContext(context); - DependencyInjectionService.getInstance().inject(this); - if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) { - new Thread(new Runnable() { - @Override - public void run() { - if (actFmPreferenceService.isLoggedIn()) { - if(intent.hasExtra("web_update")) - if (DateUtilities.now() - actFmPreferenceService.getLastSyncDate() > MIN_MILLIS_BETWEEN_FULL_SYNCS && !actFmPreferenceService.isOngoing()) - new ActFmSyncV2Provider().synchronizeActiveTasks(false, refreshOnlyCallback); - else - handleWebUpdate(intent); - else - handleMessage(intent); - } - } - }).start(); - } - } - - // --- web update handling - - /** Handle web task or list changed */ - protected void handleWebUpdate(Intent intent) { - try { - if(intent.hasExtra("tag_id")) { - TodorooCursor cursor = tagDataService.query( - Query.select(TagData.PROPERTIES).where(TagData.REMOTE_ID.eq( - intent.getStringExtra("tag_id")))); - try { - TagData tagData = new TagData(); - if(cursor.getCount() == 0) { - tagData.setValue(TagData.REMOTE_ID, Long.parseLong(intent.getStringExtra("tag_id"))); - tagData.putTransitory(SyncFlags.ACTFM_SUPPRESS_SYNC, true); - tagDataService.save(tagData); - } else { - cursor.moveToNext(); - tagData.readFromCursor(cursor); - } - - actFmSyncService.fetchTag(tagData); - } finally { - cursor.close(); - } - } else if(intent.hasExtra("task_id")) { - TodorooCursor cursor = taskService.query( - Query.select(Task.PROPERTIES).where(Task.REMOTE_ID.eq( - intent.getStringExtra("task_id")))); - try { - final Task task = new Task(); - if(cursor.getCount() == 0) { - task.setValue(Task.REMOTE_ID, Long.parseLong(intent.getStringExtra("task_id"))); - task.putTransitory(SyncFlags.ACTFM_SUPPRESS_SYNC, true); - taskService.save(task); - } else { - cursor.moveToNext(); - task.readFromCursor(cursor); - } - - actFmSyncService.fetchTask(task); - } catch(NumberFormatException e) { - // invalid task id - } finally { - cursor.close(); - } - } - - Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH); - ContextManager.getContext().sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); - - } catch (IOException e) { - Log.e("c2dm-tag-rx", "io-exception", e); - return; - } catch (JSONException e) { - Log.e("c2dm-tag-rx", "json-exception", e); - } - } - - // --- message handling - - /** Handle message. Run on separate thread. */ - private void handleMessage(Intent intent) { - String message = intent.getStringExtra("alert"); - Context context = ContextManager.getContext(); - if(TextUtils.isEmpty(message)) - return; - - long lastNotification = Preferences.getLong(PREF_LAST_C2DM, 0); - if(DateUtilities.now() - lastNotification < 5000L) - return; - Preferences.setLong(PREF_LAST_C2DM, DateUtilities.now()); - Intent notifyIntent = null; - int notifId; - - long user_idTemp = -2; - final String user_idString = intent.getStringExtra("oid"); - if (user_idString != null) { - try { - user_idTemp = Long.parseLong(user_idString); - } catch(NumberFormatException e) { - // We tried - Log.e("c2dm-receive", "oid-parse", e); - } - } - final long user_id = user_idTemp; - final String token_id = intent.getStringExtra("tid"); - // unregister - if (!actFmPreferenceService.isLoggedIn() || user_id != ActFmPreferenceService.userId()) { - - new Thread() { - @Override - public void run() { - try { - actFmSyncService.invoke("user_unset_c2dm", "tid", token_id, "oid", user_id); - } catch (IOException e) { - // - } - } - }.start(); - return; - } - - - // fetch data - if(intent.hasExtra("tag_id")) { - notifyIntent = createTagIntent(context, intent); - notifId = (int) Long.parseLong(intent.getStringExtra("tag_id")); - } else if(intent.hasExtra("task_id")) { - notifyIntent = createTaskIntent(intent); - notifId = (int) Long.parseLong(intent.getStringExtra("task_id")); - } else { - return; - } - - notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - notifyIntent.putExtra(TaskListActivity.TOKEN_SOURCE, Constants.SOURCE_C2DM); - PendingIntent pendingIntent = PendingIntent.getActivity(context, - notifId, notifyIntent, 0); - - int icon = calculateIcon(intent); - - // create notification - NotificationManager nm = new AndroidNotificationManager(ContextManager.getContext()); - Notification notification = new Notification(icon, - message, System.currentTimeMillis()); - String title; - if(intent.hasExtra("title")) - title = "Astrid: " + intent.getStringExtra("title"); - else - title = ContextManager.getString(R.string.app_name); - notification.setLatestEventInfo(ContextManager.getContext(), title, - message, pendingIntent); - notification.flags |= Notification.FLAG_AUTO_CANCEL; - - boolean sounds = !"false".equals(intent.getStringExtra("sound")); - notification.defaults = 0; - if(sounds && !Notifications.isQuietHours()) { - notification.defaults |= Notification.DEFAULT_SOUND; - notification.defaults |= Notification.DEFAULT_VIBRATE; - } - nm.notify(notifId, notification); - - if(intent.hasExtra("tag_id")) { - Intent broadcastIntent = new Intent(TagViewFragment.BROADCAST_TAG_ACTIVITY); - broadcastIntent.putExtras(intent); - ContextManager.getContext().sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); - } - } - - private int calculateIcon(Intent intent) { - if(intent.hasExtra("type")) { - String type = intent.getStringExtra("type"); - if("f".equals(type)) - return R.drawable.notif_c2dm_done; - if("s".equals(type)) - return R.drawable.notif_c2dm_assign; - if("l".equals(type)) - return R.drawable.notif_c2dm_assign; - } else { - String message = intent.getStringExtra("alert"); - if(message.contains(" finished ")) - return R.drawable.notif_c2dm_done; - if(message.contains(" invited you to ")) - return R.drawable.notif_c2dm_assign; - if(message.contains(" sent you ")) - return R.drawable.notif_c2dm_assign; - } - return R.drawable.notif_c2dm_msg; - } - - private Intent createTaskIntent(Intent intent) { - TodorooCursor cursor = taskService.query( - Query.select(Task.PROPERTIES).where(Task.REMOTE_ID.eq( - intent.getStringExtra("task_id")))); - try { - final Task task = new Task(); - if(cursor.getCount() == 0) { - task.setValue(Task.TITLE, intent.getStringExtra("title")); - task.setValue(Task.REMOTE_ID, Long.parseLong(intent.getStringExtra("task_id"))); - task.setValue(Task.USER_ID, Task.USER_ID_UNASSIGNED); - task.putTransitory(SyncFlags.ACTFM_SUPPRESS_SYNC, true); - taskService.save(task); - - new Thread(new Runnable() { - @Override - public void run() { - try { - actFmSyncService.fetchTask(task); - } catch (IOException e) { - Log.e("c2dm-task-rx", "io-exception", e); - } catch (JSONException e) { - Log.e("c2dm-task-rx", "json-exception", e); - } - } - }).start(); - } else { - cursor.moveToNext(); - task.readFromCursor(cursor); - } - - Filter filter = new Filter("", task.getValue(Task.TITLE), - new QueryTemplate().where(Task.ID.eq(task.getId())), - null); - - Intent launchIntent = ShortcutActivity.createIntent(filter); - return launchIntent; - } finally { - cursor.close(); - } - } - - private Intent createTagIntent(final Context context, final Intent intent) { - TodorooCursor cursor = tagDataService.query( - Query.select(TagData.PROPERTIES).where(TagData.REMOTE_ID.eq( - intent.getStringExtra("tag_id")))); - try { - final TagData tagData = new TagData(); - if(cursor.getCount() == 0) { - tagData.setValue(TagData.NAME, intent.getStringExtra("title")); - tagData.setValue(TagData.REMOTE_ID, Long.parseLong(intent.getStringExtra("tag_id"))); - tagData.putTransitory(SyncFlags.ACTFM_SUPPRESS_SYNC, true); - tagDataService.save(tagData); - - new Thread(new Runnable() { - @Override - public void run() { - try { - actFmSyncService.fetchTag(tagData); - } catch (IOException e) { - Log.e("c2dm-tag-rx", "io-exception", e); - } catch (JSONException e) { - Log.e("c2dm-tag-rx", "json-exception", e); - } - } - }).start(); - } else { - cursor.moveToNext(); - tagData.readFromCursor(cursor); - } - - FilterWithCustomIntent filter = (FilterWithCustomIntent)TagFilterExposer.filterFromTagData(context, tagData); - //filter.customExtras.putString(TagViewActivity.EXTRA_START_TAB, "updates"); - if(intent.hasExtra("activity_id")) { - try { - Update update = new Update(); - update.setValue(Update.REMOTE_ID, Long.parseLong(intent.getStringExtra("activity_id"))); - update.setValue(Update.USER_ID, Long.parseLong(intent.getStringExtra("user_id"))); - JSONObject user = new JSONObject(); - user.put("id", update.getValue(Update.USER_ID)); - user.put("name", intent.getStringExtra("user_name")); - update.setValue(Update.USER, user.toString()); - update.setValue(Update.ACTION, "commented"); - update.setValue(Update.ACTION_CODE, "tag_comment"); - update.setValue(Update.TARGET_NAME, intent.getStringExtra("title")); - String message = intent.getStringExtra("alert"); - if(message.contains(":")) - message = message.substring(message.indexOf(':') + 2); - update.setValue(Update.MESSAGE, message); - update.setValue(Update.CREATION_DATE, DateUtilities.now()); - update.setValue(Update.TAGS, "," + intent.getStringExtra("tag_id") + ","); - updateDao.createNew(update); - } catch (JSONException e) { - // - } catch (NumberFormatException e) { - // - } - } - - Intent launchIntent = new Intent(context, TaskListActivity.class); - launchIntent.putExtra(TaskListFragment.TOKEN_FILTER, filter); - filter.customExtras.putBoolean(TagViewFragment.TOKEN_START_ACTIVITY, shouldLaunchActivity(intent)); - launchIntent.putExtras(filter.customExtras); - - return launchIntent; - } finally { - cursor.close(); - } - } - - private boolean shouldLaunchActivity(Intent intent) { - if(intent.hasExtra("type")) { - String type = intent.getStringExtra("type"); - if("f".equals(type)) return true; - if("s".equals(type)) return false; - if("l".equals(type)) return false; - } else { - String message = intent.getStringExtra("alert"); - if(message.contains(" finished ")) return true; - if(message.contains(" invited you to ")) return false; - if(message.contains(" sent you ")) return false; - } - return true; - } - -} diff --git a/astrid/plugin-src/com/timsu/astrid/GCMIntentService.java b/astrid/plugin-src/com/timsu/astrid/GCMIntentService.java index 2d03b232a..756983ea8 100644 --- a/astrid/plugin-src/com/timsu/astrid/GCMIntentService.java +++ b/astrid/plugin-src/com/timsu/astrid/GCMIntentService.java @@ -1,5 +1,12 @@ package com.timsu.astrid; +import java.io.IOException; + +import org.json.JSONException; +import org.json.JSONObject; + +import android.app.Notification; +import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Build; @@ -9,11 +16,39 @@ import android.util.Log; import com.google.android.gcm.GCMBaseIntentService; import com.google.android.gcm.GCMRegistrar; +import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.service.DependencyInjectionService; +import com.todoroo.andlib.service.NotificationManager; +import com.todoroo.andlib.service.NotificationManager.AndroidNotificationManager; +import com.todoroo.andlib.sql.Query; +import com.todoroo.andlib.sql.QueryTemplate; import com.todoroo.andlib.utility.AndroidUtilities; +import com.todoroo.andlib.utility.DateUtilities; +import com.todoroo.andlib.utility.Preferences; +import com.todoroo.astrid.actfm.TagViewFragment; +import com.todoroo.astrid.actfm.sync.ActFmPreferenceService; import com.todoroo.astrid.actfm.sync.ActFmSyncService; +import com.todoroo.astrid.actfm.sync.ActFmSyncV2Provider; +import com.todoroo.astrid.activity.ShortcutActivity; +import com.todoroo.astrid.activity.TaskListActivity; +import com.todoroo.astrid.activity.TaskListFragment; +import com.todoroo.astrid.api.AstridApiConstants; +import com.todoroo.astrid.api.Filter; +import com.todoroo.astrid.api.FilterWithCustomIntent; +import com.todoroo.astrid.dao.UpdateDao; +import com.todoroo.astrid.data.SyncFlags; +import com.todoroo.astrid.data.TagData; +import com.todoroo.astrid.data.Task; +import com.todoroo.astrid.data.Update; +import com.todoroo.astrid.reminders.Notifications; +import com.todoroo.astrid.service.AstridDependencyInjector; +import com.todoroo.astrid.service.TagDataService; +import com.todoroo.astrid.service.TaskService; +import com.todoroo.astrid.sync.SyncResultCallbackAdapter; +import com.todoroo.astrid.tags.TagFilterExposer; +import com.todoroo.astrid.utility.Constants; @SuppressWarnings("nls") public class GCMIntentService extends GCMBaseIntentService { @@ -22,6 +57,9 @@ public class GCMIntentService extends GCMBaseIntentService { public static final String PREF_REGISTRATION = "gcm_id"; public static final String PREF_NEEDS_REGISTRATION = "gcm_needs_reg"; + private static final String PREF_LAST_GCM = "c2dm_last"; + public static final String PREF_C2DM_REGISTRATION = "c2dm_key"; + public static String getDeviceID() { String id = Secure.getString(ContextManager.getContext().getContentResolver(), Secure.ANDROID_ID);; if(AndroidUtilities.getSdkVersion() > 8) { //Gingerbread and above @@ -41,35 +79,349 @@ public class GCMIntentService extends GCMBaseIntentService { return id; } + static { + AstridDependencyInjector.initialize(); + } + @Autowired private ActFmSyncService actFmSyncService; + @Autowired + private ActFmPreferenceService actFmPreferenceService; + + @Autowired + private TaskService taskService; + + @Autowired + private TagDataService tagDataService; + + @Autowired + private UpdateDao updateDao; + public GCMIntentService() { super(); DependencyInjectionService.getInstance().inject(this); } + + // ===================== Messaging =================== // + + private final SyncResultCallbackAdapter refreshOnlyCallback = new SyncResultCallbackAdapter() { + @Override + public void finished() { + ContextManager.getContext().sendBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH)); + } + }; + + private static final long MIN_MILLIS_BETWEEN_FULL_SYNCS = DateUtilities.ONE_HOUR; + @Override - protected void onRegistered(Context context, String registrationId) { - actFmSyncService.setGCMRegistration(registrationId); + protected void onMessage(Context context, Intent intent) { + if (actFmPreferenceService.isLoggedIn()) { + if(intent.hasExtra("web_update")) + if (DateUtilities.now() - actFmPreferenceService.getLastSyncDate() > MIN_MILLIS_BETWEEN_FULL_SYNCS && !actFmPreferenceService.isOngoing()) + new ActFmSyncV2Provider().synchronizeActiveTasks(false, refreshOnlyCallback); + else + handleWebUpdate(intent); + else + handleMessage(intent); + } } - @Override - protected void onUnregistered(Context context, String registrationId) { - // Server will unregister automatically next time it tries to send a message + /** Handle web task or list changed */ + protected void handleWebUpdate(Intent intent) { + try { + if(intent.hasExtra("tag_id")) { + TodorooCursor cursor = tagDataService.query( + Query.select(TagData.PROPERTIES).where(TagData.REMOTE_ID.eq( + intent.getStringExtra("tag_id")))); + try { + TagData tagData = new TagData(); + if(cursor.getCount() == 0) { + tagData.setValue(TagData.REMOTE_ID, Long.parseLong(intent.getStringExtra("tag_id"))); + tagData.putTransitory(SyncFlags.ACTFM_SUPPRESS_SYNC, true); + tagDataService.save(tagData); + } else { + cursor.moveToNext(); + tagData.readFromCursor(cursor); + } + + actFmSyncService.fetchTag(tagData); + } finally { + cursor.close(); + } + } else if(intent.hasExtra("task_id")) { + TodorooCursor cursor = taskService.query( + Query.select(Task.PROPERTIES).where(Task.REMOTE_ID.eq( + intent.getStringExtra("task_id")))); + try { + final Task task = new Task(); + if(cursor.getCount() == 0) { + task.setValue(Task.REMOTE_ID, Long.parseLong(intent.getStringExtra("task_id"))); + task.putTransitory(SyncFlags.ACTFM_SUPPRESS_SYNC, true); + taskService.save(task); + } else { + cursor.moveToNext(); + task.readFromCursor(cursor); + } + + actFmSyncService.fetchTask(task); + } catch(NumberFormatException e) { + // invalid task id + } finally { + cursor.close(); + } + } + + Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH); + ContextManager.getContext().sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); + + } catch (IOException e) { + Log.e("c2dm-tag-rx", "io-exception", e); + return; + } catch (JSONException e) { + Log.e("c2dm-tag-rx", "json-exception", e); + } } + // --- message handling - @Override - protected void onError(Context context, String intent) { - // Unrecoverable + /** Handle message. Run on separate thread. */ + private void handleMessage(Intent intent) { + String message = intent.getStringExtra("alert"); + Context context = ContextManager.getContext(); + if(TextUtils.isEmpty(message)) + return; + + long lastNotification = Preferences.getLong(PREF_LAST_GCM, 0); + if(DateUtilities.now() - lastNotification < 5000L) + return; + Preferences.setLong(PREF_LAST_GCM, DateUtilities.now()); + Intent notifyIntent = null; + int notifId; + + long user_idTemp = -2; + final String user_idString = intent.getStringExtra("oid"); + if (user_idString != null) { + try { + user_idTemp = Long.parseLong(user_idString); + } catch(NumberFormatException e) { + // We tried + Log.e("c2dm-receive", "oid-parse", e); + } + } + final long user_id = user_idTemp; + final String token_id = intent.getStringExtra("tid"); + // unregister + if (!actFmPreferenceService.isLoggedIn() || user_id != ActFmPreferenceService.userId()) { + + new Thread() { + @Override + public void run() { + try { + actFmSyncService.invoke("user_unset_c2dm", "tid", token_id, "oid", user_id); + } catch (IOException e) { + // + } + } + }.start(); + return; + } + + + // fetch data + if(intent.hasExtra("tag_id")) { + notifyIntent = createTagIntent(context, intent); + notifId = (int) Long.parseLong(intent.getStringExtra("tag_id")); + } else if(intent.hasExtra("task_id")) { + notifyIntent = createTaskIntent(intent); + notifId = (int) Long.parseLong(intent.getStringExtra("task_id")); + } else { + return; + } + + notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + notifyIntent.putExtra(TaskListActivity.TOKEN_SOURCE, Constants.SOURCE_C2DM); + PendingIntent pendingIntent = PendingIntent.getActivity(context, + notifId, notifyIntent, 0); + + int icon = calculateIcon(intent); + + // create notification + NotificationManager nm = new AndroidNotificationManager(ContextManager.getContext()); + Notification notification = new Notification(icon, + message, System.currentTimeMillis()); + String title; + if(intent.hasExtra("title")) + title = "Astrid: " + intent.getStringExtra("title"); + else + title = ContextManager.getString(R.string.app_name); + notification.setLatestEventInfo(ContextManager.getContext(), title, + message, pendingIntent); + notification.flags |= Notification.FLAG_AUTO_CANCEL; + + boolean sounds = !"false".equals(intent.getStringExtra("sound")); + notification.defaults = 0; + if(sounds && !Notifications.isQuietHours()) { + notification.defaults |= Notification.DEFAULT_SOUND; + notification.defaults |= Notification.DEFAULT_VIBRATE; + } + nm.notify(notifId, notification); + + if(intent.hasExtra("tag_id")) { + Intent broadcastIntent = new Intent(TagViewFragment.BROADCAST_TAG_ACTIVITY); + broadcastIntent.putExtras(intent); + ContextManager.getContext().sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); + } } - @Override - protected void onMessage(Context context, Intent intent) { - // Intent extras are the keys in the server message's "data" object + private int calculateIcon(Intent intent) { + if(intent.hasExtra("type")) { + String type = intent.getStringExtra("type"); + if("f".equals(type)) + return R.drawable.notif_c2dm_done; + if("s".equals(type)) + return R.drawable.notif_c2dm_assign; + if("l".equals(type)) + return R.drawable.notif_c2dm_assign; + } else { + String message = intent.getStringExtra("alert"); + if(message.contains(" finished ")) + return R.drawable.notif_c2dm_done; + if(message.contains(" invited you to ")) + return R.drawable.notif_c2dm_assign; + if(message.contains(" sent you ")) + return R.drawable.notif_c2dm_assign; + } + return R.drawable.notif_c2dm_msg; + } + + private Intent createTaskIntent(Intent intent) { + TodorooCursor cursor = taskService.query( + Query.select(Task.PROPERTIES).where(Task.REMOTE_ID.eq( + intent.getStringExtra("task_id")))); + try { + final Task task = new Task(); + if(cursor.getCount() == 0) { + task.setValue(Task.TITLE, intent.getStringExtra("title")); + task.setValue(Task.REMOTE_ID, Long.parseLong(intent.getStringExtra("task_id"))); + task.setValue(Task.USER_ID, Task.USER_ID_UNASSIGNED); + task.putTransitory(SyncFlags.ACTFM_SUPPRESS_SYNC, true); + taskService.save(task); + + new Thread(new Runnable() { + @Override + public void run() { + try { + actFmSyncService.fetchTask(task); + } catch (IOException e) { + Log.e("c2dm-task-rx", "io-exception", e); + } catch (JSONException e) { + Log.e("c2dm-task-rx", "json-exception", e); + } + } + }).start(); + } else { + cursor.moveToNext(); + task.readFromCursor(cursor); + } + + Filter filter = new Filter("", task.getValue(Task.TITLE), + new QueryTemplate().where(Task.ID.eq(task.getId())), + null); + + Intent launchIntent = ShortcutActivity.createIntent(filter); + return launchIntent; + } finally { + cursor.close(); + } + } + + private Intent createTagIntent(final Context context, final Intent intent) { + TodorooCursor cursor = tagDataService.query( + Query.select(TagData.PROPERTIES).where(TagData.REMOTE_ID.eq( + intent.getStringExtra("tag_id")))); + try { + final TagData tagData = new TagData(); + if(cursor.getCount() == 0) { + tagData.setValue(TagData.NAME, intent.getStringExtra("title")); + tagData.setValue(TagData.REMOTE_ID, Long.parseLong(intent.getStringExtra("tag_id"))); + tagData.putTransitory(SyncFlags.ACTFM_SUPPRESS_SYNC, true); + tagDataService.save(tagData); + + new Thread(new Runnable() { + @Override + public void run() { + try { + actFmSyncService.fetchTag(tagData); + } catch (IOException e) { + Log.e("c2dm-tag-rx", "io-exception", e); + } catch (JSONException e) { + Log.e("c2dm-tag-rx", "json-exception", e); + } + } + }).start(); + } else { + cursor.moveToNext(); + tagData.readFromCursor(cursor); + } + + FilterWithCustomIntent filter = (FilterWithCustomIntent)TagFilterExposer.filterFromTagData(context, tagData); + //filter.customExtras.putString(TagViewActivity.EXTRA_START_TAB, "updates"); + if(intent.hasExtra("activity_id")) { + try { + Update update = new Update(); + update.setValue(Update.REMOTE_ID, Long.parseLong(intent.getStringExtra("activity_id"))); + update.setValue(Update.USER_ID, Long.parseLong(intent.getStringExtra("user_id"))); + JSONObject user = new JSONObject(); + user.put("id", update.getValue(Update.USER_ID)); + user.put("name", intent.getStringExtra("user_name")); + update.setValue(Update.USER, user.toString()); + update.setValue(Update.ACTION, "commented"); + update.setValue(Update.ACTION_CODE, "tag_comment"); + update.setValue(Update.TARGET_NAME, intent.getStringExtra("title")); + String message = intent.getStringExtra("alert"); + if(message.contains(":")) + message = message.substring(message.indexOf(':') + 2); + update.setValue(Update.MESSAGE, message); + update.setValue(Update.CREATION_DATE, DateUtilities.now()); + update.setValue(Update.TAGS, "," + intent.getStringExtra("tag_id") + ","); + updateDao.createNew(update); + } catch (JSONException e) { + // + } catch (NumberFormatException e) { + // + } + } + + Intent launchIntent = new Intent(context, TaskListActivity.class); + launchIntent.putExtra(TaskListFragment.TOKEN_FILTER, filter); + filter.customExtras.putBoolean(TagViewFragment.TOKEN_START_ACTIVITY, shouldLaunchActivity(intent)); + launchIntent.putExtras(filter.customExtras); + + return launchIntent; + } finally { + cursor.close(); + } + } + + private boolean shouldLaunchActivity(Intent intent) { + if(intent.hasExtra("type")) { + String type = intent.getStringExtra("type"); + if("f".equals(type)) return true; + if("s".equals(type)) return false; + if("l".equals(type)) return false; + } else { + String message = intent.getStringExtra("alert"); + if(message.contains(" finished ")) return true; + if(message.contains(" invited you to ")) return false; + if(message.contains(" sent you ")) return false; + } + return true; } + // ==================== Registration ============== // + public static final void register(Context context) { try { if (AndroidUtilities.getSdkVersion() >= 8) { @@ -91,7 +443,6 @@ public class GCMIntentService extends GCMBaseIntentService { public static final void unregister(Context context) { try { if (AndroidUtilities.getSdkVersion() >= 8) { - GCMRegistrar.checkDevice(context); GCMRegistrar.unregister(context); } } catch (Exception e) { @@ -99,4 +450,37 @@ public class GCMIntentService extends GCMBaseIntentService { } } + @Override + protected void onRegistered(Context context, String registrationId) { + actFmSyncService.setGCMRegistration(registrationId); + } + + @Override + protected void onUnregistered(Context context, String registrationId) { + // Server can unregister automatically next time it tries to send a message + } + + + @Override + protected void onError(Context context, String intent) { + // Unrecoverable + } + + // =========== Migration ============= // + + public static class GCMMigration { + @Autowired + private ActFmPreferenceService actFmPreferenceService; + + public GCMMigration() { + DependencyInjectionService.getInstance().inject(this); + } + + public void performMigration(Context context) { + if (actFmPreferenceService.isLoggedIn()) { + GCMIntentService.register(context); + } + } + } + } diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java index 17bc0ca36..f623e12ca 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java @@ -1236,11 +1236,21 @@ public final class ActFmSyncService { public void setGCMRegistration(String regId) { try { String deviceId = GCMIntentService.getDeviceID(); - if (deviceId != null) - invoke("user_set_gcm", "gcm", regId, "device_id", deviceId); - else - invoke("user_set_gcm", "gcm", regId); + String existingC2DM = Preferences.getStringValue(GCMIntentService.PREF_C2DM_REGISTRATION); + + ArrayList params = new ArrayList(); + params.add("gcm"); params.add(regId); + if (!TextUtils.isEmpty(deviceId)) { + params.add("device_id"); params.add(deviceId); + } + if (!TextUtils.isEmpty(existingC2DM)) { // Unregisters C2DM with the server for migration purposes + params.add("c2dm"); params.add(existingC2DM); + } + + invoke("user_set_gcm", params.toArray(new Object[params.size()])); + Preferences.setString(GCMIntentService.PREF_REGISTRATION, regId); + Preferences.setString(GCMIntentService.PREF_C2DM_REGISTRATION, null); Preferences.setString(GCMIntentService.PREF_NEEDS_REGISTRATION, null); } catch (IOException e) { Preferences.setString(GCMIntentService.PREF_NEEDS_REGISTRATION, regId); diff --git a/astrid/src/com/todoroo/astrid/service/UpgradeService.java b/astrid/src/com/todoroo/astrid/service/UpgradeService.java index 977a5fcb6..81919b024 100644 --- a/astrid/src/com/todoroo/astrid/service/UpgradeService.java +++ b/astrid/src/com/todoroo/astrid/service/UpgradeService.java @@ -17,6 +17,7 @@ import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.os.Bundle; +import com.timsu.astrid.GCMIntentService; import com.timsu.astrid.R; import com.todoroo.andlib.data.Property.LongProperty; import com.todoroo.andlib.data.Property.StringProperty; @@ -50,6 +51,7 @@ import com.todoroo.astrid.utility.Constants; public final class UpgradeService { + public static final int V4_5_1 = 292; public static final int V4_5_0 = 291; public static final int V4_4_4_1 = 290; public static final int V4_4_4 = 289; @@ -176,7 +178,7 @@ public final class UpgradeService { // long running tasks: pop up a progress dialog final ProgressDialog dialog; - int maxWithUpgrade = V4_4_2; // The last version that required a migration + int maxWithUpgrade = V4_5_1; // The last version that required a migration final String lastSetVersionName = AstridPreferences.getCurrentVersionName(); @@ -228,6 +230,9 @@ public final class UpgradeService { if (from < V4_4_2) new SubtasksMetadataMigration().performMigration(); + if (from < V4_5_1) + new GCMIntentService.GCMMigration().performMigration(UpgradeActivity.this); + } finally { finished = true; DialogUtilities.dismissDialog(UpgradeActivity.this, dialog); From 14509c9203f271b9b9be3e3f27d122bd85a596eb Mon Sep 17 00:00:00 2001 From: Sam Bosley Date: Thu, 13 Dec 2012 15:57:27 -0800 Subject: [PATCH 5/5] Constants in DateUtilities should be final --- api/src/com/todoroo/andlib/utility/DateUtilities.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/src/com/todoroo/andlib/utility/DateUtilities.java b/api/src/com/todoroo/andlib/utility/DateUtilities.java index 068c3ed11..7f3cfb4e3 100644 --- a/api/src/com/todoroo/andlib/utility/DateUtilities.java +++ b/api/src/com/todoroo/andlib/utility/DateUtilities.java @@ -66,16 +66,16 @@ public class DateUtilities { } /** Represents a single hour */ - public static long ONE_HOUR = 3600000L; + public static final long ONE_HOUR = 3600000L; /** Represents a single day */ - public static long ONE_DAY = 24 * ONE_HOUR; + public static final long ONE_DAY = 24 * ONE_HOUR; /** Represents a single week */ - public static long ONE_WEEK = 7 * ONE_DAY; + public static final long ONE_WEEK = 7 * ONE_DAY; /** Represents a single minute */ - public static long ONE_MINUTE = 60000L; + public static final long ONE_MINUTE = 60000L; /* ====================================================================== * =========================================================== formatters