探索Settings.System.putInt()
2016-07-29 09:53
253 查看
在android系统移植时,经常要保存系统某一变量的值,最简单的方法就是保存到系统数据库中,而不是保存在apk的xml中,只要一句话:
Settings.System.putString(ContentResolver resolver, String name, String value)
读也非常简单:
Settings.System.getString(ContentResolver resolver, String name)
只要带一个Context,就可以读写这个数据库,让我感到困惑的是:对数据库进行操作,插入和修改是两种不同命令,android是怎么知道我到底是进行插入还是修改操作呢?于是跟踪到源码里看个清楚:
首先,数据库保存在哪?
源码路径:
\frameworks\base\packages\SettingsProvider\src\com\android\providers\settings
在 DatabaseHelper类里,创建数据库和表
public class DatabaseHelper extends SQLiteOpenHelper
{
[align=left]
[/align]
[align=left]......[/align]
private void createSecureTable(SQLiteDatabase
db) {
[align=left] db.execSQL( "CREATE TABLE secure (" +[/align]
[align=left] "_id INTEGER PRIMARY KEY AUTOINCREMENT," +[/align]
[align=left] "name TEXT UNIQUE ON CONFLICT REPLACE," +[/align]
[align=left] "value TEXT" +[/align]
[align=left] ");" );[/align]
[align=left] db.execSQL( "CREATE INDEX secureIndex1 ON secure (name);" );[/align]
[align=left] }[/align]
[align=left]
[/align]
private void createGlobalTable(SQLiteDatabase
db) {
[align=left] db.execSQL( "CREATE TABLE global (" +[/align]
[align=left] "_id INTEGER PRIMARY KEY AUTOINCREMENT," +[/align]
[align=left] "name TEXT UNIQUE ON CONFLICT REPLACE," +[/align]
[align=left] "value TEXT" +[/align]
[align=left] ");" );[/align]
[align=left] db.execSQL( "CREATE INDEX globalIndex1 ON global (name);" );[/align]
[align=left] }[/align]
[align=left] @ Override[/align]
public void onCreate(SQLiteDatabase
db) {
[align=left] db.execSQL( "CREATE TABLE system (" +[/align]
[align=left] "_id INTEGER PRIMARY KEY AUTOINCREMENT," +[/align]
[align=left] "name TEXT UNIQUE ON CONFLICT REPLACE," +[/align]
[align=left] "value TEXT" +[/align]
[align=left] ");" );[/align]
[align=left] db.execSQL( "CREATE INDEX systemIndex1 ON system (name);" );[/align]
[align=left]
[/align]
[align=left] createSecureTable(db);[/align]
[align=left]
[/align]
[align=left] // Only create the global table for the singleton 'owner' user[/align]
if (mUserHandle ==
UserHandle.USER_OWNER) {
[align=left] createGlobalTable(db);[/align]
[align=left] }[/align]
[align=left]
[/align]
[align=left] db.execSQL( "CREATE TABLE bluetooth_devices (" +[/align]
[align=left] "_id INTEGER PRIMARY KEY," +[/align]
[align=left] "name TEXT," +[/align]
[align=left] "addr TEXT," +[/align]
[align=left] "channel INTEGER," +[/align]
[align=left] "type INTEGER" +[/align]
[align=left] ");" );[/align]
[align=left]
[/align]
[align=left] db.execSQL( "CREATE TABLE bookmarks (" +[/align]
[align=left] "_id INTEGER PRIMARY KEY," +[/align]
[align=left] "title TEXT," +[/align]
[align=left] "folder TEXT," +[/align]
[align=left] "intent TEXT," +[/align]
[align=left] "shortcut INTEGER," +[/align]
[align=left] "ordering INTEGER" +[/align]
[align=left] ");" );[/align]
[align=left]
[/align]
[align=left] db.execSQL( "CREATE INDEX bookmarksIndex1 ON bookmarks (folder);" );[/align]
[align=left] db.execSQL( "CREATE INDEX bookmarksIndex2 ON bookmarks (shortcut);" );[/align]
[align=left]
[/align]
[align=left] // Populate bookmarks table with initial bookmarks[/align]
[align=left] boolean onlyCore = false ;[/align]
[align=left] try {[/align]
[align=left] onlyCore = IPackageManager.Stub.asInterface(ServiceManager.getService([/align]
[align=left] "package" )).isOnlyCoreApps();[/align]
[align=left] } catch (RemoteException e) {[/align]
[align=left] }[/align]
[align=left] if (!onlyCore) {[/align]
[align=left] loadBookmarks(db);[/align]
[align=left] }[/align]
[align=left]
[/align]
[align=left] // Load initial volume levels into DB[/align]
[align=left] loadVolumeLevels(db);[/align]
[align=left]
[/align]
[align=left] // Load inital settings values[/align]
[align=left] loadSettings(db);[/align]
[align=left] }[/align]
[align=left]
[/align]
[align=left]
[/align]
这里创建了几张表,这个数据库生成的db文件,保存成(在android系统):
/data/data/com.android.providers.settings/databases/settings.db
Settings.System.putString()这个方法是把数据写入到了system表中
至于是插入还是修改,关键在于创建表时执行的SQL语句:
[align=left] "CREATE TABLE secure (" +[/align]
[align=left] "_id INTEGER PRIMARY KEY AUTOINCREMENT," +[/align]
[align=left] "name TEXT UNIQUE ON CONFLICT REPLACE," +[/align]
[align=left] "value TEXT" +[/align]
[align=left] ");"[/align]
[align=left]
[/align]
system表中,总共三个字段:_id name value
再看下name字段: name TEXT UNIQUE ON CONFLICT REPLACE
ON CONFLICT子句可以定义替代的约束冲突判定算法。缺省为ABORT。同一个表中的不同约束可以使用不同的缺省冲突判定算法。若一条COPY、INSERT或UPDATE命令指定了不同的冲突判定算法,则该算法将替代CREATE
TABLE语句中说明的缺省算法
[align=left]
[/align]
ON CONFLICT子句不是独立的SQL命令。这是一条可以出现在许多其他SQL命令中的非标准的子句。由于它并不是标准的SQL语言,这里单独介绍它。
ON CONFLICT子句的语法在如上的CREATE TABLE命令中示出。对于INSERT和UPDATE,关键词“ON CONFLICT”由“OR”替代,这样语法显得自然。例如,不用写“INSERT ON CONFLICT IGNORE”而是“INSERT OR IGNORE”。二者表示相同的意思。
ON CONFLICT子句定义了解决约束冲突的算法。有五个选择:ROLLBACK、ABORT、FAIL、IGNORE和REPLACE,缺省方案是ABORT。选项含义如下:
ROLLBACK
当发生约束冲突,立即ROLLBACK,即结束当前事务处理,命令中止并返回SQLITE_CONSTRAINT代码。若当前无活动事务(除了每一条命令创建的默认事务以外),则该算法与ABORT相同。
ABORT
当发生约束冲突,命令收回已经引起的改变并中止返回SQLITE_CONSTRAINT。但由于不执行ROLLBACK,所以前面的命令产生的改变将予以保留。缺省采用这一行为。
FAIL
当发生约束冲突,命令中止返回SQLITE_CONSTRAINT。但遇到冲突之前的所有改变将被保留。例如,若一条UPDATE语句在100行遇到冲突100th,前99行的改变将被保留,而对100行或以后的改变将不会发生。
IGNORE
当发生约束冲突,发生冲突的行将不会被插入或改变。但命令将照常执行。在冲突行之前或之后的行将被正常的插入和改变,且不返回错误信息。
REPLACE
当发生UNIQUE约束冲突,先存在的,导致冲突的行在更改或插入发生冲突的行之前被删除。这样,更改和插入总是被执行。命令照常执行且不返回错误信息。当发生NOT NULL约束冲突,导致冲突的NULL值会被字段缺省值取代。若字段无缺省值,执行ABORT算法。
当冲突应对策略为满足约束而删除行时,它不会调用删除触发器。但在新版中这一特性可能被改变。
INSERT或UPDATE的OR子句定义的算法会覆盖CREATE TABLE所定义的。ABORT算法将在没有定义任何算法时缺省使用。-->这就是关键
以上是数据库部分
Settings.System源码路径:
frameworks\base\core\java\android\provider
protected static boolean putString(ContentResolver
resolver, Uri uri,
String name, String value) {
// The database will take care of replacing duplicates.
try {
ContentValues values = new ContentValues();
values.put( NAME , name);
values.put( VALUE , value);
resolver.insert(uri, values);
return true ;
} catch (SQLException e) {
Log. w( TAG , "Can't
set key " + name + " in " + uri, e);
return false ;
}
}
Settings.System.putString(ContentResolver resolver, String name, String value)
读也非常简单:
Settings.System.getString(ContentResolver resolver, String name)
只要带一个Context,就可以读写这个数据库,让我感到困惑的是:对数据库进行操作,插入和修改是两种不同命令,android是怎么知道我到底是进行插入还是修改操作呢?于是跟踪到源码里看个清楚:
首先,数据库保存在哪?
源码路径:
\frameworks\base\packages\SettingsProvider\src\com\android\providers\settings
在 DatabaseHelper类里,创建数据库和表
public class DatabaseHelper extends SQLiteOpenHelper
{
[align=left]
[/align]
[align=left]......[/align]
private void createSecureTable(SQLiteDatabase
db) {
[align=left] db.execSQL( "CREATE TABLE secure (" +[/align]
[align=left] "_id INTEGER PRIMARY KEY AUTOINCREMENT," +[/align]
[align=left] "name TEXT UNIQUE ON CONFLICT REPLACE," +[/align]
[align=left] "value TEXT" +[/align]
[align=left] ");" );[/align]
[align=left] db.execSQL( "CREATE INDEX secureIndex1 ON secure (name);" );[/align]
[align=left] }[/align]
[align=left]
[/align]
private void createGlobalTable(SQLiteDatabase
db) {
[align=left] db.execSQL( "CREATE TABLE global (" +[/align]
[align=left] "_id INTEGER PRIMARY KEY AUTOINCREMENT," +[/align]
[align=left] "name TEXT UNIQUE ON CONFLICT REPLACE," +[/align]
[align=left] "value TEXT" +[/align]
[align=left] ");" );[/align]
[align=left] db.execSQL( "CREATE INDEX globalIndex1 ON global (name);" );[/align]
[align=left] }[/align]
[align=left] @ Override[/align]
public void onCreate(SQLiteDatabase
db) {
[align=left] db.execSQL( "CREATE TABLE system (" +[/align]
[align=left] "_id INTEGER PRIMARY KEY AUTOINCREMENT," +[/align]
[align=left] "name TEXT UNIQUE ON CONFLICT REPLACE," +[/align]
[align=left] "value TEXT" +[/align]
[align=left] ");" );[/align]
[align=left] db.execSQL( "CREATE INDEX systemIndex1 ON system (name);" );[/align]
[align=left]
[/align]
[align=left] createSecureTable(db);[/align]
[align=left]
[/align]
[align=left] // Only create the global table for the singleton 'owner' user[/align]
if (mUserHandle ==
UserHandle.USER_OWNER) {
[align=left] createGlobalTable(db);[/align]
[align=left] }[/align]
[align=left]
[/align]
[align=left] db.execSQL( "CREATE TABLE bluetooth_devices (" +[/align]
[align=left] "_id INTEGER PRIMARY KEY," +[/align]
[align=left] "name TEXT," +[/align]
[align=left] "addr TEXT," +[/align]
[align=left] "channel INTEGER," +[/align]
[align=left] "type INTEGER" +[/align]
[align=left] ");" );[/align]
[align=left]
[/align]
[align=left] db.execSQL( "CREATE TABLE bookmarks (" +[/align]
[align=left] "_id INTEGER PRIMARY KEY," +[/align]
[align=left] "title TEXT," +[/align]
[align=left] "folder TEXT," +[/align]
[align=left] "intent TEXT," +[/align]
[align=left] "shortcut INTEGER," +[/align]
[align=left] "ordering INTEGER" +[/align]
[align=left] ");" );[/align]
[align=left]
[/align]
[align=left] db.execSQL( "CREATE INDEX bookmarksIndex1 ON bookmarks (folder);" );[/align]
[align=left] db.execSQL( "CREATE INDEX bookmarksIndex2 ON bookmarks (shortcut);" );[/align]
[align=left]
[/align]
[align=left] // Populate bookmarks table with initial bookmarks[/align]
[align=left] boolean onlyCore = false ;[/align]
[align=left] try {[/align]
[align=left] onlyCore = IPackageManager.Stub.asInterface(ServiceManager.getService([/align]
[align=left] "package" )).isOnlyCoreApps();[/align]
[align=left] } catch (RemoteException e) {[/align]
[align=left] }[/align]
[align=left] if (!onlyCore) {[/align]
[align=left] loadBookmarks(db);[/align]
[align=left] }[/align]
[align=left]
[/align]
[align=left] // Load initial volume levels into DB[/align]
[align=left] loadVolumeLevels(db);[/align]
[align=left]
[/align]
[align=left] // Load inital settings values[/align]
[align=left] loadSettings(db);[/align]
[align=left] }[/align]
[align=left]
[/align]
[align=left]
[/align]
这里创建了几张表,这个数据库生成的db文件,保存成(在android系统):
/data/data/com.android.providers.settings/databases/settings.db
Settings.System.putString()这个方法是把数据写入到了system表中
至于是插入还是修改,关键在于创建表时执行的SQL语句:
[align=left] "CREATE TABLE secure (" +[/align]
[align=left] "_id INTEGER PRIMARY KEY AUTOINCREMENT," +[/align]
[align=left] "name TEXT UNIQUE ON CONFLICT REPLACE," +[/align]
[align=left] "value TEXT" +[/align]
[align=left] ");"[/align]
[align=left]
[/align]
system表中,总共三个字段:_id name value
再看下name字段: name TEXT UNIQUE ON CONFLICT REPLACE
ON CONFLICT子句可以定义替代的约束冲突判定算法。缺省为ABORT。同一个表中的不同约束可以使用不同的缺省冲突判定算法。若一条COPY、INSERT或UPDATE命令指定了不同的冲突判定算法,则该算法将替代CREATE
TABLE语句中说明的缺省算法
[align=left]
[/align]
ON CONFLICT子句不是独立的SQL命令。这是一条可以出现在许多其他SQL命令中的非标准的子句。由于它并不是标准的SQL语言,这里单独介绍它。
ON CONFLICT子句的语法在如上的CREATE TABLE命令中示出。对于INSERT和UPDATE,关键词“ON CONFLICT”由“OR”替代,这样语法显得自然。例如,不用写“INSERT ON CONFLICT IGNORE”而是“INSERT OR IGNORE”。二者表示相同的意思。
ON CONFLICT子句定义了解决约束冲突的算法。有五个选择:ROLLBACK、ABORT、FAIL、IGNORE和REPLACE,缺省方案是ABORT。选项含义如下:
ROLLBACK
当发生约束冲突,立即ROLLBACK,即结束当前事务处理,命令中止并返回SQLITE_CONSTRAINT代码。若当前无活动事务(除了每一条命令创建的默认事务以外),则该算法与ABORT相同。
ABORT
当发生约束冲突,命令收回已经引起的改变并中止返回SQLITE_CONSTRAINT。但由于不执行ROLLBACK,所以前面的命令产生的改变将予以保留。缺省采用这一行为。
FAIL
当发生约束冲突,命令中止返回SQLITE_CONSTRAINT。但遇到冲突之前的所有改变将被保留。例如,若一条UPDATE语句在100行遇到冲突100th,前99行的改变将被保留,而对100行或以后的改变将不会发生。
IGNORE
当发生约束冲突,发生冲突的行将不会被插入或改变。但命令将照常执行。在冲突行之前或之后的行将被正常的插入和改变,且不返回错误信息。
REPLACE
当发生UNIQUE约束冲突,先存在的,导致冲突的行在更改或插入发生冲突的行之前被删除。这样,更改和插入总是被执行。命令照常执行且不返回错误信息。当发生NOT NULL约束冲突,导致冲突的NULL值会被字段缺省值取代。若字段无缺省值,执行ABORT算法。
当冲突应对策略为满足约束而删除行时,它不会调用删除触发器。但在新版中这一特性可能被改变。
INSERT或UPDATE的OR子句定义的算法会覆盖CREATE TABLE所定义的。ABORT算法将在没有定义任何算法时缺省使用。-->这就是关键
以上是数据库部分
Settings.System源码路径:
frameworks\base\core\java\android\provider
protected static boolean putString(ContentResolver
resolver, Uri uri,
String name, String value) {
// The database will take care of replacing duplicates.
try {
ContentValues values = new ContentValues();
values.put( NAME , name);
values.put( VALUE , value);
resolver.insert(uri, values);
return true ;
} catch (SQLException e) {
Log. w( TAG , "Can't
set key " + name + " in " + uri, e);
return false ;
}
}
相关文章推荐
- 探索Settings.System.putInt()
- Android 应用程序分析之Settings.System.putInt
- Android 应用程序分析之Settings.System.putInt
- Android应用保存数据到系统数据库(Settings.System.putString、Settings.System.putInt)
- Android应用保存数据到系统数据库(Settings.System.putString、Settings.System.putInt)
- Android 应用程序分析之Settings.System.putInt
- Settings.System.getInt获取Setting里的设置信息
- Settings.System.putXXX数据变化,ContentObserver监听
- 获得当前系统设置界面里设置的参数Settings.System.getInt
- “System.Configuration.ConfigurationSettings.AppSettings”已过时
- Ubuntu 14.04 没有system settings的解决办法
- “System.Configuration.ConfigurationSettings.AppSettings”已过时
- It is not safe to rely on the system's timezone settings
- Android Settings.System的使用
- CentOS 6.5 [PHP Error] strftime(): It is not safe to rely on the system's timezone settings.
- 关于Settings.Global /Secure/System
- System.Configuration.ConfigurationSettings.AppSettings 已过时
- ubuntu system settings 打不开
- [导入]CLR探索系列:System.Object内存布局模型及实现研究
- 解决php的“It is not safe to rely on the system’s timezone settings”问题