สำรองข้อมูลผู้ใช้ด้วยการสำรองข้อมูลอัตโนมัติ

การสำรองข้อมูลอัตโนมัติสำหรับแอปจะสำรองข้อมูลของผู้ใช้จากแอปที่กำหนดเป้าหมายและทำงานใน Android 6.0 (ระดับ API 23) ขึ้นไปโดยอัตโนมัติ Android จะเก็บรักษาข้อมูลแอปโดยอัปโหลดไปยัง Google ไดรฟ์ของผู้ใช้ ซึ่งจะได้รับการปกป้องด้วยข้อมูลเข้าสู่ระบบของบัญชี Google ของผู้ใช้ ข้อมูลสำรองจะได้รับการเข้ารหัสจากต้นทางถึงปลายทางในอุปกรณ์ที่ใช้ Android 9 ขึ้นไปโดยใช้ PIN, รูปแบบ หรือรหัสผ่านของอุปกรณ์ ทุกแอปสามารถจัดสรรข้อมูลสำรองได้สูงสุด 25 MB ต่อผู้ใช้แอป ไม่มีค่าใช้จ่ายในการจัดเก็บข้อมูลสำรอง แอปของคุณสามารถปรับแต่งกระบวนการสำรองข้อมูลหรือเลือกไม่ใช้โดยปิดใช้การสำรองข้อมูล

ดูภาพรวมของตัวเลือกการสำรองข้อมูลของ Android และคำแนะนำเกี่ยวกับข้อมูลที่ควรสำรองและกู้คืนได้ที่ภาพรวมการสำรองข้อมูล

ไฟล์ที่สำรองข้อมูลไว้

โดยค่าเริ่มต้น การสำรองข้อมูลอัตโนมัติจะรวมไฟล์ในไดเรกทอรีส่วนใหญ่ที่ระบบกำหนดให้กับแอปของคุณ ดังนี้

  • ไฟล์ค่ากำหนดที่แชร์

  • ไฟล์ที่บันทึกไว้ในที่จัดเก็บข้อมูลภายในของแอปและเข้าถึงโดย getFilesDir() หรือ getDir(String, int)

  • ไฟล์ในไดเรกทอรีที่แสดงผลโดย getDatabasePath(String) ซึ่งรวมถึงไฟล์ที่สร้างด้วยคลาส SQLiteOpenHelper ด้วย

  • ไฟล์ในพื้นที่เก็บข้อมูลภายนอกในไดเรกทอรีที่แสดงผลโดย getExternalFilesDir(String)

การสำรองข้อมูลอัตโนมัติจะไม่รวมไฟล์ในไดเรกทอรีที่แสดงผลโดย getCacheDir(), getCodeCacheDir() และ getNoBackupFilesDir() ไฟล์ที่บันทึกไว้ในตำแหน่งเหล่านี้จำเป็นต้องใช้ชั่วคราวเท่านั้น และระบบจะยกเว้นจากการดำเนินการสำรองข้อมูลโดยเจตนา

คุณสามารถกำหนดค่าแอปให้รวมและยกเว้นไฟล์บางไฟล์ได้ ดูข้อมูลเพิ่มเติมได้ที่ส่วนรวมและยกเว้นไฟล์

ตำแหน่งของข้อมูลสำรอง

ข้อมูลสำรองจะจัดเก็บไว้ในโฟลเดอร์ส่วนตัวในบัญชี Google ไดรฟ์ของผู้ใช้ โดยจำกัดไว้ที่ 25 MB ต่อแอป ข้อมูลที่บันทึกไว้จะไม่นับรวมในโควต้า Google ไดรฟ์ส่วนตัวของผู้ใช้ ระบบจะจัดเก็บเฉพาะข้อมูลสำรองล่าสุดเท่านั้น เมื่อมีการสำรองข้อมูล ระบบจะลบข้อมูลสำรองก่อนหน้าออก ผู้ใช้หรือแอปอื่นๆ ในอุปกรณ์จะอ่านข้อมูลสำรองไม่ได้

ผู้ใช้จะดูรายการแอปที่สำรองข้อมูลไว้ในแอป Google ไดรฟ์สำหรับ Android ได้ โดยในอุปกรณ์ที่ใช้ Android ผู้ใช้จะดูรายการนี้ได้ในลิ้นชักการนำทางของแอปไดรฟ์ในส่วนการตั้งค่า > สำรองข้อมูลและรีเซ็ต

