在android备份短信和恢复短信对保存信息非常重要 避免删除重要信息后 无法挽回的局面,在此介绍一下对短信数据库的操作,注意:在android中对其他应用程序的数据库操作作的时候 不能以数据库对象的形式操作 必须使用URI转义 Uri uri = Uri.parser("content://sms/");
对短信数据库的操作需要添加权限
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
首先我们看一下短信数据库的结构 在eclipse中将短信数据库pull出来 在file Explorer中 data/
用sqlite expert打开,,,主要用到的table就是sms 其结构如下图
介绍一下各个列所代表的含义: id 不用多少 就是在这个表中的对应的id号 thread_id是用来识别是不是同一个号码发送或者接收信息的标识 address 发送对象的手机号 短信源手机号,read 1代表已经阅读 0代表没有阅读, type是用来判断是发送还是接收的 1代表发送 2代表接收 ,body就是短信内容实体,
我们需要在程序中新建一个信息实体:
package com.example.mobilesafe.domain;
public class SMSInfo {
String _id;
int type;//判断是发送还是接收
String address ;// 发送或者接收号码
String body;//短信内容
String date;//发送或者接收短信的时间
@Override
public String toString() {
return "SMSInfo [_id=" + _id + ", type=" + type + ", address="
+ address + ", body=" + body + ", date=" + date + "]";
}
//构造方法
public SMSInfo(String _id, int type, String address, String body, String date) {
super();
this._id = _id;
this.type = type;
this.address = address;
this.body = body;
this.date = date;
}
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
然后要写出 读取短信 和 回复短信的 函数
package com.example.mobilesafe.engine;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Looper;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.util.Log;
import android.util.Xml;
import android.widget.Toast;
import com.example.mobilesafe.domain.SMSInfo;
//在这个类中实现 短信的 读取 和 恢复
public class SmsInfoService {
private static final String TAG = "SmsInfoService";
private Context context;
public SmsInfoService(Context context){
this.context = context;//将上下文传递进来
}
/**
* 备份信息
* @return
*/
public List<SMSInfo> getSMSInfos(){
List<SMSInfo> smsInfos = new ArrayList<SMSInfo>();
ContentResolver contentResolver = context.getContentResolver();//这个ContentResolver是对别的应用的数据库操作的时候使用的
//不能对短信的数据库直接操作 要进行转移
Uri uri = Uri.parse("content://sms/");
/**
* 介绍下面函数的参数 第一个 是数据库的uri 第二个是返回的列 第三个是返回的行 第四个 不知道 第五个 是设置以什么来排序
*/
Cursor cursor = contentResolver.query(uri, null, null, null, null);
Log.i(TAG, "shifoujinru cursor");
if(null != cursor){
Log.i(TAG, "查询到sms数据库中数据条目"+cursor.getCount());
while(cursor.moveToNext()){
String _id = cursor.getString(cursor.getColumnIndex("_id"));
int type = cursor.getInt(cursor.getColumnIndex("type"));
String date = cursor.getString(cursor.getColumnIndex("date"));
String address = cursor.getString(cursor.getColumnIndex("address"));
String body = cursor.getString(cursor.getColumnIndex("body"));
SMSInfo smsInfo = new SMSInfo(_id, type, address, body, date);
System.out.println(smsInfo);
smsInfos.add(smsInfo);
}
cursor.close();
}
return smsInfos ;
}
/**
*
* @param path 输入保存好的 sms的路径
* @param pd 传入形参 diaolog
* @throws Exception
* @throws Exception
*/
public void restoreSMS(String path,ProgressDialog pd) throws Exception {//对短信的数据库操作不能直接使用数据库的操作 必须转义操作
File file = new File(path);//需要将这个文件的xml文件解析
XmlPullParser parser = Xml.newPullParser();//使用pullparser解析xml文件
FileInputStream fis = new FileInputStream(file);
parser.setInput(fis, "utf-8");
ContentValues values = null;
int type = parser.getEventType();
int currentcount=0;
while(type != XmlPullParser.END_DOCUMENT){//如果没有到文件的结尾 则一直执行
switch (type) {
case XmlPullParser.START_TAG://起始节点
if("count".equals(parser.getName())){
pd.setMax(Integer.parseInt(parser.nextText()));//给对话框设置最大值
}else if("sms".equals(parser.getName())){//但是信息节点的时候新建一个contentValues
values = new ContentValues();
}else if("_id".equals(parser.getName())){//获取节点的名称 如果为 id
values.put("_id", parser.nextText());
}else if("address".equals(parser.getName())){
values.put("address", parser.nextText());
}else if("date".equals(parser.getName())){
values.put("date", parser.nextText());
}else if("type".equals(parser.getName())){
values.put("type", parser.nextText());
}else if("body".equals(parser.getName())){
values.put("body", parser.nextText());
}
break;
case XmlPullParser.END_TAG:{
if("sms".equals(parser.getName())){//如果节点是sms
Uri uri = Uri.parse("content://sms/");
ContentResolver resolver = context.getContentResolver();
resolver.insert(uri, values);//先数据库中插入数据
values =null;//
currentcount++;
pd.setProgress(currentcount);//设置进度
}
}
default:
break;
}
type = parser.next();//不要忘了给type重新赋值
}
}
}
这里我们将短信以xml的形式保存起来 这就要用到 xmlpuuparser 和 xmlSerializer 两个对象
读取备份函数 如下
package com.example.mobilesafe.service;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
import com.example.mobilesafe.domain.SMSInfo;
import com.example.mobilesafe.engine.SmsInfoService;
import android.R.xml;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Looper;
import android.util.Xml;
import android.widget.Toast;
/**
* 在这个service中备份短信
* @author Administrator
*
*/
public class BackUpSMSService extends Service {
//这个service 中将会涉及到对sms数据库的读取操作 并把读取的数据保存到 xml文件中
private SmsInfoService smsInfoService;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
super.onCreate();
smsInfoService = new SmsInfoService(this);
//在这个service中 用一个线程 来读取数据库并将其写入到xml文件中去
new Thread(){
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
try {
ArrayList<SMSInfo> list = (ArrayList<SMSInfo>) smsInfoService.getSMSInfos();//获得短信的返回值
XmlSerializer xmlSerializer = Xml.newSerializer();//新建一个可以存储xml'到文件的类
File file = new File("/sdcard/backupsms.xml");
FileOutputStream fos = new FileOutputStream(file);
xmlSerializer.setOutput(fos, "utf-8");
xmlSerializer.startDocument("utf-8", true);
xmlSerializer.startTag(null, "smss");
//增加一个节点 来 给dialog计算百分比
xmlSerializer.startTag(null, "count");
xmlSerializer.text(list.size()+"");
xmlSerializer.endTag(null, "count");
for(SMSInfo smsInfo : list){
xmlSerializer.startTag(null, "sms");
xmlSerializer.startTag(null, "id");
xmlSerializer.text(smsInfo.get_id());
System.out.println(smsInfo.get_id());
xmlSerializer.endTag(null, "id");
xmlSerializer.startTag(null, "address");
xmlSerializer.text(smsInfo.getAddress());
System.out.println(smsInfo.getAddress());
xmlSerializer.endTag(null, "address");
xmlSerializer.startTag(null, "date");
xmlSerializer.text(smsInfo.getDate());
xmlSerializer.endTag(null, "date");
xmlSerializer.startTag(null, "type");
xmlSerializer.text(smsInfo.getType()+"");
xmlSerializer.endTag(null, "type");
xmlSerializer.startTag(null, "body");
xmlSerializer.text(smsInfo.getBody());
System.out.println(smsInfo.getBody());
xmlSerializer.endTag(null, "body");
xmlSerializer.endTag(null, "sms");
}
xmlSerializer.endTag(null, "smss");
xmlSerializer.endDocument();//一定要结束
fos.flush();
fos.close();
//创建一个消息循环来 显示时候写入完成
Looper.prepare();
Toast.makeText(getApplicationContext(), "备份完成", Toast.LENGTH_SHORT).show();
Looper.loop();//这个语句是执行消息循环
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
//创建一个消息循环来 显示时候写入完成
Looper.prepare();
Toast.makeText(getApplicationContext(), "备份失败", Toast.LENGTH_SHORT).show();
Looper.loop();//这个语句是执行消息循环
}
}
}.start();
}
}
短信的回复很简单 就直接调用函数public void restoreSMS(String path,ProgressDialog pd)就好