development
修訂 | 86ed8b3937f631ba3e8a04d20171dfda25c994c1 (tree) |
---|---|
時間 | 2011-02-02 07:50:47 |
作者 | Raphael Moll <ralf@andr...> |
Commiter | Android Git Automerger |
am ae431044: am 33d8964c: am e3ec8442: am 2fa9bd29: Merge "Revamped CustomLocale for the SDK."
* commit 'ae43104493bfe8271e5b1efc809ae06f8ecea893':
@@ -13,25 +13,40 @@ | ||
13 | 13 | See the License for the specific language governing permissions and |
14 | 14 | limitations under the License. |
15 | 15 | --> |
16 | + | |
16 | 17 | <manifest |
17 | 18 | xmlns:android="http://schemas.android.com/apk/res/android" |
18 | 19 | android:versionCode="1" |
19 | - android:versionName="1.0" package="com.android.customlocale"> | |
20 | + android:versionName="1.0" | |
21 | + package="com.android.customlocale2" | |
22 | + > | |
23 | + | |
24 | + <uses-sdk android:minSdkVersion="3" /> | |
25 | + | |
26 | + <uses-permission android:name="android.permission.WRITE_SETTINGS" /> | |
27 | + <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" /> | |
28 | + | |
20 | 29 | <application |
21 | 30 | android:icon="@drawable/icon" |
22 | - android:label="@string/app_name"> | |
31 | + android:label="@string/app_name" > | |
32 | + | |
23 | 33 | <activity |
24 | - android:label="@string/app_name" android:name="CustomLocaleActivity"> | |
34 | + android:label="@string/app_name" | |
35 | + android:name="CustomLocaleActivity" > | |
25 | 36 | <intent-filter> |
26 | 37 | <action android:name="android.intent.action.MAIN" /> |
27 | 38 | <category android:name="android.intent.category.LAUNCHER" /> |
28 | 39 | </intent-filter> |
29 | 40 | </activity> |
41 | + | |
30 | 42 | <activity |
31 | - android:name="NewLocaleDialog" | |
32 | - android:theme="@android:style/Theme.Dialog" /> | |
43 | + android:theme="@android:style/Theme.Dialog" | |
44 | + android:name="NewLocaleDialog" /> | |
45 | + | |
46 | + <receiver android:name="CustomLocaleReceiver" > | |
47 | + <intent-filter> | |
48 | + <action android:name="com.android.intent.action.SET_LOCALE" /> | |
49 | + </intent-filter> | |
50 | + </receiver> | |
33 | 51 | </application> |
34 | - <uses-sdk android:minSdkVersion="3" /> | |
35 | - <uses-permission android:name="android.permission.WRITE_SETTINGS" /> | |
36 | - <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" /> | |
37 | 52 | </manifest> |
@@ -1,35 +0,0 @@ | ||
1 | -<?xml version="1.0" encoding="utf-8"?> | |
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 | -<LinearLayout | |
17 | - xmlns:android="http://schemas.android.com/apk/res/android" | |
18 | - android:layout_width="match_parent" | |
19 | - android:layout_height="wrap_content" | |
20 | - android:padding="5dip"> | |
21 | - <TextView | |
22 | - android:id="@+id/locale_code" | |
23 | - android:layout_width="match_parent" | |
24 | - android:layout_height="wrap_content" | |
25 | - android:textAppearance="?android:textAppearanceLarge" | |
26 | - android:layout_weight="1" | |
27 | - android:text="@string/locale_default" /> | |
28 | - <TextView | |
29 | - xmlns:android="http://schemas.android.com/apk/res/android" | |
30 | - android:id="@+id/locale_name" | |
31 | - android:layout_width="match_parent" | |
32 | - android:layout_height="wrap_content" | |
33 | - android:textAppearance="?android:textAppearance" | |
34 | - android:layout_weight="1" /> | |
35 | -</LinearLayout> | |
\ No newline at end of file |
@@ -17,7 +17,8 @@ | ||
17 | 17 | xmlns:android="http://schemas.android.com/apk/res/android" |
18 | 18 | android:orientation="vertical" |
19 | 19 | android:layout_width="match_parent" |
20 | - android:layout_height="match_parent"> | |
20 | + android:layout_height="match_parent" | |
21 | + > | |
21 | 22 | <TextView |
22 | 23 | android:layout_width="match_parent" |
23 | 24 | android:layout_height="wrap_content" |
@@ -25,13 +26,15 @@ | ||
25 | 26 | android:text="@string/header_current_locale" |
26 | 27 | android:textAppearance="@style/TextAppearance.header" |
27 | 28 | android:gravity="center_horizontal" |
28 | - android:background="@color/header_background" /> | |
29 | + android:background="@color/header_background" | |
30 | + /> | |
29 | 31 | <TextView |
30 | 32 | android:id="@+id/current_locale" |
31 | 33 | android:layout_width="match_parent" |
32 | 34 | android:layout_height="wrap_content" |
33 | 35 | android:layout_weight="0" |
34 | - android:padding="5dip" /> | |
36 | + android:padding="5dip" | |
37 | + /> | |
35 | 38 | <TextView |
36 | 39 | android:layout_width="match_parent" |
37 | 40 | android:layout_height="wrap_content" |
@@ -39,24 +42,61 @@ | ||
39 | 42 | android:text="@string/header_locale_list" |
40 | 43 | android:textAppearance="@style/TextAppearance.header" |
41 | 44 | android:gravity="center_horizontal" |
42 | - android:background="@color/header_background" /> | |
43 | - <ListView | |
44 | - android:id="@id/android:list" | |
45 | + android:background="@color/header_background" | |
46 | + /> | |
47 | + | |
48 | + <FrameLayout | |
45 | 49 | android:layout_width="match_parent" |
46 | 50 | android:layout_height="match_parent" |
47 | 51 | android:layout_weight="1" |
48 | - android:padding="8dip" /> | |
49 | - <TextView | |
50 | - android:id="@id/android:empty" | |
51 | - android:layout_width="match_parent" | |
52 | - android:layout_height="match_parent" | |
53 | - android:text="@string/no_data_label" /> | |
54 | - <Button | |
55 | - android:id="@+id/new_locale" | |
52 | + > | |
53 | + <ListView | |
54 | + android:id="@id/android:list" | |
55 | + android:layout_width="match_parent" | |
56 | + android:layout_height="match_parent" | |
57 | + android:fastScrollEnabled="true" | |
58 | + android:focusable="true" | |
59 | + android:focusableInTouchMode="true" | |
60 | + android:padding="8dip" | |
61 | + /> | |
62 | + <TextView | |
63 | + android:id="@id/android:empty" | |
64 | + android:layout_width="match_parent" | |
65 | + android:layout_height="match_parent" | |
66 | + android:text="@string/no_data_label" | |
67 | + android:gravity="center" | |
68 | + /> | |
69 | + </FrameLayout> | |
70 | + | |
71 | + <LinearLayout | |
56 | 72 | android:layout_width="match_parent" |
57 | 73 | android:layout_height="wrap_content" |
58 | 74 | android:layout_weight="0" |
59 | - android:paddingLeft="8dip" | |
60 | - android:paddingRight="8dip" | |
61 | - android:text="@string/add_new_locale_button" /> | |
75 | + > | |
76 | + <Button | |
77 | + android:id="@+id/select_locale_button" | |
78 | + android:layout_width="match_parent" | |
79 | + android:layout_height="wrap_content" | |
80 | + android:layout_weight="0.9" | |
81 | + android:layout_gravity="center_vertical" | |
82 | + android:text="@string/select_locale_button" | |
83 | + /> | |
84 | + <Button | |
85 | + android:id="@+id/add_new_locale_button" | |
86 | + android:layout_width="match_parent" | |
87 | + android:layout_height="wrap_content" | |
88 | + android:layout_weight="1" | |
89 | + android:layout_gravity="center_vertical" | |
90 | + android:text="@string/add_new_locale_button" | |
91 | + /> | |
92 | + <Button | |
93 | + android:id="@+id/remove_locale_button" | |
94 | + android:layout_width="match_parent" | |
95 | + android:layout_height="wrap_content" | |
96 | + android:layout_weight="1" | |
97 | + android:layout_marginLeft="5dip" | |
98 | + android:layout_gravity="center_vertical" | |
99 | + android:text="@string/remove_locale_button" | |
100 | + /> | |
101 | + </LinearLayout> | |
62 | 102 | </LinearLayout> |
@@ -15,11 +15,34 @@ | ||
15 | 15 | --> |
16 | 16 | <resources> |
17 | 17 | <string name="app_name">Locales Personalisées</string> |
18 | - <string name="add_new_locale_button">Ajouter une nouvelle locale</string> | |
19 | - <string name="new_locale_label">Code de la nouvelle locale:</string> | |
20 | - <string name="add_button">Ajouter</string> | |
21 | - <string name="no_data_label">Aucune locale</string> | |
18 | + | |
19 | + <!-- Top labels in CustomLocaleActivity --> | |
20 | + | |
22 | 21 | <string name="header_current_locale">Locale courrante</string> |
23 | 22 | <string name="header_locale_list">Liste des locales</string> |
24 | - <string name="add_select_button">Ajouter et sélectionner</string> | |
23 | + <string name="no_data_label">Aucune locale</string> | |
24 | + | |
25 | + <!-- Buttons in CustomLocaleActivity --> | |
26 | + | |
27 | + <string name="select_locale_button">Choisir</string> | |
28 | + <string name="select_locale_1s_button">Choisir \'%1$s\'</string> | |
29 | + <string name="add_new_locale_button">Ajouter\u2026</string> | |
30 | + <string name="remove_locale_button">Retirer\u2026</string> | |
31 | + | |
32 | + <!-- Toast status in CustomLocaleActivity --> | |
33 | + | |
34 | + <string name="removed_custom_locale_1s">Locale supprimée: %1$s</string> | |
35 | + <string name="select_locale_1s">Locale choisie: %1$s</string> | |
36 | + <string name="added_custom_locale_1s">Locale ajoutée: %1$s</string> | |
37 | + | |
38 | + <!-- NewLocaleDialog --> | |
39 | + | |
40 | + <string name="new_locale_label">Code de la nouvelle locale:</string> | |
41 | + <string name="add_button">Ajouter</string> | |
42 | + <string name="add_select_button">Ajouter et choisir</string> | |
43 | + | |
44 | + <string name="confirm_remove_locale_1s">Voulez-vous supprimer la locale personalisée \'%1$s\' ?</string> | |
45 | + <string name="confirm_remove_locale_yes">Oui</string> | |
46 | + <string name="confirm_remove_locale_no">Non</string> | |
47 | + | |
25 | 48 | </resources> |
@@ -15,12 +15,37 @@ | ||
15 | 15 | --> |
16 | 16 | <resources> |
17 | 17 | <string name="app_name">Custom Locale</string> |
18 | - <string name="locale_default">ex_EX</string> | |
19 | - <string name="add_new_locale_button">Add New Locale</string> | |
20 | - <string name="new_locale_label">New locale code:</string> | |
21 | - <string name="add_button">Add</string> | |
22 | - <string name="no_data_label">No data</string> | |
18 | + | |
19 | + <!-- Top labels in CustomLocaleActivity --> | |
20 | + | |
23 | 21 | <string name="header_current_locale">Current Locale</string> |
24 | 22 | <string name="header_locale_list">Locale List</string> |
23 | + <string name="no_data_label">No data</string> | |
24 | + | |
25 | + <!-- Buttons in CustomLocaleActivity --> | |
26 | + | |
27 | + <string name="select_locale_button">Select</string> | |
28 | + <string name="select_locale_1s_button">Select \'%1$s\'</string> | |
29 | + <string name="add_new_locale_button">Add New\u2026</string> | |
30 | + <string name="remove_locale_button">Remove\u2026</string> | |
31 | + | |
32 | + <!-- Toast status in CustomLocaleActivity --> | |
33 | + | |
34 | + <string name="removed_custom_locale_1s">Removed custom locale: %1$s</string> | |
35 | + <string name="select_locale_1s">Select locale: %1$s</string> | |
36 | + <string name="added_custom_locale_1s">Added custom locale: %1$s</string> | |
37 | + | |
38 | + <!-- NewLocaleDialog --> | |
39 | + | |
40 | + <string name="new_locale_label">New locale code:</string> | |
41 | + <string name="add_button">Add</string> | |
25 | 42 | <string name="add_select_button">Add and Select</string> |
43 | + | |
44 | + <string name="confirm_remove_locale_1s">Do you want to remove the custom locale \'%1$s\'?</string> | |
45 | + <string name="confirm_remove_locale_yes">Yes</string> | |
46 | + <string name="confirm_remove_locale_no">No</string> | |
47 | + | |
48 | + <!-- Locale hint in textfield. Not translated --> | |
49 | + <string name="locale_default">ex_EX</string> | |
50 | + | |
26 | 51 | </resources> |
@@ -1,334 +0,0 @@ | ||
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 | |
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 | |
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 | - | |
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 | |
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 | |
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 | - | |
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 | - | |
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 | -} |
@@ -0,0 +1,78 @@ | ||
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 | + | |
17 | +package com.android.customlocale2; | |
18 | + | |
19 | + | |
20 | +import java.util.Locale; | |
21 | + | |
22 | +import android.app.ActivityManagerNative; | |
23 | +import android.app.IActivityManager; | |
24 | +import android.content.res.Configuration; | |
25 | +import android.os.RemoteException; | |
26 | +import android.util.Log; | |
27 | + | |
28 | +/** | |
29 | + * Helper class to change the system locale. | |
30 | + */ | |
31 | +public final class ChangeLocale { | |
32 | + | |
33 | + private static final String TAG = ChangeLocale.class.getSimpleName(); | |
34 | + private static final boolean DEBUG = true; | |
35 | + | |
36 | + /** | |
37 | + * Sets the system locale to the new one specified. | |
38 | + * | |
39 | + * @param locale A locale name in the form "ab_AB". Must not be null or empty. | |
40 | + * @return True if the locale was succesfully changed. | |
41 | + */ | |
42 | + public static boolean changeSystemLocale(String locale) { | |
43 | + if (DEBUG) { | |
44 | + Log.d(TAG, "Change locale to: " + locale); | |
45 | + } | |
46 | + | |
47 | + try { | |
48 | + IActivityManager am = ActivityManagerNative.getDefault(); | |
49 | + Configuration config = am.getConfiguration(); | |
50 | + | |
51 | + Locale loc = null; | |
52 | + | |
53 | + String[] langCountry = locale.split("_"); | |
54 | + if (langCountry.length == 2) { | |
55 | + loc = new Locale(langCountry[0], langCountry[1]); | |
56 | + } else { | |
57 | + loc = new Locale(locale); | |
58 | + } | |
59 | + | |
60 | + config.locale = loc; | |
61 | + | |
62 | + // indicate this isn't some passing default - the user wants this | |
63 | + // remembered | |
64 | + config.userSetLocale = true; | |
65 | + | |
66 | + am.updateConfiguration(config); | |
67 | + | |
68 | + return true; | |
69 | + | |
70 | + } catch (RemoteException e) { | |
71 | + if (DEBUG) { | |
72 | + Log.e(TAG, "Change locale failed", e); | |
73 | + } | |
74 | + } | |
75 | + | |
76 | + return false; | |
77 | + } | |
78 | +} |
@@ -0,0 +1,454 @@ | ||
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.customlocale2; | |
18 | + | |
19 | + | |
20 | +import java.util.ArrayList; | |
21 | +import java.util.Collections; | |
22 | +import java.util.Comparator; | |
23 | +import java.util.Locale; | |
24 | + | |
25 | +import android.app.ActivityManagerNative; | |
26 | +import android.app.AlertDialog; | |
27 | +import android.app.Dialog; | |
28 | +import android.app.IActivityManager; | |
29 | +import android.app.ListActivity; | |
30 | +import android.content.DialogInterface; | |
31 | +import android.content.Intent; | |
32 | +import android.content.SharedPreferences; | |
33 | +import android.content.res.Configuration; | |
34 | +import android.os.Bundle; | |
35 | +import android.os.RemoteException; | |
36 | +import android.util.Log; | |
37 | +import android.view.ContextMenu; | |
38 | +import android.view.View; | |
39 | +import android.view.ContextMenu.ContextMenuInfo; | |
40 | +import android.widget.ArrayAdapter; | |
41 | +import android.widget.Button; | |
42 | +import android.widget.ListAdapter; | |
43 | +import android.widget.ListView; | |
44 | +import android.widget.TextView; | |
45 | +import android.widget.Toast; | |
46 | +import android.widget.AdapterView.AdapterContextMenuInfo; | |
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 TAG = "CustomLocale"; | |
56 | + private static final boolean DEBUG = true; | |
57 | + | |
58 | + private static final int DLG_REMOVE_ID = 0; | |
59 | + | |
60 | + private static final String CUSTOM_LOCALES_SEP = " "; | |
61 | + private static final String CUSTOM_LOCALES = "custom_locales"; | |
62 | + | |
63 | + /** Request code returned when the NewLocaleDialog activity finishes. */ | |
64 | + private static final int UPDATE_LIST = 42; | |
65 | + /** Menu item id for applying a locale */ | |
66 | + private static final int MENU_APPLY = 43; | |
67 | + /** Menu item id for removing a custom locale */ | |
68 | + private static final int MENU_REMOVE = 44; | |
69 | + | |
70 | + /** List view displaying system and custom locales. */ | |
71 | + private ListView mListView; | |
72 | + /** Textview used to display current locale */ | |
73 | + private TextView mCurrentLocaleTextView; | |
74 | + /** Private shared preferences of this activity. */ | |
75 | + private SharedPreferences mPrefs; | |
76 | + | |
77 | + private Button mRemoveLocaleButton; | |
78 | + private Button mSelectLocaleButton; | |
79 | + | |
80 | + @Override | |
81 | + protected void onCreate(Bundle savedInstanceState) { | |
82 | + super.onCreate(savedInstanceState); | |
83 | + setContentView(R.layout.main); | |
84 | + | |
85 | + mPrefs = getPreferences(MODE_PRIVATE); | |
86 | + | |
87 | + Button addLocaleButton = (Button) findViewById(R.id.add_new_locale_button); | |
88 | + mRemoveLocaleButton = (Button) findViewById(R.id.remove_locale_button); | |
89 | + mSelectLocaleButton = (Button) findViewById(R.id.select_locale_button); | |
90 | + | |
91 | + addLocaleButton.setOnClickListener(new View.OnClickListener() { | |
92 | + public void onClick(View v) { | |
93 | + onAddNewLocale(); | |
94 | + } | |
95 | + }); | |
96 | + | |
97 | + mRemoveLocaleButton.setOnClickListener(new View.OnClickListener() { | |
98 | + @Override | |
99 | + public void onClick(View v) { | |
100 | + showDialog(DLG_REMOVE_ID); | |
101 | + } | |
102 | + }); | |
103 | + | |
104 | + mSelectLocaleButton.setOnClickListener(new View.OnClickListener() { | |
105 | + @Override | |
106 | + public void onClick(View v) { | |
107 | + onSelectLocale(); | |
108 | + } | |
109 | + }); | |
110 | + | |
111 | + mListView = (ListView) findViewById(android.R.id.list); | |
112 | + mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); | |
113 | + mListView.setItemsCanFocus(false); | |
114 | + mListView.setFocusable(true); | |
115 | + mListView.setFocusableInTouchMode(true); | |
116 | + mListView.requestFocus(); | |
117 | + setupLocaleList(); | |
118 | + | |
119 | + mCurrentLocaleTextView = (TextView) findViewById(R.id.current_locale); | |
120 | + displayCurrentLocale(); | |
121 | + } | |
122 | + | |
123 | + @Override | |
124 | + protected void onResume() { | |
125 | + super.onResume(); | |
126 | + updateLocaleButtons(); | |
127 | + } | |
128 | + | |
129 | + @Override | |
130 | + protected void onActivityResult(int requestCode, int resultCode, Intent data) { | |
131 | + super.onActivityResult(requestCode, resultCode, data); | |
132 | + | |
133 | + if (requestCode == UPDATE_LIST && resultCode == RESULT_OK && data != null) { | |
134 | + String locale = data.getExtras().getString(NewLocaleDialog.INTENT_EXTRA_LOCALE); | |
135 | + if (locale != null && locale.length() > 0) { | |
136 | + // Get current custom locale list | |
137 | + String customLocales = mPrefs.getString(CUSTOM_LOCALES, null); | |
138 | + | |
139 | + // Update | |
140 | + if (customLocales == null) { | |
141 | + customLocales = locale; | |
142 | + } else { | |
143 | + customLocales += CUSTOM_LOCALES_SEP + locale; | |
144 | + } | |
145 | + | |
146 | + // Save prefs | |
147 | + if (DEBUG) { | |
148 | + Log.d(TAG, "add/customLocales: " + customLocales); | |
149 | + } | |
150 | + mPrefs.edit().putString(CUSTOM_LOCALES, customLocales).commit(); | |
151 | + | |
152 | + Toast.makeText(this, | |
153 | + getString(R.string.added_custom_locale_1s, locale), | |
154 | + Toast.LENGTH_SHORT) | |
155 | + .show(); | |
156 | + | |
157 | + // Update list view | |
158 | + setupLocaleList(); | |
159 | + | |
160 | + // Find the item to select it in the list view | |
161 | + checkLocaleInList(locale); | |
162 | + | |
163 | + if (data.getExtras().getBoolean(NewLocaleDialog.INTENT_EXTRA_SELECT)) { | |
164 | + changeSystemLocale(locale); | |
165 | + } | |
166 | + } | |
167 | + } | |
168 | + } | |
169 | + | |
170 | + @Override | |
171 | + protected void onListItemClick(ListView l, View v, int position, long id) { | |
172 | + super.onListItemClick(l, v, position, id); | |
173 | + updateLocaleButtons(); | |
174 | + } | |
175 | + | |
176 | + @Override | |
177 | + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { | |
178 | + super.onCreateContextMenu(menu, v, menuInfo); | |
179 | + | |
180 | + if (menuInfo instanceof AdapterContextMenuInfo) { | |
181 | + int position = ((AdapterContextMenuInfo) menuInfo).position; | |
182 | + Object o = mListView.getItemAtPosition(position); | |
183 | + if (o instanceof LocaleInfo) { | |
184 | + if (((LocaleInfo) o).isCustom()) { | |
185 | + menu.setHeaderTitle("System Locale"); | |
186 | + menu.add(0, MENU_APPLY, 0, "Apply"); | |
187 | + } else { | |
188 | + menu.setHeaderTitle("Custom Locale"); | |
189 | + menu.add(0, MENU_APPLY, 0, "Apply"); | |
190 | + menu.add(0, MENU_REMOVE, 0, "Remove"); | |
191 | + } | |
192 | + } | |
193 | + } | |
194 | + } | |
195 | + | |
196 | + @Override | |
197 | + protected Dialog onCreateDialog(int id) { | |
198 | + if (id == DLG_REMOVE_ID) { | |
199 | + return createRemoveLocaleDialog(); | |
200 | + } | |
201 | + return super.onCreateDialog(id); | |
202 | + } | |
203 | + | |
204 | + //--- private parts --- | |
205 | + | |
206 | + private void setupLocaleList() { | |
207 | + if (DEBUG) { | |
208 | + Log.d(TAG, "Update locate list"); | |
209 | + } | |
210 | + | |
211 | + ArrayList<LocaleInfo> data = new ArrayList<LocaleInfo>(); | |
212 | + | |
213 | + // Insert all system locales | |
214 | + String[] locales = getAssets().getLocales(); | |
215 | + for (String locale : locales) { | |
216 | + if (locale != null && locale.length() > 0) { | |
217 | + Locale loc = new Locale(locale); | |
218 | + data.add(new LocaleInfo(locale, loc.getDisplayName())); | |
219 | + } | |
220 | + } | |
221 | + locales = null; | |
222 | + | |
223 | + // Insert all custom locales | |
224 | + String customLocales = mPrefs.getString(CUSTOM_LOCALES, ""); | |
225 | + if (DEBUG) { | |
226 | + Log.d(TAG, "customLocales: " + customLocales); | |
227 | + } | |
228 | + for (String locale : customLocales.split(CUSTOM_LOCALES_SEP)) { | |
229 | + if (locale != null && locale.length() > 0) { | |
230 | + Locale loc = new Locale(locale); | |
231 | + data.add(new LocaleInfo( | |
232 | + locale, | |
233 | + loc.getDisplayName(), | |
234 | + true /*custom*/)); | |
235 | + } | |
236 | + } | |
237 | + | |
238 | + // Sort all locales by code | |
239 | + Collections.sort(data, new Comparator<LocaleInfo>() { | |
240 | + public int compare(LocaleInfo lhs, LocaleInfo rhs) { | |
241 | + return lhs.getLocale().compareTo(rhs.getLocale()); | |
242 | + } | |
243 | + }); | |
244 | + | |
245 | + // Update the list view adapter | |
246 | + mListView.setAdapter(new ArrayAdapter<LocaleInfo>( | |
247 | + this, | |
248 | + android.R.layout.simple_list_item_single_choice, | |
249 | + data)); | |
250 | + updateLocaleButtons(); | |
251 | + } | |
252 | + | |
253 | + private void changeSystemLocale(String locale) { | |
254 | + if (ChangeLocale.changeSystemLocale(locale)) { | |
255 | + Toast.makeText(this, | |
256 | + getString(R.string.select_locale_1s, locale), | |
257 | + Toast.LENGTH_SHORT) | |
258 | + .show(); | |
259 | + } | |
260 | + } | |
261 | + | |
262 | + private void displayCurrentLocale() { | |
263 | + try { | |
264 | + IActivityManager am = ActivityManagerNative.getDefault(); | |
265 | + Configuration config = am.getConfiguration(); | |
266 | + | |
267 | + if (config.locale != null) { | |
268 | + String text = String.format("%1$s - %2$s", | |
269 | + config.locale.toString(), | |
270 | + config.locale.getDisplayName()); | |
271 | + mCurrentLocaleTextView.setText(text); | |
272 | + | |
273 | + checkLocaleInList(config.locale.toString()); | |
274 | + } | |
275 | + } catch (RemoteException e) { | |
276 | + if (DEBUG) { | |
277 | + Log.e(TAG, "get current locale failed", e); | |
278 | + } | |
279 | + } | |
280 | + } | |
281 | + | |
282 | + /** Find the locale by code to select it in the list view */ | |
283 | + private void checkLocaleInList(String locale) { | |
284 | + ListAdapter a = mListView.getAdapter(); | |
285 | + for (int i = 0; i < a.getCount(); i++) { | |
286 | + Object o = a.getItem(i); | |
287 | + if (o instanceof LocaleInfo) { | |
288 | + String code = ((LocaleInfo) o).getLocale(); | |
289 | + if (code != null && code.equals(locale)) { | |
290 | + mListView.setSelection(i); | |
291 | + mListView.clearChoices(); | |
292 | + mListView.setItemChecked(i, true); | |
293 | + updateLocaleButtons(); | |
294 | + break; | |
295 | + } | |
296 | + } | |
297 | + } | |
298 | + } | |
299 | + | |
300 | + private LocaleInfo getCheckedLocale() { | |
301 | + int pos = mListView.getCheckedItemPosition(); | |
302 | + ListAdapter a = mListView.getAdapter(); | |
303 | + int n = a.getCount(); | |
304 | + if (pos >= 0 && pos < n) { | |
305 | + Object o = a.getItem(pos); | |
306 | + if (o instanceof LocaleInfo) { | |
307 | + return (LocaleInfo) o; | |
308 | + } | |
309 | + } | |
310 | + | |
311 | + return null; | |
312 | + } | |
313 | + | |
314 | + /** Update the Select/Remove buttons based on the currently checked locale. */ | |
315 | + private void updateLocaleButtons() { | |
316 | + LocaleInfo info = getCheckedLocale(); | |
317 | + if (info != null) { | |
318 | + // Enable it | |
319 | + mSelectLocaleButton.setEnabled(true); | |
320 | + mSelectLocaleButton.setText( | |
321 | + getString(R.string.select_locale_1s_button, info.getLocale())); | |
322 | + | |
323 | + // Enable the remove button only for custom locales and set the tag to the locale | |
324 | + mRemoveLocaleButton.setEnabled(info.isCustom()); | |
325 | + } else { | |
326 | + // If nothing is selected, disable the buttons | |
327 | + mSelectLocaleButton.setEnabled(false); | |
328 | + mSelectLocaleButton.setText(R.string.select_locale_button); | |
329 | + | |
330 | + mRemoveLocaleButton.setEnabled(false); | |
331 | + } | |
332 | + } | |
333 | + | |
334 | + /** Invoked by the button "Add new..." */ | |
335 | + private void onAddNewLocale() { | |
336 | + Intent i = new Intent(CustomLocaleActivity.this, NewLocaleDialog.class); | |
337 | + startActivityForResult(i, UPDATE_LIST); | |
338 | + } | |
339 | + | |
340 | + /** Invoked by the button Select / mSelectLocaleButton */ | |
341 | + private void onSelectLocale() { | |
342 | + LocaleInfo info = getCheckedLocale(); | |
343 | + if (info != null) { | |
344 | + changeSystemLocale(info.getLocale()); | |
345 | + } | |
346 | + } | |
347 | + | |
348 | + /** | |
349 | + * Invoked by the button Remove / mRemoveLocaleButton. | |
350 | + * Creates a dialog to ask for confirmation before actually remove the custom locale. | |
351 | + */ | |
352 | + private Dialog createRemoveLocaleDialog() { | |
353 | + | |
354 | + LocaleInfo info = getCheckedLocale(); | |
355 | + final String localeToRemove = info == null ? "<error>" : info.getLocale(); | |
356 | + | |
357 | + AlertDialog.Builder b = new AlertDialog.Builder(this); | |
358 | + b.setMessage(getString(R.string.confirm_remove_locale_1s, localeToRemove)); | |
359 | + b.setCancelable(false); | |
360 | + b.setPositiveButton(R.string.confirm_remove_locale_yes, | |
361 | + new DialogInterface.OnClickListener() { | |
362 | + @Override | |
363 | + public void onClick(DialogInterface dialog, int which) { | |
364 | + removeCustomLocale(localeToRemove); | |
365 | + dismissDialog(DLG_REMOVE_ID); | |
366 | + } | |
367 | + }); | |
368 | + b.setNegativeButton(R.string.confirm_remove_locale_no, | |
369 | + new DialogInterface.OnClickListener() { | |
370 | + @Override | |
371 | + public void onClick(DialogInterface dialog, int which) { | |
372 | + dismissDialog(DLG_REMOVE_ID); | |
373 | + } | |
374 | + }); | |
375 | + | |
376 | + return b.create(); | |
377 | + } | |
378 | + | |
379 | + private void removeCustomLocale(String localeToRemove) { | |
380 | + // Get current custom locale list | |
381 | + String oldLocales = mPrefs.getString(CUSTOM_LOCALES, ""); | |
382 | + | |
383 | + if (DEBUG) { | |
384 | + Log.d(TAG, "Remove " + localeToRemove + " from custom locales: " + oldLocales); | |
385 | + } | |
386 | + | |
387 | + // Update | |
388 | + StringBuilder sb = new StringBuilder(); | |
389 | + for (String locale : oldLocales.split(CUSTOM_LOCALES_SEP)) { | |
390 | + if (locale != null && locale.length() > 0 && !locale.equals(localeToRemove)) { | |
391 | + if (sb.length() > 0) { | |
392 | + sb.append(CUSTOM_LOCALES_SEP); | |
393 | + } | |
394 | + sb.append(locale); | |
395 | + } | |
396 | + } | |
397 | + | |
398 | + String newLocales = sb.toString(); | |
399 | + if (!newLocales.equals(oldLocales)) { | |
400 | + // Save prefs | |
401 | + boolean ok = mPrefs.edit().putString(CUSTOM_LOCALES, newLocales).commit(); | |
402 | + if (DEBUG) { | |
403 | + Log.d(TAG, "Prefs commit:" + Boolean.toString(ok) + ". Saved: " + newLocales); | |
404 | + } | |
405 | + | |
406 | + Toast.makeText(this, | |
407 | + getString(R.string.removed_custom_locale_1s, localeToRemove), | |
408 | + Toast.LENGTH_SHORT) | |
409 | + .show(); | |
410 | + | |
411 | + // Update list view | |
412 | + setupLocaleList(); | |
413 | + } | |
414 | + } | |
415 | + | |
416 | + /** | |
417 | + * Immutable structure that holds the information displayed by a list view item. | |
418 | + */ | |
419 | + private static class LocaleInfo { | |
420 | + private final String mLocale; | |
421 | + private final String mDisplayName; | |
422 | + private final boolean mIsCustom; | |
423 | + | |
424 | + public LocaleInfo(String locale, String displayName, boolean isCustom) { | |
425 | + mLocale = locale; | |
426 | + mDisplayName = displayName; | |
427 | + mIsCustom = isCustom; | |
428 | + } | |
429 | + | |
430 | + public LocaleInfo(String locale, String displayName) { | |
431 | + this(locale, displayName, false /*custom*/); | |
432 | + } | |
433 | + | |
434 | + public String getLocale() { | |
435 | + return mLocale; | |
436 | + } | |
437 | + | |
438 | + public boolean isCustom() { | |
439 | + return mIsCustom; | |
440 | + } | |
441 | + | |
442 | + @Override | |
443 | + public String toString() { | |
444 | + StringBuilder sb = new StringBuilder(); | |
445 | + sb.append(mLocale) | |
446 | + .append(" - ") | |
447 | + .append(mDisplayName); | |
448 | + if (mIsCustom) { | |
449 | + sb.append(" [Custom]"); | |
450 | + } | |
451 | + return sb.toString(); | |
452 | + } | |
453 | + } | |
454 | +} |
@@ -0,0 +1,82 @@ | ||
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 | + | |
17 | +package com.android.customlocale2; | |
18 | + | |
19 | +import android.app.Activity; | |
20 | +import android.content.BroadcastReceiver; | |
21 | +import android.content.Context; | |
22 | +import android.content.Intent; | |
23 | +import android.util.Log; | |
24 | + | |
25 | +//----------------------------------------------- | |
26 | + | |
27 | +/** | |
28 | + * Broadcast receiver that can change the system's locale. | |
29 | + * <p/> | |
30 | + * This allows an external script such as an automated testing framework | |
31 | + * to easily trigger a locale change on an emulator as such: | |
32 | + * <pre> | |
33 | + * $ adb shell am broadcast -a com.android.intent.action.SET_LOCALE \ | |
34 | + * --es com.android.intent.extra.LOCALE en_US | |
35 | + * </pre> | |
36 | + */ | |
37 | +public class CustomLocaleReceiver extends BroadcastReceiver { | |
38 | + | |
39 | + private static final String TAG = CustomLocaleReceiver.class.getSimpleName(); | |
40 | + private static final boolean DEBUG = true; | |
41 | + | |
42 | + /** Intent action that triggers this receiver. */ | |
43 | + public static final String ACTION_SET_LOCALE = "com.android.intent.action.SET_LOCALE"; | |
44 | + /** An extra String that specifies the locale to set, in the form "en_US". */ | |
45 | + public static final String EXTRA_LOCALE = "com.android.intent.extra.LOCALE"; | |
46 | + | |
47 | + @Override | |
48 | + public void onReceive(Context context, Intent intent) { | |
49 | + setResult(Activity.RESULT_CANCELED, null, null); | |
50 | + if (intent == null || ! ACTION_SET_LOCALE.equals(intent.getAction())) { | |
51 | + if (DEBUG) { | |
52 | + Log.d(TAG, "Invalid intent: " + (intent == null ? "null" : intent.toString())); | |
53 | + } | |
54 | + return; | |
55 | + } | |
56 | + | |
57 | + String locale = intent.getStringExtra(EXTRA_LOCALE); | |
58 | + | |
59 | + // Enforce the locale string is either in the form "ab" or "ab_cd" | |
60 | + boolean is_ok = locale != null; | |
61 | + is_ok = is_ok && (locale.length() == 2 || locale.length() == 5); | |
62 | + if (is_ok && locale.length() >= 2) { | |
63 | + is_ok = Character.isLetter(locale.charAt(0)) && | |
64 | + Character.isLetter(locale.charAt(1)); | |
65 | + } | |
66 | + if (is_ok && locale.length() == 5) { | |
67 | + is_ok = locale.charAt(2) == '_' && | |
68 | + Character.isLetter(locale.charAt(3)) && | |
69 | + Character.isLetter(locale.charAt(4)); | |
70 | + } | |
71 | + | |
72 | + if (!is_ok && DEBUG) { | |
73 | + Log.e(TAG, "Invalid locale: expected ab_CD but got " + locale); | |
74 | + } else if (is_ok) { | |
75 | + ChangeLocale.changeSystemLocale(locale); | |
76 | + setResult(Activity.RESULT_OK, locale, null); | |
77 | + } | |
78 | + } | |
79 | + | |
80 | +} | |
81 | + | |
82 | + |
@@ -14,14 +14,12 @@ | ||
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | 16 | |
17 | -package com.android.customlocale; | |
17 | +package com.android.customlocale2; | |
18 | 18 | |
19 | 19 | import android.app.Activity; |
20 | 20 | import android.content.Intent; |
21 | 21 | import android.os.Bundle; |
22 | -import android.text.TextUtils; | |
23 | 22 | import android.util.Log; |
24 | -import android.view.KeyEvent; | |
25 | 23 | import android.view.View; |
26 | 24 | import android.widget.Button; |
27 | 25 | import android.widget.EditText; |
@@ -41,7 +39,6 @@ public class NewLocaleDialog extends Activity implements View.OnClickListener { | ||
41 | 39 | private Button mButtonAdd; |
42 | 40 | private Button mButtonAddSelect; |
43 | 41 | private EditText mEditText; |
44 | - private boolean mWasEmpty; | |
45 | 42 | |
46 | 43 | @Override |
47 | 44 | protected void onCreate(Bundle savedInstanceState) { |
@@ -50,7 +47,6 @@ public class NewLocaleDialog extends Activity implements View.OnClickListener { | ||
50 | 47 | setContentView(R.layout.new_locale); |
51 | 48 | |
52 | 49 | mEditText = (EditText) findViewById(R.id.value); |
53 | - mWasEmpty = true; | |
54 | 50 | |
55 | 51 | mButtonAdd = (Button) findViewById(R.id.add); |
56 | 52 | mButtonAdd.setOnClickListener(this); |
@@ -62,7 +58,7 @@ public class NewLocaleDialog extends Activity implements View.OnClickListener { | ||
62 | 58 | public void onClick(View v) { |
63 | 59 | String locale = mEditText.getText().toString(); |
64 | 60 | boolean select = v == mButtonAddSelect; |
65 | - | |
61 | + | |
66 | 62 | if (DEBUG) { |
67 | 63 | Log.d(TAG, "New Locale: " + locale + (select ? " + select" : "")); |
68 | 64 | } |