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