mirror of https://github.com/tasks/tasks
Imported auth manager and account chooser code from Google MyTracks (Apache License). Wired up gtasks to use auth manager. Modern seems to work but Old does not.
parent
c1079acf93
commit
d2d4f8150b
Binary file not shown.
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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<Runnable> newTokenListeners = new Vector<Runnable>();
|
||||||
|
|
||||||
|
/** 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<Runnable> 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--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<Bundle>() {
|
||||||
|
public void run(AccountManagerFuture<Bundle> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue