ContentProvider的作用:
1、为存储和获取数据提供了一个统一的接口;
2、使用ContentProvider可以在不同的应用程序之间共享数据;
3、Android为常见的一些数据提供了ContentProvider(包括音频、视频、图片和通讯录等等);
ContentProvider使用表的结构来存储数据;每个ContentProvider都提供了一个公共的URI,这个URL用于表示这个ContentProvider所提供的数据;
下面列举一些常用的接口:
1、query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder):通过Uri进行查询,返回一个Cursor.
2、insert(Uri uri,ContentValues values):将一组数据插入到Uri指定的地方。
3、update(Uri uri,ContentValues values,String where,String[] selectionArgs):更新Uri指定位置的数据。
4、delete(Uri uri,String where,String[] selectionArgs):删除指定Uri并且符合一定条件的数据。
5、getType():得到数据类型;
6、OnCreate():创建时的回调函数
实现一个ContentProvider的过程:
1 定义个CONTENT_URI常量;
2 定义一个类,继承ContentProvider;
3 实现一些方法;
4 在AndroidMainfest.xml中进行声明;
外界程序通过ContentResolver接口可以访问ContentProvider提供的数据,在Activity当中通过getContentResolver()可以得到当前应用ContentResolver实例。其提供的接口与ContentProvider提供的接口对应:
1、query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder):通过Uri进行查询,返回一个Cursor.
2、insert(Uri uri,ContentValues values):将一组数据插入到Uri指定的地方。
3、update(Uri uri,ContentValues values,String where,String[] selectionArgs):更新Uri指定位置的数据。
4、delete(Uri uri,String where,String[] selectionArgs):删除指定Uri并且符合一定条件的数据。
以下代码来自:http://blog.csdn.net/linshutao/article/details/5779558
【1】要为当前应用程序的私有数据定义URI,就需要专门定义个继承自ContentProvider的类,然后实现各个不同的操作所调用的方法。
首先在该应用程序的某个类中定义所有与数据库操作有关的静态字段,以便打包成jar文件供其他应用程序调用
此例子没有新定义一个专门的类来存放这些字段,而是在继承了SQLiteOpenHelper的类StudentData中定义:
- package com.shutao.testsqlite2;
- public class StudentData extends SQLiteOpenHelper {
- /*
- * 分别定义了数据库和表的名称、表中各个字段的名称、数据库的版本号
- */
- public final static String DB_NAME = "student";
- public final static String TABLE_NAME = "hero";
- public final static String SNAME = "name";
- //Be sure to include an integer column named "_id" (with the constant _ID) for the IDs of the records
- public final static String SID = "_id";
- public final static int DB_VERSION = 1;
- /*
- * AUTHORITY:定义了标识ContentProvider的字符串 ;
- * ITEM和ITEM_ID分别用于UriMatcher(资源标识符匹配器)中对路径item和item/id的匹配号码
- * CONTENT_TYPE和CONTENT_ITEM_TYPE定义了数据的MIME类型。需要注意的是: 单一数据的MIME 类型字符串应该以
- * vnd.android.cursor.item/开头,数据集的MIME类型字符串应该以vnd.android.cursor.dir开头
- * CONTENT_URI定义的是查询当前表数据的content://样式URI
- */
- //类名的路径名
- public static final String AUTHORITY = "com.shutao.testsqlite2.provider.studentdata";
- public static final int ITEM = 1;
- public static final int ITEM_ID = 2;
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.shutao.testsqlite2.studentdata";
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.shutao.testsqlite2.studentdata";
- public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
- + "/item");
- public StudentData(Context context) {
- super(context, DB_NAME, null, DB_VERSION);
- }
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL("CREATE TABLE " + TABLE_NAME + "(" + SID
- + " VARCHAR PRIMARY KEY," + SNAME + " VARCHAR NOT NULL);");
- }
- @Override
- public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {
- db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
- }
- }
【2】接下来定义一个继承自ContentProvider的类:MyProvider.java,来实现对数据进行操作的各个方法。这里将用到StudentData来辅助得到SQLiteDatabase对象:
- package com.shutao.testsqlite2;
- public class MyProvider extends ContentProvider {
- StudentData sd;
- private static final UriMatcher sMatcher;
- static {
- // 传入匹配码如果大于0表示匹配根路径或传入-1,即常量UriMatcher.NO_MATCH表示不匹配根路径
- // addURI()方法是用来增加其他URI匹配路径的:
- // 第一个参数代表传入标识ContentProvider的AUTHORITY字符串
- // 第二个参数是要匹配的路径,#代表任意数字,另外还可以用*来匹配任意文本
- // 第三个参数必须传入一个大于零的匹配码,用于match()方法对相匹配的URI返回相对应的匹配码
- sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
- sMatcher.addURI(StudentData.AUTHORITY, "item", StudentData.ITEM);
- sMatcher.addURI(StudentData.AUTHORITY, "item/#", StudentData.ITEM_ID);
- }
- /*
- * 每当ContentProvider启动时都会回调onCreate()方法。此方法主要执行一些ContentProvider初始化
- * 的工作,返回true表示初始化成功,返回false则初始化失败。
- */
- @Override
- public boolean onCreate() {
- sd = new StudentData(this.getContext());
- return true;
- }
- // getType()是用来返回数据的MIME类型的方法。使用sMatcher对URI进行匹配,并返回相应的MIME类型字符串
- @Override
- public String getType(Uri uri) {
- switch (sMatcher.match(uri)) {
- case StudentData.ITEM:
- return StudentData.CONTENT_TYPE;
- case StudentData.ITEM_ID:
- return StudentData.CONTENT_ITEM_TYPE;
- default:
- throw new IllegalArgumentException("Unknown URI " + uri);
- }
- }
- /*
- * 插入数据,返回新插入数据的URI,只接受数据集的URI,即指向表的URI
- */
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- SQLiteDatabase sdb = sd.getWritableDatabase();
- long rowId;
- if (sMatcher.match(uri) != StudentData.ITEM) {
- throw new IllegalArgumentException("Unknow URI " + uri);
- }
- rowId = sdb.insert(StudentData.TABLE_NAME, StudentData.SID, values);
- if (rowId > 0) {
- Uri noteUri = ContentUris.withAppendedId(StudentData.CONTENT_URI,
- rowId);
- //通知监听器,数据已经改变
- this.getContext().getContentResolver().notifyChange(noteUri, null);
- return noteUri;
- }
- throw new SQLException("Failed to insert row into " + uri);
- }
- /*
- * 用于数据的删除,返回的是所影响数据的数目,首先利用数据库辅助对象获取一个SQLiteDatabase对象
- * 然后根据传入Uri用sMatcher进行匹配,对单个数据或数据集进行删除或修改。notifyChange()方法
- * 用来通知注册在次URI上的观察者(observer)数据发生了改变。
- */
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- SQLiteDatabase sdb = sd.getWritableDatabase();
- int count;
- switch (sMatcher.match(uri)) {
- case StudentData.ITEM:
- count = sdb.delete(StudentData.DB_NAME, selection, selectionArgs);
- break;
- case StudentData.ITEM_ID:
- String id = uri.getPathSegments().get(1);
- count = sdb.delete(StudentData.DB_NAME, StudentData.SID
- + "="
- + id
- + (!TextUtils.isEmpty(selection) ? " AND (" + selection
- + ")" : ""), selectionArgs);
- break;
- default:
- throw new IllegalArgumentException("Unknown URI " + uri);
- }
- this.getContext().getContentResolver().notifyChange(uri, null);
- return count;
- }
- /*
- * 查询数据,将数据装入一个Cursor对象并返回
- */
- @Override
- public Cursor query(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
- SQLiteDatabase sdb = sd.getReadableDatabase();
- Cursor c;
- switch (sMatcher.match(uri)) {
- case StudentData.ITEM:
- c = sdb.query(StudentData.TABLE_NAME, projection, selection,
- selectionArgs, null, null, sortOrder);
- break;
- case StudentData.ITEM_ID:
- String id = uri.getPathSegments().get(1);
- c = sdb.query(StudentData.TABLE_NAME, projection, StudentData.SID
- + "="
- + id
- + (!TextUtils.isEmpty(selection) ? " AND (" + selection
- + ")" : ""), selectionArgs, null, null, sortOrder);
- break;
- default:
- Log.i("sMatcher.match(uri)", String.valueOf(sMatcher.match(uri)));
- throw new IllegalArgumentException("Query with unknown URI: " + uri);
- }
- c.setNotificationUri(getContext().getContentResolver(), uri);
- return c;
- }
- // 更新,与删除类方法类似
- @Override
- public int update(Uri uri, ContentValues values, String selection,
- String[] selectionArgs) {
- SQLiteDatabase sdb = sd.getWritableDatabase();
- int count;
- switch (sMatcher.match(uri)) {
- case StudentData.ITEM:
- count = sdb.update(StudentData.TABLE_NAME, values, selection,
- selectionArgs);
- break;
- case StudentData.ITEM_ID:
- String id = uri.getPathSegments().get(1);
- count = sdb.update(StudentData.DB_NAME, values, StudentData.SID
- + "="
- + id
- + (!TextUtils.isEmpty(selection) ? " AND (" + selection
- + ")" : ""), selectionArgs);
- break;
- default:
- throw new IllegalArgumentException("Unknown URI " + uri);
- }
- this.getContext().getContentResolver().notifyChange(uri, null);
- return count;
- }
- }
【3】完成以上方法以后,还要AndroidManifest.xml中对这个ContentProvider声明:
- <provider
- android:name="MyProvider"
- android:authorities="com.shutao.testsqlite2.provider.studentdata"/>
- <!-- 其中 android:name必须跟定义的ContentProvider的类名一样
- android:authorities则指定了content://样式的URI中标识这个ContentProvider的字符串-->
【4】接下来在另一个程序中使用ContentResolver来操作数据:
- package com.shutao.contentprovider;
- public class TestContentProvider extends Activity {
- private EditText stu_name;
- private EditText stu_sid;
- Button commit;
- ListView studList;
- ContentResolver resolver;
- // 由于在AlertDialog中用到,所以定义为全局变量。
- String sid = "";
- private final int DIALOG_IN_USED = 1;
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- stu_name = (EditText) this.findViewById(R.id.edit_name);
- stu_sid = (EditText) this.findViewById(R.id.edit_sid);
- commit = (Button) this.findViewById(R.id.butt_add);
- studList = (ListView) this.findViewById(R.id.show_stud);
- // 【重要】得到ContentResolver()
- resolver = this.getContentResolver();
- String[] projection = { StudentData.SNAME, StudentData.SID };
- Cursor c = resolver.query(StudentData.CONTENT_URI, null, null, null,
- StudentData.SID);
- CursorAdapter adapter = new SimpleCursorAdapter(this,
- android.R.layout.simple_list_item_2, c, projection, new int[] {
- android.R.id.text1, android.R.id.text2 });
- studList.setAdapter(adapter);
- commit.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (!(stu_name.getText().length() > 0)) {
- Toast.makeText(TestContentProvider.this,
- "Please input the student's name!",
- Toast.LENGTH_LONG).show();
- } else if (!(stu_sid.getText().length() > 0)) {
- Toast
- .makeText(TestContentProvider.this,
- "Please input the student's ID!",
- Toast.LENGTH_LONG).show();
- } else {
- String name = stu_name.getText().toString();
- sid = stu_sid.getText().toString();
- Uri quri = Uri.parse(StudentData.CONTENT_URI + "/" + sid);
- Cursor c = resolver.query(quri, null, null, null, null);
- if (c.moveToFirst()) {
- // 采用Toast方式提醒
- /*
- * Toast.makeText(TestContentProvider.this,
- * "Fail to add!This ID is already in used!",
- * Toast.LENGTH_LONG).show();
- */
- // 采用AlertDialog方式提醒
- TestContentProvider.this.showDialog(DIALOG_IN_USED);
- } else {
- ContentValues values = new ContentValues();
- values.put(StudentData.SNAME, name);
- values.put(StudentData.SID, sid);
- resolver.insert(StudentData.CONTENT_URI, values);
- }
- }
- }
- });
- }
- // 如果插入的Id已经存在则用提示框进行提示
- @Override
- protected Dialog onCreateDialog(int id, Bundle args) {
- // // TODO Auto-generated method stub
- // return super.onCreateDialog(id, args);
- switch (id) {
- case DIALOG_IN_USED:
- return new AlertDialog.Builder(this).setTitle("Fail to add!")
- .setIcon(R.drawable.fail).setMessage(
- "This ID:" + sid + " is already in used!")
- .setPositiveButton("确定",
- // 特别注意:必须为:new DialogInterface.OnClickListener()
- // 不能为new
- // OnClickListener(),否则会跟View.OnClickListener冲突。
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog,
- int which) {
- // TODO Auto-generated method stub
- }
- }).create();
- default:
- return super.onCreateDialog(id, args);
- }
- }
- }
【注】:在ContentProvider与ContentResolver当中用到了Uri的形式通常有两种,一种是指定全部数据,另一种是指定某个ID的数据,如:
1、content://contacts/people/:这个Uri指定的就是全部联系人的数据。
2、content://contacts/people/1:这个Uri指定的就是ID为1的联系人的数据。
Uri一般由3部分组成:
1、"content://"
2、要获得数据的一个字符串片段
3、最后就是ID,如果没有ID则返回全部数据。
但因为URI通常比较长,容易出错,所以在Android当中定义了一些辅助类,并定义了一些常量来代替这些这些字符串的使用,如:
Contacts.People.CONTENT_URI:联系人的URI.
发表评论
-
android中退出整个app应用程序
2012-07-19 13:45 1864可以通过一个列表来维护所有的activity,在需要退出的时候 ... -
有关Activity的Launch mode 以及Intent的setFlags(转载)
2012-05-15 15:02 0Activity有四种加载模式 ... -
android 开发的性能原则
2012-02-29 09:51 0手机的开发由于受到性能,电池等硬件的瓶颈,所以在开发应用的时候 ... -
android开发的9个原则
2011-11-15 14:43 9821:如果要使用全局文件,可以把变量放入Applacat ... -
Android开发之编程中15个很有用的代码片段
2011-11-15 14:23 9771:查看是否有存储卡插入 String status ... -
keytool生成数字证书
2011-11-01 14:03 1104JDK中keytool常用命令-genkey 在用户主目录中创 ... -
android中的http访问方式
2011-09-27 16:40 1648Android网络编程之Http通信 原创作品,允许 ... -
android开发综合应用之打分应用
2011-09-21 16:44 1685该程序是一个listView跟ratingbar综合的应用示例 ... -
android 开发之ratingbar
2011-09-21 16:25 2167RatingBar组件是一个打分组件,主要用于对应用打分,下面 ... -
android开发之Spinner组件
2011-09-21 08:54 2587Spinner组件组要用显示一个下拉列表,在使用中需要用到适配 ... -
android基础开发之sharedPreference
2011-09-17 17:39 2029SharePreference存储技术在android中主要应 ... -
eclipse中查看android的SDK源代码
2011-09-15 15:32 856原理: http://log4think.com/brow ... -
设置android模拟器上网(转)
2011-08-31 11:10 1146很多网友也问到为啥自己在家的PC机可以上网,而运行在PC机上面 ... -
android基础开发之二intent(意图)用法
2011-08-29 15:27 2304android中不同的activity之间的切换主要是通过in ... -
android基础开发之一setContentView用法
2011-08-29 15:05 14684android开发中如果想实现布局页面的跳转可以使用setCo ... -
android连接真实手机
2011-08-29 10:09 1258用实现用真机调试你的程序,整个操作相当的方便简单 1、首先用 ... -
android中各种permissiond详解(转)
2011-08-29 10:04 1133Android应用程序在使用很多功能的时候必须在Mainife ...
相关推荐
在Android应用开发中,数据持久化是一个至关重要的环节,而Android Room和ContentProvider是其中的两个关键组件。本文将深入探讨这两个技术,并结合实际案例,解释如何在Android应用中使用它们来管理和共享SQLite...
接下来,ContentProvider是Android四大组件之一,它提供了一种标准接口,使得其他应用程序可以访问和修改由ContentProvider管理的数据,无论这些数据是存储在SQLite数据库、文件系统还是网络中。要创建一个...
在Android开发中,ContentProvider是四大组件之一,它充当了数据共享和访问的桥梁,使得不同应用程序之间可以安全地共享数据。本示例源代码旨在帮助初学者理解ContentProvider的工作原理及其使用方法。通过分析和...
在Android开发中,ContentProvider是四大核心组件之一,它扮演着跨应用数据共享的角色。通过ContentProvider,一个应用可以将自己的数据暴露给其他应用,实现数据的透明访问。本篇内容将深入讲解ContentProvider的...
在Android开发中,ContentProvider是四大组件之一,它扮演着数据共享的重要角色。ContentProvider使得应用程序之间能够安全、有序地访问彼此的数据,无论是系统内置的数据(如联系人、日历等)还是自定义的数据存储...
在Android开发中,ContentProvider是四大组件之一,它扮演着数据共享和访问的重要角色。ContentProvider使得应用程序可以安全地分享内部数据,同时也为其他应用程序提供了一种标准接口来访问这些数据,无论是SQLite...
在Android系统中,ContentProvider是四大组件之一,它充当了数据共享和访问的桥梁,使得应用程序之间能够安全地共享数据。本主题将深入探讨如何...理解和熟练运用ContentProvider,是提升Android开发能力的重要一步。
学习和理解ContentProvider及ContentResolver的使用,对于开发Android应用尤其是涉及到数据共享和跨应用交互的场景至关重要。通过实践这些示例代码,开发者可以更好地掌握这两者的工作原理,并能灵活地应用于实际...
在Android开发中,ContentProvider是四大组件之一,它充当了数据共享的桥梁,使得不同的应用程序之间可以安全地访问和共享数据。本篇文章将详细介绍如何在Android中实现一个简单的ContentProvider。 首先,理解...
在Android系统中,ContentProvider是四大组件之一,它扮演着数据共享和访问的重要角色。ContentProvider使得应用程序可以将自己的数据结构暴露给其他应用,同时也能够访问其他应用公开的数据。本篇文章将全面解析...
在Android应用开发中,ContentResolver和ContentProvider是两个至关重要的组件,它们负责应用程序间的数据共享和访问。ContentResolver充当客户端,而ContentProvider作为服务端,实现了Android系统中不同应用程序...
在Android开发中,ContentProvider是一种重要的组件,它允许应用程序之间共享数据。本示例"android ContentProvider Demo"将深入探讨如何创建和使用ContentProvider来实现跨应用的数据交换。ContentProvider作为...
同我前面的资源一样,我的每个功能的实例都是力图实现最简短话...这个实例不讲求大而全的实现ContentProvider的所有功能,而只是为了便于理解而实现。对应于我的博客“How:ContentProvider基本功能核心框架(增删改查)”
在Android系统中,ContentProvider是四大组件之一,它充当了数据共享的桥梁,使得不同的应用程序之间可以安全地访问和操作彼此的数据。这篇博客"Android之ContentProvider手机簿使用"主要探讨了如何通过...
在Android开发中,ContentProvider和Observer模式是两个关键的概念,它们在数据管理和更新中起着重要作用。ContentProvider作为Android系统中数据共享的桥梁,允许不同的应用程序之间交换数据,而Observer模式则是一...
在Android开发中,ContentProvider和ContentResolver是两个关键组件,它们构成了Android系统中不同应用程序间数据共享的基础。本文将深入探讨如何自定义ContentProvider和如何有效地使用ContentResolver进行数据操作...
在Android开发中,ContentProvider是四大组件之一,它充当了数据共享的桥梁,使得不同的应用程序之间可以安全地访问和操作数据。本示例将详细解释如何在Android中使用ContentProvider。 1. **ContentProvider基本...
在实际开发中,ContentProvider不仅可以用于应用间的数据共享,还常用于备份和恢复数据,或者与其他系统服务(如ShareActionProvider、Intent等)进行数据交互。它为数据交换提供了一套标准的接口,使得数据操作更加...