有时候我们自己的程序也需要向外接提供数据,那么就需要我们自己实现ContentProvider。

自己实现ContentProvider的话需要新建一个类去继承ContentProvider,然后重写类中的的6个抽象方法。

onCreate():初始化内容提供器时候会调用,通常会在这里完成对数据库的创建和升级等操作,返回true表示内容提供器初始化成功,返回false则表示失败,注意,只有当存在ContentResolver尝试访问我们程序中的数据时,内容提供其才会被初始化

query():从内容提供其中查询数据,使用uri参数来确定查询哪张表,projection参数用于确定查询哪些列,selection和selectionArgs参数用于约束查询哪些行,sortOrder参数用于对结果进行排序,查询结果存放在Cursor对象中返回。

insert():向内容提供器中添加一条数据,使用uri参数来确定要添加到的表,待添加的数据保存在values参数中,添加完成后,返回一个用于表示这条新记录的URI。

update():更新内容提供器中已有的数据,使用uri参数来确定更新哪一张表中的数据,新数据保存在values参数中,selection和selectionArgs参数用于约束更新哪些列,受影响的行数将作为返回值返回。

delete():从内容提供其中删除数据,使用uri参数来确定删除哪一张表中的数据,selection和selectionArgs参数用于约束删除哪些行,被删除的行数将作为返回值返回。

getType():根据传入的内容URI来返回相应的MIME类型。

可以看到,几乎每一个方法都会带有Uri这个参数,这个参数也正是调用ContentResolver的增删改查方法时传递过来的,而现在,我们需要对传入的Uri参数进行解析,从中分析出调用方期待访问的表和数据。

一般的标准的内容URI写法是这样的

content://com.example.app.provider/table1

这就表示调用方期待访问的是com.example.app这个应用的table1表中的数据。除此之外,我们还可以在这个内容URI的后面加上一个id,例如

content://com.example.app.provider/table1/1

这就表示调用方期待访问的是com.example.app这个应用的table1表中的id为1的数据。

内容URI的格式主要就只有以上两种,以路径结尾就表示期望访问该表中所有的数据,以id结尾就表示期望访问该表中拥有相应的id的数据,我们可以使用通配符的方式来分别匹配这两种格式的内容URI,规则如下

1.*表示匹配任意长度的任意字符

2.#表示匹配任意长度的数据

所以一个能够匹配任意表的内容URI格式就可以写成:

content://com.example.app.provider/*

而一个能够匹配table1表中任意一行数据的内容URI格式就可以写成

content://com.example.app.provider/table1/#

接着我们再借助UriMatcher这个类就可以轻松的实现匹配内容URI的功能,UriMatcher中提供了一个addURI()方法,这个方法接收三个参数,可以分别把权限,路径和一个自定义代码传递进去,这样,当调用UriMatcher的match()方法时,就可以将一个Uri对象传入,返回值是某个能够匹配这个Uri对象所对应的自定义代码,利用这个代码,我们就可以判断出调用方期待访问的是哪张表中的数据了。

除此之外,还有一个getTypt()方法,它是所有的内容提供其都必须提供的一个方法,用于获取Uri对象所对应的MIME类型,一个内容URI所对应的MIME字符串主要由三部分组成,Android对这三个部分做了如下格式规定:

1.必须以vnd开头

2.如果内容URI以路径结尾,则后面接android.cursor.dir/,如果内容URI以id结尾,则后接android.cursor.item/。

3.最后接上vnd.<authority>.<path>

简单示例:

MyContentProvider

MyContentProvider.java

