diff --git a/astrid/.classpath b/astrid/.classpath index 9cf65cc65..e0db125e4 100644 --- a/astrid/.classpath +++ b/astrid/.classpath @@ -15,5 +15,6 @@ + diff --git a/astrid/AndroidManifest.xml b/astrid/AndroidManifest.xml index 01ff5b68c..b6727a190 100644 --- a/astrid/AndroidManifest.xml +++ b/astrid/AndroidManifest.xml @@ -22,6 +22,13 @@ + + + + + + + diff --git a/astrid/libs/googleloginclient-helper.jar b/astrid/libs/googleloginclient-helper.jar new file mode 100644 index 000000000..6e610e991 Binary files /dev/null and b/astrid/libs/googleloginclient-helper.jar differ diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/AccountChooser.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/AccountChooser.java new file mode 100644 index 000000000..aaa86d3b1 --- /dev/null +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/AccountChooser.java @@ -0,0 +1,125 @@ +/* + * Copyright 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.todoroo.astrid.gtasks.auth; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; + +import com.timsu.astrid.R; + +/** + * Choose which account to upload track information to. + * @author Sandor Dornbush + */ +public class AccountChooser { + + /** + * The last selected account. + */ + private int selectedAccountIndex = -1; + private Account selectedAccount = null; + + /** + * An interface for receiving updates once the user has selected the account. + */ + public interface AccountHandler { + /** + * Handle the account being selected. + * @param account The selected account or null if none could be found + */ + public void handleAccountSelected(Account account); + } + + /** + * Chooses the best account to upload to. + * If no account is found the user will be alerted. + * If only one account is found that will be used. + * If multiple accounts are found the user will be allowed to choose. + * + * @param activity The parent activity + * @param handler The handler to be notified when an account has been selected + */ + public void chooseAccount(final Activity activity, + final AccountHandler handler) { + final Account[] accounts = AccountManager.get(activity) + .getAccountsByType("com.google"); //$NON-NLS-1$ + if (accounts.length < 1) { + alertNoAccounts(activity, handler); + return; + } + if (accounts.length == 1) { + handler.handleAccountSelected(accounts[0]); + return; + } + + // TODO This should be read out of a preference. + if (selectedAccount != null) { + handler.handleAccountSelected(selectedAccount); + return; + } + + // Let the user choose. + final AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setTitle(R.string.choose_account_title); + builder.setCancelable(false); + builder.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + selectedAccount = accounts[selectedAccountIndex]; + handler.handleAccountSelected(selectedAccount); + } + }); + builder.setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + handler.handleAccountSelected(null); + } + }); + String[] choices = new String[accounts.length]; + for (int i = 0; i < accounts.length; i++) { + choices[i] = accounts[i].name; + } + builder.setSingleChoiceItems(choices, selectedAccountIndex, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + selectedAccountIndex = which; + } + }); + builder.show(); + } + + /** + * Puts up a dialog alerting the user that no suitable account was found. + */ + private void alertNoAccounts(final Activity activity, + final AccountHandler handler) { + final AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setTitle(R.string.no_account_found_title); + builder.setMessage(R.string.no_account_found); + builder.setCancelable(true); + builder.setNegativeButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + handler.handleAccountSelected(null); + } + }); + builder.show(); + } +} diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/AuthManager.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/AuthManager.java new file mode 100644 index 000000000..f410aca31 --- /dev/null +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/AuthManager.java @@ -0,0 +1,77 @@ +/* + * Copyright 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.todoroo.astrid.gtasks.auth; + +import android.content.Intent; + +/** + * This interface describes a class that will fetch and maintain a Google + * authentication token. + * + * @author Sandor Dornbush + */ +public interface AuthManager { + + /** + * Initializes the login process. The user should be asked to login if they + * haven't already. The {@link Runnable} provided will be executed when the + * auth token is successfully fetched. + * + * @param whenFinished A {@link Runnable} to execute when the auth token + * has been successfully fetched and is available via + * {@link #getAuthToken()} + */ + public abstract void doLogin(Runnable whenFinished, Object o); + + /** + * The {@link android.app.Activity} owner of this class should call this + * function when it gets {@link android.app.Activity#onActivityResult} with + * the request code passed into the constructor. The resultCode and results + * should come directly from the {@link android.app.Activity#onActivityResult} + * function. This function will return true if an auth token was successfully + * fetched or the process is not finished. + * + * @param resultCode The result code passed in to the + * {@link android.app.Activity}'s + * {@link android.app.Activity#onActivityResult} function + * @param results The data passed in to the {@link android.app.Activity}'s + * {@link android.app.Activity#onActivityResult} function + * @return True if the auth token was fetched or we aren't done fetching + * the auth token, or False if there was an error or the request was + * canceled + */ + public abstract boolean authResult(int resultCode, Intent results); + + /** + * Returns the current auth token. Response may be null if no valid auth + * token has been fetched. + * + * @return The current auth token or null if no auth token has been + * fetched + */ + public abstract String getAuthToken(); + + /** + * Invalidates the existing auth token and request a new one. The + * {@link Runnable} provided will be executed when the new auth token is + * successfully fetched. + * + * @param whenFinished A {@link Runnable} to execute when a new auth token + * is successfully fetched + */ + public abstract void invalidateAndRefresh(Runnable whenFinished); + +} diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/AuthManagerFactory.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/AuthManagerFactory.java new file mode 100644 index 000000000..8ffbd0342 --- /dev/null +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/AuthManagerFactory.java @@ -0,0 +1,53 @@ +/* + * Copyright 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.todoroo.astrid.gtasks.auth; + +import android.app.Activity; +import android.os.Build; +import android.os.Bundle; + +/** + * A factory for getting the platform specific AuthManager. + * + * @author Sandor Dornbush + */ +public class AuthManagerFactory { + + private AuthManagerFactory() { + // don't construct me + } + + /** + * Returns whether the modern AuthManager should be used + */ + public static boolean useModernAuthManager() { + return Integer.parseInt(Build.VERSION.SDK) >= 7; + } + + /** + * Get a right {@link AuthManager} for the platform. + * @return A new AuthManager + */ + public static AuthManager getAuthManager(Activity activity, int code, + Bundle extras, boolean requireGoogle, String service) { + if (useModernAuthManager()) { + return new ModernAuthManager(activity, code, extras, requireGoogle, service); + } else { + return new AuthManagerOld(activity, code, extras, requireGoogle, service); + } + } + +} diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/AuthManagerOld.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/AuthManagerOld.java new file mode 100644 index 000000000..eda7413e2 --- /dev/null +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/AuthManagerOld.java @@ -0,0 +1,198 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.todoroo.astrid.gtasks.auth; + +import java.util.Iterator; +import java.util.Vector; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +import com.google.android.googlelogindist.GoogleLoginServiceConstants; +import com.google.android.googlelogindist.GoogleLoginServiceHelper; + +/** + * AuthManager keeps track of the current auth token for a user. The advantage + * over just passing around a String is that this class can renew the auth + * token if necessary, and it will change for all classes using this + * AuthManager. + */ +public class AuthManagerOld implements AuthManager { + /** The activity that will handle auth result callbacks. */ + private final Activity activity; + + /** The code used to tell the activity that it is an auth result. */ + private final int code; + + /** Extras to pass into the getCredentials function. */ + private final Bundle extras; + + /** True if the account must be a Google account (not a domain account). */ + private final boolean requireGoogle; + + /** The name of the service to authorize for. */ + private final String service; + + /** A list of handlers to call when a new auth token is fetched. */ + private final Vector newTokenListeners = new Vector(); + + /** The most recently fetched auth token or null if none is available. */ + private String authToken; + + /** + * The number of handlers at the beginning of the above list that shouldn't + * be removed after they are called. + */ + private int stickyNewTokenListenerCount; + + /** + * AuthManager requires many of the same parameters as + * {@link GoogleLoginServiceHelper#getCredentials(Activity, int, Bundle, + * boolean, String, boolean)}. The activity must have + * a handler in {@link Activity#onActivityResult} that calls + * {@link #authResult(int, Intent)} if the request code is the code given + * here. + * + * @param activity An activity with a handler in + * {@link Activity#onActivityResult} that calls + * {@link #authResult(int, Intent)} when {@literal code} is the request + * code + * @param code The request code to pass to + * {@link Activity#onActivityResult} when + * {@link #authResult(int, Intent)} should be called + * @param extras A {@link Bundle} of extras for + * {@link GoogleLoginServiceHelper} + * @param requireGoogle True if the account must be a Google account + * @param service The name of the service to authenticate as + */ + public AuthManagerOld(Activity activity, int code, Bundle extras, + boolean requireGoogle, String service) { + this.activity = activity; + this.code = code; + this.extras = extras; + this.requireGoogle = requireGoogle; + this.service = service; + } + + /* (non-Javadoc) + * @see com.google.android.apps.mytracks.io.AuthManager#doLogin(java.lang.Runnable) + */ + public void doLogin(Runnable whenFinished, Object o) { + synchronized (newTokenListeners) { + if (whenFinished != null) { + newTokenListeners.add(whenFinished); + } + } + activity.runOnUiThread(new LoginRunnable()); + } + + /** + * Runnable which actually gets login credentials. + */ + private class LoginRunnable implements Runnable { + @Override + public void run() { + GoogleLoginServiceHelper.getCredentials( + activity, code, extras, requireGoogle, service, true); + } + } + + /* (non-Javadoc) + * @see com.google.android.apps.mytracks.io.AuthManager#authResult(int, android.content.Intent) + */ + public boolean authResult(int resultCode, Intent results) { + if (resultCode == Activity.RESULT_OK) { + authToken = results.getStringExtra( + GoogleLoginServiceConstants.AUTHTOKEN_KEY); + if (authToken == null) { + GoogleLoginServiceHelper.getCredentials( + activity, code, extras, requireGoogle, service, false); + return true; + } else { + // Notify all active listeners that we have a new auth token. + synchronized (newTokenListeners) { + Iterator iter = newTokenListeners.iterator(); + while (iter.hasNext()) { + iter.next().run(); + } + iter = null; + // Remove anything not in the sticky part of the list. + newTokenListeners.setSize(stickyNewTokenListenerCount); + } + return true; + } + } + return false; + } + + /* (non-Javadoc) + * @see com.google.android.apps.mytracks.io.AuthManager#getAuthToken() + */ + public String getAuthToken() { + return authToken; + } + + /* (non-Javadoc) + * @see com.google.android.apps.mytracks.io.AuthManager#invalidateAndRefresh(java.lang.Runnable) + */ + public void invalidateAndRefresh(Runnable whenFinished) { + synchronized (newTokenListeners) { + if (whenFinished != null) { + newTokenListeners.add(whenFinished); + } + } + activity.runOnUiThread(new Runnable() { + public void run() { + GoogleLoginServiceHelper.invalidateAuthToken(activity, code, authToken); + } + }); + } + + /** + * Adds a {@link Runnable} to be executed every time the auth token is + * updated. The {@link Runnable} will not be removed until manually removed + * with {@link #removeStickyNewTokenListener(Runnable)}. + * + * @param listener The {@link Runnable} to execute every time a new auth + * token is fetched + */ + public void addStickyNewTokenListener(Runnable listener) { + synchronized (newTokenListeners) { + newTokenListeners.add(0, listener); + stickyNewTokenListenerCount++; + } + } + + /** + * Stops executing the given {@link Runnable} every time the auth token is + * updated. This {@link Runnable} must have been added with + * {@link #addStickyNewTokenListener(Runnable)} above. If the + * {@link Runnable} was added more than once, only the first occurrence + * will be removed. + * + * @param listener The {@link Runnable} to stop executing every time a new + * auth token is fetched + */ + public void removeStickyNewTokenListener(Runnable listener) { + synchronized (newTokenListeners) { + if (stickyNewTokenListenerCount > 0 + && newTokenListeners.remove(listener)) { + stickyNewTokenListenerCount--; + } + } + } +} diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/ModernAuthManager.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/ModernAuthManager.java new file mode 100644 index 000000000..0df1b4812 --- /dev/null +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/ModernAuthManager.java @@ -0,0 +1,210 @@ +/* + * Copyright 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.todoroo.astrid.gtasks.auth; + +import java.io.IOException; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.accounts.AccountManagerCallback; +import android.accounts.AccountManagerFuture; +import android.accounts.AuthenticatorException; +import android.accounts.OperationCanceledException; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +/** + * AuthManager keeps track of the current auth token for a user. The advantage + * over just passing around a String is that this class can renew the auth + * token if necessary, and it will change for all classes using this + * AuthManager. + */ +public class ModernAuthManager implements AuthManager { + protected static final int GET_LOGIN_REQUEST = 1; + +/** The activity that will handle auth result callbacks. */ + private final Activity activity; + + /** The name of the service to authorize for. */ + private final String service; + + /** The most recently fetched auth token or null if none is available. */ + private String authToken; + + private final AccountManager accountManager; + + private Runnable whenFinished; + + /** + * AuthManager requires many of the same parameters as + * {@link com.google.android.googlelogindist.GoogleLoginServiceHelper + * #getCredentials(Activity, int, Bundle, boolean, String, boolean)}. + * The activity must have a handler in {@link Activity#onActivityResult} that + * calls {@link #authResult(int, Intent)} if the request code is the code + * given here. + * + * @param activity An activity with a handler in + * {@link Activity#onActivityResult} that calls + * {@link #authResult(int, Intent)} when {@literal code} is the request + * code + * @param code The request code to pass to + * {@link Activity#onActivityResult} when + * {@link #authResult(int, Intent)} should be called + * @param extras A {@link Bundle} of extras for + * {@link com.google.android.googlelogindist.GoogleLoginServiceHelper} + * @param requireGoogle True if the account must be a Google account + * @param service The name of the service to authenticate as + */ + public ModernAuthManager(Activity activity, int code, Bundle extras, + boolean requireGoogle, String service) { + this.activity = activity; + this.service = service; + this.accountManager = AccountManager.get(activity); + } + + /** + * Call this to do the initial login. The user will be asked to login if + * they haven't already. The {@link Runnable} provided will be executed + * when the auth token is successfully fetched. + * + * @param runnable A {@link Runnable} to execute when the auth token + * has been successfully fetched and is available via + * {@link #getAuthToken()} + */ + @SuppressWarnings("nls") + public void doLogin(final Runnable runnable, Object o) { + this.whenFinished = runnable; + if (!(o instanceof Account)) { + throw new IllegalArgumentException("FroyoAuthManager requires an account."); + } + Account account = (Account) o; + accountManager.getAuthToken(account, service, true, + new AccountManagerCallback() { + public void run(AccountManagerFuture future) { + try { + Bundle result = future.getResult(); + + // AccountManager needs user to grant permission + if (result.containsKey(AccountManager.KEY_INTENT)) { + Intent intent = (Intent) result.get(AccountManager.KEY_INTENT); + clearNewTaskFlag(intent); + activity.startActivityForResult(intent, GET_LOGIN_REQUEST); + return; + } + + authToken = result.getString( + AccountManager.KEY_AUTHTOKEN); + Log.e("gtasks-auth", "Got auth token."); + runWhenFinished(); + } catch (OperationCanceledException e) { + Log.e("gtasks-auth", "Operation Canceled", e); + } catch (IOException e) { + Log.e("gtasks-auth", "IOException", e); + } catch (AuthenticatorException e) { + Log.e("gtasks-auth", "Authentication Failed", e); + } + } + }, null /* handler */); + } + + private static void clearNewTaskFlag(Intent intent) { + int flags = intent.getFlags(); + flags &= ~Intent.FLAG_ACTIVITY_NEW_TASK; + intent.setFlags(flags); + } + + /** + * The {@link Activity} passed into the constructor should call this + * function when it gets {@link Activity#onActivityResult} with the request + * code passed into the constructor. The resultCode and results should + * come directly from the {@link Activity#onActivityResult} function. This + * function will return true if an auth token was successfully fetched or + * the process is not finished. + * + * @param resultCode The result code passed in to the {@link Activity}'s + * {@link Activity#onActivityResult} function + * @param results The data passed in to the {@link Activity}'s + * {@link Activity#onActivityResult} function + * @return True if the auth token was fetched or we aren't done fetching + * the auth token, or False if there was an error or the request was + * canceled + */ + @SuppressWarnings("nls") + public boolean authResult(int resultCode, Intent results) { + if (results != null) { + authToken = results.getStringExtra( + AccountManager.KEY_AUTHTOKEN); + Log.w("google-auth", "authResult: " + authToken); + } else { + Log.e("google-auth", "No auth result results!!"); + } + runWhenFinished(); + return authToken != null; + } + + /** + * Returns the current auth token. Response may be null if no valid auth + * token has been fetched. + * + * @return The current auth token or null if no auth token has been + * fetched + */ + public String getAuthToken() { + return authToken; + } + + /** + * Invalidates the existing auth token and request a new one. The + * {@link Runnable} provided will be executed when the new auth token is + * successfully fetched. + * + * @param runnable A {@link Runnable} to execute when a new auth token + * is successfully fetched + */ + public void invalidateAndRefresh(final Runnable runnable) { + this.whenFinished = runnable; + + activity.runOnUiThread(new Runnable() { + public void run() { + accountManager.invalidateAuthToken("com.google", authToken); //$NON-NLS-1$ + new AccountChooser().chooseAccount(activity, + new AccountChooser.AccountHandler() { + @Override + public void handleAccountSelected(Account account) { + if (account != null) { + doLogin(whenFinished, account); + } else { + runWhenFinished(); + } + } + }); + } + }); + } + + private void runWhenFinished() { + if (whenFinished != null) { + (new Thread() { + @Override + public void run() { + whenFinished.run(); + } + }).start(); + } + } +} diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncProvider.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncProvider.java index b3da92157..83aa673e7 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncProvider.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncProvider.java @@ -16,6 +16,8 @@ import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; +import android.os.Bundle; +import android.util.Log; import com.flurry.android.FlurryAgent; import com.timsu.astrid.R; @@ -41,6 +43,8 @@ import com.todoroo.astrid.gtasks.GtasksMetadataService; import com.todoroo.astrid.gtasks.GtasksPreferenceService; import com.todoroo.astrid.gtasks.GtasksPreferences; import com.todoroo.astrid.gtasks.GtasksTaskListUpdater; +import com.todoroo.astrid.gtasks.auth.AuthManager; +import com.todoroo.astrid.gtasks.auth.AuthManagerFactory; import com.todoroo.astrid.producteev.api.ApiServiceException; import com.todoroo.astrid.service.AstridDependencyInjector; import com.todoroo.astrid.sync.SyncBackgroundService; @@ -48,7 +52,6 @@ import com.todoroo.astrid.sync.SyncContainer; import com.todoroo.astrid.sync.SyncProvider; import com.todoroo.astrid.utility.Constants; import com.todoroo.gtasks.GoogleConnectionManager; -import com.todoroo.gtasks.GoogleLoginException; import com.todoroo.gtasks.GoogleTaskService; import com.todoroo.gtasks.GoogleTaskTask; import com.todoroo.gtasks.GoogleTaskView; @@ -83,8 +86,6 @@ public class GtasksSyncProvider extends SyncProvider { public GtasksSyncProvider() { super(); DependencyInjectionService.getInstance().inject(this); - // TODO? - gtasksPreferenceService.stopOngoing(); } // ---------------------------------------------------------------------- @@ -152,7 +153,8 @@ public class GtasksSyncProvider extends SyncProvider { final GoogleConnectionManager connectionManager; if(authToken == null) { - connectionManager = logInHelper(); + Log.e("astrid-sync", "No token, unable to sync"); + return; } else { connectionManager = new GoogleConnectionManager(authToken); } @@ -168,36 +170,39 @@ public class GtasksSyncProvider extends SyncProvider { } } - private GoogleConnectionManager logInHelper() throws GoogleLoginException, - IOException { - // TODO get email and password or something? - String email = "tasktest@todoroo.com"; - String password = "tasktest0000"; - GoogleConnectionManager connectionManager = new GoogleConnectionManager(email, password); - connectionManager.authenticate(true); - gtasksPreferenceService.setToken(connectionManager.getToken()); - return connectionManager; - } - /** * If user isn't already signed in, show sign in dialog. Else perform sync. */ @Override - protected void initiateManual(Activity activity) { + protected void initiateManual(final Activity activity) { String authToken = gtasksPreferenceService.getToken(); gtasksPreferenceService.stopOngoing(); // check if we have a token & it works if(authToken == null) { try { - logInHelper(); + final AuthManager authManager = AuthManagerFactory.getAuthManager(activity, 0, new Bundle(), true, "goanna_mobile"); + authManager.invalidateAndRefresh(new Runnable() { + @Override + public void run() { + String token = authManager.getAuthToken(); + if(token != null) { + gtasksPreferenceService.setToken(token); + //activity.startService(new Intent(SyncBackgroundService.SYNC_ACTION, null, + // activity, GtasksBackgroundService.class)); + System.err.println("yay! " + token); + activity.finish(); + } + } + }); } catch (Exception e) { handleException("auth", e, true); } - } - - activity.startService(new Intent(SyncBackgroundService.SYNC_ACTION, null, + } else { + activity.startService(new Intent(SyncBackgroundService.SYNC_ACTION, null, activity, GtasksBackgroundService.class)); + activity.finish(); + } } diff --git a/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevPreferences.java b/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevPreferences.java index 3d51b53ae..d62fa6e86 100644 --- a/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevPreferences.java +++ b/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevPreferences.java @@ -31,6 +31,7 @@ public class ProducteevPreferences extends SyncProviderPreferences { @Override public void startSync() { new ProducteevSyncProvider().synchronize(this); + finish(); } @Override diff --git a/astrid/res/values/strings-gtasks.xml b/astrid/res/values/strings-gtasks.xml index febd2d61a..912031eb3 100644 --- a/astrid/res/values/strings-gtasks.xml +++ b/astrid/res/values/strings-gtasks.xml @@ -35,5 +35,14 @@ Astrid: Google Tasks + + Choose Account + + + No Accounts Found + + + We were unable to find a Google account on this phone. You will not be able to synchronize to Google Tasks without one! + diff --git a/astrid/rmilk-src/org/weloveastrid/rmilk/MilkPreferences.java b/astrid/rmilk-src/org/weloveastrid/rmilk/MilkPreferences.java index 613486a18..89b3ab780 100644 --- a/astrid/rmilk-src/org/weloveastrid/rmilk/MilkPreferences.java +++ b/astrid/rmilk-src/org/weloveastrid/rmilk/MilkPreferences.java @@ -23,6 +23,7 @@ public class MilkPreferences extends SyncProviderPreferences { @Override public void startSync() { new MilkSyncProvider().synchronize(this); + finish(); } @Override