ContentProvider是不同應用程式之間進行數據交換的一種方式或者稱標準API. http://www.qq.com:80/news.jsp ContentProvider要求的;Uri與上面類似 在AndroidManifest.xml中註冊ContentProvider,指定 建立一
安卓第十四天筆記-內容提供者(ContentProvider)
ContentProvider--內容提供者
1.ContentProvider簡介
ContentProvider是不同應用程式之間進行數據交換的一種方式或者稱標準API.
- ContentProvider以某種Uri的方式對外提供數據,允許其他應用訪問或者修改數據
- 其它的程式根據Uri去訪問操作指定的數據
2.Uri簡介
http://www.qq.com:80/news.jsp
- http://:URL的協議部分,只要通過HTTP協議來訪問網路,這具部分是固定的.如FTP
- www.qq.com:功能變數名稱部分
- news.jsp:網站資源部分,訪問不能的資源這具部分是不同的,這個部分是動態的
ContentProvider要求的;Uri與上面類似
content://com.pc.pp.provider/words
- content://這個Android的ContentProvider規定的,就像預設的http://,ContentProvider的協議預設就是Content://
- com.pc.pp.provider:這部分就是ContentProvider的authorities.系統就是由這具部分來找到操作哪個ContentProvider的.只要訪問指定的ContentProvider,這個部分是固定的
- words:資源部分或者數據
3.建立ContentProvider
- 寫一個類繼承ContentProvider重寫query,insert,update,delete,getType等方法
-
在AndroidManifest.xml中註冊ContentProvider,指定
android:authorities屬性 //這個給其它應用程式使用的
建立一個數據幫助類
public class BankSqliteOpenHelper extends SQLiteOpenHelper { public BankSqliteOpenHelper(Context context) { super(context, "bank.db", null, 1); } @Override public void onCreate(SQLiteDatabase db) { String sql = "create table account(_id integer primary key, name varchar(30),money double)"; db.execSQL(sql); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
建立一個ContentProvider
/** 本地資料庫的內容提供者, @author 劉楠 * 2016-3-2下午8:35:19 */ public class BankDbProvider extends ContentProvider { private static final String TAG = "BankDbProvider"; private static final int ACCOUNT = 0; private static final int ACCOUNT_ID = 1; //預設匹配,不能匹配就執行UriMatcher.NO_MATCH private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); //資料庫操作類 private BankSqliteOpenHelper helper; /** * 初始始化一些可以匹配的URI */ static { matcher.addURI("com.itheima.bankdb.BankDbProvider", "account", ACCOUNT); matcher.addURI("com.itheima.bankdb.BankDbProvider", "account/#", ACCOUNT_ID); } /** * 這個Provider被創建時執行,做一些初始始化操作 */ @Override public boolean onCreate() { helper = new BankSqliteOpenHelper(getContext()); return true; } /** * 查詢操作 */ @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { if (matcher.match(uri) == ACCOUNT) { SQLiteDatabase db = helper.getReadableDatabase(); Cursor cursor = db.query("account", projection, selection, selectionArgs, null, null, sortOrder); return cursor; } else if (matcher.match(uri) == ACCOUNT_ID) { SQLiteDatabase db = helper.getReadableDatabase(); long id = ContentUris.parseId(uri); Cursor cursor = db.query("account", null, "_id=?", new String[] { id + "" }, null, null, sortOrder); return cursor; } return null; } /** * 返回類型,主要針對查詢操作 * vnd.android.cursor.dir:表示返回多條數據 * vnd.android.cursor.item:表示返回一條數據 */ @Override public String getType(Uri uri) { if (matcher.match(uri) == ACCOUNT) { return "vnd.android.cursor.dir/account"; } else if (matcher.match(uri) == ACCOUNT_ID) { return "vnd.android.cursor.item/account"; } return null; } /** * 插入操作 */ @Override public Uri insert(Uri uri, ContentValues values) { if (matcher.match(uri) == ACCOUNT) { SQLiteDatabase db = helper.getWritableDatabase(); long insert = db.insert("account", null, values); db.close(); } return uri; } /** * 刪除操作 */ @Override public int delete(Uri uri, String selection, String[] selectionArgs) { if (matcher.match(uri) == ACCOUNT) { SQLiteDatabase db = helper.getWritableDatabase(); int delete = db.delete("account", selection, selectionArgs); db.close(); return delete; } return 0; } /** * 更新操作 */ @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { if (matcher.match(uri) == ACCOUNT) { SQLiteDatabase db = helper.getWritableDatabase(); int update = db.update("account", values, selection, selectionArgs); db.close(); return update; } return 0; } }
在清單文件中註冊這個provider
<!-- 註冊Provider authorities:對外暴露的訪問路徑 --> <provider android:name="com.itheima.bankdb.provider.BankDbProvider" android:authorities="com.itheima.bankdb.BankDbProvider" > </provider>
authorities :可以隨便定義,建立使用包名.Provider
4.訪問這個應用程式的Provider
新建一個應用
ContentResolver resolver = getContentResolver(); 使用這個對象來實現對象Privoider的解析
/** * 插入數據 * * @param v */ public void insert(View v) { ContentResolver resolver = getContentResolver(); Uri uri = Uri.parse("content://com.itheima.bankdb.BankDbProvider/account"); ContentValues values = new ContentValues(); values.put("name", "lisi"); values.put("money", 503.3); Uri insert = resolver.insert(uri, values); System.out.println("insert:"+insert); } /** * 更新 * * @param v */ public void update(View v) { ContentResolver resolver = getContentResolver(); Uri uri = Uri.parse("content://com.itheima.bankdb.BankDbProvider/account"); ContentValues values = new ContentValues(); values.put("money", 1003.3); int update = resolver.update(uri, values, "name=?", new String[]{"lisi"}); System.out.println("update"+update); } /** * 刪除 * * @param v */ public void delete(View v) { ContentResolver resolver = getContentResolver(); Uri uri = Uri.parse("content://com.itheima.bankdb.BankDbProvider/account"); int delete = resolver.delete(uri, "name=?", new String[]{"lisi"}); System.out.println("delete:"+delete); } /** * 查詢全部 * * @param v */ public void query(View v) { ContentResolver resolver = getContentResolver(); Uri uri = Uri.parse("content://com.itheima.bankdb.BankDbProvider/account"); Cursor cursor = resolver.query(uri, null, null, null, null); while(cursor.moveToNext()){ int id=cursor.getInt(cursor.getColumnIndex("_id")); String name = cursor.getString(cursor.getColumnIndex("name")); double money =cursor.getDouble(cursor.getColumnIndex("money")); Toast.makeText(this, "ID:"+id+"姓名:"+name+",Money:"+money, Toast.LENGTH_SHORT).show(); } cursor.close(); } /** * 查詢一個 * * @param v */ public void queryOne(View v) { ContentResolver resolver = getContentResolver(); Uri uri = Uri.parse("content://com.itheima.bankdb.BankDbProvider/account/2"); Cursor cursor = resolver.query(uri, null, null, null, null); while(cursor.moveToNext()){ int id=cursor.getInt(cursor.getColumnIndex("_id")); String name = cursor.getString(cursor.getColumnIndex("name")); double money =cursor.getDouble(cursor.getColumnIndex("money")); Toast.makeText(this, "ID:"+id+"姓名:"+name+",Money:"+money, Toast.LENGTH_SHORT).show(); } cursor.close(); }
5.使用簡訊的內容提供者
向簡訊中添加一條數據
/** * 像簡訊中添加一條數據 * @param v */ public void insert(View v){ //獲取內容解析都 ContentResolver resolver = getContentResolver(); //查看源碼中找到提供的uri Uri uri =Uri.parse("content://sms"); //要添加的數據就是一個MAP集合,對應的數據表的欄位 ContentValues values = new ContentValues(); values.put("address", "10086"); values.put("date", System.currentTimeMillis()); values.put("body", "這是一條新的簡訊"); values.put("type", 1); resolver.insert(uri, values); }
添加許可權
<uses-permission android:name="android.permission.READ_SMS"/> <uses-permission android:name="android.permission.WRITE_SMS"/>
6.使用聯繫人ContentProvider
查詢聯繫人
/** * 查詢所有聯繫人, * @param context * @return */ public static List<ContactInfo> getContacts(Context context){ List<ContactInfo> list = new ArrayList<ContactInfo>(); Uri rowUri = Uri.parse("content://com.android.contacts/raw_contacts"); Uri dataUri = Uri.parse("content://com.android.contacts/data"); ContentResolver resolver = context.getContentResolver(); Cursor rawCursor = resolver.query(rowUri, new String[]{"contact_id"}, null, null, null); while(rawCursor.moveToNext()){ String id =rawCursor.getString(rawCursor.getColumnIndex("contact_id")); if(id==null){ continue; } ContactInfo info = new ContactInfo(); info.id=id; Cursor dataCursor= resolver.query(dataUri, new String[]{"data1","mimetype"}, "raw_contact_id=?", new String[]{id}, null); while(dataCursor.moveToNext()){ String data1=dataCursor.getString(dataCursor.getColumnIndex("data1")); String mimetype=dataCursor.getString(dataCursor.getColumnIndex("mimetype")); if("vnd.android.cursor.item/email_v2".equals(mimetype)){ info.email=data1; }else if("vnd.android.cursor.item/im".equals(mimetype)){ info.im=data1; }else if("vnd.android.cursor.item/phone_v2".equals(mimetype)){ info.phone=data1; }else if("vnd.android.cursor.item/name".equals(mimetype)){ info.name=data1; } } dataCursor.close(); list.add(info); } rawCursor.close(); return list; }
添加聯繫人
/** * 添加聯繫人 * * @param v */ public void insert(View v) { String name = etName.getText().toString().trim(); String phone = etPhone.getText().toString().trim(); String email = etEmail.getText().toString().trim(); if (TextUtils.isEmpty(name) || TextUtils.isEmpty(phone) || TextUtils.isEmpty(email)) { Toast.makeText(this, "名字,電話,郵件不能為空", Toast.LENGTH_SHORT).show(); return; } Uri rowUri = Uri.parse("content://com.android.contacts/raw_contacts"); Uri dataUri = Uri.parse("content://com.android.contacts/data"); // 先查詢ID ContentResolver resolver = getContentResolver(); Cursor rawCursor = resolver.query(rowUri, new String[] { "_id" }, null, null, null); rawCursor.moveToLast(); int id = 1; id = rawCursor.getInt(rawCursor.getColumnIndex("_id")) + 1; rawCursor.close(); // 插入raw_contact表ID ContentValues values = new ContentValues(); values.put("contact_id", id); resolver.insert(rowUri, values); // 向data表中插入數據 ContentValues nameValues = new ContentValues(); nameValues.put("data1", name); nameValues.put("mimetype", "vnd.android.cursor.item/name"); nameValues.put("raw_contact_id", id); resolver.insert(dataUri, nameValues); ContentValues phoneValues = new ContentValues(); phoneValues.put("data1", phone); phoneValues.put("mimetype", "vnd.android.cursor.item/phone_v2"); phoneValues.put("raw_contact_id", id); resolver.insert(dataUri, phoneValues); ContentValues emailValues = new ContentValues(); emailValues.put("data1", email); emailValues.put("mimetype", "vnd.android.cursor.item/email_v2"); emailValues.put("raw_contact_id", id); resolver.insert(dataUri, emailValues); Toast.makeText(this, "添加成功", Toast.LENGTH_SHORT).show(); }
添加許可權
<uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
7.內容觀察者
ContentObserver 觀察某一個路徑的數據, 某個指定的數據,一旦數據發生了變化,那麼將會收到通知
作用: 資料庫的數據發生變化之後,會發佈一個通知出來,我們收到通知之後,再去查詢資料庫,即可得到最新的數據
發佈通知
//參數一: 具體是什麼位置的數據發生了改變 //參數二:具體的內容觀察者對象, 如果是null , 那麼表明不告訴具體的某一個人, getContext().getContentResolver().notifyChange(uri, null);
收到通知
//註冊內容觀察者 Uri uri = Uri.parse("content://com.itheima.bank.BACKDOOR/account"); //參數一: 觀察的具體位置 ,uri //參數二: true : uri只要匹配前半段,也能收到通知, false . 所有的字母都全部匹配才能收到通知 getContentResolver().registerContentObserver(uri, true, new MyObserver(new Handler())); ---------------------- class MyObserver extends ContentObserver{ public MyObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); Log.d(TAG, "表數據發生了改變.."); } }