ข้อมูลสำรองจากอายุการใช้งานของการตั้งค่าอุปกรณ์แต่ละครั้งจะจัดเก็บไว้ในชุดข้อมูลแยกกัน ดังที่อธิบายไว้ในตัวอย่างต่อไปนี้

  • หากผู้ใช้เป็นเจ้าของอุปกรณ์ 2 เครื่อง ชุดข้อมูลสำรองจะมีสำหรับอุปกรณ์แต่ละเครื่อง

  • หากผู้ใช้รีเซ็ตอุปกรณ์เป็นค่าเริ่มต้นแล้วตั้งค่าอุปกรณ์ด้วยบัญชีเดิม ระบบจะจัดเก็บข้อมูลสำรองไว้ในชุดข้อมูลใหม่ ระบบจะลบชุดข้อมูลที่ล้าสมัยโดยอัตโนมัติหลังจากไม่มีการใช้งานเป็นระยะเวลาหนึ่ง

กำหนดเวลาสำรองข้อมูล

การสำรองข้อมูลจะเกิดขึ้นโดยอัตโนมัติเมื่อเป็นไปตามเงื่อนไขต่อไปนี้ทั้งหมด

  • ผู้ใช้เปิดใช้การสำรองข้อมูลในอุปกรณ์ ใน Android 9 การตั้งค่านี้จะอยู่ในการตั้งค่า > ระบบ > การสำรองข้อมูล
  • เวลาผ่านไปอย่างน้อย 24 ชั่วโมงนับจากการสำรองข้อมูลครั้งล่าสุด
  • อุปกรณ์ไม่มีการใช้งาน
  • อุปกรณ์เชื่อมต่อกับเครือข่าย Wi-Fi (หากผู้ใช้อุปกรณ์ไม่ได้เลือกใช้การสำรองข้อมูลผ่านอินเทอร์เน็ตมือถือ)

ในทางปฏิบัติ เงื่อนไขเหล่านี้จะเกิดขึ้นเกือบทุกคืน แต่อุปกรณ์อาจไม่เคยสำรองข้อมูลเลย (เช่น หากไม่เคยเชื่อมต่อกับเครือข่าย) เพื่อประหยัดแบนด์วิดท์เครือข่าย การอัปโหลดจะเกิดขึ้นก็ต่อเมื่อข้อมูลแอปมีการเปลี่ยนแปลงเท่านั้น

ในระหว่างการสำรองข้อมูลอัตโนมัติ ระบบจะปิดแอปเพื่อให้แน่ใจว่าแอปจะไม่เขียนลงในระบบไฟล์อีกต่อไป โดยค่าเริ่มต้น ระบบสำรองข้อมูลจะไม่สนใจแอปที่ทำงานอยู่เบื้องหน้าเพื่อหลีกเลี่ยงประสบการณ์ที่ไม่ดีของผู้ใช้ คุณลบล้างลักษณะการทำงานเริ่มต้นได้โดยตั้งค่าแอตทริบิวต์ android:backupInForeground เป็น "จริง"

Android มีเครื่องมือที่ช่วยให้คุณเริ่มการสำรองข้อมูลแอปด้วยตนเองเพื่อลดความซับซ้อนในการทดสอบ ดูข้อมูลเพิ่มเติมได้ที่ทดสอบการสำรองและกู้คืนข้อมูล

กู้คืนกำหนดเวลา

ระบบจะกู้คืนข้อมูลเมื่อใดก็ตามที่มีการติดตั้งแอป ไม่ว่าจะจาก Play Store, ระหว่างการตั้งค่าอุปกรณ์ (เมื่อระบบติดตั้งแอปที่ติดตั้งไว้ก่อนหน้านี้) หรือโดยการเรียกใช้ adb install การดำเนินการกู้คืนจะเกิดขึ้นหลังจากติดตั้ง APK แล้ว แต่ก่อนที่ผู้ใช้จะเปิดแอปได้

ในระหว่างวิซาร์ดการตั้งค่าอุปกรณ์เริ่มต้น ระบบจะแสดงรายการชุดข้อมูลสำรองที่ใช้ได้ให้ผู้ใช้เห็น และถามว่าต้องการกู้คืนข้อมูลจากชุดข้อมูลใด ชุดข้อมูลสำรองที่เลือกจะกลายเป็นชุดข้อมูลหลักสำหรับอุปกรณ์ อุปกรณ์สามารถกู้คืนจากข้อมูลสำรองของตัวเองหรือชุดข้อมูลเดิมได้ หากมีข้อมูลสำรองจากทั้ง 2 แหล่ง อุปกรณ์จะให้ความสำคัญกับข้อมูลสำรองของตนเองก่อน หากผู้ใช้ไม่ได้ดำเนินการผ่านวิซาร์ดการตั้งค่าอุปกรณ์ อุปกรณ์จะกู้คืนได้จากข้อมูลสำรองของตนเองเท่านั้น

