ChooseAccountTypeActivity.java revision a77253a417e885f87280901a3519412262758412
1/*
2 * Copyright (C) 2011 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 */
16package android.accounts;
17
18import android.app.Activity;
19import android.content.Context;
20import android.content.Intent;
21import android.content.pm.PackageManager;
22import android.content.res.Resources;
23import android.graphics.drawable.Drawable;
24import android.os.Bundle;
25import android.util.Log;
26import android.view.LayoutInflater;
27import android.view.View;
28import android.view.ViewGroup;
29import android.widget.AdapterView;
30import android.widget.ArrayAdapter;
31import android.widget.ImageView;
32import android.widget.ListView;
33import android.widget.TextView;
34import com.android.internal.R;
35
36import java.io.IOException;
37import java.util.ArrayList;
38import java.util.HashMap;
39import java.util.HashSet;
40import java.util.Map;
41import java.util.Set;
42
43/**
44 * @hide
45 */
46public class ChooseAccountTypeActivity extends Activity implements AccountManagerCallback<Bundle> {
47    private static final String TAG = "AccountManager";
48
49    private HashMap<String, AuthInfo> mTypeToAuthenticatorInfo = new HashMap<String, AuthInfo>();
50    private ArrayList<AuthInfo> mAuthenticatorInfosToDisplay;
51
52    @Override
53    public void onCreate(Bundle savedInstanceState) {
54        super.onCreate(savedInstanceState);
55        setContentView(R.layout.choose_account_type);
56
57        // Read the validAccountTypes, if present, and add them to the setOfAllowableAccountTypes
58        Set<String> setOfAllowableAccountTypes = null;
59        String[] validAccountTypes = getIntent().getStringArrayExtra(
60                ChooseTypeAndAccountActivity.EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY);
61        if (validAccountTypes != null) {
62            setOfAllowableAccountTypes = new HashSet<String>(validAccountTypes.length);
63            for (String type : validAccountTypes) {
64                setOfAllowableAccountTypes.add(type);
65            }
66        }
67
68        // create a map of account authenticators
69        buildTypeToAuthDescriptionMap();
70
71        // Create a list of authenticators that are allowable. Filter out those that
72        // don't match the allowable account types, if provided.
73        mAuthenticatorInfosToDisplay = new ArrayList<AuthInfo>(mTypeToAuthenticatorInfo.size());
74        for (Map.Entry<String, AuthInfo> entry: mTypeToAuthenticatorInfo.entrySet()) {
75            final String type = entry.getKey();
76            final AuthInfo info = entry.getValue();
77            if (setOfAllowableAccountTypes != null
78                    && !setOfAllowableAccountTypes.contains(type)) {
79                continue;
80            }
81            mAuthenticatorInfosToDisplay.add(info);
82        }
83
84        if (mAuthenticatorInfosToDisplay.isEmpty()) {
85            Bundle bundle = new Bundle();
86            bundle.putString(AccountManager.KEY_ERROR_MESSAGE, "no allowable account types");
87            setResult(Activity.RESULT_OK, new Intent().putExtras(bundle));
88            finish();
89            return;
90        }
91
92        if (mAuthenticatorInfosToDisplay.size() == 1) {
93            runAddAccountForAuthenticator(mAuthenticatorInfosToDisplay.get(0));
94            return;
95        }
96
97        // Setup the list
98        ListView list = (ListView) findViewById(android.R.id.list);
99        // Use an existing ListAdapter that will map an array of strings to TextViews
100        list.setAdapter(new AccountArrayAdapter(this,
101                android.R.layout.simple_list_item_1, mAuthenticatorInfosToDisplay));
102        list.setChoiceMode(ListView.CHOICE_MODE_NONE);
103        list.setTextFilterEnabled(false);
104        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
105            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
106                runAddAccountForAuthenticator(mAuthenticatorInfosToDisplay.get(position));
107            }
108        });
109    }
110
111    private void buildTypeToAuthDescriptionMap() {
112        for(AuthenticatorDescription desc : AccountManager.get(this).getAuthenticatorTypes()) {
113            String name = null;
114            Drawable icon = null;
115            try {
116                Context authContext = createPackageContext(desc.packageName, 0);
117                icon = authContext.getResources().getDrawable(desc.iconId);
118                final CharSequence sequence = authContext.getResources().getText(desc.labelId);
119                if (sequence != null) {
120                    name = sequence.toString();
121                }
122                name = sequence.toString();
123            } catch (PackageManager.NameNotFoundException e) {
124                // Nothing we can do much here, just log
125                if (Log.isLoggable(TAG, Log.WARN)) {
126                    Log.w(TAG, "No icon name for account type " + desc.type);
127                }
128            } catch (Resources.NotFoundException e) {
129                // Nothing we can do much here, just log
130                if (Log.isLoggable(TAG, Log.WARN)) {
131                    Log.w(TAG, "No icon resource for account type " + desc.type);
132                }
133            }
134            AuthInfo authInfo = new AuthInfo(desc, name, icon);
135            mTypeToAuthenticatorInfo.put(desc.type, authInfo);
136        }
137    }
138
139    protected void runAddAccountForAuthenticator(AuthInfo authInfo) {
140        Log.d(TAG, "selected account type " + authInfo.name);
141        final Bundle options = getIntent().getBundleExtra(
142                ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_OPTIONS_BUNDLE);
143        final String[] requiredFeatures = getIntent().getStringArrayExtra(
144                ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_REQUIRED_FEATURES_STRING_ARRAY);
145        final String authTokenType = getIntent().getStringExtra(
146                ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_AUTH_TOKEN_TYPE_STRING);
147        AccountManager.get(this).addAccount(authInfo.desc.type, authTokenType, requiredFeatures,
148                options, this, this, null /* Handler */);
149    }
150
151    public void run(final AccountManagerFuture<Bundle> accountManagerFuture) {
152        try {
153            Bundle accountManagerResult = accountManagerFuture.getResult();
154            Bundle bundle = new Bundle();
155            bundle.putString(AccountManager.KEY_ACCOUNT_NAME,
156                    accountManagerResult.getString(AccountManager.KEY_ACCOUNT_NAME));
157            bundle.putString(AccountManager.KEY_ACCOUNT_TYPE,
158                    accountManagerResult.getString(AccountManager.KEY_ACCOUNT_TYPE));
159            setResult(Activity.RESULT_OK, new Intent().putExtras(bundle));
160            finish();
161            return;
162        } catch (OperationCanceledException e) {
163            setResult(Activity.RESULT_CANCELED);
164            finish();
165            return;
166        } catch (IOException e) {
167        } catch (AuthenticatorException e) {
168        }
169        Bundle bundle = new Bundle();
170        bundle.putString(AccountManager.KEY_ERROR_MESSAGE, "error communicating with server");
171        setResult(Activity.RESULT_OK, new Intent().putExtras(bundle));
172        finish();
173    }
174
175    private static class AuthInfo {
176        final AuthenticatorDescription desc;
177        final String name;
178        final Drawable drawable;
179
180        AuthInfo(AuthenticatorDescription desc, String name, Drawable drawable) {
181            this.desc = desc;
182            this.name = name;
183            this.drawable = drawable;
184        }
185    }
186
187    private static class ViewHolder {
188        ImageView icon;
189        TextView text;
190    }
191
192    private static class AccountArrayAdapter extends ArrayAdapter<AuthInfo> {
193        private LayoutInflater mLayoutInflater;
194        private ArrayList<AuthInfo> mInfos;
195
196        public AccountArrayAdapter(Context context, int textViewResourceId,
197                ArrayList<AuthInfo> infos) {
198            super(context, textViewResourceId, infos);
199            mInfos = infos;
200            mLayoutInflater = (LayoutInflater) context.getSystemService(
201                    Context.LAYOUT_INFLATER_SERVICE);
202        }
203
204        @Override
205        public View getView(int position, View convertView, ViewGroup parent) {
206            ViewHolder holder;
207
208            if (convertView == null) {
209                convertView = mLayoutInflater.inflate(R.layout.choose_account_row, null);
210                holder = new ViewHolder();
211                holder.text = (TextView) convertView.findViewById(R.id.account_row_text);
212                holder.icon = (ImageView) convertView.findViewById(R.id.account_row_icon);
213                convertView.setTag(holder);
214            } else {
215                holder = (ViewHolder) convertView.getTag();
216            }
217
218            holder.text.setText(mInfos.get(position).name);
219            holder.icon.setImageDrawable(mInfos.get(position).drawable);
220
221            return convertView;
222        }
223    }
224}
225