извлечение значений из SharedPreferences после переустановки и с помощью allowBackup = true с помощью Android Auto backup


9

У меня проблемы с получением значений (на устройстве Android 9.0) из общих настроек после того, как я переустановил приложение и у меня было allowBackup = true.

<manifest ... >
    ...
    <application android:allowBackup="true" ... >
        ...
    </application>
</manifest>

Согласно этому: https://developer.android.com/guide/topics/data/autobackup

Общие настройки должны быть восстановлены?

    SharedPreferences prefs = getSharedPreferences("TEST", MODE_PRIVATE);
    String name = prefs.getString("name", "No name defined");//"No name defined" is the default value.
    int idName = prefs.getInt("idName", 0); //0 is the default value.

    SharedPreferences.Editor editor = getSharedPreferences("TEST", MODE_PRIVATE).edit();
    editor.putString("name", "Elena");
    editor.putInt("idName", 12);
    editor.apply();
  • Я вошел в свою учетную запись Gmail на (эмуляторе) телефона (API 27), и при переходе в приложение Drive, резервные копии, данные приложения я вижу 18 приложений, таких как Youtube, Gmail и т. Д., А также свое собственное приложение.
  • Когда я захожу в «Настройки> Система> Резервное копирование», я вижу те же приложения, а также свое собственное приложение. Я загружаю приложение, код sharedprefs выполняется. Я закрываю приложение и удаляю его из памяти. И тогда я нажимаю кнопку «Резервное копирование сейчас»:

введите описание изображения здесь

Чтобы убедиться, что я вижу свое приложение в списке, оно получило резервную копию 0 минут назад:

введите описание изображения здесь

Затем я удаляю и переустанавливаю приложение и ожидаю, что 2 значения (Елена и 12) будут там. Но они стерты ...

Я также попробовал то же самое через командную строку, но тоже не работает: https://developer.android.com/guide/topics/data/testingbackup.html#Preparing

adb shell
dreamlte:/ $ bmgr enabled
Backup Manager currently enabled
dreamlte:/ $ bmgr list transports
    android/com.android.internal.backup.LocalTransport
    com.google.android.gms/.backup.migrate.service.D2dTransport
* com.google.android.gms/.backup.BackupTransportService
dreamlte:/ $ bmgr backupnow my.package.name
Running incremental backup for 1 requested packages.
Package @pm@ with result: Success
Package nl.dagelijkswoord.android with progress: 1536/309248
Package nl.dagelijkswoord.android with result: Success
Backup finished with result: Success

dreamlte:/ $ dumpsys backup
Backup Manager is enabled / provisioned / not pending init
Auto-restore is disabled
No backups running
Last backup pass started: 1573804513565 (now = 1573806675410)
  next scheduled: 1573819001046
...
1573806051616 : my.package.name

dreamlte:/ $ bmgr restore 1573806051616 my.package.name                                                                                                            
No matching restore set token.  Available sets:
  35e84268c94b7d9c : SM-G950F
  3a8e32898034f8af : SM-G950F
  3e2610c4ea45fb96 : Nexus 5X
done

dreamlte:/ $ bmgr restore 35e84268c94b7d9c my.package.name                                                                                                         
Scheduling restore: SM-G950F
restoreStarting: 1 packages
onUpdate: 0 = my.package.name 
restoreFinished: 0
done
  1. Удалить приложение
  2. Переустановите приложение и проверьте, сохраняются ли значения SharedPreferences.
  3. Ценности ушли ...

Поведение также, кажется, отличается на устройствах Samsung с Samsung Cloud, но сейчас давайте сосредоточимся на стандартном Android.

ОБНОВИТЬ:

Это больше не работало, потому что я понизил версию в build.gradle:

build.gradle:
versionCode 70
versionName "1.6.1"

Даже с android:restoreAnyVersion="true"в AndroidManifestон будет работать только тогда, когда версия не была понижена.


Это может помочь вам сделать резервную копию общих настроек в Android
PraveenSP

Здравствуйте @PraveenSP Я хочу использовать Android Auto Backup, а не более старую версию хранилища ключей / значений.
Джим Клермонтс

Ответы:


1

По умолчанию система Android выполняет резервное копирование всех данных по умолчанию, если устройство подключено к сети Wi-Fi (если пользователь устройства не включил резервное копирование мобильных данных), попробуйте переустановить приложение и подключиться с помощью WI-FI, как правило, с помощью системы синхронизации Android. данные один раз в 24 часа, если есть какие-либо изменения. Вы также можете попытаться указать свои собственные правила для резервного копирования, как это.

`<application 
 android:fullBackupContent="@xml/backup_rules">
</application>`

и создайте XML-файл и поместите его в каталог res / xml. Внутри файла добавьте правила с элементами и. В следующем примере выполняется резервное копирование всех общих настроек, кроме device.xml.

