四大组件之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"/>