récupération des valeurs de SharedPreferences après la réinstallation et avec allowBackup = true à l'aide de la sauvegarde Android Auto

9

J'ai du mal à récupérer des valeurs (sur un appareil Android 9.0) à partir des préférences partagées après avoir réinstallé l'application et tout en ayant allowBackup = true.

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

Selon cela: https://developer.android.com/guide/topics/data/autobackup

Les préférences partagées devraient être restaurées?

    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();
  • Je me suis connecté à mon compte Gmail sur le téléphone (émulateur) (API 27) et lorsque je vais à l'application Drive, aux sauvegardes, aux données d'application, je vois 18 applications telles que Youtube, Gmail, etc. et également ma propre application.
  • Lorsque je vais dans "Paramètres> Système> Sauvegarde", je vois les mêmes applications et aussi ma propre application. Je charge l'application, le code sharedprefs est exécuté. Je ferme l'application et la supprime de la mémoire. Et puis j'appuie sur le bouton "Sauvegarder maintenant":

entrez la description de l'image ici

Pour vérifier, je peux voir mon application dans la liste et elle a été sauvegardée il y a 0 minutes:

entrez la description de l'image ici

Ensuite, je supprime et réinstalle l'application et je m'attends à ce que les 2 valeurs (Elena et 12) soient là. Mais ils sont effacés ...

J'ai également essayé la même chose via la ligne de commande, mais ne fonctionnait pas non plus: 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. Supprimer l'application
  2. Réinstallez l'application et vérifiez si les valeurs SharedPreferences sont toujours là.
  3. Les valeurs ont disparu ...

Le comportement semble également différer sur les appareils Samsung avec Samsung Cloud, mais pour l'instant concentrons-nous sur le stock Android.

MISE À JOUR:

Cela ne fonctionnait plus car j'ai rétrogradé la version dans build.gradle:

build.gradle:
versionCode 70
versionName "1.6.1"

Même avec android:restoreAnyVersion="true"le, AndroidManifestcela ne fonctionnerait que lorsque la version n'était pas rétrogradée.

Jim Clermonts
la source
Cela pourrait vous aider à sauvegarder des préférences partagées dans Android
PraveenSP
Bonjour @PraveenSP Je souhaite utiliser la sauvegarde Android Auto et non l'ancienne version du magasin de clés / valeurs.
Jim Clermonts

Réponses:

1

Par défaut, le système Android sauvegarde toutes les données par défaut si l'appareil est connecté à un réseau Wi-Fi (si l'utilisateur de l'appareil n'a pas opté pour les sauvegardes de données mobiles), essayez de réinstaller l'application et connectez-vous avec le WI-FI, généralement la synchronisation du système Android les données une fois toutes les 24 heures s'il y a des changements. Vous pouvez également essayer de spécifier vos propres règles de sauvegarde comme celle-ci.

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

et créez un fichier xml et placez-le dans le répertoire res / xml. A l'intérieur du fichier, ajoutez des règles avec les éléments et. L'exemple suivant sauvegarde toutes les préférences partagées à l'exception de 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>`

J'espère que cela résoudra votre problème.

Ashish srivastava
la source
Je veux simplement enregistrer sharedprefs, pas de xml.
Jim Clermonts
Le code ci-dessus est des règles pour que le système Android enregistre les données sur le lecteur utilisateur, il ne sera pas enregistré au format XML, la balise Include & Exclude notifie au système les données à synchroniser et à enregistrer et les données à exclure lors de l'opération de synchronisation. .
Ashish srivastava
Je comprends mais c'est inutile je pense?
Jim Clermonts
1
Je ne pense pas, c'est inutile parce que le démarrage du système Android s'est terminé, il vérifie toutes les règles des applications configurées dans le manifeste par défaut, il se synchronise également lorsque allowBackup est vrai, mais lorsque nous écrivons des règles, le système Android reste dans les règles locales et l'associons au nom du package.
Ashish srivastava
J'ai ajouté le code XML ci-dessus mais cela ne fait aucune différence.
Jim Clermonts
1

Conformément au document de sauvegarde des données, vous devez créer SharedPreferencesBackupHelper et suivre ces étapes pour obtenir une sauvegarde SharedPreferences également besoin d' enregistrer les services de sauvegarde pour votre cas.

