android之内容提供者解析

该系统有两个应用,比较繁琐。但是内容提供者是android里非常非常重要的一个内容,我们得好好学习下哦。先看效果图,我们提供了四个按钮,点击按钮便会进行相应的操作。

我们先看内容提供者所在的应用,代码结构:

activity代码:

[java] view plaincopy

  1. package cn.com.contentProvider;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.widget.TextView;
  5. public class ContentProviderAcitivity extends Activity {
  6. @Override
  7. public void onCreate(Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.main);
  10. }
  11. }

MyContentProvider.java代码

[java] view plaincopy

  1. package cn.com.contentProvider;
  2. import android.content.ContentProvider;
  3. import android.content.ContentUris;
  4. import android.content.ContentValues;
  5. import android.content.Context;
  6. import android.content.UriMatcher;
  7. import android.database.Cursor;
  8. import android.database.sqlite.SQLiteDatabase;
  9. import android.database.sqlite.SQLiteOpenHelper;
  10. import android.database.sqlite.SQLiteDatabase.CursorFactory;
  11. import android.net.Uri;
  12. /**
  13. *
  14. * @author chenzheng_java
  15. * @description 自定义的内容提供者.
  16. *  总结下访问内容提供者的主要步骤:
  17. * 第一:我们要有一个uri,这就相当于我们的网址,我们有了网址才能去访问具体的网站
  18. * 第二:我们去系统中寻找该uri中的authority(可以理解为主机地址),
  19. *      只要我们的内容提供者在manifest.xml文件中注册了,那么系统中就一定存在。
  20. * 第三:通过内容提供者内部的uriMatcher对请求进行验证(你找到我了,还不行,我还得看看你有没有权限访问我呢)。
  21. * 第四:验证通过后,就可以调用内容提供者的增删查改方法进行操作了
  22. */
  23. public class MyContentProvider extends ContentProvider {
  24. // 自己实现的数据库操作帮助类
  25. private MyOpenHelper myOpenHelper;
  26. // 数据库相关类
  27. private SQLiteDatabase sqLiteDatabase;
  28. // uri匹配相关
  29. private static UriMatcher uriMatcher;
  30. // 主机名称(这一部分是可以随便取得)
  31. private static final String authority = "cn.com.chenzheng_java.hello";
  32. // 注册该内容提供者匹配的uri
  33. static {
  34. uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
  35. /*
  36. * path_chenzheng部分的字符串是随便取得,1代表着如果请求的uri与当前加入
  37. * 的匹配uri正好吻合,uriMathcher.match()方法返回的值.#代表任意数字,*代表任意字符串
  38. */
  39. uriMatcher.addURI(authority, "path_chenzheng", 1);// 代表当前表中的所有的记录
  40. uriMatcher.addURI(authority, "path_chenzheng/#", 2);// 代表当前表中的某条特定的记录,记录id便是#处得数字
  41. }
  42. // 数据表中的列名映射
  43. private static final String _id = "id";
  44. private static final String name = "name";
  45. private static final String age = "age";
  46. private static final String isMan = "isMan";
  47. /**
  48. * @description 当内容提供者第一次创建时执行
  49. */
  50. @Override
  51. public boolean onCreate() {
  52. try {
  53. myOpenHelper = new MyOpenHelper(getContext(), DB_Name, null,
  54. Version_1);
  55. } catch (Exception e) {
  56. return false;
  57. }
  58. return true;
  59. }
  60. /**
  61. * @description 对数据库进行删除操作的时候执行
  62. *              android.content.ContentUri为我们解析uri相关的内容提供了快捷方便的途径
  63. */
  64. @Override
  65. public int delete(Uri uri, String selection, String[] selectionArgs) {
  66. int number = 0;
  67. sqLiteDatabase = myOpenHelper.getWritableDatabase();
  68. int code = uriMatcher.match(uri);
  69. switch (code) {
  70. case 1:
  71. number = sqLiteDatabase
  72. .delete(Table_Name, selection, selectionArgs);
  73. break;
  74. case 2:
  75. long id = ContentUris.parseId(uri);
  76. /*
  77. * 拼接where子句用三目运算符是不是特烦人啊? 实际上,我们这里可以用些技巧的.
  78. * if(selection==null||"".equals(selection.trim())) selection =
  79. * " 1=1 and "; selection+=_id+"="+id;
  80. * 拼接where子句中最麻烦的就是and的问题,这里我们通过添加一个1=1这样的恒等式便将问题解决了
  81. */
  82. selection = (selection == null || "".equals(selection.trim())) ? _id
  83. + "=" + id
  84. : selection + " and " + _id + "=" + id;
  85. number = sqLiteDatabase
  86. .delete(Table_Name, selection, selectionArgs);
  87. break;
  88. default:
  89. throw new IllegalArgumentException("异常参数");
  90. }
  91. return number;
  92. }
  93. /**
  94. *@description 获取当前内容提供者的MIME类型 集合类型必须添加前缀vnd.android.cursor.dir/(该部分随意)
  95. *              单条记录类型添加前缀vnd,android.cursor.item/(该部分随意)
  96. *              定义了该方法之后,系统会在第一次请求时进行验证,验证通过则执行crub方法时不再重复进行验证,
  97. *              否则如果没有定义该方法或者验证失败,crub方法执行的时候系统会默认的为其添加类型验证代码。
  98. */
  99. @Override
  100. public String getType(Uri uri) {
  101. int code = uriMatcher.match(uri);
  102. switch (code) {
  103. case 1:
  104. return "vnd.android.cursor.dir/chenzheng_java";
  105. case 2:
  106. return "vnd.android.cursor.item/chenzheng_java";
  107. default:
  108. throw new IllegalArgumentException("异常参数");
  109. }
  110. }
  111. /**
  112. * @description 对数据表进行insert时执行该方法
  113. */
  114. @Override
  115. public Uri insert(Uri uri, ContentValues values) {
  116. sqLiteDatabase = myOpenHelper.getWritableDatabase();
  117. int code = uriMatcher.match(uri);
  118. switch (code) {
  119. case 1:
  120. sqLiteDatabase.insert(Table_Name, name, values);
  121. break;
  122. case 2:
  123. long id = sqLiteDatabase.insert(Table_Name, name, values);
  124. // withAppendId将id添加到uri的最后
  125. ContentUris.withAppendedId(uri, id);
  126. break;
  127. default:
  128. throw new IllegalArgumentException("异常参数");
  129. }
  130. return uri;
  131. }
  132. /**
  133. * 当执行查询时调用该方法
  134. */
  135. @Override
  136. public Cursor query(Uri uri, String[] projection, String selection,
  137. String[] selectionArgs, String sortOrder) {
  138. Cursor cursor = null;
  139. sqLiteDatabase = myOpenHelper.getReadableDatabase();
  140. int code = uriMatcher.match(uri);
  141. switch (code) {
  142. case 1:
  143. cursor = sqLiteDatabase.query(Table_Name, projection, selection,
  144. selectionArgs, null, null, sortOrder);
  145. break;
  146. case 2:
  147. // 从uri中解析出ID
  148. long id = ContentUris.parseId(uri);
  149. selection = (selection == null || "".equals(selection.trim())) ? _id
  150. + "=" + id
  151. : selection + " and " + _id + "=" + id;
  152. cursor = sqLiteDatabase.query(Table_Name, projection, selection,
  153. selectionArgs, null, null, sortOrder);
  154. break;
  155. default:
  156. throw new IllegalArgumentException("参数错误");
  157. }
  158. return cursor;
  159. }
  160. /**
  161. * 当执行更新操作的时候执行该方法
  162. */
  163. @Override
  164. public int update(Uri uri, ContentValues values, String selection,
  165. String[] selectionArgs) {
  166. int num = 0;
  167. sqLiteDatabase = myOpenHelper.getWritableDatabase();
  168. int code = uriMatcher.match(uri);
  169. switch (code) {
  170. case 1:
  171. num = sqLiteDatabase.update(Table_Name, values, selection, selectionArgs);
  172. break;
  173. case 2:
  174. long id = ContentUris.parseId(uri);
  175. selection = (selection == null || "".equals(selection.trim())) ? _id
  176. + "=" + id
  177. : selection + " and " + _id + "=" + id;
  178. num = sqLiteDatabase.update(Table_Name, values, selection, selectionArgs);
  179. break;
  180. default:
  181. break;
  182. }
  183. return num;
  184. }
  185. // 数据库名称
  186. private final String DB_Name = "chenzheng_java.db";
  187. // 数据表名
  188. private final String Table_Name = "chenzheng_java";
  189. // 版本号
  190. private final int Version_1 = 1;
  191. private class MyOpenHelper extends SQLiteOpenHelper {
  192. public MyOpenHelper(Context context, String name,
  193. CursorFactory factory, int version) {
  194. super(context, name, factory, version);
  195. }
  196. /**
  197. * @description 当数据表无连接时创建新的表
  198. */
  199. @Override
  200. public void onCreate(SQLiteDatabase db) {
  201. String sql = " create table if not exists " + Table_Name
  202. + "(id INTEGER,name varchar(20),age integer,isMan boolean)";
  203. db.execSQL(sql);
  204. }
  205. /**
  206. * @description 当版本更新时触发的方法
  207. */
  208. @Override
  209. public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  210. String sql = " drop table if exists " + Table_Name;
  211. db.execSQL(sql);
  212. onCreate(db);
  213. }
  214. }
  215. }

