android 系統數據庫Settings的使用整理

概述:做系統或者系統應用開發時經常會需要用到跨進程通信,並且需要傳遞狀態值時,可以通過系統數據庫的屬性進行通信,比如原生系統的設置中的設置休眠時間,usb調試開關等,都是通過Settings.apk中通過選擇項設置一個屬性值,然後再在framework中的相應模塊中通過ContentObserver中的onchange去實現具體的邏輯以達到功能模塊的解耦以及跨進程通信的目的,且系統數據庫中的值類似於contentprovider,是可以在任何其他應用中隨意讀取的(有些屬性值需要權限),寫值的話則需要系統簽名才行,並且可以使用ContentObserver監聽屬性值的變化,不需要像有些場景中需要起個線程去不停的檢測某個值的變化,ContentObserver的onchangge只會在數據變化時纔有回調

1.系統調用流程

1.1最開始是在frameworks\base\packages\SettingsProvider\res\values\defaults.xml中設置默認值,如

    <!-- Default for Settings.Secure.USER_SETUP_COMPLETE -->
    <bool name="def_user_setup_complete">false</bool>

1.2後面使用到的字符串是在frameworks\base\core\java\android\provider\Settings.java中定義,如

public static final String USER_SETUP_COMPLETE = "user_setup_complete";

1.3僅在第一次開機或者恢復出廠設置時在\frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java中分別通過以下方法加入系統數據庫中

loadSystemSettings(SQLiteDatabase db)--對應數據庫的system表
loadSecureSettings(SQLiteDatabase db)--對應數據庫的secure表
loadGlobalSettings(SQLiteDatabase db)--對應數據庫的global表

說明:以上方法內部會有幾種添加數據類型的方法,如

            loadBooleanSetting(stmt, Settings.Global.GUEST_USER_ENABLED,
                    R.bool.def_guest_user_enabled);//添加boolean類型
            loadIntegerSetting(stmt, Global.HEADS_UP_NOTIFICATIONS_ENABLED,
                    R.integer.def_heads_up_enabled);//添加int類型
            loadStringSetting(stmt, Settings.Global.DESK_DOCK_SOUND,
                    R.string.def_desk_dock_sound);//添加string類型

            loadSetting(stmt, Settings.Global.SET_INSTALL_LOCATION, 0);

//最終都會走到這個方法中,都是保存的object類型,拿的時候會去判斷類型拿值,再轉換爲相應的類型的值

    private void loadSetting(SQLiteStatement stmt, String key, Object value) {
        stmt.bindString(1, key);
        stmt.bindString(2, value.toString());
        stmt.execute();
    }

1.4具體數據庫在機器的/data/data/com.android.providers.settings 中,名稱爲settings.db(實際有後綴名,保存時去掉後綴名保存即可,然後可數據庫查看軟件查看裏面的數值)

2.基本使用

2.1添加自定義的字段到數據庫中

\frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java中

loadSystemSettings-loadSetting(stmt,"power_save_mode_state", 0);

說明:上面有提到可以在3個方法下面去加,最後結果就是對應到不同的數據庫表中,如果不閒麻煩可以參考系統的正規流程,在Settings中去去加字符串,然後默認值通過default.xml去定義,然後參考上面1調用流程中的方法去獲得;

2.2讀寫方法

import android.provider.Settings;
Settings.System.getString(mContext.getContentResolver(), "xxx");
Settings.System.putString(mContext.getContentResolver(),"xxx","defaultStr");
Settings.System.getInt(mContext.getContentResolver(),"power_save_mode_state", 0);
Settings.System.putInt(mContext.getContentResolver(),"power_save_mode_state",1);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);

說明:注意讀寫方法需要用對應的System/Global/Secure方法,否則讀寫數據會不對應;如果沒在DatabaseHelper.java中添加字段及默認值到數據庫中,也是可以正常用put和get方法的,只是數據庫表中看不到這個字段而已

2.3狀態值改變的監聽

import android.database.ContentObserver;
mContext.getContentResolver().registerContentObserver(Settings.System.getUriFor("power_save_mode_state"), false, mXXXObserver);
private ContentObserver mXXXObserver=new ContentObserver(new Handler()) {
        public void onChange(boolean selfChange) {

            
        };
    };
mContext.getContentResolver().unregisterContentObserver(mXXXObserver);

說明:如果是系統源碼裏面去加則注意手動導包

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章