Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android組件----內容提供器Content Provider

Android組件----內容提供器Content Provider

編輯:關於Android編程

內容提供器(Content Provider)主要用於在不同的應用程序之間共享數據,雖然Android提供的文件存儲和SharePreferences都可以設置全局讀寫模式共享數據,但由於安全性問題,已經在Android4.2中被廢棄。內容提供器將提供一種安全的數據共享方式。當一個程序通過內容提供器提供了外部訪問接口,其他任何程序都可以通過該接口來對這部分數據進行訪問,例如:聯系人數據,短信數據。


一、訪問其他應用程序中的數據

1 . 獲得ContentResolver類的實例

對於每一個應用程序,如果想要訪問內容提供器中的數據,就必須要借助於ContentResolver類,可以通過Context中的getContentResolver()放法獲得該類的實例。

ContentResolver類中提供了類似於SQLite中類似的insert()、delete()、update()、query()等方法實現對數據的增刪改查,但是參數與SQLite中的參數略有不同。

注:ContentResolver中的增刪改查方法都是不接受表名參數的,而是使用Uri參數代替,這個參數被稱為內容URI。

2 . 獲得內容URI

內容URI給內容提供器中的參數建立了唯一標識符,它主要由權限路徑兩部分組成,權限主要是為了區分不同的應用程序,一般使用程序包名。比如:com.example.app.provider。路徑則是對同一應用程序中不同的表進行區分,以/+表名的方式接在權限的後面。最後我餓還需要加上協議聲明才組成了完整的內容URI。

內容URI標准格式

content://com.example.app.provider/table1

content://com.example.app.provider/table2

3 . 將URI字符串解析為Uri對象

Uri uri = Uri.parse("content://com.example.app.provider/table1");

4 . 對數據進行增刪改查

//插入數據
ContentValues values1 = new ContentValues();
values1.put("column1", "text1");
values1.put("column2", "text2");
getContentResolver().insert(uri, values1);

//刪除數據
getContentResolver().delete(uri, "cloumn2=?", new String[]{"1"});

//修改數據
ContentValues values2 = new ContentValues();
values2.put("column1", "t");
getContentResolver().update(uri, values2, "column1 = ? and column2=?", new String[]{"text", "1"});

//查詢數據
Cursor cursor = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
if (cursor != null){
    while (cursor.moveToNext()){
        String column1 = cursor.getString(cursor.getColumnIndex("column1"));
        int column2 = cursor.getInt(cursor.getColumnIndex("column2"));
    }
    cursor.close();
}

上面的操作和SQLite的操作十分類似,只是傳入的參數不再是表名,而是解析出來的Uri對象。


下面重點介紹query()中各參數的意義

query方法參數 對應SQL部分 描述 uri from table_name 指定要查詢的應用程序下的某一張表 projection select column1,column2 指定查詢的列名 selection where column=value 指定where的約束條件 selectionArgs - 為where中的占位符提供具體的值 orderBy order by column1,column2 指定查詢結果的排序方式

下面放上一個獲取聯系人信息的小例子

MainActivity.java中的代碼
public class MainActivity extends AppCompatActivity {
    private ListView contactsView;
    private ArrayAdapter adapter;
    private List contactsList = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        contactsView = (ListView) findViewById(R.id.contacts_view);
        adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, contactsList);
        contactsView.setAdapter(adapter);
        readContacts();

    }

    private void readContacts() {
        Cursor cursor = null;
        try{
            //查詢聯系人數據
            cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
            while(cursor.moveToNext()){
                //獲取聯系人姓名
                String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                //獲取聯系人手機號
                String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                contactsList.add(displayName + "\n" + number);
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (cursor != null){
                cursor.close();
            }
        }
    }
}
activity_main.xml文件



    

上面的代碼中的Uri對象並不是通過parse()方法解析,是因為官方向我們直接提供了解析好的Uri對象。我們獲取到手機聯系人姓名和電話號碼後簡單地顯示在了ListView中。


二、創建自己的內容提供器

上面我們使用別人提供的內容提供器來獲取其他程序共享的數據,下面我們將創建自己的內容提供器來共享自己應用程序中的數據。下面是基本的步驟

1 . 創建一個類去繼承ContentProvider,重寫其中的6個抽象方法。

