October 8, 2018
Импорт и экспорт данных приложения. Теория.
Порой нам бывает необходимо восстановить некоторые настройки приложения. Это просто делается вручную, но что если в приложении десятки, а то и сотни независимых настроек? На многих устройствах нет рута, с adb не каждый разберется. Так что же делать? Сейчас узнаем.
Данный код будет работать при 2-х условиях:
- Наличие разрешения на запись
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
- В настройках системы тоже должен быть предоставлен доступ
Создадим класс BackupFactory.java:
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class BackupFactory {
// Экспорт БД
public static void exportDb(Activity activity, String dbFiles) {
ContextWrapper contextWrapper = new ContextWrapper(activity);
// Преобразование строки в массив
String[] dbs = dbFiles.split(",");
// Экспорт каждого отдельного файла
for (String db : dbs) {
File expDb = contextWrapper.getDatabasePath(db);
exportFile(expDb, activity);
}
}
//Импорт БД
public static void importDb(Activity activity, String dbFiles) {
ContextWrapper contextWrapper = new ContextWrapper(activity);
// Преобразование строки в массив
String[] dbs = dbFiles.split(",");
// Импорт каждого отдельного файла
for (String db : dbs) {
File expDb = contextWrapper.getDatabasePath(db);
importFile(expDb, activity);
}
}
// Экспорт файла настроек
public static void exportPrefs(Activity activity) {
ApplicationInfo info = activity.getApplicationInfo();
String dir = new ContextWrapper(activity).getCacheDir().getParent();
File prefs = new File(dir, "shared_prefs/" + info.packageName + "_preferences.xml");
exportFile(prefs, activity);
}
// Импорт файла настроек
public static void importPrefs(Activity activity) {
ApplicationInfo info = activity.getApplicationInfo();
String dir = new ContextWrapper(activity).getCacheDir().getParent();
File prefs = new File(dir, "shared_prefs/" + info.packageName + "_preferences.xml");
importFile(prefs, activity);
}
// Экспорт файла
private static void exportFile(File file, Activity activity) {
// Если нет разрешения на запись
if (!isExternalStorageWritable() || !canWriteStorage(activity)) {
Toast.makeText(activity, "Нет разрешения на чтение/запись!", Toast.LENGTH_SHORT).show();
return;
}
File backup = new File(getFolder(), file.getName());
// Перезаписываем существующий файл
if (backup.exists()) {
backup.delete();
}
if (copy(file, backup)) {
Toast.makeText(activity, "Успешно!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(activity, "Ошибка!", Toast.LENGTH_SHORT).show();
}
}
// Импорт файла
private static void importFile(File file, Activity activity) {
// Если нет разрешения на запись
if (!isExternalStorageReadable() || !canWriteStorage(activity)) {
Toast.makeText(activity, "Нет разрешения на чтение/запись!", Toast.LENGTH_SHORT).show();
return;
}
File backup = new File(getFolder(), file.getName());
if (!backup.exists()) {
Toast.makeText(activity, "Файлы бэкапа отсутствуют!", Toast.LENGTH_LONG).show();
return;
}
if (file.exists()) {
file.delete();
}
// Всё хорошо
if (copy(backup, file)) {
Toast.makeText(activity, "Успешно!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(activity, "Ошибка!", Toast.LENGTH_SHORT).show();
}
}
// Получение пути к папке бэкапов
// [SDCARD]/Documents/backup/
private static File getFolder() {
File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "backup");
if (!folder.exists()) {
folder.mkdirs();
}
return folder;
}
// Проверка на возможность записи
private static boolean canWriteStorage(Activity activity) {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED;
}
// Копирование файлов тудым-сюдым
private static boolean copy(File inFile, File outFile) {
FileInputStream in;
FileOutputStream out;
try {
in = new FileInputStream(inFile);
out = new FileOutputStream(outFile);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
// write the output file
out.flush();
out.close();
return true;
} catch (Exception e) {
Log.e("BackupFactory", e.getMessage());
}
return false;
}
/* Checks if external storage is available for read and write */
private static boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
return Environment.MEDIA_MOUNTED.equals(state);
}
/* Checks if external storage is available to at least read */
private static boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
return Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state);
}
Я добавил комментарии к коду. Основных метода 4 - импорт/экспорт БД, импорт/экспорт настроек. Файлов БД может быть несколько, указывать их надо через запятую "test.db,sec.db" etc.
Теперь попробуем написать...[Продолжение следует]