| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.customlocale; |
| |
| |
| import android.app.ActivityManagerNative; |
| import android.app.IActivityManager; |
| import android.app.ListActivity; |
| import android.content.Intent; |
| import android.content.SharedPreferences; |
| import android.content.res.Configuration; |
| import android.os.Bundle; |
| import android.os.RemoteException; |
| import android.util.Log; |
| import android.view.ContextMenu; |
| import android.view.MenuItem; |
| import android.view.View; |
| import android.view.ContextMenu.ContextMenuInfo; |
| import android.widget.Button; |
| import android.widget.ListAdapter; |
| import android.widget.ListView; |
| import android.widget.SimpleAdapter; |
| import android.widget.TextView; |
| import android.widget.Toast; |
| import android.widget.AdapterView.AdapterContextMenuInfo; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.Locale; |
| import java.util.Map; |
| |
| /** |
| * Displays the list of system locales as well as maintain a custom list of user |
| * locales. The user can select a locale and apply it or it can create or remove |
| * a custom locale. |
| */ |
| public class CustomLocaleActivity extends ListActivity { |
| |
| private static final String CUSTOM_LOCALES_SEP = " "; |
| private static final String CUSTOM_LOCALES = "custom_locales"; |
| private static final String KEY_CUSTOM = "custom"; |
| private static final String KEY_NAME = "name"; |
| private static final String KEY_CODE = "code"; |
| |
| private static final String TAG = "LocaleSetup"; |
| private static final boolean DEBUG = true; |
| |
| /** Request code returned when the NewLocaleDialog activity finishes. */ |
| private static final int UPDATE_LIST = 42; |
| /** Menu item id for applying a locale */ |
| private static final int MENU_APPLY = 43; |
| /** Menu item id for removing a custom locale */ |
| private static final int MENU_REMOVE = 44; |
| |
| /** List view displaying system and custom locales. */ |
| private ListView mListView; |
| /** Textview used to display current locale */ |
| private TextView mCurrentLocaleTextView; |
| /** Private shared preferences of this activity. */ |
| private SharedPreferences mPrefs; |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.main); |
| |
| mPrefs = getPreferences(MODE_PRIVATE); |
| |
| Button newLocaleButton = (Button) findViewById(R.id.new_locale); |
| |
| newLocaleButton.setOnClickListener(new View.OnClickListener() { |
| public void onClick(View v) { |
| Intent i = new Intent(CustomLocaleActivity.this, NewLocaleDialog.class); |
| startActivityForResult(i, UPDATE_LIST); |
| } |
| }); |
| |
| mListView = (ListView) findViewById(android.R.id.list); |
| mListView.setFocusable(true); |
| mListView.setFocusableInTouchMode(true); |
| mListView.requestFocus(); |
| registerForContextMenu(mListView); |
| setupLocaleList(); |
| |
| mCurrentLocaleTextView = (TextView) findViewById(R.id.current_locale); |
| displayCurrentLocale(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| protected void onActivityResult(int requestCode, int resultCode, Intent data) { |
| super.onActivityResult(requestCode, resultCode, data); |
| |
| if (requestCode == UPDATE_LIST && resultCode == RESULT_OK && data != null) { |
| String locale = data.getExtras().getString(NewLocaleDialog.INTENT_EXTRA_LOCALE); |
| if (locale != null && locale.length() > 0) { |
| // Get current custom locale list |
| String customLocales = mPrefs.getString(CUSTOM_LOCALES, null); |
| |
| // Update |
| if (customLocales == null) { |
| customLocales = locale; |
| } else { |
| customLocales += CUSTOM_LOCALES_SEP + locale; |
| } |
| |
| // Save prefs |
| if (DEBUG) { |
| Log.d(TAG, "add/customLocales: " + customLocales); |
| } |
| mPrefs.edit().putString(CUSTOM_LOCALES, customLocales).commit(); |
| |
| Toast.makeText(this, "Added custom locale: " + locale, Toast.LENGTH_SHORT).show(); |
| |
| // Update list view |
| setupLocaleList(); |
| |
| // Find the item to select it in the list view |
| ListAdapter a = mListView.getAdapter(); |
| for (int i = 0; i < a.getCount(); i++) { |
| Object o = a.getItem(i); |
| if (o instanceof Map<?, ?>) { |
| String code = ((Map<String, String>) o).get(KEY_CODE); |
| if (code != null && code.equals(locale)) { |
| mListView.setSelection(i); |
| break; |
| } |
| } |
| } |
| |
| if (data.getExtras().getBoolean(NewLocaleDialog.INTENT_EXTRA_SELECT)) { |
| selectLocale(locale); |
| } |
| } |
| } |
| } |
| |
| private void setupLocaleList() { |
| if (DEBUG) { |
| Log.d(TAG, "Update locate list"); |
| } |
| |
| ArrayList<Map<String, String>> data = new ArrayList<Map<String, String>>(); |
| |
| // Insert all system locales |
| String[] locales = getAssets().getLocales(); |
| for (String locale : locales) { |
| Locale loc = new Locale(locale); |
| |
| Map<String, String> map = new HashMap<String, String>(1); |
| map.put(KEY_CODE, locale); |
| map.put(KEY_NAME, loc.getDisplayName()); |
| data.add(map); |
| } |
| locales = null; |
| |
| // Insert all custom locales |
| String customLocales = mPrefs.getString(CUSTOM_LOCALES, ""); |
| if (DEBUG) { |
| Log.d(TAG, "customLocales: " + customLocales); |
| } |
| for (String locale : customLocales.split(CUSTOM_LOCALES_SEP)) { |
| if (locale != null && locale.length() > 0) { |
| Locale loc = new Locale(locale); |
| |
| Map<String, String> map = new HashMap<String, String>(1); |
| map.put(KEY_CODE, locale); |
| map.put(KEY_NAME, loc.getDisplayName() + " [Custom]"); |
| // the presence of the "custom" key marks it as custom. |
| map.put(KEY_CUSTOM, ""); |
| data.add(map); |
| } |
| } |
| |
| // Sort all locales by code |
| Collections.sort(data, new Comparator<Map<String, String>>() { |
| public int compare(Map<String, String> lhs, Map<String, String> rhs) { |
| return lhs.get(KEY_CODE).compareTo(rhs.get(KEY_CODE)); |
| } |
| }); |
| |
| // Update the list view adapter |
| mListView.setAdapter(new SimpleAdapter(this, data, R.layout.list_item, new String[] { |
| KEY_CODE, KEY_NAME}, new int[] {R.id.locale_code, R.id.locale_name})); |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { |
| super.onCreateContextMenu(menu, v, menuInfo); |
| |
| if (menuInfo instanceof AdapterContextMenuInfo) { |
| int position = ((AdapterContextMenuInfo) menuInfo).position; |
| Object o = mListView.getItemAtPosition(position); |
| if (o instanceof Map<?, ?>) { |
| String locale = ((Map<String, String>) o).get(KEY_CODE); |
| String custom = ((Map<String, String>) o).get(KEY_CUSTOM); |
| |
| if (custom == null) { |
| menu.setHeaderTitle("System Locale"); |
| menu.add(0, MENU_APPLY, 0, "Apply"); |
| } else { |
| menu.setHeaderTitle("Custom Locale"); |
| menu.add(0, MENU_APPLY, 0, "Apply"); |
| menu.add(0, MENU_REMOVE, 0, "Remove"); |
| } |
| } |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public boolean onContextItemSelected(MenuItem item) { |
| |
| String pendingLocale = null; |
| boolean is_custom = false; |
| |
| ContextMenuInfo menuInfo = item.getMenuInfo(); |
| if (menuInfo instanceof AdapterContextMenuInfo) { |
| int position = ((AdapterContextMenuInfo) menuInfo).position; |
| Object o = mListView.getItemAtPosition(position); |
| if (o instanceof Map<?, ?>) { |
| pendingLocale = ((Map<String, String>) o).get(KEY_CODE); |
| is_custom = ((Map<String, String>) o).get(KEY_CUSTOM) != null; |
| } |
| } |
| |
| if (pendingLocale == null) { |
| // should never happen |
| return super.onContextItemSelected(item); |
| } |
| |
| if (item.getItemId() == MENU_REMOVE) { |
| // Get current custom locale list |
| String customLocales = mPrefs.getString(CUSTOM_LOCALES, ""); |
| |
| if (DEBUG) { |
| Log.d(TAG, "Remove " + pendingLocale + " from custom locales: " + customLocales); |
| } |
| |
| // Update |
| StringBuilder sb = new StringBuilder(); |
| for (String locale : customLocales.split(CUSTOM_LOCALES_SEP)) { |
| if (locale != null && locale.length() > 0 && !locale.equals(pendingLocale)) { |
| if (sb.length() > 0) { |
| sb.append(CUSTOM_LOCALES_SEP); |
| } |
| sb.append(locale); |
| } |
| } |
| String newLocales = sb.toString(); |
| if (!newLocales.equals(customLocales)) { |
| // Save prefs |
| mPrefs.edit().putString(CUSTOM_LOCALES, customLocales).commit(); |
| |
| Toast.makeText(this, "Removed custom locale: " + pendingLocale, Toast.LENGTH_SHORT) |
| .show(); |
| } |
| |
| } else if (item.getItemId() == MENU_APPLY) { |
| selectLocale(pendingLocale); |
| } |
| |
| return super.onContextItemSelected(item); |
| } |
| |
| private void selectLocale(String locale) { |
| if (DEBUG) { |
| Log.d(TAG, "Select locale " + locale); |
| } |
| |
| try { |
| IActivityManager am = ActivityManagerNative.getDefault(); |
| Configuration config = am.getConfiguration(); |
| |
| Locale loc = new Locale(locale); |
| config.locale = loc; |
| |
| // indicate this isn't some passing default - the user wants this |
| // remembered |
| config.userSetLocale = true; |
| |
| am.updateConfiguration(config); |
| |
| Toast.makeText(this, "Select locale: " + locale, Toast.LENGTH_SHORT).show(); |
| } catch (RemoteException e) { |
| if (DEBUG) { |
| Log.e(TAG, "Select locale failed", e); |
| } |
| } |
| } |
| |
| private void displayCurrentLocale() { |
| try { |
| IActivityManager am = ActivityManagerNative.getDefault(); |
| Configuration config = am.getConfiguration(); |
| |
| if (config.locale != null) { |
| String text = String.format("%s - %s", |
| config.locale.toString(), |
| config.locale.getDisplayName()); |
| mCurrentLocaleTextView.setText(text); |
| } |
| } catch (RemoteException e) { |
| if (DEBUG) { |
| Log.e(TAG, "get current locale failed", e); |
| } |
| } |
| } |
| } |