androidManifest.xml代码

[xhtml] view plaincopy

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="cn.com.contentProvider" android:versionCode="1"
  4. android:versionName="1.0">
  5. <uses-sdk android:minSdkVersion="8" />
  6. <application android:icon="@drawable/icon" android:label="@string/app_name">
  7. <activity android:name=".ContentProviderAcitivity"
  8. android:label="@string/app_name">
  9. <intent-filter>
  10. <action android:name="android.intent.action.MAIN" />
  11. <category android:name="android.intent.category.LAUNCHER" />
  12. </intent-filter>
  13. </activity>
  14. <provider android:name=".MyContentProvider"
  15. android:authorities="cn.com.chenzheng_java.hello"
  16. android:multiprocess="true" android:permission="cn.com.chenzheng_java.permission"></provider>
  17. </application>
  18. <!--
  19. permission中的android:name的值与provider中的android:permission的值是一样的
  20. android:protectionLevel 则代表了权限等级
  21. -->
  22. <permission android:name="cn.com.chenzheng_java.permission"
  23. android:protectionLevel="normal"></permission>
  24. </manifest>

main.xml为默认。

----------------------------------------------------------------------------------------------------------------

第二个应用(用于访问内容提供者的应用)

activity代码

[java] view plaincopy

  1. package cn.com.chenzheng_java;
  2. import android.app.Activity;
  3. import android.content.ContentResolver;
  4. import android.content.ContentValues;
  5. import android.database.Cursor;
  6. import android.net.Uri;
  7. import android.os.Bundle;
  8. import android.util.Log;
  9. import android.view.View;
  10. import android.widget.Button;
  11. import android.widget.TextView;
  12. /**
  13. *
  14. * @author chenzheng_java
  15. * @description 通过访问内容提供者进行增删查改.注意本程序中为了方便阅读,
  16. * 在需要数据库列名的地方直接写上了数据库中字段的名称,实际上这是不合理的,
  17. * 作为内容提供者的使用者,我们不可能在使用这个内容提供者之前先去了解sqlite
  18. * 中表的结构。比较适宜的做法是,在内容提供者中将愿意提供给外部访问的字段名称(列名)
  19. * 定义为string final 的常量!
  20. */
  21. public class ContentAccessActivity extends Activity {
  22. private final static String tag = "通知";
  23. private TextView textView;
  24. String result = "结果:/n";
  25. ContentResolver reslover;
  26. Uri uri;
  27. @Override
  28. public void onCreate(Bundle savedInstanceState) {
  29. super.onCreate(savedInstanceState);
  30. setContentView(R.layout.main);
  31. /**
  32. * 这里我们一定要搞清楚,uri的内容到底和内容提供者中哪个地方一一对应
  33. * 在MyContentProvider中我们有如下片段
  34. * uriMatcher.addURI(authority, "path_chenzheng", 1);// 代表当前表中的所有的记录
  35. uriMatcher.addURI(authority, "path_chenzheng/#", 2);// 代表当前表中的某条特定的记录,记录id便是#处得数字
  36. 其中authority为cn.com.chenzheng_java.hello。
  37. */
  38. uri = Uri.parse("content://cn.com.chenzheng_java.hello/path_chenzheng");
  39. /**
  40. * 内容提供者是什么?内容提供者相当于一个封装好了增删改查操作的接口,这个接口有一把锁,只有携带钥匙的访问者才能访问。
  41. * ContentResolver是什么?ContentResolver是一个开锁匠,他携带者钥匙(钥匙上有标签显示他是那个门得钥匙,如path_chenzheng)
  42. * 去寻找内容提供者,然后访问内容提供者的增删查改方法
  43. * 我们这里调用contentResolver的增删查改就相当于将任务交给了锁匠,
  44. * 然后让锁匠去找能打开的内容提供者,并且执行里面相应的方法,并将结果返回.
  45. * ContentResolver的好处在于,我们可以无视CotentProvider的具体实现,无论contentProvider里面是如何实现的,我想执行
  46. * 某一个操作时,所要书写的代码都是一样的。
  47. */
  48. reslover = this.getContentResolver();
  49. textView = (TextView) findViewById(R.id.textView);
  50. Button insertButton = (Button) findViewById(R.id.insertButton);
  51. insertButton.setOnClickListener(new View.OnClickListener() {
  52. @Override
  53. public void onClick(View v) {
  54. insert(reslover, uri);
  55. }
  56. });
  57. Button deleteButton = (Button) findViewById(R.id.deleteButton);
  58. deleteButton.setOnClickListener(new View.OnClickListener() {
  59. @Override
  60. public void onClick(View v) {
  61. delete(reslover, uri);
  62. }
  63. });
  64. Button updateButton = (Button) findViewById(R.id.updateButton);
  65. updateButton.setOnClickListener(new View.OnClickListener() {
  66. @Override
  67. public void onClick(View v) {
  68. update(reslover, uri);
  69. }
  70. });
  71. Button queryButton = (Button) findViewById(R.id.queryButton);
  72. queryButton.setOnClickListener(new View.OnClickListener() {
  73. @Override
  74. public void onClick(View v) {
  75. query(reslover, uri);
  76. }
  77. });
  78. }
  79. private void insert(ContentResolver resolver, Uri uri) {
  80. ContentValues contentValues = new ContentValues();
  81. contentValues.put("name", "张小凡");
  82. contentValues.put("age", 22);
  83. contentValues.put("isMan", true);
  84. Uri uri2 = resolver.insert(uri, contentValues);
  85. Log.i(tag, "插入成功!");
  86. result += "成功插入了一条记录,uri为" + uri2;
  87. textView.setText(result);
  88. result = "";
  89. }
  90. private void update(ContentResolver resolver, Uri uri) {
  91. ContentValues contentValues = new ContentValues();
  92. contentValues.put("age", 122);
  93. int number = resolver.update(uri, contentValues, null, null);
  94. Log.i(tag, "更新成功!");
  95. result += "成功更新了" + number+"条记录";
  96. textView.setText(result);
  97. result = "";
  98. }
  99. private void delete(ContentResolver resolver, Uri uri) {
  100. String where = " 1=1 and isMan=?";
  101. //这里要注意哦,sqlite数据库中是没有boolean的,true会被转成1存储
  102. String[] selectionArgs = new String[] { "1" };
  103. int number = resolver.delete(uri, where, selectionArgs);
  104. Log.i(tag, "删除成功!");
  105. textView.setText(result + "成功删除了" + number + "条记录");
  106. result = "";
  107. }
  108. private void query(ContentResolver resolver, Uri uri) {
  109. String[] projection = new String[] { "id", "name", "age", "isMan" };
  110. Cursor cursor = resolver.query(uri, projection, null, null, null);
  111. int count = cursor.getCount();
  112. Log.i(tag, "总记录数" + count);
  113. int idIndex = cursor.getColumnIndex("id");
  114. int nameIndex = cursor.getColumnIndex("name");
  115. int ageIndex = cursor.getColumnIndex("age");
  116. int isManIndex = cursor.getColumnIndex("isMan");
  117. cursor.moveToFirst();
  118. while (!cursor.isAfterLast()) {
  119. int id = cursor.getInt(idIndex);
  120. String name = cursor.getString(nameIndex);
  121. int age = cursor.getInt(ageIndex);
  122. int isMan = cursor.getInt(isManIndex);
  123. Log.i(tag, "id=" + id + " name=" + name + " age=" + age + " isMan="
  124. + isMan);
  125. result += "id=" + id + " name=" + name + " age=" + age + " isMan="
  126. + isMan;
  127. cursor.moveToNext();
  128. }
  129. textView.setText(result);
  130. result = "";
  131. }
  132. }

