diff options
26 files changed, 756 insertions, 6 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index a767cb4..caf1b18 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -830,6 +830,17 @@ </intent-filter> </activity> + <activity-alias + android:name="ManageAccountsSettings" + android:label="@string/sync_settings" + android:targetActivity="Settings"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <action android:name="android.settings.SYNC_SETTINGS" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + </activity-alias> + <receiver android:name=".widget.SettingsAppWidgetProvider" android:label="@string/gadget_title"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> diff --git a/res/drawable-hdpi/ic_list_sync_anim0.png b/res/drawable-hdpi/ic_list_sync_anim0.png Binary files differnew file mode 100755 index 0000000..dc78905 --- /dev/null +++ b/res/drawable-hdpi/ic_list_sync_anim0.png diff --git a/res/drawable-hdpi/ic_list_sync_anim1.png b/res/drawable-hdpi/ic_list_sync_anim1.png Binary files differnew file mode 100755 index 0000000..5fe6b4f --- /dev/null +++ b/res/drawable-hdpi/ic_list_sync_anim1.png diff --git a/res/drawable-hdpi/ic_list_sync_anim2.png b/res/drawable-hdpi/ic_list_sync_anim2.png Binary files differnew file mode 100755 index 0000000..d9d68ed --- /dev/null +++ b/res/drawable-hdpi/ic_list_sync_anim2.png diff --git a/res/drawable-hdpi/ic_list_sync_anim3.png b/res/drawable-hdpi/ic_list_sync_anim3.png Binary files differnew file mode 100755 index 0000000..7275c29 --- /dev/null +++ b/res/drawable-hdpi/ic_list_sync_anim3.png diff --git a/res/drawable-hdpi/ic_sync_green.png b/res/drawable-hdpi/ic_sync_green.png Binary files differnew file mode 100644 index 0000000..6956088 --- /dev/null +++ b/res/drawable-hdpi/ic_sync_green.png diff --git a/res/drawable-hdpi/ic_sync_grey.png b/res/drawable-hdpi/ic_sync_grey.png Binary files differnew file mode 100644 index 0000000..3e9995a --- /dev/null +++ b/res/drawable-hdpi/ic_sync_grey.png diff --git a/res/drawable-hdpi/ic_sync_red.png b/res/drawable-hdpi/ic_sync_red.png Binary files differnew file mode 100644 index 0000000..5abb707 --- /dev/null +++ b/res/drawable-hdpi/ic_sync_red.png diff --git a/res/drawable-mdpi/ic_list_sync_anim0.png b/res/drawable-mdpi/ic_list_sync_anim0.png Binary files differnew file mode 100644 index 0000000..981a72e --- /dev/null +++ b/res/drawable-mdpi/ic_list_sync_anim0.png diff --git a/res/drawable-mdpi/ic_list_sync_anim1.png b/res/drawable-mdpi/ic_list_sync_anim1.png Binary files differnew file mode 100644 index 0000000..4581ba2 --- /dev/null +++ b/res/drawable-mdpi/ic_list_sync_anim1.png diff --git a/res/drawable-mdpi/ic_list_sync_anim2.png b/res/drawable-mdpi/ic_list_sync_anim2.png Binary files differnew file mode 100644 index 0000000..b745916 --- /dev/null +++ b/res/drawable-mdpi/ic_list_sync_anim2.png diff --git a/res/drawable-mdpi/ic_list_sync_anim3.png b/res/drawable-mdpi/ic_list_sync_anim3.png Binary files differnew file mode 100644 index 0000000..43e453d --- /dev/null +++ b/res/drawable-mdpi/ic_list_sync_anim3.png diff --git a/res/drawable-mdpi/ic_list_syncerror.png b/res/drawable-mdpi/ic_list_syncerror.png Binary files differnew file mode 100644 index 0000000..328b6a7 --- /dev/null +++ b/res/drawable-mdpi/ic_list_syncerror.png diff --git a/res/drawable-mdpi/ic_sync_green.png b/res/drawable-mdpi/ic_sync_green.png Binary files differnew file mode 100644 index 0000000..177a024 --- /dev/null +++ b/res/drawable-mdpi/ic_sync_green.png diff --git a/res/drawable-mdpi/ic_sync_grey.png b/res/drawable-mdpi/ic_sync_grey.png Binary files differnew file mode 100644 index 0000000..8f168d4 --- /dev/null +++ b/res/drawable-mdpi/ic_sync_grey.png diff --git a/res/drawable-mdpi/ic_sync_red.png b/res/drawable-mdpi/ic_sync_red.png Binary files differnew file mode 100644 index 0000000..5e38136 --- /dev/null +++ b/res/drawable-mdpi/ic_sync_red.png diff --git a/res/drawable/ic_list_sync_anim.xml b/res/drawable/ic_list_sync_anim.xml new file mode 100644 index 0000000..b6965c5 --- /dev/null +++ b/res/drawable/ic_list_sync_anim.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/res/drawable/status_icon_background.xml +** +** Copyright 2007, 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. +*/ +--> +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:oneshot="false"> + <item android:drawable="@drawable/ic_list_sync_anim0" android:duration="150" /> + <item android:drawable="@drawable/ic_list_sync_anim1" android:duration="150" /> + <item android:drawable="@drawable/ic_list_sync_anim2" android:duration="150" /> + <item android:drawable="@drawable/ic_list_sync_anim3" android:duration="150" /> +</animation-list> + diff --git a/res/layout/account_preference.xml b/res/layout/account_preference.xml new file mode 100644 index 0000000..810c57a --- /dev/null +++ b/res/layout/account_preference.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="?android:attr/listPreferredItemHeight" + android:gravity="center_vertical" + android:paddingLeft="16dip" + android:paddingRight="?android:attr/scrollbarSize"> + + <ImageView + android:id="@+id/providerIcon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginRight="5dip" + android:layout_gravity="center" /> + + <RelativeLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginRight="6dip" + android:layout_marginTop="6dip" + android:layout_marginBottom="6dip" + android:layout_weight="1"> + + <TextView android:id="@+android:id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceMedium" /> + + <TextView android:id="@+android:id/summary" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@android:id/title" + android:layout_alignLeft="@android:id/title" + android:textAppearance="?android:attr/textAppearanceSmall" + android:maxLines="2" /> + + </RelativeLayout> + + <ImageView + android:id="@+id/syncStatusIcon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="5dip" + android:layout_marginRight="7dip" + android:layout_gravity="center" /> + +</LinearLayout> diff --git a/res/layout/manage_accounts_screen.xml b/res/layout/manage_accounts_screen.xml new file mode 100644 index 0000000..2150ddf --- /dev/null +++ b/res/layout/manage_accounts_screen.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/layout/list_content.xml +** +** Copyright 2006, 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. +*/ +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <ListView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@android:id/list" + android:layout_width="match_parent" + android:layout_height="0dip" + android:layout_weight="1" + android:drawSelectorOnTop="false" + android:scrollbarAlwaysDrawVerticalTrack="true" + /> + + <TextView android:id="@+id/sync_settings_error_info" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/sync_is_failing" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:background="@android:drawable/bottom_bar"> + + <View + android:layout_width="0dip" + android:layout_height="match_parent" + android:layout_weight="1"/> + + <Button android:id="@+id/add_account_button" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_weight="2" + android:layout_marginTop="5dip" + android:text="@string/add_account_label" /> + + <View + android:layout_width="0dip" + android:layout_height="match_parent" + android:layout_weight="1"/> + </LinearLayout> + +</LinearLayout> diff --git a/res/values/strings.xml b/res/values/strings.xml index 7581275..9408544 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2700,4 +2700,38 @@ found in the list of installed applications.</string> <!-- Do not translate. This is a stub which will be removed soon. --> <string name="time_zone_auto_stub" translatable="false">Select Time Zone</string> + + + + <!-- Message when sync is currently failing [CHAR LIMIT=100] --> + <string name="sync_is_failing">Sync is currently experiencing problems. It will be back shortly.</string> + <!-- Button label to add an account [CHAR LIMIT=20] --> + <string name="add_account_label">Add account</string> + <!-- Header title for those settings relating to general syncing. + [CHAR LIMIT=30] --> + <string name="header_general_sync_settings">General sync settings</string> + <!-- Data synchronization settings screen, title of setting that controls whether background data should be used [CHAR LIMIT=30] --> + <string name="background_data">Background data</string> + <!-- Data synchronization settings screen, summary of setting that controls whether background data should be used [CHAR LIMIT=60] --> + <string name="background_data_summary">Applications can sync, send, and receive data at any time</string> + <!-- Data synchronization settings screen, title of dialog that confirms the user's unchecking of background data [CHAR LIMIT=20] --> + <string name="background_data_dialog_title">Attention</string> + <!-- Data synchronization settings screen, message of dialog that confirms the user's unchecking of background data [CHAR LIMIT=200] --> + <string name="background_data_dialog_message">Disabling background data extends battery life and lowers data use. Some applications may still use the background data connection.</string> + <!-- Data synchronization settings screen, setting option name + [CHAR LIMIT=30] --> + <string name="sync_automatically">Auto-sync</string> + <!-- Data synchronization settings screen, setting option summary text when check box is selected [CHAR LIMIT=60] --> + <string name="sync_automatically_summary">Applications sync data automatically</string> + <!-- Header title for list of accounts on Accounts & Synchronization settings [CHAR LIMIT=30] --> + <string name="header_manage_accounts">Manage accounts</string> + + <!-- Sync status messages on Accounts & Synchronization settings --><skip/> + <!-- Sync status shown when sync is enabled [CHAR LIMIT=20] --> + <string name="sync_enabled">Sync is ON</string> + <!-- Sync status shown when sync is disabled [CHAR LIMIT=20] --> + <string name="sync_disabled">Sync is OFF</string> + <!-- Sync status shown when last sync resulted in an error [CHAR LIMIT=20] --> + <string name="sync_error">Sync error</string> + </resources> diff --git a/res/xml/manage_accounts_settings.xml b/res/xml/manage_accounts_settings.xml new file mode 100644 index 0000000..8ddd7e7 --- /dev/null +++ b/res/xml/manage_accounts_settings.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> + + <PreferenceCategory + android:title="@string/header_general_sync_settings" /> + + <CheckBoxPreference android:key="backgroundDataCheckBox" + android:persistent="false" + android:title="@string/background_data" + android:summary="@string/background_data_summary"/> + + <CheckBoxPreference android:key="syncAutomaticallyCheckBox" + android:persistent="false" + android:dependency="backgroundDataCheckBox" + android:title="@string/sync_automatically" + android:summary="@string/sync_automatically_summary"/> + + <PreferenceCategory android:key="manageAccountsCategory" + android:title="@string/header_manage_accounts" /> + +</PreferenceScreen> diff --git a/res/xml/settings.xml b/res/xml/settings.xml index a91d279..5b6691e 100644 --- a/res/xml/settings.xml +++ b/res/xml/settings.xml @@ -93,10 +93,10 @@ preference. --> <com.android.settings.IconPreferenceScreen + android:fragment="com.android.settings.ManageAccountsSettings" settings:icon="@drawable/ic_settings_sync" android:title="@string/sync_settings" android:key="sync_settings"> - <intent android:action="android.settings.SYNC_SETTINGS" /> </com.android.settings.IconPreferenceScreen> <!-- Privacy --> 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 { |