Android มีเครื่องมือที่ช่วยให้คุณเริ่มการกู้คืนแอปด้วยตนเองเพื่อลดความซับซ้อนในการทดสอบ ดูข้อมูลเพิ่มเติมได้ที่ทดสอบการสำรองและกู้คืนข้อมูล

เปิดและปิดใช้การสำรองข้อมูล

แอปที่กำหนดเป้าหมายเป็น Android 6.0 (ระดับ API 23) ขึ้นไปจะเข้าร่วมการสำรองข้อมูลอัตโนมัติโดยอัตโนมัติ ในไฟล์ Manifest ของแอป ให้ตั้งค่าบูลีน android:allowBackup เพื่อเปิดหรือปิดใช้การสำรองข้อมูล ค่าเริ่มต้นคือ true แต่เราขอแนะนำให้ตั้งค่าแอตทริบิวต์อย่างชัดเจนในไฟล์ Manifest ดังที่แสดงในตัวอย่างต่อไปนี้

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

คุณปิดใช้การสำรองข้อมูลได้โดยตั้งค่า android:allowBackup เป็น false คุณอาจต้องทำเช่นนี้หากแอปสามารถสร้างสถานะขึ้นมาใหม่ผ่านกลไกอื่นๆ หรือหากแอปจัดการกับข้อมูลที่ละเอียดอ่อน

รวมและยกเว้นไฟล์

โดยค่าเริ่มต้น ระบบจะสำรองข้อมูลแอปเกือบทั้งหมด ดูข้อมูลเพิ่มเติมได้ที่ส่วนเกี่ยวกับไฟล์ที่สำรองข้อมูลไว้

คุณควบคุมได้ว่าจะรวมข้อมูลใดไว้ในการสำรองข้อมูลตามประเภทการโอน การสำรองข้อมูลอัตโนมัติรองรับการสำรองข้อมูลในระบบคลาวด์ไปยัง Google ไดรฟ์และการโอนจากอุปกรณ์หนึ่งไปยังอีกอุปกรณ์หนึ่งโดยตรง (D2D) วิธีการกำหนดค่าจะแตกต่างกันไปตามเวอร์ชัน Android และ targetSdkVersion ของแอป

ควบคุมการสำรองข้อมูลใน Android 11 และต่ำกว่า

ทำตามขั้นตอนในส่วนนี้เพื่อควบคุมว่าจะสำรองข้อมูลไฟล์ใดในอุปกรณ์ที่ใช้ Android 11 (ระดับ API 30) หรือต่ำกว่า

  1. ในไฟล์ AndroidManifest.xml ให้เพิ่มแอตทริบิวต์ android:fullBackupContent ลงในองค์ประกอบ <application> ดังที่แสดงในตัวอย่างต่อไปนี้ แอตทริบิวต์นี้ชี้ไปยังไฟล์ XML ที่มีกฎการสำรองข้อมูล

    <application ...
        android:fullBackupContent="@xml/backup_rules">
    </application>
    
  2. สร้างไฟล์ XML ชื่อ @xml/backup_rules ในไดเรกทอรี res/xml/ ในไฟล์นี้ ให้เพิ่มกฎที่มีองค์ประกอบ <include> และ <exclude> ตัวอย่างต่อไปนี้จะสำรองข้อมูลค่ากำหนดที่ใช้ร่วมกันทั้งหมด ยกเว้น 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>
    

กำหนดเงื่อนไขของอุปกรณ์ที่จำเป็นสำหรับการสำรองข้อมูล

หากแอปบันทึกข้อมูลที่ละเอียดอ่อนไว้ในอุปกรณ์ คุณสามารถระบุเงื่อนไขที่ข้อมูลของแอปจะรวมอยู่ในการสำรองข้อมูลของผู้ใช้ได้ คุณสามารถเพิ่มเงื่อนไขต่อไปนี้ใน Android 9 (ระดับ API 28) ขึ้นไป

หากคุณอัปเกรดอุปกรณ์ที่ใช้ในการพัฒนาเป็น Android 9 คุณต้องปิดใช้แล้วเปิดใช้การสำรองข้อมูลอีกครั้งหลังจากอัปเกรด เนื่องจาก Android จะเข้ารหัสข้อมูลสำรองด้วยข้อมูลลับฝั่งไคลเอ็นต์หลังจากแจ้งให้ผู้ใช้ทราบในการตั้งค่าหรือวิซาร์ดการตั้งค่าเท่านั้น