`<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
</full-backup-content>`

Я надеюсь, что это решит вашу проблему.


Я просто хочу сохранить sharedprefs, без XML.
Джим Клермонтс

Приведенный выше код представляет собой правила для системы Android для сохранения данных на диске пользователя, он не будет сохраняться в формате XML, тег «Включить и исключить» уведомляет систему о том, какие данные необходимо синхронизировать и сохранить, а какие - исключить в операции синхронизации. ,
Ашиш Шривастава

Я понимаю, но это ненужно, я думаю?
Джим Клермонтс

1
я не думаю, что это излишняя причина того, что при завершении загрузки системы Android он проверяет все правила приложений, настроенные в манифесте по умолчанию, он также синхронизируется, когда allowBackup имеет значение true, но когда мы пишем правила, система Android сохраняет локальные правила и связывает его с именем пакета.
Ашиш Шривастава

Я добавил приведенный выше код XML, но это не имеет значения.
Джим Клермонтс

1

В соответствии с документом возврата данных вам необходимо создать SharedPreferencesBackupHelper и выполнить следующие шаги, чтобы выполнить резервное копирование SharedPreferences, а также необходимо зарегистрировать службы резервного копирования для вашего случая.


Здравствуйте, я говорю об Android Auto Backup, а не о сервисе резервного копирования Android.
Джим Клермонтс

это связано только с автоматическим резервным копированием. для образца вы можете следовать эти шаги codelabs.developers.google.com/codelabs/android-backup-codelab/...
Damodhar

1

Пусть эта процедура будет работать для вас. Попробуйте выполнить резервное копирование и восстановление общих настроек пользователя. Это создаст резервную копию ваших предпочтений для любого внешнего хранилища или устройства.

Когда пользователь удаляет приложение, пользователь должен создать его резервную копию. Добавьте некоторую логику: если файл присутствует во внешнем хранилище или устройстве, восстановите его обратно.

используйте приведенный ниже код для резервного копирования ваших предпочтений.

public static void backupUserPrefs(Context context) {
    final File prefsFile = new File(context.getFilesDir(), "../shared_prefs/" + context.getPackageName() + "_preferences.xml");
    final File backupFile = new File(context.getExternalFilesDir(null),
        "preferenceBackup.xml");
    String error = "";

    try {
        FileChannel src = new FileInputStream(prefsFile).getChannel();
        FileChannel dst = new FileOutputStream(backupFile).getChannel();

        dst.transferFrom(src, 0, src.size());

        src.close();
        dst.close();

        Toast toast = Toast.makeText(context, "Backed up user prefs to " + backupFile.getAbsolutePath(), Toast.LENGTH_SHORT);
        toast.show();
        return;
    } catch (FileNotFoundException e) {
        error = e.getMessage();
        e.printStackTrace();
    } catch (IOException e) {
        error = e.getMessage();
        e.printStackTrace();
    }

используйте приведенный ниже код для восстановления настроек

public static boolean restoreUserPrefs(Context context) {
    final File backupFile = new File(context.getExternalFilesDir(null),
        "preferenceBackup.xml");
    String error = "";

    try {

        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);

        Editor editor = sharedPreferences.edit();

        InputStream inputStream = new FileInputStream(backupFile);

        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

        Document doc = docBuilder.parse(inputStream);
        Element root = doc.getDocumentElement();

        Node child = root.getFirstChild();
        while (child != null) {
            if (child.getNodeType() == Node.ELEMENT_NODE) {

                Element element = (Element) child;

                String type = element.getNodeName();
                String name = element.getAttribute("name");

                // In my app, all prefs seem to get serialized as either "string" or
                // "boolean" - this will need expanding if yours uses any other types!    
                if (type.equals("string")) {
                    String value = element.getTextContent();
                    editor.putString(name, value);
                } else if (type.equals("boolean")) {
                    String value = element.getAttribute("value");
                    editor.putBoolean(name, value.equals("true"));
                }
            }

            child = child.getNextSibling();

        }

        editor.commit();

        Toast toast = Toast.makeText(context, "Restored user prefs from " + backupFile.getAbsolutePath(), Toast.LENGTH_SHORT);
        toast.show();

        return true;

    } catch (FileNotFoundException e) {
        error = e.getMessage();
        e.printStackTrace();
    } catch (ParserConfigurationException e) {
        error = e.getMessage();
        e.printStackTrace();
    } catch (SAXException e) {
        error = e.getMessage();
        e.printStackTrace();
    } catch (IOException e) {
        error = e.getMessage();
        e.printStackTrace();
    }

    Toast toast = Toast.makeText(context, "Failed to restore user prefs from " + backupFile.getAbsolutePath() + " - " + error, Toast.LENGTH_SHORT);
    toast.show();

    return false;
}


    Toast toast = Toast.makeText(context, "Failed to Back up user prefs to " + backupFile.getAbsolutePath() + " - " + error, Toast.LENGTH_SHORT);
    toast.show();

}

