本文中涉及的代碼所對應的Android Source版本為2.3.3,代號Gingerbread.
這兩天在調查Android系統Setting程式中對於語言設定這塊的內容。具體位置有以下兩處:
1)、設定顯示語言:Settings -> Language & keyboard -> Select language
2)、設定輸入語言:Settings -> Language & keyboard -> Android keyboard [settings] -> Input languages
Settings工程中,Settings -> Language & keyboard介面所對應的Java代碼和Preference布局如下:
<android_root>/packages/apps/Settings/src/com/android/settings/LanguageSettings.java
<android_root>/packages/apps/Settings/res/xml/language_settings.xml
1、Settings -> Language & keyboard -> Select language
在<android_root>/packages/apps/Settings/res/xml/language_settings.xml中,該模組的Preference布局為:
view plaincopy to clipboardprint?
1. <PreferenceScreen
2. android:key="phone_language"
3. android:title="@string/phone_language">
4. <intent android:action="android.intent.action.MAIN"
5. android:targetPackage="com.android.settings"
6. android:targetClass="com.android.settings.LocalePicker"/>
7. </PreferenceScreen>
<PreferenceScreen android:key="phone_language" android:title="@string/phone_language"> <intent android:action="android.intent.action.MAIN" android:targetPackage="com.android.settings" android:targetClass="com.android.settings.LocalePicker"/> </PreferenceScreen>
所以,當使用者點擊“Settings -> Language & keyboard -> Select language”時,將啟動“com.android.settings.LocalePicker”的Activity。其對應的原始碼為:
<android_root>/packages/apps/Settings/src/com/android/settings/LocalePicker.java
LocalePicker Activity繼承自ListActivity。在它的onCreate()回調中,調用了下面一條語句:
String[] locales = getAssets().getLocales();
LocalePicker Activity將取得的locale字串進行了一些處理,然後建立了ArrayAdapter<Loc> adapter,並綁定到ListActivity的ListView上。當使用者點擊ListView上的Item時,再將選中的locale資訊設定到 Android系統中。
view plaincopy to clipboardprint?
1. @Override
2. protected void onListItemClick(ListView l, View v, int position, long id) {
3. try {
4. IActivityManager am = ActivityManagerNative.getDefault();
5. Configuration config = am.getConfiguration();
6. Loc loc = mLocales[position];
7. config.locale = loc.locale;
8. // indicate this isn't some passing default - the user wants this remembered
9. config.userSetLocale = true;
10. am.updateConfiguration(config);
11. // Trigger the dirty bit for the Settings Provider.
12. BackupManager.dataChanged("com.android.providers.settings");
13. } catch (RemoteException e) {
14. // Intentionally left blank
15. }
16. finish();
17. }
@Override protected void onListItemClick(ListView l, View v, int position, long id) { try { IActivityManager am = ActivityManagerNative.getDefault(); Configuration config = am.getConfiguration(); Loc loc = mLocales[position]; config.locale = loc.locale; //
indicate this isn't some passing default - the user wants this remembered config.userSetLocale = true; am.updateConfiguration(config); // Trigger the dirty bit for the Settings Provider. BackupManager.dataChanged("com.android.providers.settings"); } catch
(RemoteException e) { // Intentionally left blank } finish(); }
2、Settings -> Language & keyboard -> Android keyboard [settings] -> Input languages
在<android_root>/packages/apps/Settings/res/xml /language_settings.xml中,找不到IME相關的布局內容。但是,可以在<android_root> /packages/apps/Settings/src/com/android/settings/LanguageSettings.java中找到一個onCreateIMM()函數,它在onCreate()回調中被調用。它的作用就是通過InputMethodManager類的 getInputMethodList()
API獲得當前系統已安裝的IME列表,然後逐個地動態產生Preference布局,追加加到設定介面上。
事實上,Gingerbread預設的有三種IME:英文,中文,日文。對應的工程代碼路徑為:
<android_root>/packages/inputmethods/LatinIME/
<android_root>/packages/inputmethods/OpenWnn/
<android_root>/packages/inputmethods/PinyinIME/
通過Log,可以發現,當點擊 Android keyboard [settings] 功能表項目時,將會啟動一個 Activity:com.android.inputmethod.latin/com.android.inputmethod.latin.LatinIMESettings。因此可以斷定<android_root>/packages/inputmethods/LatinIME/就是我們要找的Android keyboard [settings]IME的原始碼工程。
通過<android_root>/packages/inputmethods/LatinIME/java/AndroidManifest.xml,可以找到這個Activity和布局是:
<android_root>/packages/inputmethods/LatinIME/java/src/com/android/inputmethod/latin/LatinIMESettings.java
<android_root>/packages/inputmethods/LatinIME/java/res/xml/prefs.xml
最後綜合可以判定Settings -> Language & keyboard -> Android keyboard [settings] -> Input languages對應的代碼是:
<android_root>/packages/inputmethods/LatinIME/java/src/.../latin/InputLanguageSelection.java
InputLanguageSelection繼承自PreferenceActivity,它有一個getUniqueLocales()函數,在這個函數中,它如同<android_root>/packages/apps/Settings/src/com/android /settings/LocalePicker.java一樣,調用了下面的語句:
String[] locales = getAssets().getLocales();
然後InputLanguageSelection Activity將取得的locale字串進行了一些處理,然後迴圈最終的Locale列表,逐個的為每種語言動態產生 CheckBoxPreference載入到InputLanguageSelection的畫面上。當使用者選中語言,退出 InputLanguageSelection Activity時,這些選中的語言就會被儲存到SharedPreferences中去。
到此,可以看到以上這兩處的做法都是使用Activity的getAssets()方法取得AssetManager的執行個體,然後調用 AssetManager的getLocales()函數取得系統所支援的語言。然後經過自己的一些過濾辦法,最終顯示在UI介面。
phone對語言進行設定的代碼在(setSystemLocale方法)
/work/updatecode/androidx86-froyo/frameworks/base/telephony/java/com/android/internal/telephony/PhoneBase.java