Android Settings模組分析
阿新 • • 發佈:2019-01-26
Settings模組 第一部分 Settings涉及的模組 4.0設定的layout有很大的改變。將設定分為四個部分: WIRELESS & NETWORKS :SIM卡管理,流量使用情況,飛航模式,VPN,網路共享等 DEVICE : 情景模式,顯示,儲存,電池,應用程式 PERSONAL: 賬戶與同步,位置服務,安全,語言和輸入法,備份和重置 SYSTEM: 日期和時間,定時開關及,輔助功能,開發人員選項,關於手機 第二部分 Fragment 2.1 com.android.settings.Settings類 設定頁面的Activity: public class Settings extends PreferenceActivity implements ButtonBarHandler{}。因為從3.0中就引入了Fragment機制,所以在Settings裡面就只有這一個(待確定)Acitivity類,而進入裡表中的某項設定後,不是進入到新的Activity,而是在原來的Activity上切換了一個UI介面而已。 2.2 Settings模組的Fragment 4.0上Settings使用了Framgment機制。Fragment是我們在單個Activity上要切換多 個UI介面,顯示不同內容,對不同的介面不再使用不同的Activity。模組化這些UI面板以便提供給其他Acitivity使用便利。同時我們顯示的Fragment也會受到當前的這個 Acitivity生命週期影響。(而平常的Fragment有其自己的生命週期)。 因為使用了Fragment機制,所有Settings的主要的Layout檔案和2.3已經有很大不同。在res/xml/settings_headers.xml中可以找到settings中包含的選項,可以比較一下兩者的不同:在2.3中layout檔案為:(res/xml/settings.xml)<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res/com.android.settings" android:title="@string/settings_label" android:key="parent"> <!-- Customization Settings --> <com.android.settings.IconPreferenceScreen android:key="customization_settings" android:title="@string/customization" settings:icon="@drawable/ic_settings_customization"> </com.android.settings.IconPreferenceScreen> ...(以下略) 而在4.0中的layout檔案為: <preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> <!-- WIRELESS and NETWORKS --> <header android:title="@string/header_category_wireless_networks" /> <!-- Sim management --> <header android:id="@+id/sim_settings" android:icon="@drawable/ic_settings_dualsim" android:fragment="com.android.settings.gemini.SimManagement" android:title="@string/gemini_sim_management_title" /> 兩者的很大的不同就是在4.0中用了Fragment機制後,每個列表相應後不是重新啟動一個Activity,而是在原來的Activity(Settings)上切換了一個UI介面,在<header …/>中通過以下方法指定每個模組設定相關的類: android:fragment="com.android.settings.****.****" 這些類都是繼承自Fragment類。相關的模組設定的入口類如下: SIM卡設定: com.android.settings.gemini.SimManagement wifi設定: com.android.settings.wifi.WifiSettings 藍芽設定: com.android.settings.bluetooth.BluetoothSettings 流量: com.android.settings.DataUsageSummary 更多(wireless): com.android.settings.WirelessSettings 情景模式: com.android.settings.audioprofile.AudioProfileSettings 顯示: com.android.settings.DisplaySettings 儲存: com.android.settings.deviceinfo.Memory 電池: com.android.settings.fuelgauge.PowerUsageSummary 應用程式: com.android.settings.applications.ManageApplications 賬戶與同步: com.android.settings.accounts.ManageAccountsSettings 位置: com.android.settings.LocationSettings 安全: com.android.settings.SecuritySettings 輸入法與語言: com.android.settings.inputmethod.InputMethodAndLanguageSettings 日期時間設定: com.android.settings.DateTimeSettings 定時開關機: com.android.settings.schpwronoff.AlarmClock 開發人員選項: com.android.settings.DevelopmentSettings 關於手機: com.android.settings.DeviceInfoSettings (關於Fragment的相關待補充) 第三部分 獲取與設定系統屬性 在android中,許多的系統屬性都在settings應用當中進行設定的,如wifi,藍芽狀態,本機語言,螢幕亮度等一些相關的系統屬性值。這些資料儲存在資料庫中,對應的兩個主要的URI:content://settings/system和 content://settings/secure。 在settings應用中所獲取或者修改屬性都是呼叫了framework中的android.provider.settings中的Settings類對應的方法。在android.provider.settings.Settings裡面,包含了System和Secure幾個內部類,每個內部類對應了一張資料庫表,也就是繼承自BaseColumn類。System和Secure類分別對應著system和secure資料庫表。裡面包含了獲取設定值的方法以及相關設定項的URI字串。 常見的獲取和設定系統屬性的方法有: getString(param1,param2) <---> putString(param1,param2) getInt(param1,param2) <---> putInt(param1,param2) getLong(param1,param2) <---> putLong(param1,param2) getConfiguration(param1,param2) <---> putConfiguration(param1,param2) getFloat(param1,param2) <---> putFloat(param1,param2) ... Example:settings應用中是如何對系統屬性進行設定的。 當需要獲得當前wifi狀態的值,呼叫已封裝的方法如下: Settings.Secure.getInt(getContentResolver() , Settings.Secure.WIFI_ON); 修改wifi狀態只需要呼叫對應的setInt方法就可以實現。 當需要獲得當前時間日期自動獲取,呼叫如下: Settings.System.getInt(getContentResolver() , "auto_time"); 修改也是呼叫對應的setInt方法。 第四部分 language settings示例分析 我們通過分析 language settings中的 auto_caps(自動替換)設定來分析Settings中是怎麼對系統屬性進行基本設定的. 4.1 找到對應的JAVA類檔案 InputMethodAndLanguageSettings 在 res./xml/settings_headers.xml中有: < !-- Language --> <header android:id="@+id/language_settings" android:fragment="com.android.settings.inputmethod.InputMethodAndLanguageSettings" android:icon="@drawable/ic_settings_language" android:title="@string/language_settings" /> 根據fragment的定義我們找到: 4.2 找到 R.xml.language_settings佈局檔案 在 InputMethodAndLanguageSettings.java中,我們找到: ... public void onCreate(Bundle icicle) { super.onCreate(icicle); addPreferencesFromResource(R.xml.language_settings); … } … 可以找到language_settings.xml檔案.同樣可以看到這裡利用了Fragment機制。 在程式碼中我們找到自動替換的設定選項分析: <CheckBoxPreference android:key="auto_caps" android:title="@string/auto_caps" android:summaryOn="@string/auto_caps_summary" android:summaryOff="@string/auto_caps_summary" android:persistent="false"/> 對應的手機中的UI介面為: 4.3 獲取和設定屬性 在 com.android.settings.inputmethod.InputMethodAndLanguageSettings.java中: 在以下程式碼獲得auto_replace的checkbox的key值: private static final String[] sHardKeyboardKeys = { "auto_replace", "auto_caps", "auto_punctuate", }; 在onResume()中來初始化checkbox:四個迴圈分別為物理鍵盤的checkbox選項: // Hard keyboard if (mHaveHardKeyboard) { for (int i = 0; i < sHardKeyboardKeys.length; ++i) { /*以下獲取Checkbox的物件*/ CheckBoxPreference chkPref = (CheckBoxPreference) mHardKeyboardCategory.findPreference(sHardKeyboardKeys[i]); /*利用Settings.System.getInt()來獲取屬性值*/ chkPref.setChecked( System.getInt(getContentResolver(), sSystemSettingNames[i], 1) > 0); } } 我們可以看到Settings.System.getInt()方法的應用。 在onPreferenceClick()中可以看到對auto_cap選項的設定: if (mHaveHardKeyboard) { for (int i = 0; i < sHardKeyboardKeys.length; ++i) { if (chkPref == mHardKeyboardCategory.findPreference(sHardKeyboardKeys[i])) { /*將設定的新的屬性寫如資料庫*/ System.putInt(getContentResolver(), sSystemSettingNames[i], chkPref.isChecked() ? 1 : 0); return true; } } } 我們可以看到Settings.System.putInt()方法的應用。 通過以上步驟,我們可以詳細地明白Settings是怎麼獲取與設定系統的屬性的。