Sao lưu dữ liệu người dùng bằng tính năng Tự động sao lưu

Tính năng Tự động sao lưu cho ứng dụng tự động sao lưu dữ liệu của người dùng từ các ứng dụng nhắm đến và chạy trên Android 6.0 (API cấp 23) trở lên. Android lưu giữ dữ liệu ứng dụng bằng cách tải dữ liệu đó lên Google Drive của người dùng. Tại đây, dữ liệu được bảo vệ bằng thông tin đăng nhập Tài khoản Google của người dùng. Dữ liệu sao lưu được mã hoá hai đầu trên các thiết bị chạy Android 9 trở lên bằng mã PIN, hình mở khoá hoặc mật khẩu của thiết bị. Mỗi ứng dụng có thể phân bổ tối đa 25 MB dữ liệu sao lưu cho mỗi người dùng ứng dụng. Việc lưu trữ dữ liệu sao lưu không mất phí. Ứng dụng của bạn có thể tuỳ chỉnh quy trình sao lưu hoặc chọn không sao lưu bằng cách tắt tính năng sao lưu.

Để biết tổng quan về các tuỳ chọn sao lưu của Android và hướng dẫn về dữ liệu bạn cần sao lưu và khôi phục, hãy xem bài viết tổng quan về sao lưu dữ liệu.

Tệp được sao lưu

Theo mặc định, quá trình Tự động sao lưu bao gồm các tệp trong hầu hết các thư mục mà hệ thống gán cho ứng dụng của bạn:

Quá trình Tự động sao lưu sẽ loại trừ các tệp trong các thư mục do getCacheDir(), getCodeCacheDir()getNoBackupFilesDir() trả về. Những tệp được lưu tại các vị trí này chỉ được dùng trong thời gian ngắn và được chủ động loại trừ khỏi các hoạt động sao lưu.

Bạn có thể định cấu hình ứng dụng để bao gồm và loại trừ các tệp cụ thể. Để biết thêm thông tin, hãy xem phần Bao gồm và loại trừ tệp.

Vị trí sao lưu

Dữ liệu sao lưu được lưu trữ trong một thư mục riêng trong tài khoản Google Drive của người dùng, giới hạn là 25 MB trên mỗi ứng dụng. Dữ liệu đã lưu không được tính vào hạn mức cá nhân của người dùng trên Google Drive. Chỉ có bản sao lưu gần đây nhất được lưu trữ. Khi một bản sao lưu được tạo, mọi bản sao lưu trước đó sẽ bị xoá. Người dùng hoặc các ứng dụng khác trên thiết bị sẽ không đọc được dữ liệu sao lưu.

Người dùng có thể xem danh sách các ứng dụng đã được sao lưu trong ứng dụng Google Drive trên Android. Trên thiết bị chạy Android, người dùng có thể tìm thấy danh sách này trong ngăn điều hướng của ứng dụng Drive trong phần Cài đặt > Sao lưu và đặt lại.

Bản sao lưu từ mỗi lần thiết lập thiết bị trong thời gian hoạt động được lưu trữ trong các tập dữ liệu riêng biệt, như mô tả trong các ví dụ sau:

  • Nếu người dùng sở hữu 2 thiết bị, thì mỗi thiết bị sẽ có một tập dữ liệu sao lưu.

  • Nếu người dùng đặt lại thiết bị về trạng thái ban đầu và sau đó thiết lập thiết bị đó bằng cùng một tài khoản, thì bản sao lưu sẽ được lưu trữ trong một tập dữ liệu mới. Các tập dữ liệu lỗi thời sẽ tự động bị xoá sau một khoảng thời gian không hoạt động.

Lịch biểu sao lưu

Hoạt động sao lưu tự động diễn ra khi đáp ứng tất cả các điều kiện sau đây:

  • Người dùng đã bật tính năng sao lưu trên thiết bị. Trong Android 9, chế độ cài đặt này nằm trong phần Cài đặt > Hệ thống > Sao lưu.
  • Đã ít nhất 24 giờ trôi qua kể từ lần sao lưu gần đây nhất.
  • Thiết bị ở trạng thái rảnh.
  • 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 thực hiện sao lưu qua dữ liệu di động).

Trong thực tế, những điều kiện này xảy ra gần như mỗi đêm nhưng có thể thiết bị không bao giờ sao lưu được (ví dụ: nếu thiết bị chưa từng kết nối với mạng). Để tiết kiệm băng thông mạng, quá trình tải lên chỉ diễn ra nếu dữ liệu ứng dụng đã thay đổi.

Trong quá trình Tự động sao lưu, hệ thống sẽ tắt ứng dụng để đảm bảo rằng ứng dụng không còn ghi vào hệ thống tệp nữa. Theo mặc định, hệ thống sao lưu sẽ bỏ qua các ứng dụng đang chạy ở nền trước để tránh ảnh hưởng đến trải nghiệm người dùng. Bạn có thể ghi đè hành vi mặc định bằng cách đặt thuộc tính android:backupInForeground thành true.

Để đơn giản hoá quá trình kiểm thử, Android có các công cụ cho phép bạn tạo bản sao lưu thủ công cho ứng dụng của mình. Để biết thêm thông tin, hãy xem phần Kiểm thử tính năng sao lưu và khôi phục.

Khôi phục lịch biểu

Dữ liệu được khôi phục mỗi khi người dùng cài đặt ứng dụng, dù từ Cửa hàng Play, trong quá trình thiết lập thiết bị (khi hệ thống cài đặt các ứng dụng đã cài đặt trước đó) hay bằng cách chạy lệnh cài đặt adb. Thao tác khôi phục diễn ra sau khi APK được cài đặt, nhưng trước khi ứng dụng có sẵn cho người dùng khởi chạy.

Trong trình hướng dẫn thiết lập thiết bị ban đầu, người dùng sẽ nhìn thấy danh sách các tập dữ liệu sao lưu hiện có và được hỏi xem tập dữ liệu nào cần khôi phục dữ liệu. Bất kỳ tập dữ liệu sao lưu nào được chọn sẽ trở thành tập dữ liệu cấp trên của thiết bị. Thiết bị có thể khôi phục từ bản sao lưu riêng hoặc tập dữ liệu cấp trên. Nếu có các bản sao lưu từ cả hai nguồn, thiết bị sẽ ưu tiên bản sao lưu của chính nó. Nếu người dùng không thực hiện theo trình hướng dẫn thiết lập thiết bị, thì thiết bị chỉ có thể khôi phục từ các bản sao lưu của chính mình.

Để đơn giản hoá quá trình kiểm thử, Android có các công cụ cho phép bạn tạo bản sao lưu thủ công cho ứng dụng của mình. Để biết thêm thông tin, hãy xem phần Kiểm thử tính năng sao lưu và khôi phục.

Bật và tắt tính năng sao lưu

Các ứng dụng nhắm đến Android 6.0 (API cấp 23) trở lên sẽ tự động bật tính năng Tự động sao lưu. Trong tệp kê khai của ứng dụng, hãy đặt giá trị boolean android:allowBackup để bật hoặc tắt tính năng sao lưu. Giá trị mặc định là true, nhưng bạn nên đặt thuộc tính rõ ràng trong tệp kê khai như trong ví dụ sau:

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

Bạn có thể tắt tính năng sao lưu bằng cách đặt android:allowBackup thành false. Bạn có thể cần làm như vậy nếu ứng dụng của bạn có thể tạo lại trạng thái thông qua một số cơ chế khác hoặc nếu ứng dụng xử lý thông tin nhạy cảm.

Bao gồm và loại trừ tệp

Theo mặc định, hệ thống sao lưu hầu như mọi dữ liệu ứng dụng. Để biết thêm thông tin, hãy xem phần tệp được sao lưu.

Phần này cho bạn biết cách xác định các quy tắc XML tuỳ chỉnh để kiểm soát nội dung được sao lưu. Nếu ứng dụng của bạn nhắm đến Android 12 (API cấp 31) trở lên, thì bạn phải chỉ định một bộ quy tắc bổ sung cho hoạt động sao lưu XML như mô tả trong phần này để hỗ trợ cho những thay đổi về việc khôi phục bản sao lưu được giới thiệu cho các thiết bị chạy những phiên bản Android này.

Kiểm soát việc sao lưu trên Android 11 trở xuống

Làm theo các bước trong phần này để kiểm soát những tệp được sao lưu trên các thiết bị chạy Android 11 (API cấp 30) trở xuống.

  1. Trong tệp AndroidManifest.xml, hãy thêm thuộc tính android:fullBackupContent vào phần tử <application>, như trong ví dụ sau. Thuộc tính này trỏ đến một tệp XML chứa các quy tắc sao lưu.

    <application ...
     android:fullBackupContent="@xml/backup_rules">
    </application>
    
  2. Tạo một tệp XML có tên là @xml/backup_rules trong thư mục res/xml/. Trong tệp này, hãy thêm các quy tắc có phần tử <include><exclude>. Mẫu sau đây sao lưu tất cả các lựa chọn ưu tiên chung, 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>
    

