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 17 package com.android.settings; 18 19 import java.util.ArrayList; 20 import java.util.HashMap; 21 import java.util.Map; 22 23 import com.google.android.collect.Maps; 24 25 import android.accounts.Account; 26 import android.accounts.AccountManager; 27 import android.accounts.AuthenticatorDescription; 28 import android.accounts.OnAccountsUpdateListener; 29 import android.content.ContentResolver; 30 import android.content.Context; 31 import android.content.SyncAdapterType; 32 import android.content.SyncStatusObserver; 33 import android.content.pm.PackageManager; 34 import android.graphics.drawable.Drawable; 35 import android.os.Bundle; 36 import android.os.Handler; 37 import android.preference.PreferenceActivity; 38 import android.preference.PreferenceScreen; 39 import android.util.Log; 40 41 class AccountPreferenceBase extends PreferenceActivity implements OnAccountsUpdateListener { 42 protected static final String TAG = "AccountSettings"; 43 public static final String AUTHORITIES_FILTER_KEY = "authorities"; 44 private static final boolean LDEBUG = Log.isLoggable(TAG, Log.DEBUG);; 45 private Map<String, AuthenticatorDescription> mTypeToAuthDescription 46 = new HashMap<String, AuthenticatorDescription>(); 47 protected AuthenticatorDescription[] mAuthDescs; 48 private final Handler mHandler = new Handler(); 49 private Object mStatusChangeListenerHandle; 50 private HashMap<String, ArrayList<String>> mAccountTypeToAuthorities = null; 51 52 @Override 53 public void onCreate(Bundle icicle) { 54 super.onCreate(icicle); 55 } 56 57 /** 58 * Overload to handle account updates. 59 */ 60 public void onAccountsUpdated(Account[] accounts) { 61 62 } 63 64 /** 65 * Overload to handle authenticator description updates 66 */ 67 protected void onAuthDescriptionsUpdated() { 68 69 } 70 71 /** 72 * Overload to handle sync state updates. 73 */ 74 protected void onSyncStateUpdated() { 75 76 } 77 78 @Override 79 protected void onResume() { 80 super.onResume(); 81 mStatusChangeListenerHandle = ContentResolver.addStatusChangeListener( 82 ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE 83 | ContentResolver.SYNC_OBSERVER_TYPE_STATUS 84 | ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, 85 mSyncStatusObserver); 86 onSyncStateUpdated(); 87 } 88 89 @Override 90 protected void onPause() { 91 super.onPause(); 92 ContentResolver.removeStatusChangeListener(mStatusChangeListenerHandle); 93 } 94 95 96 private SyncStatusObserver mSyncStatusObserver = new SyncStatusObserver() { 97 public void onStatusChanged(int which) { 98 mHandler.post(new Runnable() { 99 public void run() { 100 onSyncStateUpdated(); 101 } 102 }); 103 } 104 }; 105 106 public ArrayList<String> getAuthoritiesForAccountType(String type) { 107 if (mAccountTypeToAuthorities == null) { 108 mAccountTypeToAuthorities = Maps.newHashMap(); 109 SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypes(); 110 for (int i = 0, n = syncAdapters.length; i < n; i++) { 111 final SyncAdapterType sa = syncAdapters[i]; 112 ArrayList<String> authorities = mAccountTypeToAuthorities.get(sa.accountType); 113 if (authorities == null) { 114 authorities = new ArrayList<String>(); 115 mAccountTypeToAuthorities.put(sa.accountType, authorities); 116 } 117 if (LDEBUG) { 118 Log.d(TAG, "added authority " + sa.authority + " to accountType " 119 + sa.accountType); 120 } 121 authorities.add(sa.authority); 122 } 123 } 124 return mAccountTypeToAuthorities.get(type); 125 } 126 127 /** 128 * Gets an icon associated with a particular account type. If none found, return null. 129 * @param accountType the type of account 130 * @return a drawable for the icon or null if one cannot be found. 131 */ 132 protected Drawable getDrawableForType(final String accountType) { 133 Drawable icon = null; 134 if (mTypeToAuthDescription.containsKey(accountType)) { 135 try { 136 AuthenticatorDescription desc = (AuthenticatorDescription) 137 mTypeToAuthDescription.get(accountType); 138 Context authContext = createPackageContext(desc.packageName, 0); 139 icon = authContext.getResources().getDrawable(desc.iconId); 140 } catch (PackageManager.NameNotFoundException e) { 141 // TODO: place holder icon for missing account icons? 142 Log.w(TAG, "No icon for account type " + accountType); 143 } 144 } 145 return icon; 146 } 147 148 /** 149 * Gets the label associated with a particular account type. If none found, return null. 150 * @param accountType the type of account 151 * @return a CharSequence for the label or null if one cannot be found. 152 */ 153 protected CharSequence getLabelForType(final String accountType) { 154 CharSequence label = null; 155 if (mTypeToAuthDescription.containsKey(accountType)) { 156 try { 157 AuthenticatorDescription desc = (AuthenticatorDescription) 158 mTypeToAuthDescription.get(accountType); 159 Context authContext = createPackageContext(desc.packageName, 0); 160 label = authContext.getResources().getText(desc.labelId); 161 } catch (PackageManager.NameNotFoundException e) { 162 Log.w(TAG, "No label for account type " + ", type " + accountType); 163 } 164 } 165 return label; 166 } 167 168 /** 169 * Gets the preferences.xml file associated with a particular account type. 170 * @param accountType the type of account 171 * @return a PreferenceScreen inflated from accountPreferenceId. 172 */ 173 protected PreferenceScreen addPreferencesForType(final String accountType) { 174 PreferenceScreen prefs = null; 175 if (mTypeToAuthDescription.containsKey(accountType)) { 176 AuthenticatorDescription desc = null; 177 try { 178 desc = (AuthenticatorDescription) mTypeToAuthDescription.get(accountType); 179 if (desc != null && desc.accountPreferencesId != 0) { 180 Context authContext = createPackageContext(desc.packageName, 0); 181 prefs = getPreferenceManager().inflateFromResource(authContext, 182 desc.accountPreferencesId, getPreferenceScreen()); 183 } 184 } catch (PackageManager.NameNotFoundException e) { 185 Log.w(TAG, "Couldn't load preferences.xml file from " + desc.packageName); 186 } 187 } 188 return prefs; 189 } 190 191 /** 192 * Updates provider icons. Subclasses should call this in onCreate() 193 * and update any UI that depends on AuthenticatorDescriptions in onAuthDescriptionsUpdated(). 194 */ 195 protected void updateAuthDescriptions() { 196 mAuthDescs = AccountManager.get(this).getAuthenticatorTypes(); 197 for (int i = 0; i < mAuthDescs.length; i++) { 198 mTypeToAuthDescription.put(mAuthDescs[i].type, mAuthDescs[i]); 199 } 200 onAuthDescriptionsUpdated(); 201 } 202 } 203