Android开发之ContentProvider的简单使用
ContentProvider,内容提供者
官网结构图:

作为四大组件之一的ContentProvider,主要是用于应用间数据共享使用的。
ContentProvider把应用的数据封装起来,然后提供一个对外访问的ContentResolver接口。
假如只是本应用使用的数据,直接通过SQLiteDatabase操作数据库。
主要原理:一个Uri对象通过ContentResolver请求该应用的数据,ContentProvider解析该Uri并返回给需要的数据。
实现自定义的ContentProvider,需要继承抽象类android.content.ContentProvider,并实现5个方法:
onCreate() 初始化provider,返回一个布尔值,创建成功返回一个true
query(Uri,String[],String,String[],String) 从ContentProvider中查询数据 返回一个Cursor
insert(Uri,ContentValues) 通过ContentProvider插入新的数据 返回一个Uri
update(Uri,ContentValues,String,String[]) 通过ContentProvider更新数据 返回一个int
delete(Uri,String,String[]) 通过ContentProvider删除数据 返回一个int
getType(Uri) 根据传入的Uri,返回相应的MIME类型。 返回一个String
Uri类:
一个Uri有三部分组成:Scheme+Authority+Path
1.scheme, contentprovider为content://
2.Authority,一般使用应用的包名,如com.example.appone或者也可以这样com.example.appone.provider
3.Path,即提供对外访问的table,如访问表table,写成/table
上面的Uri可以写成这样:content://com.example.appone.provider/table
一个字符串通过Uri类中的parse()方法可以转换为Uri对象,如下:
Uri uri=Uri.parse("content://com.example.appone.provider/table");
UriMatcher类,ContentUris类和contentResolver类
UriMather类用于匹配uri,用法如下:
private static final int PEOPLE = 1;
private static final int PEOPLE_ID = 2;
private static final int PEOPLE_PHONES = 3;
private static final int PEOPLE_PHONES_ID = 4;
private static final int PEOPLE_CONTACTMETHODS = 7;
private static final int PEOPLE_CONTACTMETHODS_ID = 8; private static final int DELETED_PEOPLE = 20; private static final int PHONES = 9;
private static final int PHONES_ID = 10;
private static final int PHONES_FILTER = 14; private static final int CONTACTMETHODS = 18;
private static final int CONTACTMETHODS_ID = 19; private static final int CALLS = 11;
private static final int CALLS_ID = 12;
private static final int CALLS_FILTER = 15; private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1) static
{
sURIMatcher.addURI("contacts", "people", PEOPLE); //如果match()方法匹配,返回匹配码为1
sURIMatcher.addURI("contacts", "people/#", PEOPLE_ID); //如果match()方法匹配,返回匹配码为2
sURIMatcher.addURI("contacts", "people/#/phones", PEOPLE_PHONES);
sURIMatcher.addURI("contacts", "people/#/phones/#", PEOPLE_PHONES_ID);
sURIMatcher.addURI("contacts", "people/#/contact_methods", PEOPLE_CONTACTMETHODS);
sURIMatcher.addURI("contacts", "people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID);
sURIMatcher.addURI("contacts", "deleted_people", DELETED_PEOPLE);
sURIMatcher.addURI("contacts", "phones", PHONES);
sURIMatcher.addURI("contacts", "phones/filter/*", PHONES_FILTER);
sURIMatcher.addURI("contacts", "phones/#", PHONES_ID);
sURIMatcher.addURI("contacts", "contact_methods", CONTACTMETHODS);
sURIMatcher.addURI("contacts", "contact_methods/#", CONTACTMETHODS_ID);
sURIMatcher.addURI("call_log", "calls", CALLS);
sURIMatcher.addURI("call_log", "calls/filter/*", CALLS_FILTER);
sURIMatcher.addURI("call_log", "calls/#", CALLS_ID);
}
从API:18开始,路径可以用一个斜线开始。 例如:
sURIMatcher.addURI("contacts", "/people", PEOPLE);
注册完需要匹配的Uri后,在getType()方法中可以使用sURIMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配成功就返回匹配码,匹配码是调用addURI()方法传入的第三个参数。
public String getType(Uri url)
{
int match = sURIMatcher.match(url);
switch (match)
{
case PEOPLE:
return "vnd.android.cursor.dir/person";
case PEOPLE_ID:
return "vnd.android.cursor.item/person";
... snip ...
return "vnd.android.cursor.dir/snail-mail";
case PEOPLE_ADDRESS_ID:
return "vnd.android.cursor.item/snail-mail";
default:
return null;
}
}
ContentUris类,用于获取Uri路径后面的ID部分,它有两个比较实用的方法:
withAppendedId(uri, id)用于为路径加上ID部分
Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person")
Uri resultUri = ContentUris.withAppendedId(uri, 10);
//生成后的Uri为:content://com.ljq.provider.personprovider/person/10
parseId(uri)方法用于从路径中获取ID部分
Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person/10")
long personid = ContentUris.parseId(uri);//获取的结果为:10
ContentResolver类,当外部应用需要对ContentProvider的数据库进行CRUD时,可以使用ContentResolver类来完成。获取ContentResolver对象,可以通过Content的getContentResolver()方法获取到。ContentResolver使用insert()、delete()、update()、query()方法,来操作数据。
实现了一个Demo,代码如下:
1.工具类:Xin类
package com.example.appone;
public class Xin {
public static final String DBNAME = "xinonlinedb";
public static final String TNAME = "xinonline";
public static final int VERSION = 3;
public static String TID = "tid";
public static final String EMAIL = "email";
public static final String USERNAME = "username";
public static final String DATE = "date";
public static final String SEX = "sex";
public static final String AUTOHORITY = "com.example.appone.provider";
public static final int ITEM = 1;
public static final int ITEM_ID = 2;
public static final String CONTENT_TYPE = "vnd.android.cursor.dir";
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item";
}
2.创建数据库:DBlite类
package com.example.appone; import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper; public class DBlite extends SQLiteOpenHelper { public DBlite(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version); } @Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + Xin.TNAME + "(" + Xin.TID
+ " integer primary key autoincrement not null," + Xin.EMAIL
+ " text not null, " + Xin.USERNAME + " text not null,"
+ Xin.DATE + " text not null, " + Xin.SEX + " text not null);");
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
3.创建自定义的ContentProvider,对数据库进行包装:MyProvider类
package com.example.appone; import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri; public class MyProvider extends ContentProvider { private DBlite dBlite;
private SQLiteDatabase db;
private Cursor cursor; private static final UriMatcher sMatcher;
static {
sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sMatcher.addURI(Xin.AUTOHORITY, Xin.TNAME, Xin.ITEM);
sMatcher.addURI(Xin.AUTOHORITY, Xin.TNAME + "/#", Xin.ITEM_ID); } @Override
public boolean onCreate() {
dBlite = new DBlite(getContext(), Xin.DBNAME, null, Xin.VERSION);
return true; } @Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
db = dBlite.getWritableDatabase();
switch (sMatcher.match(uri)) {
case Xin.ITEM:
cursor = db.query(Xin.TNAME, projection, selection, selectionArgs,
null, null, sortOrder);
break;
case Xin.ITEM_ID:
String id = uri.getPathSegments().get(1);
cursor = db.query(Xin.TNAME, projection, "tid=?",
new String[] { id }, null, null, sortOrder);
break; default:
break;
}
return cursor;
} @Override
public Uri insert(Uri uri, ContentValues values) {
db = dBlite.getWritableDatabase();
long returnId = db.insert(Xin.TNAME, null, values);
Uri uriReturn = Uri.parse("content://" + Xin.AUTOHORITY + "/"
+ Xin.TNAME + "/" + returnId); return uriReturn;
} @Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
db = dBlite.getWritableDatabase();
int deleteId = 0;
switch (sMatcher.match(uri)) {
case Xin.ITEM:
deleteId = db.delete(Xin.TNAME, selection, selectionArgs); break;
case Xin.ITEM_ID:
String id = uri.getPathSegments().get(1);
deleteId = db.delete(Xin.TNAME, "tid=?", new String[] { id }); default:
break;
}
return deleteId;
} @Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
db = dBlite.getWritableDatabase();
int updateId = 0;
switch (sMatcher.match(uri)) {
case Xin.ITEM:
updateId = db.update(Xin.TNAME, values, selection, selectionArgs);
break;
case Xin.ITEM_ID:
String id = uri.getPathSegments().get(1);
updateId = db.update(Xin.TNAME, values, "tid= ?",
new String[] { id });
break; default:
break;
}
return updateId;
} @Override
public String getType(Uri uri) {
switch (sMatcher.match(uri)) {
case Xin.ITEM:
return Xin.CONTENT_TYPE + "/vnd." + Xin.AUTOHORITY + Xin.TNAME;
case Xin.ITEM_ID:
return Xin.CONTENT_ITEM_TYPE + "/vnd." + Xin.AUTOHORITY + Xin.TNAME; }
return null;
} }
4.在manifest文件中对MyProvider进行注册
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.appone"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" /> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity> <provider
android:name="com.example.appone.MyProvider"
android:authorities="com.example.appone.provider"
android:exported="true" >
</provider>
</application> </manifest>
5.在MainActivity中使用ContentProvider进行CRUD
package com.example.appone; import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window; public class MainActivity extends Activity implements OnClickListener { private String newid; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_contentprovider); findViewById(R.id.contentProvider_query).setOnClickListener(this);
findViewById(R.id.contentProvider_insert).setOnClickListener(this);
findViewById(R.id.contentProvider_update).setOnClickListener(this);
findViewById(R.id.contentProvider_delete).setOnClickListener(this);
} @Override
public void onClick(View v) {
Uri uriItem = Uri.parse("content://"+Xin.AUTOHORITY+"/"+Xin.TNAME);
Uri uriId = Uri.parse("content://"+Xin.AUTOHORITY+"/"+Xin.TNAME+"/"+newid);
switch (v.getId()) {
case R.id.contentProvider_query:
Cursor cursor=this.getContentResolver().query(uriItem, null, null, null, null);
if (cursor!=null) {
while (cursor.moveToNext()) {
String userName=cursor.getString(cursor.getColumnIndex(Xin.USERNAME));
String sex = cursor.getString(cursor.getColumnIndex(Xin.SEX));
String email = cursor.getString(cursor.getColumnIndex(Xin.EMAIL));
String date = cursor.getString(cursor.getColumnIndex(Xin.DATE));
Log.e("appone", "获取到的信息为:"+userName+email+date+sex);
}
cursor.close();
}
break; case R.id.contentProvider_insert:
ContentValues values = new ContentValues();
values.put(Xin.EMAIL, "1234@12.com");
values.put(Xin.USERNAME, "张三");
values.put(Xin.DATE, "2015");
values.put(Xin.SEX, "男");
Uri newUri = this.getContentResolver().insert(uriItem,values);
newid = newUri.getPathSegments().get(1);
break; case R.id.contentProvider_update:
ContentValues values2= new ContentValues();
values2.put(Xin.USERNAME, "王五");
values2.put(Xin.EMAIL, "xxx@ddd.com");
values2.put(Xin.SEX, "女");
this.getContentResolver().update(uriId, values2, null, null);
break; case R.id.contentProvider_delete:
this.getContentResolver().delete(uriId, null, null);
break; default:
break;
}
} }
注意:
首先需要插入消息,然后再查询或者更新或者删除,否则newId的值为空。
Android开发之ContentProvider的简单使用的更多相关文章
- Android开发之AutoCompleteTextView的简单使用
这里只谈简单的使用: 代码xml: <AutoCompleteTextView android:id="@+id/actv" android:layout_width=&qu ...
- Android开发之ContentProvider(内容提供者)
1. ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据.虽然使用其他方法也可以对外共享数据,但数据访问 ...
- Android开发之ViewPager的简单使用
ViewPager是V4包中的,如果你的编译器敲不出ViewPager,那么你就需要添加,看下面: 第一步:点击+号 第二步:选择第一个Library 第三步:添加这个包: 然后点击ok-->o ...
- Android开发之EventBus的简单使用
参考: 1.http://blog.csdn.net/harvic880925/article/details/40660137 2.http://blog.csdn.net/harvic880925 ...
- Android开发之Notification的简单使用
创建Notification Buider 一个Builder至少包含以下内容: 一个小的icon,用setSmallIcon())方法设置 一个标题,用setContentTitle())方法 ...
- Android开发之旅4:应用程序基础及组件
引言 为了后面的例子做准备,本篇及接下来几篇将介绍Android应用程序的原理及术语,这些也是作为一个Android的开发人员必须要了解,且深刻理解的东西.本篇的主题如下: 1.应用程序基础 2.应用 ...
- Android开发之旅2:HelloWorld项目的目录结构
引言 前面Android开发之旅:环境搭建及HelloWorld,我们介绍了如何搭建Android开发环境及简单地建立一个HelloWorld项目,本篇将通过HelloWorld项目来介绍Androi ...
- Android开发之Java集合类性能分析
对于Android开发者来说深入了解Java的集合类很有必要主要是从Collection和Map接口衍生出来的,目前主要提供了List.Set和 Map这三大类的集合,今天Android吧(ard8. ...
- 【Android UI】Android开发之View的几种布局方式及实践
引言 通过前面两篇: Android 开发之旅:又见Hello World! Android 开发之旅:深入分析布局文件&又是“Hello World!” 我们对Android应用程序运行原理 ...
随机推荐
- Linux文件目录结构说明
- 【oracle】Enterprise Manager 无法连接到数据库实例。下面列出了组件的状态---个人解决方案
最近在学习Oracle,平常喜欢使用EM查看数据库状态,但是在最近突然发现EM连接不上Oracle数据库了,不知道问题出在哪里,只好卸载了重装.但是,在使用了几天以后,又出现了相同的问题,于是下决心将 ...
- mysql中limit的用法实例解析
mysql中limit的用法解析. 在mysql中,select * from table limit m,n.其中m是指记录开始的index,从0开始,n是指从第m条开始,取n条. 例如: mysq ...
- Python urllib2 模块学习笔记
2015.3.6 urllib2的使用方法大致如下 # 定制Handler处理函数 opener = urllib2.build_opener(ProxyHandler, HTTPHandler) ...
- Django开发网站(二)
第一课:视图显示 1 建立一个项目:django-admin startproject blog, 进入blog: cd blog 显示:blog(__init__.py settings.py ...
- oracle 绿色版本 instantclient 使用说明
1,将instantclient直接放到D盘根目录 2,注册表修改 3,点击工具>>首选项, 在Oracle主目录名中输入“D:\instantclient_10_2\”,在OCI库中输入 ...
- SVN备份教程(二)
上次的博文中SVN备份教程(一)我们简单介绍了一下SVN备份是如何操作的,今天我们接着将上次的问题进行优化. 1.问题回顾 在讲之前,我们先来将上次的问题重申一下.之前的SVN备份存在的问题很简单,每 ...
- TCP报头
源端口和目的端口: 各占16位 ,服务相对应的源端口和目的端口. 序列号: 占32位,它的范围在[0~2^32-1],序号随着通信的进行不断的递增,当达到最大值的时候重新回到0在开始递增.TCP是面向 ...
- hdu 4740 The Donkey of Gui Zhou(暴力搜索)
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4740 [题意]: 森林里有一只驴和一只老虎,驴和老虎互相从来都没有见过,各自自己走过的地方不能走第二次 ...
- [转载]用.NET开发的磁力搜索引擎——Btbook.net
去年10月份开始研究相关的协议与资料,中途乱七八糟的事情差点没坚持下来,寒假里修修补补上礼拜把Btbook发布了,经过社交网络的推广之后,上线第三天UV就达到了两万多,也算是对这几个月工作的一点肯定吧 ...