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应用程序运行原理 ...
随机推荐
- asp.net runat="server" && hiddenfield
runat="server", c#可以直接获得client控件,并且赋值 hiddenfield 可以作为传值,或者界面存值,后台每次读取,并且再赋值到前台,这样前台就可以把上一 ...
- [Oracle]Oracle数据库任何用户密码都能以sysdba角色登入
* 本文相关环境:Windows 10,64位操作系统:Oracle 11gR2:toad for Oracle12.1 最近在学习Oracle数据库,使用Toad for Oracle来查看数据库的 ...
- Linux中Kill进程的N种方法
常规篇: 首先,用ps查看进程,方法如下: $ ps -ef …… smx 1822 1 0 11:38 ? 00:00:49 gnome-terminal smx ...
- MenuItem
private void 文件ToolStripMenuItem_Click(object sender, EventArgs e) { MessageBox.Show("打开测试" ...
- 十九、mysql 数据分布式
1.RAID 廉价磁盘冗余阵列 2.Symbolic links 通俗易懂的说就是通过连接符指向的操作,人为的将某些数据库分布到其他的文件夹/磁盘上 Linux: Mysql DATA路径:/opt/ ...
- linq and rest api in sharepoint
//1.make sure your application using the .net fromwork 3.5 //2.create entity classes using the instr ...
- Visual Studio 2013 之 Productivity Power Tools
http://blogs.msdn.com/b/visualstudio_cn/archive/2014/02/20/visual-studio-2013-productivity-power-too ...
- 设计模式之:组合模式(Composite)
支持原创:http://blog.csdn.net/hguisu/article/details/7530783 设计模式(七)组合模式Composite(结构型) 1. 概述 在数据结构里面,树结构 ...
- js学习之函数表达式及闭包
来自<javascript高级程序设计 第三版:作者Nicholas C. Zakas>的学习笔记(七) 直接切入主题~ 定义函数的方式有两种: 函数声明 function functio ...
- Hadoop之RPC
Hadoop的RPC主要是通过Java的动态代理(Dynamic Proxy)与反射(Reflect)实现,代理类是由java.lang.reflect.Proxy类在运行期时根据接口, ...