Home | History | Annotate | Download | only in customlocale
      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 }
    335