| Index: remoting/android/java/src/org/chromium/chromoting/Chromoting.java
|
| diff --git a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
|
| index 04741a456fa69b26db7eb8566314de96abf209e5..9335f8ac3b6697410e71ed0a449074bec7608572 100644
|
| --- a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
|
| +++ b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
|
| @@ -10,11 +10,13 @@ import android.accounts.AccountManagerCallback;
|
| import android.accounts.AccountManagerFuture;
|
| import android.accounts.AuthenticatorException;
|
| import android.accounts.OperationCanceledException;
|
| +import android.app.ActionBar;
|
| import android.app.Activity;
|
| import android.app.ProgressDialog;
|
| import android.content.DialogInterface;
|
| import android.content.Intent;
|
| import android.content.SharedPreferences;
|
| +import android.content.res.Configuration;
|
| import android.os.Bundle;
|
| import android.util.Log;
|
| import android.view.Menu;
|
| @@ -34,7 +36,8 @@ import java.util.Arrays;
|
| * also requests and renews authentication tokens using the system account manager.
|
| */
|
| public class Chromoting extends Activity implements JniInterface.ConnectionListener,
|
| - AccountManagerCallback<Bundle>, HostListLoader.Callback {
|
| + AccountManagerCallback<Bundle>, ActionBar.OnNavigationListener,
|
| + HostListLoader.Callback {
|
| /** Only accounts of this type will be selectable for authentication. */
|
| private static final String ACCOUNT_TYPE = "com.google";
|
|
|
| @@ -45,6 +48,9 @@ public class Chromoting extends Activity implements JniInterface.ConnectionListe
|
| /** User's account details. */
|
| private Account mAccount;
|
|
|
| + /** List of accounts on the system. */
|
| + private Account[] mAccounts;
|
| +
|
| /** Account auth token. */
|
| private String mToken;
|
|
|
| @@ -57,9 +63,6 @@ public class Chromoting extends Activity implements JniInterface.ConnectionListe
|
| /** Refresh button. */
|
| private MenuItem mRefreshButton;
|
|
|
| - /** Account switcher. */
|
| - private MenuItem mAccountSwitcher;
|
| -
|
| /** Greeting at the top of the displayed list. */
|
| private TextView mGreeting;
|
|
|
| @@ -74,7 +77,7 @@ public class Chromoting extends Activity implements JniInterface.ConnectionListe
|
| * this flag is set and a fresh authentication token is fetched from the AccountsService, and
|
| * used to request the host list a second time.
|
| */
|
| - boolean mAlreadyTried;
|
| + boolean mTriedNewAuthToken;
|
|
|
| /**
|
| * Called when the activity is first created. Loads the native library and requests an
|
| @@ -85,7 +88,7 @@ public class Chromoting extends Activity implements JniInterface.ConnectionListe
|
| super.onCreate(savedInstanceState);
|
| setContentView(R.layout.main);
|
|
|
| - mAlreadyTried = false;
|
| + mTriedNewAuthToken = false;
|
| mHostListLoader = new HostListLoader();
|
|
|
| // Get ahold of our view widgets.
|
| @@ -95,21 +98,40 @@ public class Chromoting extends Activity implements JniInterface.ConnectionListe
|
| // Bring native components online.
|
| JniInterface.loadLibrary(this);
|
|
|
| + mAccounts = AccountManager.get(this).getAccountsByType(ACCOUNT_TYPE);
|
| + if (mAccounts.length == 0) {
|
| + // TODO(lambroslambrou): Show a dialog with message: "To use <App Name>, you'll need
|
| + // to add a Google Account to your device." and two buttons: "Close", "Add account".
|
| + // The "Add account" button should navigate to the system "Add a Google Account"
|
| + // screen.
|
| + return;
|
| + }
|
| +
|
| SharedPreferences prefs = getPreferences(MODE_PRIVATE);
|
| + int index = -1;
|
| if (prefs.contains("account_name") && prefs.contains("account_type")) {
|
| - // Perform authentication using saved account selection.
|
| mAccount = new Account(prefs.getString("account_name", null),
|
| prefs.getString("account_type", null));
|
| - AccountManager.get(this).getAuthToken(mAccount, TOKEN_SCOPE, null, this, this, null);
|
| - if (mAccountSwitcher != null) {
|
| - mAccountSwitcher.setTitle(mAccount.name);
|
| - }
|
| + index = Arrays.asList(mAccounts).indexOf(mAccount);
|
| + }
|
| + if (index == -1) {
|
| + // Preference not loaded, or does not correspond to a valid account, so just pick the
|
| + // first account arbitrarily.
|
| + index = 0;
|
| + mAccount = mAccounts[0];
|
| + }
|
| +
|
| + if (mAccounts.length == 1) {
|
| + getActionBar().setDisplayShowTitleEnabled(true);
|
| + getActionBar().setSubtitle(mAccount.name);
|
| } else {
|
| - // Request auth callback once user has chosen an account.
|
| - Log.i("auth", "Requesting auth token from system");
|
| - AccountManager.get(this).getAuthTokenByFeatures(ACCOUNT_TYPE, TOKEN_SCOPE, null, this,
|
| - null, null, this, null);
|
| + AccountsAdapter adapter = new AccountsAdapter(this, mAccounts);
|
| + getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
|
| + getActionBar().setListNavigationCallbacks(adapter, this);
|
| + getActionBar().setSelectedNavigationItem(index);
|
| }
|
| +
|
| + refreshHostList();
|
| }
|
|
|
| /** Called when the activity is finally finished. */
|
| @@ -119,26 +141,28 @@ public class Chromoting extends Activity implements JniInterface.ConnectionListe
|
| JniInterface.disconnectFromHost();
|
| }
|
|
|
| + /** Called when the display is rotated (as registered in the manifest). */
|
| + @Override
|
| + public void onConfigurationChanged(Configuration newConfig) {
|
| + super.onConfigurationChanged(newConfig);
|
| +
|
| + // Reload the spinner resources, since the font sizes are dependent on the screen
|
| + // orientation.
|
| + if (mAccounts.length != 1) {
|
| + AccountsAdapter adapter = new AccountsAdapter(this, mAccounts);
|
| + getActionBar().setListNavigationCallbacks(adapter, this);
|
| + }
|
| + }
|
| +
|
| /** Called to initialize the action bar. */
|
| @Override
|
| public boolean onCreateOptionsMenu(Menu menu) {
|
| getMenuInflater().inflate(R.menu.chromoting_actionbar, menu);
|
| mRefreshButton = menu.findItem(R.id.actionbar_directoryrefresh);
|
| - mAccountSwitcher = menu.findItem(R.id.actionbar_accountswitcher);
|
| -
|
| - Account[] usableAccounts = AccountManager.get(this).getAccountsByType(ACCOUNT_TYPE);
|
| - if (usableAccounts.length == 1 && usableAccounts[0].equals(mAccount)) {
|
| - // If we're using the only available account, don't offer account switching.
|
| - // (If there are *no* accounts available, clicking this allows you to add a new one.)
|
| - mAccountSwitcher.setEnabled(false);
|
| - }
|
|
|
| if (mAccount == null) {
|
| - // If no account has been chosen, don't allow the user to refresh the listing.
|
| + // If there is no account, don't allow the user to refresh the listing.
|
| mRefreshButton.setEnabled(false);
|
| - } else {
|
| - // If the user has picked an account, show its name directly on the account switcher.
|
| - mAccountSwitcher.setTitle(mAccount.name);
|
| }
|
|
|
| return super.onCreateOptionsMenu(menu);
|
| @@ -147,16 +171,7 @@ public class Chromoting extends Activity implements JniInterface.ConnectionListe
|
| /** Called whenever an action bar button is pressed. */
|
| @Override
|
| public boolean onOptionsItemSelected(MenuItem item) {
|
| - mAlreadyTried = false;
|
| - if (item == mAccountSwitcher) {
|
| - // The account switcher triggers a listing of all available accounts.
|
| - AccountManager.get(this).getAuthTokenByFeatures(ACCOUNT_TYPE, TOKEN_SCOPE, null, this,
|
| - null, null, this, null);
|
| - } else {
|
| - // The refresh button simply makes use of the currently-chosen account.
|
| - AccountManager.get(this).getAuthToken(mAccount, TOKEN_SCOPE, null, this, this, null);
|
| - }
|
| -
|
| + refreshHostList();
|
| return true;
|
| }
|
|
|
| @@ -174,6 +189,13 @@ public class Chromoting extends Activity implements JniInterface.ConnectionListe
|
| this);
|
| }
|
|
|
| + private void refreshHostList() {
|
| + mTriedNewAuthToken = false;
|
| +
|
| + // The refresh button simply makes use of the currently-chosen account.
|
| + AccountManager.get(this).getAuthToken(mAccount, TOKEN_SCOPE, null, this, this, null);
|
| + }
|
| +
|
| @Override
|
| public void run(AccountManagerFuture<Bundle> future) {
|
| Log.i("auth", "User finished with auth dialogs");
|
| @@ -182,6 +204,12 @@ public class Chromoting extends Activity implements JniInterface.ConnectionListe
|
| try {
|
| // Here comes our auth token from the Android system.
|
| result = future.getResult();
|
| + String authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
|
| + Log.i("auth", "Received an auth token from system");
|
| +
|
| + mToken = authToken;
|
| +
|
| + mHostListLoader.retrieveHostList(authToken, this);
|
| } catch (OperationCanceledException ex) {
|
| explanation = getString(R.string.error_auth_canceled);
|
| } catch (AuthenticatorException ex) {
|
| @@ -195,20 +223,26 @@ public class Chromoting extends Activity implements JniInterface.ConnectionListe
|
| return;
|
| }
|
|
|
| - String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
|
| - String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
|
| String authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
|
| Log.i("auth", "Received an auth token from system");
|
|
|
| - mAccount = new Account(accountName, accountType);
|
| mToken = authToken;
|
| - getPreferences(MODE_PRIVATE).edit().putString("account_name", accountName).
|
| - putString("account_type", accountType).apply();
|
|
|
| mHostListLoader.retrieveHostList(authToken, this);
|
| }
|
|
|
| @Override
|
| + public boolean onNavigationItemSelected(int itemPosition, long itemId) {
|
| + mAccount = mAccounts[itemPosition];
|
| +
|
| + getPreferences(MODE_PRIVATE).edit().putString("account_name", mAccount.name).
|
| + putString("account_type", mAccount.type).apply();
|
| +
|
| + refreshHostList();
|
| + return true;
|
| + }
|
| +
|
| + @Override
|
| public void onHostListReceived(HostInfo[] hosts) {
|
| // Store a copy of the array, so that it can't be mutated by the HostListLoader. HostInfo
|
| // is an immutable type, so a shallow copy of the array is sufficient here.
|
| @@ -244,11 +278,11 @@ public class Chromoting extends Activity implements JniInterface.ConnectionListe
|
|
|
| // This is the AUTH_FAILED case.
|
|
|
| - if (!mAlreadyTried) {
|
| + if (!mTriedNewAuthToken) {
|
| // This was our first connection attempt.
|
|
|
| AccountManager authenticator = AccountManager.get(this);
|
| - mAlreadyTried = true;
|
| + mTriedNewAuthToken = true;
|
|
|
| Log.w("auth", "Requesting renewal of rejected auth token");
|
| authenticator.invalidateAuthToken(mAccount.type, mToken);
|
| @@ -270,9 +304,6 @@ public class Chromoting extends Activity implements JniInterface.ConnectionListe
|
| */
|
| private void updateUi() {
|
| mRefreshButton.setEnabled(mAccount != null);
|
| - if (mAccount != null) {
|
| - mAccountSwitcher.setTitle(mAccount.name);
|
| - }
|
|
|
| if (mHosts == null) {
|
| mGreeting.setText(getString(R.string.inst_empty_list));
|
|
|