diff options
Diffstat (limited to 'src/com/android')
-rw-r--r-- | src/com/android/settings/AccountPreference.java | 142 | ||||
-rw-r--r-- | src/com/android/settings/ManageAccountsSettings.java | 373 | ||||
-rw-r--r-- | src/com/android/settings/Settings.java | 2 | ||||
-rw-r--r-- | src/com/android/settings/Utils.java | 7 |
4 files changed, 519 insertions, 5 deletions
diff --git a/src/com/android/settings/AccountPreference.java b/src/com/android/settings/AccountPreference.java new file mode 100644 index 0000000..a860d1a --- /dev/null +++ b/src/com/android/settings/AccountPreference.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2008 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; + +import java.util.ArrayList; + +import android.accounts.Account; +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.preference.Preference; +import android.util.Log; +import android.view.View; +import android.widget.ImageView; + +/** + * AccountPreference is used to display a username, status and provider icon for an account on + * the device. + */ +public class AccountPreference extends Preference { + private static final String TAG = "AccountPreference"; + public static final int SYNC_ENABLED = 0; // all know sync adapters are enabled and OK + public static final int SYNC_DISABLED = 1; // no sync adapters are enabled + public static final int SYNC_ERROR = 2; // one or more sync adapters have a problem + private int mStatus; + private Account mAccount; + private ArrayList<String> mAuthorities; + private Drawable mProviderIcon; + private ImageView mSyncStatusIcon; + private ImageView mProviderIconView; + + public AccountPreference(Context context, Account account, Drawable icon, + ArrayList<String> authorities) { + super(context); + mAccount = account; + mAuthorities = authorities; + mProviderIcon = icon; + setLayoutResource(R.layout.account_preference); + setTitle(mAccount.name); + setSummary(""); + // Add account info to the intent for AccountSyncSettings + Intent intent = new Intent("android.settings.ACCOUNT_SYNC_SETTINGS"); + intent.putExtra("account", mAccount); + setIntent(intent); + setPersistent(false); + setSyncStatus(SYNC_DISABLED); + } + + public Account getAccount() { + return mAccount; + } + + public ArrayList<String> getAuthorities() { + return mAuthorities; + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + setSummary(getSyncStatusMessage(mStatus)); + mProviderIconView = (ImageView) view.findViewById(R.id.providerIcon); + mProviderIconView.setImageDrawable(mProviderIcon); + mSyncStatusIcon = (ImageView) view.findViewById(R.id.syncStatusIcon); + mSyncStatusIcon.setImageResource(getSyncStatusIcon(mStatus)); + } + + public void setProviderIcon(Drawable icon) { + mProviderIcon = icon; + if (mProviderIconView != null) { + mProviderIconView.setImageDrawable(icon); + } + } + + public void setSyncStatus(int status) { + mStatus = status; + if (mSyncStatusIcon != null) { + mSyncStatusIcon.setImageResource(getSyncStatusIcon(status)); + } + setSummary(getSyncStatusMessage(status)); + } + + private int getSyncStatusMessage(int status) { + int res; + switch (status) { + case SYNC_ENABLED: + res = R.string.sync_enabled; + break; + case SYNC_DISABLED: + res = R.string.sync_disabled; + break; + case SYNC_ERROR: + res = R.string.sync_error; + break; + default: + res = R.string.sync_error; + Log.e(TAG, "Unknown sync status: " + status); + } + return res; + } + + private int getSyncStatusIcon(int status) { + int res; + switch (status) { + case SYNC_ENABLED: + res = R.drawable.ic_sync_green; + break; + case SYNC_DISABLED: + res = R.drawable.ic_sync_grey; + break; + case SYNC_ERROR: + res = R.drawable.ic_sync_red; + break; + default: + res = R.drawable.ic_sync_red; + Log.e(TAG, "Unknown sync status: " + status); + } + return res; + } + + @Override + public int compareTo(Preference other) { + if (!(other instanceof AccountPreference)) { + // Put other preference types above us + return 1; + } + return mAccount.name.compareTo(((AccountPreference) other).mAccount.name); + } +} diff --git a/src/com/android/settings/ManageAccountsSettings.java b/src/com/android/settings/ManageAccountsSettings.java new file mode 100644 index 0000000..f138674 --- /dev/null +++ b/src/com/android/settings/ManageAccountsSettings.java @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2008 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; + +import com.google.android.collect.Maps; + +import com.android.settings.SettingsPreferenceFragment.SettingsDialogFragment; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.accounts.AuthenticatorDescription; +import android.accounts.OnAccountsUpdateListener; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.ContentResolver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SyncAdapterType; +import android.content.SyncInfo; +import android.content.SyncStatusInfo; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; +import android.net.ConnectivityManager; +import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.PreferenceFragment; +import android.preference.PreferenceScreen; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +public class ManageAccountsSettings extends PreferenceFragment + implements View.OnClickListener, OnAccountsUpdateListener, DialogCreatable { + private static final String TAG = ManageAccountsSettings.class.getSimpleName(); + + private static final String AUTHORITIES_FILTER_KEY = "authorities"; + private static final boolean LDEBUG = Log.isLoggable(TAG, Log.DEBUG); + + private static final String AUTO_SYNC_CHECKBOX_KEY = "syncAutomaticallyCheckBox"; + private static final String MANAGE_ACCOUNTS_CATEGORY_KEY = "manageAccountsCategory"; + private static final String BACKGROUND_DATA_CHECKBOX_KEY = "backgroundDataCheckBox"; + private static final int DIALOG_DISABLE_BACKGROUND_DATA = 1; + + private CheckBoxPreference mBackgroundDataCheckBox; + private PreferenceCategory mManageAccountsCategory; + private String[] mAuthorities; + private TextView mErrorInfoView; + private Button mAddAccountButton; + private CheckBoxPreference mAutoSyncCheckbox; + + private SettingsDialogFragment mDialogFragment; + + private AuthenticatorDescription[] mAuthDescs; + private Map<String, AuthenticatorDescription> mTypeToAuthDescription + = new HashMap<String, AuthenticatorDescription>(); + private HashMap<String, ArrayList<String>> mAccountTypeToAuthorities = null; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + final View view = inflater.inflate(R.layout.manage_accounts_screen, container, false); + return view; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + final Activity activity = getActivity(); + addPreferencesFromResource(R.xml.manage_accounts_settings); + final View view = getView(); + + mErrorInfoView = (TextView)view.findViewById(R.id.sync_settings_error_info); + mErrorInfoView.setVisibility(View.GONE); + mErrorInfoView.setCompoundDrawablesWithIntrinsicBounds( + activity.getResources().getDrawable(R.drawable.ic_list_syncerror), + null, null, null); + + mBackgroundDataCheckBox = (CheckBoxPreference) findPreference(BACKGROUND_DATA_CHECKBOX_KEY); + mAutoSyncCheckbox = (CheckBoxPreference) findPreference(AUTO_SYNC_CHECKBOX_KEY); + + mManageAccountsCategory = (PreferenceCategory)findPreference(MANAGE_ACCOUNTS_CATEGORY_KEY); + mAuthorities = activity.getIntent().getStringArrayExtra(AUTHORITIES_FILTER_KEY); + mAddAccountButton = (Button)view.findViewById(R.id.add_account_button); + mAddAccountButton.setOnClickListener(this); + + AccountManager.get(activity).addOnAccountsUpdatedListener(this, null, true); + updateAuthDescriptions(activity); + } + + @Override + public void onDestroy() { + AccountManager.get(getActivity()).removeOnAccountsUpdatedListener(this); + super.onDestroy(); + } + + @Override + public boolean onPreferenceTreeClick(PreferenceScreen preferences, Preference preference) { + if (preference == mBackgroundDataCheckBox) { + final ConnectivityManager connManager = (ConnectivityManager) + getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); + final boolean oldBackgroundDataSetting = connManager.getBackgroundDataSetting(); + final boolean backgroundDataSetting = mBackgroundDataCheckBox.isChecked(); + if (oldBackgroundDataSetting != backgroundDataSetting) { + if (backgroundDataSetting) { + setBackgroundDataInt(true); + onSyncStateUpdated(); + } else { + // This will get unchecked only if the user hits "Ok" + mBackgroundDataCheckBox.setChecked(true); + showDialog(DIALOG_DISABLE_BACKGROUND_DATA); + } + } + } else if (preference == mAutoSyncCheckbox) { + ContentResolver.setMasterSyncAutomatically(mAutoSyncCheckbox.isChecked()); + onSyncStateUpdated(); + } else { + return false; + } + return true; + } + + @Override + public Dialog onCreateDialog(int id) { + switch (id) { + case DIALOG_DISABLE_BACKGROUND_DATA: + final CheckBoxPreference pref = + (CheckBoxPreference) findPreference(BACKGROUND_DATA_CHECKBOX_KEY); + return new AlertDialog.Builder(getActivity()) + .setTitle(R.string.background_data_dialog_title) + .setIcon(android.R.drawable.ic_dialog_alert) + .setMessage(R.string.background_data_dialog_message) + .setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + setBackgroundDataInt(false); + pref.setChecked(false); + onSyncStateUpdated(); + } + }) + .setNegativeButton(android.R.string.cancel, null) + .create(); + } + + return null; + } + + void showDialog(int dialogId) { + if (mDialogFragment != null) { + Log.e(TAG, "Old dialog fragment not null!"); + } + mDialogFragment = new SettingsDialogFragment(this, dialogId); + mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId)); + } + + private void setBackgroundDataInt(boolean enabled) { + final ConnectivityManager connManager = (ConnectivityManager) + getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); + connManager.setBackgroundDataSetting(enabled); + } + + private void onSyncStateUpdated() { + // Set background connection state + final ConnectivityManager connManager = (ConnectivityManager) + getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); + final boolean backgroundDataSetting = connManager.getBackgroundDataSetting(); + mBackgroundDataCheckBox.setChecked(backgroundDataSetting); + boolean masterSyncAutomatically = ContentResolver.getMasterSyncAutomatically(); + mAutoSyncCheckbox.setChecked(masterSyncAutomatically); + + // iterate over all the preferences, setting the state properly for each + SyncInfo currentSync = ContentResolver.getCurrentSync(); + + boolean anySyncFailed = false; // true if sync on any account failed + + // only track userfacing sync adapters when deciding if account is synced or not + final SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypes(); + HashSet<String> userFacing = new HashSet<String>(); + for (int k = 0, n = syncAdapters.length; k < n; k++) { + final SyncAdapterType sa = syncAdapters[k]; + if (sa.isUserVisible()) { + userFacing.add(sa.authority); + } + } + for (int i = 0, count = mManageAccountsCategory.getPreferenceCount(); i < count; i++) { + Preference pref = mManageAccountsCategory.getPreference(i); + if (! (pref instanceof AccountPreference)) { + continue; + } + + AccountPreference accountPref = (AccountPreference) pref; + Account account = accountPref.getAccount(); + int syncCount = 0; + boolean syncIsFailing = false; + final ArrayList<String> authorities = accountPref.getAuthorities(); + if (authorities != null) { + for (String authority : authorities) { + SyncStatusInfo status = ContentResolver.getSyncStatus(account, authority); + boolean syncEnabled = ContentResolver.getSyncAutomatically(account, authority) + && masterSyncAutomatically + && backgroundDataSetting + && (ContentResolver.getIsSyncable(account, authority) > 0); + boolean authorityIsPending = ContentResolver.isSyncPending(account, authority); + boolean activelySyncing = currentSync != null + && currentSync.authority.equals(authority) + && new Account(currentSync.account.name, currentSync.account.type) + .equals(account); + boolean lastSyncFailed = status != null + && syncEnabled + && status.lastFailureTime != 0 + && status.getLastFailureMesgAsInt(0) + != ContentResolver.SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS; + if (lastSyncFailed && !activelySyncing && !authorityIsPending) { + syncIsFailing = true; + anySyncFailed = true; + } + syncCount += syncEnabled && userFacing.contains(authority) ? 1 : 0; + } + } else { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "no syncadapters found for " + account); + } + } + int syncStatus = AccountPreference.SYNC_DISABLED; + if (syncIsFailing) { + syncStatus = AccountPreference.SYNC_ERROR; + } else if (syncCount == 0) { + syncStatus = AccountPreference.SYNC_DISABLED; + } else if (syncCount > 0) { + syncStatus = AccountPreference.SYNC_ENABLED; + } + accountPref.setSyncStatus(syncStatus); + } + + mErrorInfoView.setVisibility(anySyncFailed ? View.VISIBLE : View.GONE); + } + + @Override + public void onAccountsUpdated(Account[] accounts) { + mManageAccountsCategory.removeAll(); + for (int i = 0, n = accounts.length; i < n; i++) { + final Account account = accounts[i]; + final ArrayList<String> auths = getAuthoritiesForAccountType(account.type); + + boolean showAccount = true; + if (mAuthorities != null && auths != null) { + showAccount = false; + for (String requestedAuthority : mAuthorities) { + if (auths.contains(requestedAuthority)) { + showAccount = true; + break; + } + } + } + + if (showAccount) { + final Drawable icon = getDrawableForType(account.type); + final AccountPreference preference = + new AccountPreference(getActivity(), account, icon, auths); + mManageAccountsCategory.addPreference(preference); + } + } + onSyncStateUpdated(); + } + + private void onAuthDescriptionsUpdated() { + // Update account icons for all account preference items + for (int i = 0; i < mManageAccountsCategory.getPreferenceCount(); i++) { + AccountPreference pref = (AccountPreference) mManageAccountsCategory.getPreference(i); + pref.setProviderIcon(getDrawableForType(pref.getAccount().type)); + pref.setSummary(getLabelForType(pref.getAccount().type)); + } + } + + public void onClick(View v) { + if (v == mAddAccountButton) { + Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS"); + intent.putExtra(AUTHORITIES_FILTER_KEY, mAuthorities); + startActivity(intent); + } + } + + /* The logic below is copied from AcountPrefernceBase */ + + private Drawable getDrawableForType(final String accountType) { + Drawable icon = null; + if (mTypeToAuthDescription.containsKey(accountType)) { + try { + AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType); + Context authContext = getActivity().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 for account type " + accountType); + } + } + return icon; + } + + private CharSequence getLabelForType(final String accountType) { + CharSequence label = null; + if (mTypeToAuthDescription.containsKey(accountType)) { + try { + AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType); + Context authContext = getActivity().createPackageContext(desc.packageName, 0); + label = authContext.getResources().getText(desc.labelId); + } catch (PackageManager.NameNotFoundException e) { + Log.w(TAG, "No label for account type " + ", type " + accountType); + } + } + return label; + } + + private 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 (LDEBUG) { + Log.d(TAG, "added authority " + sa.authority + " to accountType " + + sa.accountType); + } + authorities.add(sa.authority); + } + } + return mAccountTypeToAuthorities.get(type); + } + + private void updateAuthDescriptions(Context context) { + mAuthDescs = AccountManager.get(context).getAuthenticatorTypes(); + for (int i = 0; i < mAuthDescs.length; i++) { + mTypeToAuthDescription.put(mAuthDescs[i].type, mAuthDescs[i]); + } + onAuthDescriptionsUpdated(); + } +} diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index cc3f7ea..224aa53 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -235,8 +235,6 @@ public class Settings extends Activity private void updatePreferenceList() { final Activity activity = getActivity(); PreferenceGroup parent = (PreferenceGroup) findPreference(KEY_PARENT); - Utils.updatePreferenceToSpecificActivityOrRemove(activity, parent, - KEY_SYNC_SETTINGS, 0); Preference dockSettings = parent.findPreference(KEY_DOCK_SETTINGS); if (activity.getResources().getBoolean(R.bool.has_dock_settings) == false && dockSettings != null) { diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java index 694bc1f..4c43712 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -16,14 +16,12 @@ package com.android.settings; -import java.util.List; - import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; import android.graphics.drawable.Drawable; @@ -33,6 +31,9 @@ import android.preference.Preference; import android.preference.PreferenceGroup; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.util.Log; + +import java.util.List; public class Utils { |