Android查缺補漏--ContentProvider的使用

來源:互聯網
上載者:User

標籤:type   應用   one   provider   cte   col   手機   開發   oncreate   

ContentProvider (內容提供者)是一種共用型組件,可以為系統內應用於與應用之間提供提供者。

ContentProvide要想正常工作需要三個關鍵點:

  • ContentProvider:對外提供資料的提供者。
  • Uri:ContentProvider的唯一標識,外界可根據其訪問對應的ContentProvider。
  • ContentResolver

比如,當應用A想把自己資料暴露出來讓別的應用也可以操作的話,就可以在應用A內部建立一個ContentProvider實現相關方法並添加URI,然後在其他應用中(應用B)就可以通過ContentResolver和URI來訪問應用A中的ContentProvider了。

很多人都會覺得ContentProvider很難理解,因為很多書上在介紹ContentProvider是後上來就用很複雜的方式來講解,還結合什麼資料庫、xml等等之類操作,搞得看起來很複雜,讓很多的初學者望而卻步,其實我們完全不必害怕。你可以把ContentProvider看做是一個網站,在生活中你想訪問一個網站就必須要有一個URL地址,而這裡的URI就好比這個URL地址,然後就可以用ContentResolver拿著這個這個URI地址去訪問了。

一、建立自己的ContentProvider
  • 建立ContentProvider。

建立一個自己的ContentProvider也很簡單,同四大組件中其他的組件類似,首先繼承系統ContentProvider來建立一個類,並實現相關方法:

public class UserInfoProvider extends ContentProvider {        static final String TAG = UserInfoProvider.class.getSimpleName();    @Override    public boolean onCreate() {        Log.i(TAG, "onCreate: ");        return false;    }    @Nullable    @Override    public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {        Log.i(TAG, "query: ");        return null;    }    @Nullable    @Override    public String getType(@NonNull Uri uri) {        Log.i(TAG, "getType: ");        return null;    }    @Nullable    @Override    public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {        Log.i(TAG, "insert: ");        return null;    }    @Override    public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) {        Log.i(TAG, "delete: ");        return 0;    }    @Override    public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) {        Log.i(TAG, "update: ");        return 0;    }}

然後再 AndroidMainfest.xml 中註冊並添加 authorities,這個authorities就是傳入到URI中用的,注意要將exported設為true這樣外界才能訪問到。

<provider    android:name=".contentprovides.UserInfoProvider"    android:authorities="cn.codingblock.androidadvancestudy.contentprovides.UserInfoProvider"    android:exported="true" />

一個基本的ContentProvider建立好了,接下來要做的就是使用ContentResolver來訪問它了。

  • 解析Uri

解析Uri使用Uri.parse()來解析,傳入對應的參數,參數格式為:
content://authorities/ 對應於上面的UserInfoProvider來說,一個URI為:

Uri uri = Uri.parse("content://cn.codingblock.androidadvancestudy.contentprovides.UserInfoProvider/");
  • 通過Context.getContentResolver()擷取ContentResolver對象。

    ContentResolver contentResolver = getContentResolver();

    我們另外建立一個工程,暫且叫做TestApp吧,在這個新的工程裡面添加一個Activity,在Activity中使用ContentResolver,通過URI來訪問上面的(不同應用中)ContentProvider。

public class UserInfoResolverActivity extends AppCompatActivity implements View.OnClickListener {    private final static String TAG = UserInfoResolverActivity.class.getSimpleName();    private ContentResolver contentResolver;    private Uri uri = Uri.parse("content://cn.codingblock.androidadvancestudy.contentprovides.UserInfoProvider/");    Button btn_insert;    Button btn_query;    Button btn_update;    Button btn_delete;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_user_info_resolver);        // 擷取ContentResolver對象        contentResolver = getContentResolver();        btn_insert = (Button) findViewById(R.id.btn_insert);        btn_query = (Button) findViewById(R.id.btn_query);        btn_update = (Button) findViewById(R.id.btn_update);        btn_delete = (Button) findViewById(R.id.btn_delete);        btn_insert.setOnClickListener(this);        btn_query.setOnClickListener(this);        btn_update.setOnClickListener(this);        btn_delete.setOnClickListener(this);    }    @Override    public void onClick(View view) {        switch (view.getId()) {            case R.id.btn_insert:                insert();                break;            case R.id.btn_query:                query();                break;            case R.id.btn_update:                update();                break;            case R.id.btn_delete:                delete();                break;        }    }    public void insert() {        Uri tempUri = contentResolver.insert(uri, values);        Log.i(TAG, "insert: tempUri = " + tempUri);    }    public void query() {        Cursor cursor = contentResolver.query(uri, null, "where", null, null);        Log.i(TAG, "query: cursor = " + cursor);    }    public void update() {        int n = contentResolver.update(uri, values, "where", null);        Log.i(TAG, "update: n = " + n);    }    public void delete() {        int n = contentResolver.delete(uri, "where", null);        Log.i(TAG, "delete: n = " + n);    }}

需要注意一點是,這個UserInfoProvider和UserInfoResolverActivity並沒有在同一個應用中,UserInfoProvider在AndroidAdvanceStudy這個應用裡面,他的進程名是:cn.codingblock.androidadvancestudy。UserInfoResolverActivity在TestApp應用裡面,進程名是:cn.codingblock.testapp。

在testApp點擊以上的增、查、改、刪按鈕,log如下:

12-12 15:06:26.846 28104-28118/cn.codingblock.androidadvancestudy I/UserInfoProvider: insert: 12-12 15:06:28.070 28104-28118/cn.codingblock.androidadvancestudy I/UserInfoProvider: query: 12-12 15:06:29.733 28104-28118/cn.codingblock.androidadvancestudy I/UserInfoProvider: update: 12-12 15:06:30.376 28104-28118/cn.codingblock.androidadvancestudy I/UserInfoProvider: delete: 

