Android之——短信的备份与还原

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47091281

目前,Android手机中的一些软件可以实现手机短信的备份与还原操作。这篇博文就是要向大家介绍如何实现Android短信的备份与还原操作。好了,相信大家对这些实用的功能还是比较感兴趣的,不多说了,我们直接进入主题吧。

一、原理

我的实现原理很简单,界面上放置几个TextView列表,其中两项为“短信的备份”和“短信的还原”,点击“短信的备份”,读取所有的短信信息,将短信信息保存在一个xml文件中,这个xml文件放置的sdcard中,作为短信的备份文件,然后当需要还原短信的时候,只需要点击“短信的还原”,这时程序首先会删除手机上现有的短信,然后从短信的备份xml文件中读取之前备份的短信内容,写入手机短信数据库中。

原理讲完了,是不是很简单呢?下面,我们就一起来实现这些功能吧!

二、实践

1、创建短信的实体类SmsInfo

为了使程序更加面向对象化,更加符合面向对象的封装,我将短信信息封装成了一个实体类SmsInfo

具体代码如下:

package cn.lyz.mobilesafe.domain;

/**
 * 短信内容的实体类
 * @author liuyazhuang
 *
 */
public class SmsInfo {
	
	//电话号码
	private String address;
	//日期
	private String date;
	//短信类型
	private String type;
	//短信内容
	private String body;
	
	public SmsInfo() {
		super();
		// TODO Auto-generated constructor stub
	}
	public SmsInfo(String address, String date, String type, String body) {
		super();
		this.address = address;
		this.date = date;
		this.type = type;
		this.body = body;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public String getDate() {
		return date;
	}
	public void setDate(String date) {
		this.date = date;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	public String getBody() {
		return body;
	}
	public void setBody(String body) {
		this.body = body;
	}
	@Override
	public String toString() {
		return "SmsInfo [address=" + address + ", date=" + date + ", type="
				+ type + ", body=" + body + "]";
	}
	
	
}

2、创建短信操作业务类SmsInfoService

这个类主要封装了对短信数据的操作,同时封装了对xml文件的写入与解析操作。备份短信流程是首先从短信数据库中读取短信,然后将短信信息写入xml文件。还原短信的流程为先删除手机中的短信,然后解析备份的短信文件,将解析出的短信信息写入短信数据库。

具体实现代码如下:

package cn.lyz.mobilesafe.engine;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.util.Xml;
import cn.lyz.mobilesafe.domain.SmsInfo;

/**
 * 获取短信内容的业务类
 * @author liuyazhuang
 *
 */
public class SmsInfoService {

	private Context context;
	public SmsInfoService(Context context) {
		// TODO Auto-generated constructor stub
		this.context = context;
	}
	
	//得到所有的短信
	public List<SmsInfo> getSmsInfos(){
		List<SmsInfo> smsInfos = new ArrayList<SmsInfo>();
		Uri uri = Uri.parse("content://sms");
		Cursor c = context.getContentResolver().query(uri, new String[]{"address","date","type","body"}, null, null, null);
		while(c.moveToNext()){
			String address = c.getString(c.getColumnIndex("address"));
			String date = c.getString(c.getColumnIndex("date"));
			String type = c.getString(c.getColumnIndex("type"));
			String body = c.getString(c.getColumnIndex("body"));
			
			SmsInfo smsInfo = new SmsInfo(address, date, type, body);
			smsInfos.add(smsInfo);
		}
		return smsInfos;
	}
	
	//把短信数据写入到xml文件
	public void createXml(List<SmsInfo> smsInfos) throws Exception{
		XmlSerializer serializer = Xml.newSerializer();
		File file = new File(Environment.getExternalStorageDirectory(), "smsbackup.xml");
		OutputStream os = new FileOutputStream(file);
		serializer.setOutput(os, "UTF-8");
		
		serializer.startDocument("UTF-8", true);
		serializer.startTag(null, "smsinfos");
		
		for(SmsInfo info:smsInfos){
			serializer.startTag(null, "smsinfo");
			//address
			serializer.startTag(null, "address");
			serializer.text(info.getAddress());
			serializer.endTag(null, "address");
			
			//date
			serializer.startTag(null, "date");
			serializer.text(info.getDate());
			serializer.endTag(null, "date");
			
			//type
			serializer.startTag(null, "type");
			serializer.text(info.getType());
			serializer.endTag(null, "type");
			
			//body
			serializer.startTag(null, "body");
			serializer.text(info.getBody());
			serializer.endTag(null, "body");
			
			serializer.endTag(null, "smsinfo");
		}
		serializer.endTag(null, "smsinfos");
		serializer.endDocument();
		os.close();
	}
	
	//从xml文件中得到短信数据
	public List<SmsInfo> getSmsInfosFromXml() throws Exception{
		List<SmsInfo> smsInfos =null;
		SmsInfo smsInfo = null;
		XmlPullParser parser = Xml.newPullParser();
		File file = new File(Environment.getExternalStorageDirectory(), "smsbackup.xml");
		InputStream inputStream = new FileInputStream(file);
		parser.setInput(inputStream, "UTF-8");
		int eventType = parser.getEventType();
		while(eventType != XmlPullParser.END_DOCUMENT){
			switch (eventType) {
			case XmlPullParser.START_TAG:
				if("smsinfos".equals(parser.getName())){
					smsInfos = new ArrayList<SmsInfo>();
				}else if("smsinfo".equals(parser.getName())){
					smsInfo = new SmsInfo();
				}else if("address".equals(parser.getName())){
					String address = parser.nextText();
					smsInfo.setAddress(address);
				}else if("date".equals(parser.getName())){
					String date = parser.nextText();
					smsInfo.setDate(date);
				}else if("type".equals(parser.getName())){
					String type = parser.nextText();
					smsInfo.setType(type);
				}else if("body".equals(parser.getName())){
					String body = parser.nextText();
					smsInfo.setBody(body);
				}
				
				break;
			case XmlPullParser.END_TAG:
                if("smsinfo".equals(parser.getName())){
					smsInfos.add(smsInfo);
					smsInfo = null;
				}
				break;

			default:
				break;
			}
			eventType = parser.next();
		}
		return smsInfos;
	}
}

3、创建备份短信的服务类BackupSmsService

这个类主要是实现备份短信的操作,将备份短信的操作放在一个服务类中执行,由于读取数据库的操作是一个耗时的操作,所以我在这个类中开启了一个线程来做短信的备份操作,如果备份短信失败,则提示用户备份失败,如果备份短信成功,则对外发出通知,提示用户短信备份成功。操作完毕后停止服务。

具体实现代码如下:

package cn.lyz.mobilesafe.service;

import java.util.List;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.Looper;
import android.widget.Toast;
import cn.lyz.mobilesafe.R;
import cn.lyz.mobilesafe.activity.MainActivity;
import cn.lyz.mobilesafe.domain.SmsInfo;
import cn.lyz.mobilesafe.engine.SmsInfoService;

/**
 * 备份短信的服务类
 * @author liuyazhuang
 *
 */
public class BackupSmsService extends Service {
	
	private SmsInfoService smsInfoService;
	private NotificationManager nm;
	
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		
		smsInfoService = new SmsInfoService(this);
		nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		new Thread(){
			public void run() {
				//1 得到所有的短信
				//2 生成一个xml文件
				List<SmsInfo> smsInfos = smsInfoService.getSmsInfos();
				
				try {
					smsInfoService.createXml(smsInfos);
					//发送一个通知告诉用户备份完成
					Notification notification = new Notification(R.drawable.notification, "短信备份完毕", System.currentTimeMillis());
					Intent intent = new Intent(getApplicationContext(),MainActivity.class);
					PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 100, intent, 0);
					notification.setLatestEventInfo(getApplicationContext(), "提示信息", "短信备份完毕", contentIntent);
					//点击通知消息自动消失
					notification.flags = Notification.FLAG_AUTO_CANCEL;
					nm.notify(100, notification);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					//looper是一个消息泵,从消息队列(MessageQueue)里面抽取消息,把消息交给Handler处理
					Looper.prepare();
					Toast.makeText(getApplicationContext(), "短信备份失败", 0).show();
					Looper.loop();
				}
				stopSelf();//停止服务
			};
		}.start();
	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

}

4、布局实现

具体实现代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        style="@style/text_title_style"
        android:text="高级工具"
       />
    
    <View style="@style/view_divide_line_style"/>
    
    <TextView android:id="@+id/tv_atools_add_ipcall"
            android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="添加ip拨号"
    android:textColor="@android:color/white"
    android:textSize="20sp"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"/>
    
    <include layout="@layout/line"/>
    
    <TextView android:id="@+id/tv_atools_address_query"
            android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="号码归属地查询"
    android:textColor="@android:color/white"
    android:textSize="20sp"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"/>
    
    <include layout="@layout/line"/>
    