Damodhar
la source
Bonjour, je parle d'Android Auto Backup, pas du service de sauvegarde Android.
Jim Clermonts
c'est lié à la sauvegarde automatique uniquement. pour l'exemple, vous pouvez suivre ces étapes codelabs.developers.google.com/codelabs/android-backup-codelab/…
Damodhar
1

Que cette procédure fonctionne pour vous. Essayez de sauvegarder et de restaurer les préférences partagées d'un utilisateur. Cela sauvegardera vos préférences sur n'importe quel stockage externe ou appareil.

Lorsque l'utilisateur désinstalle l'application, l'utilisateur doit la sauvegarder. Ajoutez une logique selon laquelle si le fichier est présent dans le stockage externe ou le périphérique, restaurez-le.

utilisez le code ci-dessous pour sauvegarder votre préférence.

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();
    }

utilisez le code ci-dessous pour restaurer les préférences

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();

}

puis redémarrez votre application avant que ces préférences ne s'installent

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);
}
UD ..
la source
Bonjour, le problème était qu'il ne sauvegarde pas lorsque mon versionCode dans build.gradle est déclassé. Voilà pourquoi cela ne fonctionnait pas. Cette quantité de code n'est pas nécessaire pour stocker uniquement une chaîne simple.
Jim Clermonts
travaillé pour moi ... sauvé ma journée ... merci
unownsp
0

Vous n'avez pas activé les paramètres de restauration automatique comme indiqué dans le message de la console. Vous devez accéder aux paramètres système et l'activer. Après cela, la restauration pourrait fonctionner.

Paramètres -> Sauvegarde -> Restauration automatique.

BTW, le jeton que vous avez utilisé n'est pas correct. 1573806051616 est un horodatage au lieu du jeton. Le jeton doit apparaître comme ci-dessous:

Ancestral packages: none
Ever backed up: XXXXXXXXXXXXXXXX

Ici, le XXXXXXXXXXXXXXXXdevrait être le jeton.

étudiant
la source
-1

Pour tester la restauration, vous devez exécuter la commande ci-dessous sans supprimer votre application. La commande de restauration forcera l'arrêt de l'application, effacera ses données et effectuera la restauration, simulant ainsi la fonctionnalité d'Android AutoBackup:

bmgr restore <TOKEN> <PACKAGE>

TOKENest récupéré de la logcatcommande lors de l'exécution de la commande de sauvegarde ou de la dumpsys backupcommande. Vous pouvez également vérifier le dumpsys backuppour vérifier que la sauvegarde a été créée.

Plus d'informations ici: https://developer.android.com/guide/topics/data/testingbackup.html#TestingRestore

ahasbini
la source
J'ai essayé ceci et édité la réponse mais les valeurs sharedpref sont toujours parties.
Jim Clermonts
Certaines conditions préalables doivent être remplies pour la sauvegarde. Veuillez vérifier le lien ci-dessous :: blog.devknox.io/…
Susheel Tickoo
Les conditions préalables sont remplies et cela ne fonctionne pas.
Jim Clermonts
-1

Une façon de procéder est la suivante (veuillez noter que ce n'est peut-être pas la meilleure façon, mais cela fonctionne!)

Avant de désinstaller l'application, reprenez-la. Ajoutez une logique selon laquelle si le fichier est présent dans le stockage externe , restaurez-le.

Les préférences stockées dans la classe SharedPreferences sont enregistrées dans /data/data//shared_prefs/_preferences.xml - la sauvegarde est facile, il vous suffit de copier le contenu de ce fichier sur un stockage externe:

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();
}

Utilisez le code suivant pour restaurer les préférences

Mais la restauration pose plus de problèmes, car le fichier shared_prefs n'est pas directement accessible en écriture par l'application et la classe SharedPrefs n'expose pas directement ses fonctionnalités pour sérialiser à partir de xml. Au lieu de cela, vous devez analyser le XML vous-même et repousser les valeurs. Heureusement, le fichier XML a une structure simple, il est donc facile de parcourir les éléments et de les reconvertir en préférences.

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);
}

REMARQUE : autorisation d'écriture et de lecture de stockage externe requise.

ChandraMouli Poreddy
la source