1.什麼是ContentProvider
首先,ContentProvider(内容提供者)是android中的四大元件之一,但是在一般的開發中,可能使用的比較少。 ContentProvider為不同的軟體之間資料共享,提供統一的接口。也就是說,如果我們想讓其他的應用使用我們自己程式内的資料,就可以使用ContentProvider定義一個對外開放的接口,進而使得其他的應用可以使用咱們應用的檔案、資料庫記憶體儲的資訊。當然,自己開發的應用需要給其他應用共享資訊的需求可能比較少見,但是在Android系統中,很多系統自帶應用,比如聯系人資訊,圖檔庫,音頻庫等應用,為了對其他應用暴露資料,是以就使用了ContentProvider機制。是以,我們還是要學習ContentProvider的基本使用,在遇到擷取聯系人資訊,圖檔庫,音頻庫等需求的時候,才能更好的實作功能
2.如何定義一個ContentProvider
Android系統為了讓我們更好的對外暴露資料,提供了統一的接口,是以定義了抽象類ContentProvider,是以,如果我們想對外提供資料,我們需要繼承ContentProvider,并且實作下面的這幾個方法:
onCreate() 當我們的provider初始化時被調用,我們應該在這個方法裡面完成部分初始化操作 query() 查詢方法,用于給調用者傳回資料 insert() 插入操作,用于讓外部應用插入資料到内容提供者中 update() 更新操作,用于更新内容提供者的資料 delete() 用于删除資料 getType 傳回内容提供者的MIME Type
上面這些方法,當我們繼承自ContentProvider的時候,eclipse會自動的給我們添加,但是這并不代表我們每個方法都需要自定義實作。如果我們隻希望給其他應用提供資料,而不允許其他應用修改我們的資料,那麼我們隻需要實作onCreate(),getType()和query()這三個方法就可以了,其他的三個方法我們可以根據業務需求,實作或者是不實作。
因為一般使用ContentProvider向外部暴露資料庫的資訊,是以,本篇将以使用ContentProvider向其他應用暴露資料庫資訊為例,講解ContentProvider的基本使用。
Android中SQLite資料庫的建立和使用,本篇不再介紹,不清楚的請看這篇文章 SQLite資料庫的簡單實用
假設讀者已經學會了SQLite資料庫的使用,并且已經建立好了資料庫,下面我們開始寫我們的ContentProvider。 因為注釋解析的比較詳細,是以就不過多解釋了
1 /**
2 * 内容提供者
3 *
4 * @author ZhaoKaiQiang
5 * @time 2014年6月6日
6 */
7 public class StudentProvider extends ContentProvider {
8 // 資料庫操作類,用于擷取SQLiteDatabase
9 private MyDbOpenHelper dbHelper;
10
11 private static final int STUDENT = 1;
12 private static final int STUDENTS = 2;
13
14 // UriMatcher類是一個很重要的類,因為我們需要根據傳入的uri,來判斷執行相對應的操作
15 private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
16
17 // 靜态代碼塊用于初始化MATCHER需要比對的uri
18 static {
19 // MATCHER.addURI(主機名(用于唯一标示一個ContentProvider,這個需要和清單檔案中的authorities屬性相同),路徑(可以用來表示我們要操作的資料,路徑的建構應根據業務而定),傳回值(用于比對uri的時候,作為比對的傳回值));
20 MATCHER.addURI("com.example.mydbdemo.StudentProvider", "student", STUDENTS);
21 MATCHER.addURI("com.example.mydbdemo.StudentProvider", "student/#", STUDENT);
22 }
23
24 // 進行資料的初始化操作
25 @Override
26 public boolean onCreate() {
27 dbHelper = new MyDbOpenHelper(getContext());
28 return false;
29 }
30
31 // 查詢
32 // 如果uri為 content://com.example.mydbdemo.StudentProvider/student
33 // 則代表查詢所有的student表内的資料
34 // 如果uri為 content://com.example.mydbdemo.StudentProvider/student/6
35 // 則代表查詢student表内id=6的資料
36 @Override
37 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
38
39 SQLiteDatabase db = dbHelper.getReadableDatabase();
40 //判斷傳入的uri到底比對哪一個,進而實作不同的業務需求
41 switch (MATCHER.match(uri)) {
42 //查詢全部的學生資訊
43 case STUDENTS:
44 //db.query(表明, 要查詢的列(是一個String數組), where條件, where條件中的參數, groupBy, having, sortOrder);
45 return db.query("student", projection, selection, selectionArgs, null, null, sortOrder);
46 //查詢某一個id對應的學生的資訊
47 case STUDENT:
48 //取出我們要查詢的資料的id
49 long id = ContentUris.parseId(uri);
50 String where = "id=" + id;
51 //将selection查詢資訊拼接到我們的where條件中
52 if (selection != null && !"".equals(selection)) {
53 where = selection + " and " + where;
54 }
55 return db.query("student", projection, where, selectionArgs, null, null, sortOrder);
56 //如uri不比對,抛出不合法參數的異常
57 default:
58 throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
59 }
60
61 }
62
63 // 插入
64 @Override
65 public Uri insert(Uri uri, ContentValues values) {
66 SQLiteDatabase db = dbHelper.getWritableDatabase();
67 switch (MATCHER.match(uri)) {
68 case STUDENTS:
69 long id = db.insert("student", "name", values);
70 return ContentUris.withAppendedId(uri, id);
71 default:
72 throw new IllegalArgumentException("Uri不比對");
73 }
74
75 }
76
77 //删除資料
78 @Override
79 public int delete(Uri uri, String selection, String[] selectionArgs) {
80 SQLiteDatabase db = dbHelper.getWritableDatabase();
81 int count = 0;
82 switch (MATCHER.match(uri)) {
83 case STUDENTS:
84 count = db.delete("student", selection, selectionArgs);
85 return count;
86
87 case STUDENT:
88 long id = ContentUris.parseId(uri);
89 String where = "id=" + id;
90 if (selection != null && !"".equals(selection)) {
91 where = selection + " and " + where;
92 }
93 count = db.delete("student", where, selectionArgs);
94 return count;
95
96 default:
97 throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
98 }
99 }
100
101 //更新資料
102 @Override
103 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
104 SQLiteDatabase db = dbHelper.getWritableDatabase();
105 int count = 0;
106 switch (MATCHER.match(uri)) {
107 case STUDENTS:
108 count = db.update("student", values, selection, selectionArgs);
109 return count;
110
111 case STUDENT:
112 long id = ContentUris.parseId(uri);
113 String where = "id=" + id;
114 if (selection != null && !"".equals(selection)) {
115 where = selection + " and " + where;
116 }
117 count = db.update("student", values, where, selectionArgs);
118 return count;
119
120 default:
121 throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
122 }
123 }
124
125 // 用于擷取MIME Type
126 @Override
127 public String getType(Uri uri) {
128 switch (MATCHER.match(uri)) {
129 case STUDENT:
130 return "vnd.android.cursor.item/student";
131 case STUDENTS:
132 return "vnd.android.cursor.dir/student";
133 default:
134 throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
135 }
136
137 }
138
139 }
我們在定義好我們的ContentProvider之後,因為ContentProvider資料四大元件之一,是以我們還需要在AndroidManifest清單檔案中進行注冊才能使用,下面是注冊資訊
1 <!-- 不要忘記exported這個屬性,如果不加,可能會導緻外部程式通路失敗,錯誤資訊為權限拒絕 -->
2 <!-- authorities這個屬性就是我們在ContentProvider中使用的addURI方法時的第一個參數的取值 -->
3 <provider
4 android:name="com.example.mydbdemo.StudentProvider"
5 android:exported="true"
6 android:authorities="com.example.mydbdemo.StudentProvider" >
7 </provider>
注意,provider的聲明和activity一樣,都是在application節點進行聲明的。
至此,我們就完成了我們自己的ContentProvider的生命,其他的應用現在就可以使用我們往外部暴露的資料資訊了。
3.外部應用如何使用我們的ContentProvider
我們已經定義好了我們自己的ContentProvider,那麼外部應用如何調用呢? 下面,我将建立一個測試單元工程,完成對ContentProvider的各個方法的測試
添加方法測試
1 //使用ContentProvider添加資料的測試
2 public void testadd() throws Throwable {
3 //擷取ContentResolver對象,完成對ContentProvider的調用
4 ContentResolver contentResolver = this.getContext().getContentResolver();
5 //建構我們的uir,這個uri
6 Uri insertUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student");
7 ContentValues values = new ContentValues();
8 values.put("name", "zhaokaikai");
9 values.put("age", 91);
10 values.put("school", "bbbb");
11 //傳回值為我們剛插入進入的資料的uri位址
12 Uri uri = contentResolver.insert(insertUri, values);
13 Log.i(TAG, uri.toString());
14 }
删除方法測試
1 //使用ContentProvider删除資料的測試
2 public void testDelete() throws Throwable {
3 ContentResolver contentResolver = this.getContext().getContentResolver();
4 //删除id為6的學生資訊
5 Uri deleteUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student/6");
6 contentResolver.delete(deleteUri, null, null);
7 }
修改方法測試
1 //使用ContentProvider更新資料的測試
2 public void testUpdate() throws Throwable {
3 ContentResolver contentResolver = this.getContext().getContentResolver();
4 //更新id = 6 的學生資訊
5 Uri updateUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student/6");
6 ContentValues values = new ContentValues();
7 values.put("name", "testUp");
8 values.put("age", "101");
9 values.put("school", "ccccc");
10 contentResolver.update(updateUri, values, null, null);
11 }
查詢
1 //使用ContentProvider查詢資料的測試
2 public void testFind() throws Throwable {
3 ContentResolver contentResolver = this.getContext().getContentResolver();
4 //這個uri用于查詢所有的資料,若查詢某個id的資料,則建構下面的uri
5 //Uri selectUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student/要查詢的id");
6 Uri selectUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student");
7 Cursor cursor = contentResolver.query(selectUri, null, null, null, "id desc");
8 while (cursor.moveToNext()) {
9 int id = cursor.getInt(cursor.getColumnIndex("id"));
10 String name = cursor.getString(cursor.getColumnIndex("name"));
11 int age = cursor.getInt(cursor.getColumnIndex("age"));
12 String school = cursor.getString(cursor.getColumnIndex("school"));
13 Log.i(TAG, "id=" + id + ",name=" + name + ",age=" + age +",school="+school);
14 }
15 }
上面的方法都經過了單元測試。
好了,至此,我們就使用ContentProvider實作了在第三方應用中對我們應用的資料庫進行增删改查等操作,如有疑問,請留言。
轉載自:http://www.it165.net/pro/html/201406/15166.html