Commit 43c69785 authored by Amith Yamasani's avatar Amith Yamasani
Browse files

Move Account & sync settings into Settings app.

Fragmentized some of the activities and moved buttons into the menu area.

Bug: 3148844
parent f3c32f49
......@@ -41,6 +41,13 @@
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.MOVE_PACKAGE" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.BACKUP" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<application android:label="@string/settings_label"
android:icon="@mipmap/ic_launcher_settings"
......@@ -942,11 +949,62 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.ManageAccountsSettings" />
android:value="com.android.settings.accounts.ManageAccountsSettings" />
<meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
android:resource="@id/sync_settings" />
</activity>
<activity android:name="Settings$AccountSyncSettingsActivity"
android:label="@string/account_sync_settings_title"
android:theme="@android:style/Theme.Holo">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.ACCOUNT_SYNC_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.accounts.AccountSyncSettings" />
<meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
android:resource="@id/sync_settings" />
</activity>
<activity android:name="Settings$AccountSyncSettingsInAddAccountActivity"
android:label="@string/account_sync_settings_title"
android:theme="@android:style/Theme.Holo">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.ACCOUNT_SYNC_SETTINGS_ADD_ACCOUNT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.accounts.AccountSyncSettingsInAddAccount" />
<meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
android:resource="@id/sync_settings" />
</activity>
<activity android:name="com.android.settings.accounts.AddAccountSettings"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:label="@string/header_add_an_account">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.ADD_ACCOUNT_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="com.android.settings.accounts.ChooseAccountActivity"
android:label="@string/header_add_an_account"
android:theme="@android:style/Theme.Holo.DialogWhenLarge"/>
<activity android:name="com.android.settings.accounts.SyncActivityTooManyDeletes"
android:theme="@android:style/Theme.Holo.Dialog"
android:label="@string/sync_too_many_deletes">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<receiver android:name=".widget.SettingsAppWidgetProvider"
android:label="@string/gadget_title" android:exported="false">
<intent-filter>
......
......@@ -9,4 +9,5 @@
-keep class com.android.settings.inputmethod.*
-keep class com.android.settings.MasterClear
-keep class com.android.settings.MasterClearConfirm
-keep class com.android.settings.accounts.*
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** 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">
<include layout="@layout/title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<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:id="@+id/remove_account_area"
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/remove_account_button"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="2"
android:layout_marginTop="5dip"
android:text="@string/remove_account_label" />
<View
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1"/>
</LinearLayout>
-->
<RelativeLayout android:id="@+id/finish_button_area"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="@android:drawable/bottom_bar"
android:visibility="gone">
<Button android:id="@+id/finish_button"
android:layout_width="150dip"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:layout_alignParentRight="true"
android:drawableRight="@drawable/ic_btn_next"
android:drawablePadding="3dip"
android:text="@string/finish_button_label"
/>
</RelativeLayout>
</LinearLayout>
<?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"
/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 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.
-->
<!-- Layout used by SyncStateCheckBoxPreference. This is inflated
inside android.R.layout.preference. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|right"
android:gravity="center_vertical|right">
<ImageView
android:id="@+android:id/sync_failed"
android:src="@drawable/ic_list_syncerror"
android:layout_width="wrap_content"
android:layout_marginLeft="6sp"
android:layout_marginBottom="2sp"
android:layout_height="wrap_content" />
<ImageView
android:id="@+android:id/sync_active"
android:src="@drawable/ic_list_sync_anim"
android:layout_width="wrap_content"
android:layout_marginLeft="6sp"
android:layout_marginBottom="2sp"
android:layout_height="wrap_content" />
<ImageView
android:id="@+android:id/sync_pending"
android:src="@drawable/ic_list_sync_anim0"
android:layout_width="wrap_content"
android:layout_marginLeft="6sp"
android:layout_marginBottom="2sp"
android:layout_height="wrap_content" />
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+android:id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="4sp"
android:layout_gravity="center_vertical"
android:focusable="false"
android:clickable="false" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!--
/**
* Copyright (C) 2009 Google Inc.
*
* 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.
*/
-->
<!-- The title area at the top of the settings pane -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/title_area"
android:orientation="horizontal">
<ImageView android:id="@+id/provider_icon"
android:layout_width="48dip"
android:layout_height="48dip"
android:layout_margin="5dip"
android:layout_gravity="center_vertical" />
<LinearLayout
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/user_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorTertiary"
android:textStyle="bold"
android:singleLine="true"
android:ellipsize="end"
android:gravity="center_vertical"
android:layout_marginTop="5dip"/>
<TextView
android:id="@+id/provider_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorTertiary"
android:singleLine="true"
android:ellipsize="end"
android:layout_gravity="bottom"
android:layout_marginBottom="5dip"/>
</LinearLayout>
</LinearLayout>
......@@ -3015,6 +3015,8 @@ 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>
<!-- Account specific sync settings title [CHAR LIMIT=35] -->
<string name="account_sync_settings_title">Sync settings</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] -->
......@@ -3046,4 +3048,73 @@ found in the list of installed applications.</string>
<!-- Sync status shown when last sync resulted in an error [CHAR LIMIT=20] -->
<string name="sync_error">Sync error</string>
<!-- Title of the feed synchronization activity. -->
<string name="app_label">Account and Sync Settings</string>
<!-- Error message when the sync tried to delete too many things -->
<string name="sync_too_many_deletes">Delete limit exceeded</string>
<!-- Data synchronization settings screen, setting option name -->
<string name="settings_backup">Back up settings</string>
<!-- Data synchronization settings screen, setting option summary text when check box is selected -->
<string name="settings_backup_summary">Back up my settings</string>
<!-- Data synchronization settings screen, menu option -->
<string name="sync_menu_sync_now">Sync now</string>
<!-- Data synchronization settings screen, menu option -->
<string name="sync_menu_sync_cancel">Cancel sync</string>
<!-- Data synchronization settings screen, summary of a sync provider (for example, Gmail) when autosync is off and the user wants to do a one-time sync. -->
<string name="sync_one_time_sync">Touch to sync now<xliff:g id="last_sync_time">\n%1$s</xliff:g></string>
<!-- Data synchronization settings screen, checkbox setting option name. Controls whether Gmail should be synced. Should use "Gmail" to refer to this app.-->
<string name="sync_gmail">Gmail</string>
<!-- Data synchronization settings screen, checkbox setting option name. Controls whether Calendar shoudl be synced. -->
<string name="sync_calendar">Calendar</string>
<!-- Data synchronization settings screen, checkbox setting option name -->
<string name="sync_contacts">Contacts</string>
<!-- Dialog message for when there are too many deletes that would take place and we want user confirmation -->
<string name="sync_too_many_deletes_desc">There are <xliff:g id="number_of_deleted_items">%1$d</xliff:g> deleted items for <xliff:g id="type_of_sync">%2$s</xliff:g>, account <xliff:g id="account_name">%3$s</xliff:g>. What would you like to do?</string>
<!-- Dialog action for when there are too many deletes that would take place and we want user confirmation, and the user wants to delete the items -->
<string name="sync_really_delete">Delete the items.</string>
<!-- Dialog action for when there are too many deletes that would take place and we want user confirmation, and the user wants to undo the deletions -->
<string name="sync_undo_deletes">Undo the deletes.</string>
<!-- Dialog action for when there are too many deletes that would take place and we want user confirmation, and the user wants to do nothing for now -->
<string name="sync_do_nothing">Do nothing for now.</string>
<!-- Message introducing the user to Google Sync. -->
<string name="sync_plug"><font fgcolor="#ffffffff">Welcome to Google sync!</font>
\nA Google approach to synchronizing data to allow access to your contacts, appointments, and more from wherever you are.
</string>
<!-- Header title for those settings relating to application syncing. -->
<string name="header_application_sync_settings">Application sync settings</string>
<!-- Header for data and synchronization -->
<string name="header_data_and_synchronization">Data &amp; synchronization</string>
<!-- Preference item that lets the user change password -->
<string name="preference_change_password_title">Change password</string>
<!-- Header that appears at the top of Account Settings screen -->
<string name="header_account_settings">Account settings</string>
<!-- Button label to remove current account -->
<string name="remove_account_label">Remove account</string>
<!-- Title shown in AddAccount -->
<string name="header_add_an_account">Add an account</string>
<!-- Button shown when this activity is run from SetupWizard -->
<string name="finish_button_label">Finish</string>
<!-- Title of remove message for remove account dialog -->
<string name="really_remove_account_title">Remove account</string>
<!-- Remove account message in dialog -->
<string name="really_remove_account_message" product="tablet">Do you really want to remove this account? Removing it will also delete all of its messages, contacts, and other data from the tablet.
\nProceed?</string>
<!-- Remove account message in dialog -->
<string name="really_remove_account_message" product="default">Do you really want to remove this account? Removing it will also delete all of its messages, contacts, and other data from the phone.
\nProceed?</string>
<!-- This is shown if the autheticator for a given account fails to remove it. -->
<string name="remove_account_failed" product="tablet">This account is required by some applications. You can only remove it by resetting the tablet to factory defaults (which deletes all your personal data). You do that in the Settings application, under Privacy.</string>
<!-- This is shown if the autheticator for a given account fails to remove it. -->
<string name="remove_account_failed" product="default">This account is required by some applications. You can only remove it by resetting the phone to factory defaults (which deletes all your personal data). You do that in the Settings application, under Privacy.</string>
<!-- What to show in messaging that refers to this provider, e.g. AccountSyncSettings -->
<string name="provider_label">Push subscriptions</string>
<!-- Formatter in AccountSyncSettings for each application we wish to synchronize, e.g. "Sync Calendar" -->
<string name="sync_item_title">Sync <xliff:g id="authority" example="Calendar">%s</xliff:g></string>
<!-- Title of dialog shown when you can't manually sync an item because it's disabled -->
<string name="cant_sync_dialog_title">Cannot manually sync</string>
<!-- Messaage shown in dialog when you can't manually sync -->
<string name="cant_sync_dialog_message">Sync for this item is currently disabled. To change your preference, temporarily turn on background data and automatic sync.</string>
</resources>
<?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:key="dataAndSynchronization"
android:title="@string/header_data_and_synchronization" />
</PreferenceScreen>
<?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">
</PreferenceScreen>
......@@ -90,7 +90,7 @@
preference. -->
<header
android:fragment="com.android.settings.ManageAccountsSettings"
android:fragment="com.android.settings.accounts.ManageAccountsSettings"
android:icon="@drawable/ic_settings_sync"
android:title="@string/sync_settings"
android:id="@+id/sync_settings" />
......
......@@ -52,10 +52,6 @@ public class AccountPreference extends Preference {
setWidgetLayoutResource(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);
}
......
/*
* 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;
import android.app.Dialog;
/**
* Letting the class, assumed to be Fragment, create a Dialog on it. Should be useful
* you want to utilize some capability in {@link SettingsPreferenceFragment} but don't want
* the class inherit the class itself (See {@link ProxySelector} for example).
*/
public interface DialogCreatable {
public Dialog onCreateDialog(int dialogId);
}
......@@ -208,4 +208,6 @@ public class Settings extends PreferenceActivity {
public static class VoiceInputOutputSettingsActivity extends Settings { }
public static class ManageAccountsSettingsActivity extends Settings { }
public static class PowerUsageSummaryActivity extends Settings { }
public static class AccountSyncSettingsActivity extends Settings { }
public static class AccountSyncSettingsInAddAccountActivity extends Settings { }
}
......@@ -33,15 +33,6 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
/**
* Letting the class, assumed to be Fragment, create a Dialog on it. Should be useful
* you want to utilize some capability in {@link SettingsPreferenceFragment} but don't want
* the class inherit the class itself (See {@link ProxySelector} for example).
*/
interface DialogCreatable {
public Dialog onCreateDialog(int dialogId);
}
/**
* Base class for Settings fragments, with some helper functions and dialog management.
*/
......@@ -122,12 +113,12 @@ public class SettingsPreferenceFragment extends PreferenceFragment
mDialogFragment = null;
}
static class SettingsDialogFragment extends DialogFragment {
public static class SettingsDialogFragment extends DialogFragment {
private int mDialogId;
private DialogCreatable mFragment;
SettingsDialogFragment(DialogCreatable fragment, int dialogId) {
public SettingsDialogFragment(DialogCreatable fragment, int dialogId) {
mDialogId = dialogId;
mFragment = fragment;
}
......
/*
* 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.accounts;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import com.android.settings.SettingsPreferenceFragment;
import com.google.android.collect.Maps;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription;
import android.accounts.OnAccountsUpdateListener;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SyncAdapterType;
import android.content.SyncStatusObserver;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.util.Log;
class AccountPreferenceBase extends SettingsPreferenceFragment
implements OnAccountsUpdateListener {
protected static final String TAG = "AccountSettings";
public static final String AUTHORITIES_FILTER_KEY = "authorities";
public static final String ACCOUNT_TYPES_FILTER_KEY = "account_types";
private Map<String, AuthenticatorDescription> mTypeToAuthDescription
= new HashMap<String, AuthenticatorDescription>();
protected AuthenticatorDescription[] mAuthDescs;
private final Handler mHandler = new Handler();
private Object mStatusChangeListenerHandle;
private HashMap<String, ArrayList<String>> mAccountTypeToAuthorities = null;
/**
* Overload to handle account updates.
*/
public void onAccountsUpdated(Account[] accounts) {
}
/**
* Overload to handle authenticator description updates
*/
protected void onAuthDescriptionsUpdated() {
}
/**
* Overload to handle sync state updates.
*/
protected void onSyncStateUpdated() {
}
@Override
public void onResume() {
super.onResume();
mStatusChangeListenerHandle = ContentResolver.addStatusChangeListener(
ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE
| ContentResolver.SYNC_OBSERVER_TYPE_STATUS
| ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS,
mSyncStatusObserver);
onSyncStateUpdated();
}
@Override
public void onPause() {
super.onPause();
ContentResolver.removeStatusChangeListener(mStatusChangeListenerHandle);
}
private SyncStatusObserver mSyncStatusObserver = new SyncStatusObserver() {
public void onStatusChanged(int which) {
mHandler.post(new Runnable() {
public void run() {
onSyncStateUpdated();
}
});
}
};
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 = 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;
}
/**
* 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 = 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;
}
/**
* Gets the preferences.xml file associated with a particular account type.
* @param accountType the type of account
* @return a PreferenceScreen inflated from accountPreferenceId.
*/
protected PreferenceScreen addPreferencesForType(final String accountType) {
PreferenceScreen prefs = null;
if (mTypeToAuthDescription.containsKey(accountType)) {
AuthenticatorDescription desc = null;
try {
desc = mTypeToAuthDescription.get(accountType);
if (desc != null && desc.accountPreferencesId != 0) {
Context authContext = getActivity().createPackageContext(desc.packageName, 0);
prefs = getPreferenceManager().inflateFromResource(authContext,
desc.accountPreferencesId, getPreferenceScreen());
}
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Couldn't load preferences.xml file from " + desc.packageName);
}
}
return prefs;
}
/**
* Updates provider icons. Subclasses should call this in onCreate()
* and update any UI that depends on AuthenticatorDescriptions in onAuthDescriptionsUpdated().
*/
protected void updateAuthDescriptions() {
mAuthDescs = AccountManager.get(getActivity()).getAuthenticatorTypes();
for (int i = 0; i < mAuthDescs.length; i++) {
mTypeToAuthDescription.put(mAuthDescs[i].type, mAuthDescs[i]);
}
onAuthDescriptionsUpdated();
}
}
This diff is collapsed.
package com.android.settings.accounts;
import com.android.settings.R;
import android.app.Activity;
import android.content.ContentResolver;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
/**
* This is AccountSyncSettings with 'remove account' button always gone and
* a wizard-like button bar to complete the activity.
*/
public class AccountSyncSettingsInAddAccount extends AccountSyncSettings
implements OnClickListener {
private View mFinishArea;
private View mFinishButton;
@Override
protected void initializeUi(final View rootView) {
super.initializeUi(rootView);
mFinishArea = (View) rootView.findViewById(R.id.finish_button_area);
mFinishArea.setVisibility(View.VISIBLE);
mFinishButton = (View) rootView.findViewById(R.id.finish_button);
mFinishButton.setOnClickListener(this);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
// Remove the "remove account" menu item
menu.findItem(MENU_REMOVE_ACCOUNT_ID).setVisible(false);
}
public void onClick(View v) {
finish();
}
}
/*
* 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.accounts;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import java.io.IOException;
/**
* Entry point Actiivty for account setup. Works as follows
*
* 1) When the other Activities launch this Activity, it launches {@link ChooseAccountActivity}
* without showing anything.
* 2) After receiving an account type from ChooseAccountActivity, this Activity launches the
* account setup specified by AccountManager.
* 3) After the account setup, this Activity finishes without showing anything.
*
* Note:
* Previously this Activity did what {@link ChooseAccountActivity} does right now, but we
* currently delegate the work to the other Activity. When we let this Activity do that work, users
* would see the list of account types when leaving this Activity, since the UI is already ready
* when returning from each account setup, which doesn't look good.
*/
public class AddAccountSettings extends Activity {
private static final String TAG = "AccountSettings";
/* package */ static final String EXTRA_SELECTED_ACCOUNT = "selected_account";
private static final int CHOOSE_ACCOUNT_REQUEST = 1;
private AccountManagerCallback<Bundle> mCallback = new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> future) {
try {
Bundle bundle = future.getResult();
bundle.keySet();
setResult(RESULT_OK);
if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "account added: " + bundle);
} catch (OperationCanceledException e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "addAccount was canceled");
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "addAccount failed: " + e);
} catch (AuthenticatorException e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "addAccount failed: " + e);
} finally {
finish();
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final String[] authorities =
getIntent().getStringArrayExtra(AccountPreferenceBase.AUTHORITIES_FILTER_KEY);
final String[] accountTypes =
getIntent().getStringArrayExtra(AccountPreferenceBase.ACCOUNT_TYPES_FILTER_KEY);
final Intent intent = new Intent(this, ChooseAccountActivity.class);
if (authorities != null) {
intent.putExtra(AccountPreferenceBase.AUTHORITIES_FILTER_KEY, authorities);
}
if (accountTypes != null) {
intent.putExtra(AccountPreferenceBase.ACCOUNT_TYPES_FILTER_KEY, accountTypes);
}
startActivityForResult(intent, CHOOSE_ACCOUNT_REQUEST);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case CHOOSE_ACCOUNT_REQUEST:
if (resultCode == RESULT_CANCELED) {
setResult(resultCode);
finish();
return;
}
// Go to account setup screen. finish() is called inside mCallback.
addAccount(data.getStringExtra(EXTRA_SELECTED_ACCOUNT));
break;
}
}
private void addAccount(String accountType) {
AccountManager.get(this).addAccount(
accountType,
null, /* authTokenType */
null, /* requiredFeatures */
null, /* addAccountOptions */
this,
mCallback,
null /* handler */);
}
}
/*
* 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 com.android.settings.R;
import com.google.android.collect.Maps;
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.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 java.util.ArrayList;
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 {
private final CharSequence name;
private final String type;
ProviderEntry(CharSequence providerName, String accountType) {
name = providerName;
type = accountType;
}
}
@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) {
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 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 for account type " + ", 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();
}
}
......@@ -14,9 +14,12 @@
* limitations under the License.
*/
package com.android.settings;
package com.android.settings.accounts;
import com.android.settings.SettingsPreferenceFragment.SettingsDialogFragment;
import com.android.settings.AccountPreference;
import com.android.settings.DialogCreatable;
import com.android.settings.R;
import com.android.settings.vpn.VpnTypeSelection;
import com.google.android.collect.Maps;
import android.accounts.Account;
......@@ -39,8 +42,8 @@ import android.net.ConnectivityManager;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import android.util.Log;
import android.view.LayoutInflater;
......@@ -57,9 +60,9 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
public class ManageAccountsSettings extends PreferenceFragment
implements OnAccountsUpdateListener,
DialogCreatable {
public class ManageAccountsSettings extends AccountPreferenceBase
implements OnAccountsUpdateListener, DialogCreatable {
private static final String TAG = ManageAccountsSettings.class.getSimpleName();
private static final String AUTHORITIES_FILTER_KEY = "authorities";
......@@ -72,6 +75,8 @@ public class ManageAccountsSettings extends PreferenceFragment
private static final int MENU_ADD_ACCOUNT = Menu.FIRST;
private static final int REQUEST_SHOW_SYNC_SETTINGS = 1;
private CheckBoxPreference mBackgroundDataCheckBox;
private PreferenceCategory mManageAccountsCategory;
private String[] mAuthorities;
......@@ -90,6 +95,8 @@ public class ManageAccountsSettings extends PreferenceFragment
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.manage_accounts_settings);
AccountManager.get(getActivity()).addOnAccountsUpdatedListener(this, null, true);
setHasOptionsMenu(true);
}
......@@ -100,18 +107,11 @@ public class ManageAccountsSettings extends PreferenceFragment
return view;
}
@Override
public void onResume() {
super.onResume();
onSyncStateUpdated();
}
@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);
......@@ -126,8 +126,7 @@ public class ManageAccountsSettings extends PreferenceFragment
mManageAccountsCategory = (PreferenceCategory)findPreference(MANAGE_ACCOUNTS_CATEGORY_KEY);
mAuthorities = activity.getIntent().getStringArrayExtra(AUTHORITIES_FILTER_KEY);
AccountManager.get(activity).addOnAccountsUpdatedListener(this, null, true);
updateAuthDescriptions(activity);
updateAuthDescriptions();
}
@Override
......@@ -156,12 +155,23 @@ public class ManageAccountsSettings extends PreferenceFragment
} else if (preference == mAutoSyncCheckbox) {
ContentResolver.setMasterSyncAutomatically(mAutoSyncCheckbox.isChecked());
onSyncStateUpdated();
} else if (preference instanceof AccountPreference) {
startAccountSettings((AccountPreference) preference);
} else {
return false;
}
return true;
}
private void startAccountSettings(AccountPreference acctPref) {
Bundle args = new Bundle();
args.putParcelable(AccountSyncSettings.ACCOUNT_KEY, acctPref.getAccount());
((PreferenceActivity) getActivity()).startPreferencePanel(
AccountSyncSettings.class.getCanonicalName(), args,
R.string.account_sync_settings_title, acctPref.getAccount().name,
this, REQUEST_SHOW_SYNC_SETTINGS);
}
@Override
public Dialog onCreateDialog(int id) {
switch (id) {
......@@ -187,7 +197,7 @@ public class ManageAccountsSettings extends PreferenceFragment
return null;
}
void showDialog(int dialogId) {
public void showDialog(int dialogId) {
if (mDialogFragment != null) {
Log.e(TAG, "Old dialog fragment not null!");
}
......@@ -216,7 +226,7 @@ public class ManageAccountsSettings extends PreferenceFragment
connManager.setBackgroundDataSetting(enabled);
}
private void onSyncStateUpdated() {
protected void onSyncStateUpdated() {
// Set background connection state
final ConnectivityManager connManager = (ConnectivityManager)
getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
......@@ -320,7 +330,7 @@ public class ManageAccountsSettings extends PreferenceFragment
onSyncStateUpdated();
}
private void onAuthDescriptionsUpdated() {
protected void onAuthDescriptionsUpdated() {
// Update account icons for all account preference items
for (int i = 0; i < mManageAccountsCategory.getPreferenceCount(); i++) {
AccountPreference pref = (AccountPreference) mManageAccountsCategory.getPreference(i);
......@@ -334,64 +344,4 @@ public class ManageAccountsSettings extends PreferenceFragment
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();
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment