前言
公司開(kāi)發(fā) Android Launcher 項(xiàng)目匪傍,需要設(shè)置一些系統(tǒng)的屬性,比如說(shuō)修改系統(tǒng)語(yǔ)言設(shè)置观挎,修改輸入法琴儿,修改時(shí)間格式,修改時(shí)區(qū)等等嘁捷,因?yàn)槭且恍┫到y(tǒng)屬性造成,配置的時(shí)候都一些注意的要點(diǎn)。
修改系統(tǒng)語(yǔ)言設(shè)置
修改系統(tǒng)語(yǔ)言比較特殊雄嚣,需要用到一個(gè)叫作
ActivityManagerNative
類晒屎,這個(gè)類在layoutlib.jar
中,它與 android.jar 是同一級(jí)別的缓升,不參與編譯進(jìn) apk 中鼓鲁,所以需要自己導(dǎo)入。
- android studo 的導(dǎo)入方法如下:
android {
...需寫(xiě)在 android 之后
}
dependencies {
...
provided files(getLayoutLibPath())
...
}
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
/**
* get layoutlib.jar path
* android.os.SystemProperties need it
* must called after "android" definition
*/
def getLayoutLibPath() {
return "${android.getSdkDirectory().getAbsolutePath()}" + "/platforms/" + android.compileSdkVersion + "/data/layoutlib.jar"
}
接下來(lái)就是修改語(yǔ)言的代碼
IActivityManager iManager;
try {
iManager = ActivityManagerNative.getDefault();
Configuration localConfiguration = iManager.getConfiguration();
localConfiguration.locale = mInfos.get(position).getLocale();
iManager.updateConfiguration(localConfiguration);
BackupManager.dataChanged("com.android.providers.settings");
finish();
} catch (RemoteException e) {
e.printStackTrace();
}
這里的locale對(duì)象港谊,代表了一個(gè)特定的地理骇吭、政治和文化地區(qū)。在操作 Date歧寺、Calendar等表示日期/時(shí)間的對(duì)象時(shí)燥狰,經(jīng)常會(huì)用到。
-
這里用到了
Configuration
成福,對(duì)其進(jìn)行了修改碾局,就需要聲明權(quán)限<uses-permission android:name="android.permission.CHANGE_CONFIGURATION"/>
-
同時(shí)因?yàn)檫@是系統(tǒng)級(jí)別的權(quán)限,普通的第三方應(yīng)用沒(méi)有權(quán)限使用奴艾,即使聲明了該權(quán)限也無(wú)法獲取該權(quán)限,需要聲明該應(yīng)用為系統(tǒng)應(yīng)用:需要在 AndroidManifest.xml 添加:
android:sharedUserId="android.uid.system"
Android Settings
其它許多系統(tǒng)屬性的修改都在 Settings 應(yīng)用當(dāng)中進(jìn)行設(shè)置内斯,比如 wifi蕴潦,藍(lán)牙狀態(tài)像啼,等一些相關(guān)的系統(tǒng)屬性。這些屬性的數(shù)據(jù)主要保存在數(shù)據(jù)庫(kù) settings 中潭苞,而 settings 保存的位置在:/data/data/com.android.providers.settings/databases/settings.db忽冻。
我從自己機(jī)器中拉了一個(gè)出來(lái),上傳了堅(jiān)果云此疹,可以下載了看看僧诚。
settings數(shù)據(jù)庫(kù)堅(jiān)果云地址
主要的操作就是針對(duì)以下三張表:
表名 | URI | 備注 | |
---|---|---|---|
secure | Settings.Secure | content://settings/secure | 安全性的用戶偏好系統(tǒng)設(shè)置,第三方APP有讀沒(méi)有寫(xiě)的權(quán)限 |
global | Settings.Global | content://settings/global | 所有的編號(hào)設(shè)置蝗碎,對(duì)系統(tǒng)的所有用戶公開(kāi)湖笨,第三方APP有讀沒(méi)有寫(xiě)的權(quán)限 |
system | Settings.system | content://settings/system | 包含各種各樣的用戶偏好系統(tǒng)設(shè)置 |
因?yàn)檫@是一個(gè)本應(yīng)用外的數(shù)據(jù)庫(kù),不能跨進(jìn)程和包直接訪問(wèn)蹦骑,就需要用到了內(nèi)容提供者ContentProvider
和內(nèi)容解析者ContentResolver
慈省。
跨進(jìn)程通信的ContentProvider
簡(jiǎn)短的概括一下就是,如果跨進(jìn)程訪問(wèn)數(shù)據(jù)眠菇,需要將這個(gè)數(shù)據(jù)通過(guò)ContentProvider
共享出來(lái)边败,然后通過(guò)ContentResolver
訪問(wèn)到,執(zhí)行增刪改查的操作捎废。ContentProvider
是一個(gè)抽象類笑窜,也就是繼承實(shí)現(xiàn)它,而 Android 中對(duì) settings.db
實(shí)現(xiàn)的就是 SettingsProvider
登疗,當(dāng)中封裝了對(duì) settings.db
的操作排截,而framework
有一個(gè)類對(duì)使用SettingsProvider
進(jìn)行了封裝。
以Secure表為例
三個(gè)表的使用都差不多谜叹,就以secure
為例匾寝。
獲取當(dāng)前輸入法
String defaultMethodId = Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
修改當(dāng)前輸入法
先在系統(tǒng)的配置信息中添加該輸入法,通過(guò) Settings.Secure.ENABLE_INPUT_METHODS 添加荷腊,如果有多個(gè)輸入法艳悔,這些字符串間以分號(hào)分隔,再將輸入法設(shè)置成默認(rèn)輸入法
Settings.Secure.putString(getContentResolver(), Settings.Secure.ENABLED_INPUT_METHODS, newInputMethodId);
Settings.Secure.putString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD, newInputMethodId);
獲取日期格式
Settings.System.getString(getContentResolver(), Settings.System.DATE_FORMAT)
添加權(quán)限
<uses-permission android:name="android.permission.SET_TIME"/> <!--允許程序設(shè)置系統(tǒng)時(shí)間-->
<uses-permission android:name="android.permission.SET_TIME_ZONE" /> <!--允許程序設(shè)置系統(tǒng)時(shí)區(qū)-->
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/> <!--允許應(yīng)用程序讀取或?qū)懭氚踩到y(tǒng)設(shè)置-->
<uses-permission android:name="android.permission.WRITE_SETTINGS" /> <!--允許應(yīng)用程序讀取或?qū)懭氚踩到y(tǒng)設(shè)置-->
Condition
- 在獲取時(shí)區(qū)的時(shí)候女仰,Calendar對(duì)象需要重新獲取猜年,不然獲得時(shí)區(qū)值不會(huì)變
- 在 Android6.0 之后,申請(qǐng) WRITE_SETTINGS 的權(quán)限疾忍,會(huì)出現(xiàn)閃退的情況乔外,異常為:java.lang.IllegalArgumentException : You can not keep your settings in the secure settings.
- 原因:在 Android6.0 以后,WRITE_SETTINGS 權(quán)限的保護(hù)等級(jí)已經(jīng)由原來(lái)的 dangerous 升級(jí)為signatrue, 意味著APP需要用系統(tǒng)簽名或者成為系統(tǒng)預(yù)裝軟件才能夠申請(qǐng)?jiān)摍?quán)限一罩,并且還需要提示用戶跳轉(zhuǎn)到修改系統(tǒng)的設(shè)置界面去授予此權(quán)限杨幼。
- 解決方案:要想申請(qǐng)?jiān)摍?quán)限,apk必須要打包,簽名打包差购,debug模式是不能申請(qǐng)?jiān)摍?quán)限的