mengambil nilai dari SharedPreferences setelah menginstal ulang dan dengan allowBackup = true menggunakan cadangan Android Otomatis


9

Saya mengalami masalah dalam mengambil nilai (pada perangkat Android 9.0) dari Preferensi yang dibagikan setelah saya menginstal ulang Aplikasi dan ketika memiliki allowBackup = true.

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

Menurut ini: https://developer.android.com/guide/topics/data/autobackup

Preferensi bersama harus dikembalikan?

    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();
  • Saya telah masuk ke akun Gmail saya di telepon (emulator) (API 27) dan ketika pergi ke Aplikasi Drive, Backup, App-data, saya melihat 18 Aplikasi seperti Youtube, Gmail dll. Dan juga Aplikasi saya sendiri.
  • Ketika saya pergi ke "Pengaturan> Sistem> Cadangan" Saya melihat Aplikasi yang sama dan juga Aplikasi saya sendiri. Saya memuat Aplikasi, kode sharedprefs dieksekusi. Saya menutup Aplikasi dan menghapusnya dari memori. Dan kemudian saya tekan tombol "Cadangkan sekarang":

masukkan deskripsi gambar di sini

Untuk memverifikasi, saya dapat melihat Aplikasi saya di daftar dan mendapat cadangan 0 menit yang lalu:

masukkan deskripsi gambar di sini

Lalu saya menghapus dan menginstal ulang Aplikasi dan mengharapkan 2 nilai (Elena dan 12) ada di sana. Tapi mereka terhapus ...

Saya juga mencoba hal yang sama melalui baris perintah, tetapi juga tidak berhasil: 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. Hapus Aplikasi
  2. Instal ulang Aplikasi dan periksa apakah nilai SharedPreferences masih ada.
  3. Nilai hilang ...

Perilaku ini juga tampaknya berbeda pada perangkat Samsung dengan Samsung Cloud, tetapi untuk sekarang mari kita fokus pada Android stock.

MEMPERBARUI:

Itu tidak berfungsi lagi karena saya menurunkan versi di build.gradle:

build.gradle:
versionCode 70
versionName "1.6.1"

Bahkan dengan android:restoreAnyVersion="true"di AndroidManifestdalamnya hanya akan berfungsi ketika versi tidak diturunkan.


Ini mungkin membantu Anda membuat cadangan-sharedpreferences-in-android
PraveenSP

Halo @PraveenSP Saya ingin menggunakan cadangan Android Otomatis dan bukan versi toko kunci / nilai yang lebih lama.
Jim Clermonts

Jawaban:


1

Secara default sistem android mencadangkan semua data default jika perangkat terhubung ke jaringan Wi-Fi (jika pengguna perangkat belum memilih untuk backup data seluler), cobalah untuk menginstal ulang aplikasi dan terhubung dengan WI-FI biasanya sinkronisasi sistem android data sekali dalam setiap 24 jam jika ada perubahan. Anda juga dapat mencoba menentukan aturan Anda sendiri untuk cadangan seperti ini.

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

