1. 程式人生 > >Android Settings模組分析

Android Settings模組分析

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是怎麼獲取與設定系統的屬性的。