android uri db,Android ContentProvider封装数据库和文件读写总结

本文是我各处东拼西凑加上自己实现一个ContentProvider的使用总结,留做后用,主要介绍ContentProvider的集成方法。

一、综述

ContentProvider是Android四大组件之一,其核心功能是提供应用间的统一的数据访问方式,当然也可以用于应用内的数据封装。ContentProvider类似C/S结构,应用A实现ContentProvider向外提供应用内的数据访问,应用B使用Context.getContentResolver()来间接与应用A的Provider交互。

ContentProvider提供一套类似数据库的query/delete/insert/update的方法来操作数据,开发者可以以此来屏蔽管理数据的真正方式 (SharePreference/File/SQLite等)。另外,ContentProvider也提供了直接操作文件的方式(覆写openFile),第三方应用可以通过该方式读写当前应用的私有文件(data/data等)。

二、相关知识

2.1 UriMatcher和ContentUris的使用

UriMatcher主要用户判断Uri是否符合特定格式,用法如下:

private static final int TYPE_ALL = 1;

private static final int TYPE_SINGLE = 2;

private static UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

static {

mUriMatcher.addURI(AUTHORITY, "person", TYPE_ALL);

mUriMatcher.addURI(AUTHORITY, "person/#", TYPE_SINGLE);//#号表示一个数字

}

以上为其声明与配置,下面是使用方法:

switch (mUriMatcher.match(uri)) {

case TYPE_ALL:

//uri匹配到第一种类型

case TYPE_SINGLE:

//uri匹配到第二种类型

default:

//uri没有匹配到这两种类型

}

这样我们就可以知道外部传入的Uri的类型了。

2.2 ContentUris用法

ContentUris用于处理Uri后面的id部分(纯数字),常用函数有:

parseId(uri): 解析Uri里的最后的id

withAppendedId(uri, id):在路径后面加上id部分

三、封装ContentProvider的步骤

提供Provider的工程简称应用A。下面是封装ContentProvider的步骤:

3.1 在Manifest中声明ContentProvider:

android:authorities="org.test.auth"

android:exported="true"/>

声明后,应用安装到设备上第三方应用就能通过ContentResolver访问此Provider。

3.2 ContentProvider的代码

package org.test.auth;

import java.io.File;

import java.io.FileNotFoundException;

import android.content.ContentProvider;

import android.content.ContentUris;

import android.content.ContentValues;

import android.content.UriMatcher;

import android.database.Cursor;

import android.database.sqlite.SQLiteDatabase;

import android.net.Uri;

import android.os.ParcelFileDescriptor;

import android.text.TextUtils;

import android.util.Log;

public class MyDataProvider extends ContentProvider {

private static final String AUTHORITY = "org.test.auth";

private static final int TYPE_ALL = 1;

private static final int TYPE_SINGLE = 2;

private static final String TAG = "TEST111_DataProvider";

private MyDBHelper mDbHelper;

private SQLiteDatabase mDatabase;

private static UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

static {

mUriMatcher.addURI(AUTHORITY, "person", TYPE_ALL);

mUriMatcher.addURI(AUTHORITY, "person/#", TYPE_SINGLE);

}

@Override

public int delete(Uri uri, String selection, String[] selectionArgs) {

switch (mUriMatcher.match(uri)) {

case TYPE_ALL:

return mDatabase.delete(MyDBHelper.TABLE_NAME,

selection,

selectionArgs);

case TYPE_SINGLE:

long id = ContentUris.parseId(uri);

String where = MyDBHelper.COLUMN_ID + " = " + id;

if(!TextUtils.isEmpty(selection)) {

where = where + " and " + selection;

}

return mDatabase.delete(MyDBHelper.TABLE_NAME,

where,

selectionArgs);

default:

return -1;

}

}

@Override

public String getType(Uri uri) {

switch (mUriMatcher.match(uri)) {

case TYPE_ALL:

return "vnd.android.cursor.dir/person";

case TYPE_SINGLE:

return "vnd.android.cursor.item/person";

default:

return null;

}

}

@Override

public Uri insert(Uri uri, ContentValues values) {

//由于此时的values中具体是否含有数据是不确定的,所以此时需要在第二个参数中添加person表中的非主键的一列

long id = mDatabase.insert(MyDBHelper.TABLE_NAME, MyDBHelper.COLUMN_NAME, values);

return ContentUris.withAppendedId(uri, id);

}

@Override

public boolean onCreate() {

mDbHelper = new MyDBHelper(getContext());

mDatabase = mDbHelper.getWritableDatabase();

return true;

}

@Override

public Cursor query(Uri uri, String[] columns,

String selection, String[] selectionArgs,

String orderBy) {

switch (mUriMatcher.match(uri)) {

case TYPE_ALL:

return mDatabase.query(MyDBHelper.TABLE_NAME, columns, selection, selectionArgs, null, null, orderBy);

case TYPE_SINGLE:

long id = ContentUris.parseId(uri);

String where = MyDBHelper.COLUMN_ID + " = " + id;

if(!TextUtils.isEmpty(selection)) {

where = where + " and " + selection;

}

return mDatabase.query(MyDBHelper.TABLE_NAME, columns, where, selectionArgs, null, null, orderBy);

default:

return null;

}

}

@Override

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {

switch (mUriMatcher.match(uri)) {

case TYPE_ALL:

return mDatabase.update(MyDBHelper.TABLE_NAME, values,

selection, selectionArgs);

case TYPE_SINGLE:

long id = ContentUris.parseId(uri);

String where = MyDBHelper.COLUMN_ID + " = " + id;

if(!TextUtils.isEmpty(selection)) {

where = where + " and " + selection;

}

return mDatabase.update(MyDBHelper.TABLE_NAME, values,

where, selectionArgs);

default:

return -1;

}

}

@Override

public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {

File root = new File(getContext().getFilesDir() + "/" + uri.getPath());

root.getParentFile().mkdirs();

int imode = 0;

if (mode.contains("w")) {

imode |= ParcelFileDescriptor.MODE_WRITE_ONLY;

if (!root.exists()) {

try {

root.createNewFile();

} catch (Exception ex) {

Log.d(TAG, "error happened", ex);

}

}

}

if (mode.contains("r")) imode |= ParcelFileDescriptor.MODE_READ_ONLY;

if (mode.contains("+")) imode |= ParcelFileDescriptor.MODE_APPEND;

return ParcelFileDescriptor.open(root, imode);

}

}