manifest.xml

[xhtml] view plaincopy

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="cn.com.chenzheng_java"
  4. android:versionCode="1"
  5. android:versionName="1.0">
  6. <uses-sdk android:minSdkVersion="8" />
  7. <application android:icon="@drawable/icon" android:label="@string/app_name">
  8. <activity android:name=".ContentAccessActivity"
  9. android:label="@string/app_name">
  10. <intent-filter>
  11. <action android:name="android.intent.action.MAIN" />
  12. <category android:name="android.intent.category.LAUNCHER" />
  13. </intent-filter>
  14. </activity>
  15. </application>
  16. <!-- 添加对内容提供者访问的权限,该权限是有我们自己定义的哦 -->
  17. <uses-permission android:name="cn.com.chenzheng_java.permission"></uses-permission>
  18. </manifest>

main.xml

[xhtml] view plaincopy

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. >
  7. <TextView
  8. android:id="@+id/textView"
  9. android:layout_width="fill_parent"
  10. android:layout_height="wrap_content"
  11. android:text="@string/hello"
  12. />
  13. <Button
  14. android:id="@+id/insertButton"
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:text="insert"
  18. ></Button>
  19. <Button
  20. android:id="@+id/deleteButton"
  21. android:layout_width="wrap_content"
  22. android:layout_height="wrap_content"
  23. android:text="delete"
  24. ></Button>
  25. <Button
  26. android:id="@+id/updateButton"
  27. android:layout_width="wrap_content"
  28. android:layout_height="wrap_content"
  29. android:text="update"
  30. ></Button>
  31. <Button
  32. android:id="@+id/queryButton"
  33. android:layout_width="wrap_content"
  34. android:layout_height="wrap_content"
  35. android:text="query"
  36. ></Button>
  37. </LinearLayout>

