130.短信的备份

来源:互联网 发布:中国的顶级域名 编辑:程序博客网 时间:2024/05/16 16:56

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

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() {@Overridepublic 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,这种方法子线程弹出ToastLooper.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表示文件独立。yesserializer.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 blocke.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 availableSecretKey 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;}}



0 0