    <TextView android:id="@+id/tv_atools_sms_backup"
            android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="短信备份"
    android:textColor="@android:color/white"
    android:textSize="20sp"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"/>
    
    <include layout="@layout/line"/>
    
    <TextView android:id="@+id/tv_atools_sms_restore"
            android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="短信的还原"
    android:textColor="@android:color/white"
    android:textSize="20sp"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"/>
    
    <include layout="@layout/line"/>

</LinearLayout>

5、完善Activity类

在这个类中主要完成的功能是,找到页面上的控件,并设置控件的状态事件,在相应事件中完成对业务的响应操作。

具体实现代码如下:

package cn.lyz.mobilesafe.activity;

import java.util.List;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ContentValues;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Looper;
import android.os.SystemClock;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;
import cn.lyz.mobilesafe.R;
import cn.lyz.mobilesafe.domain.SmsInfo;
import cn.lyz.mobilesafe.engine.SmsInfoService;
import cn.lyz.mobilesafe.service.BackupSmsService;

/**
 * 短信的备份与还原
 * @author liuyazhuang
 *
 */
public class AtoolsActivity extends Activity implements OnClickListener{

	private TextView tv_atools_sms_backup;
	private TextView tv_atools_sms_restore;
	private ProgressDialog mPd;
	private SmsInfoService smsInfoService;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.atools);
		
		tv_atools_sms_backup = (TextView) findViewById(R.id.tv_atools_sms_backup);
		tv_atools_sms_backup.setOnClickListener(this);
		
		tv_atools_sms_restore = (TextView) findViewById(R.id.tv_atools_sms_restore);
		tv_atools_sms_restore.setOnClickListener(this);
		smsInfoService = new SmsInfoService(this);
	}
	
	
	public void onClick(View v) {
		// TODO Auto-generated method stub
		int id = v.getId();
		Intent intent = null;
		switch (id) {
		case R.id.tv_atools_sms_backup:
			intent = new Intent(this,BackupSmsService.class);
			startService(intent);
			break;
		case R.id.tv_atools_sms_restore:
			restoreSms();

		default:
			break;
		}
	}

	/**
	 * 还原短信操作
	 */
	private void restoreSms() {
		//1 删除所有的短信
		//2 把xml里面的数据插入到短信的数据库
		   //2.1 先解析xml文件
		   //2.2 插入数据
		
		mPd = new ProgressDialog(this);
		mPd.setTitle("正在删除原来的短信");
		mPd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		mPd.show();
		
		new Thread(){
			public void run() {
				try {
					Uri uri = Uri.parse("content://sms");
					getContentResolver().delete(uri, null, null);
					mPd.setTitle("正在还原短信");
					List<SmsInfo> smsInfos = smsInfoService.getSmsInfosFromXml();
					mPd.setMax(smsInfos.size());
					for(SmsInfo smsInfo:smsInfos){
						ContentValues values = new ContentValues();
						values.put("address", smsInfo.getAddress());
						values.put("date", smsInfo.getDate());
						values.put("type", smsInfo.getType());
						values.put("body", smsInfo.getBody());
						getContentResolver().insert(uri, values);
						SystemClock.sleep(2000);
						mPd.incrementProgressBy(1);//每次进度条刻度值加1
						
					}
					mPd.dismiss();
					Looper.prepare();
					Toast.makeText(getApplicationContext(), "短信还原成功", 1).show();
					Looper.loop();
					
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					mPd.dismiss();
					Looper.prepare();
					Toast.makeText(getApplicationContext(), "短信还原失败", 1).show();
					Looper.loop();
				}
				
			};
		}.start();
	}
}

6、添加权限

别忘了向AndroidManifest.xml文件注册相应的权限

具体如下:

<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>

三、运行效果

运行界面

Android之——短信的备份与还原_第1张图片

短信备份完毕

Android之——短信的备份与还原_第2张图片

通知显示

Android之——短信的备份与还原_第3张图片

开始还原短信

Android之——短信的备份与还原_第4张图片

正在还原短信

Android之——短信的备份与还原_第5张图片

短信还原成功

Android之——短信的备份与还原_第6张图片

四、温馨提示

本实例中,为了方面,我把一些文字直接写在了布局文件中和相关的类中,大家在真实的项目中要把这些文字写在string.xml文件中,在外部引用这些资源,切记,这是作为一个Android程序员最基本的开发常识和规范,我在这里只是为了方便直接写在了类和布局文件中。

你可能感兴趣的:(android,备份,还原,短信)