--------------------------------------------------------------------------------

想说的话,在代码的注释中已经说的很清晰了。这里再次重复下我们定义和使用内容提供者的步骤吧。

定义内容提供者:

我们定义内容提供者的目的是什么,共享数据,对,定义内容提供者的目的就是让别的应用能够访问当前应用的一些数据,至于到底暴露给外界什么数据,我们可以 在定义内容提供者的时候详细控制!不管如何,我们明确了第一个问题,定义内容提供者的目的----数据共享!

我们平时对数据的操作都有哪些?增删改查!就四个字!这也是为什么我们再定义内容提供者的时候必须要实现相应的方法了。当然如果你要是不想提供相应的操作,你可以在内部进行方法空实现。

是不是所有的应用都可以访问我啊?不可能!我们可不是随便的人,对吧!所以我们要进行验证,验证不通过的直接让它去死就可以了。验证怎么验证啊?通过UriMatcher进行匹配!

现在我们已经提供了访问接口了,我们怎么让系统知道,别的应用可以用我的东西啊?去配置文件中注册!!

使用内容提供者:

如何找到该内容提供者啊?需要Uri和相应的访问权限。相当于地址

如何进行增删查改啊?通过ContentResolver对象的相应方法。

android之内容提供者解析

时间: 2024-08-01 18:12:46

