summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/accounts/ChooseAccountActivity.java
diff options
context:
space:
mode:
authorFabrice Di Meglio <fdimeglio@google.com>2014-02-20 14:41:51 -0800
committerFabrice Di Meglio <fdimeglio@google.com>2014-02-20 16:21:14 -0800
commit74309ea53a5a72430bafaa8cea4d82d4e24f61bd (patch)
tree2b52da2b96af969339c4dc93dd7a93c6bb535581 /src/com/android/settings/accounts/ChooseAccountActivity.java
parente611b8590d8da69bb95e29a7faa5200a95b427f3 (diff)
downloadpackages_apps_Settings-74309ea53a5a72430bafaa8cea4d82d4e24f61bd.tar.gz
packages_apps_Settings-74309ea53a5a72430bafaa8cea4d82d4e24f61bd.tar.bz2
packages_apps_Settings-74309ea53a5a72430bafaa8cea4d82d4e24f61bd.zip
Fix bug #13058470 Cannot add account -- Settings app crashes
- revert back to an Activity instead of a fragment. This is a straight reverse of the changes introduced for trying to have a Fragment. Basically ChooseAccountActivity was previously an Activity for choosing an account type. If the list of account types was containing only one item, then the ChooseAccountActivity was just a pass thru and was falling back to the only account authority available. In the current reported bug, this was happening by disabling the Email app and thus having only the GoogleAuthenticator as an Authority. Then in the onCreate() the ChooseAccountFragment was seeing that there was only one account authenticator and issuing a BACK button press. Too bad, this was done into a non finished Fragment transaction and leading to a crash. All in all, we NEED to have an Activity and cannot use a Fragment in that case. Change-Id: I4a867a25fe9580929ec50a6775105adac1f88c52
Diffstat (limited to 'src/com/android/settings/accounts/ChooseAccountActivity.java')
-rw-r--r--src/com/android/settings/accounts/ChooseAccountActivity.java251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/com/android/settings/accounts/ChooseAccountActivity.java b/src/com/android/settings/accounts/ChooseAccountActivity.java
new file mode 100644
index 000000000..631fe47d6
--- /dev/null
+++ b/src/com/android/settings/accounts/ChooseAccountActivity.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2010 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.settings.accounts;
+
+import android.accounts.AccountManager;
+import android.accounts.AuthenticatorDescription;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SyncAdapterType;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceScreen;
+import android.util.Log;
+import com.android.internal.util.CharSequences;
+import com.android.settings.R;
+import com.google.android.collect.Maps;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+/**
+ * Activity asking a user to select an account to be set up.
+ */
+public class ChooseAccountActivity extends PreferenceActivity {
+
+ private static final String TAG = "ChooseAccountActivity";
+ private String[] mAuthorities;
+ private PreferenceGroup mAddAccountGroup;
+ private final ArrayList<ProviderEntry> mProviderList = new ArrayList<ProviderEntry>();
+ public HashSet<String> mAccountTypesFilter;
+ private AuthenticatorDescription[] mAuthDescs;
+ private HashMap<String, ArrayList<String>> mAccountTypeToAuthorities = null;
+ private Map<String, AuthenticatorDescription> mTypeToAuthDescription
+ = new HashMap<String, AuthenticatorDescription>();
+
+ private static class ProviderEntry implements Comparable<ProviderEntry> {
+ private final CharSequence name;
+ private final String type;
+ ProviderEntry(CharSequence providerName, String accountType) {
+ name = providerName;
+ type = accountType;
+ }
+
+ public int compareTo(ProviderEntry another) {
+ if (name == null) {
+ return -1;
+ }
+ if (another.name == null) {
+ return +1;
+ }
+ return CharSequences.compareToIgnoreCase(name, another.name);
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ setContentView(R.layout.add_account_screen);
+ addPreferencesFromResource(R.xml.add_account_settings);
+ mAuthorities = getIntent().getStringArrayExtra(
+ AccountPreferenceBase.AUTHORITIES_FILTER_KEY);
+ String[] accountTypesFilter = getIntent().getStringArrayExtra(
+ AccountPreferenceBase.ACCOUNT_TYPES_FILTER_KEY);
+ if (accountTypesFilter != null) {
+ mAccountTypesFilter = new HashSet<String>();
+ for (String accountType : accountTypesFilter) {
+ mAccountTypesFilter.add(accountType);
+ }
+ }
+ mAddAccountGroup = getPreferenceScreen();
+ updateAuthDescriptions();
+ }
+
+ /**
+ * Updates provider icons. Subclasses should call this in onCreate()
+ * and update any UI that depends on AuthenticatorDescriptions in onAuthDescriptionsUpdated().
+ */
+ private void updateAuthDescriptions() {
+ mAuthDescs = AccountManager.get(this).getAuthenticatorTypes();
+ for (int i = 0; i < mAuthDescs.length; i++) {
+ mTypeToAuthDescription.put(mAuthDescs[i].type, mAuthDescs[i]);
+ }
+ onAuthDescriptionsUpdated();
+ }
+
+ private void onAuthDescriptionsUpdated() {
+ // Create list of providers to show on preference screen
+ for (int i = 0; i < mAuthDescs.length; i++) {
+ String accountType = mAuthDescs[i].type;
+ CharSequence providerName = getLabelForType(accountType);
+
+ // Skip preferences for authorities not specified. If no authorities specified,
+ // then include them all.
+ ArrayList<String> accountAuths = getAuthoritiesForAccountType(accountType);
+ boolean addAccountPref = true;
+ if (mAuthorities != null && mAuthorities.length > 0 && accountAuths != null) {
+ addAccountPref = false;
+ for (int k = 0; k < mAuthorities.length; k++) {
+ if (accountAuths.contains(mAuthorities[k])) {
+ addAccountPref = true;
+ break;
+ }
+ }
+ }
+ if (addAccountPref && mAccountTypesFilter != null
+ && !mAccountTypesFilter.contains(accountType)) {
+ addAccountPref = false;
+ }
+ if (addAccountPref) {
+ mProviderList.add(new ProviderEntry(providerName, accountType));
+ } else {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Skipped pref " + providerName + ": has no authority we need");
+ }
+ }
+ }
+
+ if (mProviderList.size() == 1) {
+ // If there's only one provider that matches, just run it.
+ finishWithAccountType(mProviderList.get(0).type);
+ } else if (mProviderList.size() > 0) {
+ Collections.sort(mProviderList);
+ mAddAccountGroup.removeAll();
+ for (ProviderEntry pref : mProviderList) {
+ Drawable drawable = getDrawableForType(pref.type);
+ ProviderPreference p =
+ new ProviderPreference(this, pref.type, drawable, pref.name);
+ mAddAccountGroup.addPreference(p);
+ }
+ } else {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ final StringBuilder auths = new StringBuilder();
+ for (String a : mAuthorities) {
+ auths.append(a);
+ auths.append(' ');
+ }
+ Log.v(TAG, "No providers found for authorities: " + auths);
+ }
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+ }
+
+ public ArrayList<String> getAuthoritiesForAccountType(String type) {
+ if (mAccountTypeToAuthorities == null) {
+ mAccountTypeToAuthorities = Maps.newHashMap();
+ SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypes();
+ for (int i = 0, n = syncAdapters.length; i < n; i++) {
+ final SyncAdapterType sa = syncAdapters[i];
+ ArrayList<String> authorities = mAccountTypeToAuthorities.get(sa.accountType);
+ if (authorities == null) {
+ authorities = new ArrayList<String>();
+ mAccountTypeToAuthorities.put(sa.accountType, authorities);
+ }
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.d(TAG, "added authority " + sa.authority + " to accountType "
+ + sa.accountType);
+ }
+ authorities.add(sa.authority);
+ }
+ }
+ return mAccountTypeToAuthorities.get(type);
+ }
+
+ /**
+ * Gets an icon associated with a particular account type. If none found, return null.
+ * @param accountType the type of account
+ * @return a drawable for the icon or null if one cannot be found.
+ */
+ protected Drawable getDrawableForType(final String accountType) {
+ Drawable icon = null;
+ if (mTypeToAuthDescription.containsKey(accountType)) {
+ try {
+ AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
+ Context authContext = createPackageContext(desc.packageName, 0);
+ icon = authContext.getResources().getDrawable(desc.iconId);
+ } catch (PackageManager.NameNotFoundException e) {
+ // TODO: place holder icon for missing account icons?
+ Log.w(TAG, "No icon name for account type " + accountType);
+ } catch (Resources.NotFoundException e) {
+ // TODO: place holder icon for missing account icons?
+ Log.w(TAG, "No icon resource for account type " + accountType);
+ }
+ }
+ return icon;
+ }
+
+ /**
+ * Gets the label associated with a particular account type. If none found, return null.
+ * @param accountType the type of account
+ * @return a CharSequence for the label or null if one cannot be found.
+ */
+ protected CharSequence getLabelForType(final String accountType) {
+ CharSequence label = null;
+ if (mTypeToAuthDescription.containsKey(accountType)) {
+ try {
+ AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
+ Context authContext = createPackageContext(desc.packageName, 0);
+ label = authContext.getResources().getText(desc.labelId);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "No label name for account type " + accountType);
+ } catch (Resources.NotFoundException e) {
+ Log.w(TAG, "No label resource for account type " + accountType);
+ }
+ }
+ return label;
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(PreferenceScreen preferences, Preference preference) {
+ if (preference instanceof ProviderPreference) {
+ ProviderPreference pref = (ProviderPreference) preference;
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Attempting to add account of type " + pref.getAccountType());
+ }
+ finishWithAccountType(pref.getAccountType());
+ }
+ return true;
+ }
+
+ private void finishWithAccountType(String accountType) {
+ Intent intent = new Intent();
+ intent.putExtra(AddAccountSettings.EXTRA_SELECTED_ACCOUNT, accountType);
+ setResult(RESULT_OK, intent);
+ finish();
+ }
+}