安卓儲存資料和檔案系列4:內容提供者(Content Provider)方式
阿新 • • 發佈:2019-02-14
內容提供者(Content Provider)是android的四大元件之一,重要性可想而知,一個程序的資料可以被另外一個程序訪問(在不同的apk之間可以訪問),內容提供者可以跨應用,資料庫跨應用的使用場景:一個應用中提供資料給其他應用;允許使用者從一個應用中拷貝資料到另一個應用;在整個框架中提供一種自定義的查詢建議。如果只在一個應用中使用資料的話使用SQLite,不需要使用Content Provider。
整體思路:建立一個繼承SQLiteOpenHelper的DbHelper類,在這個類中宣告資料庫名稱和版本號碼,在onCreate方法中寫建立表的sql語句並執行,onUpgrade方法中暫時不做任何操作(目前不涉及升級資料庫的操作)。建立一個繼承ContentProvider的StudentProvider類,在這個類中定義一個預設不匹配的UriMatcher物件,宣告兩個標誌位,宣告一個靜態程式碼塊,在這個程式碼塊中定義兩個匹配規則,定義一個getType方法,在這個方法中根據不同的標記返回不同的型別,在這個類中定義增刪改查操作對應的方法,在這些方法中根據不同的標記來執行單條記錄和多條記錄的操作。建立一個繼承AndroidTestCase的MyTest單元測試類,在這個類中定義增刪改查方法,在這些方法中定義一個內容解析者,使用內容解析者呼叫操作資料庫的方法。注意:在清單檔案AndroidManifest.xml檔案中註冊內容提供者和註冊測試單元。建立另一個工程,在這個工程中將MyTest類複製過來,執行裡面的各個方式進行測試。這樣就完成了從一個工程向另一個工程中訪問資料的操作。
DbHelper.java檔案:
StudentProvider.java檔案:public class DbHelper extends SQLiteOpenHelper { private static String name="mydb.db"; private static int version=1;//初始的版本號是1 public DbHelper(Context context) { super(context, name, null, version); // TODO Auto-generated constructor stub } @Override public void onCreate(SQLiteDatabase database) { // TODO Auto-generated method stub String sql="create table student (id integer primary key autoincrement ,name varchar(64),address varchar(64))"; database.execSQL(sql);//對資料庫表的建立 } @Override public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) { // TODO Auto-generated method stub } }
MyTest.java檔案://ContentProvider是一個抽象類,需要宣告一個類去繼承它,分別去重寫增刪改查的方法 public class StudentProvider extends ContentProvider { private final String TAG = "StudentProvider"; private DbHelper helper = null; // 預設是不匹配 private static final UriMatcher URI_MATCHER = new UriMatcher( UriMatcher.NO_MATCH); // 宣告兩個標誌位 private static final int STUDENT = 1;// 表示操作單條記錄 private static final int STUDENTS = 2;// 表示操作多條記錄 // 宣告一個靜態的程式碼模組 static { // 定義了兩個匹配規則 URI_MATCHER.addURI( "com.example.android_contentprovider.StudentProvider", "student", STUDENTS); URI_MATCHER.addURI( "com.example.android_contentprovider.StudentProvider", "student/#", STUDENT); } public StudentProvider() { // TODO Auto-generated constructor stub } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // TODO Auto-generated method stub int count = -1;// 表示影響資料庫的行數 try { int flag = URI_MATCHER.match(uri); SQLiteDatabase database = helper.getWritableDatabase(); switch (flag) { case STUDENT:// 單條記錄 // delete from student where id=? id是通過客戶端傳遞過來的 long id = ContentUris.parseId(uri); String where_value = "id=" + id; if (selection != null && !selection.equals("")) { where_value += " and " + selection; } count = database.delete("student", where_value, selectionArgs); break; case STUDENTS:// 多條記錄 count = database.delete("student", selection, selectionArgs); break; } } catch (Exception e) { // TODO: handle exception } return count; } @Override public String getType(Uri uri) { // TODO Auto-generated method stub int flag = URI_MATCHER.match(uri); switch (flag) { case STUDENT: return "vnd.android.cursor.item/student"; case STUDENTS: return "vnd.android.cursor.dir/students"; } return null; } @Override public Uri insert(Uri uri, ContentValues values) { // TODO Auto-generated method stub // insert into student() (?,?); Uri resultUri = null; int flag = URI_MATCHER.match(uri);// 外部傳遞進來的uri來匹配內部的規則 switch (flag) { case STUDENTS: SQLiteDatabase database = helper.getWritableDatabase(); // 返回插入當前行的行號 long id = database.insert("student", null, values); resultUri = ContentUris.withAppendedId(uri, id); break; } Log.i(TAG, "-->>" + resultUri.toString()); return resultUri; } @Override public boolean onCreate() { // TODO Auto-generated method stub helper = new DbHelper(getContext()); return false; } @Override public Cursor query(Uri uri, String[] arg1, String selection, String[] selectionArgs, String arg4) { // TODO Auto-generated method stub Cursor cursor = null; try { SQLiteDatabase database = helper.getReadableDatabase(); int flag = URI_MATCHER.match(uri);// 匹配路徑 switch (flag) { case STUDENT:// 查詢返回單條記錄 long id = ContentUris.parseId(uri); String where_value = " id = " + id; if (selection != null && !selection.equals("")) { where_value += " and " + selection; } cursor = database.query("student", null, where_value, selectionArgs, null, null, null, null); break; case STUDENTS:// 查詢返回多條記錄 cursor = database.query("student", null, selection, selectionArgs, null, null, null, null); break; } } catch (Exception e) { // TODO: handle exception } return cursor; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // TODO Auto-generated method stub int count = -1; try { // update table set name= ?,address= ? where id = ? SQLiteDatabase database = helper.getWritableDatabase(); long id = ContentUris.parseId(uri); int flag = URI_MATCHER.match(uri); switch (flag) { case STUDENT: String where_value = " id= " + id; if (selection != null && !selection.equals("")) { where_value += " and " + selection; } count = database.update("student", values, where_value, selectionArgs); break; } } catch (Exception e) { // TODO: handle exception } return count; } }
public class MyTest extends AndroidTestCase {
public MyTest() {
// TODO Auto-generated constructor stub
}
public void insert(){
// 訪問內容提供者的步驟:
// 1.需要一個內容解析者
ContentResolver contentResolver=getContext().getContentResolver();
// 使用content://+授權路徑 來訪問一個內容提供者
Uri url=Uri.parse("content://com.example.android_contentprovider.StudentProvider/student");
ContentValues values=new ContentValues();
values.put("name", "吳孟達");
values.put("address", "香港");
contentResolver.insert(url, values);
}
public void delete(){
// 內容解析者
ContentResolver contentResolver=getContext().getContentResolver();
// 刪除第一條記錄,在後面需要加/1
// 刪除多條記錄,後面不加任何東西
Uri url=Uri.parse("content://com.example.android_contentprovider.StudentProvider/student/1");
contentResolver.delete(url, null, null);
}
public void update(){
// 得到一個內容解析者
ContentResolver contentResolver=getContext().getContentResolver();
Uri uri=Uri.parse("content://com.example.android_contentprovider.StudentProvider/student/2");
ContentValues values=new ContentValues();
values.put("name", "美人魚");
values.put("address", "香港");
contentResolver.update(uri, values, null, null);
}
public void query(){
ContentResolver contentResolver=getContext().getContentResolver();
// 查詢單條記錄(查詢id為2的那條記錄):content://com.example.android_contentprovider.StudentProvider/student/2
// 查詢多條記錄:content://com.example.android_contentprovider.StudentProvider/student
// Uri uri=Uri.parse("content://com.example.android_contentprovider.StudentProvider/student/2");
Uri uri=Uri.parse("content://com.example.android_contentprovider.StudentProvider/student");
// 相當於這樣的sql語句:select * from student where id =2;
Cursor cursor=contentResolver.query(uri, null, null, null, null);
while (cursor.moveToNext()) {
System.out.println("-->>"+cursor.getString(cursor.getColumnIndex("name"))+" "+cursor.getString(cursor.getColumnIndex("address")));
}
}
}
AndroidManifest.xml檔案:
<instrumentation android:targetPackage="com.example.android_contentprovider" android:name="android.test.InstrumentationTestRunner"></instrumentation>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<uses-library android:name="android.test.runner"/>
<activity
android:name="com.example.android_contentprovider.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 定義了一個內容提供者 authorities是授權:包名加類名 android:exported="true"-->
<provider
android:exported="true"
android:name=".StudentProvider" android:authorities="com.example.android_contentprovider.StudentProvider"
></provider>
</application>