ManageAccountsSettings.java revision 13b7d8aa456d451ade4b926e91c5119d43eab489
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.settings.accounts; 18 19import android.accounts.Account; 20import android.accounts.AccountManager; 21import android.accounts.OnAccountsUpdateListener; 22import android.app.ActionBar; 23import android.app.Activity; 24import android.content.ContentResolver; 25import android.content.Intent; 26import android.content.SyncAdapterType; 27import android.content.SyncInfo; 28import android.content.SyncStatusInfo; 29import android.graphics.drawable.Drawable; 30import android.os.Bundle; 31import android.preference.Preference; 32import android.preference.PreferenceActivity; 33import android.preference.PreferenceScreen; 34import android.util.Log; 35import android.view.Gravity; 36import android.view.LayoutInflater; 37import android.view.Menu; 38import android.view.MenuInflater; 39import android.view.MenuItem; 40import android.view.View; 41import android.view.ViewGroup; 42import android.widget.CompoundButton; 43import android.widget.Switch; 44import android.widget.TextView; 45 46import com.android.settings.AccountPreference; 47import com.android.settings.DialogCreatable; 48import com.android.settings.R; 49 50import java.util.ArrayList; 51import java.util.HashSet; 52 53public class ManageAccountsSettings extends AccountPreferenceBase 54 implements OnAccountsUpdateListener, DialogCreatable { 55 56 private static final int MENU_ADD_ACCOUNT = Menu.FIRST; 57 58 private static final int REQUEST_SHOW_SYNC_SETTINGS = 1; 59 60 private String[] mAuthorities; 61 private TextView mErrorInfoView; 62 63 private SettingsDialogFragment mDialogFragment; 64 private Switch mAutoSyncSwitch; 65 66 @Override 67 public void onCreate(Bundle icicle) { 68 super.onCreate(icicle); 69 70 addPreferencesFromResource(R.xml.manage_accounts_settings); 71 setHasOptionsMenu(true); 72 } 73 74 @Override 75 public void onStart() { 76 super.onStart(); 77 AccountManager.get(getActivity()).addOnAccountsUpdatedListener(this, null, true); 78 } 79 80 @Override 81 public View onCreateView(LayoutInflater inflater, ViewGroup container, 82 Bundle savedInstanceState) { 83 final View view = inflater.inflate(R.layout.manage_accounts_screen, container, false); 84 return view; 85 } 86 87 @Override 88 public void onActivityCreated(Bundle savedInstanceState) { 89 super.onActivityCreated(savedInstanceState); 90 91 final Activity activity = getActivity(); 92 final View view = getView(); 93 94 mErrorInfoView = (TextView)view.findViewById(R.id.sync_settings_error_info); 95 mErrorInfoView.setVisibility(View.GONE); 96 97 mAutoSyncSwitch = new Switch(activity); 98 99 // TODO Where to put the switch in tablet multipane layout? 100 final int padding = activity.getResources().getDimensionPixelSize( 101 R.dimen.action_bar_switch_padding); 102 mAutoSyncSwitch.setPadding(0, 0, padding, 0); 103 activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, 104 ActionBar.DISPLAY_SHOW_CUSTOM); 105 activity.getActionBar().setCustomView(mAutoSyncSwitch, new ActionBar.LayoutParams( 106 ActionBar.LayoutParams.WRAP_CONTENT, 107 ActionBar.LayoutParams.WRAP_CONTENT, 108 Gravity.CENTER_VERTICAL | Gravity.RIGHT)); 109 mAutoSyncSwitch.setChecked(ContentResolver.getMasterSyncAutomatically()); 110 mAutoSyncSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 111 @Override 112 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 113 ContentResolver.setMasterSyncAutomatically(isChecked); 114 onSyncStateUpdated(); 115 } 116 }); 117 118 mAuthorities = activity.getIntent().getStringArrayExtra(AUTHORITIES_FILTER_KEY); 119 120 updateAuthDescriptions(); 121 } 122 123 @Override 124 public void onStop() { 125 super.onStop(); 126 AccountManager.get(getActivity()).removeOnAccountsUpdatedListener(this); 127 } 128 129 @Override 130 public boolean onPreferenceTreeClick(PreferenceScreen preferences, Preference preference) { 131 if (preference instanceof AccountPreference) { 132 startAccountSettings((AccountPreference) preference); 133 } else { 134 return false; 135 } 136 return true; 137 } 138 139 private void startAccountSettings(AccountPreference acctPref) { 140 Bundle args = new Bundle(); 141 args.putParcelable(AccountSyncSettings.ACCOUNT_KEY, acctPref.getAccount()); 142 ((PreferenceActivity) getActivity()).startPreferencePanel( 143 AccountSyncSettings.class.getCanonicalName(), args, 144 R.string.account_sync_settings_title, acctPref.getAccount().name, 145 this, REQUEST_SHOW_SYNC_SETTINGS); 146 } 147 148 @Override 149 public void showDialog(int dialogId) { 150 if (mDialogFragment != null) { 151 Log.e(TAG, "Old dialog fragment not null!"); 152 } 153 mDialogFragment = new SettingsDialogFragment(this, dialogId); 154 mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId)); 155 } 156 157 @Override 158 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 159 MenuItem addAccountItem = menu.add(0, MENU_ADD_ACCOUNT, 0, R.string.add_account_label); 160 addAccountItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM 161 | MenuItem.SHOW_AS_ACTION_WITH_TEXT); 162 } 163 164 @Override 165 public boolean onOptionsItemSelected(MenuItem item) { 166 final int itemId = item.getItemId(); 167 if (itemId == MENU_ADD_ACCOUNT) { 168 onAddAccountClicked(); 169 return true; 170 } else { 171 return super.onOptionsItemSelected(item); 172 } 173 } 174 175 @Override 176 protected void onSyncStateUpdated() { 177 // Catch any delayed delivery of update messages 178 if (getActivity() == null) return; 179 // Set background connection state 180 if (mAutoSyncSwitch != null) { 181 mAutoSyncSwitch.setChecked(ContentResolver.getMasterSyncAutomatically()); 182 } 183 184 // iterate over all the preferences, setting the state properly for each 185 SyncInfo currentSync = ContentResolver.getCurrentSync(); 186 187 boolean anySyncFailed = false; // true if sync on any account failed 188 189 // only track userfacing sync adapters when deciding if account is synced or not 190 final SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypes(); 191 HashSet<String> userFacing = new HashSet<String>(); 192 for (int k = 0, n = syncAdapters.length; k < n; k++) { 193 final SyncAdapterType sa = syncAdapters[k]; 194 if (sa.isUserVisible()) { 195 userFacing.add(sa.authority); 196 } 197 } 198 for (int i = 0, count = getPreferenceScreen().getPreferenceCount(); i < count; i++) { 199 Preference pref = getPreferenceScreen().getPreference(i); 200 if (! (pref instanceof AccountPreference)) { 201 continue; 202 } 203 204 AccountPreference accountPref = (AccountPreference) pref; 205 Account account = accountPref.getAccount(); 206 int syncCount = 0; 207 boolean syncIsFailing = false; 208 final ArrayList<String> authorities = accountPref.getAuthorities(); 209 if (authorities != null) { 210 for (String authority : authorities) { 211 SyncStatusInfo status = ContentResolver.getSyncStatus(account, authority); 212 boolean syncEnabled = ContentResolver.getSyncAutomatically(account, authority) 213 && ContentResolver.getMasterSyncAutomatically() 214 && (ContentResolver.getIsSyncable(account, authority) > 0); 215 boolean authorityIsPending = ContentResolver.isSyncPending(account, authority); 216 boolean activelySyncing = currentSync != null 217 && currentSync.authority.equals(authority) 218 && new Account(currentSync.account.name, currentSync.account.type) 219 .equals(account); 220 boolean lastSyncFailed = status != null 221 && syncEnabled 222 && status.lastFailureTime != 0 223 && status.getLastFailureMesgAsInt(0) 224 != ContentResolver.SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS; 225 if (lastSyncFailed && !activelySyncing && !authorityIsPending) { 226 syncIsFailing = true; 227 anySyncFailed = true; 228 } 229 syncCount += syncEnabled && userFacing.contains(authority) ? 1 : 0; 230 } 231 } else { 232 if (Log.isLoggable(TAG, Log.VERBOSE)) { 233 Log.v(TAG, "no syncadapters found for " + account); 234 } 235 } 236 int syncStatus = AccountPreference.SYNC_DISABLED; 237 if (syncIsFailing) { 238 syncStatus = AccountPreference.SYNC_ERROR; 239 } else if (syncCount == 0) { 240 syncStatus = AccountPreference.SYNC_DISABLED; 241 } else if (syncCount > 0) { 242 syncStatus = AccountPreference.SYNC_ENABLED; 243 } 244 accountPref.setSyncStatus(syncStatus); 245 } 246 247 mErrorInfoView.setVisibility(anySyncFailed ? View.VISIBLE : View.GONE); 248 } 249 250 @Override 251 public void onAccountsUpdated(Account[] accounts) { 252 if (getActivity() == null) return; 253 getPreferenceScreen().removeAll(); 254 for (int i = 0, n = accounts.length; i < n; i++) { 255 final Account account = accounts[i]; 256 final ArrayList<String> auths = getAuthoritiesForAccountType(account.type); 257 258 boolean showAccount = true; 259 if (mAuthorities != null && auths != null) { 260 showAccount = false; 261 for (String requestedAuthority : mAuthorities) { 262 if (auths.contains(requestedAuthority)) { 263 showAccount = true; 264 break; 265 } 266 } 267 } 268 269 if (showAccount) { 270 final Drawable icon = getDrawableForType(account.type); 271 final AccountPreference preference = 272 new AccountPreference(getActivity(), account, icon, auths); 273 getPreferenceScreen().addPreference(preference); 274 } 275 } 276 onSyncStateUpdated(); 277 } 278 279 @Override 280 protected void onAuthDescriptionsUpdated() { 281 // Update account icons for all account preference items 282 for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) { 283 AccountPreference pref = (AccountPreference) getPreferenceScreen().getPreference(i); 284 pref.setProviderIcon(getDrawableForType(pref.getAccount().type)); 285 pref.setSummary(getLabelForType(pref.getAccount().type)); 286 } 287 } 288 289 public void onAddAccountClicked() { 290 Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS"); 291 intent.putExtra(AUTHORITIES_FILTER_KEY, mAuthorities); 292 startActivity(intent); 293 } 294} 295