หากต้องการประกาศเงื่อนไขการรวม ให้ตั้งค่าแอตทริบิวต์ requireFlags เป็นค่าที่เลือกในองค์ประกอบ <include> ภายในชุดกฎสำรอง ดังนี้

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>

หากแอปใช้ระบบการสำรองข้อมูลคีย์-ค่าหรือหากคุณใช้ BackupAgent ด้วยตนเอง คุณยังสามารถใช้ข้อกำหนดแบบมีเงื่อนไขเหล่านี้กับตรรกะการสำรองข้อมูลได้โดยทำการเปรียบเทียบระดับบิตระหว่างชุดแฟล็กการรับส่งของออบเจ็กต์ BackupDataOutput กับแฟล็ก FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED หรือ FLAG_DEVICE_TO_DEVICE_TRANSFER ของตัวแทนการสำรองข้อมูลที่กำหนดเอง

ข้อมูลโค้ดต่อไปนี้แสดงตัวอย่างการใช้เมธอดนี้

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.
}

ควบคุมการสำรองข้อมูลใน Android 12 ขึ้นไป

หากแอปกำหนดเป้าหมายเป็น Android 12 (ระดับ API 31) ขึ้นไป ให้ทำตามขั้นตอนในส่วนนี้เพื่อควบคุมไฟล์ที่จะสำรองข้อมูลในอุปกรณ์ที่ใช้ Android 12 ขึ้นไป

  1. ในไฟล์ AndroidManifest.xml ให้เพิ่มแอตทริบิวต์ android:dataExtractionRules ลงในองค์ประกอบ <application> ดังที่แสดงในตัวอย่างต่อไปนี้ แอตทริบิวต์นี้ชี้ไปยังไฟล์ XML ที่มีกฎการสำรองข้อมูล

    <application ...
        android:dataExtractionRules="backup_rules.xml">
    </application>
    
  2. สร้างไฟล์ XML ชื่อ backup_rules.xml ในไดเรกทอรี res/xml/ ในไฟล์นี้ ให้เพิ่มกฎที่มีองค์ประกอบ <include> และ <exclude> ตัวอย่างต่อไปนี้จะสำรองข้อมูลค่ากำหนดที่ใช้ร่วมกันทั้งหมด ยกเว้น 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>
    

ไวยากรณ์การกำหนดค่า XML

ไวยากรณ์ XML สำหรับไฟล์การกำหนดค่าจะแตกต่างกันไปตามเวอร์ชันของ Android ที่แอปกำหนดเป้าหมายและทำงานอยู่

Android 11 หรือต่ำกว่า

ใช้ไวยากรณ์ XML ต่อไปนี้สำหรับไฟล์การกำหนดค่าที่ควบคุมการสำรองข้อมูลสำหรับอุปกรณ์ที่ใช้ Android 11 หรือต่ำกว่า

<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 ขึ้นไป

หากแอปกำหนดเป้าหมายเป็น Android 12 (ระดับ API 31) ขึ้นไป ให้ใช้ไวยากรณ์ XML ต่อไปนี้สำหรับไฟล์การกำหนดค่าที่ควบคุมการสำรองข้อมูลสำหรับอุปกรณ์ที่ใช้ Android 12 ขึ้นไป

<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>
  <cross-platform-transfer platform="ios">
    ...
    <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"/>
    ...
    <platform-specific-params bundleId="string" teamId="string" contentVersion="string"/>
    ...
  </cross-platform-transfer>
</data-extraction-rules>

การกำหนดค่าแต่ละส่วน (<cloud-backup>, <device-transfer>, <cross-platform-transfer>) จะมีกฎที่ใช้กับการโอนประเภทนั้นเท่านั้น การแยกนี้ช่วยให้คุณยกเว้นไฟล์หรือไดเรกทอรีจากการสำรองข้อมูลใน Google ไดรฟ์ได้ เป็นต้น ขณะที่ยังคงโอนไฟล์หรือไดเรกทอรีดังกล่าวในระหว่างการโอนจากอุปกรณ์หนึ่งไปยังอีกอุปกรณ์หนึ่ง (D2D) หรือการโอนข้ามแพลตฟอร์ม ซึ่งจะเป็นประโยชน์หากคุณมีไฟล์ที่มีขนาดใหญ่เกินกว่าจะสำรองข้อมูลไปยังระบบคลาวด์ แต่สามารถโอนระหว่างอุปกรณ์ได้โดยไม่มีปัญหา