затем перезапустите приложение, прежде чем эти преференции вступят в силу

if (restoreUserPrefs(context)) {
    // Restart              
    AlarmManager alm = (AlarmManager) context.getSystemService(
    Context.ALARM_SERVICE);
    alm.set(AlarmManager.RTC,
    System.currentTimeMillis() + 1000, PendingIntent.getActivity(context, 0,
    new Intent(context, MainActivityName.class), 0));
    android.os.Process.sendSignal(android.os.Process.myPid(),
    android.os.Process.SIGNAL_KILL);
}

Здравствуйте, проблема заключалась в том, что он не выполняет резервное копирование, когда мой versionCode в build.gradle понижен. Вот почему это не сработало. Этот большой код не нужен для хранения только простой строки.
Джим Клермонтс

работал для меня ... спас мой день ... спасибо
unownsp

0

Вы не включили параметры автоматического восстановления, как показано в сообщении консоли. Вам нужно зайти в настройки системы и включить ее. После этого реставрация может заработать.

Настройки -> Резервное копирование -> Автоматическое восстановление.

Кстати, используемый вами токен неверен. 1573806051616 - это метка времени вместо токена. Маркер должен выглядеть так:

Ancestral packages: none
Ever backed up: XXXXXXXXXXXXXXXX

Здесь XXXXXXXXXXXXXXXXдолжен быть токен.


-1

Чтобы проверить восстановление, вам нужно запустить приведенную ниже команду, не удаляя ваше приложение. Команда восстановления заставит остановить приложение, стереть его данные и выполнить восстановление, следовательно имитируя функциональность AutoBackup Android:

bmgr restore <TOKEN> <PACKAGE>

TOKENизвлекается из logcatкоманды при выполнении команды резервного копирования или из dumpsys backupкоманды. Также вы можете проверить, dumpsys backupчтобы убедиться, что резервная копия была создана.

Более подробная информация здесь: https://developer.android.com/guide/topics/data/testingbackup.html#TestingRestore


Я попробовал это и отредактировал ответ, но значения sharedpref все еще пропали.
Джим Клермонтс

Есть несколько предварительных условий для резервного копирования. Пожалуйста, проверьте ниже ссылку :: blog.devknox.io/…
Susheel Tickoo

Предварительные условия выполнены, и это не работает.
Джим Клермонтс

-1

Один из способов сделать это заключается в следующем (обратите внимание, это может быть не лучшим способом, но это работает!)

Перед удалением приложения сделайте резервную копию. Добавьте некоторую логику: если файл присутствует во внешнем хранилище , восстановите его обратно.

Настройки, хранящиеся в классе SharedPreferences, сохраняются в /data/data//shared_prefs/_preferences.xml - резервное копирование легко, вам просто нужно скопировать содержимое этого файла на внешнее хранилище:

public static void backupUserPrefs(Context context) {
final File prefsFile = new File(context.getFilesDir(), "../shared_prefs/" + context.getPackageName() + "_preferences.xml");
final File backupFile = new File(context.getExternalFilesDir(null),
    "preferenceBackup.xml");
String error = "";

try {
    FileChannel src = new FileInputStream(prefsFile).getChannel();
    FileChannel dst = new FileOutputStream(backupFile).getChannel();

    dst.transferFrom(src, 0, src.size());

    src.close();
    dst.close();

    Toast toast = Toast.makeText(context, "Backed up user prefs to " + backupFile.getAbsolutePath(), Toast.LENGTH_SHORT);
    toast.show();
    return;
} catch (FileNotFoundException e) {
    error = e.getMessage();
    e.printStackTrace();
} catch (IOException e) {
    error = e.getMessage();
    e.printStackTrace();
}

Используйте следующий код для восстановления настроек

Но восстановление представляет собой более сложную задачу, так как файл shared_prefs не может напрямую записываться приложением, а класс SharedPrefs не предоставляет напрямую свою функциональность для сериализации из XML. Вместо этого вы должны самостоятельно проанализировать XML и вставить значения обратно. К счастью, XML-файл имеет простую структуру, так что легко зациклить элементы и превратить их обратно в настройки.

if (restoreUserPrefs(context)) {
// Restart              
AlarmManager alm = (AlarmManager) context.getSystemService(
Context.ALARM_SERVICE);
alm.set(AlarmManager.RTC,
System.currentTimeMillis() + 1000, PendingIntent.getActivity(context, 0,
new Intent(context, MainActivityName.class), 0));
android.os.Process.sendSignal(android.os.Process.myPid(),
android.os.Process.SIGNAL_KILL);
}

ПРИМЕЧАНИЕ . Требуется разрешение на запись и чтение во внешнем хранилище.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.