Move Account & sync settings into Settings app.
Fragmentized some of the activities and moved buttons into the menu area. Bug: 3148844
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
29
src/com/android/settings/DialogCreatable.java
Normal file
29
src/com/android/settings/DialogCreatable.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
198
src/com/android/settings/accounts/AccountPreferenceBase.java
Normal file
198
src/com/android/settings/accounts/AccountPreferenceBase.java
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
505
src/com/android/settings/accounts/AccountSyncSettings.java
Normal file
505
src/com/android/settings/accounts/AccountSyncSettings.java
Normal file
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
* 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 com.android.settings.R;
|
||||
import com.google.android.collect.Lists;
|
||||
import com.google.android.collect.Maps;
|
||||
|
||||
import android.accounts.Account;
|
||||
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.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.ProviderInfo;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateFormat;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class AccountSyncSettings extends AccountPreferenceBase {
|
||||
|
||||
public static final String ACCOUNT_KEY = "account";
|
||||
protected static final int MENU_REMOVE_ACCOUNT_ID = Menu.FIRST;
|
||||
private static final int MENU_SYNC_NOW_ID = Menu.FIRST + 1;
|
||||
private static final int MENU_SYNC_CANCEL_ID = Menu.FIRST + 2;
|
||||
private static final int REALLY_REMOVE_DIALOG = 100;
|
||||
private static final int FAILED_REMOVAL_DIALOG = 101;
|
||||
private static final int CANT_DO_ONETIME_SYNC_DIALOG = 102;
|
||||
private TextView mUserId;
|
||||
private TextView mProviderId;
|
||||
private ImageView mProviderIcon;
|
||||
private TextView mErrorInfoView;
|
||||
protected View mRemoveAccountArea;
|
||||
private java.text.DateFormat mDateFormat;
|
||||
private java.text.DateFormat mTimeFormat;
|
||||
private Account mAccount;
|
||||
// List of all accounts, updated when accounts are added/removed
|
||||
// We need to re-scan the accounts on sync events, in case sync state changes.
|
||||
private Account[] mAccounts;
|
||||
private Button mRemoveAccountButton;
|
||||
private ArrayList<SyncStateCheckBoxPreference> mCheckBoxes =
|
||||
new ArrayList<SyncStateCheckBoxPreference>();
|
||||
private ArrayList<String> mInvisibleAdapters = Lists.newArrayList();
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(final int id) {
|
||||
Dialog dialog = null;
|
||||
if (id == REALLY_REMOVE_DIALOG) {
|
||||
dialog = new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.really_remove_account_title)
|
||||
.setMessage(R.string.really_remove_account_message)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.remove_account_label,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
AccountManager.get(AccountSyncSettings.this.getActivity())
|
||||
.removeAccount(mAccount,
|
||||
new AccountManagerCallback<Boolean>() {
|
||||
public void run(AccountManagerFuture<Boolean> future) {
|
||||
boolean failed = true;
|
||||
try {
|
||||
if (future.getResult() == true) {
|
||||
failed = false;
|
||||
}
|
||||
} catch (OperationCanceledException e) {
|
||||
// handled below
|
||||
} catch (IOException e) {
|
||||
// handled below
|
||||
} catch (AuthenticatorException e) {
|
||||
// handled below
|
||||
}
|
||||
if (failed) {
|
||||
showDialog(FAILED_REMOVAL_DIALOG);
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
})
|
||||
.create();
|
||||
} else if (id == FAILED_REMOVAL_DIALOG) {
|
||||
dialog = new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.really_remove_account_title)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.setMessage(R.string.remove_account_failed)
|
||||
.create();
|
||||
} else if (id == CANT_DO_ONETIME_SYNC_DIALOG) {
|
||||
dialog = new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.cant_sync_dialog_title)
|
||||
.setMessage(R.string.cant_sync_dialog_message)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.create();
|
||||
}
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
final View view = inflater.inflate(R.layout.account_sync_screen, container, false);
|
||||
|
||||
initializeUi(view);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
protected void initializeUi(final View rootView) {
|
||||
addPreferencesFromResource(R.xml.account_sync_settings);
|
||||
|
||||
mErrorInfoView = (TextView) rootView.findViewById(R.id.sync_settings_error_info);
|
||||
mErrorInfoView.setVisibility(View.GONE);
|
||||
mErrorInfoView.setCompoundDrawablesWithIntrinsicBounds(
|
||||
getResources().getDrawable(R.drawable.ic_list_syncerror), null, null, null);
|
||||
|
||||
mUserId = (TextView) rootView.findViewById(R.id.user_id);
|
||||
mProviderId = (TextView) rootView.findViewById(R.id.provider_id);
|
||||
mProviderIcon = (ImageView) rootView.findViewById(R.id.provider_icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
final Activity activity = getActivity();
|
||||
|
||||
mDateFormat = DateFormat.getDateFormat(activity);
|
||||
mTimeFormat = DateFormat.getTimeFormat(activity);
|
||||
|
||||
mAccount = (Account) getArguments().getParcelable(ACCOUNT_KEY);
|
||||
if (mAccount != null) {
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "Got account: " + mAccount);
|
||||
mUserId.setText(mAccount.name);
|
||||
mProviderId.setText(mAccount.type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
final Activity activity = getActivity();
|
||||
AccountManager.get(activity).addOnAccountsUpdatedListener(this, null, false);
|
||||
updateAuthDescriptions();
|
||||
onAccountsUpdated(AccountManager.get(activity).getAccounts());
|
||||
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
AccountManager.get(getActivity()).removeOnAccountsUpdatedListener(this);
|
||||
}
|
||||
|
||||
private void addSyncStateCheckBox(Account account, String authority) {
|
||||
SyncStateCheckBoxPreference item =
|
||||
new SyncStateCheckBoxPreference(getActivity(), account, authority);
|
||||
item.setPersistent(false);
|
||||
final ProviderInfo providerInfo = getPackageManager().resolveContentProvider(authority, 0);
|
||||
CharSequence providerLabel = providerInfo != null
|
||||
? providerInfo.loadLabel(getPackageManager()) : null;
|
||||
if (TextUtils.isEmpty(providerLabel)) {
|
||||
Log.e(TAG, "Provider needs a label for authority '" + authority + "'");
|
||||
providerLabel = authority;
|
||||
}
|
||||
String title = getString(R.string.sync_item_title, providerLabel);
|
||||
item.setTitle(title);
|
||||
item.setKey(authority);
|
||||
getPreferenceScreen().addPreference(item);
|
||||
mCheckBoxes.add(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
|
||||
MenuItem removeAccount = menu.add(0, MENU_REMOVE_ACCOUNT_ID, 0,
|
||||
getString(R.string.remove_account_label))
|
||||
.setIcon(com.android.internal.R.drawable.ic_menu_delete);
|
||||
MenuItem syncNow = menu.add(0, MENU_SYNC_NOW_ID, 0,
|
||||
getString(R.string.sync_menu_sync_now))
|
||||
.setIcon(com.android.internal.R.drawable.ic_menu_refresh);
|
||||
MenuItem syncCancel = menu.add(0, MENU_SYNC_CANCEL_ID, 0,
|
||||
getString(R.string.sync_menu_sync_cancel))
|
||||
.setIcon(com.android.internal.R.drawable.ic_menu_close_clear_cancel);
|
||||
|
||||
removeAccount.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS
|
||||
| MenuItem.SHOW_AS_ACTION_WITH_TEXT);
|
||||
syncNow.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
syncCancel.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
boolean syncActive = ContentResolver.getCurrentSync() != null;
|
||||
menu.findItem(MENU_SYNC_NOW_ID).setVisible(!syncActive);
|
||||
menu.findItem(MENU_SYNC_CANCEL_ID).setVisible(syncActive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENU_SYNC_NOW_ID:
|
||||
startSyncForEnabledProviders();
|
||||
return true;
|
||||
case MENU_SYNC_CANCEL_ID:
|
||||
cancelSyncForEnabledProviders();
|
||||
return true;
|
||||
case MENU_REMOVE_ACCOUNT_ID:
|
||||
showDialog(REALLY_REMOVE_DIALOG);
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferences, Preference preference) {
|
||||
if (preference instanceof SyncStateCheckBoxPreference) {
|
||||
SyncStateCheckBoxPreference syncPref = (SyncStateCheckBoxPreference) preference;
|
||||
String authority = syncPref.getAuthority();
|
||||
Account account = syncPref.getAccount();
|
||||
boolean syncAutomatically = ContentResolver.getSyncAutomatically(account, authority);
|
||||
if (syncPref.isOneTimeSyncMode()) {
|
||||
requestOrCancelSync(account, authority, true);
|
||||
} else {
|
||||
boolean syncOn = syncPref.isChecked();
|
||||
boolean oldSyncState = syncAutomatically;
|
||||
if (syncOn != oldSyncState) {
|
||||
// if we're enabling sync, this will request a sync as well
|
||||
ContentResolver.setSyncAutomatically(account, authority, syncOn);
|
||||
// if the master sync switch is off, the request above will
|
||||
// get dropped. when the user clicks on this toggle,
|
||||
// we want to force the sync, however.
|
||||
if (!ContentResolver.getMasterSyncAutomatically() || !syncOn) {
|
||||
requestOrCancelSync(account, authority, syncOn);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return super.onPreferenceTreeClick(preferences, preference);
|
||||
}
|
||||
}
|
||||
|
||||
private void startSyncForEnabledProviders() {
|
||||
requestOrCancelSyncForEnabledProviders(true /* start them */);
|
||||
getActivity().invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
private void cancelSyncForEnabledProviders() {
|
||||
requestOrCancelSyncForEnabledProviders(false /* cancel them */);
|
||||
getActivity().invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
private void requestOrCancelSyncForEnabledProviders(boolean startSync) {
|
||||
// sync everything that the user has enabled
|
||||
int count = getPreferenceScreen().getPreferenceCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
Preference pref = getPreferenceScreen().getPreference(i);
|
||||
if (! (pref instanceof SyncStateCheckBoxPreference)) {
|
||||
continue;
|
||||
}
|
||||
SyncStateCheckBoxPreference syncPref = (SyncStateCheckBoxPreference) pref;
|
||||
if (!syncPref.isChecked()) {
|
||||
continue;
|
||||
}
|
||||
requestOrCancelSync(syncPref.getAccount(), syncPref.getAuthority(), startSync);
|
||||
}
|
||||
// plus whatever the system needs to sync, e.g., invisible sync adapters
|
||||
if (mAccount != null) {
|
||||
for (String authority : mInvisibleAdapters) {
|
||||
requestOrCancelSync(mAccount, authority, startSync);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void requestOrCancelSync(Account account, String authority, boolean flag) {
|
||||
if (flag) {
|
||||
Bundle extras = new Bundle();
|
||||
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
|
||||
ContentResolver.requestSync(account, authority, extras);
|
||||
} else {
|
||||
ContentResolver.cancelSync(account, authority);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSyncing(List<SyncInfo> currentSyncs, Account account, String authority) {
|
||||
for (SyncInfo syncInfo : currentSyncs) {
|
||||
if (syncInfo.account.equals(account) && syncInfo.authority.equals(authority)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSyncStateUpdated() {
|
||||
// iterate over all the preferences, setting the state properly for each
|
||||
Date date = new Date();
|
||||
List<SyncInfo> currentSyncs = ContentResolver.getCurrentSyncs();
|
||||
boolean syncIsFailing = false;
|
||||
|
||||
// Refresh the sync status checkboxes - some syncs may have become active.
|
||||
updateAccountCheckboxes(mAccounts);
|
||||
|
||||
for (int i = 0, count = getPreferenceScreen().getPreferenceCount(); i < count; i++) {
|
||||
Preference pref = getPreferenceScreen().getPreference(i);
|
||||
if (! (pref instanceof SyncStateCheckBoxPreference)) {
|
||||
continue;
|
||||
}
|
||||
SyncStateCheckBoxPreference syncPref = (SyncStateCheckBoxPreference) pref;
|
||||
|
||||
String authority = syncPref.getAuthority();
|
||||
Account account = syncPref.getAccount();
|
||||
|
||||
SyncStatusInfo status = ContentResolver.getSyncStatus(account, authority);
|
||||
boolean syncEnabled = ContentResolver.getSyncAutomatically(account, authority);
|
||||
boolean authorityIsPending = status == null ? false : status.pending;
|
||||
boolean initialSync = status == null ? false : status.initialize;
|
||||
|
||||
boolean activelySyncing = isSyncing(currentSyncs, account, authority);
|
||||
boolean lastSyncFailed = status != null
|
||||
&& status.lastFailureTime != 0
|
||||
&& status.getLastFailureMesgAsInt(0)
|
||||
!= ContentResolver.SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS;
|
||||
if (!syncEnabled) lastSyncFailed = false;
|
||||
if (lastSyncFailed && !activelySyncing && !authorityIsPending) {
|
||||
syncIsFailing = true;
|
||||
}
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.d(TAG, "Update sync status: " + account + " " + authority +
|
||||
" active = " + activelySyncing + " pend =" + authorityIsPending);
|
||||
}
|
||||
|
||||
final long successEndTime = (status == null) ? 0 : status.lastSuccessTime;
|
||||
if (successEndTime != 0) {
|
||||
date.setTime(successEndTime);
|
||||
final String timeString = mDateFormat.format(date) + " "
|
||||
+ mTimeFormat.format(date);
|
||||
syncPref.setSummary(timeString);
|
||||
} else {
|
||||
syncPref.setSummary("");
|
||||
}
|
||||
int syncState = ContentResolver.getIsSyncable(account, authority);
|
||||
|
||||
syncPref.setActive(activelySyncing && (syncState >= 0) &&
|
||||
!initialSync);
|
||||
syncPref.setPending(authorityIsPending && (syncState >= 0) &&
|
||||
!initialSync);
|
||||
|
||||
syncPref.setFailed(lastSyncFailed);
|
||||
ConnectivityManager connManager =
|
||||
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
final boolean masterSyncAutomatically = ContentResolver.getMasterSyncAutomatically();
|
||||
final boolean backgroundDataEnabled = connManager.getBackgroundDataSetting();
|
||||
final boolean oneTimeSyncMode = !masterSyncAutomatically || !backgroundDataEnabled;
|
||||
syncPref.setOneTimeSyncMode(oneTimeSyncMode);
|
||||
syncPref.setChecked(oneTimeSyncMode || syncEnabled);
|
||||
}
|
||||
mErrorInfoView.setVisibility(syncIsFailing ? View.VISIBLE : View.GONE);
|
||||
getActivity().invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccountsUpdated(Account[] accounts) {
|
||||
super.onAccountsUpdated(accounts);
|
||||
mAccounts = accounts;
|
||||
updateAccountCheckboxes(accounts);
|
||||
onSyncStateUpdated();
|
||||
}
|
||||
|
||||
private void updateAccountCheckboxes(Account[] accounts) {
|
||||
mInvisibleAdapters.clear();
|
||||
|
||||
SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypes();
|
||||
HashMap<String, ArrayList<String>> accountTypeToAuthorities =
|
||||
Maps.newHashMap();
|
||||
for (int i = 0, n = syncAdapters.length; i < n; i++) {
|
||||
final SyncAdapterType sa = syncAdapters[i];
|
||||
if (sa.isUserVisible()) {
|
||||
ArrayList<String> authorities = accountTypeToAuthorities.get(sa.accountType);
|
||||
if (authorities == null) {
|
||||
authorities = new ArrayList<String>();
|
||||
accountTypeToAuthorities.put(sa.accountType, authorities);
|
||||
}
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.d(TAG, "onAccountUpdated: added authority " + sa.authority
|
||||
+ " to accountType " + sa.accountType);
|
||||
}
|
||||
authorities.add(sa.authority);
|
||||
} else {
|
||||
// keep track of invisible sync adapters, so sync now forces
|
||||
// them to sync as well.
|
||||
mInvisibleAdapters.add(sa.authority);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0, n = mCheckBoxes.size(); i < n; i++) {
|
||||
getPreferenceScreen().removePreference(mCheckBoxes.get(i));
|
||||
}
|
||||
mCheckBoxes.clear();
|
||||
|
||||
for (int i = 0, n = accounts.length; i < n; i++) {
|
||||
final Account account = accounts[i];
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.d(TAG, "looking for sync adapters that match account " + account);
|
||||
}
|
||||
final ArrayList<String> authorities = accountTypeToAuthorities.get(account.type);
|
||||
if (authorities != null && (mAccount == null || mAccount.equals(account))) {
|
||||
for (int j = 0, m = authorities.size(); j < m; j++) {
|
||||
final String authority = authorities.get(j);
|
||||
// We could check services here....
|
||||
int syncState = ContentResolver.getIsSyncable(account, authority);
|
||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||
Log.d(TAG, " found authority " + authority + " " + syncState);
|
||||
}
|
||||
if (syncState > 0) {
|
||||
addSyncStateCheckBox(account, authority);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the titlebar with an icon for the provider type.
|
||||
*/
|
||||
@Override
|
||||
protected void onAuthDescriptionsUpdated() {
|
||||
super.onAuthDescriptionsUpdated();
|
||||
getPreferenceScreen().removeAll();
|
||||
mProviderIcon.setImageDrawable(getDrawableForType(mAccount.type));
|
||||
mProviderId.setText(getLabelForType(mAccount.type));
|
||||
PreferenceScreen prefs = addPreferencesForType(mAccount.type);
|
||||
if (prefs != null) {
|
||||
updatePreferenceIntents(prefs);
|
||||
}
|
||||
addPreferencesFromResource(R.xml.account_sync_settings);
|
||||
}
|
||||
|
||||
private void updatePreferenceIntents(PreferenceScreen prefs) {
|
||||
for (int i = 0; i < prefs.getPreferenceCount(); i++) {
|
||||
Intent intent = prefs.getPreference(i).getIntent();
|
||||
if (intent != null) {
|
||||
intent.putExtra(ACCOUNT_KEY, mAccount);
|
||||
// This is somewhat of a hack. Since the preference screen we're accessing comes
|
||||
// from another package, we need to modify the intent to launch it with
|
||||
// FLAG_ACTIVITY_NEW_TASK.
|
||||
// TODO: Do something smarter if we ever have PreferenceScreens of our own.
|
||||
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
114
src/com/android/settings/accounts/AddAccountSettings.java
Normal file
114
src/com/android/settings/accounts/AddAccountSettings.java
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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 */);
|
||||
}
|
||||
}
|
233
src/com/android/settings/accounts/ChooseAccountActivity.java
Normal file
233
src/com/android/settings/accounts/ChooseAccountActivity.java
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
46
src/com/android/settings/accounts/ProviderPreference.java
Normal file
46
src/com/android/settings/accounts/ProviderPreference.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 com.android.settings.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.preference.Preference;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
/**
|
||||
* ProviderPreference is used to display an image to the left of a provider name.
|
||||
* The preference ultimately calls AccountManager.addAccount() for the account type.
|
||||
*/
|
||||
public class ProviderPreference extends Preference {
|
||||
private String mAccountType;
|
||||
|
||||
public ProviderPreference(
|
||||
Context context, String accountType, Drawable icon, CharSequence providerName) {
|
||||
super(context);
|
||||
mAccountType = accountType;
|
||||
setIcon(icon);
|
||||
setPersistent(false);
|
||||
setTitle(providerName);
|
||||
}
|
||||
|
||||
public String getAccountType() {
|
||||
return mAccountType;
|
||||
}
|
||||
}
|
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
package com.android.settings.accounts;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* Presents multiple options for handling the case where a sync was aborted because there
|
||||
* were too many pending deletes. One option is to force the delete, another is to rollback
|
||||
* the deletes, the third is to do nothing.
|
||||
*/
|
||||
public class SyncActivityTooManyDeletes extends Activity
|
||||
implements AdapterView.OnItemClickListener {
|
||||
|
||||
private long mNumDeletes;
|
||||
private Account mAccount;
|
||||
private String mAuthority;
|
||||
private String mProvider;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Bundle extras = getIntent().getExtras();
|
||||
if (extras == null) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
mNumDeletes = extras.getLong("numDeletes");
|
||||
mAccount = (Account) extras.getParcelable("account");
|
||||
mAuthority = extras.getString("authority");
|
||||
mProvider = extras.getString("provider");
|
||||
|
||||
// the order of these must match up with the constants for position used in onItemClick
|
||||
CharSequence[] options = new CharSequence[]{
|
||||
getResources().getText(R.string.sync_really_delete),
|
||||
getResources().getText(R.string.sync_undo_deletes),
|
||||
getResources().getText(R.string.sync_do_nothing)
|
||||
};
|
||||
|
||||
ListAdapter adapter = new ArrayAdapter<CharSequence>(this,
|
||||
android.R.layout.simple_list_item_1,
|
||||
android.R.id.text1,
|
||||
options);
|
||||
|
||||
ListView listView = new ListView(this);
|
||||
listView.setAdapter(adapter);
|
||||
listView.setItemsCanFocus(true);
|
||||
listView.setOnItemClickListener(this);
|
||||
|
||||
TextView textView = new TextView(this);
|
||||
CharSequence tooManyDeletesDescFormat =
|
||||
getResources().getText(R.string.sync_too_many_deletes_desc);
|
||||
textView.setText(String.format(tooManyDeletesDescFormat.toString(),
|
||||
mNumDeletes, mProvider, mAccount.name));
|
||||
|
||||
final LinearLayout ll = new LinearLayout(this);
|
||||
ll.setOrientation(LinearLayout.VERTICAL);
|
||||
final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0);
|
||||
ll.addView(textView, lp);
|
||||
ll.addView(listView, lp);
|
||||
|
||||
// TODO: consider displaying the icon of the account type
|
||||
// AuthenticatorDescription[] descs = AccountManager.get(this).getAuthenticatorTypes();
|
||||
// for (AuthenticatorDescription desc : descs) {
|
||||
// if (desc.type.equals(mAccount.type)) {
|
||||
// try {
|
||||
// final Context authContext = createPackageContext(desc.packageName, 0);
|
||||
// ImageView imageView = new ImageView(this);
|
||||
// imageView.setImageDrawable(authContext.getResources().getDrawable(desc.iconId));
|
||||
// ll.addView(imageView, lp);
|
||||
// } catch (PackageManager.NameNotFoundException e) {
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
setContentView(ll);
|
||||
}
|
||||
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
// the constants for position correspond to the items options array in onCreate()
|
||||
if (position == 0) startSyncReallyDelete();
|
||||
else if (position == 1) startSyncUndoDeletes();
|
||||
finish();
|
||||
}
|
||||
|
||||
private void startSyncReallyDelete() {
|
||||
Bundle extras = new Bundle();
|
||||
extras.putBoolean(ContentResolver.SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS, true);
|
||||
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
|
||||
extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
|
||||
extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
|
||||
ContentResolver.requestSync(mAccount, mAuthority, extras);
|
||||
}
|
||||
|
||||
private void startSyncUndoDeletes() {
|
||||
Bundle extras = new Bundle();
|
||||
extras.putBoolean(ContentResolver.SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS, true);
|
||||
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
|
||||
extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
|
||||
extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
|
||||
ContentResolver.requestSync(mAccount, mAuthority, extras);
|
||||
}
|
||||
}
|
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* 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 com.android.settings.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.AnimationDrawable;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.accounts.Account;
|
||||
|
||||
public class SyncStateCheckBoxPreference extends CheckBoxPreference {
|
||||
|
||||
private boolean mIsActive = false;
|
||||
private boolean mIsPending = false;
|
||||
private boolean mFailed = false;
|
||||
private Account mAccount;
|
||||
private String mAuthority;
|
||||
|
||||
/**
|
||||
* A mode for this preference where clicking does a one-time sync instead of
|
||||
* toggling whether the provider will do autosync.
|
||||
*/
|
||||
private boolean mOneTimeSyncMode = false;
|
||||
|
||||
public SyncStateCheckBoxPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setWidgetLayoutResource(R.layout.preference_widget_sync_toggle);
|
||||
mAccount = null;
|
||||
mAuthority = null;
|
||||
}
|
||||
|
||||
public SyncStateCheckBoxPreference(Context context, Account account, String authority) {
|
||||
super(context, null);
|
||||
mAccount = account;
|
||||
mAuthority = authority;
|
||||
setWidgetLayoutResource(R.layout.preference_widget_sync_toggle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindView(View view) {
|
||||
super.onBindView(view);
|
||||
ImageView syncActiveView = (ImageView) view.findViewById(R.id.sync_active);
|
||||
View syncPendingView = view.findViewById(R.id.sync_pending);
|
||||
View syncFailedView = view.findViewById(R.id.sync_failed);
|
||||
|
||||
syncActiveView.setVisibility(mIsActive ? View.VISIBLE : View.GONE);
|
||||
final AnimationDrawable anim = (AnimationDrawable) syncActiveView.getDrawable();
|
||||
boolean showError;
|
||||
boolean showPending;
|
||||
if (mIsActive) {
|
||||
syncActiveView.post(new Runnable() {
|
||||
public void run() {
|
||||
anim.start();
|
||||
}
|
||||
});
|
||||
showPending = false;
|
||||
showError = false;
|
||||
} else {
|
||||
anim.stop();
|
||||
if (mIsPending) {
|
||||
showPending = true;
|
||||
showError = false;
|
||||
} else {
|
||||
showPending = false;
|
||||
showError = mFailed;
|
||||
}
|
||||
}
|
||||
|
||||
syncFailedView.setVisibility(showError ? View.VISIBLE : View.GONE);
|
||||
syncPendingView.setVisibility((showPending && !mIsActive) ? View.VISIBLE : View.GONE);
|
||||
|
||||
View checkBox = view.findViewById(android.R.id.checkbox);
|
||||
if (mOneTimeSyncMode) {
|
||||
checkBox.setVisibility(View.GONE);
|
||||
|
||||
/*
|
||||
* Override the summary. Fill in the %1$s with the existing summary
|
||||
* (what ends up happening is the old summary is shown on the next
|
||||
* line).
|
||||
*/
|
||||
TextView summary = (TextView) view.findViewById(android.R.id.summary);
|
||||
summary.setText(getContext().getString(R.string.sync_one_time_sync, getSummary()));
|
||||
} else {
|
||||
checkBox.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the sync is active.
|
||||
* @param isActive whether or not the sync is active
|
||||
*/
|
||||
public void setActive(boolean isActive) {
|
||||
mIsActive = isActive;
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether a sync is pending.
|
||||
* @param isPending whether or not the sync is pending
|
||||
*/
|
||||
public void setPending(boolean isPending) {
|
||||
mIsPending = isPending;
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the corresponding sync failed.
|
||||
* @param failed whether or not the sync failed
|
||||
*/
|
||||
public void setFailed(boolean failed) {
|
||||
mFailed = failed;
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the preference is in one-time sync mode.
|
||||
*/
|
||||
public void setOneTimeSyncMode(boolean oneTimeSyncMode) {
|
||||
mOneTimeSyncMode = oneTimeSyncMode;
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the preference is in one-time sync mode.
|
||||
*/
|
||||
public boolean isOneTimeSyncMode() {
|
||||
return mOneTimeSyncMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClick() {
|
||||
// When we're in one-time sync mode, we don't want a click to change the
|
||||
// checkbox state
|
||||
if (!mOneTimeSyncMode) {
|
||||
super.onClick();
|
||||
}
|
||||
}
|
||||
|
||||
public Account getAccount() {
|
||||
return mAccount;
|
||||
}
|
||||
|
||||
public String getAuthority() {
|
||||
return mAuthority;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user