Xác định các điều kiện thiết bị cần có để sao lưu

Nếu ứng dụng của bạn lưu thông tin nhạy cảm trên thiết bị, bạn có thể chỉ định những điều kiện mà dữ liệu của ứng dụng được đưa vào bản sao lưu của người dùng. Bạn có thể thêm các điều kiện sau vào Android 9 (API cấp 28) trở lên:

Nếu đã nâng cấp các thiết bị phát triển lên Android 9, bạn cần tắt rồi bật lại tính năng sao lưu dữ liệu sau khi nâng cấp. Điều này là do Android chỉ mã hoá bản sao lưu bằng mã bí mật phía máy khách sau khi thông báo cho người dùng trong phần Cài đặt hoặc trình hướng dẫn thiết lập.

Để khai báo các điều kiện đưa vào, hãy đặt thuộc tính requireFlags thành giá trị hoặc các giá trị đã chọn trong các phần tử <include> trong bộ quy tắc sao lưu của bạn:

backup_rules.xml

<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
    <!-- App data isn't included in user's backup
         unless client-side encryption is enabled. -->
    <include domain="file" path="."
             requireFlags="clientSideEncryption" />
</full-backup-content>

Nếu ứng dụng của bạn triển khai hệ thống sao lưu khoá-giá trị hoặc nếu bạn tự triển khai BackupAgent, thì bạn cũng có thể áp dụng các yêu cầu có điều kiện này cho logic sao lưu bằng cách so sánh bit giữa tập hợp cờ vận chuyển của đối tượng BackupDataOutput và cờ FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED hoặc FLAG_DEVICE_TO_DEVICE_TRANSFER của tác nhân sao lưu tuỳ chỉnh.

Đoạn mã sau đây cho thấy ví dụ về cách sử dụng phương thức này:

Kotlin

class CustomBackupAgent : BackupAgent() {
    override fun onBackup(oldState: ParcelFileDescriptor?,
            data: BackupDataOutput?, newState: ParcelFileDescriptor?) {
        if (data != null) {
            if ((data.transportFlags and
                    FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED) != 0) {
                // Client-side backup encryption is enabled.
            }

            if ((data.transportFlags and FLAG_DEVICE_TO_DEVICE_TRANSFER) != 0) {
                // Local device-to-device transfer is enabled.
            }
        }
    }

    // Implementation of onRestore() here.
}

Java

public class CustomBackupAgent extends BackupAgent {
    @Override
    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
            ParcelFileDescriptor newState) throws IOException {
        if ((data.getTransportFlags() &
                FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED) != 0) {
            // Client-side backup encryption is enabled.
        }

        if ((data.getTransportFlags() &
                FLAG_DEVICE_TO_DEVICE_TRANSFER) != 0) {
            // Local device-to-device transfer is enabled.
        }
    }

    // Implementation of onRestore() here.
}

Kiểm soát việc sao lưu trên Android 12 trở lên

Nếu ứng dụng của bạn nhắm đến Android 12 (API cấp 31) trở lên, hãy làm theo các bước trong phần này để kiểm soát các tệp được sao lưu trên các thiết bị đang chạy Android 12 trở lên.

  1. Trong tệp AndroidManifest.xml, hãy thêm thuộc tính android:dataExtractionRules vào phần tử <application>, như minh hoạ trong ví dụ sau. Thuộc tính này trỏ đến một tệp XML chứa các quy tắc sao lưu.

    <application ...
     android:dataExtractionRules="backup_rules.xml">
    </application>
    
  2. Tạo một tệp XML có tên là backup_rules.xml trong thư mục res/xml/. Trong tệp này, hãy thêm các quy tắc có phần tử <include><exclude>. Mẫu sau đây sao lưu tất cả các lựa chọn ưu tiên chung, ngoại trừ device.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <data-extraction-rules>
     <cloud-backup [disableIfNoEncryptionCapabilities="true|false"]>
       <include domain="sharedpref" path="."/>
       <exclude domain="sharedpref" path="device.xml"/>
     </cloud-backup>
    </data-extraction-rules>
    

Cú pháp cấu hình XML

Cú pháp XML cho tệp cấu hình sẽ thay đổi tuỳ thuộc vào việc ứng dụng của bạn chạy và nhắm đến phiên bản Android nào.