package cn.lixyz.mycontentprovider;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri; public class MyContentProvider extends ContentProvider { public static final int STUDENTS_DIR = 0;
public static final int STUDENTS_ITEM = 1;
public static final int CLASSES_DIR = 2;
public static final int CLASSES_ITEM = 3; private static UriMatcher uriMatcher; private MyDBHelper myDBHelper;
private SQLiteDatabase database; private static final String AUTHORITY = "cn.lixyz.mycontentprovider.cp"; static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI("cn.lixyz.mycontentprovider.cp", "students", STUDENTS_DIR);
uriMatcher.addURI("cn.lixyz.mycontentprovider.cp", "students/#", STUDENTS_ITEM);
uriMatcher.addURI("cn.lixyz.mycontentprovider.cp", "classes", CLASSES_DIR);
uriMatcher.addURI("cn.lixyz.mycontentprovider.cp", "classes/#", CLASSES_ITEM);
} @Override
public boolean onCreate() {
myDBHelper = new MyDBHelper(getContext(), "school.db", null, 1);
return true;
} @Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { database = myDBHelper.getReadableDatabase();
Cursor cursor = null;
switch (uriMatcher.match(uri)) {
case STUDENTS_DIR:
cursor = database.query("students", projection, selection, selectionArgs, null, null, sortOrder);
break;
case STUDENTS_ITEM:
String studentID = uri.getPathSegments().get(1);
cursor = database.query("students", projection, "_id=?", new String[] { studentID }, null, null, sortOrder);
break;
case CLASSES_DIR:
cursor = database.query("classes", projection, selection, selectionArgs, null, null, sortOrder);
break;
case CLASSES_ITEM:
String classID = uri.getPathSegments().get(1);
cursor = database.query("classes", projection, "_id=?", new String[] { classID }, null, null, sortOrder);
break;
} return cursor;
} @Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case STUDENTS_DIR:
return "vnd.android.cursor.dir/vnd.cn.lixyz.mycontentprovider.cp.students";
case STUDENTS_ITEM:
return "vnd.android.cursor.item/vnd.cn.lixyz.mycontentprovider.cp.students";
case CLASSES_DIR:
return "vnd.android.cursor.dir/vnd.cn.lixyz.mycontentprovider.cp.classes";
case CLASSES_ITEM:
return "vnd.android.cursor.item/vnd.cn.lixyz.mycontentprovider.cp.classes";
}
return null;
} @Override
public Uri insert(Uri uri, ContentValues values) { database = myDBHelper.getWritableDatabase();
Uri returnUri = null;
switch (uriMatcher.match(uri)) {
case STUDENTS_DIR:
case STUDENTS_ITEM:
long newStudent = database.insert("students", null, values);
returnUri = Uri.parse("content://" + AUTHORITY + "/students/" + newStudent);
break;
case CLASSES_DIR:
case CLASSES_ITEM:
long newClass = database.insert("classes", null, values);
returnUri = Uri.parse("content://" + AUTHORITY + "/classes/" + newClass);
break; }
return returnUri;
} @Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
} @Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
} class MyDBHelper extends SQLiteOpenHelper { private Context mContext; public MyDBHelper(Context context, String name, CursorFactory factory, int version) {
super(context, name, factory, version);
this.mContext = context; } @Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(
"create table if not exists students (_id integer primary key autoincrement,studentName text,studentAge integer,class text)");
db.execSQL("create table if not exists classes (_id integer primary key autoincrement,className text)");
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub } } }

AndroidManifest.xml

<provider
android:name="MyContentProvider"
android:authorities="cn.lixyz.mycontentprovider.cp"
android:exported="true" >
</provider>

MyContentResolver

MainActivity.java