หากไม่มีกฎสำหรับโหมดการสำรองข้อมูลบางโหมด เช่น หากไม่มีส่วน <device-transfer> โหมดนั้นจะเปิดใช้โดยสมบูรณ์สำหรับเนื้อหาทั้งหมด ยกเว้นไดเรกทอรี no-backup และ cache ตามที่อธิบายไว้ในส่วนไฟล์ที่สำรองข้อมูล

แอปของคุณสามารถตั้งค่าแฟล็ก disableIfNoEncryptionCapabilities ในส่วน <cloud-backup> เพื่อให้แน่ใจว่าการสำรองข้อมูลจะเกิดขึ้นก็ต่อเมื่อสามารถเข้ารหัสได้เท่านั้น เช่น เมื่อผู้ใช้มีหน้าจอล็อก การตั้งค่าข้อจำกัดนี้จะหยุดการส่งข้อมูลสำรองไปยังระบบคลาวด์หากอุปกรณ์ของผู้ใช้ไม่รองรับการเข้ารหัส แต่เนื่องจากระบบไม่ได้ส่งการโอนแบบ D2D ไปยังเซิร์ฟเวอร์ การโอนจึงยังคงทำงานต่อไปแม้ในอุปกรณ์ที่ไม่รองรับการเข้ารหัส

ไวยากรณ์สำหรับองค์ประกอบรวมและยกเว้น

ภายในแท็ก <full-backup-content>, <cloud-backup> และ <device-transfer> (ขึ้นอยู่กับเวอร์ชัน Android ของอุปกรณ์และ targetSDKVersion ของแอป) คุณสามารถกำหนดองค์ประกอบ <include> และ <exclude> ได้ดังนี้

<include>

ระบุไฟล์หรือโฟลเดอร์ที่จะสำรองข้อมูล โดยค่าเริ่มต้น การสำรองข้อมูลอัตโนมัติจะรวมไฟล์แอปเกือบทั้งหมด หากคุณระบุองค์ประกอบ <include> ระบบจะไม่รวมไฟล์ใดๆ โดยค่าเริ่มต้นอีกต่อไป และจะสำรองข้อมูลเฉพาะไฟล์ที่ระบุ หากต้องการรวมไฟล์หลายไฟล์ ให้ใช้องค์ประกอบ <include> หลายรายการ

ใน Android 11 และต่ำกว่า องค์ประกอบนี้ยังมีแอตทริบิวต์ requireFlags ได้ด้วย ซึ่งส่วนที่อธิบายวิธีกำหนดข้อกำหนดแบบมีเงื่อนไขสำหรับการสำรองข้อมูลจะกล่าวถึงรายละเอียดเพิ่มเติม

ระบบจะยกเว้นไฟล์ในไดเรกทอรีที่ getCacheDir(), getCodeCacheDir() หรือ getNoBackupFilesDir() แสดงผลเสมอ แม้ว่าคุณจะพยายามรวมไฟล์เหล่านั้นก็ตาม

<exclude>

ระบุไฟล์หรือโฟลเดอร์ที่จะยกเว้นระหว่างการสำรองข้อมูล ตัวอย่างไฟล์ที่มักจะยกเว้นจากการสำรองข้อมูลมีดังนี้

  • ไฟล์ที่มีตัวระบุเฉพาะอุปกรณ์ ซึ่งเซิร์ฟเวอร์เป็นผู้ออกหรือสร้างขึ้นในอุปกรณ์ ตัวอย่างเช่น Firebase Cloud Messaging (FCM) ต้องสร้างโทเค็นการลงทะเบียนทุกครั้งที่ผู้ใช้ติดตั้งแอปของคุณในอุปกรณ์ใหม่ หากมีการกู้คืนโทเค็นการลงทะเบียนเก่า แอปอาจทำงานผิดปกติ

  • ไฟล์ที่เกี่ยวข้องกับการแก้ไขข้อบกพร่องของแอป

  • ไฟล์ขนาดใหญ่ที่ทำให้แอปมีขนาดเกินโควต้าการสำรองข้อมูล 25 MB

องค์ประกอบ <include> และ <exclude> แต่ละรายการต้องมีแอตทริบิวต์ 2 รายการต่อไปนี้

domain