此示例中使用的数据操作方式是数据库,onCreate执行ContentProvider启动时的初始化操作,query/insert/delete/update操作数据,getType返回指定Uri对应的数据类型。“vnd.android.cursor.dir”表示cursor集合,“vnd.android.cursor.item”表示cursor条目。

覆写openFile方法提供私有文件的对外访问,在该方法内可以控制是否提供文件读写,本例代码来自网络,支持读写操作。

附上数据库帮助类代码:

package org.test.auth;

import android.content.Context;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteOpenHelper;

public class MyDBHelper extends SQLiteOpenHelper {

public static final String DB_NAME = "test.db";

public static final String TABLE_NAME = "person";

public static final String COLUMN_ID = "_id";

public static final String COLUMN_AGE = "age";

public static final String COLUMN_NAME = "name";

public static final int DB_VERSION = 1;

public MyDBHelper(Context context) {

super(context, DB_NAME, null, DB_VERSION);

}

@Override

public void onCreate(SQLiteDatabase database) {

String sql = "create table if not exists " + TABLE_NAME + "( " +

COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +

COLUMN_NAME +" varchar(100), " +

COLUMN_AGE + " integer" +

" )" ;

database.execSQL(sql);

}

@Override

public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {

}

}

四、测试代码

测试代码在另一个工程中,简称应用B。

package com.example.testcontentprovider;

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileNotFoundException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.io.OutputStreamWriter;

import android.app.Activity;

import android.content.ContentResolver;

import android.content.ContentValues;

import android.database.Cursor;

import android.net.Uri;

import android.os.Bundle;

import android.os.ParcelFileDescriptor;

import android.util.Log;

public class MainActivity extends Activity {

private static final String URI = "content://org.test.auth/person";

private static final String TAG = "TEST111_";

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

doTest();

}

private void doTest() {

ContentResolver cr = getContentResolver();

String typeAll = cr.getType(Uri.parse(URI));

Log.d(TAG, "get all type= " + typeAll);

String typeOne = cr.getType(Uri.parse(URI + "/1"));

Log.d(TAG, "get one type= " + typeOne);

insertValue(cr, "张三", 12);

insertValue(cr, "李四", 23);

//查询所有数据

query(cr, -1);

//查询单条数据

query(cr, 1);

//更改id=1的数据

updateValue(cr, 1, "王五", 20, null, null);

//查询所有数据

query(cr, -1);

//更改name=李四的数据

updateValue(cr, 2, "哈哈", 34, "name=?", new String[] {"李四"});

//查询所有数据

query(cr, -1);

//更改所有数据

updateValue(cr, -1, "小明", 15, null, null);

//查询所有数据

query(cr, -1);

//删除id=1数据

int affectedColumnCountOne = cr.delete(Uri.parse(URI + "/1"), null, null);

Log.d(TAG, "delete one affectedColumnCount= " + affectedColumnCountOne);

//查询所有数据

query(cr, -1);

//删除所有数据

int affectedColumnCountAll = cr.delete(Uri.parse(URI), null, null);

Log.d(TAG, "delete all affectedColumnCount= " + affectedColumnCountAll);

//查询所有数据

query(cr, -1);

//测试文件读写

try {

OutputStream os = cr.openOutputStream(Uri.parse(URI+"/provider_file.txt"));

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));