package cn.lixyz.mycontentresolver;

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.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); initView();
} public void clickButton(View view) {
switch (view.getId()) {
case R.id.bt_addclass:
addClass();
break;
case R.id.bt_addstudent:
addStudent();
break;
case R.id.searchclass:
searchClass();
break;
case R.id.searchstudent:
searchStrudent();
break;
}
} // 搜索学生方法
private void searchStrudent() {
Uri uri = Uri.parse("content://cn.lixyz.mycontentprovider.cp/students");
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(uri, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
while (cursor.moveToNext()) {
String tudentName = cursor.getString(cursor.getColumnIndex("studentName"));
int studentAge = cursor.getInt(cursor.getColumnIndex("studentAge"));
String className = cursor.getString(cursor.getColumnIndex("class"));
Log.d("TTTT", "学生姓名:" + tudentName + ",年龄 : " + studentAge + ",所在班级:" + className);
}
}
} // 搜索班级方法
private void searchClass() {
Uri uri = Uri.parse("content://cn.lixyz.mycontentprovider.cp/classes");
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(uri, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
while (cursor.moveToNext()) {
String className = cursor.getString(cursor.getColumnIndex("className"));
Log.d("TTTT", "班级:" + className);
}
}
} // 添加学生方法
private void addStudent() {
String studentName = et_studentname.getText().toString().trim();
String studentAge = et_studentage.getText().toString().trim();
String studentClass = et_studentclass.getText().toString().trim();
Uri uri = Uri.parse("content://cn.lixyz.mycontentprovider.cp/students");
ContentResolver contentResolver = getContentResolver();
ContentValues cv = new ContentValues();
cv.put("studentName", studentName);
cv.put("studentAge", studentAge);
cv.put("class", studentClass);
Uri returnUri = contentResolver.insert(uri, cv); Log.d("TTTT", "returnUri:" + returnUri.toString());
} // 添加班级方法
private void addClass() {
ContentResolver contentResolver = getContentResolver();
Uri uri = Uri.parse("content://cn.lixyz.mycontentprovider.cp/classes");
String className = et_addclass.getText().toString().trim();
ContentValues cv = new ContentValues();
cv.put("className", className);
contentResolver.insert(uri, cv);
} private EditText et_addclass, et_studentname, et_studentage, et_studentclass;
private Button bt_addclass, bt_addstudent, searchclass, searchstudent; private void initView() {
et_addclass = (EditText) findViewById(R.id.et_addclass);
et_studentname = (EditText) findViewById(R.id.et_studentname);
et_studentage = (EditText) findViewById(R.id.et_studentage);
et_studentclass = (EditText) findViewById(R.id.et_studentclass);
bt_addclass = (Button) findViewById(R.id.bt_addclass);
bt_addstudent = (Button) findViewById(R.id.bt_addstudent);
searchclass = (Button) findViewById(R.id.searchclass);
searchstudent = (Button) findViewById(R.id.searchstudent);
}
}

activity_main.xml

<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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="cn.lixyz.mycontentresolver.MainActivity" > <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="添加班级" /> <EditText
android:id="@+id/et_addclass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="输入班级名称" /> <Button
android:id="@+id/bt_addclass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="添 加" /> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="添加学生" /> <EditText
android:id="@+id/et_studentname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="输入学生姓名" /> <EditText
android:id="@+id/et_studentage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="输入学生年龄" /> <EditText
android:id="@+id/et_studentclass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="输入学生班级" /> <Button
android:id="@+id/bt_addstudent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="添 加" /> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="搜索" /> <Button
android:id="@+id/searchclass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="点我搜索班级" /> <Button
android:id="@+id/searchstudent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="点我搜索学生" /> </LinearLayout>

  这样,就可以在ContentResolver应用中,对ContentProvider应用的数据库进行insert和query操作了。

最新文章

  1. [C1] C1FlexGrid 排除非绑定列的验证效果
  2. CSS:position:fixed使用(转)
  3. Android出现java.net.SocketException: Permission denied报错
  4. python学习之——爬取网页信息
  5. 面向对象--类库、委托、is和as运算符、泛型集合
  6. Eclipse安装SVN插件的方法( 手动安装)
  7. 什么是staging server
  8. mongod
  9. Linux 下文件监控
  10. BOOST_PP_INC_I(x)实现
  11. 网易ios 面试
  12. 好用的消息对话框-TipsWindown
  13. Linux 下使用网易的SMTP服务器 发送邮件
  14. hasOwnProperty的用法
  15. 容器化时代我们应当选择Kubernetes
  16. Java 程序国际化
  17. HC32F003与STM8S003资源对比,只是对比,大家评论~!
  18. sql语句中select……as的用法
  19. 【UOJ#236】[IOI2016]railroad(欧拉回路,最小生成树)
  20. Got fatal error 1236 from master when reading data from binary log: &#39;Could not find first log file name in binary log index file&#39;系列二:reset slave

热门文章

  1. 深度强化学习 之 运行环境 mujoco 报错 ERROR: GLEW initalization error: Missing GL version
  2. Python3基础 yield 创建生成器
  3. PAT 甲级 1074 Reversing Linked List (25 分)(链表部分逆置,结合使用双端队列和栈,其实使用vector更简单呐)
  4. Swift编码总结7
  5. [LeetCode] 529. Minesweeper 扫雷
  6. [LeetCode] 774. Minimize Max Distance to Gas Station 最小化加油站间的最大距离
  7. LeetCode:第K个排列【60】
  8. 后会有期,江湖再见!(WondersGroup)
  9. 史上最详细bitbucket入门手册,手把手操作指南
  10. Netty--索引