ระบุตำแหน่งของทรัพยากร ค่าที่ถูกต้องสำหรับแอตทริบิวต์นี้มีดังต่อไปนี้

  • root: ไดเรกทอรีในระบบไฟล์ที่จัดเก็บไฟล์ส่วนตัวทั้งหมดของแอปนี้
  • file: ไดเรกทอรีที่ getFilesDir() แสดงผล
  • database: ไดเรกทอรีที่ getDatabasePath() แสดงผล ฐานข้อมูลที่สร้างด้วย SQLiteOpenHelper จะจัดเก็บไว้ที่นี่
  • sharedpref: ไดเรกทอรีที่จัดเก็บ SharedPreferences
  • external: ไดเรกทอรีที่ getExternalFilesDir() แสดงผล
  • device_root: คล้ายกับ root แต่ใช้สำหรับพื้นที่เก็บข้อมูลที่ได้รับการปกป้องในอุปกรณ์
  • device_file: คล้ายกับ file แต่ใช้สำหรับพื้นที่เก็บข้อมูลที่ได้รับการปกป้องในอุปกรณ์
  • device_database: คล้ายกับ database แต่ใช้สำหรับพื้นที่เก็บข้อมูลที่ได้รับการปกป้องในอุปกรณ์
  • device_sharedpref: เหมือนกับ sharedpref แต่สำหรับพื้นที่เก็บข้อมูลที่อุปกรณ์คุ้มครอง
path

ระบุไฟล์หรือโฟลเดอร์ที่จะรวมหรือยกเว้นจากการสำรองข้อมูล สิ่งที่ควรทราบมีดังนี้

  • แอตทริบิวต์นี้ไม่รองรับไวยากรณ์ไวลด์การ์ดหรือนิพจน์ทั่วไป
  • คุณสามารถอ้างอิงไดเรกทอรีปัจจุบันโดยใช้ ./ แต่จะอ้างอิงไดเรกทอรีระดับบนไม่ได้ เช่น การใช้ .. ด้วยเหตุผลด้านความปลอดภัย
  • หากคุณระบุไดเรกทอรี กฎจะมีผลกับไฟล์ทั้งหมดในไดเรกทอรีและไดเรกทอรีย่อยแบบเรียกซ้ำ

กำหนดค่าการโอนข้ามแพลตฟอร์ม

ตั้งแต่ Android 16 QPR2 (API ระดับ 36.1) เป็นต้นไป คุณสามารถกำหนดค่าการสำรองข้อมูลอัตโนมัติสำหรับการโอนข้อมูลไปยังและจากอุปกรณ์ที่ไม่ใช่ Android ได้ โดยเพิ่มองค์ประกอบ <cross-platform-transfer> ภายในองค์ประกอบ <data-extraction-rules> ดังที่แสดงในไวยากรณ์ Android 12 ขึ้นไป คุณต้องระบุแพลตฟอร์มเป้าหมายโดยใช้แอตทริบิวต์ platform ที่จำเป็น ค่าเดียวที่รองรับคือ ios

ในส่วนนี้ คุณสามารถใช้องค์ประกอบ <include> และ <exclude> มาตรฐานตามที่อธิบายไว้ในไวยากรณ์สำหรับองค์ประกอบ include และ exclude เพื่อระบุข้อมูลที่จะโอน

นอกจากนี้ คุณต้องใส่องค์ประกอบ <platform-specific-params> เพื่อช่วยให้ระบบจับคู่แอปของคุณกับแอปที่เกี่ยวข้องในแพลตฟอร์มเป้าหมาย องค์ประกอบนี้มีแอตทริบิวต์ที่จำเป็นต่อไปนี้

  • bundleId: รหัสชุดของแอปในแพลตฟอร์มอื่น (เช่น รหัสชุดของแอป iOS)
  • teamId: รหัสทีมของแอปในแพลตฟอร์มอื่น (เช่น รหัสทีมของแอป iOS)
  • contentVersion: สตริงเวอร์ชันที่คุณกำหนด ซึ่งเชื่อมโยงกับรูปแบบข้อมูลที่ส่งออก

ระบบจะใช้แอตทริบิวต์ bundleId และ teamId เพื่อช่วยยืนยันความสมบูรณ์ของข้อมูลและการจับคู่ระหว่างแอปที่เหมาะสม โดยจะรับประกันว่าข้อมูลจะโอนไปยังแอปที่ระบุในแพลตฟอร์มอื่นเท่านั้นในระหว่างการส่งออก และแอป Android นี้จะนำเข้าข้อมูลจากแอปที่ระบุเท่านั้นในระหว่างการนำเข้า

หากต้องการควบคุมกระบวนการเปลี่ยนรูปแบบและการโอนข้อมูลอย่างละเอียดยิ่งขึ้นนอกเหนือจากที่กฎ XML มีให้ คุณสามารถใช้ BackupAgent ที่กำหนดเองและใช้ Cross-Platform Transfer API ได้

การแมปไฟล์สำหรับการโอน iOS

เมื่อโอนไฟล์ไปยัง iOS ระบบจะจับคู่ domain และ path ของ Android ที่คุณระบุในกฎ <include> กับโครงสร้างไดเรกทอรีที่เฉพาะเจาะจง ตารางต่อไปนี้แสดงเส้นทางปลายทางใน iOS ที่สัมพันธ์กับรูทปลายทางการโอน โดยอิงตาม domain ของ Android

Android domain เส้นทางใน iOS (สัมพันธ์กับรูทการโอน)
root app/
file app/files/
database app/databases/
sharedpref app/shared_prefs/
external external/files/
device_root device/app/
device_file device/app/files/
device_database device/app/databases/
device_sharedpref device/app/shared_prefs/

ตัวอย่างเช่น ไฟล์ที่รวมอยู่ใน <include domain="file" path="my_settings.txt"/> จะพร้อมใช้งานในฝั่ง iOS ที่ app/files/my_settings.txt โดยสัมพันธ์กับรูทปลายทางการโอน

ใช้ BackupAgent

แอปที่ใช้การสำรองข้อมูลอัตโนมัติไม่จำเป็นต้องใช้ BackupAgent อย่างไรก็ตาม คุณสามารถเลือกใช้ BackupAgent ที่กำหนดเองได้ โดยทั่วไปแล้ว การดำเนินการนี้มีสาเหตุ 2 ประการดังนี้

  • คุณต้องการรับการแจ้งเตือนเกี่ยวกับเหตุการณ์การสำรองข้อมูล เช่น onRestoreFinished() และ onQuotaExceeded() ระบบจะเรียกใช้เมธอด Callback เหล่านี้แม้ว่าแอปจะไม่ได้ทำงานอยู่ก็ตาม

  • คุณไม่สามารถแสดงชุดไฟล์ที่ต้องการสำรองข้อมูลด้วยกฎ XML ได้โดยง่าย ในกรณีที่เกิดขึ้นไม่บ่อยนักเหล่านี้ คุณสามารถใช้ BackupAgent ที่ลบล้าง onFullBackup(FullBackupDataOutput) เพื่อจัดเก็บสิ่งที่คุณต้องการได้ หากต้องการคงการติดตั้งใช้งานเริ่มต้นของระบบไว้ ให้เรียกใช้เมธอดที่เกี่ยวข้องในคลาสใหญ่สุดด้วย super.onFullBackup()

หากคุณใช้ BackupAgent โดยค่าเริ่มต้น ระบบจะคาดหวังให้แอปของคุณดำเนินการสำรองและกู้คืนคีย์-ค่า หากต้องการใช้การสำรองข้อมูลอัตโนมัติแบบอิงตามไฟล์แทน ให้ตั้งค่าแอตทริบิวต์ android:fullBackupOnly เป็น true ในไฟล์ Manifest ของแอป

ในระหว่างการสำรองข้อมูลอัตโนมัติและกู้คืน ระบบจะเปิดแอปในโหมดที่จำกัดเพื่อป้องกันไม่ให้แอปเข้าถึงไฟล์ที่อาจทำให้เกิดความขัดแย้ง และอนุญาตให้แอปเรียกใช้เมธอด Callback ใน BackupAgent ของแอป ในโหมดที่จำกัดนี้ กิจกรรมหลักของแอปจะไม่เปิดขึ้นโดยอัตโนมัติ Content Provider จะไม่เริ่มต้น และระบบจะสร้างอินสแตนซ์ Application ของคลาสพื้นฐานแทนคลาสย่อยที่ประกาศในไฟล์ Manifest ของแอป

BackupAgent ต้องใช้เมธอดนามธรรม onBackup() และ onRestore() ซึ่งใช้สำหรับการสำรองข้อมูลคีย์-ค่า หากไม่ต้องการสำรองข้อมูลคีย์-ค่า คุณสามารถปล่อยการใช้งานเมธอดเหล่านั้นว่างไว้ได้

ดูข้อมูลเพิ่มเติมได้ที่ขยาย BackupAgent

จัดการการโอนข้ามแพลตฟอร์มใน BackupAgent

ตั้งแต่ Android 16 QPR2 (ระดับ API 36.1) เป็นต้นไป จะมี API ใหม่หลายรายการใน BackupAgent เพื่อรองรับการโอนข้อมูลข้ามแพลตฟอร์มได้ดียิ่งขึ้น

New Transport Flag:

  • FLAG_CROSS_PLATFORM_TRANSFER_IOS: ระบบจะเพิ่มแฟล็กนี้ลงใน transportFlags ที่ส่งไปยัง BackupAgent ของคุณ
    • ใน onFullBackup ระบบจะตั้งค่าแฟล็กนี้หากการดำเนินการสำรองข้อมูลปัจจุบันเป็นส่วนหนึ่งของการส่งออกข้อมูลไปยังอุปกรณ์ iOS
    • ในโอเวอร์โหลด onRestoreFile ใหม่ ระบบจะตั้งค่าแฟล็กนี้หากมีการนำเข้าข้อมูลจากอุปกรณ์ iOS

วิธีใหม่ในการonRestoreFile:

มีการเปิดตัวโอเวอร์โหลดใหม่ของ onRestoreFile ซึ่งใช้พารามิเตอร์ FullRestoreDataInput รายการเดียว ออบเจ็กต์นี้ให้บริบทเพิ่มเติมเกี่ยวกับการดำเนินการกู้คืน ดังนี้

  • FullRestoreDataInput.getTransportFlags(): แสดงผลแฟล็กการส่งสำหรับการดำเนินการกู้คืนปัจจุบัน ซึ่งอาจรวมถึง FLAG_CROSS_PLATFORM_TRANSFER_IOS
  • FullRestoreDataInput.getContentVersion(): แสดงผลสตริงเวอร์ชันเนื้อหาที่แอปพลิเคชันต้นทางระบุไว้ในแพลตฟอร์มอื่นระหว่างการโอนข้ามแพลตฟอร์ม ค่านี้จะเป็นสตริงว่างหากแหล่งที่มาไม่ได้ระบุไว้

วิธีการประมาณขนาดใหม่

  • onEstimateFullBackupBytes(): วิธีนี้ช่วยให้คุณระบุขนาดโดยประมาณของข้อมูลที่แอปต้องการสำรองข้อมูลได้ เราขอแนะนำอย่างยิ่งให้ติดตั้งใช้งานหากแอปของคุณทำการแปลงข้อมูลที่สำคัญระหว่างการสำรองข้อมูลหรือจัดการข้อมูลจำนวนมาก เนื่องจากจะช่วยเพิ่มประสิทธิภาพได้โดยหลีกเลี่ยงการทดสอบระบบเริ่มต้น สำหรับแอปที่มีการสำรองข้อมูลขนาดเล็กและไม่ซับซ้อน โดยทั่วไปแล้ววิธีนี้ไม่จำเป็น

ตัวอย่างการใช้งาน

Kotlin

// In your custom BackupAgent class

override fun onFullBackup(out: FullBackupDataOutput) {
    // Check if this is a cross-platform export to iOS
    if ((out.transportFlags and FLAG_CROSS_PLATFORM_TRANSFER_IOS) != 0) {
        Log.d(TAG, "onFullBackup for iOS transfer")
        // Your custom export logic here
        // Call fullBackupFile() for files to include
    }
}

override fun onRestoreFile(input: FullRestoreDataInput) {
    if ((input.transportFlags and FLAG_CROSS_PLATFORM_TRANSFER_IOS) != 0) {
        val sourceContentVersion = input.contentVersion
        Log.d(TAG, "onRestoreFile from iOS, content version: $sourceContentVersion")
        // Your custom import logic here, using input.data, input.destination, etc.
    }
}

// Optional: Provide an estimate of the backup size
override fun onEstimateFullBackupBytes(): Long {
    return calculateEstimatedBackupSize()
}

Java

// In your custom BackupAgent class

@Override
public void onFullBackup(FullBackupDataOutput out) throws IOException {
    // Check if this is a cross-platform export to iOS
    if ((out.getTransportFlags() & FLAG_CROSS_PLATFORM_TRANSFER_IOS) != 0) {
        Log.d(TAG, "onFullBackup for iOS transfer");
        // Your custom export logic here
        // Call fullBackupFile() for files to include
    }
}

@Override
public void onRestoreFile(FullRestoreDataInput input) {
    if ((input.getTransportFlags() & FLAG_CROSS_PLATFORM_TRANSFER_IOS) != 0) {
        String sourceContentVersion = input.getContentVersion();
        Log.d(TAG, "onRestoreFile from iOS, content version: " + sourceContentVersion);
        // Your custom import logic here, using input.getData(), input.getDestination(), etc.
    }
}

// Optional: Provide an estimate of the backup size
@Override
public long onEstimateFullBackupBytes() {
    return calculateEstimatedBackupSize();
}