Android中內容提供者ContentProvider的詳解


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM