lấy các giá trị từ SharedPreferences sau khi cài đặt lại và với allowBackup = true bằng cách sử dụng sao lưu Android Auto


9

Tôi gặp sự cố khi truy xuất các giá trị (trên thiết bị Android 9.0) từ Tùy chọn được chia sẻ sau khi tôi cài đặt lại Ứng dụng và trong khi có allowBackup = true.

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

Theo đó: https://developer.android.com/guide/topics/data/autobackup

Các sở thích chung nên được khôi phục?

    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();
  • Tôi đã đăng nhập vào tài khoản Gmail của mình trên điện thoại (trình giả lập) (API 27) và khi đi tới Ứng dụng Drive, Sao lưu, Dữ liệu ứng dụng, tôi thấy 18 Ứng dụng như Youtube, Gmail, v.v. và cả Ứng dụng của riêng tôi.
  • Khi tôi đi đến "Cài đặt> Hệ thống> Sao lưu", tôi thấy các Ứng dụng tương tự và Ứng dụng của riêng tôi. Tôi tải Ứng dụng, mã sharedprefs được thực thi. Tôi đóng Ứng dụng và xóa nó khỏi bộ nhớ. Và sau đó tôi nhấn nút "Sao lưu ngay":

nhập mô tả hình ảnh ở đây

Để xác minh tôi có thể thấy Ứng dụng của mình trong danh sách và nó đã được sao lưu 0 phút trước:

nhập mô tả hình ảnh ở đây

Sau đó, tôi gỡ bỏ và cài đặt lại Ứng dụng và hy vọng 2 giá trị (Elena và 12) sẽ ở đó. Nhưng họ đã bị xóa ...

Tôi cũng đã thử tương tự thông qua dòng lệnh, nhưng cũng không hoạt động: 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. Gỡ bỏ ứng dụng
  2. Cài đặt lại ứng dụng và kiểm tra xem các giá trị SharedPreferences có còn không.
  3. Giá trị không còn nữa ...

Hành vi dường như cũng khác nhau trên các thiết bị Samsung với Samsung Cloud, nhưng bây giờ hãy tập trung vào chứng khoán Android.

CẬP NHẬT:

Nó không hoạt động nữa vì tôi đã hạ cấp phiên bản trong build.gradle:

build.gradle:
versionCode 70
versionName "1.6.1"

Ngay cả với android:restoreAnyVersion="true"trong AndroidManifestnó sẽ chỉ làm việc khi phiên bản không được hạ cấp.


Điều này có thể giúp bạn sao lưu-sharedpreferences-in-android
PraveenSP

Xin chào @PraveenSP Tôi muốn sử dụng sao lưu Android Auto chứ không phải phiên bản lưu trữ khóa / giá trị cũ hơn.
Jim Clermonts

Câu trả lời:


1

Theo mặc định, hệ thống android sao lưu tất cả dữ liệu mặc định nếu thiết bị được kết nối với mạng Wi-Fi (nếu người dùng thiết bị chưa chọn sao lưu dữ liệu di động), hãy thử cài đặt lại ứng dụng và kết nối với WI-FI thường đồng bộ hóa hệ thống android dữ liệu một lần trong mỗi 24 giờ nếu có bất kỳ thay đổi nào. Bạn cũng có thể cố gắng chỉ định các quy tắc của riêng mình để sao lưu như thế này.

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

và tạo một tệp xml và đặt nó vào thư mục res / xml. Trong tệp, thêm quy tắc với các phần tử và. Mẫu sau sao lưu tất cả các tùy chọn được chia sẻ ngoại trừ 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>`

Tôi hy vọng nó sẽ giải quyết vấn đề của bạn.


Tôi chỉ muốn lưu sharedprefs, không có xml.
Jim Clermonts

Đoạn mã trên là quy tắc để hệ thống Android lưu dữ liệu trên ổ đĩa người dùng, nó sẽ không được lưu dưới dạng xml, Thẻ bao gồm & loại trừ thông báo cho hệ thống biết dữ liệu nào phải đồng bộ hóa và lưu và dữ liệu nào phải loại trừ trong hoạt động đồng bộ hóa .
Ashish srivastava

Tôi hiểu nhưng tôi không cần thiết?
Jim Clermonts

1
Tôi không nghĩ rằng, vì nó không thành công khi hệ thống khởi động Android bị lỗi, nó kiểm tra tất cả các quy tắc ứng dụng được cấu hình theo mặc định, nó cũng đồng bộ hóa khi allowBackup là đúng, nhưng khi chúng tôi viết quy tắc, hệ thống android sẽ giữ nguyên quy tắc cục bộ và liên kết nó với tên gói.
Ashish srivastava

Tôi đã thêm mã XML ở trên nhưng nó không tạo ra sự khác biệt.
Jim Clermonts

1

Theo tài liệu sao lưu dữ liệu, bạn cần tạo SharedPreferencesBackupHelper và làm theo các bước sau để đạt được SharedPreferences sao lưu cũng cần phải đăng ký dịch vụ sao lưu cho trường hợp của bạn


Xin chào, tôi đang nói về Android Auto Backup, không phải dịch vụ sao lưu Android.
Jim Clermonts

nó chỉ liên quan đến tự động sao lưu. đối với mẫu, bạn có thể thực hiện theo các bước này codelabs.developers.google.com/codelabs/android-backup-codelab/ Kẻ
Damodhar

1

Có thể thủ tục này sẽ làm việc cho bạn. Cố gắng sao lưu và khôi phục sharedPreferences của người dùng. Điều này sẽ sao lưu tùy chọn của bạn vào bất kỳ Bộ nhớ ngoài hoặc thiết bị nào.

Khi người dùng gỡ cài đặt ứng dụng, người dùng nên sao lưu nó. Thêm một số logic nếu tập tin có trong Bộ nhớ ngoài hoặc thiết bị, khôi phục lại.

sử dụng mã dưới đây để sao lưu sở thích của bạn.

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

sử dụng mã dưới đây để khôi phục ưu tiên

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

}

sau đó khởi động lại ứng dụng của bạn trước khi các prefrence này được giữ

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

Xin chào, vấn đề là nó không sao lưu khi phiên bản Mã của tôi trong build.gradle bị hạ cấp. Đó là lý do tại sao nó không hoạt động. Mã nhiều này là không cần thiết để chỉ lưu trữ một chuỗi đơn giản.
Jim Clermonts

làm việc cho tôi ... đã cứu ngày của tôi ... cảm ơn bạn
unownsp

0

Bạn đã không bật cài đặt Tự động khôi phục như hiển thị trong thông báo bảng điều khiển. Bạn nên vào cài đặt hệ thống và bật nó lên. Sau đó, phục hồi có thể làm việc.

Cài đặt -> Sao lưu -> Tự động khôi phục.

BTW, mã thông báo bạn đã sử dụng không chính xác. 1573806051616 là dấu thời gian thay vì mã thông báo. Mã thông báo sẽ xuất hiện như dưới đây:

Ancestral packages: none
Ever backed up: XXXXXXXXXXXXXXXX

Ở đây, XXXXXXXXXXXXXXXXnên là mã thông báo.


-1

Để kiểm tra khôi phục, bạn cần chạy lệnh bên dưới mà không cần xóa ứng dụng của mình. Lệnh khôi phục sẽ buộc dừng ứng dụng, xóa sạch dữ liệu của nó và thực hiện khôi phục do đó mô phỏng chức năng của Android AutoBackup:

bmgr restore <TOKEN> <PACKAGE>

TOKENđược lấy từ logcatlệnh khi chạy lệnh sao lưu hoặc từ dumpsys backuplệnh. Ngoài ra, bạn có thể kiểm tra dumpsys backupđể xác minh rằng bản sao lưu đã được tạo.

Thêm thông tin tại đây: https://developer.android.com/guide/topics/data/testingbackup.html#TestingRestore


Tôi đã thử điều này và chỉnh sửa câu trả lời nhưng các giá trị sharedpref vẫn không còn.
Jim Clermonts

Có một số điều kiện tiên quyết được đáp ứng để sao lưu. Vui lòng kiểm tra liên kết dưới đây :: blog.devknox.io/ từ
Susheel Tickoo

Các điều kiện tiên quyết được đáp ứng và nó không hoạt động.
Jim Clermonts

-1

Một cách để làm điều này là như sau, (Xin lưu ý, đây có thể không phải là cách tốt nhất, nhưng nó hoạt động!)

Trước khi gỡ cài đặt ứng dụng, hãy sao lưu ứng dụng. Thêm một số logic nếu tập tin có trong Bộ nhớ ngoài , khôi phục lại.

Các tùy chọn được lưu trữ trong lớp SharedPreferences được lưu vào /data/data// Shared_prefs/_preferences.xml - sao lưu rất dễ dàng, bạn chỉ cần sao chép nội dung của tệp này vào bộ nhớ ngoài:

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

Sử dụng mã sau để khôi phục ưu tiên

Nhưng việc khôi phục cung cấp nhiều thách thức hơn, vì tệp shared_prefs không thể ghi trực tiếp bởi ứng dụng và lớp SharedPrefs không trực tiếp phơi bày chức năng của nó để tuần tự hóa từ xml. Thay vào đó, bạn phải tự phân tích cú pháp XML và đẩy các giá trị trở lại. Rất may, tệp XML có cấu trúc đơn giản, do đó, thật dễ dàng để lặp lại các phần tử và biến chúng trở lại thành các tùy chọn.

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

LƯU Ý : Lưu trữ bên ngoài ghi và đọc yêu cầu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.