blob: 8e09c3dfbb7cf8c6cee8e3d494582b81ba160185 [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* 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.android.development;
import android.app.Activity;
import android.app.Dialog;
import android.app.AlertDialog;
import android.content.*;
import android.content.pm.PackageManager;
import android.accounts.*;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.Handler;
import android.view.*;
import android.widget.*;
import android.widget.ArrayAdapter;
import android.util.Log;
import android.text.TextUtils;
import java.io.IOException;
public class AccountsTester extends Activity implements OnAccountsUpdateListener {
private static final String TAG = "AccountsTester";
private Spinner mAccountTypesSpinner;
private ListView mAccountsListView;
private ListView mAuthenticatorsListView;
private AccountManager mAccountManager;
private String mLongPressedAccount = null;
private static final String COM_GOOGLE = "com.google";
private AuthenticatorDescription[] mAuthenticatorDescs;
private static final int GET_AUTH_TOKEN_DIALOG_ID = 1;
private static final int UPDATE_CREDENTIALS_DIALOG_ID = 2;
private static final int INVALIDATE_AUTH_TOKEN_DIALOG_ID = 3;
private EditText mDesiredAuthTokenTypeEditText;
private EditText mDesiredFeaturesEditText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAccountManager = AccountManager.get(this);
setContentView(R.layout.accounts_tester);
ButtonClickListener buttonClickListener = new ButtonClickListener();
mAccountTypesSpinner = (Spinner) findViewById(R.id.accounts_tester_account_types_spinner);
mAccountsListView = (ListView) findViewById(R.id.accounts_tester_accounts_list);
mAuthenticatorsListView = (ListView) findViewById(R.id.accounts_tester_authenticators_list);
registerForContextMenu(mAccountsListView);
getAuthenticatorTypes();
findViewById(R.id.accounts_tester_get_all_accounts).setOnClickListener(buttonClickListener);
findViewById(R.id.accounts_tester_get_accounts_by_type).setOnClickListener(
buttonClickListener);
findViewById(R.id.accounts_tester_add_account).setOnClickListener(buttonClickListener);
findViewById(R.id.accounts_tester_edit_properties).setOnClickListener(buttonClickListener);
mDesiredAuthTokenTypeEditText =
(EditText) findViewById(R.id.accounts_tester_desired_authtokentype);
mDesiredFeaturesEditText = (EditText) findViewById(R.id.accounts_tester_desired_features);
}
private static class AuthenticatorsArrayAdapter extends ArrayAdapter<AuthenticatorDescription> {
protected LayoutInflater mInflater;
private static final int mResource = R.layout.authenticators_list_item;
public AuthenticatorsArrayAdapter(Context context, AuthenticatorDescription[] items) {
super(context, mResource, items);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
static class ViewHolder {
TextView label;
ImageView icon;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// A ViewHolder keeps references to children views to avoid unneccessary calls
// to findViewById() on each row.
ViewHolder holder;
// When convertView is not null, we can reuse it directly, there is no need
// to reinflate it. We only inflate a new View when the convertView supplied
// by ListView is null.
if (convertView == null) {
convertView = mInflater.inflate(R.layout.authenticators_list_item, null);
// Creates a ViewHolder and store references to the two children views
// we want to bind data to.
holder = new ViewHolder();
holder.label = (TextView) convertView.findViewById(
R.id.accounts_tester_authenticator_label);
holder.icon = (ImageView) convertView.findViewById(
R.id.accounts_tester_authenticator_icon);
convertView.setTag(holder);
} else {
// Get the ViewHolder back to get fast access to the TextView
// and the ImageView.
holder = (ViewHolder) convertView.getTag();
}
final AuthenticatorDescription desc = getItem(position);
final String packageName = desc.packageName;
try {
final Context authContext = getContext().createPackageContext(packageName, 0);
// Set text field
holder.label.setText(authContext.getString(desc.labelId));
// Set resource icon
holder.icon.setImageDrawable(authContext.getResources().getDrawable(desc.iconId));
} catch (PackageManager.NameNotFoundException e) {
Log.d(TAG, "error getting the Package Context for " + packageName, e);
}
return convertView;
}
}
private void getAuthenticatorTypes() {
mAuthenticatorDescs = mAccountManager.getAuthenticatorTypes();
String[] names = new String[mAuthenticatorDescs.length];
for (int i = 0; i < mAuthenticatorDescs.length; i++) {
Context authContext;
try {
authContext = createPackageContext(mAuthenticatorDescs[i].packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
continue;
}
names[i] = authContext.getString(mAuthenticatorDescs[i].labelId);
}
ArrayAdapter<String> adapter =
new ArrayAdapter<String>(AccountsTester.this,
android.R.layout.simple_spinner_item, names);
mAccountTypesSpinner.setAdapter(adapter);
mAuthenticatorsListView.setAdapter(new AuthenticatorsArrayAdapter(
AccountsTester.this, mAuthenticatorDescs));
}
public void onAccountsUpdated(Account[] accounts) {
Log.d(TAG, "onAccountsUpdated: \n " + TextUtils.join("\n ", accounts));
String[] accountNames = new String[accounts.length];
for (int i = 0; i < accounts.length; i++) {
accountNames[i] = accounts[i].name;
}
ArrayAdapter<String> adapter =
new ArrayAdapter<String>(AccountsTester.this,
android.R.layout.simple_list_item_1, accountNames);
mAccountsListView.setAdapter(adapter);
}
protected void onStart() {
super.onStart();
final Handler mainHandler = new Handler(getMainLooper());
mAccountManager.addOnAccountsUpdatedListener(this, mainHandler,
true /* updateImmediately */);
}
protected void onStop() {
super.onStop();
mAccountManager.removeOnAccountsUpdatedListener(this);
}
class ButtonClickListener implements View.OnClickListener {
public void onClick(View v) {
if (R.id.accounts_tester_get_all_accounts == v.getId()) {
onAccountsUpdated(mAccountManager.getAccounts());
} else if (R.id.accounts_tester_get_accounts_by_type == v.getId()) {
String type = getSelectedAuthenticator().type;
onAccountsUpdated(mAccountManager.getAccountsByType(type));
} else if (R.id.accounts_tester_add_account == v.getId()) {
AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> future) {
try {
Bundle bundle = future.getResult();
bundle.keySet();
Log.d(TAG, "account added: " + bundle);
} catch (OperationCanceledException e) {
Log.d(TAG, "addAccount was canceled");
} catch (IOException e) {
Log.d(TAG, "addAccount failed: " + e);
} catch (AuthenticatorException e) {
Log.d(TAG, "addAccount failed: " + e);
}
}
};
String authTokenType = mDesiredAuthTokenTypeEditText.getText().toString();
if (TextUtils.isEmpty(authTokenType)) {
authTokenType = null;
}
String featureString = mDesiredFeaturesEditText.getText().toString();
String[] requiredFeatures = TextUtils.split(featureString, " ");
if (requiredFeatures.length == 0) {
requiredFeatures = null;
}
mAccountManager.addAccount(getSelectedAuthenticator().type,
authTokenType, requiredFeatures, null /* options */,
AccountsTester.this, callback, null /* handler */);
} else if (R.id.accounts_tester_edit_properties == v.getId()) {
mAccountManager.editProperties(getSelectedAuthenticator().type,
AccountsTester.this, new EditPropertiesCallback(), null /* handler */);
} else {
// unknown button
}
}
private class EditPropertiesCallback implements AccountManagerCallback<Bundle> {
public void run(AccountManagerFuture<Bundle> future) {
try {
Bundle bundle = future.getResult();
bundle.keySet();
Log.d(TAG, "editProperties succeeded: " + bundle);
} catch (OperationCanceledException e) {
Log.d(TAG, "editProperties was canceled");
} catch (IOException e) {
Log.d(TAG, "editProperties failed: ", e);
} catch (AuthenticatorException e) {
Log.d(TAG, "editProperties failed: ", e);
}
}
}
}
private AuthenticatorDescription getSelectedAuthenticator() {
return mAuthenticatorDescs[mAccountTypesSpinner.getSelectedItemPosition()];
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo) {
menu.setHeaderTitle(R.string.accounts_tester_account_context_menu_title);
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.layout.account_list_context_menu, menu);
mLongPressedAccount = ((TextView)info.targetView).getText().toString();
}
@Override
public boolean onContextItemSelected(MenuItem item) {
if (item.getItemId() == R.id.accounts_tester_remove_account) {
final Account account = new Account(mLongPressedAccount, COM_GOOGLE);
mAccountManager.removeAccount(account, new AccountManagerCallback<Boolean>() {
public void run(AccountManagerFuture<Boolean> future) {
try {
Log.d(TAG, "removeAccount(" + account + ") = " + future.getResult());
} catch (OperationCanceledException e) {
} catch (IOException e) {
} catch (AuthenticatorException e) {
}
}
}, null /* handler */);
} else if (item.getItemId() == R.id.accounts_tester_get_auth_token) {
showDialog(GET_AUTH_TOKEN_DIALOG_ID);
} else if (item.getItemId() == R.id.accounts_tester_invalidate_auth_token) {
showDialog(INVALIDATE_AUTH_TOKEN_DIALOG_ID);
} else if (item.getItemId() == R.id.accounts_tester_update_credentials) {
showDialog(UPDATE_CREDENTIALS_DIALOG_ID);
} else if (item.getItemId() == R.id.accounts_tester_confirm_credentials) {
mAccountManager.confirmCredentials(new Account(mLongPressedAccount, COM_GOOGLE), null,
AccountsTester.this, new ConfirmCredentialsCallback(), null /* handler */);
}
return true;
}
@Override
protected Dialog onCreateDialog(final int id) {
if (id == GET_AUTH_TOKEN_DIALOG_ID || id == INVALIDATE_AUTH_TOKEN_DIALOG_ID
|| id == UPDATE_CREDENTIALS_DIALOG_ID) {
final View view = LayoutInflater.from(this).inflate(R.layout.get_auth_token_view, null);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setPositiveButton(R.string.accounts_tester_do_get_auth_token,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
EditText value = (EditText) view.findViewById(
R.id.accounts_tester_auth_token_type);
String authTokenType = value.getText().toString();
AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> future) {
try {
Bundle bundle = future.getResult();
bundle.keySet();
Log.d(TAG, "dialog " + id + " success: " + bundle);
} catch (OperationCanceledException e) {
Log.d(TAG, "dialog " + id + " canceled");
} catch (IOException e) {
Log.d(TAG, "dialog " + id + " failed: " + e);
} catch (AuthenticatorException e) {
Log.d(TAG, "dialog " + id + " failed: " + e);
}
}
};
final Account account = new Account(mLongPressedAccount,
COM_GOOGLE);
if (id == GET_AUTH_TOKEN_DIALOG_ID) {
mAccountManager.getAuthToken(account, authTokenType,
null /* loginOptions */, AccountsTester.this,
callback, null /* handler */);
} else if (id == INVALIDATE_AUTH_TOKEN_DIALOG_ID) {
mAccountManager.getAuthToken(account, authTokenType, false,
new GetAndInvalidateAuthTokenCallback(), null);
} else {
mAccountManager.updateCredentials(
account,
authTokenType, null /* loginOptions */,
AccountsTester.this, callback, null /* handler */);
}
}
});
builder.setView(view);
return builder.create();
}
return super.onCreateDialog(id);
}
AccountManagerCallback<Bundle> newAccountsCallback(String type, String[] features) {
return new GetAccountsCallback(type, features);
}
class GetAccountsCallback implements AccountManagerCallback<Bundle> {
final String[] mFeatures;
final String mAccountType;
public GetAccountsCallback(String type, String[] features) {
mFeatures = features;
mAccountType = type;
}
public void run(AccountManagerFuture<Bundle> future) {
Log.d(TAG, "GetAccountsCallback: type " + mAccountType
+ ", features "
+ (mFeatures == null ? "none" : TextUtils.join(",", mFeatures)));
try {
Bundle result = future.getResult();
Parcelable[] accounts = result.getParcelableArray(AccountManager.KEY_ACCOUNTS);
Log.d(TAG, "found " + accounts.length + " accounts");
for (Parcelable account : accounts) {
Log.d(TAG, " " + account);
}
} catch (OperationCanceledException e) {
Log.d(TAG, "failure", e);
} catch (IOException e) {
Log.d(TAG, "failure", e);
} catch (AuthenticatorException e) {
Log.d(TAG, "failure", e);
}
}
}
AccountManagerCallback<Bundle> newAuthTokensCallback(String type, String authTokenType, String[] features) {
return new GetAuthTokenCallback(type, authTokenType, features);
}
class GetAuthTokenCallback implements AccountManagerCallback<Bundle> {
final String[] mFeatures;
final String mAccountType;
final String mAuthTokenType;
public GetAuthTokenCallback(String type, String authTokenType, String[] features) {
mFeatures = features;
mAccountType = type;
mAuthTokenType = authTokenType;
}
public void run(AccountManagerFuture<Bundle> future) {
Log.d(TAG, "GetAuthTokenCallback: type " + mAccountType
+ ", features "
+ (mFeatures == null ? "none" : TextUtils.join(",", mFeatures)));
try {
Bundle result = future.getResult();
result.keySet();
Log.d(TAG, " result: " + result);
} catch (OperationCanceledException e) {
Log.d(TAG, "failure", e);
} catch (IOException e) {
Log.d(TAG, "failure", e);
} catch (AuthenticatorException e) {
Log.d(TAG, "failure", e);
}
}
}
private class GetAndInvalidateAuthTokenCallback implements AccountManagerCallback<Bundle> {
public void run(AccountManagerFuture<Bundle> future) {
try {
Bundle bundle = future.getResult();
String authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
mAccountManager.invalidateAuthToken(COM_GOOGLE, authToken);
} catch (OperationCanceledException e) {
Log.d(TAG, "invalidate: interrupted while getting authToken");
} catch (IOException e) {
Log.d(TAG, "invalidate: error getting authToken", e);
} catch (AuthenticatorException e) {
Log.d(TAG, "invalidate: error getting authToken", e);
}
}
}
private static class ConfirmCredentialsCallback implements AccountManagerCallback<Bundle> {
public void run(AccountManagerFuture<Bundle> future) {
try {
Bundle bundle = future.getResult();
bundle.keySet();
Log.d(TAG, "confirmCredentials success: " + bundle);
} catch (OperationCanceledException e) {
Log.d(TAG, "confirmCredentials canceled");
} catch (AuthenticatorException e) {
Log.d(TAG, "confirmCredentials failed: " + e);
} catch (IOException e) {
Log.d(TAG, "confirmCredentials failed: " + e);
}
}
}
}