bw.append("think who am I?!");

bw.flush();

bw.close();

InputStream is = cr.openInputStream(Uri.parse(URI+"/provider_file.txt"));

BufferedReader br = new BufferedReader(new InputStreamReader(is));

String result = br.readLine();

br.close();

Log.d(TAG, "read file result : " + result);

} catch (Exception e) {

Log.d(TAG, "file op failed", e);

}

}

private void query(ContentResolver cr, int id) {

String idCause = "";

if(id >= 0) {

idCause = "/" + id;

}

Cursor cursorResultAll = cr.query(Uri.parse(URI + idCause), null, null, null, null);

if(null != cursorResultAll) {

while(cursorResultAll.moveToNext()) {

int result = cursorResultAll.getInt(0);

String name = cursorResultAll.getString(1);

int age = cursorResultAll.getInt(2);

Log.d(TAG, "query()| originid= " + id +"; id = " + result + " name= " + name + " age= " + age);

}

}

}

private void insertValue(ContentResolver cr, String name, int age) {

ContentValues value = new ContentValues();

value.put("name", name);

value.put("age", age);

Uri insertColumn = cr.insert(Uri.parse(URI), value);

Log.d(TAG, "insertValue() insert at column: " + insertColumn);

}

private void updateValue(ContentResolver cr, int id, String name, int age,

String selection, String[] selectionArgs) {

if (id >= 0) {

ContentValues value = new ContentValues();

value.put("name", name);

value.put("age", age);

int affectedColumnCount = cr.update(Uri.parse(URI + "/" + id), value, selection, selectionArgs);

Log.d(TAG, "updateValue() affectedColumnCount: " + affectedColumnCount);

} else {

ContentValues value = new ContentValues();

value.put("name", name);

value.put("age", age);

int affectedColumnCount = cr.update(Uri.parse(URI), value,

selection, selectionArgs);

Log.d(TAG, "updateValue() affectedColumnCount: " + affectedColumnCount);

}

}

}

以上,就是实现一个ContentProvider的方法,后续需要补充ContentProvider的原理部分,据说进程间通信是基于共享内存的,以后有时间需要分析一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/346579.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ddos攻击工具_简单有效的ddos攻击防御方法

做过网站的站长大多有被ddos攻击的经历,不少人面对竞争对手的网站就是直接雇人ddos攻击网站,导致对方网站长期打不开,最后无奈关闭网站,初尧今天就告诉大家一个最简单也是最有效的防御方法。高防服务器/高防IP对于游戏&#xff0c…

android gpio驱动实例,安卓gpio操作示例

GPIO值在RK3288中的计算方法为:bank32pin,如:GPIO7A3: 732 0*8 3227GPIO0B5: 032 1*8 5131. 导出/sys/class/gpio# echo 44 > export2. 设置方向/sys/class/gpio/gpio44# echo out > direction3. 查看方向/sys/class/gpio/…

回调函数中有回调函数吗_嗨,那里有回调!

回调函数中有回调函数吗因为是我的书包,所以我喜欢JavaScript 。 实际上,我已经开始喜欢JavaScritp的面向异步回调的编程风格 。 因此,当我发现自己处于非JavaScript环境中时(例如Java) ,我往往会错过使用回…

python的django_django能用来做什么

Django是什么 Django是一个开放源代码的Web应用框架,由Python写成。采用了MT‘V的框架模式,即模型M,模板T和视图V。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统&am…

小程序确定取消弹窗_浅析微信小程序modal弹窗关闭默认会执行cancel问题

在我们使用小程序的modal组件时候,有的时候会碰到一个问题,那就是弹框的关闭,我们并没有选择取消或确定,而是点击弹框之外的部分,这个时候弹框会关闭,按理来说不会触发取消和确定的绑定事件,但是…

android n 发布时间,Android N 正式版将在9月发布