dan buat file xml dan letakkan di direktori res / xml. Di dalam file, tambahkan aturan dengan elemen dan. Sampel berikut mencadangkan semua preferensi bersama kecuali 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>`

Saya harap ini akan menyelesaikan masalah Anda.


Saya hanya ingin menyimpan sharedprefs, tanpa xml.
Jim Clermonts

Kode di atas adalah aturan untuk sistem android untuk menyimpan data di drive pengguna, itu tidak akan disimpan sebagai xml, Sertakan & Kecualikan, beri tahu sistem yang data harus disinkronkan dan disimpan dan data mana yang harus dikecualikan dalam operasi sinkronisasi. .
Ashish srivastava

Saya mengerti tetapi saya pikir itu tidak perlu?
Jim Clermonts

1
i dont think, Ini karena tidak perlu ketika sistem android boot selesai memeriksa semua aturan aplikasi yang dikonfigurasikan dalam manifes secara default juga disinkronkan ketika allowBackup benar, tetapi ketika kita menulis aturan, sistem android tetap menggunakan aturan lokal dan mengaitkannya dengan nama paket.
Ashish srivastava

Saya telah menambahkan kode XML di atas tetapi tidak ada bedanya.
Jim Clermonts

1

Sesuai dokumen data cadangan , Anda perlu membuat SharedPreferencesBackupHelper dan ikuti langkah - langkah ini untuk mencapai pencadangan SharedPreferences juga perlu mendaftarkan layanan cadangan untuk kasus Anda


Halo, saya berbicara tentang Pencadangan Otomatis Android, bukan layanan pencadangan Android.
Jim Clermonts

ini terkait dengan cadangan otomatis saja. untuk sampel Anda dapat mengikuti langkah-langkah ini codelabs.developers.google.com/codelabs/android-backup-codelab/…
Damodhar

1

Semoga prosedur ini berhasil untuk Anda. Cobalah mencadangkan dan memulihkan Preferensi yang dibagikan pengguna. Ini akan mencadangkan preferensi Anda ke Penyimpanan atau perangkat Eksternal apa pun.

Saat pengguna menghapus aplikasi, pengguna harus mengambilnya kembali. Tambahkan beberapa logika bahwa jika file ada di Penyimpanan Eksternal atau perangkat, kembalikan kembali.

gunakan kode di bawah ini untuk membuat cadangan preferensi Anda.

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

gunakan kode di bawah ini untuk mengembalikan preferensi

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

}

kemudian restart aplikasi Anda sebelum prefrence ini akan bertahan

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

Halo, masalahnya adalah itu tidak cadangan ketika versionCode saya di build.gradle diturunkan. Itu sebabnya tidak bekerja. Kode sebanyak ini tidak diperlukan untuk menyimpan hanya string sederhana.
Jim Clermonts

bekerja untuk saya ... menyelamatkan hari saya ... terima kasih
unownsp

0

Anda tidak mengaktifkan pengaturan Auto-restore seperti yang ditunjukkan dalam pesan konsol. Anda harus pergi ke pengaturan sistem dan menyalakannya. Setelah itu, restorasi bisa bekerja.

Pengaturan -> Cadangan -> Pemulihan otomatis.

BTW, token yang Anda gunakan tidak benar. 1573806051616 adalah cap waktu alih-alih token. Token akan muncul seperti di bawah ini:

Ancestral packages: none
Ever backed up: XXXXXXXXXXXXXXXX

Di sini, XXXXXXXXXXXXXXXXseharusnya tokennya.


-1

Untuk menguji pemulihan, Anda harus menjalankan perintah di bawah ini tanpa menghapus aplikasi Anda. Perintah restore akan memaksa menghentikan aplikasi, menghapus datanya dan melakukan restore karenanya mensimulasikan fungsi Android AutoBackup:

bmgr restore <TOKEN> <PACKAGE>

TOKENdiambil dari logcatperintah saat menjalankan perintah cadangan atau dari dumpsys backupperintah. Anda juga dapat memeriksa dumpsys backupuntuk memverifikasi bahwa cadangan telah dibuat.

Info lebih lanjut di sini: https://developer.android.com/guide/topics/data/testingbackup.html#TestingRestore


Saya mencoba ini dan mengedit jawabannya tetapi nilai sharedpref masih hilang.
Jim Clermonts

Ada beberapa prasyarat yang harus dipenuhi untuk cadangan. Silakan periksa tautan di bawah ini :: blog.devknox.io/…
Susheel Tickoo

Prasyarat terpenuhi dan tidak berfungsi.
Jim Clermonts

-1

Salah satu cara untuk melakukan ini adalah sebagai berikut, (Harap dicatat, ini mungkin bukan cara terbaik, tetapi berhasil!)

Sebelum menghapus instalan aplikasi, ambil kembali itu. Tambahkan beberapa logika bahwa jika file ada di Penyimpanan Eksternal , kembalikan kembali.

Preferensi yang disimpan di kelas SharedPreferences dapat disimpan ke /data/data//shared_prefs/_preferences.xml - membuat cadangan mudah, Anda hanya perlu menyalin konten file ini ke penyimpanan eksternal:

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

Gunakan kode berikut untuk mengembalikan preferensi

Tetapi memulihkan memberikan lebih banyak tantangan, karena file shared_prefs tidak dapat ditulis secara langsung oleh aplikasi, dan kelas SharedPrefs tidak secara langsung mengekspos fungsionalitasnya ke serial dari xml. Alih-alih, Anda harus mem-parsing XML sendiri dan mendorong nilai-nilai kembali. Untungnya file XML memiliki struktur yang mudah, sehingga mudah untuk mengulang elemen dan mengubahnya kembali menjadi preferensi.

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

CATATAN : Diperlukan izin tulis dan baca penyimpanan eksternal.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.