type) {
+ return objectGraph.get(type);
+ }
+}
diff --git a/app/src/main/java/com/donnfelker/android/bootstrap/RootModule.java b/app/src/main/java/com/donnfelker/android/bootstrap/RootModule.java
new file mode 100644
index 0000000..e8e1e5d
--- /dev/null
+++ b/app/src/main/java/com/donnfelker/android/bootstrap/RootModule.java
@@ -0,0 +1,15 @@
+package com.donnfelker.android.bootstrap;
+
+import dagger.Module;
+
+/**
+ * Add all the other modules to this one.
+ */
+@Module(
+ includes = {
+ AndroidModule.class,
+ BootstrapModule.class
+ }
+)
+public class RootModule {
+}
diff --git a/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/AccountAuthenticatorService.java b/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/AccountAuthenticatorService.java
index e9eb16c..1dcd71d 100644
--- a/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/AccountAuthenticatorService.java
+++ b/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/AccountAuthenticatorService.java
@@ -1,26 +1,31 @@
package com.donnfelker.android.bootstrap.authenticator;
-import static android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
+import static android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT;
+
/**
- * Authenticator service that returns a subclass of AbstractAccountAuthenticator in onBind()
+ * Authenticator service that returns a subclass of AbstractAccountAuthenticator in onBind().
*/
public class AccountAuthenticatorService extends Service {
- private static BootstrapAccountAuthenticator AUTHENTICATOR = null;
+ private static BootstrapAccountAuthenticator authenticator = null;
@Override
- public IBinder onBind(Intent intent) {
- return intent.getAction().equals(ACTION_AUTHENTICATOR_INTENT) ? getAuthenticator().getIBinder() : null;
+ public IBinder onBind(final Intent intent) {
+ if (intent != null && ACTION_AUTHENTICATOR_INTENT.equals(intent.getAction())) {
+ return getAuthenticator().getIBinder();
+ }
+ return null;
}
private BootstrapAccountAuthenticator getAuthenticator() {
- if (AUTHENTICATOR == null)
- AUTHENTICATOR = new BootstrapAccountAuthenticator(this);
- return AUTHENTICATOR;
+ if (authenticator == null) {
+ authenticator = new BootstrapAccountAuthenticator(this);
+ }
+ return authenticator;
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/ActionBarAccountAuthenticatorActivity.java b/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/ActionBarAccountAuthenticatorActivity.java
new file mode 100644
index 0000000..d554a38
--- /dev/null
+++ b/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/ActionBarAccountAuthenticatorActivity.java
@@ -0,0 +1,72 @@
+package com.donnfelker.android.bootstrap.authenticator;
+
+import android.accounts.AccountAuthenticatorResponse;
+import android.accounts.AccountManager;
+import android.os.Bundle;
+import android.support.v7.app.ActionBarActivity;
+
+
+/**
+ * Base class for implementing an Activity that is used to help implement an
+ * AbstractAccountAuthenticator. If the AbstractAccountAuthenticator needs to use an activity
+ * to handle the request then it can have the activity extend ActionBarAccountAuthenticatorActivity.
+ * The AbstractAccountAuthenticator passes in the response to the intent using the following:
+ *
+ * intent.putExtra({@link android.accounts.AccountManager#KEY_ACCOUNT_AUTHENTICATOR_RESPONSE}, response);
+ *
+ * The activity then sets the result that is to be handed to the response via
+ * {@link #setAccountAuthenticatorResult(android.os.Bundle)}.
+ * This result will be sent as the result of the request when the activity finishes. If this
+ * is never set or if it is set to null then error
+ * {@link android.accounts.AccountManager#ERROR_CODE_CANCELED}
+ * will be called on the response.
+ */
+public class ActionBarAccountAuthenticatorActivity extends ActionBarActivity {
+ private AccountAuthenticatorResponse accountAuthenticatorResponse = null;
+ private Bundle resultBundle = null;
+
+ /**
+ * Set the result that is to be sent as the result of the request that caused this
+ * Activity to be launched. If result is null or this method is never called then
+ * the request will be canceled.
+ *
+ * @param result this is returned as the result of the AbstractAccountAuthenticator request
+ */
+ public final void setAccountAuthenticatorResult(Bundle result) {
+ resultBundle = result;
+ }
+
+ /**
+ * Retreives the AccountAuthenticatorResponse from either the intent of the icicle, if the
+ * icicle is non-zero.
+ *
+ * @param icicle the save instance data of this Activity, may be null
+ */
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ accountAuthenticatorResponse =
+ getIntent().getParcelableExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE);
+
+ if (accountAuthenticatorResponse != null) {
+ accountAuthenticatorResponse.onRequestContinued();
+ }
+ }
+
+ /**
+ * Sends the result or a Constants.ERROR_CODE_CANCELED error if a result isn't present.
+ */
+ public void finish() {
+ if (accountAuthenticatorResponse != null) {
+ // send the result bundle back if set, otherwise send an error.
+ if (resultBundle != null) {
+ accountAuthenticatorResponse.onResult(resultBundle);
+ } else {
+ accountAuthenticatorResponse.onError(AccountManager.ERROR_CODE_CANCELED,
+ "canceled");
+ }
+ accountAuthenticatorResponse = null;
+ }
+ super.finish();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/ApiKeyProvider.java b/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/ApiKeyProvider.java
index 500a6f0..cd97ab7 100644
--- a/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/ApiKeyProvider.java
+++ b/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/ApiKeyProvider.java
@@ -2,37 +2,47 @@
package com.donnfelker.android.bootstrap.authenticator;
-import static android.accounts.AccountManager.KEY_AUTHTOKEN;
-
import android.accounts.AccountManager;
import android.accounts.AccountManagerFuture;
import android.accounts.AccountsException;
import android.app.Activity;
import android.os.Bundle;
-import com.donnfelker.android.bootstrap.core.Constants;
-import com.google.inject.Inject;
-
import java.io.IOException;
+import javax.inject.Inject;
+
+import static android.accounts.AccountManager.KEY_AUTHTOKEN;
+import static com.donnfelker.android.bootstrap.core.Constants.Auth.AUTHTOKEN_TYPE;
+import static com.donnfelker.android.bootstrap.core.Constants.Auth.BOOTSTRAP_ACCOUNT_TYPE;
+
/**
* Bridge class that obtains a API key for the currently configured account
*/
public class ApiKeyProvider {
- @Inject private Activity activity;
- @Inject private AccountManager accountManager;
+ @Inject protected AccountManager accountManager;
/**
- * This call blocks, so shouldn't be called on the UI thread
+ * This call blocks, so shouldn't be called on the UI thread.
+ * This call is what makes the login screen pop up. If the user has
+ * not logged in there will no accounts in the {@link android.accounts.AccountManager}
+ * and therefore the Activity that is referenced in the
+ * {@link com.donnfelker.android.bootstrap.authenticator.BootstrapAccountAuthenticator} will get started.
+ * If you want to remove the authentication then you can comment out the code below and return a string such as
+ * "foo" and the authentication process will not be kicked off. Alternatively, you can remove this class
+ * completely and clean up any references to the authenticator.
+ *
*
- * @return API key to be used for authorization with a {@link com.donnfelker.android.bootstrap.core.BootstrapService} instance
+ * @return API key to be used for authorization with a
+ * {@link com.donnfelker.android.bootstrap.core.BootstrapService} instance
* @throws AccountsException
* @throws IOException
*/
- public String getAuthKey() throws AccountsException, IOException {
- AccountManagerFuture accountManagerFuture = accountManager.getAuthTokenByFeatures(Constants.Auth.BOOTSTRAP_ACCOUNT_TYPE,
- Constants.Auth.AUTHTOKEN_TYPE, new String[0], activity, null, null, null, null);
+ public String getAuthKey(final Activity activity) throws AccountsException, IOException {
+ final AccountManagerFuture accountManagerFuture
+ = accountManager.getAuthTokenByFeatures(BOOTSTRAP_ACCOUNT_TYPE,
+ AUTHTOKEN_TYPE, new String[0], activity, null, null, null, null);
return accountManagerFuture.getResult().getString(KEY_AUTHTOKEN);
}
diff --git a/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/BootstrapAccountAuthenticator.java b/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/BootstrapAccountAuthenticator.java
index 1913d2b..81e9d18 100644
--- a/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/BootstrapAccountAuthenticator.java
+++ b/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/BootstrapAccountAuthenticator.java
@@ -1,13 +1,6 @@
package com.donnfelker.android.bootstrap.authenticator;
-import static android.accounts.AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE;
-import static android.accounts.AccountManager.KEY_ACCOUNT_NAME;
-import static android.accounts.AccountManager.KEY_ACCOUNT_TYPE;
-import static android.accounts.AccountManager.KEY_AUTHTOKEN;
-import static android.accounts.AccountManager.KEY_BOOLEAN_RESULT;
-import static android.accounts.AccountManager.KEY_INTENT;
-import static com.donnfelker.android.bootstrap.authenticator.BootstrapAuthenticatorActivity.PARAM_AUTHTOKEN_TYPE;
import android.accounts.AbstractAccountAuthenticator;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorResponse;
@@ -16,9 +9,17 @@
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.util.Log;
import com.donnfelker.android.bootstrap.core.Constants;
+import com.donnfelker.android.bootstrap.util.Ln;
+
+import static android.accounts.AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE;
+import static android.accounts.AccountManager.KEY_ACCOUNT_NAME;
+import static android.accounts.AccountManager.KEY_ACCOUNT_TYPE;
+import static android.accounts.AccountManager.KEY_AUTHTOKEN;
+import static android.accounts.AccountManager.KEY_BOOLEAN_RESULT;
+import static android.accounts.AccountManager.KEY_INTENT;
+import static com.donnfelker.android.bootstrap.authenticator.BootstrapAuthenticatorActivity.PARAM_AUTHTOKEN_TYPE;
class BootstrapAccountAuthenticator extends AbstractAccountAuthenticator {
@@ -26,42 +27,49 @@ class BootstrapAccountAuthenticator extends AbstractAccountAuthenticator {
private final Context context;
- public BootstrapAccountAuthenticator(Context context) {
+ public BootstrapAccountAuthenticator(final Context context) {
super(context);
this.context = context;
}
/*
- * The user has requested to add a new account to the system. We return an intent that will launch our login screen
- * if the user has not logged in yet, otherwise our activity will just pass the user's credentials on to the account
- * manager.
+ * The user has requested to add a new account to the system. We return an intent that will
+ * launch our login screen if the user has not logged in yet, otherwise our activity will
+ * just pass the user's credentials on to the account manager.
*/
@Override
- public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType,
- String[] requiredFeatures, Bundle options) throws NetworkErrorException {
+ public Bundle addAccount(final AccountAuthenticatorResponse response, final String accountType,
+ final String authTokenType, final String[] requiredFeatures,
+ final Bundle options) throws NetworkErrorException {
final Intent intent = new Intent(context, BootstrapAuthenticatorActivity.class);
intent.putExtra(PARAM_AUTHTOKEN_TYPE, authTokenType);
intent.putExtra(KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
+
final Bundle bundle = new Bundle();
bundle.putParcelable(KEY_INTENT, intent);
+
return bundle;
}
@Override
- public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) {
+ public Bundle confirmCredentials(final AccountAuthenticatorResponse response,
+ final Account account, final Bundle options) {
return null;
}
@Override
- public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
+ public Bundle editProperties(final AccountAuthenticatorResponse response,
+ final String accountType) {
return null;
}
/**
* This method gets called when the
- * {@link com.donnfelker.android.bootstrap.authenticator.ApiKeyProvider#getAuthKey()} methods gets invoked.
+ * {@link com.donnfelker.android.bootstrap.authenticator.ApiKeyProvider#getAuthKey()}
+ * methods gets invoked.
* This happens on a different process, so debugging it can be a beast.
+ *
* @param response
* @param account
* @param authTokenType
@@ -70,35 +78,39 @@ public Bundle editProperties(AccountAuthenticatorResponse response, String accou
* @throws NetworkErrorException
*/
@Override
- public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType,
- Bundle options) throws NetworkErrorException {
+ public Bundle getAuthToken(final AccountAuthenticatorResponse response,
+ final Account account, final String authTokenType,
+ final Bundle options) throws NetworkErrorException {
+
+ Ln.d("Attempting to get authToken");
- Log.d("AccountAuthenticator", "Attempting to get authToken");
+ final String authToken = AccountManager.get(context).peekAuthToken(account, authTokenType);
- String authToken = AccountManager.get(context).peekAuthToken(account, authTokenType);
- Bundle bundle = new Bundle();
+ final Bundle bundle = new Bundle();
bundle.putString(KEY_ACCOUNT_NAME, account.name);
bundle.putString(KEY_ACCOUNT_TYPE, Constants.Auth.BOOTSTRAP_ACCOUNT_TYPE);
bundle.putString(KEY_AUTHTOKEN, authToken);
+
return bundle;
}
@Override
- public String getAuthTokenLabel(String authTokenType) {
+ public String getAuthTokenLabel(final String authTokenType) {
return authTokenType.equals(Constants.Auth.AUTHTOKEN_TYPE) ? authTokenType : null;
}
@Override
- public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features)
- throws NetworkErrorException {
+ public Bundle hasFeatures(final AccountAuthenticatorResponse response, final Account account,
+ final String[] features) throws NetworkErrorException {
final Bundle result = new Bundle();
result.putBoolean(KEY_BOOLEAN_RESULT, false);
return result;
}
@Override
- public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType,
- Bundle options) {
+ public Bundle updateCredentials(final AccountAuthenticatorResponse response,
+ final Account account, final String authTokenType,
+ final Bundle options) {
return null;
}
}
diff --git a/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/BootstrapAuthenticatorActivity.java b/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/BootstrapAuthenticatorActivity.java
index 84d5627..930b146 100644
--- a/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/BootstrapAuthenticatorActivity.java
+++ b/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/BootstrapAuthenticatorActivity.java
@@ -1,21 +1,5 @@
-
package com.donnfelker.android.bootstrap.authenticator;
-import static android.R.layout.simple_dropdown_item_1line;
-import static android.accounts.AccountManager.KEY_ACCOUNT_NAME;
-import static android.accounts.AccountManager.KEY_ACCOUNT_TYPE;
-import static android.accounts.AccountManager.KEY_AUTHTOKEN;
-import static android.accounts.AccountManager.KEY_BOOLEAN_RESULT;
-import static android.view.KeyEvent.ACTION_DOWN;
-import static android.view.KeyEvent.KEYCODE_ENTER;
-import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
-import static com.donnfelker.android.bootstrap.core.Constants.Http.HEADER_PARSE_APP_ID;
-import static com.donnfelker.android.bootstrap.core.Constants.Http.HEADER_PARSE_REST_API_KEY;
-import static com.donnfelker.android.bootstrap.core.Constants.Http.PARSE_APP_ID;
-import static com.donnfelker.android.bootstrap.core.Constants.Http.PARSE_REST_API_KEY;
-import static com.donnfelker.android.bootstrap.core.Constants.Http.URL_AUTH;
-import static com.github.kevinsawicki.http.HttpRequest.get;
-import static com.github.kevinsawicki.http.HttpRequest.post;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Dialog;
@@ -27,7 +11,6 @@
import android.text.Html;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
-import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnKeyListener;
@@ -38,39 +21,49 @@
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
-import com.donnfelker.android.bootstrap.core.Constants;
-import com.donnfelker.android.bootstrap.core.User;
-import com.github.kevinsawicki.http.HttpRequest;
-import com.github.kevinsawicki.wishlist.Toaster;
import com.donnfelker.android.bootstrap.R.id;
import com.donnfelker.android.bootstrap.R.layout;
import com.donnfelker.android.bootstrap.R.string;
+import com.donnfelker.android.bootstrap.core.Constants;
+import com.donnfelker.android.bootstrap.core.User;
import com.donnfelker.android.bootstrap.ui.TextWatcherAdapter;
-import com.github.rtyley.android.sherlock.roboguice.activity.RoboSherlockAccountAuthenticatorActivity;
+import com.donnfelker.android.bootstrap.util.Ln;
+import com.donnfelker.android.bootstrap.util.SafeAsyncTask;
+import com.donnfelker.android.bootstrap.util.Strings;
+import com.github.kevinsawicki.http.HttpRequest;
+import com.github.kevinsawicki.wishlist.Toaster;
import com.google.gson.Gson;
-import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
-import roboguice.inject.InjectView;
-import roboguice.util.Ln;
-import roboguice.util.RoboAsyncTask;
-import roboguice.util.Strings;
+import butterknife.InjectView;
+import butterknife.Views;
-import static com.donnfelker.android.bootstrap.core.Constants.Http.USERNAME;
-import static com.donnfelker.android.bootstrap.core.Constants.Http.PASSWORD;
+import static android.R.layout.simple_dropdown_item_1line;
+import static android.accounts.AccountManager.KEY_ACCOUNT_NAME;
+import static android.accounts.AccountManager.KEY_ACCOUNT_TYPE;
+import static android.accounts.AccountManager.KEY_AUTHTOKEN;
+import static android.accounts.AccountManager.KEY_BOOLEAN_RESULT;
+import static android.view.KeyEvent.ACTION_DOWN;
+import static android.view.KeyEvent.KEYCODE_ENTER;
+import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
+import static com.donnfelker.android.bootstrap.core.Constants.Http.HEADER_PARSE_APP_ID;
+import static com.donnfelker.android.bootstrap.core.Constants.Http.HEADER_PARSE_REST_API_KEY;
+import static com.donnfelker.android.bootstrap.core.Constants.Http.PARSE_APP_ID;
+import static com.donnfelker.android.bootstrap.core.Constants.Http.PARSE_REST_API_KEY;
+import static com.donnfelker.android.bootstrap.core.Constants.Http.URL_AUTH;
+import static com.github.kevinsawicki.http.HttpRequest.get;
/**
* Activity to authenticate the user against an API (example API on Parse.com)
*/
-public class BootstrapAuthenticatorActivity extends
- RoboSherlockAccountAuthenticatorActivity {
+public class BootstrapAuthenticatorActivity extends ActionBarAccountAuthenticatorActivity {
/**
- * PARAM_CONFIRMCREDENTIALS
+ * PARAM_CONFIRM_CREDENTIALS
*/
- public static final String PARAM_CONFIRMCREDENTIALS = "confirmCredentials";
+ public static final String PARAM_CONFIRM_CREDENTIALS = "confirmCredentials";
/**
* PARAM_PASSWORD
@@ -90,18 +83,13 @@ public class BootstrapAuthenticatorActivity extends
private AccountManager accountManager;
- @InjectView(id.et_email)
- private AutoCompleteTextView emailText;
-
- @InjectView(id.et_password)
- private EditText passwordText;
+ @InjectView(id.et_email) protected AutoCompleteTextView emailText;
+ @InjectView(id.et_password) protected EditText passwordText;
+ @InjectView(id.b_signin) protected Button signInButton;
- @InjectView(id.b_signin)
- private Button signinButton;
+ private final TextWatcher watcher = validationTextWatcher();
- private TextWatcher watcher = validationTextWatcher();
-
- private RoboAsyncTask authenticationTask;
+ private SafeAsyncTask authenticationTask;
private String authToken;
private String authTokenType;
@@ -133,24 +121,27 @@ public void onCreate(Bundle bundle) {
super.onCreate(bundle);
accountManager = AccountManager.get(this);
+
final Intent intent = getIntent();
email = intent.getStringExtra(PARAM_USERNAME);
authTokenType = intent.getStringExtra(PARAM_AUTHTOKEN_TYPE);
+ confirmCredentials = intent.getBooleanExtra(PARAM_CONFIRM_CREDENTIALS, false);
+
requestNewAccount = email == null;
- confirmCredentials = intent.getBooleanExtra(PARAM_CONFIRMCREDENTIALS,
- false);
setContentView(layout.login_activity);
+ Views.inject(this);
+
emailText.setAdapter(new ArrayAdapter(this,
simple_dropdown_item_1line, userEmailAccounts()));
passwordText.setOnKeyListener(new OnKeyListener() {
- public boolean onKey(View v, int keyCode, KeyEvent event) {
+ public boolean onKey(final View v, final int keyCode, final KeyEvent event) {
if (event != null && ACTION_DOWN == event.getAction()
- && keyCode == KEYCODE_ENTER && signinButton.isEnabled()) {
- handleLogin(signinButton);
+ && keyCode == KEYCODE_ENTER && signInButton.isEnabled()) {
+ handleLogin(signInButton);
return true;
}
return false;
@@ -159,10 +150,10 @@ public boolean onKey(View v, int keyCode, KeyEvent event) {
passwordText.setOnEditorActionListener(new OnEditorActionListener() {
- public boolean onEditorAction(TextView v, int actionId,
- KeyEvent event) {
- if (actionId == IME_ACTION_DONE && signinButton.isEnabled()) {
- handleLogin(signinButton);
+ public boolean onEditorAction(final TextView v, final int actionId,
+ final KeyEvent event) {
+ if (actionId == IME_ACTION_DONE && signInButton.isEnabled()) {
+ handleLogin(signInButton);
return true;
}
return false;
@@ -172,22 +163,23 @@ public boolean onEditorAction(TextView v, int actionId,
emailText.addTextChangedListener(watcher);
passwordText.addTextChangedListener(watcher);
- TextView signupText = (TextView) findViewById(id.tv_signup);
- signupText.setMovementMethod(LinkMovementMethod.getInstance());
- signupText.setText(Html.fromHtml(getString(string.signup_link)));
+ final TextView signUpText = (TextView) findViewById(id.tv_signup);
+ signUpText.setMovementMethod(LinkMovementMethod.getInstance());
+ signUpText.setText(Html.fromHtml(getString(string.signup_link)));
}
private List userEmailAccounts() {
- Account[] accounts = accountManager.getAccountsByType("com.google");
- List emailAddresses = new ArrayList(accounts.length);
- for (Account account : accounts)
+ final Account[] accounts = accountManager.getAccountsByType("com.google");
+ final List emailAddresses = new ArrayList(accounts.length);
+ for (final Account account : accounts) {
emailAddresses.add(account.name);
+ }
return emailAddresses;
}
private TextWatcher validationTextWatcher() {
return new TextWatcherAdapter() {
- public void afterTextChanged(Editable gitDirEditText) {
+ public void afterTextChanged(final Editable gitDirEditText) {
updateUIWithValidation();
}
@@ -201,11 +193,11 @@ protected void onResume() {
}
private void updateUIWithValidation() {
- boolean populated = populated(emailText) && populated(passwordText);
- signinButton.setEnabled(populated);
+ final boolean populated = populated(emailText) && populated(passwordText);
+ signInButton.setEnabled(populated);
}
- private boolean populated(EditText editText) {
+ private boolean populated(final EditText editText) {
return editText.length() > 0;
}
@@ -216,9 +208,10 @@ protected Dialog onCreateDialog(int id) {
dialog.setIndeterminate(true);
dialog.setCancelable(true);
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- if (authenticationTask != null)
+ public void onCancel(final DialogInterface dialog) {
+ if (authenticationTask != null) {
authenticationTask.cancel(true);
+ }
}
});
return dialog;
@@ -232,29 +225,36 @@ public void onCancel(DialogInterface dialog) {
*
* @param view
*/
- public void handleLogin(View view) {
- if (authenticationTask != null)
+ public void handleLogin(final View view) {
+ if (authenticationTask != null) {
return;
+ }
- if (requestNewAccount)
+ if (requestNewAccount) {
email = emailText.getText().toString();
+ }
+
password = passwordText.getText().toString();
showProgress();
- authenticationTask = new RoboAsyncTask(this) {
+ authenticationTask = new SafeAsyncTask() {
public Boolean call() throws Exception {
- final String query = String.format("%s=%s&%s=%s", PARAM_USERNAME, email, PARAM_PASSWORD, password);
+ final String query = String.format("%s=%s&%s=%s",
+ PARAM_USERNAME, email, PARAM_PASSWORD, password);
- HttpRequest request = get(URL_AUTH + "?" + query)
+ final HttpRequest request = get(URL_AUTH + "?" + query)
.header(HEADER_PARSE_APP_ID, PARSE_APP_ID)
.header(HEADER_PARSE_REST_API_KEY, PARSE_REST_API_KEY);
- Log.d("Auth", "response=" + request.code());
+ Ln.d("Authentication response=%s", request.code());
- if(request.ok()) {
- final User model = new Gson().fromJson(Strings.toString(request.buffer()), User.class);
+ if (request.ok()) {
+ final User model = new Gson().fromJson(
+ Strings.toString(request.buffer()),
+ User.class
+ );
token = model.getSessionToken();
}
@@ -262,23 +262,24 @@ public Boolean call() throws Exception {
}
@Override
- protected void onException(Exception e) throws RuntimeException {
- Throwable cause = e.getCause() != null ? e.getCause() : e;
+ protected void onException(final Exception e) throws RuntimeException {
+ final Throwable cause = e.getCause() != null ? e.getCause() : e;
- String message;
+ final String message;
// A 404 is returned as an Exception with this message
if ("Received authentication challenge is null".equals(cause
- .getMessage()))
+ .getMessage())) {
message = getResources().getString(
string.message_bad_credentials);
- else
+ } else {
message = cause.getMessage();
+ }
Toaster.showLong(BootstrapAuthenticatorActivity.this, message);
}
@Override
- public void onSuccess(Boolean authSuccess) {
+ public void onSuccess(final Boolean authSuccess) {
onAuthenticationResult(authSuccess);
}
@@ -298,7 +299,7 @@ protected void onFinally() throws RuntimeException {
*
* @param result
*/
- protected void finishConfirmCredentials(boolean result) {
+ protected void finishConfirmCredentials(final boolean result) {
final Account account = new Account(email, Constants.Auth.BOOTSTRAP_ACCOUNT_TYPE);
accountManager.setPassword(account, password);
@@ -319,17 +320,24 @@ protected void finishConfirmCredentials(boolean result) {
protected void finishLogin() {
final Account account = new Account(email, Constants.Auth.BOOTSTRAP_ACCOUNT_TYPE);
- if (requestNewAccount)
+ if (requestNewAccount) {
accountManager.addAccountExplicitly(account, password, null);
- else
+ } else {
accountManager.setPassword(account, password);
- final Intent intent = new Intent();
+ }
+
+
authToken = token;
+
+ final Intent intent = new Intent();
intent.putExtra(KEY_ACCOUNT_NAME, email);
intent.putExtra(KEY_ACCOUNT_TYPE, Constants.Auth.BOOTSTRAP_ACCOUNT_TYPE);
+
if (authTokenType != null
- && authTokenType.equals(Constants.Auth.AUTHTOKEN_TYPE))
+ && authTokenType.equals(Constants.Auth.AUTHTOKEN_TYPE)) {
intent.putExtra(KEY_AUTHTOKEN, authToken);
+ }
+
setAccountAuthenticatorResult(intent.getExtras());
setResult(RESULT_OK, intent);
finish();
@@ -356,20 +364,22 @@ protected void showProgress() {
*
* @param result
*/
- public void onAuthenticationResult(boolean result) {
- if (result)
- if (!confirmCredentials)
+ public void onAuthenticationResult(final boolean result) {
+ if (result) {
+ if (!confirmCredentials) {
finishLogin();
- else
+ } else {
finishConfirmCredentials(true);
- else {
+ }
+ } else {
Ln.d("onAuthenticationResult: failed to authenticate");
- if (requestNewAccount)
+ if (requestNewAccount) {
Toaster.showLong(BootstrapAuthenticatorActivity.this,
string.message_auth_failed_new_account);
- else
+ } else {
Toaster.showLong(BootstrapAuthenticatorActivity.this,
string.message_auth_failed);
+ }
}
}
}
diff --git a/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/LogoutService.java b/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/LogoutService.java
index 871a018..603dd97 100644
--- a/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/LogoutService.java
+++ b/app/src/main/java/com/donnfelker/android/bootstrap/authenticator/LogoutService.java
@@ -4,70 +4,76 @@
import android.accounts.AccountManager;
import android.accounts.AccountManagerFuture;
import android.content.Context;
-import android.util.Log;
import com.donnfelker.android.bootstrap.core.Constants;
-import com.google.inject.Inject;
+import com.donnfelker.android.bootstrap.util.Ln;
+import com.donnfelker.android.bootstrap.util.SafeAsyncTask;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executor;
+import javax.inject.Inject;
-import roboguice.inject.ContextSingleton;
-import roboguice.util.RoboAsyncTask;
-@ContextSingleton
+/**
+ * Class used for logging a user out.
+ */
public class LogoutService {
- @Inject protected Context context;
- @Inject protected AccountManager accountManager;
-
+ protected final Context context;
+ protected final AccountManager accountManager;
+ @Inject
+ public LogoutService(final Context context, final AccountManager accountManager) {
+ this.context = context;
+ this.accountManager = accountManager;
+ }
public void logout(final Runnable onSuccess) {
-
new LogoutTask(context, onSuccess).execute();
}
- private static class LogoutTask extends RoboAsyncTask {
+ private static class LogoutTask extends SafeAsyncTask {
- private Runnable onSuccess;
+ private final Context taskContext;
+ private final Runnable onSuccess;
- protected LogoutTask(Context context, Runnable onSuccess) {
- super(context);
+ protected LogoutTask(final Context context, final Runnable onSuccess) {
+ this.taskContext = context;
this.onSuccess = onSuccess;
}
@Override
public Boolean call() throws Exception {
- final Account[] accounts = AccountManager.get(context).getAccountsByType(Constants.Auth.BOOTSTRAP_ACCOUNT_TYPE);
- if(accounts.length > 0) {
- AccountManagerFuture removeAccountFuture = AccountManager.get(context).removeAccount
- (accounts[0], null, null);
- if(removeAccountFuture.getResult() == true) {
- return true;
- } else {
- return false;
+ final AccountManager accountManagerWithContext = AccountManager.get(taskContext);
+ if (accountManagerWithContext != null) {
+ final Account[] accounts = accountManagerWithContext
+ .getAccountsByType(Constants.Auth.BOOTSTRAP_ACCOUNT_TYPE);
+ if (accounts.length > 0) {
+ final AccountManagerFuture removeAccountFuture
+ = accountManagerWithContext.removeAccount(accounts[0], null, null);
+
+ return removeAccountFuture.getResult();
}
+ } else {
+ Ln.w("accountManagerWithContext is null");
}
return false;
}
@Override
- protected void onSuccess(Boolean accountWasRemoved) throws Exception {
+ protected void onSuccess(final Boolean accountWasRemoved) throws Exception {
super.onSuccess(accountWasRemoved);
- Log.d("LOGOUT_SERVICE", "Logout succeeded:" + accountWasRemoved);
+ Ln.d("Logout succeeded: %s", accountWasRemoved);
onSuccess.run();
}
@Override
- protected void onException(Exception e) throws RuntimeException {
+ protected void onException(final Exception e) throws RuntimeException {
super.onException(e);
- Log.e("LOGOUT_SERVICE", "Logout failed.", e.getCause());
- }
- };
+ Ln.e(e.getCause(), "Logout failed.");
+ }
+ }
}
diff --git a/app/src/main/java/com/donnfelker/android/bootstrap/core/AvatarLoader.java b/app/src/main/java/com/donnfelker/android/bootstrap/core/AvatarLoader.java
deleted file mode 100644
index 2d1a3b2..0000000
--- a/app/src/main/java/com/donnfelker/android/bootstrap/core/AvatarLoader.java
+++ /dev/null
@@ -1,408 +0,0 @@
-package com.donnfelker.android.bootstrap.core;
-
-import static android.graphics.Bitmap.CompressFormat.PNG;
-import static android.graphics.Bitmap.Config.ARGB_8888;
-import static android.view.View.VISIBLE;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-import android.util.Log;
-import android.widget.ImageView;
-
-import com.actionbarsherlock.app.ActionBar;
-import com.donnfelker.android.bootstrap.R;
-import com.github.kevinsawicki.http.HttpRequest;
-import com.google.inject.Inject;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.atomic.AtomicReference;
-
-import roboguice.util.RoboAsyncTask;
-
-/**
- * Avatar utilities
- */
-public class AvatarLoader {
-
- private static final String TAG = "AvatarLoader";
-
- private static final float CORNER_RADIUS_IN_DIP = 3;
-
- private static final int CACHE_SIZE = 75;
-
- private static abstract class FetchAvatarTask extends
- RoboAsyncTask {
-
- private static final Executor EXECUTOR = Executors
- .newFixedThreadPool(1);
-
- private FetchAvatarTask(Context context) {
- super(context, EXECUTOR);
- }
-
- @Override
- protected void onException(Exception e) throws RuntimeException {
- Log.d(TAG, "Avatar load failed", e);
- }
- }
-
- private final float cornerRadius;
-
- private final Map