【环球科技综合报道】据外媒5月8日报道,谷歌预计将在9月份放出正式版Android N。三星、华为、LG、HTC和黑莓等品牌手机将获Android N升级。此前谷歌发出的路线图中的升级安排:3月: Android N 开发者预览版 1 (alpha)4月: Android N 开发者预览版 2 (beta…

ios realm 文件_关于ios:具有后台进程的Realm实例会丢失数据

我将Realm for Swift与仅内存配置一起使用。 由于在后台线程中更新数据库,因此每次使用时都会创建一个Realm实例。 在Realm文档中提到了此问题,这里还有另一个问题https://stackoverflow.com/a/45375608/613121。但是通过测试数据库,我注意到…

datatable如何生成级联数据_如何把Excel表数据批量生成条形码

条形码属于一维条码,是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符,条形码的种类比较多,比如常用的Code128码,Code39码,Code93码,EAN-13码&am…

android数字累加,Android自己设置View之数字自动增长

第一次写文,请多指教,有何问题及改进建议都可以告诉我-.-Idea来自金山词霸App的单词计数,下面先放图autoNumber.gif如上图,就是,下面开始进入自己设置View自己设置View步骤1. 自己设置属性2. 生成构造方法3. onMeasure…

spring条件注解有哪些_Spring4有条件

spring条件注解有哪些Spring 4引入了一个称为Conditional的新功能,该功能针对于生成bean的Spring组件,并注视这些bean的生成,实质上,它提供了一种条件生成bean的方法。 考虑一个简单的例子: 我有一个名为“ Customer…

settimeout怎么用_怎么实现一个3d翻书效果

本篇主要讨论以下两种翻书动画的实现:第一种是整页翻转的效果:这种整页翻转的效果主要是做rotateY的动画,并结合一些CSS的3d属性实现。第二种折线翻转的效果,如下图所示:主要是通过计算页面翻折过来的位置。这两种原理…

springboot怎么返回404_SpringBoot(二十)_404返回统一异常处理结果

1.修改application.properties文件# 自定义404#出现错误时, 直接抛出异常spring.mvc.throw-exception-if-no-handler-foundtrue#不要为我们工程中的资源文件建立映射spring.resources.add-mappingsfalse2.添加controller增强处理if (e instanceof NoHandlerFoundException) {re…

android 通知垃圾回收,Android中垃圾回收日志信息

原因GC_CONCURRENTfreed 178K, 41% free 3673K/6151K, external 0K/0K, paused 2ms2msGC_EXPLICITfreed 6K, 41% free 3667K/6151K, external 0K/0K, paused 29ms红颜色标出的部分就是垃圾回收触发的原因。在Android中有五种类型的垃圾回收触发原因。GC_CONCURRENT当堆内存增长…

5个令人震惊的统计数据证明日志不足

事实证明,我们都犯有记录不当行为的罪行。 不相信我们吗? 这些统计数据可能会改变您的想法 当人们提出带有明显答案的问题时,这非常令人不快,因此,我不会坐在这里问您和您的团队是否使用日志文件来监视预生产和生产环…

linearregression_机器学习-TensorFlow建模过程 Linear Regression线性拟合应用

TensorFlow是咱们机器学习领域非常常用的一个组件,它在数据处理,模型建立,模型验证等等关于机器学习方面的领域都有很好的表现,前面的一节我已经简单介绍了一下TensorFlow里面基础的数据结构即:Tensor和Dataset&#x…

yum配置文件 重启后还原_江湖救急 : CentOS7.5 /usr 目录误删, 恢复操作.

一.概述前两天在网上找了个脚本,看着没问题,直接复制粘贴了. 结果有特殊字符,直接换行.执行了 rm -rf /usr 目录. 然后就傻了,各种操作命令找不到, 无法登陆.......万分幸运的是,数据没丢,要是丢了.那我就要命了1.如果可以进入操作系统,并且可以正常操作的话. 依旧会存在隐患.…

html页面调用存储过程,用WebBrowser实现HTML界面的应用

HTML的界面有以下特点:图文混排,格式灵活,可以包含Flash、声音和视频等,实现图文声像的多媒体界面,而且易于建立和维护。另外,HTML的显示环境一般机器上都具备,通常不需要安装额外的软件。当然&…

凡事多找找自己的原因_布袋除尘器灰斗积粉过多、堵灰该咋办?别急,从这8个方面找原因...

灰斗布置在袋室的下部,它除了存放收集下来的粉尘以外,还作为下进气总管使用,当含尘气体进入袋室前先进入灰斗,由于灰斗内容积较大,使得气流速度降低,加之气流方向的改变,使得较粗的尘粒在这里得…

javaone_Javaone 2013评论

javaonetl; dr我今年再次参加了Javaone。 好玩。 星期日 会议于周日开幕,进行了用户组会议和主要主题演讲。 由于我正在运行Java大学关于Java SE 7和8的新功能的培训课程,因此我实际上无法参加这些课程。该课程涵盖了Java 7的项目硬币,NIO 2…

python怎么改变字体大小_Python-docx 整体修改或者部分修改文字的大小和字体类型...

Python中可以用docx来生成word文档,docx中可以自定义文字的大小和字体等。 其中要整体修改文字的字体大小和字体,可以用以下方法: newfile docx.Document() newfile.styles[Normal].font.name Times New Roman newfile.styles[Normal]._ele…