第一行代码-7.3 创建自己的内容提供器
来源:互联网 发布:工业机器人软件平台 编辑:程序博客网 时间:2024/05/17 01:51
之前我们为了实现SQLite的功能,需要创建自己的DatabaseHelper类,现在我们也可以定义自己的ContentProvider来实现跨应用访问数据。但是六个方法都要重写。
由于整个MyProvider的实现比较复杂,所以先看代码再解释。在DatabaseTest中创建DatabaseProvider类,注意要把Toast去除掉,因为跨程序访问的时候不能使用Toast。
// DatabaseTest-DatabaseProvider.javapublic class DatabaseProvider extends ContentProvider{ public static final int STUDENT_DIR = 0; public static final int STUDENT_ITEM = 1; public static final int SUBJECT_DIR = 2; public static final int SUBJECT_ITEM = 3; public static final String AUTHORITY = "com.example.databasetest.provider"; private static UriMatcher uriMatcher; private MyDatabaseHelper dbHelper; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(AUTHORITY, "student", STUDENT_DIR); uriMatcher.addURI(AUTHORITY, "student/#", STUDENT_ITEM); uriMatcher.addURI(AUTHORITY, "subject", SUBJECT_DIR); uriMatcher.addURI(AUTHORITY, "subject/#", SUBJECT_ITEM); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = dbHelper.getWritableDatabase(); int deletedRows = 0; switch (uriMatcher.match(uri)) { case STUDENT_DIR: deletedRows = db.delete("student", selection, selectionArgs); break; case STUDENT_ITEM: String studentId = uri.getPathSegments().get(1); deletedRows = db.delete("student", "id = ?", new String[] {studentId}); break; case SUBJECT_DIR: deletedRows = db.delete("subject", selection, selectionArgs); break; case SUBJECT_ITEM: String subjectId = uri.getPathSegments().get(1); deletedRows = db.delete("subject", "id = ?", new String[] {subjectId}); break; default: break; } return deletedRows; } @Override public String getType(Uri uri) { switch (uriMatcher.match(uri)) { case STUDENT_DIR: return "vnd.android.cursor.dir/vnd.com.example.databasetest.provider.student"; case STUDENT_ITEM: return "vnd.android.cursor.item/vnd.com.example.databasetest.provider.student"; case SUBJECT_DIR: return "vnd.android.cursor.dir/vnd.com.example.databasetest.provider.subject"; case SUBJECT_ITEM: return "vnd.android.cursor.item/vnd.com.example.databasetest.provider.subject"; default: break; } return null; } @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = dbHelper.getWritableDatabase(); Uri uriReturn = null; switch (uriMatcher.match(uri)) { case STUDENT_ITEM: long newStudentId = db.insert("student", null, values); uriReturn = Uri.parse("content://"+AUTHORITY+"/student/"+newStudentId); break; case SUBJECT_ITEM: long newSubjectId = db.insert("subject", null, values); uriReturn = Uri.parse("content://"+AUTHORITY+"/student/"+newSubjectId); break; default: break; } return uriReturn; } @Override public boolean onCreate() { dbHelper = new MyDatabaseHelper(getContext(), "student.db", null, 1); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor cursor = null; switch (uriMatcher.match(uri)) { case STUDENT_DIR: cursor = db.query("student", projection, selection, selectionArgs, null, null, sortOrder); break; case STUDENT_ITEM: String studentId = uri.getPathSegments().get(1); cursor = db.query("student", projection, "id = ?", new String[] {studentId}, null, null, sortOrder); break; case SUBJECT_DIR: cursor = db.query("subject", projection, selection, selectionArgs, null, null, sortOrder); break; case SUBJECT_ITEM: String subjectId = uri.getPathSegments().get(1); cursor = db.query("subject", projection, "id = ?", new String[] {subjectId}, null, null, sortOrder); break; default:break; } return cursor; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db = dbHelper.getWritableDatabase(); int updatedRows = 0; switch (uriMatcher.match(uri)) { case STUDENT_DIR: updatedRows = db.update("student", values, selection, selectionArgs); break; case STUDENT_ITEM: String studentId = uri.getPathSegments().get(1); updatedRows = db.update("student", values, "id = ?", new String[] {studentId}); break; case SUBJECT_DIR: updatedRows = db.update("subject", values, selection, selectionArgs); break; case SUBJECT_ITEM: String subjectId = uri.getPathSegments().get(1); updatedRows = db.update("subject", values, "id = ?", new String[] {subjectId}); break; default: break; } return updatedRows; }}
有几点需要注意的地方:首先是uri.getPathSegments方法,它会把uri权限之后的内容以'/'符号进行分割,并把分割后
的结果放入到一个字符串列表中。根据前面提到的uri的格式,这个列表的第0 个位置存放的就是路径,第1 个位置存放的就是id 了。
然后是getType方法:它是所有的内容提供器都必须提供的一个方法,用于获取Uri 对象所对应的MIME 类型。一个内容URI 所对应的MIME字符串主要由三部分组分,Android 对这三个部分做了如下格式规定:
1. 必须以vnd 开头。
2. 如果内容URI 以路径结尾,则后接android.cursor.dir/,如果内容URI 以id 结尾,
则后接android.cursor.item/。
3. 最后接上vnd.<authority>.<path>。
写完了provider,还要在manifest中注册才可以使用:
<!-- DatabaseTest manifest --><provider android:name="com.example.databasetest.DatabaseProvider" android:authorities="com.example.databasetest.databasetest.provider"></provider>
最后是uriMatcher里面的方法,涉及到通配符:#的意思是任意长度的数字,*表示任意长度的字符。为什么要用到任意数字的匹配?因为Update和Delete方法都可能要传入行数的参数(也就是id的值),所以需要提取这个数字,就需要在uriMatcher中插入这个匹配。
终于到了最后一步:在其他应用中对DatabaseTest中的数据库操作。创建ProviderTest项目,并修改布局如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/insert_button" android:text="插入数据"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/query_button" android:text="遍历数据"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/update_button" android:text="更新数据"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/delete_button" android:text="删除数据"/></LinearLayout>
然后是MainActivity.java:
public class MainActivity extends Activity implements OnClickListener{ private Button mBInsert; private Button mBUpdate; private Button mBDelete; private Button mBQuery; private String newId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBInsert = (Button) findViewById(R.id.insert_button); mBUpdate = (Button) findViewById(R.id.update_button); mBDelete = (Button) findViewById(R.id.delete_button); mBQuery = (Button) findViewById(R.id.query_button); mBInsert.setOnClickListener(this); mBUpdate.setOnClickListener(this); mBDelete.setOnClickListener(this); mBQuery.setOnClickListener(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } @Override public void onClick(View view) { Uri uri; ContentValues values; switch (view.getId()) { case R.id.insert_button: // 添加数据 uri = Uri.parse("content://com.example.databasetest.provider/student"); values = new ContentValues(); values.put("no", "23"); values.put("name", "James"); values.put("number", "112233"); Uri newUri = getContentResolver().insert(uri, values); newId = newUri.getPathSegments().get(1); break; case R.id.query_button: // 遍历数据 uri = Uri.parse("content://com.example.databasetest.provider/student"); Cursor cursor = getContentResolver().query(uri, null, null, null, null); if (cursor != null) { while (cursor.moveToNext()) { String name = cursor.getString(cursor.getColumnIndex("name")); String no = cursor.getString(cursor.getColumnIndex("no")); String number = cursor.getString(cursor.getColumnIndex("number")); Log.d("sysu", name); Log.d("sysu", no); Log.d("sysu", number); } cursor.close(); } break; case R.id.update_button: // 更新数据 uri = Uri.parse("content://com.example.databasetest.provider/student/"+newId); values = new ContentValues(); values.put("no", "6"); values.put("name", "James"); values.put("number", "112233"); getContentResolver().update(uri, values, "id = ?", new String[] {newId}); break; case R.id.delete_button: // 删除数据 uri = Uri.parse("content://com.example.databasetest.provider/student/"+newId); getContentResolver().delete(uri, null, null); break; default: break; } }}
实现效果:
总结一下:ContentProvider是建立在数据存储的基础上实现的,只不过在访问另一个应用的数据的时候,需要借助uri访问,uri包括权限和参数(比如id的值),需要注意格式。在数据存储的应用中借助UriMatch判断出要访问的数据是什么。最后要注意getType的格式。
- 第一行代码-7.3 创建自己的内容提供器
- 第一行代码-第7章 内容提供器
- [Android][第一行代码][第 7 章 内容提供器]
- 《第一行代码》读书笔记(十一)----内容提供器
- 《第一行代码--Android》读书笔记之内容提供器
- 第一行代码-7.1 内容提供器简介
- Android第一行代码学习笔记五----内容提供器
- 内容提供器(ContentResolver)---《第一行代码Android》笔记
- 创建自己的内容提供器ContentProvider
- 创建自己的内容提供器
- Andriod---创建自己的内容提供器
- 第一行代码 第7章 内容提供器 -- 运行时权限
- 第一行代码 第7章 内容提供器 --基本用法
- 第一行代码 第7章 内容提供器 --实现跨程序数据共享
- android 学习笔记 创建自己的内容提供器
- 22读书笔记之创建自己的内容提供器
- 阅读郭林《第一行代码》的笔记——第7章 跨程序共享数据,探究内容提供器
- Android开发之创建自己的内容提供器并测试
- 微观经济学-- 第1章 经济学十大原理
- 获取上线APP的连接地址
- symfony分页实现方法
- struts环境本机搭建
- ApplePay 实现代码片段
- 第一行代码-7.3 创建自己的内容提供器
- vim 的使用方法
- 【三层架构】——基础知识
- linux下网络程序遭遇SIGPIPE的解决(转)
- app store 获取app信息
- 使用自定义framework 注意事项
- android studio快捷键
- 【C#】面向对象基础
- Android-Tab