android之内容提供者解析的相关文章

Android 中内容提供者的使用

在Android中内容提供者主要是用于不同程序之间的数据共享.内容提供器的用法一般有两种,一种是使用现有的内容提供器来读取和操作相应程序的数据,另一种是创建自己的内容提供器,供其他的程序访问. 使用现有的内容提供器来读取和操作相应程序的数据 ContentResolve中提供了一系列的方法用于对数据进行增删改查的操作,其中,insert()用于添加数据,update()用于数据更新,delete()方法用于删除数据,query()用于数据的查询. 在ContentResolve中,使用内容URI

[Android Pro] 内容提供者ContentProvider的基本使用

一.ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据.ContentProvider为存储和获取数据提供了统一的接口.虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如采用文件方式对外共享数据,需要进行文件操作读写数据:采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据.而使用ContentProvider共享数据的

Android中内容提供者ContentProvider实现数据库增删改查

1.我们首先new一个我们自己的类集成ContentProvider,并实现方法如下 package com.wzw.sqllitedemo.providers; import com.wzw.sqllitedemo.db.PersonSQLiteOpenHelper; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues;

android contentprovider内容提供者

contentprovider内容提供者:让其他app可以访问私有数据库(文件) 1.AndroidManifest.xml 配置provider <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.dbtest&q

