1. 程式人生 > >使用 自定義的 ContentProvider 進行應用間的資料互動(另一個APP對當前的應用資料進行修改,查詢),getType()等內容的講解

使用 自定義的 ContentProvider 進行應用間的資料互動(另一個APP對當前的應用資料進行修改,查詢),getType()等內容的講解

本部落格內容

應用B 對 應用A的資料庫資料進行插入和查詢(其他操作簡略不寫)

bookProject 應用A

看一下目錄結構

在這裡插入圖片描述

Book_TABLE.java

  • 關鍵點:private static final String BOOK_DB = "create table Book(id integer primary key autoincrement ,author text) ";
  • 這裡面的 id 必須寫
Book_TABLE extends SQLiteOpenHelper
// 建立表 此處內容省略

MainActivity.java

... //此處內容省略,新增一些資料到資料庫就OK

MyProvider.java 程式碼中有註釋。此程式碼部分結束後還有解釋

public class MyProvider extends ContentProvider {

    public static final int BOOK_TABLE_DIR = 0;        // 判斷 另一個應用的行為 是查詢全部資料
    public static final int BOOK_TABLE_ITEM = 1;    //// 判斷 另一個應用的行為 是查詢單條

    private static UriMatcher uriMatcher;              // 進行 匹配工作 的類工具

// 靜態程式碼塊 
    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI("com.example.tnt.bookproject", "Book", BOOK_TABLE_DIR); // 要匹配 book 下所有的資料 == table1/*
        uriMatcher.addURI("com.example.tnt.bookproject", "Book/#", BOOK_TABLE_ITEM); // 要匹配 book 下任意一行的資料
    }

    private Book_TABLE book_table;
    private SQLiteDatabase db;

    // 初始化 內容提供器時啟動, true 表示成功 false 表示失敗 。
    @Override
    public boolean onCreate() {
        book_table = new Book_TABLE(getContext());
        db = book_table.getWritableDatabase();
        return true;
    }


    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        Cursor cursor = null;
        switch (uriMatcher.match(uri)) {
            case BOOK_TABLE_DIR:
                // 查詢 table1 下所有資料
                cursor = db.query("Book", projection, selection, selectionArgs, null, null, sortOrder);
                break;
            case BOOK_TABLE_ITEM:
                //查詢 table1 下某條資料
                String book_ID = uri.getPathSegments().get(1); // 將許可權之後的內容部分已 “/” 進行分割,0位置放 路徑 ,1 位置放 id 了
                cursor = db.query("Book", projection, "id=?", new String[]{book_ID}, null, null, sortOrder);
                break;
            default:
                break;
        }
        return cursor;
    }

  // 所有內容提供器都必須提供的方法,用於獲取 Uri 物件對應的 MIME 型別。怎麼寫,下面是示例,此程式碼部分結束後,有講解
    @Override
    public String getType(Uri uri) {
        switch (uriMatcher.match(uri)) {
            case BOOK_TABLE_DIR:
                return "vnd.android.cursor.dir/vnd.com.example.tnt.bookproject.Book";
            case BOOK_TABLE_ITEM:
                return "vnd.android.cursor.item/vnd.com.example.tnt.bookproject.Book";
        }
        return null;
    }


    // 插入成功後需返回一個 Uri 用於提示插入的 位置
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        Uri newUri;
        long newId =  db.insert("Book",null,values);
        newUri = Uri.parse("content://com.example.tnt.bookproject/Book/"+newId);
        return newUri;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
}

關於 MyProvider 的內容講解

  • getPathSegments() 方法 // 將 內容URI 許可權之後的內容部分以 “/” 進行分割,放入一個數組裡,0位置放 路徑 ,1 位置放 id 了,在通過 selection 和 selectionArgs 引數進行約束就實現了查詢單條資料功能
  • Uri.parse() 方法將 內容URI 解析成 Uri 物件
  • 務必實現 getType()裡的操作 實現方法
一個內容 URI 對應的 MIME 字串主要有 3 部分組成。Android 對著 3 部分做了如下格式規定。
 1. 必須以 vnd 開頭
 2. 如果內容 URI 以 路徑結尾,則接 android.cursor.dir/ ,如果以 id 結尾,則接 andriod.cursor.item/ 
 3. 最後 接上 vnd.<authority>.path
 -  所以對於 content://com.example.tnt.bookproject/Book  這個內容URI,它所對應的 MIME 型別 就可以寫成:
    vnd.android.cursor.dir/vnd.com.example.tnt.bookproject.Book 
 - 所以對於 content://com.example.tnt.bookproject/Book/1  這個內容URI,它所對應的 MIME 型別 就可以寫成:
    vnd.android.cursor.item/vnd.com.example.tnt.bookproject.Book 

註冊 AndroidManifest.xml

android:enabled //啟用此內容提供器 android:exported=“true” // 外部應用可以使用此內容提供器

       <provider
            android:enabled="true"    
            android:exported="true"
            android:authorities="com.example.tnt.bookproject"
            android:name=".MyProvider"/>

OperatorProject 應用B (來操作 bookProject 的內容)

MainActivity.java (只實現了 插入和 查詢操作)

   public void insertInfo(View view) {
        // 新增資料
        Uri uri = Uri.parse("content://com.example.tnt.bookproject/Book");
        
        ContentValues cv = new ContentValues();
        cv.put("author", "諸葛亮");
        
        Uri newUri = getContentResolver().insert(uri, cv); // ContentResolver 我理解的就是 ContentProvider 的應用之間溝通的橋樑
        String newID = newUri.getPathSegments().get(1);  // 獲取插入資料後,表 生成的 id 位置。// 在定義表 Book 時,id 設定成了 自增
        
        Log.i(TAG, "insertInfo: " + newID);
    }

    public void queryInfo(View view) {
        // 查詢資料
        Uri uri = Uri.parse("content://com.example.tnt.bookproject/Book");
        Cursor cursor = getContentResolver().query(uri, null, null, null, null);
        if (cursor != null) {
            while (cursor.moveToNext()) {
                Log.i(TAG, "queryInfo:查到的作者 " + cursor.getString(cursor.getColumnIndex("author")));
                Log.i(TAG, "queryInfo: 作者ID " + cursor.getString(cursor.getColumnIndex("id")));
            }
            cursor.close();
        }
    }