Android 11 trở xuống

Hãy sử dụng cú pháp XML sau cho tệp cấu hình kiểm soát quá trình sao lưu cho các thiết bị đang chạy Android 11 trở xuống.

<full-backup-content>
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"
    requireFlags=["clientSideEncryption" | "deviceToDeviceTransfer"] />
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string" />
</full-backup-content>

Android 12 trở lên

Nếu ứng dụng của bạn nhắm đến Android 12 (API cấp 31) trở lên, hãy sử dụng cú pháp XML sau đây cho tệp cấu hình kiểm soát quá trình sao lưu cho các thiết bị chạy Android 12 trở lên.

<data-extraction-rules>
  <cloud-backup [disableIfNoEncryptionCapabilities="true|false"]>
    ...
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
  </cloud-backup>
  <device-transfer>
    ...
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
  </device-transfer>
</data-extraction-rules>

Mỗi phần của cấu hình (<cloud-backup>, <device-transfer>) chứa các quy tắc chỉ áp dụng cho loại phương thức chuyển dữ liệu đó. Ví dụ: việc phân tách này cho phép bạn loại trừ một tệp hoặc thư mục khỏi bản sao lưu trên Google Drive trong khi vẫn chuyển dữ liệu trong quá trình chuyển từ thiết bị này sang thiết bị khác (D2D). Điều này sẽ hữu ích nếu bạn có các tệp quá lớn nên không thể sao lưu lên đám mây nhưng có thể chuyển giữa các thiết bị mà không gặp vấn đề nào.

Nếu không có quy tắc nào cho một chế độ sao lưu cụ thể, chẳng hạn như nếu phần <device-transfer> bị thiếu, thì chế độ đó sẽ được bật hoàn toàn cho tất cả nội dung ngoại trừ thư mục no-backupcache, như mô tả trong phần Tệp được sao lưu.

Ứng dụng của bạn có thể đặt cờ disableIfNoEncryptionCapabilities trong phần <cloud-backup> để đảm bảo rằng quá trình sao lưu chỉ xảy ra nếu có thể mã hoá, chẳng hạn như khi người dùng có màn hình khoá. Khi đặt hạn chế này, bản sao lưu sẽ không được gửi tới đám mây nếu thiết bị của người dùng không thể hỗ trợ tính năng mã hoá. Tuy nhiên, do quá trình chuyển D2D không được gửi đến máy chủ nên các bản sao lưu đó sẽ tiếp tục hoạt động ngay cả trên những thiết bị không hỗ trợ tính năng mã hoá.

Cú pháp để bao gồm và loại trừ các phần tử

Trong các thẻ <full-backup-content>, <cloud-backup><device-transfer> (tuỳ thuộc vào phiên bản Android của thiết bị và targetSDKVersion của ứng dụng), bạn có thể xác định các phần tử <include><exclude>:

<include>

Chỉ định một tệp hoặc thư mục cần sao lưu. Theo mặc định, tính năng Tự động sao lưu bao gồm hầu hết các tệp ứng dụng. Nếu bạn chỉ định một phần tử <include>, thì theo mặc định, hệ thống sẽ không bao gồm bất kỳ tệp nào và chỉ sao lưu các tệp được chỉ định. Để bao gồm nhiều tệp, hãy sử dụng nhiều phần tử <include>.

Trên Android 11 trở xuống, phần tử này cũng có thể chứa thuộc tính requireFlags. Phần mô tả cách xác định các yêu cầu có điều kiện để sao lưu sẽ thảo luận chi tiết hơn về thuộc tính đó.

Nếu là do getCacheDir(), getCodeCacheDir() hoặc getNoBackupFilesDir() trả về, tệp trong các thư mục sẽ luôn bị loại trừ ngay cả khi bạn cố gắng đưa những tệp đó vào.

<exclude>

Chỉ định một tệp hoặc thư mục cần loại trừ trong quá trình sao lưu. Dưới đây là một số tệp thường bị loại trừ khỏi quá trình sao lưu:

  • Tệp có mã nhận dạng cụ thể theo thiết bị, do máy chủ cấp hoặc được tạo trên thiết bị. Ví dụ: Giải pháp gửi thông báo qua đám mây của Firebase (FCM) cần tạo mã thông báo đăng ký mỗi khi người dùng cài đặt ứng dụng của bạn trên một thiết bị mới. Nếu mã thông báo đăng ký cũ được khôi phục, ứng dụng có thể hoạt động không như mong muốn.

  • Các tệp liên quan đến việc gỡ lỗi ứng dụng.

  • Các tệp có kích thước lớn khiến ứng dụng vượt quá hạn mức sao lưu 25 MB.

