130.s1-短信的备份

短信备份的原理,是用内容提供者读取短信,然后保存。

android源码中FramWork和Package是java的代码

短信存储在com.android.providers.telephoney的database中,里面有2个文件mmsms.db和一个telephoney.db中,前者是

mmsms.db表的内容如下:

type:1表示接受,2表示发生送

body表示内容

address:电话号码

date:时间

需要权限

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

布局文件

activity_advancetools.xml

<?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/TitleStyle"
        android:text="高级工具"
        />
    <TextView 
        android:layout_width="match_parent"
    	android:layout_height="wrap_content"
    	android:background="@drawable/button"
    	android:text="电话归属地查询"
    	android:textColor="@color/black"
    	android:drawableLeft="@android:drawable/ic_menu_camera"
    	android:gravity="center_vertical"
    	android:textSize="20sp"
    	android:drawablePadding="5dp"
    	android:padding="10dp"
    	android:clickable="true"
    	android:onClick="numberAddressQuery"
        />
    <TextView 
        android:layout_width="match_parent"
    	android:layout_height="wrap_content"
    	android:background="@drawable/button"
    	android:text="短信备份"
    	android:textColor="@color/black"
    	android:drawableLeft="@android:drawable/ic_menu_camera"
    	android:gravity="center_vertical"
    	android:textSize="20sp"
    	android:drawablePadding="5dp"
    	android:padding="10dp"
    	android:clickable="true"
    	android:onClick="backUpsms"
        />    

</LinearLayout>

Toast的封装UIUtils.java

package com.ldw.safe.utils;

import android.app.Activity;
import android.widget.Toast;

public class UIUtils {
	public static void showToast(final Activity context,final String msg){
		if("main".equals(Thread.currentThread().getName())){
			Toast.makeText(context, msg, 1).show();
		}else{
			context.runOnUiThread(new Runnable() {
				@Override
				public void run() {
					Toast.makeText(context, msg, 1).show();
				}
			});
		}
	}
}

布局的逻辑文件AdvancedToolsActivity.java

package com.ldw.safe.Activity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Looper;
import android.view.View;
import android.widget.Toast;

import com.ldw.safe.R;
import com.ldw.safe.utils.SmsUtils;

/*
 * 高级工具,包含归属地和短信备份
 */
public class AdvancedToolsActivity extends Activity {

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_advancedtools);
	}
	
	/*
	 * 归属地查询
	 */
	public void numberAddressQuery(View v){
		startActivity(new Intent(this, AddressActivity.class));
	}
	
	/*
	 * 短信备份的功能
	 */
	public void backUpsms(View v){
		new Thread(){
			public void run() {
				boolean result = SmsUtils.backUp(AdvancedToolsActivity.this);
				if(result){
					//子线程不能刷新UI,这种方法子线程弹出Toast
					Looper.prepare();
					Toast.makeText(AdvancedToolsActivity.this, "备份成功", Toast.LENGTH_SHORT).show();
					Looper.loop();
				}else{
					Looper.prepare();
					Toast.makeText(AdvancedToolsActivity.this, "备份失败", Toast.LENGTH_SHORT).show();
					Looper.loop();
				}
			}
		}.start();

	}
}

生成短信备份的工具文件,获取到内容观察者,读取短信,然后以xml文件的形式输出

SmsUtils.java

package com.ldw.safe.utils;

import java.io.File;
import java.io.FileOutputStream;

import org.xmlpull.v1.XmlSerializer;

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.util.Xml;

/*
 * 短信的工具类,用于短信备份
 */
public class SmsUtils {

