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.
Теперь попробуем написать...[Продолжение следует]