7 package com.google.appinventor.components.runtime.util;
9 import android.accounts.Account;
10 import android.accounts.AccountManager;
11 import android.accounts.AccountManagerFuture;
12 import android.accounts.AuthenticatorException;
13 import android.accounts.OperationCanceledException;
14 import android.app.Activity;
15 import android.app.AlertDialog;
16 import android.content.Context;
17 import android.content.DialogInterface;
18 import android.content.DialogInterface.OnCancelListener;
19 import android.content.DialogInterface.OnClickListener;
20 import android.content.SharedPreferences;
21 import android.os.Bundle;
22 import android.text.Html;
23 import android.util.Log;
25 import java.io.IOException;
26 import java.util.concurrent.SynchronousQueue;
42 private static final String NO_ACCOUNT =
"";
43 private static final String LOG_TAG =
"AccountChooser";
44 private static final String ACCOUNT_PREFERENCE =
"account";
48 private static final String ACCOUNT_TYPE =
"com.google";
50 private AccountManager accountManager;
51 private String service;
52 private String preferencesKey;
53 private Activity activity;
54 private String chooseAccountPrompt;
56 public AccountChooser(Activity activity, String service, String title, String key) {
57 this.activity = activity;
58 this.service = service;
59 this.chooseAccountPrompt = title;
60 this.preferencesKey = key;
61 this.accountManager = AccountManager.get(activity);
68 Account[] accounts = accountManager.getAccountsByType(ACCOUNT_TYPE);
71 if (accounts.length == 1) {
72 persistAccountName(accounts[0].name);
78 if (accounts.length == 0) {
79 String accountName = createAccount();
80 if (accountName !=
null) {
81 persistAccountName(accountName);
82 return accountManager.getAccountsByType(ACCOUNT_TYPE)[0];
84 Log.i(LOG_TAG,
"User failed to create a valid account");
92 String accountName = getPersistedAccountName();
93 if (accountName !=
null && (account = chooseAccount(accountName, accounts)) !=
null) {
100 accountName = selectAccount(accounts);
101 if (accountName !=
null) {
102 persistAccountName(accountName);
103 return chooseAccount(accountName, accounts);
107 Log.i(LOG_TAG,
"User failed to choose an account");
111 private Account chooseAccount(String accountName, Account[] accounts) {
112 for (Account account : accounts) {
113 if (account.name.equals(accountName)) {
114 Log.i(LOG_TAG,
"chose account: " + accountName);
121 private String createAccount() {
122 AccountManagerFuture<Bundle> future;
123 Log.i(LOG_TAG,
"Adding auth token account ...");
124 future = accountManager.addAccount(ACCOUNT_TYPE, service,
null,
null, activity,
null,
null);
126 Bundle result = future.getResult();
127 String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
128 Log.i(LOG_TAG,
"created: " + accountName);
130 }
catch (OperationCanceledException e) {
132 }
catch (AuthenticatorException e) {
134 }
catch (IOException e) {
140 private String selectAccount(Account accounts[]) {
141 final SynchronousQueue<String> queue =
new SynchronousQueue<String>();
142 SelectAccount select =
new SelectAccount(accounts, queue);
144 Log.i(LOG_TAG,
"Select: waiting for user...");
145 String account =
null;
147 account = queue.take();
148 }
catch (InterruptedException e) {
151 Log.i(LOG_TAG,
"Selected: " + account);
152 return NO_ACCOUNT.equals(account) ? null : account;
155 private SharedPreferences getPreferences() {
156 return activity.getSharedPreferences(preferencesKey, Context.MODE_PRIVATE);
159 private String getPersistedAccountName() {
160 return getPreferences().getString(ACCOUNT_PREFERENCE,
null);
163 private void persistAccountName(String accountName) {
164 Log.i(LOG_TAG,
"persisting account: " + accountName);
165 getPreferences().edit().putString(ACCOUNT_PREFERENCE, accountName).commit();
169 getPreferences().edit().remove(ACCOUNT_PREFERENCE).commit();
177 class SelectAccount
extends Thread implements OnClickListener, OnCancelListener {
178 private String[] accountNames;
179 private SynchronousQueue<String> queue;
181 SelectAccount(Account[] accounts, SynchronousQueue<String> queue) {
183 accountNames =
new String[accounts.length];
184 for (
int i = 0; i < accounts.length; i++) {
185 accountNames[i] = accounts[i].name;
191 activity.runOnUiThread(
new Runnable() {
194 AlertDialog.Builder ab =
new AlertDialog.Builder(activity)
195 .setTitle(Html.fromHtml(chooseAccountPrompt))
196 .setOnCancelListener(SelectAccount.this)
197 .setSingleChoiceItems(accountNames, -1, SelectAccount.this);
199 Log.i(LOG_TAG,
"Dialog showing!");
205 public void onClick(DialogInterface dialog,
int button) {
208 String account = accountNames[button];
209 Log.i(LOG_TAG,
"Chose: " + account);
212 queue.put(NO_ACCOUNT);
214 }
catch (InterruptedException e) {
221 public void onCancel(DialogInterface dialog) {
222 Log.i(LOG_TAG,
"Chose: canceled");