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