说到ContentProvider之前,还是贴一段android-developer对它下定义的的原文:
Content providers are one of the primary building blocks of Android applications, providing content to applications. They encapsulate data and provide it to applications through the single ContentResolver interface. A content provider is only required if you need to share data between multiple applications.
上面说得很清楚,ContentProvider的主要作用是在不同的应用程序之间提供数据的共享,我们可以通过ContentResolver来获取ContentProvider中的数据,并进行增删改查的数据库操作。只有当我们需要在多个应用程序之间共享数据时,才有必要用到ContentProvider。
贴上使用ContentProvider的相关代码:
1 public class MyContentProvider extends ContentProvider{
2
3 private static final String TAG = "MyContentProvider";
4
5 private static final String AUTHORITY = "com.demo.contentprovidersample";
6 private static final String CONTENT_PATH= "content://"+ AUTHORITY+"/item";
7 public static final Uri CONTENT_URI = Uri.parse(CONTENT_PATH);
8
9 private static final String DATABASE_NAME = "update.db";
10 private static final String DATABASE_TABLE = "musicinfo";
11 private static final int DATABASE_VERSION = 1;
12
13 private static final String KEY_ID = "_id";
14 public static final String KEY_SINGER = "singer";
15 public static final String KEY_DATE = "date";
16 public static final String KEY_PRICE = "price";
17
18 private SQLiteDatabase mSqliteDatabase;
19 private MySQLiteHelper mSqliteHelper;
20 private static final UriMatcher URI_MATCHER;
21 private static final int ITEM = 1;
22 private static final int ITEM_ID = 2;
23 static {
24 URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
25 URI_MATCHER.addURI(AUTHORITY, "item", ITEM);
26 URI_MATCHER.addURI(AUTHORITY, "item/#", ITEM_ID);
27 }
28 @Override
29 public String getType(Uri uri) {
30 switch(URI_MATCHER.match(uri)){
31 case ITEM:
32 //vnd.android.cursor.dir/ 数据集的MIME类型字符串
33 return "vnd.android.cursor.dir/item";
34 case ITEM_ID:
35 //vnd.android.cursor.item/ 单一数据的MIME类型字符串
36 return "vnd.android.cursor.item/item";
37 default:
38 return null;
39 }
40 }
41 public boolean open() throws SQLiteException {
42 try{
43 mSqliteDatabase = mSqliteHelper.getWritableDatabase();
44 } catch(SQLiteException e) {
45 mSqliteDatabase = mSqliteHelper.getReadableDatabase();
46 }
47 return mSqliteDatabase != null ? true : false;
48 }
49 @Override
50 public int delete(Uri uri, String selection, String[] selectionArgs) {
51 return 0;
52 }
53 @Override
54 public Uri insert(Uri uri, ContentValues values) {
55 if(URI_MATCHER.match(uri) != ITEM) {
56 throw new IllegalArgumentException();
57 }
58 long row = mSqliteDatabase.insert(DATABASE_TABLE, KEY_ID, values);
59 if(row > 0) {
60 Log.i(TAG, "insert new item to database success!");
61 Uri mUri = ContentUris.withAppendedId(CONTENT_URI, row);
62 getContext().getContentResolver().notifyChange(uri, null);
63 return mUri;
64 }
65 return null;
66 }
67 @Override
68 public boolean onCreate() {
69 mSqliteHelper = new MySQLiteHelper(getContext(), DATABASE_NAME, null, DATABASE_VERSION);
70 return open();
71 }
72 @Override
73 public Cursor query(Uri uri, String[] projection, String selection,
74 String[] selectionArgs, String sortOrder) {
75 Cursor cursor = null;
76 switch(URI_MATCHER.match(uri)) {
77 case ITEM:
78 cursor = mSqliteDatabase.query(DATABASE_TABLE,
79 projection, selection, selectionArgs, null, null, sortOrder);
80 break;
81 case ITEM_ID:
82 String id = uri.getPathSegments().get(1);
83 cursor = mSqliteDatabase.query(DATABASE_TABLE,
84 projection,
85 // 加上其他查询条件
86 KEY_ID + "=" + id + (TextUtils.isEmpty(selection) ? "" : " and (" + selection + ")"),
87 selectionArgs, null, null, sortOrder);
88 break;
89 default:
90 throw new IllegalArgumentException();
91 }
92
93 return cursor;
94 }
95 @Override
96 public int update(Uri uri, ContentValues values, String selection,
97 String[] selectionArgs) {
98 return 0;
99 }
100 private static class MySQLiteHelper extends SQLiteOpenHelper {
101
102 private static final String DATABASE_CREATE = "create table "
103 + DATABASE_TABLE + " ("
104 + KEY_ID + " integer primary key autoincrement, "
105 + KEY_SINGER + " text not null, "
106 + KEY_DATE + " long not null, "
107 + KEY_PRICE + " float);";
108 private static final String DATABASE_DROP = "drop table if exists " + DATABASE_TABLE;
109
110 public MySQLiteHelper(Context context, String name,
111 CursorFactory factory, int version) {
112 super(context, name, factory, version);
113 }
114 @Override
115 public void onCreate(SQLiteDatabase db) {
116 db.execSQL(DATABASE_CREATE);
117 }
118 @Override
119 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
120 db.execSQL(DATABASE_DROP);
121 onCreate(db);
122 }
123 }
124 }
AndroidManifest.xml
1 <provider android:name=".MyContentProvider"
2 android:authorities="com.demo.contentprovidersample">
3 </provider>
MyContentProvider继承ContentProvider并实现onCreate,delete,update,insert,query,getType方法。我们可以在onCreate方法里初始化SQLiteOpenHelper的实例对象。delete,update,insert,query方法能通过SQLiteDatabase对象实现相应的数据库操作。
这里重点讲一下有关getType()的调用,其实我们不需要手动调用该方法。getType方法的目的是返回一个android系统可以识别的MIME值(wiki:MIME是多用途互联网邮件扩展(MIME,Multipurpose Internet Mail Extensions)是一个互联网标准,它扩展了电子邮件标准)
在隐式Intent机制中,如下面的代码:
1 Intent intent = new Intent();
2 intent.setAction(Intent.ACTION_VIEW);
3 intent.setData(Uri.parse("content://com.demo.contentprovidersample/item"));
4 intent.addCategory(Intent.CATEGORY_DEFAULT);
5 startActivity(intent);
系统先分析Uri为"content://com.demo.contentprovider/item",提取"com.demo.contentprovider",在所有AndroidManifest.xml中,找到authority是"com.demo.contentprovider"的ContentProvider,并调用该ContentProvider的getType方法,通过UriMatcher匹配已经申明的Uri类型,并返回一个android系统可以识别的MIME值,这里其实是一个特定内容的字符串。然后就可以找到注册了相应<intent-filter>的Activity,并启动之:
1 <intent-filter android:label="@string/content_provider">
2 <action android:name="android.intent.action.VIEW" />
3 <category android:name="android.intent.category.DEFAULT" />
4 <data android:mimeType="vnd.android.cursor.dir/item" />
5 </intent-filter>
如果你希望自己的ContentProvider可以被其他应用程序访问,并且它的CONTENT_URI,数据库字段等不是硬编码写入其他应用程序中,那么效仿Contacts的ContentProvider实现就可以了,有关这部分的内容也可以参考android NotePad项目。
浙公网安备 33010602011771号