四大組件之ContentProvider
ContentProvider簡介
ContentProvider的主要作用是實現不同的應用程序之間的數據的共享,而且還保證了數據的安全性。 ContentProvider是android提供的實現程序之間數據共享的一套機制。
ContentProvider的使用
1.創建ContentProvider
首先我們要爲應用程序準備數據,我們在數據庫裏面添加100條數據
public class MySQLiteOpenHelper extends SQLiteOpenHelper { public MySQLiteOpenHelper(Context context) { super(context, "mydb.db", null, 1); // TODO Auto-generated constructor stub } @Override public void onCreate(SQLiteDatabase db) { // TODO Auto-generated method stub //創建一張表 db.execSQL("create table student( _id integer primary key autoincrement,name text,age text,score text)"); //向表中插入100條記錄 for(int i=0;i<100;i++){ db.execSQL("insert into student(name,age,score)values('zhangsan"+i+"','"+(20+i)+"','"+(60+i)+"')"); } } //更新時調用 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub } }
添加完數據之後,開始創建自己的
ContentProvider
。我們需要建一個類,繼承ContentProvider
類,然後複寫裏面的方法public class MyContentProder extends ContentProvider { //創建一個UriMatcher對象 private static final UriMatcher urimatcher =new UriMatcher(UriMatcher.NO_MATCH); private static final int INSERT=1; private static final int DELETE=2; private static final int UPDATE=3; private static final int QUERY=4; private MySQLiteOpenHelper helper; static{ //添加uri urimatcher.addURI("com.example.provider", "insert", INSERT); urimatcher.addURI("com.example.provider", "delete", DELETE); urimatcher.addURI("com.example.provider", "update", UPDATE); urimatcher.addURI("com.example.provider", "query", QUERY); } @Override public boolean onCreate() { helper = new MySQLiteOpenHelper(getContext()); return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // TODO Auto-generated method stub //匹配uri if(urimatcher.match(uri)==QUERY){ SQLiteDatabase db = helper.getWritableDatabase(); Cursor cursor = db.query("student", projection, selection, selectionArgs, null, null, sortOrder); return cursor; } return null; } @Override public String getType(Uri uri) { // TODO Auto-generated method stub return null; } @Override public Uri insert(Uri uri, ContentValues values) { // TODO Auto-generated method stub if(urimatcher.match(uri)==INSERT){ SQLiteDatabase db = helper.getWritableDatabase(); long insert2 = db.insert("student", null, values); db.close(); return Uri.parse("content://com.example.provider"+insert2); } return null; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // TODO Auto-generated method stub if(urimatcher.match(uri)==DELETE){ SQLiteDatabase db = helper.getWritableDatabase(); int delete2 = db.delete("student", selection, selectionArgs); return delete2; } return 0; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // TODO Auto-generated method stub if(urimatcher.match(uri)==UPDATE){ SQLiteDatabase db = helper.getWritableDatabase(); int update2 = db.update("student", values, selection, selectionArgs); return update2; } return 0; } }
和其他的幾大大組件組件一樣
ContentProvider
也需要在Manifest.xml
裏面註冊,註冊ContentProvider
的時候,還要配置兩個額外的屬性。<provider android:name="com.example.contentproviderdemo.MyContentProder" android:authorities="com.example.provider" android:exported="true"> </provider>
這樣,我們就將這個application裏面的數據通過ContentProvider暴露出去了,其他的application就可以通過getContentResolver()
來訪問這個application裏面的數據。
2.在另外的application中進行對數據庫的內容的操作
上面我們已經將數據暴露出來了,這裏我們就在另外的application中來操作數據。
我們在另外的一個application的佈局文件中定義4個button,分別用來對contentprovide的數據進行增刪改查。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="click1" android:text="查詢"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="click2" android:text="刪除"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="click3" android:text="添加"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="click4" android:text="更新"/> </LinearLayout>
在Mainctivity裏面,我們通過設置button的點擊事件來操作數據。
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } // 查詢 public void click1(View v) { Uri uri = Uri.parse("content://com.example.provider/query"); Cursor cursor = getContentResolver().query(uri, null, null, null, null); if(cursor!=null && cursor.getCount()>0){ while(cursor.moveToNext()){ String name = cursor.getString(1); String age =cursor.getString(2); String score = cursor.getString(3); System.out.println(name+" "+age+" "+score); } } } // 刪除 public void click2(View v) { Uri uri = Uri.parse("content://com.example.provider/delete"); int delete = getContentResolver().delete(uri, "_id=?", new String[]{"1"}); System.out.println(delete); } // 添加 public void click3(View v) { Uri uri = Uri.parse("content://com.example.provider/insert"); ContentValues values =new ContentValues(); values.put("name", "xiaoming"); values.put("age", "100"); values.put("score", "200"); Uri insert = getContentResolver().insert(uri, values ); System.out.println(insert); } // 更新 public void click4(View v) { Uri uri = Uri.parse("content://com.example.provider/update"); ContentValues values =new ContentValues(); values.put("score", "2000"); int update = getContentResolver().update(uri, values , "_id =?", new String[]{"100"}); System.out.println(update); } }
到這裏爲止,我們就已經會使用ContentProvider了。下面我們來寫一個短信備份的案例。
使用ContentProvider實現手機短信備份
1.獲取短信存儲的信息
毫無疑問,手機短信存儲在手機的數據庫裏面,所以我們首先要知道短信存儲的情況。我們可以在手機文件夾的 \data\data\com.android.providers.telephony\databases\
目錄下找到mmssms.db
文件,這就是存儲短信的表,我們打開這張後發現,我們只需要通過查詢這個表的3個字段就可以進行短信的完整備份,它們分別是:date
表示短信的發送日期、address
短信來源的號碼、body
表示短信的具體內容。
2.得到系統爲短信設置的ContentProvider的Uri
想要得到這個,我們百度或者自己查下系統上層應用的源代碼。如果我們要在源碼裏面找的話,需要在\providers\TelephonyProvider\src\com\android\providers\telephony\SmsProvider.java
這個文件裏面找。這裏我粘一段靜態代碼塊的內容參考:
static {
sURLMatcher.addURI("sms", null, SMS_ALL);
sURLMatcher.addURI("sms", "#", SMS_ALL_ID);
sURLMatcher.addURI("sms", "inbox", SMS_INBOX);
sURLMatcher.addURI("sms", "inbox/#", SMS_INBOX_ID);
sURLMatcher.addURI("sms", "sent", SMS_SENT);
//省略若干
...
}
3.備份短信
備份短信的思路:從數據庫中將短信獲取後,將其序列化到SDcard中。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void click(View v){
//設置Uri
Uri uri=Uri.parse("content://sms");
//查詢所需要的數據
Cursor cursor = getContentResolver().query(uri, new String[]{"address","date","body"},
null, null, null);
if(cursor!=null && cursor.getCount()>0){
//獲取xml解析器,開始序列化
XmlSerializer serializer = Xml.newSerializer();
//設置文件存儲的位置
File file =new File(Environment.getExternalStorageDirectory(),"smss.xml");
//設置輸出流
FileOutputStream fos;
try {
fos = new FileOutputStream(file);
serializer.setOutput(fos, "utf-8");
//開始文檔
serializer.startDocument("utf-8", true);
//根標籤
serializer.startTag(null, "smss");
//將查詢到的數據序列化到XML文件中
while (cursor.moveToNext()) {
String address = cursor.getString(0);//短信人電話 爲null
String date = cursor.getString(1);//短信發送時間
String body = cursor.getString(2);//短信內容
//根目錄下的一級標題
serializer.startTag(null, "sms");
//設置address
serializer.startTag(null, "address");
serializer.text(address);
serializer.endTag(null, "address");
//設置date
serializer.startTag(null, "date");
serializer.text(date);
serializer.endTag(null, "date");
//設置body
serializer.startTag(null, "body");
serializer.text(body);
serializer.endTag(null, "body");
serializer.endTag(null, "sms");
}
serializer.endTag(null, "smss");
//結束文檔
serializer.endDocument();
Toast.makeText(this, "序列化完成", 0).show();;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
最後,我們需要添加相應的權限。
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>