Mỗi phần tử <include><exclude> phải bao gồm hai thuộc tính sau:

domain

Chỉ định vị trí của tài nguyên. Sau đây là các giá trị hợp lệ cho thuộc tính này:

  • root: thư mục trên hệ thống tệp, nơi lưu trữ mọi tệp riêng tư của ứng dụng này.
  • file: Thư mục được getFilesDir() trả về.
  • database: Thư mục được getDatabasePath() trả về. Cơ sở dữ liệu do SQLiteOpenHelper tạo sẽ được lưu trữ ở đây.
  • sharedpref: thư mục lưu trữ SharedPreferences.
  • external: Thư mục được getExternalFilesDir() trả về.
  • device_root: giống như root nhưng dành cho bộ nhớ được bảo vệ bằng thiết bị.
  • device_file: giống như file nhưng dành cho bộ nhớ được bảo vệ bằng thiết bị.
  • device_database: giống như database nhưng dành cho bộ nhớ được bảo vệ bằng thiết bị.
  • device_sharedpref: giống như sharedpref nhưng dành cho bộ nhớ được bảo vệ bằng thiết bị.
path

Chỉ định một tệp hoặc thư mục để bao gồm hoặc loại trừ khỏi bản sao lưu. Lưu ý những điều sau:

  • Thuộc tính này không hỗ trợ cú pháp ký tự đại diện hoặc biểu thức chính quy.
  • Bạn có thể dùng ./ để tham chiếu đến thư mục hiện tại. Tuy nhiên, vì lý do bảo mật nên bạn không thể tham chiếu đến thư mục chính, chẳng hạn như bằng ...
  • Nếu bạn chỉ định một thư mục, thì quy tắc này sẽ áp dụng cho mọi tệp trong thư mục đó và các thư mục con đệ quy.

Triển khai BackupAgent

Các ứng dụng triển khai tính năng Tự động sao lưu không cần phải triển khai BackupAgent. Tuy nhiên, bạn có thể tuỳ ý triển khai một BackupAgent tuỳ chỉnh. Thông thường, có hai lý do để làm điều này:

  • Bạn muốn nhận thông báo về các sự kiện sao lưu, chẳng hạn như onRestoreFinished()onQuotaExceeded(long, long). Các phương thức gọi lại này được thực thi ngay cả khi ứng dụng không chạy.

  • Bạn không thể dễ dàng biểu thị tập hợp các tệp bạn muốn sao lưu bằng các quy tắc XML. Trong một số ít trường hợp, bạn có thể triển khai một BackupAgent ghi đè onFullBackup(FullBackupDataOutput) để lưu trữ nội dung mình muốn. Để duy trì cách triển khai mặc định của hệ thống, hãy gọi phương thức tương ứng trên siêu lớp bằng super.onFullBackup().

Nếu bạn triển khai BackupAgent, theo mặc định, hệ thống dự kiến ứng dụng của bạn sẽ thực hiện sao lưu và khôi phục khoá-giá trị. Thay vào đó, để sử dụng tính năng Tự động sao lưu dựa trên tệp, hãy đặt thuộc tính android:fullBackupOnly thành true trong tệp kê khai của ứng dụng.

Trong quá trình diễn ra hoạt động tự động sao lưu và khôi phục, hệ thống khởi chạy ứng dụng ở chế độ hạn chế để ngăn ứng dụng truy cập vào các tệp có thể gây xung đột đồng thời cho phép ứng dụng thực thi các phương thức gọi lại trong BackupAgent của mình. Ở chế độ hạn chế này, hoạt động chính của ứng dụng không được tự động khởi chạy, trình cung cấp nội dung của ứng dụng không được khởi chạy và lớp cơ sở Application được tạo thực thể thay vì bất kỳ lớp con nào được khai báo trong tệp kê khai của ứng dụng.

BackupAgent của bạn phải triển khai các phương thức trừu tượng onBackup()onRestore(), dùng cho tính năng sao lưu khoá-giá trị. Nếu không muốn thực hiện sao lưu khoá-giá trị, bạn có thể để trống việc triển khai các phương thức đó.

Để biết thêm thông tin, hãy xem phần Mở rộng BackupAgent.