Android之内容提供者ContentProvider的总结

本文包含以下知识点: ContentProvider Uri 的介绍 ContentResolver: 监听ContentProvider的数据改变 一:ContentProvider部分 ContentProvider的作用: Content providers store and retrieve data and make it accessible to all applications. They're the only way to share data across applica

Android 利用内容提供者添加联系人的操作

上文中<Android 获取系统的联系人>主要介绍了怎样获取系统联系人并实战了一下,本文将介绍如何添加一条联系人信息 添加联系人 1. 添加raw_contacts表,添加一条联系人的id 2. 操作data表,插入联系人的数据,每个联系人数据都对应一列 raw_contact_id 新建项目,布局文件代码如下: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns

Android组件系列----ContentProvider内容提供者

[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4108017.html 联系方式:[email protected] [正文] 一.ContentProvider简介: ContentProvider内容提供者(四大组件之一)主要用于在不同的应用程序之间实现数据共享的功能. ContentProvider可以理解为一个Android应用对外开放的

Android四大基本组件(2)之Service 服务与Content Provider内容提供者

一.Service 服务: 一个Service 是一段长生命周期的,没有用户界面的程序,可以用来开发如监控类程序. 比较好的一个例子就是一个正在从播放列表中播放歌曲的媒体播放器.在一个媒体播放器的应用中,应该会有多个activity,让使用者可以选择歌曲并播放歌曲.然而,音乐重放这个功能并没有对应的activity,因为使用者当然会认为在导航到其它屏幕时音乐应该还在播放的.在这个例子中,媒体播放器这个activity 会使用Context.startService()来启动一个service,从

【android基础篇】利用内容提供者实现短信备份

I,准备工作 系统存储短信内容的目录为:/dada/dada/com.android.providers.telephony/databases/mmssms.db,我们找到对应的数据库文件. 我们可以发现该文件对于第三方而言,是不可读不可写的,这里则必须要使用内容提供者. 问题就来了:我不知道主机名,也就无法作为中间人去找证监会打探消息.其实,完全没有关系,我们可以翻阅安卓的源代码: \packages\providers\TelephonyProvider的清单文件,因为主机名都配置在清单文