下面簡單介紹這6個方法(與SQLite中的方法很類似)

1 . onCreate() ——- 初始化內容提供器的時候調用。通常在這裡完成數據庫的額創建或升級等操作。返回true表示內容提供器初始化成功,返回false表示失敗。

注:只有當有ContentResolver嘗試訪問我們程序中的數據時,內容提供器才會被初始化。

2 . query() —–從內容提供器中來查詢數據,query方法的參數已經在上面的表格中做了詳細說明。

3 . insert() —– 向內容提供器中添加一條數據,使用方法咋在上面的代碼中已經有介紹。

4 . update() —– 更新內容提供器中已有的數據。

5 . delete() —– 從內容提供器中刪除數據

6 . getType() —– 根據傳入的URI來返回響應的MIME類型。

2 . 分析內容URI。

標准的內容URI(以路徑結尾,表示期望訪問表中的所有數據):

content://com.example.app.provider/table

含有id的內容URI(以id結尾,表示訪問表中擁有相應id的數據):

content://com.example.app.provider/table/1

為了下一步准確解析這兩種內容URI,我們還必須使用通配符來匹配上面兩種模式。

1 . * ——- 表示匹配任意長度的任意字符
2 . # ——- 表示匹配任意長度的數字

//匹配上面第一行內容URI(所有數據)
content://com.example.app.provider/table/*

//匹配上面第二種URI(相應id的數據)
content://com.example.app.provider/table/#

3 . 借助於UriMatcher類實現匹配內容URI。

上面我們已經分析了內容URI,接下來我們借助於UriMatcher類提供的addURI()方法,分別依次傳入三個參數(權限、路徑,自定義代碼(標識))。最後我們再調用UriMatcher的match()方法,傳入一個Uri對象,就會返回我們剛剛傳入的自定義代碼(標識),我們以此來判斷調用方想訪問數據的意圖。

public class MyProvider extends ContentProvider {
  //自定義代碼
  public static final int TABLE1_DIR = 0;
  public static final int TABLE1_ITEM = 1;

  private static UriMatcher uriMatcher;
  static {
      uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
      //期望查詢所有數據
      uriMatcher.addURI("com.example.app.provider", "table1", TABLE1_DIR);
      //期望查詢相應id的數據
      uriMatcher.addURI("com.example.app.provider", "table1/#", TABLE1_ITEM);
  }

  @Nullable
  @Override
  public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
      switch (uriMatcher.match(uri)){
          case TABLE1_DIR:
              //查詢所有數據
              break;
          case TABLE1_ITEM:
              //查詢單條數據
              break;
          default:
              break;
      }
      return null;
  }
}

上面的代碼只是簡單演示了在query()方法中的重寫,對於insert()、update()、delete()中的重寫都是類似的,都是從Uri對象中獲得自定義代碼,得到訪問數據者的意圖後寫相應的邏輯。

4 . 重寫getType()方法。

getType()方法是所有內容提供器都必須提供的一個方法,用於獲取Uri對象所對應的MIME類型,一個內容URI所對應的MIME類型字符串有三部分組成。Android做了如下規定:

1 . 必須以vnd開頭

2 . 如果內容URI以路徑結尾,則後面接android.cursor.dir/,如果內容URI以id結尾,則後接android.cursor.item/

3 . 最後接vnd.<權限>.<路徑>

//內容URI以路徑結尾
vnd.android.cursor.dir/vnd.com.example.app.provider.table1

//內容URI以id結尾
vnd.android.cursor.item/vnd.com.example.app.provider.table1
@Nullable
@Override
public String getType(Uri uri) {
    switch (uriMatcher.match(uri)){
        case TABLE1_DIR:
            return "vnd.android.cursor.dir/vnd.com.example.app.provider.table1";
        case TABLE1_ITEM:
            return "vnd.android.cursor.item/vnd.com.example.app.provider.table1";
    }
    return null;
}

從上面的內容我們也會發現,內容提供器之所以可以保證數據的安全性,是因為要想對數據進行增刪改查,我們都首先需要匹配到內容URI格式才可以,只要我們不把隱私數據添加進UriMatcher中,我們的隱私數據就不會被訪問到。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved