package com.ittianyu.mobileguard.engine;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ittianyu.mobileguard.R;
import com.ittianyu.mobileguard.domain.ContactBackupBean;
import com.ittianyu.mobileguard.domain.SmsBackupBean;
import com.ittianyu.mobileguard.utils.FileUtils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by yu.
* Provide contacts and sms backup.
*/
public class BackupRestoreEngine {
private static final String CONTENT_SMS = "content://sms";
/**
* backup contacts
* @param context
* @param dir the directory of backup files
* @return true if success, false otherwise
*/
public static boolean backupContacts(final Context context, File dir) {
// contacts directory
File contactsDir = new File(dir.getAbsolutePath() + "/contacts");
// if directory not exist, create it
if(!contactsDir.isDirectory()) {
boolean mkdir = contactsDir.mkdir();
System.out.println("contactsDir create:" + mkdir);
}
// query contacts
List<ContactBackupBean> contacts = queryContacts(context);
if(contacts.size() == 0) {
// Message.obtain(handler, MSG_TOAST, R.string.tips_no_data_to_backup).sendToTarget();
System.out.println(context.getString(R.string.tips_no_data_to_backup));
return false;
}
// generate json
Gson gson = new Gson();
String json = gson.toJson(contacts);
System.out.println(json);
// save file
// get file name
String fileName = generateFileName() + ".json";
try {
FileUtils.saveFileWithString(new File(contactsDir, fileName), json);
} catch (IOException e) {
e.printStackTrace();
System.out.println(context.getString(R.string.failed_to_save_file));
// Message.obtain(handler, MSG_TOAST, R.string.failed_to_save_file).sendToTarget();
return false;
}
return true;
}
/**
* restore sms
* @param context
* @param backupFile the backup file
* @return true if success, false otherwise
*/
public static boolean restoreContacts(final Context context, File backupFile) {
FileReader reader = null;
try {
reader = new FileReader(backupFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
// Message.obtain(handler, MSG_TOAST, R.string.file_not_found).sendToTarget();
System.out.println(context.getString(R.string.file_not_found));
// Toast.makeText(context, R.string.file_not_found, Toast.LENGTH_SHORT).show();
return false;
}
// parse json
Gson gson = new Gson();
List<ContactBackupBean> contacts = gson.fromJson(reader, new TypeToken<List<ContactBackupBean>>(){}.getType());
System.out.println(contacts);
if(contacts.size() == 0) {
// Toast.makeText(context, R.string.tips_no_data_to_restore, Toast.LENGTH_SHORT).show();
// Message.obtain(handler, MSG_TOAST, R.string.tips_no_data_to_restore).sendToTarget();
System.out.println(context.getString(R.string.tips_no_data_to_restore));
return false;
}
// restore contacts database
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
// delete all data and raw_contacts
ops.add(ContentProviderOperation.newDelete(Data.CONTENT_URI).build());
ops.add(ContentProviderOperation.newDelete(RawContacts.CONTENT_URI).build());
try {
context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
ops.clear();
}
for (ContactBackupBean contact: contacts) {
// add to raw_contacts
ops.add(ContentProviderOperation
.newInsert(RawContacts.CONTENT_URI)
.withValue(RawContacts.ACCOUNT_NAME, contact.getAccountName())
.withValue(RawContacts.ACCOUNT_TYPE, contact.getAccountType())
.build());
// add to data
for (ContactBackupBean.ContactBackupDataBean data: contact.getDatas()) {
ops.add(ContentProviderOperation
.newInsert(Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(Data.MIMETYPE, data.getMimetype())
.withValue(Data.DATA1, data.getData())
.build());
}
// apply batch
try {
context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
} catch (Exception e) {
e.printStackTrace();
// Toast.makeText(context, R.string.failed_to_restore, Toast.LENGTH_SHORT).show();
// Message.obtain(handler, MSG_TOAST, R.string.failed_to_restore).sendToTarget();
System.out.println(context.getString(R.string.failed_to_restore));
return false;
} finally {
// never forget to clear when success to insert a contact
ops.clear();
}
}
return true;
}
/**
* backup sms
* @param context
* @param dir the directory of backup files
* @return true if success, false otherwise
*/
public static boolean backupSms(Context context, File dir) {
// contacts directory
File smsDir = new File(dir.getAbsolutePath() + "/sms");
// if directory not exist, create it
if(!smsDir.isDirectory()) {
boolean mkdir = smsDir.mkdir();
System.out.println("smsDir create:" + mkdir);
}
// query contacts
List<SmsBackupBean> smses = querySms(context);
if(smses.size() == 0) {
System.out.println(context.getString(R.string.tips_no_data_to_backup));
return false;
}
// generate json
Gson gson = new Gson();
String json = gson.toJson(smses);
System.out.println(json);
// save to file
// get file name
String fileName = generateFileName() + ".json";
try {
FileUtils.saveFileWithString(new File(smsDir, fileName), json);
} catch (IOException e) {
e.printStackTrace();
System.out.println(context.getString(R.string.failed_to_save_file));
return false;
}
return true;
}
/**
* restore sms
* @param context
* @param backupFile the backup file
* @return true if success, false otherwise
*/
public static boolean restoreSms(final Context context, File backupFile) {
FileReader reader = null;
try {
reader = new FileReader(backupFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println(context.getString(R.string.file_not_found));
return false;
}
// parse json
Gson gson = new Gson();
List<SmsBackupBean> smses = gson.fromJson(reader, new TypeToken<List<SmsBackupBean>>(){}.getType());
System.out.println(smses);
if(smses.size() == 0) {
System.out.println(context.getString(R.string.tips_no_data_to_restore));
return false;
}
// start restore
for (SmsBackupBean sms: smses) {
ContentValues values = new ContentValues(sms.getDatas().size());
// add data to ContentValues
for (SmsBackupBean.Data data: sms.getDatas()) {
values.put(data.getKey(), data.getValue());
}
// query the sms whether exist
Cursor cursor = context.getContentResolver().query(
Uri.parse(CONTENT_SMS),
new String[]{"_id"},
"address =? and body=? and date=?",
new String[]{values.getAsString("address"),
values.getAsString("body"),
values.getAsString("date")},
null);
// if the sms not exist, insert it
if (cursor.getCount() == 0) {
context.getContentResolver().insert(
Uri.parse(CONTENT_SMS), values);
System.out.println("success restore a sms");
}
cursor.close();// never forget close
}
return true;
}
/**
* generate file by current time
*/
private static String generateFileName() {
return System.currentTimeMillis() + "";
}
/**
* query all contacts that not deleted
* @param context
* @return return a list which would not be null.
*/
public static List<ContactBackupBean> queryContacts(Context context) {
// create a list to contain contact bean
List<ContactBackupBean> contacts = new ArrayList<>();
// start to query
ContentResolver resolver = context.getContentResolver();
Cursor contactCursor = resolver
.query(RawContacts.CONTENT_URI,
new String[]{RawContacts._ID, RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE},
RawContacts.DELETED + "!=1", // the deleted contacts should not backup
null, null);
while (contactCursor.moveToNext()) {
// create bean and add to list
ContactBackupBean contact = new ContactBackupBean();
contacts.add(contact);
// read value
int id = contactCursor.getInt(0);
String accountName = contactCursor.getString(1);
String accountType = contactCursor.getString(2);
// set to bean
contact.setAccountName(accountName);
contact.setAccountType(accountType);
// create datas bean and set datas to bean
List<ContactBackupBean.ContactBackupDataBean> datas = new ArrayList<>();
contact.setDatas(datas);
// query data
Cursor dataCursor = resolver
.query(ContactsContract.Data.CONTENT_URI,
new String[]{Data._ID, Data.MIMETYPE, Data.DATA1},
Data.RAW_CONTACT_ID + "=? and " + Data.DATA1 + " not null",
new String[]{id + ""},
null);
while (dataCursor.moveToNext()) {
// get value
String mimetype = dataCursor.getString(1);
String data = dataCursor.getString(2);
// create data bean and add to datas
ContactBackupBean.ContactBackupDataBean dataBean = new ContactBackupBean.ContactBackupDataBean(mimetype, data);
datas.add(dataBean);
}
dataCursor.close();
}
contactCursor.close();
return contacts;
}
/**
* query all sms
* @param context
* @return return a list which would not be null.
*/
public static List<SmsBackupBean> querySms(Context context) {
// create a list to contain contact bean
List<SmsBackupBean> smses = new ArrayList<>();
// select all sms
Cursor cursor = context.getContentResolver()
.query(android.net.Uri.parse(CONTENT_SMS)
, null, null, null, null);
// record all column and value
int colCount = cursor.getColumnCount();
while (cursor.moveToNext()) {
// create sms and add to list
SmsBackupBean sms = new SmsBackupBean();
smses.add(sms);
// create sms datas and set it
List<SmsBackupBean.Data> datas = new ArrayList<>();
sms.setDatas(datas);
// start from 2, for detail to see the database
for (int i = 2; i < colCount; i++) {
String name = cursor.getColumnName(i);
String value = cursor.getString(i);
// System.out.println(name + ":" + value);
// create data and add to datas
datas.add(new SmsBackupBean.Data(name, value));
}
}
cursor.close();
return smses;
}
}