开发的时候,我们经常会有这样的一种需求:
在什么位置(如db)保存一个变量,可以跨应用的读写此值。
system.prop
我们可以在system.prop中定义一个宏开关,可以很好的实现此目的。
参考:
android system.prop使用(1)
android Systemproperties数据读写
- 此方法的优势是可以控制java,cpp文件,控制范围更广。
- 不足的地方是要提高权限。
在framework/base/core/res/res的资源中添加一个变量的方法:
先看一个framework本身就有的一个变量:
config_sms_ringtone_incall
定义此变量:
./frameworks/base/core/res/res/values/symbols.xml:
<java-symbol type="bool" name="config_sms_ringtone_incall" />
./frameworks/base/core/res/res/values/config.xml
<bool name="config_sms_ringtone_incall">true</bool>
在java文件中的读取此变量:
./frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
boolean smsRingtone = getContext().getResources().getBoolean(
com.android.internal.R.bool.config_sms_ringtone_incall);
- 此种方法是使用方便,简单。
- 但是不足之处是只能读取此变量,不能改变此变量的值
我们可以参考上面的例子,也添加一个宏开关:
config_gesture_mode
定义此变量:
./frameworks/base/core/res/res/values/symbols.xml:
<java-symbol type="bool" name="config_gesture_mode" />
./frameworks/base/core/res/res/values/config.xml:
<bool name="config_gesture_mode">false</bool>
读取方式:
context.getResources().getBoolean(com.android.internal.R.bool.config_gesture_mode)
SettingProvider
SettingProvider本质是使用contentprovider的跨应用的特性来实现此需求的。
我们先看一个已有的样例:
wifi_scan_always_enabled
定义变量:
./frameworks/base/core/java/android/provider/Settings.java
public static final String WIFI_SCAN_ALWAYS_AVAILABLE =
"wifi_scan_always_enabled";
定义默认值:
./frameworks/base/packages/SettingsProvider/res/values/defaults.xml
<integer name="def_wifi_scan_always_available">0</integer>
将默认值给其赋值:
./frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
loadIntegerSetting(stmt, Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE,
R.integer.def_wifi_scan_always_available);
读写方式:
import android.provider.Settings;
import android.provider.Settings.Global;
Settings.Global.putInt(getContentResolver(),
Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 1);
android.provider.Settings.Global.getInt(getActivity().getContentResolver(), android.provider.Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0)
我们参考此方式,来添加一个宏开关:
leather_sheath
在./frameworks/base/core/java/android/provider/Settings.java文件中定义变量:
public static final String LEATHER_SHEATH = "leather_sheath";
在frameworks/base/packages/SettingsProvider/res/values/defaults.xml定义一个值:
<bool name="def_leather_sheath">true</bool>
将默认值给其赋值:
在./frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java文件中:
loadBooleanSetting(stmt, Settings.Secure.LEATHER_SHEATH, R.bool.def_leather_sheath);
读取方式:
import android.provider.Settings;
Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.LEATHER_SHEATH, 0)
Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.LEATHER_SHEATH, state);
(注):
今天无意中发现,原来,我们不需要在framework下来定义这个db字段,可以直接在app层来新增加一个字段,然后直接使用。
比如:
import android.provider.Settings;
//新增加一个test_set_db,给其赋值
Settings.System.putInt(context.getContentResolver(), "test_set_db", 1);
//新增加一个test_set_db,获取其值
Settings.System.getInt(context.getContentResolver(), "test_set_db", 0)
- 此种方法优点是借用已有的contentprovider,方便简单,并且可以对此开关进行读写操作。
以上是三种添加全局变量宏开关的方法,其优势和不足大家自己比较,选择自己需要的方式。