AST-285 - rtm login page randomly comes up

pull/14/head
Tim Su 16 years ago
parent 16449a4ae2
commit 5c5612746a

@ -11,20 +11,16 @@ import java.util.HashMap;
import android.app.Activity;
import android.app.Notification;
import android.app.Service;
import android.content.Context;
import android.widget.Toast;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.data.Property.LongProperty;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.service.ExceptionService;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.NotificationManager;
import com.todoroo.astrid.api.TaskContainer;
import com.todoroo.astrid.model.Task;
import com.todoroo.astrid.utility.Constants;
import com.todoroo.astrid.utility.Flags;
/**
* A helper class for writing synchronization services for Astrid. This class
@ -42,13 +38,23 @@ public abstract class SyncProvider<TYPE extends TaskContainer> {
// --- abstract methods - your services should implement these
/**
* Perform authenticate and other pre-synchronization steps, then
* synchronize.
* Perform log in (launching activity if necessary) and sync. This is
* invoked when users manually request synchronization
*
* @param context
* either the parent activity, or a background service
* @param activity
* context
*/
abstract protected void initiateManual(Activity activity);
/**
* Perform synchronize. Since this can be called from background services,
* you should not open up new activities. Instead, if the user is not signed
* in, your service should do nothing.
*
* @param service
* context
*/
abstract protected void initiate(Context context);
abstract protected void initiateBackground(Service service);
/**
* Updates the text of a notification and the intent to open when tapped
@ -128,14 +134,9 @@ public abstract class SyncProvider<TYPE extends TaskContainer> {
// --- implementation
@Autowired
private ExceptionService exceptionService;
private final Notification notification;
public SyncProvider() {
DependencyInjectionService.getInstance().inject(this);
// initialize notification
int icon = android.R.drawable.stat_notify_sync;
long when = System.currentTimeMillis();
@ -153,34 +154,24 @@ public abstract class SyncProvider<TYPE extends TaskContainer> {
Toast.LENGTH_LONG).show();
}
});
}
// display notification
updateNotification(context, notification);
final NotificationManager nm = new NotificationManager.AndroidNotificationManager(context);
nm.notify(Constants.NOTIFICATION_SYNC, notification);
// start next step in background thread
new Thread(new Runnable() {
public void run() {
try {
initiate(context);
} finally {
nm.cancel(Constants.NOTIFICATION_SYNC);
initiateManual((Activity)context);
} else if(context instanceof Service) {
// display notification
updateNotification(context, notification);
final NotificationManager nm = new NotificationManager.AndroidNotificationManager(context);
nm.notify(Constants.NOTIFICATION_SYNC, notification);
// start next step in background thread
new Thread(new Runnable() {
public void run() {
try {
initiateBackground((Service)context);
} finally {
nm.cancel(Constants.NOTIFICATION_SYNC);
}
}
}
}).start();
}
// --- utilities
/**
* Utility method for showing synchronization errors. If message is null,
* the contents of the throwable is displayed. It is assumed that the error
* was logged separately.
*/
protected void showError(final Context context, Throwable e, String message) {
exceptionService.displayAndReportError(context, message, e);
}).start();
}
}
// --- synchronization logic
@ -310,8 +301,6 @@ public abstract class SyncProvider<TYPE extends TaskContainer> {
handleException("sync-remote-updated", e, false); //$NON-NLS-1$
}
}
Flags.set(Flags.REFRESH);
}
// --- helper classes

@ -1,9 +1,8 @@
package com.todoroo.astrid.api;
package com.todoroo.astrid.common;
import java.util.ArrayList;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.astrid.common.SyncProvider;
import com.todoroo.astrid.model.Metadata;
import com.todoroo.astrid.model.Task;

