Merge remote-tracking branch 'origin/121212_sb_gcm'

pull/14/head
Sam Bosley 12 years ago
commit b3625f4c63

@ -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

@ -31,5 +31,6 @@
<classpathentry kind="lib" path="libs/crittercism_v2_1_2.jar"/>
<classpathentry kind="lib" path="libs/findbugs-annotations.jar"/>
<classpathentry kind="lib" path="libs/CWAC-SackOfViewsAdapter.jar"/>
<classpathentry kind="lib" path="libs/gcm.jar" sourcepath="libs/gcm-src.jar"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

@ -45,6 +45,9 @@
<!-- required for in-app billing of premium subscriptions -->
<uses-permission android:name="com.android.vending.BILLING"/>
<!-- Required for GCM - keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- ============================================== Exported Permissions = -->
@ -408,19 +411,17 @@
android:windowSoftInputMode="stateHidden"
android:theme="@style/Theme.Dialog"/>
<activity android:name="com.todoroo.astrid.actfm.CommentsActivity"
android:windowSoftInputMode="stateHidden"/>
<receiver android:name="com.timsu.astrid.C2DMReceiver" permission="com.google.android.c2dm.permission.SEND">
<!-- Receive the actual message -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.timsu.astrid" />
</intent-filter>
<!-- Receive the registration id -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.timsu.astrid" />
</intent-filter>
</receiver>
android:windowSoftInputMode="stateHidden"/>
<receiver android:name="com.google.android.gcm.GCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.timsu.astrid" />
</intent-filter>
</receiver>
<service android:name=".GCMIntentService" />
<!-- gtasks -->
<activity android:name="com.todoroo.astrid.gtasks.GtasksListFragment"

Binary file not shown.

Binary file not shown.

@ -1,8 +1,3 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.timsu.astrid;
import java.io.IOException;
@ -12,7 +7,6 @@ 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.os.Build;
@ -20,6 +14,8 @@ 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.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager;
@ -55,36 +51,18 @@ import com.todoroo.astrid.tags.TagFilterExposer;
import com.todoroo.astrid.utility.Constants;
@SuppressWarnings("nls")
public class C2DMReceiver extends BroadcastReceiver {
public class GCMIntentService extends GCMBaseIntentService {
public static final String C2DM_SENDER = "c2dm@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";
private static final String PREF_REGISTRATION = "c2dm_key";
private static final String PREF_LAST_C2DM = "c2dm_last";
private static final String PREF_LAST_GCM = "c2dm_last";
public static final String PREF_C2DM_REGISTRATION = "c2dm_key";
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));
}
};
private static String getDeviceID() {
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))
@ -101,31 +79,54 @@ public class C2DMReceiver extends BroadcastReceiver {
return id;
}
@Override
public void onReceive(Context context, final Intent intent) {
ContextManager.setContext(context);
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);
if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) {
handleRegistration(intent);
} else 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
// ===================== 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 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);
}
}
/** Handle web task or list changed */
protected void handleWebUpdate(Intent intent) {
@ -192,10 +193,10 @@ public class C2DMReceiver extends BroadcastReceiver {
if(TextUtils.isEmpty(message))
return;
long lastNotification = Preferences.getLong(PREF_LAST_C2DM, 0);
long lastNotification = Preferences.getLong(PREF_LAST_GCM, 0);
if(DateUtilities.now() - lastNotification < 5000L)
return;
Preferences.setLong(PREF_LAST_C2DM, DateUtilities.now());
Preferences.setLong(PREF_LAST_GCM, DateUtilities.now());
Intent notifyIntent = null;
int notifId;
@ -419,56 +420,67 @@ 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);
}
// ==================== Registration ============== //
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?
}
}.start();
}
} catch (Exception e) {
// phone may not support gcm
Log.e("actfm-sync", "gcm-register", e);
}
}
/** 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);
public static final void unregister(Context context) {
try {
if (AndroidUtilities.getSdkVersion() >= 8) {
GCMRegistrar.unregister(context);
}
}.start();
} catch (Exception e) {
Log.e("actfm-sync", "gcm-unregister", e);
}
}
/** 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);
@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);
}
}
}
}

@ -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")

@ -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,31 @@ public final class ActFmSyncService {
}
}
public void setGCMRegistration(String regId) {
try {
String deviceId = GCMIntentService.getDeviceID();
String existingC2DM = Preferences.getStringValue(GCMIntentService.PREF_C2DM_REGISTRATION);
ArrayList<Object> params = new ArrayList<Object>();
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);
Log.e("gcm", "error-gcm-register", e);
}
}
private void pushQueuedUpdatesForTag(TagData tagData) {
Criterion criterion = null;
if (tagData.getValue(TagData.REMOTE_ID) < 1) {

@ -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);
}

@ -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);

Loading…
Cancel
Save