Android ContentProvider完整案例
Posted 星辰
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android ContentProvider完整案例相关的知识,希望对你有一定的参考价值。
ContentData类,提供数据常量:
/** * 提供ContentProvider对外的各种常量,当外部数据需要访问的时候,就可以参考这些常量操作数据。 * @author HB * */ public class ContentData { public static final String AUTHORITY = "hb.android.contentProvider"; public static final String DATABASE_NAME = "teacher.db"; //创建 数据库的时候,都必须加上版本信息;并且必须大于4 public static final int DATABASE_VERSION = 4; public static final String USERS_TABLE_NAME = "teacher"; public static final class UserTableData implements BaseColumns { public static final String TABLE_NAME = "teacher"; //Uri,外部程序需要访问就是通过这个Uri访问的,这个Uri必须的唯一的。 public static final Uri CONTENT_URI = Uri.parse("content://"+ AUTHORITY + "/teacher"); // 数据集的MIME类型字符串则应该以vnd.android.cursor.dir/开头 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/hb.android.teachers"; // 单一数据的MIME类型字符串应该以vnd.android.cursor.item/开头 public static final String CONTENT_TYPE_ITME = "vnd.android.cursor.item/hb.android.teacher"; /* 自定义匹配码 */ public static final int TEACHERS = 1; /* 自定义匹配码 */ public static final int TEACHER = 2; public static final String TITLE = "title"; public static final String NAME = "name"; public static final String DATE_ADDED = "date_added"; public static final String SEX = "SEX"; public static final String DEFAULT_SORT_ORDER = "_id desc"; public static final UriMatcher uriMatcher; static { // 常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码 uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); // 如果match()方法匹配content://hb.android.teacherProvider/teachern路径,返回匹配码为TEACHERS uriMatcher.addURI(ContentData.AUTHORITY, "teacher", TEACHERS); // 如果match()方法匹配content://hb.android.teacherProvider/teacher/230,路径,返回匹配码为TEACHER uriMatcher.addURI(ContentData.AUTHORITY, "teacher/#", TEACHER); } } }
SQLite操作类DBOpenHelper
/** * 这个类继承SQLiteOpenHelper抽象类,用于创建数据库和表。创建数据库是调用它的父类构造方法创建。 * @author HB */ public class DBOpenHelper extends SQLiteOpenHelper { // 在SQLiteOepnHelper的子类当中,必须有该构造函数,用来创建一个数据库; public DBOpenHelper(Context context, String name, CursorFactory factory, int version) { // 必须通过super调用父类当中的构造函数 super(context, name, factory, version); // TODO Auto-generated constructor stub } // public DBOpenHelper(Context context, String name) { // this(context, name, VERSION); // } public DBOpenHelper(Context context, String name, int version) { this(context, name, null, version); } /** * 只有当数据库执行创建 的时候,才会执行这个方法。如果更改表名,也不会创建,只有当创建数据库的时候,才会创建改表名之后 的数据表 */ @Override public void onCreate(SQLiteDatabase db) { System.out.println("create table"); db.execSQL("create table " + ContentData.UserTableData.TABLE_NAME + "(" + ContentData.UserTableData._ID + " INTEGER PRIMARY KEY autoincrement," + ContentData.UserTableData.NAME + " varchar(20)," + ContentData.UserTableData.TITLE + " varchar(20)," + ContentData.UserTableData.DATE_ADDED + " long," + ContentData.UserTableData.SEX + " boolean)" + ";"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
内容提供者类
/** * 这个类给外部程序提供访问内部数据的一个接口 * @author HB * */ public class TeacherContentProvider extends ContentProvider { private DBOpenHelper dbOpenHelper = null; // UriMatcher类用来匹配Uri,使用match()方法匹配路径时返回匹配码 /** * 是一个回调函数,在ContentProvider创建的时候,就会运行,第二个参数为指定数据库名称,如果不指定,就会找不到数据库; * 如果数据库存在的情况下是不会再创建一个数据库的。(当然首次调用 在这里也不会生成数据库必须调用SQLiteDatabase的 getWritableDatabase,getReadableDatabase两个方法中的一个才会创建数据库) */ @Override public boolean onCreate() { //这里会调用 DBOpenHelper的构造函数创建一个数据库; dbOpenHelper = new DBOpenHelper(this.getContext(), ContentData.DATABASE_NAME, ContentData.DATABASE_VERSION); return true; } /** * 当执行这个方法的时候,如果没有数据库,他会创建,同时也会创建表,但是如果没有表,下面在执行insert的时候就会出错 * 这里的插入数据也完全可以用sql语句书写,然后调用 db.execSQL(sql)执行。 */ @Override public Uri insert(Uri uri, ContentValues values){ //获得一个可写的数据库引用,如果数据库不存在,则根据onCreate的方法里创建; SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); long id = 0; switch (uriMatcher.match(uri)) { case TEACHERS: id = db.insert("teacher", null, values); // 返回的是记录的行号,主键为int,实际上就是主键值 return ContentUris.withAppendedId(uri, id); case TEACHER: id = db.insert("teacher", null, values); String path = uri.toString(); return Uri.parse(path.substring(0, path.lastIndexOf("/"))+id); // 替换掉id default: throw new IllegalArgumentException("Unknown URI " + uri); } } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); int count = 0; switch (uriMatcher.match(uri)) { case TEACHERS: count = db.delete("teacher", selection, selectionArgs); break; case TEACHER: // 下面的方法用于从URI中解析出id,对这样的路径content://hb.android.teacherProvider/teacher/10 // 进行解析,返回值为10 long personid = ContentUris.parseId(uri); String where = "_ID=" + personid; // 删除指定id的记录 where += !TextUtils.isEmpty(selection) ? " and (" + selection + ")" : ""; // 把其它条件附加上 count = db.delete("teacher", where, selectionArgs); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } db.close(); return count; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); int count = 0; switch (uriMatcher.match(uri)) { case TEACHERS: count = db.update("teacher", values, selection, selectionArgs); break; case TEACHER: // 下面的方法用于从URI中解析出id,对这样的路径content://com.ljq.provider.personprovider/person/10 // 进行解析,返回值为10 long personid = ContentUris.parseId(uri); String where = "_ID=" + personid;// 获取指定id的记录 where += !TextUtils.isEmpty(selection) ? " and (" + selection + ")" : "";// 把其它条件附加上 count = db.update("teacher", values, where, selectionArgs); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } db.close(); return count; } @Override public String getType(Uri uri) { switch (uriMatcher.match(uri)) { case TEACHERS: return CONTENT_TYPE; case TEACHER: return CONTENT_TYPE_ITME; default: throw new IllegalArgumentException("Unknown URI " + uri); } } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); switch (uriMatcher.match(uri)) { case TEACHERS: return db.query("teacher", projection, selection, selectionArgs, null, null, sortOrder); case TEACHER: // 进行解析,返回值为10 long personid = ContentUris.parseId(uri); String where = "_ID=" + personid;// 获取指定id的记录 where += !TextUtils.isEmpty(selection) ? " and (" + selection + ")" : "";// 把其它条件附加上 return db.query("teacher", projection, where, selectionArgs, null, null, sortOrder); default: throw new IllegalArgumentException("Unknown URI " + uri); } } }
文件清单:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="hb.android.contentProvider" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="8" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".TeacherActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <span style="white-space:pre"> </span><provider android:name=".TeacherContentProvider" <span style="white-space:pre"> </span>android:authorities="hb.android.contentProvider" /> </application> </manifest>
main.xml文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/insert" android:text="@string/insert" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <Button android:id="@+id/query" android:text="@string/query" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <Button android:id="@+id/querys" android:text="@string/querys" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <Button android:id="@+id/update" android:text="@string/update" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <Button android:id="@+id/delete" android:text="@string/delete" android:layout_width="fill_parent" android:layout_height="wrap_content"/> </LinearLayout>
TeacherActivity内容提供者测试类
package hb.android.contentProvider; import java.util.Date; 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.view.View; import android.view.View.OnClickListener; import android.widget.Button; /** * 这个类用来测试ContentProvider是否可用。通过 给定的uri访问,数据库; * * @author HB * */ public class TeacherActivity extends Activity { Button insert; Button query; Button update; Button delete; Button querys; Uri uri = Uri.parse("content://hb.android.contentProvider/teacher"); /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); insert = (Button) findViewById(R.id.insert); query = (Button) findViewById(R.id.query); update = (Button) findViewById(R.id.update); delete = (Button) findViewById(R.id.delete); querys = (Button) findViewById(R.id.querys); // 绑定监听器的两种方法一; insert.setOnClickListener(new InsertListener()); query.setOnClickListener(new QueryListener()); // 方法二 update.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub ContentResolver cr = getContentResolver(); ContentValues cv = new ContentValues(); cv.put("name", "huangbiao"); cv.put("date_added", (new Date()).toString()); int uri2 = cr.update(uri, cv, "_ID=?", new String[]{"3"}); System.out.println("updated"+":"+uri2); } }); delete.setOnClickListener(new OnClickListener() { public void onClick(View v) { ContentResolver cr = getContentResolver(); cr.delete(uri, "_ID=?", new String[]{"2"}); } }); querys.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub ContentResolver cr = getContentResolver(); // 查找id为1的数据 Cursor c = cr.query(uri, null, null,null, null); System.out.println(c.getCount()); c.close(); } }); } class InsertListener implements OnClickListener { public void onClick(View v) { // TODO Auto-generated method stub ContentResolver cr = getContentResolver(); ContentValues cv = new ContentValues(); cv.put("title", "jiaoshou"); cv.put("name", "jiaoshi"); cv.put("sex", true); Uri uri2 = cr.insert(uri, cv); System.out.println(uri2.toString()); } } class QueryListener implements OnClickListener { public void onClick(View v) { // TODO Auto-generated method stub ContentResolver cr = getContentResolver(); // 查找id为1的数据 Cursor c = cr.query(uri, null, "_ID=?", new String[] { "1" }, null); //这里必须要调用 c.moveToFirst将游标移动到第一条数据,不然会出现index -1 requested , with a size of 1错误;cr.query返回的是一个结果集。 if (c.moveToFirst() == false) { // 为空的Cursor return; } int name = c.getColumnIndex("name"); System.out.println(c.getString(name)); c.close(); } } }
运行结果为:
以上是关于Android ContentProvider完整案例的主要内容,如果未能解决你的问题,请参考以下文章