A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 邱本超老师 黑马帝   /  2015-12-27 10:03  /  1150 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

      为了避免重要信息删除后无法挽回的局面,目前很多Android应用都实现了短信的备份操作。短信备份,其实就是从短信应用中读取短信,然后将短信数据写入XML文件的过程。但这里会涉及到两个问题:
第一:如何从短信应用中读取短信
第二:如何将短信数据写入XML文件
      系统存储短信内容的目录为/dada/dada/com.android.providers.telephony/databases/mmssms.db,我们可以通过Eclipse找到对应的数据库文件,具体如图1所示。

点击File Explorer右上角标注的那个按钮,将数据库导出,然后使用SQLite Expert Personal打开查看短信数据的存储结构,如图2所示。

从图2中可以看出,用于存放短信的表有很多字段,其中,address字段表示接受短信的号码,body表示短信内容,date表示短信发送的时间。
但是,mmssms.db 文件对于第三方而言,是不可读不可写的,所以,我们要想在程序中访问短信内容,需要使用内容提供者。
Android提供了许多自带的内容提供者给开发者使用,这些内容提供者给我们提供了一些系统数据供我们访问,通过查看短信内容提供者的源码我们可以得到以下内容。
查看清单配置文件源码得到短信内容提供者的主机名为:sms

  1. <provider android:name="SmsProvider"
  2.       android:authorities="sms"
  3.       android:multiprocess="false"
  4.       android:exported="true"
  5.       android:readPermission="android.permission.READ_SMS"
  6.       android:writePermission="android.permission.WRITE_SMS"/>
复制代码
查看SmsProvider系统短信内容提供者类得到以下内容,即当uri匹配上content//sms/则可调用query方法,查询短信数据库,即sms表。
  1. //系统短信内容提供者类
  2. public class SmsProvider extends ContentProvider{
  3.     ...
  4.     static {
  5. /**
  6. 维护主机名后,维护短信数据库中指定短信表的访问方式,null则在说明在主机名后不需要
  7. 拼接后续内容,则为content://sms/
  8. */
  9.         sURLMatcher.addURI("sms", null, SMS_ALL);
  10.     }
  11.     ...
  12.     //源码查询数据方法,此方法中包含查询短信数据
  13.     public Cursor query(Uri url, String[] projectionIn, String selection,
  14.         String[] selectionArgs, String sort){
  15.         SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
  16.         /**
  17. 如果参数url和sURLMatcher.addURI("sms", null, SMS_ALL)的url一致,
  18. 则匹配其返回值,即SMS_ALL
  19. */
  20.         int match = sURLMatcher.match(url);
  21.         switch (match) {
  22.         case SMS_ALL:
  23.             //指定查询表名为sms
  24.             constructQueryForBox(qb, Sms.MESSAGE_TYPE_ALL);
  25.             break;
  26.         }   
  27.         //做查询操作,返回查询所有短信表的游标
  28.       SQLiteDatabase db = mOpenHelper.getReadableDatabase();
  29.       Cursor ret = qb.query(db, projectionIn, selection, selectionArgs,null, null,
  30. orderBy);
  31.         return ret;
  32.     }
  33.     ...
  34. }
复制代码
设置查询表名,TABLE_SMS量的值就是sms表名
  1. //设置查询表名,TABLE_SMS常量的值就是sms表名
  2. private void constructQueryForBox(SQLiteQueryBuilder qb, int type) {
  3.     qb.setTables(TABLE_SMS);
  4. }
复制代码
编写查询短信数据,并且备份至xml的方法backup
  1. // 1.获取xml序列化器
  2. XmlSerializer serializer = Xml.newSerializer();
  3. // 2.将文件存储至sd卡中,并且将短信备份至sd卡的backup.xml中
  4. File file = new File(Environment.getExternalStorageDirectory().getPath(),
  5. backup.xml");
  6. FileOutputStream fos = new FileOutputStream(file);
  7. serializer.setOutput(fos, "utf-8");
  8. // 3. 写xml文档开头
  9. serializer.startDocument("utf-8", true);
  10. // 4 写根节点
  11. serializer.startTag(null, "smss");
  12. // 5 通过内容解析器,匹配uri,获取系统短信数据库中短信表中数据
  13. Uri uri = Uri.parse("content://sms/");
  14. Cursor cursor = getContentResolver().query(uri,
  15.         new String[] { "address", "body", "date" }, null, null,null);
  16. while (cursor.moveToNext()) {
  17. serializer.startTag(null, "sms");
  18.     serializer.startTag(null, "address");
  19.     serializer.text(cursor.getString(0));
  20.     serializer.endTag(null, "address");
  21.     serializer.startTag(null, "body");
  22.     serializer.text(cursor.getString(1));
  23.     serializer.endTag(null, "body");
  24.     serializer.startTag(null, "date");
  25.     serializer.text(cursor.getString(2));
  26. serializer.endTag(null, "date");
  27. serializer.endTag(null, "sms");
  28. }
  29. serializer.endTag(null, "smss");
  30. serializer.endDocument();
复制代码

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马