看,我們是在TestApp應用中做的相關操作,果然可以調用AndroidAdvanceStudy裡面的UserInfoProvider。

ContenProvider就是這麼簡單,當然 ContentProvider 的功能遠不止如此,我們也可以結合資料庫或者SharePreference等實現更加複雜的對外資料操作。

二、調用系統的ContentProvider

除了我們自己建立ContentProvider,Android系統也給我們提供了豐富的ContentProvider介面,這裡就以作業系統的連絡人為例來說明一下怎使用系統提供的ContentProvider介面。

  • ContactsContract.Contacts.CONTENT_URI:連絡人Uri。
  • ContactsContract.CommonDataKinds.Phone.CONTENT_URI:連絡人電話號碼Uri。

1、查詢系統連絡人

通過系統連絡人的Uri擷取系統連絡人及手機號碼:

public void query() {    showContact = "";    // 擷取連絡人的Cursor集合    Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);    while (cursor.moveToNext()) {        // 擷取連絡人id        String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));        // 擷取連絡人姓名        String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));        // 擷取當前連絡人id下的所有電話號碼        Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,                null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + id, null, null);        showContact += "--id="+ id + " | name=" + name + "--\n";        Log.i(TAG, "onCreate: ------id="+ id + " | name=" + name + "------");        while (phones.moveToNext()) {            String phone = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));            showContact += "phone = " + phone + "\n";            Log.i(TAG, "onCreate: phone = " + phone);        }        phones.close();    }    cursor.close();    tv_show.setText(showContact);}

查詢後log如下:

12-13 17:19:49.490 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: ------id=1 | name=張飛------12-13 17:19:49.490 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 151 1511 151112-13 17:19:49.499 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: ------id=2 | name=關羽------12-13 17:19:49.499 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 153 6969 386912-13 17:19:49.499 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 135 6497 866412-13 17:19:49.499 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 155 5555 555512-13 17:19:49.499 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 133 3333 333312-13 17:19:49.508 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: ------id=3 | name=劉備------12-13 17:19:49.508 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 156 9637 564812-13 17:19:49.508 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 153 7564 864312-13 17:19:49.520 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: ------id=14 | name=呂布------12-13 17:19:49.520 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 1567890908712-13 17:19:49.529 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: ------id=20 | name=孫權------12-13 17:19:49.529 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 1536666999912-13 17:19:49.538 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: ------id=21 | name=曹操------12-13 17:19:49.538 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 1569978896612-13 17:19:49.547 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: ------id=22 | name=馬超------12-13 17:19:49.547 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 15366999966

2、添加系統連絡人:

public void insert() {    String name = et_name.getText().toString();    String phone = et_phone.getText().toString();    if (TextUtils.isEmpty(name) || TextUtils.isEmpty(phone)) {        Toast.makeText(getApplicationContext(), "不可為空", Toast.LENGTH_LONG).show();        return;    }    ContentValues values = new ContentValues();    // 往插入一個空值以便擷取id    Uri rawContactUri = getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI, values);    long rawContactId = ContentUris.parseId(rawContactUri);    // ------插入連絡人姓名------    // 設定id    values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);    // 設定內容類型    values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);    // 設定名字    values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, name);    // 插入姓名    getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);    values.clear();    // ------插入連絡人電話------    values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);    values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);    values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone);    values.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);    getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);    Toast.makeText(getApplicationContext(), "添加成功", Toast.LENGTH_LONG).show();    query();}

在輸入框中輸入連絡人姓名(諸葛亮)及電話號碼(13696969696),然後點擊添加按鈕,log如下:

12-13 17:23:37.577 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: ------id=1 | name=張飛------12-13 17:23:37.577 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 151 1511 151112-13 17:23:37.589 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: ------id=2 | name=關羽------12-13 17:23:37.590 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 153 6969 386912-13 17:23:37.590 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 135 6497 866412-13 17:23:37.590 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 155 5555 555512-13 17:23:37.590 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 133 3333 333312-13 17:23:37.603 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: ------id=3 | name=劉備------12-13 17:23:37.603 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 156 9637 564812-13 17:23:37.603 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 153 7564 864312-13 17:23:37.616 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: ------id=14 | name=呂布------12-13 17:23:37.617 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 1567890908712-13 17:23:37.630 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: ------id=20 | name=孫權------12-13 17:23:37.630 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 1536666999912-13 17:23:37.657 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: ------id=21 | name=曹操------12-13 17:23:37.657 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 1569978896612-13 17:23:37.671 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: ------id=22 | name=馬超------12-13 17:23:37.671 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 1536699996612-13 17:23:37.712 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: ------id=23 | name=諸葛亮------12-13 17:23:37.712 14978-14978/cn.codingblock.androidadvancestudy I/ContactProviderActivity: onCreate: phone = 13696969696

可以看到,諸葛亮和電話號碼已經被成功添加進去了。

當然,除了以上幾個Uri,系統的ContentProvider介面還有很多很多,就不一一舉例了,用到時可以查詢官方API。

最後想說的是,本系列文章為博主對Android知識進行再次梳理,查缺補漏的學習過程,一方面是對自己遺忘的東西加以複習重新掌握,另一方面相信在重新學習的過程中定會有巨大的新收穫,如果你也有跟我同樣的想法,不妨關注我一起學習,互相探討,共同進步!

參考文獻:

  • 《Android開發藝術探索》
  • 《Android開發進階從小工到專家》

Android查缺補漏--ContentProvider的使用

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.