A左右ndroid正在使用Uri监视数据库中的更改
在监控数据库在线原创文章是非常小的变化,基本上没有找到一个实际的问题。所以,如果你看到一个有点蓝牙源代码,写一个Demo。在这里,供大家参考,查看源代码:
src有三个文件MyDataProvider、MainActivity和MyBean。看以下:
MyDataProvider.java:
public class MyDataProvider extends ContentProvider
{ // public static final String SCHEME = "test";
public static final String SCHEME = "content"; // 源代码里面规定这样写,所以这个地方改变不了 public static final String HOST = "com.zyj";
public static final String PORT = "497393102";
public static final String PATH = "simple"; public static final int ALARMS = 1;
public static final String SHARE_LIST_TYPE = "com.zyj.test.dir/";
public static final int ALARMS_ID = 2;
public static final String SHARE_TYPE = "com.zyj.test.item/"; private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); private SQLiteOpenHelper mDB = null; // ===content://com.zyj:497393102/simple
public static final Uri CONTENT_URI = Uri.parse(SCHEME + "://" + HOST + ":" + PORT + "/" + PATH); // 加入Uri的匹配方式,返回的就是上面自己定义的整数类型。1代表操作的是一个批量,2操作的是单独的一个对象
static
{
sURIMatcher.addURI(HOST + ":" + PORT, PATH, ALARMS);
sURIMatcher.addURI(HOST + ":" + PORT, PATH + "/#", ALARMS_ID);
} @Override
public boolean onCreate()
{
mDB = new MyDB(getContext()); // 获取数据库的引用
return mDB != null;
} @Override
public String getType(Uri uri)
{
// 得到我们自己定义的Uri的类型。看上面你自己的定义
int match = sURIMatcher.match(uri);
switch (match)
{
case ALARMS:
{
return SHARE_LIST_TYPE;
}
case ALARMS_ID:
{
return SHARE_TYPE;
}
default:
{
throw new IllegalArgumentException("Unknown URI: " + uri);
}
}
} @Override
public Uri insert(Uri uri, ContentValues values)
{
// 首先是看Uri和我们自己定义的是否匹配。,匹配则将数据属性插入到数据库中并同志更新
SQLiteDatabase db = mDB.getWritableDatabase();
if (sURIMatcher.match(uri) != ALARMS)
{
throw new IllegalArgumentException("Unknown/Invalid URI " + uri);
} ContentValues filteredValues = new ContentValues();
filteredValues.put(MyDB.BEAN_ID, values.getAsInteger(MyDB.BEAN_ID));
filteredValues.put(MyDB.MESSAGE, values.getAsString(MyDB.MESSAGE));
filteredValues.put(MyDB.TASK_PROGRESS, values.getAsFloat(MyDB.TASK_PROGRESS));
long rowID = db.insert(MyDB.TABLET, null, filteredValues);
if (rowID != -1)
{
getContext().getContentResolver().notifyChange(uri, null);
}
return CONTENT_URI;
} @Override
public int delete(Uri uri, String selection, String[] selectionArgs)
{ // 首先是看Uri和我们自己定义的是否匹配,,匹配则进行删除 SQLiteDatabase db = mDB.getWritableDatabase();
int count = 0;
int match = sURIMatcher.match(uri);
switch (match)
{
case ALARMS:
case ALARMS_ID:
String where = null;
// 这里对selection进行匹配操作,看你传递的是一个批量还是一个单独的文件
if (selection != null)
{
if (match == ALARMS)
{
where = "( " + selection + " )";
}
else
{
where = "( " + selection + " ) AND ";
}
}
else
{
where = "";
}
if (match == ALARMS_ID)
{
// 假设你传递的是一个单独的文件,也就是Uri后面加入了/item的,那么在这里把该值与数据库中的属性段进行比較,返回sql语句中的where
String segment = uri.getPathSegments().get(1);
long rowId = Long.parseLong(segment);
where += " ( " + MyDB.BEAN_ID + " = " + rowId + " ) ";
}
count = db.delete(MyDB.TABLET, where, selectionArgs);
break;
default:
throw new UnsupportedOperationException("Cannot delete URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
} @Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
{
// 基本同上了
SQLiteDatabase db = mDB.getWritableDatabase(); int count;
long rowId = 0; int match = sURIMatcher.match(uri);
switch (match)
{
case ALARMS:
case ALARMS_ID:
{
String myWhere;
if (selection != null)
{
if (match == ALARMS)
{
myWhere = "( " + selection + " )";
}
else
{
myWhere = "( " + selection + " ) AND ";
}
}
else
{
myWhere = "";
}
if (match == ALARMS_ID)
{
String segment = uri.getPathSegments().get(1);
rowId = Long.parseLong(segment);
myWhere += " ( " + MyDB.BEAN_ID + " = " + rowId + " ) ";
} if (values.size() > 0)
{
count = db.update(MyDB.TABLET, values, myWhere, selectionArgs);
}
else
{
count = 0;
}
break;
}
default:
{
throw new UnsupportedOperationException("Cannot update URI: " + uri);
}
}
getContext().getContentResolver().notifyChange(uri, null); return count;
} @Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
{
SQLiteDatabase db = mDB.getReadableDatabase();
SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); //SQLiteQueryBuilder是一个构造SQL查询语句的辅助类 int match = sURIMatcher.match(uri);
switch (match)
{
case ALARMS:
{
qb.setTables(MyDB.TABLET);
break;
}
case ALARMS_ID:
{
qb.setTables(MyDB.TABLET);
qb.appendWhere(MyDB.BEAN_ID + "=");
qb.appendWhere(uri.getPathSegments().get(1));
break;
}
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
Cursor ret = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder); if (ret != null)
{
ret.setNotificationUri(getContext().getContentResolver(), uri);
Log.d("zyj", "created cursor " + ret + " on behalf of ");
}
else
{
Log.d("zyj", "query failed in downloads database");
}
return ret;
} private static class MyDB extends SQLiteOpenHelper
{ // 这里就是数据库了,数据库字段、名称、表名等...
private static final String DATABASE = "test_database";
public static final String TABLET = "test_table";
public static String ID = "_id";
public static String BEAN_ID = "_bean_id";
public static String MESSAGE = "_message";
public static String TASK_PROGRESS = "_progress"; private SQLiteDatabase mDB = null; private final String msql = "CREATE TABLE IF NOT EXISTS " + TABLET + "( " + ID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, " + BEAN_ID + " TEXT, " + MESSAGE + " TEXT, " + TASK_PROGRESS
+ " TEXT )"; private MyDB(Context context)
{
super(context, DATABASE, null, 1);
} @Override
public void onCreate(SQLiteDatabase db)
{
mDB = db;
mDB.execSQL(msql);
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
// 升级。自己能够去实现
}
}
}
MyBean.java一个实例对象
public class MyBean
{ public int id = 0; public String message = null; public float progress = 0.0f; public MyBean(int id)
{
this.id = id;
} }
MainActivity.java主界面了
public class MainActivity extends Activity
{ TextView mMessage = null; private ContentObserver mDatabaseListener = null;
private Handler mHand = null; @Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mMessage = (TextView) findViewById(R.id.message); init(); // 注冊数据库的监听。相应的是特定的Uri
getContentResolver().registerContentObserver(MyDataProvider.CONTENT_URI, true, mDatabaseListener);
} @Override
protected void onDestroy()
{
super.onDestroy();
// 注销掉监听
getContentResolver().unregisterContentObserver(mDatabaseListener);
} private void init()
{
mHand = new Handler();
// 数据库变动时的回调
mDatabaseListener = new ContentObserver(mHand)
{
@Override
public boolean deliverSelfNotifications()
{
System.out.println("deliverSelfNotifications ---------------- ");
return super.deliverSelfNotifications();
} @Override
public void onChange(boolean selfChange, Uri uri)
{
System.out.println("onChange ---------------- " + uri.toString());
super.onChange(selfChange, uri);
} @Override
public void onChange(boolean selfChange)
{
System.out.println("onChange ---------------- ...");
super.onChange(selfChange);
}
};
} private int count = 0; public void onViewClick(View view)
{
switch (view.getId())
{
case R.id.add:
// 插入数据
ContentValues calues = new ContentValues();
calues.put("_bean_id", count++);
calues.put("_message", "AAAAAAAAAAAAAAAAAAAAA");
calues.put("_progress", 0.0f);
getContentResolver().insert(MyDataProvider.CONTENT_URI, calues);
break;
case R.id.del:
// 假设找不到指定的_bean_id=1、2、3的,则数据库不进行增减。但还是会调用回调方法
getContentResolver().delete(Uri.parse(MyDataProvider.CONTENT_URI.toString() + "/1"), null, null);
getContentResolver().delete(Uri.parse(MyDataProvider.CONTENT_URI.toString() + "/2"), null, null);
getContentResolver().delete(Uri.parse(MyDataProvider.CONTENT_URI.toString() + "/3"), null, null);
break;
case R.id.modify:
ContentValues values = new ContentValues();
values.put("_message", "ZZZZZZZZZZZZZZZZZZZZZ");
// 这两中方法一样,这样就能够更加明确Uri中在后面加入的/item了数字的意思了
getContentResolver()
.update(Uri.parse(MyDataProvider.CONTENT_URI.toString() + "/5"), values, null, null);
getContentResolver().update(MyDataProvider.CONTENT_URI, values, "_bean_id=? ", new String[] { "6" });
break;
case R.id.query:
showMessage(getContentResolver().query(MyDataProvider.CONTENT_URI, null, null, null, null));
break;
}
} private void showMessage(Cursor c)
{
if (c == null)
{
return;
}
final StringBuffer sb = new StringBuffer();
if (c.getCount() > 0)
{
while (c.moveToNext())
{
MyBean bean = new MyBean(c.getInt(c.getColumnIndex("_bean_id")));
bean.message = c.getString(c.getColumnIndex("_message"));
bean.progress = c.getFloat(c.getColumnIndex("_progress"));
sb.append(bean.id + "\t\t\t:" + bean.message + "\t\t\t,progress = " + bean.progress + "\n");
}
} c.close(); mHand.post(new Runnable()
{
public void run()
{
mMessage.setText(sb.toString());
}
});
}
}
activity_main.xml 上面就是四个button,以下就是一个TextView显示控件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10.0dip" > <LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:orientation="vertical" > <Button
android:id="@+id/add"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="onViewClick"
android:text="Add" /> <Button
android:id="@+id/del"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="onViewClick"
android:text="Delete" /> <Button
android:id="@+id/modify"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="onViewClick"
android:text="Modify" /> <Button
android:id="@+id/query"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="onViewClick"
android:text="Query" />
</LinearLayout> <ScrollView
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:maxHeight="20dip" > <TextView
android:id="@+id/message"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="20sp" />
</ScrollView> </LinearLayout>
最后就是AndroidManifest.xml了。和平时一样的,仅仅只是在里面将你自定义的ContentProvider写上,类似我的这样:
<provider
android:name="com.example.databasetest.MyDataProvider"
android:authorities="com.zyj:497393102" />
上面的authorities属性是一定要写的。它就是上面MyDataProvider.java里面的CONTENT_URI的HOST + ":" + PORT,能够看以下画的。就比較清楚了。
content://com.example.project:200/folder/subfolder/etc
\---------/ \---------------------------/ \---/ \--------------------------/
scheme host port path
\--------------------------------/
authority
然后就没有了,能够自己执行,感受一下Uri和数据库的监听。
有错误我希望你能来部出,谢谢!!
!
版权声明:本文博主原创文章,博客,未经同意不得转载。
A左右ndroid正在使用Uri监视数据库中的更改的更多相关文章
- list utilities监视数据库前滚操作
您可以使用 db2pd 或 LIST UTILITIES 命令来监视数据库前滚操作的进度. 过程 发出 LIST UTILITIES 命令并指定 SHOW DETAIL 参数 db2 LIST UTI ...
- [转]SQL server 2008R2 中 C#Winfoirm 使用 SqlDependency 机制实现 数据库中某一张表的监视
转自:https://blog.csdn.net/u012183487/article/details/77776930 System.Data.SqlClient命名空间下的 sqlDependen ...
- 腾讯优测干货精选|Android双卡双待适配——隐藏在数据库中的那些秘密
腾讯优测是专业的app自动化测试平台,除了提供兼容性测试,远程真机租用等多维度的测试服务,还有优分享-腾讯内部的移动研发测试干货精选~ 许多APP都希望获取用户通讯录联系人,利用通讯录关系链信息来丰富 ...
- 数据库中触发器before与after认识
Before与After区别: before:(insert.update)可以对new进行修改,after不能对new进行修改,两者都不能修改old数据. 对于INSERT语句, 只有NEW是合法的 ...
- MVC模式:实现数据库中数据的增删改查功能
*.数据库连接池c3p0,连接mysql数据库: *.Jquery使用,删除时跳出框,确定是否要删除: *.使用EL和JSTL,简化在jsp页面中插入的java语言 1.连接数据库 (1)导入连接数据 ...
- 如何找出MySQL数据库中的低效SQL语句
面对业务的迅猛发展,DBA的一项重要工作就是及时发现数据库中的低效SQL语句,有的可以立刻着手解决(比如缺少合适的索引),有的需要尽快反馈给开发人员进行修改. MySQL数据库有几个配置选项可以帮助我 ...
- SQL server数据库中的DateTime类型出现的问题
我们知道这个SQL server数据库中的DateTime类型是数据库应用开发中经经常使用到的一种数据类型.而C#语言中也有DateTime类型,尽管二者都是用来描写叙述时间的,可是它们的默认值是不同 ...
- Android端上传图片到后台,存储到数据库中 详细代码
首先点击头像弹出popwindow,点击相册,相机,调用手机自带的裁剪功能,然后异步任务类访问服务器,上传头像,保存到数据库中, 下面写出popwindow的代码 //设置popwindow publ ...
- 使用SignalR和SQLTableDependency跟踪数据库中记录的变动
原文地址:查看 SqlTableDependency是一个组件用来接收数据库的通知,包含在数据表上该记录的值的Inserted.Deleted或者Update操作. 备注:原文提供示例代码下载,但是j ...
随机推荐
- 从零开始,使用python快速开发web站点(2)
书接上文.http://blog.csdn.net/i7788/article/details/10306595 首先是数据库的搭建,这里的django的数据模型搭建十分easy. no sql.ju ...
- IO流的总结
流操作的基本规律: 最痛苦的就是流对象有非常多.不知道该用那一个. 通过明白来完毕. (1).明白源和目的 源:输入流InputStream Reader 目的:输出流OutputStream Wri ...
- 祖国版SoloWheel:Airwheel爱尔威火星车 拆箱&上手经验_运动户外_晒物广场_什么值得买
http://m.baidu.com/from=844b/bd_page_type=1/ssid=0/uid=3151E6C0905477A13653132D762BB6FB/pu=sz%401320 ...
- Xenu-web开发死链接检測工具应用
Xenu 是一款深受业界好评,并被广泛使用的死链接检測工具. 时常检測站点并排除死链接,对站点的SEO 很重要,由于大量死链接存在会减少用户和搜索引擎对站点的信任,web程序开发者还可通过其找到死链接 ...
- jquery validation remote depends 验证触发条件
背景: 1:简介页面的变化: 2:邮箱不能反复 改动页面,邮箱默认带出,但字段上带有remote验证.不能反复,焦点由邮箱输入框失去时.会默认触发remote验证. 介绍完成 watermark/2/ ...
- ArcGIS For Flex给定两个
1.错误叙述性说明 2.错误原因 3.解决方案 版权声明:本文博客原创文章,博客,未经同意,不得转载.
- js实现页面重定位的几种方法
参考地址:http://www.cnblogs.com/super-d2/archive/2011/10/01/2197004.html js实现页面重定向 在现行的网站应用中URL重定向的应用有很多 ...
- HashMap-死锁导致cpu占用100%分析(转)
最近项目里面的一段千年代码出了问题,这个问题以前也出现过,不过不是那么明显,这次迁移机器由以前的4台机子变成2台以后问题被放大,最终不得不解决,特此分析一下. 先放出问题的代码 ? 1 2 3 4 5 ...
- Linux php/php-fpm 安装,配置
1> 下载php源代码 #wget http://cn2.php.net/get/php-5.4.30.tar.gz/from/this/mirror 官网5.2的版本号貌似没提供 ...
- _00019 Storm架构介绍和Storm获取案例(简单的官方网站Java案例)
博文作者:妳那伊抹微笑 itdog8 地址链接 : http://www.itdog8.com(个人链接) 博客地址:http://blog.csdn.net/u012185296 博文标题:_000 ...