@ -39,7 +39,8 @@ public class ProducteevBackgroundService extends Service {
@Override
public void onStart(Intent intent, int startId) {
try {
startSynchronization(this);
if(intent != null && SYNC_ACTION.equals(intent.getAction()))
startSynchronization(this);
} catch (Exception e) {
PluginServices.getExceptionService().reportError("pdv-bg-sync", e); //$NON-NLS-1$
}

@ -1,6 +1,5 @@
package com.todoroo.astrid.producteev;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.preference.ListPreference;
@ -31,8 +30,7 @@ public class ProducteevPreferences extends SyncProviderPreferences {
@Override
public void startSync() {
startService(new Intent(ProducteevBackgroundService.SYNC_ACTION, null,
this, ProducteevBackgroundService.class));
new ProducteevSyncProvider().synchronize(this);
}
@Override

@ -15,6 +15,7 @@ import org.json.JSONObject;
import android.app.Activity;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
@ -31,11 +32,12 @@ import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.TaskContainer;
import com.todoroo.astrid.common.SyncProvider;
import com.todoroo.astrid.common.TaskContainer;
import com.todoroo.astrid.model.Metadata;
import com.todoroo.astrid.model.StoreObject;
import com.todoroo.astrid.model.Task;
import com.todoroo.astrid.producteev.ProducteevBackgroundService;
import com.todoroo.astrid.producteev.ProducteevLoginActivity;
import com.todoroo.astrid.producteev.ProducteevPreferences;
import com.todoroo.astrid.producteev.ProducteevUtilities;
@ -75,7 +77,7 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
}
// ----------------------------------------------------------------------
// ------------------------------------------------------- public methods
// ------------------------------------------------------ utility methods
// ----------------------------------------------------------------------
/**
@ -94,10 +96,6 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
dataService.clearMetadata();
}
// ----------------------------------------------------------------------
// ------------------------------------------------------- authentication
// ----------------------------------------------------------------------
/**
* Deal with a synchronization exception. If requested, will show an error
* to the user (unless synchronization is happening in background)
@ -111,44 +109,40 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
* whether to display a dialog
*/
@Override
protected void handleException(String tag, Exception e, boolean showError) {
protected void handleException(String tag, Exception e, boolean displayError) {
final Context context = ContextManager.getContext();
preferences.setLastError(e.toString());
String message = null;
// occurs when application was closed
if(e instanceof IllegalStateException) {
exceptionService.reportError(tag + "-caught", e); //$NON-NLS-1$
// occurs when network error
// occurs when network error
} else if(!(e instanceof ApiServiceException) && e instanceof IOException) {
exceptionService.reportError(tag + "-ioexception", e); //$NON-NLS-1$
if(showError) {
Context context = ContextManager.getContext();
showError(context, e, context.getString(R.string.producteev_ioerror));
}
message = context.getString(R.string.producteev_ioerror);
} else {
message = context.getString(R.string.DLG_error, e.toString());
exceptionService.reportError(tag + "-unhandled", e); //$NON-NLS-1$
if(showError) {
Context context = ContextManager.getContext();
showError(context, e, null);
}
}
}
@Override
protected void initiate(Context context) {
dataService = ProducteevDataService.getInstance();
// authenticate the user. this will automatically call the next step
authenticate();
if(displayError && context instanceof Activity && message != null) {
dialogUtilities.okDialog((Activity)context,
message, null);
}
}
// ----------------------------------------------------------------------
// ------------------------------------------------------ initiating sync
// ----------------------------------------------------------------------
/**
* Perform authentication with RTM. Will open the SyncBrowser if necessary
* initiate sync in background
*/
private void authenticate() {
FlurryAgent.onEvent("producteev-started");
preferences.recordSyncStart();
@Override
protected void initiateBackground(Service service) {
dataService = ProducteevDataService.getInstance();
try {
String authToken = preferences.getToken();
@ -163,16 +157,7 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
performSync();
} else {
if (email == null && password == null) {
// display login-activity
final Context context = ContextManager.getContext();
Intent intent = new Intent(context, ProducteevLoginActivity.class);
if(context instanceof Activity)
((Activity)context).startActivityForResult(intent, 0);
else {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
ProducteevUtilities.INSTANCE.stopOngoing();
}
// we can't do anything, user is not logged in
} else {
invoker.authenticate(email, password);
preferences.setToken(invoker.getToken());
@ -180,7 +165,7 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
}
}
} catch (IllegalStateException e) {
// occurs when application was closed
// occurs when application was closed
} catch (Exception e) {
handleException("pdv-authenticate", e, true);
} finally {
@ -188,6 +173,25 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
}
}
/**
* If user isn't already signed in, show sign in dialog. Else perform sync.
*/
@Override
protected void initiateManual(Activity activity) {
String authToken = preferences.getToken();
ProducteevUtilities.INSTANCE.stopOngoing();
// check if we have a token & it works
if(authToken == null) {
// display login-activity
Intent intent = new Intent(activity, ProducteevLoginActivity.class);
activity.startActivityForResult(intent, 0);
} else {
activity.startService(new Intent(ProducteevBackgroundService.SYNC_ACTION, null,
activity, ProducteevBackgroundService.class));
}
}
public static ProducteevInvoker getInvoker() {
String z = stripslashes(0, "71o3346pr40o5o4nt4n7t6n287t4op28","2");
String v = stripslashes(2, "9641n76n9s1736q1578q1o1337q19233","4ae");
@ -199,6 +203,9 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
// ----------------------------------------------------------------------
protected void performSync() {
FlurryAgent.onEvent("producteev-started");
preferences.recordSyncStart();
try {
// load user information
JSONObject user = invoker.usersView(null).getJSONObject("user");

@ -5,7 +5,7 @@ import java.util.Iterator;
import org.json.JSONObject;
import com.todoroo.astrid.api.TaskContainer;
import com.todoroo.astrid.common.TaskContainer;
import com.todoroo.astrid.model.Metadata;
import com.todoroo.astrid.model.Task;

@ -29,7 +29,7 @@ public class MilkBackgroundService extends Service {
private static final long AUTO_SYNC_MIN_OFFSET = 5*60*1000L;
/** alarm identifier */
private static final String SYNC_ACTION = "sync"; //$NON-NLS-1$
public static final String SYNC_ACTION = "sync"; //$NON-NLS-1$
// --- BroadcastReceiver abstract methods
@ -37,7 +37,8 @@ public class MilkBackgroundService extends Service {
@Override
public void onStart(Intent intent, int startId) {
try {
startSynchronization(this);
if(intent != null && SYNC_ACTION.equals(intent.getAction()))
startSynchronization(this);
} catch (Exception e) {
PluginServices.getExceptionService().reportError("rtm-bg-sync", e); //$NON-NLS-1$
}

@ -3,7 +3,6 @@ package com.todoroo.astrid.rmilk;
import java.util.Date;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.content.res.Resources;
import android.graphics.Color;
@ -100,7 +99,7 @@ public class MilkPreferences extends TodorooPreferences {
statusColor = Color.RED;
preference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference p) {
startService(new Intent(MilkPreferences.this, MilkBackgroundService.class));
new RTMSyncProvider().synchronize(MilkPreferences.this);
finish();
return true;
}
@ -140,7 +139,7 @@ public class MilkPreferences extends TodorooPreferences {
statusColor = Color.rgb(0, 0, 100);
preference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference p) {
startService(new Intent(MilkPreferences.this, MilkBackgroundService.class));
new RTMSyncProvider().synchronize(MilkPreferences.this);
finish();
return true;
}
@ -159,7 +158,7 @@ public class MilkPreferences extends TodorooPreferences {
boolean loggedIn = MilkUtilities.isLoggedIn();
preference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference p) {
startService(new Intent(MilkPreferences.this, MilkBackgroundService.class));
new RTMSyncProvider().synchronize(MilkPreferences.this);
finish();
return true;
}

@ -13,6 +13,7 @@ import java.util.List;
import android.app.Activity;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@ -31,15 +32,18 @@ import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.TaskContainer;
import com.todoroo.astrid.common.SyncProvider;
import com.todoroo.astrid.common.TaskContainer;
import com.todoroo.astrid.model.Metadata;
import com.todoroo.astrid.model.Task;
import com.todoroo.astrid.producteev.api.ApiServiceException;
import com.todoroo.astrid.rmilk.MilkBackgroundService;
import com.todoroo.astrid.rmilk.MilkLoginActivity;
import com.todoroo.astrid.rmilk.MilkLoginActivity.SyncLoginCallback;
import com.todoroo.astrid.rmilk.MilkPreferences;
import com.todoroo.astrid.rmilk.MilkUtilities;
import com.todoroo.astrid.rmilk.api.ApplicationInfo;
import com.todoroo.astrid.rmilk.api.ServiceException;
import com.todoroo.astrid.rmilk.api.ServiceImpl;
import com.todoroo.astrid.rmilk.api.ServiceInternalException;
import com.todoroo.astrid.rmilk.api.data.RtmAuth.Perms;
@ -92,10 +96,6 @@ public class RTMSyncProvider extends SyncProvider<RTMTaskContainer> {
dataService.clearMetadata();
}
// ----------------------------------------------------------------------
// ------------------------------------------------------- authentication
// ----------------------------------------------------------------------
/**
* Deal with a synchronization exception. If requested, will show an error
* to the user (unless synchronization is happening in background)
@ -109,63 +109,65 @@ public class RTMSyncProvider extends SyncProvider<RTMTaskContainer> {
* whether to display a dialog
*/
@Override
protected void handleException(String tag, Exception e, boolean showError) {
protected void handleException(String tag, Exception e, boolean displayError) {
final Context context = ContextManager.getContext();
MilkUtilities.setLastError(e.toString());
String message = null;
// occurs when application was closed
if(e instanceof IllegalStateException) {
exceptionService.reportError(tag + "-caught", e); //$NON-NLS-1$
// occurs when network error
} else if(e instanceof ServiceInternalException &&
((ServiceInternalException)e).getEnclosedException() instanceof
IOException) {
Exception enclosedException = ((ServiceInternalException)e).getEnclosedException();
exceptionService.reportError(tag + "-ioexception", enclosedException); //$NON-NLS-1$
if(showError) {
Context context = ContextManager.getContext();
showError(context, enclosedException,
context.getString(R.string.rmilk_ioerror));
}
// occurs when network error
} else if(!(e instanceof ApiServiceException) && e instanceof IOException) {
message = context.getString(R.string.rmilk_ioerror);
} else {
if(e instanceof ServiceInternalException)
e = ((ServiceInternalException)e).getEnclosedException();
message = context.getString(R.string.DLG_error, e.toString());
exceptionService.reportError(tag + "-unhandled", e); //$NON-NLS-1$
if(showError) {
Context context = ContextManager.getContext();
showError(context, e, null);
}
}
if(displayError && context instanceof Activity && message != null) {
dialogUtilities.okDialog((Activity)context,
message, null);
}
}
@Override
protected void initiate(Context context) {
dataService = MilkDataService.getInstance();
// ----------------------------------------------------------------------
// ------------------------------------------------------ initiating sync
// ----------------------------------------------------------------------
// authenticate the user. this will automatically call the next step
authenticate(context);
/**
* set up service
*/
@SuppressWarnings("nls")
private void initializeService(String authToken) throws ServiceInternalException {
String appName = null;
String z = stripslashes(0,"q9883o3384n21snq17501qn38oo1r689", "b");
String v = stripslashes(16,"19o2n020345219os","a");
if(authToken == null)
rtmService = new ServiceImpl(new ApplicationInfo(
z, v, appName));
else
rtmService = new ServiceImpl(new ApplicationInfo(
z, v, appName, authToken));
}
/**
* Perform authentication with RTM. Will open the SyncBrowser if necessary
* initiate sync in background
*/
@Override
@SuppressWarnings("nls")
private void authenticate(final Context context) {
final Resources r = context.getResources();
FlurryAgent.onEvent("rtm-started");
MilkUtilities.recordSyncStart();
protected void initiateBackground(Service service) {
dataService = MilkDataService.getInstance();
try {
String appName = null;
String authToken = MilkUtilities.getToken();
String z = stripslashes(0,"q9883o3384n21snq17501qn38oo1r689", "b");
String v = stripslashes(16,"19o2n020345219os","a");
// check if we have a token & it works
if(authToken != null) {
rtmService = new ServiceImpl(new ApplicationInfo(
z, v, appName, authToken));
initializeService(authToken);
if(!rtmService.isServiceAuthorized()) // re-do login
authToken = null;
}
@ -180,53 +182,17 @@ public class RTMSyncProvider extends SyncProvider<RTMTaskContainer> {
return;
} catch (Exception e) {
// didn't work. do the process again.
// didn't work.
}
}
// open up a dialog and have the user go to browser
rtmService = new ServiceImpl(new ApplicationInfo(
z, v, appName));
final String url = rtmService.beginAuthorization(Perms.delete);
Intent intent = new Intent(context, MilkLoginActivity.class);
MilkLoginActivity.setCallback(new SyncLoginCallback() {
public String verifyLogin(final Handler syncLoginHandler) {
if(rtmService == null) {
return null;
}
try {
String token = rtmService.completeAuthorization();
MilkUtilities.setToken(token);
synchronize(context);
return null;
} catch (Exception e) {
// didn't work
exceptionService.reportError("rtm-verify-login", e);
rtmService = null;
if(e instanceof ServiceInternalException)
e = ((ServiceInternalException)e).getEnclosedException();
return r.getString(R.string.rmilk_MLA_error, e.getMessage());
}
}
});
intent.putExtra(MilkLoginActivity.URL_TOKEN, url);
if(context instanceof Activity)
((Activity)context).startActivityForResult(intent, 0);
else {
// can't synchronize until user logs in
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
MilkUtilities.stopOngoing();
}
// can't do anything, user not logged in
} else {
performSync();
}
} catch (IllegalStateException e) {
// occurs when application was closed
// occurs when application was closed
} catch (Exception e) {
handleException("rtm-authenticate", e, true);
} finally {
@ -234,11 +200,66 @@ public class RTMSyncProvider extends SyncProvider<RTMTaskContainer> {
}
}
/**
* If user isn't already signed in, show sign in dialog. Else perform sync.
*/
@SuppressWarnings("nls")
@Override
protected void initiateManual(final Activity activity) {
final Resources r = activity.getResources();
String authToken = MilkUtilities.getToken();
MilkUtilities.stopOngoing();
// check if we have a token & it works
if(authToken == null) {
// open up a dialog and have the user go to browser
final String url;
try {
initializeService(null);
url = rtmService.beginAuthorization(Perms.delete);
} catch (ServiceException e) {
handleException("rmilk-auth", e, true);
return;
}
Intent intent = new Intent(activity, MilkLoginActivity.class);
MilkLoginActivity.setCallback(new SyncLoginCallback() {
public String verifyLogin(final Handler syncLoginHandler) {
if(rtmService == null) {
return null;
}
try {
String token = rtmService.completeAuthorization();
MilkUtilities.setToken(token);
synchronize(activity);
return null;
} catch (Exception e) {
// didn't work
exceptionService.reportError("rtm-verify-login", e);
rtmService = null;
if(e instanceof ServiceInternalException)
e = ((ServiceInternalException)e).getEnclosedException();
return r.getString(R.string.rmilk_MLA_error, e.getMessage());
}
}
});
intent.putExtra(MilkLoginActivity.URL_TOKEN, url);
activity.startActivityForResult(intent, 0);
} else {
activity.startService(new Intent(MilkBackgroundService.SYNC_ACTION, null,
activity, MilkBackgroundService.class));
}
}
// ----------------------------------------------------------------------
// ----------------------------------------------------- synchronization!
// ----------------------------------------------------------------------
protected void performSync() {
FlurryAgent.onEvent("rtm-started"); //$NON-NLS-1$
MilkUtilities.recordSyncStart();
try {
// get RTM timeline
timeline = rtmService.timelines_create();

@ -3,7 +3,7 @@ package com.todoroo.astrid.rmilk.sync;
import java.util.ArrayList;
import java.util.Iterator;
import com.todoroo.astrid.api.TaskContainer;
import com.todoroo.astrid.common.TaskContainer;
import com.todoroo.astrid.model.Metadata;
import com.todoroo.astrid.model.Task;
import com.todoroo.astrid.rmilk.api.data.RtmTaskSeries;

Loading…
Cancel
Save