<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ContentProvider 使用詳解

          共 19789字,需瀏覽 40分鐘

           ·

          2020-09-27 04:10

          和你一起終身學習,這里是程序員Android

          經(jīng)典好文推薦,通過閱讀本文,您將收獲以下知識點:

          一、ContentProvider 概述
          二、ContentProvider的注冊
          三、自定義ContentProvider 的實現(xiàn)
          四、獲取聯(lián)系人ContactProvider實現(xiàn)的方法
          五、獲取短信內(nèi)容的實現(xiàn)方法
          六、ContentResolver 內(nèi)容解析者
          七、ContentObserver 內(nèi)容觀察者
          八、ContentProvider ContentResolver ContentObserver 三者關(guān)系

          一、ContentProvider 概述

          在了解 ContentProvider 之前,我們首先了解一下ContentProvider 的繼承關(guān)系。

          ContentProvider 繼承關(guān)系如下:

          java.lang.Object
          ? android.content.ContentProvider

          ContentProviderAndroid四大組件之一,其本質(zhì)上是一個標準化的數(shù)據(jù)管道,它屏蔽了底層的數(shù)據(jù)管理和服務等細節(jié),以標準化的方式在Android 應用間共享數(shù)據(jù)。用戶可以靈活實現(xiàn)ContentProvider所封裝的數(shù)據(jù)存儲以及增刪改查等,所有的ContentProvider 必須實現(xiàn)一個對外統(tǒng)一的接口(URI)。

          二、ContentProvider的注冊

          ContentProvider 屬于四大組件之一,必須在Androidmainfest.xml 中注冊。

          ContentProvider注冊方法如下:

            <provider           
          android:name="com.programandroid.CustomContentProviderMethod"
          android:authorities="ProgramAndroid"
          android:exported="true" />

          注意 :
          URI 中的元素是android:authorities="ProgramAndroid"。

          三、自定義ContentProvider 的實現(xiàn)

          自定義ContentProvider 需要繼承 ContentProvider ,并實現(xiàn)增刪改查等方法。

          1.自定義ContentProvider 類

          public class CustomContentProviderMethod extends ContentProvider {

          private SQLiteDatabase db;
          private static final String MAUTHORITIESNAME = "ProgramAndroid";
          private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
          private static final int PERSON = 1;
          private static final int PERSON_NUMBER = 2;
          private static final int PERSON_TEXT = 3;
          private static final String TABLE_NAME = "table_person";
          // 構(gòu)建URI
          static {
          // content://programandroid/person
          matcher.addURI(MAUTHORITIESNAME, "person", PERSON);
          // # 代表任意數(shù)字content://programandroid/person/4
          matcher.addURI(MAUTHORITIESNAME, "person/#", PERSON_NUMBER);
          // * 代表任意文本 content://programandroid/person/filter/ssstring
          matcher.addURI(MAUTHORITIESNAME, "person/filter/*", PERSON_TEXT);
          }

          @Override
          public boolean onCreate() {
          DBHelper helper = new DBHelper(getContext());
          // 創(chuàng)建數(shù)據(jù)庫
          db = helper.getWritableDatabase();
          return true;

          }

          @Nullable
          @Override
          public Cursor query(Uri uri, String[] projection, String selection,
          String[] selectionArgs, String sortOrder) {

          // 過濾URI
          int match = matcher.match(uri);
          switch (match) {
          case PERSON:
          // content://autoname/person

          return db.query(TABLE_NAME, projection, selection, selectionArgs,
          null, null, sortOrder);

          case PERSON_NUMBER:
          break;
          case PERSON_TEXT:
          break;
          default:
          break;
          }
          return null;
          }

          @Nullable
          @Override
          public Uri insert(Uri uri, ContentValues values) {
          // 過濾URI
          int match = matcher.match(uri);
          switch (match) {
          case PERSON:
          // content://autoname/person

          long id = db.insert(TABLE_NAME, null, values);

          // 將原有的uri跟id進行拼接從而獲取新的uri
          return ContentUris.withAppendedId(uri, id);

          case PERSON_NUMBER:
          break;
          case PERSON_TEXT:
          break;
          default:
          break;
          }
          return null;
          }

          @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;
          }

          @Nullable
          @Override
          public String getType(Uri uri) {
          return null;
          }

          }

          2. 提供對外提供操作的數(shù)據(jù)庫方法

          public class DBHelper extends SQLiteOpenHelper {
          private static final String DB_NAME = "persons.db";
          private static final int DB_VERSION = 1;
          private static final String TABLE_NAME = "table_person";
          private static final String ID = "_id";
          private static final String NAME = "name";

          public DBHelper(Context context) {
          super(context, DB_NAME, null, DB_VERSION);
          }

          @Override
          public void onCreate(SQLiteDatabase db) {

          String sql = "CREATE TABLE " + TABLE_NAME + "(" + ID
          + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL" + "," + NAME
          + " CHAR(10) )";

          db.execSQL(sql);
          }

          @Override
          public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

          }

          }

          3.其他APK 訪問此ContentProvider 數(shù)據(jù)庫的方法

          public class MainActivity extends Activity {

          private String uri = "content://ProgramAndroid/person";
          private EditText mEditText;

          @Override
          protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          mEditText = (EditText) findViewById(R.id.ed_name);
          }

          public void QureyData(View view) {
          String name = null;
          Cursor cursor = getContentResolver().query(Uri.parse(uri), null, null, null, null);
          while (cursor.moveToNext()) {
          name = cursor.getString(cursor.getColumnIndex("name"));
          }
          mEditText.setText(name);
          }

          public void InsertData(View view) {
          String editName = mEditText.getText().toString();
          ContentValues values = new ContentValues();
          values.put("name, editName);

          Uri result = getContentResolver().insert(Uri.parse(uri), values);
          // 注意 :此條添加上才ContentObserver可以監(jiān)聽數(shù)據(jù)庫改變
          getContentResolver().notifyChange(Uri.parse(uri),null);
          long parseid = ContentUris.parseId(result);
          if (parseid > 0) {
          Toast.makeText(MainActivity.this, "
          保存成功", Toast.LENGTH_LONG).show();
          mEditText.setText("
          ");
          }

          }

          }

          注意 :

             //  此條添加上才ContentObserver可以監(jiān)聽數(shù)據(jù)庫改變
          getContentResolver().notifyChange(Uri.parse(uri),null);

          至此,自定義ContentProvider的使用方法已經(jīng)實現(xiàn)。

          四、獲取聯(lián)系人ContactProvider實現(xiàn)的方法

          Android 系統(tǒng)自帶一些ContentProvider ,比如 聯(lián)系人的ContactProvider
          例如:源碼packages\providers 下的內(nèi)容

          Android 系統(tǒng)Provider

          1. 獲取聯(lián)系人實現(xiàn)方法

          public class ContactListActivity extends Activity {
          private static final String tag = "ContactListActivity";
          private ListView lv_contact_list;
          private List<HashMap<String, String>> mContactList = new ArrayList<HashMap<String, String>>();

          private Handler mHandler = new Handler() {
          public void handleMessage(android.os.Message msg) {
          // 給數(shù)據(jù)適配器設(shè)置數(shù)據(jù)
          MyAdapter myAdapter = new MyAdapter();

          TextView emptyView = new TextView(getApplicationContext());
          emptyView.setLayoutParams(new LayoutParams(
          LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
          emptyView.setText(getResources().getString(
          R.string.please_add_contanct));
          emptyView.setVisibility(View.GONE);
          emptyView.setTextColor(Color.BLACK);
          emptyView.setTextSize(20);
          emptyView.setGravity(Gravity.CENTER);
          ((ViewGroup) lv_contact_list.getParent()).addView(emptyView);
          lv_contact_list.setEmptyView(emptyView);

          lv_contact_list.setAdapter(myAdapter);
          };
          };

          @Override
          protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_contact_list);

          initUI();
          initData();
          }

          /**
          * 從系統(tǒng)數(shù)據(jù)庫中獲取聯(lián)系人數(shù)據(jù),權(quán)限,讀取聯(lián)系人
          */

          private void initData() {
          new Thread() {
          public void run() {
          // 1,獲取內(nèi)容解析器(訪問地址(后門))
          ContentResolver contentResolver = getContentResolver();
          // 2,對數(shù)據(jù)庫指定表進行查詢操作
          Cursor cursor = contentResolver.query(Uri
          .parse("content://com.android.contacts/raw_contacts"),
          new String[] { "contact_id" }, null, null, null);
          // 3,判斷游標中是否有數(shù)據(jù),有數(shù)據(jù)一直度
          while (cursor.moveToNext()) {
          String id = cursor.getString(0);
          Log.i(tag, "id = " + id);// 1,2,3
          // 4,通過此id去關(guān)聯(lián)data表和mimetype表生成視圖,data1(數(shù)據(jù)),mimetype(數(shù)據(jù)類型)
          Cursor indexCursor = contentResolver.query(
          Uri.parse("content://com.android.contacts/data"),
          new String[] { "data1", "mimetype" },
          "raw_contact_id = ?", new String[] { id }, null);
          HashMap<String, String> hashMap = new HashMap<String, String>();
          // 5,游標向下移動獲取數(shù)據(jù)過程
          while (indexCursor.moveToNext()) {
          String data = indexCursor.getString(0);
          String type = indexCursor.getString(1);

          // Log.i(tag, "data = "+data);
          // Log.i(tag, "type = "+type);

          if (type.equals("vnd.android.cursor.item/phone_v2")) {
          // data就為電話號碼
          hashMap.put("phone", data);
          } else if (type.equals("vnd.android.cursor.item/name")) {
          // data 為聯(lián)系人名字
          hashMap.put("name", data);
          }
          }
          indexCursor.close();
          mContactList.add(hashMap);
          }
          cursor.close();
          // 告知主線程集合中的數(shù)據(jù)以及準備完畢,可以讓主線程去使用此集合,填充數(shù)據(jù)適配器
          mHandler.sendEmptyMessage(0);
          };
          }.start();
          }

          private void initUI() {
          lv_contact_list = (ListView) findViewById(R.id.lv_contact_list);
          lv_contact_list.setOnItemClickListener(new OnItemClickListener() {
          @Override
          public void onItemClick(AdapterView<?> parent, View view,
          int position, long id) {
          // 1,position點中條目的索引值,集合的索引值
          String phone = mContactList.get(position).get("phone");
          // 2,將此電話號碼傳遞給前一個界面
          Intent intent = new Intent();
          intent.putExtra("phone", phone);
          setResult(0, intent);
          // 3,關(guān)閉此界面
          finish();
          }
          });
          }

          class MyAdapter extends BaseAdapter {
          @Override
          public int getCount() {
          return mContactList.size();
          }

          @Override
          public HashMap<String, String> getItem(int position) {
          return mContactList.get(position);
          }

          @Override
          public long getItemId(int position) {
          return position;
          }

          @Override
          public View getView(int position, View convertView, ViewGroup parent) {

          Holder holder;
          if (convertView == null) {
          holder = new Holder();
          // 1,生成當前l(fā)istview一個條目相應的view對象
          convertView = View.inflate(getApplicationContext(),
          R.layout.list_item_contact, null);
          // 2,找到view中的控件
          holder.tv_name = (TextView) convertView
          .findViewById(R.id.tv_name);
          holder.tv_phone = (TextView) convertView
          .findViewById(R.id.tv_phone);
          convertView.setTag(holder);

          } else {
          holder = (Holder) convertView.getTag();
          }

          // 3,給控件賦值
          holder.tv_name.setText(getItem(position).get("name"));
          holder.tv_phone.setText(getItem(position).get("phone"));

          return convertView;
          }
          }

          class Holder {

          public TextView tv_name;
          public TextView tv_phone;
          }
          }

          2. ListView 顯示布局如下


          <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical" >


          <ListView
          android:id="@+id/lv_contact_list"
          android:layout_width="match_parent"
          android:layout_height="wrap_content">

          ListView>
          LinearLayout>

          3. item 布局如下:


          <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:padding="10dp"
          android:orientation="vertical" >

          <TextView
          android:text="聯(lián)系人名稱"
          android:id="@+id/tv_name"
          android:textSize="18sp"
          android:textColor="@color/black"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"/>

          <TextView
          android:text="聯(lián)系人電話號碼"
          android:id="@+id/tv_phone"
          android:textSize="18sp"
          android:textColor="@color/grey"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"/>


          LinearLayout>

          注意:
          獲取聯(lián)系人需要申請權(quán)限

           
          <uses-permission android:name="android.permission.READ_CONTACTS" />

          至此,已經(jīng)可以獲取并顯示聯(lián)系人信息。

          五、獲取短信內(nèi)容的實現(xiàn)方法

          短信內(nèi)容數(shù)據(jù)也是Android系統(tǒng)提供的,獲取方法如下:

          1.短信內(nèi)容獲取方法

          public class MmsListActivity extends Activity {
          private ContentResolver resolver;
          private ListView listView;
          private static final String SMS_URI = "content://sms";
          private Cursor cursor;

          @Override
          protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_mms_list);
          listView = (ListView) findViewById(R.id.lv_mms);
          resolver = getContentResolver();

          }

          public void GetMMSBtn(View view) {

          // 插入數(shù)據(jù)
          ContentValues values = new ContentValues();
          values.put("address", "136259");
          values.put("body", "測試數(shù)據(jù)中。。。。。");
          resolver.insert(Uri.parse(SMS_URI), values);
          // 查詢數(shù)據(jù)方法
          cursor = resolver.query(Uri.parse(SMS_URI), null, null, null, null);
          // 將數(shù)據(jù)顯示到ListView中
          listView.setAdapter(new MyAdapter(MmsListActivity.this, cursor,
          CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER));

          }

          @Override
          protected void onDestroy() {
          super.onDestroy();
          if (cursor != null) {
          // 關(guān)閉cursor
          // cursor.close();
          }
          }

          class MyAdapter extends CursorAdapter {

          public MyAdapter(Context context, Cursor c, int flags) {
          super(context, c, flags);
          }

          // 創(chuàng)建一個視圖,引入listview要展示的子視圖
          @Override
          public View newView(Context context, Cursor cursor, ViewGroup parent) {
          return getLayoutInflater().inflate(R.layout.list_item_mms, null);
          }

          // 綁定數(shù)據(jù)的方法
          @Override
          public void bindView(View view, Context context, Cursor cursor) {

          TextView tvNumber = (TextView) view.findViewById(R.id.tv_number);
          TextView tvContent = (TextView) view.findViewById(R.id.tv_content);
          TextView tvState = (TextView) view.findViewById(R.id.tv_state);
          TextView tvDate = (TextView) view.findViewById(R.id.tv_date);
          TextView tvId = (TextView) view.findViewById(R.id.tv_id);
          TextView tvRead = (TextView) view.findViewById(R.id.tv_read);

          String number = cursor.getString(cursor.getColumnIndex("address"));
          String body = cursor.getString(cursor.getColumnIndex("body"));
          String date = cursor.getString(cursor.getColumnIndex("date"));
          int read = cursor.getInt(cursor.getColumnIndex("read"));
          int id = cursor.getInt(cursor.getColumnIndex("_id"));
          int type = cursor.getInt(cursor.getColumnIndex("type"));

          if (read == 0) {
          tvRead.setText("短信狀態(tài):未讀");
          } else {
          tvRead.setText("短信狀態(tài):已讀");
          }

          tvNumber.setText("手機號:" + number);
          tvContent.setText("短信內(nèi)容:" + body);
          tvDate.setText("接收短信時間:" + date);
          tvId.setText("短信Id:" + id);

          if (type == 1) {
          tvState.setText("短信狀態(tài):已接收");

          } else {
          tvState.setText("短信狀態(tài):已發(fā)送");
          }
          }
          }

          }

          2.ListView 布局如下


          <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical" >


          <ListView
          android:id="@+id/lv_mms"
          android:layout_width="match_parent"
          android:layout_height="match_parent"/>


          LinearLayout>

          3.item 布局如下:


          <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">


          <TextView
          android:id="@+id/tv_number"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:text="ddd" />


          <TextView
          android:id="@+id/tv_content"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"

          android:text="ddd" />


          <TextView
          android:id="@+id/tv_state"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:text="ddd" />

          <TextView
          android:id="@+id/tv_date"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:text="ddd" />

          <TextView
          android:id="@+id/tv_id"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:text="ddd" />

          <TextView
          android:id="@+id/tv_read"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:text="ddd" />

          LinearLayout>

          六、ContentResolver 內(nèi)容解析者

          ContentResolver主要是通過URI調(diào)用getContentResolver()獲取ContentProvider 提供的數(shù)據(jù)接口,進而進行增刪改查等操作。
          ContentResolver 使用舉例如下:

          // 查詢
          Cursor cursor = getContentResolver().query(Uri.parse(uri), null, null, null, null);
          // 插入數(shù)據(jù)到指定 URI 中
          getContentResolver().insert(Uri.parse(uri), ContentValues);

          七、ContentObserver 內(nèi)容觀察者

          ContentObserver 內(nèi)容觀察者通過指定URI 監(jiān)聽ContentProvider數(shù)據(jù)是否改變。

          下面介紹自定義 ContentObserver內(nèi)容觀察者

          1.注冊ContentObserver 內(nèi)容觀察者

              /**
          * 監(jiān)聽ContentProvider數(shù)據(jù)庫變化
          */

          private void ContentObserverDatabase() {
          // [1]注冊內(nèi)容觀察者
          Uri uri = Uri.parse("content://ProgramAndroid/person");
          // false 觀察的uri 必須是一個確切的uri 如果是true
          getContentResolver().registerContentObserver(uri, true,
          new CustomContentObserver(new Handler()));
          }

          2.繼承 ContentObserver 實現(xiàn) onChange方法

          public class CustomContentObserver extends ContentObserver {

          /**
          * @param handler
          */

          public CustomContentObserver(Handler handler) {
          super(handler);
          // TODO Auto-generated constructor stub
          }

          // 當我們觀察的uri發(fā)生改變的時候調(diào)用
          @Override
          public void onChange(boolean selfChange) {
          System.out.println(" 數(shù)據(jù)庫被操作了 ");

          super.onChange(selfChange);
          }

          }

          至此自定義內(nèi)容觀察者已經(jīng)實現(xiàn)完成

          3.調(diào)用ContentObserver 監(jiān)聽短信數(shù)據(jù)改變

          public class MainActivity extends Activity {

          @Override
          protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);

          //[1]注冊一個內(nèi)容觀察者
          Uri uri = Uri.parse("content://sms/");
          getContentResolver().registerContentObserver(uri, true, new MyContentObserver(new Handler()));

          }

          private class MyContentObserver extends ContentObserver{

          public MyContentObserver(Handler handler) {
          super(handler);
          }
          //當觀察的內(nèi)容發(fā)生改變的時候調(diào)用
          @Override
          public void onChange(boolean selfChange) {
          System.out.println(" 短信的數(shù)據(jù)庫發(fā)生了改變");
          super.onChange(selfChange);
          }

          }

          八、ContentProvider ContentResolver ContentObserver 三者關(guān)系

          • 三者關(guān)系圖如下

          關(guān)系圖.png

          至此,本篇已結(jié)束。轉(zhuǎn)載網(wǎng)絡的文章,小編覺得很優(yōu)秀,歡迎點擊閱讀原文,支持原創(chuàng)作者,如有侵權(quán),懇請聯(lián)系小編刪除。同時感謝您的閱讀,期待您的關(guān)注。

          瀏覽 43
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文字幕在线免费观看 | 日本破处视频 | 欧美高清日韩 | 91精品久 | 又紧又色AV |