	public static boolean backUp(Context context){
		
		/*
		 * 1.先判断是否有sd卡,
		 * 2.权限是---因此必须使用内容观察者读取
		 * 3.写短信
		 */
		//判断sd卡的状态
		if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
			
			//sd卡存在,获取到内容观察者
			ContentResolver resolver = context.getContentResolver();
			// 获取短信的路径
			Uri uri = Uri.parse("content://sms/");
			//通过内容观察着,读取短信内容,type:1接受短信,2发送短信
			Cursor cursor = resolver.query(uri, new String[]{"address", "date", "type", "body"}, null, null, null);
			//短信的数量
			int count = cursor.getCount();
			
			//写文件
			try {
				//创建保存的短信备份的文件的名字
				File file = new File(Environment.getExternalStorageDirectory(), "smsbackup.xml");
				
				FileOutputStream os = new FileOutputStream(file);
				//xml序列化器,xml解析是pull解析
				XmlSerializer serializer = Xml.newSerializer();
				//短信序列化到sd卡,设置编码格式
				serializer.setOutput(os, "utf-8");
				// standalone表示当前的xml是否是独立文件 ture表示文件独立。yes
				serializer.startDocument("utf-8", true);
				// 设置开始的节点 第一个参数是命名空间。第二个参数是节点的名字
				serializer.startTag(null, "smss");
				//设置smss节点上面的属性值 第二个参数是名字。第三个参数是值
				serializer.attribute(null, "size", String.valueOf(count));
				
				//读取短信数据
				while (cursor.moveToNext()) {
					System.err.println("----------------------------");
					System.out.println("address = " + cursor.getString(0));
					System.out.println("date = " + cursor.getString(1));
					System.out.println("type = " + cursor.getString(2));
					System.out.println("body = " + cursor.getString(3));
					
					serializer.startTag(null, "sms");
					serializer.startTag(null, "address");
					// 设置文本的内容
					serializer.text(cursor.getString(0));
					serializer.endTag(null, "address");
					serializer.startTag(null, "date");
					serializer.text(cursor.getString(1));
					serializer.endTag(null, "date");
					serializer.startTag(null, "type");
					serializer.text(cursor.getString(2));
					serializer.endTag(null, "type");
					serializer.startTag(null, "body");
					serializer.endTag(null, "body");
					 //读取短信的内容
					/**
					 * 加密:第一个参数表示加密种子(密钥)
					 *     第二个参数表示加密的内容
					 */
					serializer.text(Crypto.encrypt("123", cursor.getString(3)));
					serializer.endTag(null, "sms");
				}
				cursor.close();
				serializer.endTag(null, "smss");
				serializer.endDocument();
				os.flush();	
				os.close();
				return true;
				
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			


		}
		return false;
	}
}

中间需要调用一个Crypto.java的文件(可以用来加密,github)

package com.ldw.safe.utils;


import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import android.util.Base64;
/**
*
* ━━━━━━神兽出没━━━━━━
*    ┏┓   ┏┓
*   ┏┛┻━━━┛┻┓
*   ┃       ┃
*   ┃   ━   ┃
*   ┃ ┳┛ ┗┳ ┃
*   ┃       ┃
*   ┃   ┻   ┃
*   ┃       ┃
*   ┗━┓   ┏━┛Code is far away from bug with the animal protecting
*     ┃   ┃    神兽保佑,代码无bug
*     ┃   ┃
*     ┃   ┗━━━┓
*     ┃       ┣┓
*     ┃       ┏┛
*     ┗┓┓┏━┳┓┏┛
*      ┃┫┫ ┃┫┫
*      ┗┻┛ ┗┻┛
*
* ━━━━━━感觉萌萌哒━━━━━━
*/
public class Crypto {
	/**
	 * Encrypt plain string and encode to Base64
	 * 
	 * @param seed
	 * @param plain
	 * @return
	 * @throws Exception
	 */
	public static String encrypt(String seed, String plain) throws Exception {
		byte[] rawKey = getRawKey(seed.getBytes());
		byte[] encrypted = encrypt(rawKey, plain.getBytes());
		return Base64.encodeToString(encrypted, Base64.DEFAULT);
	}

	/**
	 * Decrypt Base64 encoded encrypted string
	 * 
	 * @param seed
	 * @param encrypted
	 * @return
	 * @throws Exception
	 */
	public static String decrypt(String seed, String encrypted)
			throws Exception {
		byte[] rawKey = getRawKey(seed.getBytes());
		byte[] enc = Base64.decode(encrypted.getBytes(), Base64.DEFAULT);
		byte[] result = decrypt(rawKey, enc);
		return new String(result);
	}

	private static byte[] getRawKey(byte[] seed) throws Exception {
		KeyGenerator keygen = KeyGenerator.getInstance("AES");
		SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
		random.setSeed(seed);
		keygen.init(128, random); // 192 and 256 bits may not be available
		SecretKey key = keygen.generateKey();
		byte[] raw = key.getEncoded();
		return raw;
	}

	private static byte[] encrypt(byte[] raw, byte[] plain) throws Exception {
		SecretKeySpec keySpec = new SecretKeySpec(raw, "AES");
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.ENCRYPT_MODE, keySpec);
		byte[] encrypted = cipher.doFinal(plain);
		return encrypted;
	}

	private static byte[] decrypt(byte[] raw, byte[] encrypted)
			throws Exception {
		SecretKeySpec keySpec = new SecretKeySpec(raw, "AES");
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.DECRYPT_MODE, keySpec);
		byte[] decrypted = cipher.doFinal(encrypted);
		return decrypted;
	}
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值