• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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.customlocale;
18 
19 
20 import android.app.ActivityManagerNative;
21 import android.app.IActivityManager;
22 import android.app.ListActivity;
23 import android.content.Intent;
24 import android.content.SharedPreferences;
25 import android.content.res.Configuration;
26 import android.os.Bundle;
27 import android.os.RemoteException;
28 import android.util.Log;
29 import android.view.ContextMenu;
30 import android.view.MenuItem;
31 import android.view.View;
32 import android.view.ContextMenu.ContextMenuInfo;
33 import android.widget.Button;
34 import android.widget.ListAdapter;
35 import android.widget.ListView;
36 import android.widget.SimpleAdapter;
37 import android.widget.TextView;
38 import android.widget.Toast;
39 import android.widget.AdapterView.AdapterContextMenuInfo;
40 
41 import java.util.ArrayList;
42 import java.util.Collections;
43 import java.util.Comparator;
44 import java.util.HashMap;
45 import java.util.Locale;
46 import java.util.Map;
47 
48 /**
49  * Displays the list of system locales as well as maintain a custom list of user
50  * locales. The user can select a locale and apply it or it can create or remove
51  * a custom locale.
52  */
53 public class CustomLocaleActivity extends ListActivity {
54 
55     private static final String CUSTOM_LOCALES_SEP = " ";
56     private static final String CUSTOM_LOCALES = "custom_locales";
57     private static final String KEY_CUSTOM = "custom";
58     private static final String KEY_NAME = "name";
59     private static final String KEY_CODE = "code";
60 
61     private static final String TAG = "LocaleSetup";
62     private static final boolean DEBUG = true;
63 
64     /** Request code returned when the NewLocaleDialog activity finishes. */
65     private static final int UPDATE_LIST = 42;
66     /** Menu item id for applying a locale */
67     private static final int MENU_APPLY = 43;
68     /** Menu item id for removing a custom locale */
69     private static final int MENU_REMOVE = 44;
70 
71     /** List view displaying system and custom locales. */
72     private ListView mListView;
73     /** Textview used to display current locale */
74     private TextView mCurrentLocaleTextView;
75     /** Private shared preferences of this activity. */
76     private SharedPreferences mPrefs;
77 
78     @Override
onCreate(Bundle savedInstanceState)79     protected void onCreate(Bundle savedInstanceState) {
80         super.onCreate(savedInstanceState);
81         setContentView(R.layout.main);
82 
83         mPrefs = getPreferences(MODE_PRIVATE);
84 
85         Button newLocaleButton = (Button) findViewById(R.id.new_locale);
86 
87         newLocaleButton.setOnClickListener(new View.OnClickListener() {
88             public void onClick(View v) {
89                 Intent i = new Intent(CustomLocaleActivity.this, NewLocaleDialog.class);
90                 startActivityForResult(i, UPDATE_LIST);
91             }
92         });
93 
94         mListView = (ListView) findViewById(android.R.id.list);
95         mListView.setFocusable(true);
96         mListView.setFocusableInTouchMode(true);
97         mListView.requestFocus();
98         registerForContextMenu(mListView);
99         setupLocaleList();
100 
101         mCurrentLocaleTextView = (TextView) findViewById(R.id.current_locale);
102         displayCurrentLocale();
103     }
104 
105     @SuppressWarnings("unchecked")
106     @Override
onActivityResult(int requestCode, int resultCode, Intent data)107     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
108         super.onActivityResult(requestCode, resultCode, data);
109 
110         if (requestCode == UPDATE_LIST && resultCode == RESULT_OK && data != null) {
111             String locale = data.getExtras().getString(NewLocaleDialog.INTENT_EXTRA_LOCALE);
112             if (locale != null && locale.length() > 0) {
113                 // Get current custom locale list
114                 String customLocales = mPrefs.getString(CUSTOM_LOCALES, null);
115 
116                 // Update
117                 if (customLocales == null) {
118                     customLocales = locale;
119                 } else {
120                     customLocales += CUSTOM_LOCALES_SEP + locale;
121                 }
122 
123                 // Save prefs
124                 if (DEBUG) {
125                     Log.d(TAG, "add/customLocales: " + customLocales);
126                 }
127                 mPrefs.edit().putString(CUSTOM_LOCALES, customLocales).commit();
128 
129                 Toast.makeText(this, "Added custom locale: " + locale, Toast.LENGTH_SHORT).show();
130 
131                 // Update list view
132                 setupLocaleList();
133 
134                 // Find the item to select it in the list view
135                 ListAdapter a = mListView.getAdapter();
136                 for (int i = 0; i < a.getCount(); i++) {
137                     Object o = a.getItem(i);
138                     if (o instanceof Map<?, ?>) {
139                         String code = ((Map<String, String>) o).get(KEY_CODE);
140                         if (code != null && code.equals(locale)) {
141                             mListView.setSelection(i);
142                             break;
143                         }
144                     }
145                 }
146 
147                 if (data.getExtras().getBoolean(NewLocaleDialog.INTENT_EXTRA_SELECT)) {
148                     selectLocale(locale);
149                 }
150             }
151         }
152     }
153 
setupLocaleList()154     private void setupLocaleList() {
155         if (DEBUG) {
156             Log.d(TAG, "Update locate list");
157         }
158 
159         ArrayList<Map<String, String>> data = new ArrayList<Map<String, String>>();
160 
161         // Insert all system locales
162         String[] locales = getAssets().getLocales();
163         for (String locale : locales) {
164             Locale loc = new Locale(locale);
165 
166             Map<String, String> map = new HashMap<String, String>(1);
167             map.put(KEY_CODE, locale);
168             map.put(KEY_NAME, loc.getDisplayName());
169             data.add(map);
170         }
171         locales = null;
172 
173         // Insert all custom locales
174         String customLocales = mPrefs.getString(CUSTOM_LOCALES, "");
175         if (DEBUG) {
176             Log.d(TAG, "customLocales: " + customLocales);
177         }
178         for (String locale : customLocales.split(CUSTOM_LOCALES_SEP)) {
179             if (locale != null && locale.length() > 0) {
180                 Locale loc = new Locale(locale);
181 
182                 Map<String, String> map = new HashMap<String, String>(1);
183                 map.put(KEY_CODE, locale);
184                 map.put(KEY_NAME, loc.getDisplayName() + " [Custom]");
185                 // the presence of the "custom" key marks it as custom.
186                 map.put(KEY_CUSTOM, "");
187                 data.add(map);
188             }
189         }
190 
191         // Sort all locales by code
192         Collections.sort(data, new Comparator<Map<String, String>>() {
193             public int compare(Map<String, String> lhs, Map<String, String> rhs) {
194                 return lhs.get(KEY_CODE).compareTo(rhs.get(KEY_CODE));
195             }
196         });
197 
198         // Update the list view adapter
199         mListView.setAdapter(new SimpleAdapter(this, data, R.layout.list_item, new String[] {
200                 KEY_CODE, KEY_NAME}, new int[] {R.id.locale_code, R.id.locale_name}));
201     }
202 
203     @SuppressWarnings("unchecked")
204     @Override
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)205     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
206         super.onCreateContextMenu(menu, v, menuInfo);
207 
208         if (menuInfo instanceof AdapterContextMenuInfo) {
209             int position = ((AdapterContextMenuInfo) menuInfo).position;
210             Object o = mListView.getItemAtPosition(position);
211             if (o instanceof Map<?, ?>) {
212                 String locale = ((Map<String, String>) o).get(KEY_CODE);
213                 String custom = ((Map<String, String>) o).get(KEY_CUSTOM);
214 
215                 if (custom == null) {
216                     menu.setHeaderTitle("System Locale");
217                     menu.add(0, MENU_APPLY, 0, "Apply");
218                 } else {
219                     menu.setHeaderTitle("Custom Locale");
220                     menu.add(0, MENU_APPLY, 0, "Apply");
221                     menu.add(0, MENU_REMOVE, 0, "Remove");
222                 }
223             }
224         }
225     }
226 
227     @SuppressWarnings("unchecked")
228     @Override
onContextItemSelected(MenuItem item)229     public boolean onContextItemSelected(MenuItem item) {
230 
231         String pendingLocale = null;
232         boolean is_custom = false;
233 
234         ContextMenuInfo menuInfo = item.getMenuInfo();
235         if (menuInfo instanceof AdapterContextMenuInfo) {
236             int position = ((AdapterContextMenuInfo) menuInfo).position;
237             Object o = mListView.getItemAtPosition(position);
238             if (o instanceof Map<?, ?>) {
239                 pendingLocale = ((Map<String, String>) o).get(KEY_CODE);
240                 is_custom = ((Map<String, String>) o).get(KEY_CUSTOM) != null;
241             }
242         }
243 
244         if (pendingLocale == null) {
245             // should never happen
246             return super.onContextItemSelected(item);
247         }
248 
249         if (item.getItemId() == MENU_REMOVE) {
250             // Get current custom locale list
251             String customLocales = mPrefs.getString(CUSTOM_LOCALES, "");
252 
253             if (DEBUG) {
254                 Log.d(TAG, "Remove " + pendingLocale + " from custom locales: " + customLocales);
255             }
256 
257             // Update
258             StringBuilder sb = new StringBuilder();
259             for (String locale : customLocales.split(CUSTOM_LOCALES_SEP)) {
260                 if (locale != null && locale.length() > 0 && !locale.equals(pendingLocale)) {
261                     if (sb.length() > 0) {
262                         sb.append(CUSTOM_LOCALES_SEP);
263                     }
264                     sb.append(locale);
265                 }
266             }
267             String newLocales = sb.toString();
268             if (!newLocales.equals(customLocales)) {
269                 // Save prefs
270                 mPrefs.edit().putString(CUSTOM_LOCALES, customLocales).commit();
271 
272                 Toast.makeText(this, "Removed custom locale: " + pendingLocale, Toast.LENGTH_SHORT)
273                         .show();
274             }
275 
276         } else if (item.getItemId() == MENU_APPLY) {
277             selectLocale(pendingLocale);
278         }
279 
280         return super.onContextItemSelected(item);
281     }
282 
selectLocale(String locale)283     private void selectLocale(String locale) {
284         if (DEBUG) {
285             Log.d(TAG, "Select locale " + locale);
286         }
287 
288         try {
289             IActivityManager am = ActivityManagerNative.getDefault();
290             Configuration config = am.getConfiguration();
291 
292             Locale loc = null;
293 
294             String[] langCountry = locale.split("_");
295             if (langCountry.length == 2) {
296                 loc = new Locale(langCountry[0], langCountry[1]);
297             } else {
298                 loc = new Locale(locale);
299             }
300 
301             config.locale = loc;
302 
303             // indicate this isn't some passing default - the user wants this
304             // remembered
305             config.userSetLocale = true;
306 
307             am.updateConfiguration(config);
308 
309             Toast.makeText(this, "Select locale: " + locale, Toast.LENGTH_SHORT).show();
310         } catch (RemoteException e) {
311             if (DEBUG) {
312                 Log.e(TAG, "Select locale failed", e);
313             }
314         }
315     }
316 
displayCurrentLocale()317     private void displayCurrentLocale() {
318         try {
319             IActivityManager am = ActivityManagerNative.getDefault();
320             Configuration config = am.getConfiguration();
321 
322             if (config.locale != null) {
323                 String text = String.format("%s - %s",
324                         config.locale.toString(),
325                         config.locale.getDisplayName());
326                 mCurrentLocaleTextView.setText(text);
327             }
328         } catch (RemoteException e) {
329             if (DEBUG) {
330                 Log.e(TAG, "get current locale failed", e);
331             }
332         }
333     }
334 }
335