บริการสำรองข้อมูล Android ให้บริการสำรองและกู้คืนข้อมูลระบบคลาวด์สำหรับข้อมูลคีย์-ค่าในแอป Android ในระหว่างการดำเนินการสำรองข้อมูลคีย์-ค่า ระบบจะส่งข้อมูลสํารองของแอปไปยังตัวขนส่งข้อมูลสํารองของอุปกรณ์ หากอุปกรณ์ใช้ตัวขนส่งข้อมูลสํารองของ Google เริ่มต้น ระบบจะส่งข้อมูลไปยังบริการสํารองข้อมูล Android เพื่อนําไปเก็บถาวร
ข้อมูลจะจำกัดอยู่ที่ 5 MB ต่อผู้ใช้ 1 คนของแอป โดยไม่มีค่าใช้จ่ายในการจัดเก็บข้อมูลสำรอง
หากต้องการดูภาพรวมของตัวเลือกการสำรองข้อมูลของ Android และคำแนะนำเกี่ยวกับข้อมูลที่คุณ ควรสำรองข้อมูลและคืนค่า โปรดดูการสำรองข้อมูล ภาพรวม
ใช้การสำรองข้อมูลคีย์-ค่า
หากต้องการสำรองข้อมูลแอป คุณต้องใช้ Agent สำรอง ข้อมูลสำรองของคุณ เครื่องมือจัดการการสำรองข้อมูลจะเรียก Agent ทั้งในระหว่างการสำรองข้อมูลและการกู้คืน
หากต้องการใช้ Agent สำรอง คุณต้องดำเนินการดังนี้
ประกาศ Agent ข้อมูลสำรองในไฟล์ Manifest ด้วยเมธอด
android:backupAgent
กำหนด Agent สำรองโดยทำอย่างใดอย่างหนึ่งต่อไปนี้
-
ชั้นเรียน
BackupAgent
มีอินเทอร์เฟซส่วนกลางที่แอปของคุณใช้เพื่อสื่อสารกับ เครื่องมือจัดการการสำรองข้อมูล หากขยายคลาสนี้โดยตรง คุณต้องลบล้างonBackup()
และonRestore()
เพื่อจัดการการดำเนินการสำรองและกู้คืนข้อมูล -
คลาส
BackupAgentHelper
เป็นตัวช่วยที่สะดวกสำหรับคลาสBackupAgent
ซึ่งจะช่วยลดปริมาณโค้ดที่คุณต้องเขียน ในBackupAgentHelper
คุณต้องใช้ออบเจ็กต์ตัวช่วยอย่างน้อย 1 รายการ สำรองข้อมูลและคืนค่าข้อมูลบางประเภทโดยอัตโนมัติ เพื่อที่คุณไม่ต้อง ต้องติดตั้งใช้งานonBackup()
และonRestore()
เราขอแนะนำให้ใช้BackupAgentHelper
เพื่อจัดการข้อมูลสำรองของแอป เว้นแต่ว่าคุณต้องการควบคุมข้อมูลสำรองของแอปอย่างเต็มรูปแบบปัจจุบัน Android มีเครื่องมือช่วยสํารองข้อมูลที่จะสํารองและกู้คืนไฟล์ที่สมบูรณ์จาก
SharedPreferences
และพื้นที่เก็บข้อมูลภายใน
-
ประกาศตัวแทนการสำรองข้อมูลในไฟล์ Manifest
เมื่อเลือกชื่อคลาสสำหรับตัวแทนการสำรองข้อมูลแล้ว ให้ประกาศชื่อนั้นในไฟล์ Manifest โดยใช้แอตทริบิวต์ android:backupAgent
ในแท็ก <application>
เช่น
<manifest ... > ... <application android:label="MyApplication" android:backupAgent="MyBackupAgent"> <meta-data android:name="com.google.android.backup.api_key" android:value="unused" /> <activity ... > ... </activity> </application> </manifest>
หากต้องการรองรับอุปกรณ์รุ่นเก่า เราขอแนะนำให้เพิ่มคีย์ API <meta-data>
ลงในไฟล์ Manifest ของ Android Android Backup Service ไม่จำเป็นต้องใช้คีย์บริการอีกต่อไป แต่อุปกรณ์รุ่นเก่าบางรุ่นอาจยังตรวจสอบคีย์เมื่อสำรองข้อมูล ตั้งค่า android:name
เป็น com.google.android.backup.api_key
และ
android:value
ถึง unused
แอตทริบิวต์ android:restoreAnyVersion
ใช้ค่าบูลีนเพื่อระบุว่าคุณต้องการกู้คืนข้อมูลแอปหรือไม่ โดยไม่คำนึงถึงเวอร์ชันปัจจุบันของแอปเทียบกับเวอร์ชันที่สร้างข้อมูลสํารอง ค่าเริ่มต้นคือ false
ดูข้อมูลเพิ่มเติมได้ที่ตรวจสอบเวอร์ชันข้อมูลการกู้คืน
ขยาย BackupAgentHelper
คุณควรสร้าง Agent สำรองโดยใช้ BackupAgentHelper
หากต้องการ
สำรองไฟล์ที่สมบูรณ์จาก SharedPreferences
หรือที่จัดเก็บข้อมูลภายใน
การสร้าง Agent สำรองด้วย BackupAgentHelper
ต้องใช้โค้ดน้อยกว่ามาก
ขยายเวลาของ BackupAgent
เพราะคุณไม่ต้องติดตั้งใช้งาน onBackup()
และ
onRestore()
การใช้งาน BackupAgentHelper
ต้องใช้ผู้ช่วยเหลือในการสำรองข้อมูลอย่างน้อย 1 ราย
ผู้ช่วยสำรองคือคอมโพเนนต์พิเศษที่ BackupAgentHelper
เรียกใช้
ทำการสำรองและกู้คืนข้อมูลสำหรับข้อมูลประเภทใดประเภทหนึ่ง ปัจจุบันเฟรมเวิร์ก Android มีตัวช่วย 2 รายการ ได้แก่
SharedPreferencesBackupHelper
เพื่อสำรองข้อมูลไฟล์SharedPreferences
FileBackupHelper
ถึงด้านหลัง ไฟล์จากที่จัดเก็บข้อมูลภายใน
คุณสามารถใส่ผู้ช่วยได้หลายคนในBackupAgentHelper
แต่ทำได้แค่คนเดียว
ข้อมูลแต่ละประเภทจะต้องใช้ตัวช่วย กล่าวคือ หากคุณมีไฟล์ SharedPreferences
หลายไฟล์ คุณต้องใช้ SharedPreferencesBackupHelper
เพียงไฟล์เดียว
สำหรับผู้ช่วยแต่ละคนที่คุณต้องการเพิ่มลงใน BackupAgentHelper
คุณจะต้องทำ
การติดตามระหว่าง
เมธอด onCreate()
:
- สร้างอินสแตนซ์ของคลาสตัวช่วยที่ต้องการ ในคอนสตรัคเตอร์ของคลาส คุณต้องระบุไฟล์ที่ต้องการสํารองข้อมูล
- โทรไปที่
addHelper()
เพื่อเพิ่มผู้ช่วยลงในBackupAgentHelper
ส่วนต่อไปนี้จะอธิบายวิธีสร้าง Agent สำรองโดยใช้ ผู้ช่วยเหลือที่พร้อมให้บริการ
สำรองข้อมูล SharedPreferences
เมื่อสร้างอินสแตนซ์ SharedPreferencesBackupHelper
คุณต้องระบุชื่อไฟล์ SharedPreferences
อย่างน้อย 1 ไฟล์
ตัวอย่างเช่น หากต้องการสำรองข้อมูลไฟล์ SharedPreferences
ที่ชื่อ user_preferences
ตัวแทนการสำรองข้อมูลแบบสมบูรณ์ที่ใช้ BackupAgentHelper
จะมีลักษณะดังนี้
Kotlin
// The name of the SharedPreferences file const val PREFS = "user_preferences" // A key to uniquely identify the set of backup data const val PREFS_BACKUP_KEY = "prefs" class MyPrefsBackupAgent : BackupAgentHelper() { override fun onCreate() { // Allocate a helper and add it to the backup agent SharedPreferencesBackupHelper(this, PREFS).also { addHelper(PREFS_BACKUP_KEY, it) } } }
Java
public class MyPrefsBackupAgent extends BackupAgentHelper { // The name of the SharedPreferences file static final String PREFS = "user_preferences"; // A key to uniquely identify the set of backup data static final String PREFS_BACKUP_KEY = "prefs"; // Allocate a helper and add it to the backup agent @Override public void onCreate() { SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, PREFS); addHelper(PREFS_BACKUP_KEY, helper); } }
SharedPreferencesBackupHelper
มีโค้ดทั้งหมดที่จำเป็นในการสำรองและกู้คืนไฟล์ SharedPreferences
เมื่อผู้จัดการสำรองโทรหา onBackup()
และ onRestore()
BackupAgentHelper
จะโทรหาผู้ช่วยสำรองข้อมูลเพื่อสำรองข้อมูลและกู้คืน
ไฟล์ที่ระบุ
สำรองไฟล์อื่นๆ
เมื่อสร้างอินสแตนซ์ FileBackupHelper
คุณต้องระบุชื่อของ
บันทึกไฟล์ลงในที่จัดเก็บข้อมูลภายในของแอป ตามที่ระบุโดย
getFilesDir()
,
ซึ่งเป็นตำแหน่งเดียวกับที่
openFileOutput()
เขียนไฟล์
เช่น หากต้องการสำรองข้อมูล 2 ไฟล์ชื่อ scores
และ stats
ซึ่งเป็น Agent ข้อมูลสำรอง
ที่ใช้ BackupAgentHelper
จะมีลักษณะดังนี้
Kotlin
// The name of the file const val TOP_SCORES = "scores" const val PLAYER_STATS = "stats" // A key to uniquely identify the set of backup data const val FILES_BACKUP_KEY = "myfiles" class MyFileBackupAgent : BackupAgentHelper() { override fun onCreate() { // Allocate a helper and add it to the backup agent FileBackupHelper(this, TOP_SCORES, PLAYER_STATS).also { addHelper(FILES_BACKUP_KEY, it) } } }
Java
public class MyFileBackupAgent extends BackupAgentHelper { // The name of the file static final String TOP_SCORES = "scores"; static final String PLAYER_STATS = "stats"; // A key to uniquely identify the set of backup data static final String FILES_BACKUP_KEY = "myfiles"; // Allocate a helper and add it to the backup agent @Override public void onCreate() { FileBackupHelper helper = new FileBackupHelper(this, TOP_SCORES, PLAYER_STATS); addHelper(FILES_BACKUP_KEY, helper); } }
FileBackupHelper
มีโค้ดทั้งหมดที่จำเป็นในการสำรองและกู้คืนข้อมูล
ไฟล์ที่บันทึกไว้ในที่จัดเก็บข้อมูลภายในของแอป
อย่างไรก็ตาม การอ่านและการเขียนไฟล์ในที่จัดเก็บข้อมูลภายในไม่ปลอดภัยสำหรับเธรด คุณต้องใช้คำสั่งแบบซิงค์ทุกครั้งที่อ่านหรือเขียนเพื่อให้มั่นใจว่าตัวแทนการสำรองข้อมูลจะไม่อ่านหรือเขียนไฟล์ในเวลาเดียวกับที่คุณดำเนินการ ตัวอย่างเช่น ในกิจกรรมใดก็ตามที่คุณอ่านและเขียนไฟล์ คุณต้องมีออบเจ็กต์ที่จะใช้เป็นล็อกภายในสำหรับคำสั่งแบบซิงค์
Kotlin
// Object for intrinsic lock companion object { val sDataLock = Any() }
Java
// Object for intrinsic lock static final Object sDataLock = new Object();
จากนั้นสร้างคำสั่งที่ซิงค์กับการล็อกนี้ทุกครั้งที่คุณอ่านหรือเขียนไฟล์ เช่น ต่อไปนี้เป็นข้อความที่ซิงค์สำหรับการเขียนข้อมูลล่าสุด ทำคะแนนในเกมเป็นไฟล์:
Kotlin
try { synchronized(MyActivity.sDataLock) { val dataFile = File(filesDir, TOP_SCORES) RandomAccessFile(dataFile, "rw").apply { writeInt(score) } } } catch (e: IOException) { Log.e(TAG, "Unable to write to file") }
Java
try { synchronized (MyActivity.sDataLock) { File dataFile = new File(getFilesDir(), TOP_SCORES); RandomAccessFile raFile = new RandomAccessFile(dataFile, "rw"); raFile.writeInt(score); } } catch (IOException e) { Log.e(TAG, "Unable to write to file"); }
คุณควรซิงค์ข้อความการอ่านด้วยล็อกเดียวกัน
จากนั้นใน BackupAgentHelper
คุณต้องลบล้าง onBackup()
และ
onRestore()
เพื่อซิงค์การดำเนินการสำรองและกู้คืนข้อมูล
ล็อกภายใน ตัวอย่างเช่น ตัวอย่าง MyFileBackupAgent
จากด้านบนต้องใช้วิธีการต่อไปนี้
Kotlin
@Throws(IOException::class) override fun onBackup( oldState: ParcelFileDescriptor, data: BackupDataOutput, newState: ParcelFileDescriptor ) { // Hold the lock while the FileBackupHelper performs back up synchronized(MyActivity.sDataLock) { super.onBackup(oldState, data, newState) } } @Throws(IOException::class) override fun onRestore( data: BackupDataInput, appVersionCode: Int, newState: ParcelFileDescriptor ) { // Hold the lock while the FileBackupHelper restores the file synchronized(MyActivity.sDataLock) { super.onRestore(data, appVersionCode, newState) } }
Java
@Override public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException { // Hold the lock while the FileBackupHelper performs back up synchronized (MyActivity.sDataLock) { super.onBackup(oldState, data, newState); } } @Override public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException { // Hold the lock while the FileBackupHelper restores the file synchronized (MyActivity.sDataLock) { super.onRestore(data, appVersionCode, newState); } }
ขยาย BackupAgent
แอปส่วนใหญ่ไม่ควรต้องขยายคลาส BackupAgent
โดยตรง แต่ควร
แต่ให้ขยาย BackupAgentHelper
เพื่อใช้ประโยชน์จาก
ชั้นเรียนตัวช่วยแบบบิวท์อินที่จะสำรองและกู้คืนไฟล์ของคุณโดยอัตโนมัติ
อย่างไรก็ตาม คุณอาจขยาย BackupAgent
โดยตรงเพื่อดำเนินการต่อไปนี้
- กำหนดเวอร์ชันรูปแบบข้อมูล ตัวอย่างเช่น หากคาดว่าจะต้องแก้ไขรูปแบบที่คุณเขียนข้อมูลแอป ให้สร้างตัวแทนการสำรองข้อมูลเพื่อตรวจสอบเวอร์ชันแอประหว่างการดำเนินการกู้คืน และดำเนินการที่จำเป็นเพื่อตรวจสอบความเข้ากันได้หากเวอร์ชันในอุปกรณ์แตกต่างจากเวอร์ชันของข้อมูลสํารอง โปรดดูข้อมูลเพิ่มเติมที่หัวข้อตรวจสอบการกู้คืน เวอร์ชันข้อมูล
- ระบุส่วนของข้อมูลที่จะสํารอง คุณสามารถระบุส่วนของข้อมูลที่จะสำรองและวิธีกู้คืนแต่ละส่วนไปยังอุปกรณ์แทนการสำรองข้อมูลทั้งไฟล์ วิธีนี้ยังช่วยให้คุณจัดการกับ เพราะคุณอ่านและเขียนข้อมูลเป็นเอนทิตีที่ไม่ซ้ำกัน แต่ กว่าไฟล์สมบูรณ์
- สำรองข้อมูลในฐานข้อมูล หากมีฐานข้อมูล SQLite ที่ต้องการกู้คืนเมื่อผู้ใช้ติดตั้งแอปอีกครั้ง คุณจะต้องสร้าง
BackupAgent
ที่กําหนดเองซึ่งจะอ่านข้อมูลที่เหมาะสมระหว่างการดำเนินการสำรองข้อมูล จากนั้นสร้างตารางและแทรกข้อมูลระหว่างการดำเนินการกู้คืน
หากไม่จําเป็นต้องทํางานใดๆ ข้างต้นและต้องการสํารองข้อมูลไฟล์ทั้งหมดจาก SharedPreferences
หรือพื้นที่เก็บข้อมูลภายใน โปรดดูการขยายBackupAgentHelper
เมธอดที่จำเป็น
เมื่อสร้าง BackupAgent
คุณต้องติดตั้งใช้งานเมธอดการเรียกกลับต่อไปนี้
onBackup()
- เครื่องมือจัดการข้อมูลสํารองจะเรียกใช้เมธอดนี้หลังจากที่คุณขอสํารองข้อมูล วิธีนี้ให้คุณอ่านข้อมูลแอปจาก อุปกรณ์ของคุณและส่งข้อมูลที่คุณต้องการสำรองไปยังเครื่องมือจัดการการสำรองข้อมูล ตามที่อธิบายไว้ในหัวข้อดำเนินการสำรองข้อมูล
onRestore()
ตัวจัดการข้อมูลสํารองจะเรียกใช้เมธอดนี้ในระหว่างการดําเนินการกู้คืน วิธีนี้ จะส่งข้อมูลสำรองของคุณ ซึ่งแอปสามารถใช้เพื่อคืนค่าข้อมูลเดิม ตามที่อธิบายไว้ในดำเนินการกู้คืน
ระบบจะเรียกใช้เมธอดนี้เพื่อกู้คืนข้อมูลสำรองเมื่อผู้ใช้ติดตั้งแอปของคุณอีกครั้ง แต่แอปของคุณก็ขอการกู้คืนได้เช่นกัน
สำรองข้อมูล
คำขอสำรองจะไม่ส่งผลให้คุณโทรหา onBackup()
ทันที
แต่เครื่องมือจัดการข้อมูลสํารองจะรอเวลาที่เหมาะสม จากนั้นจะสํารองข้อมูลสําหรับแอปทั้งหมดที่ขอสํารองข้อมูลนับตั้งแต่ที่สํารองข้อมูลครั้งล่าสุด ขั้นตอนนี้เป็นเวลาที่คุณต้องให้ข้อมูลแอปแก่เครื่องมือจัดการข้อมูลสํารองเพื่อให้บันทึกข้อมูลลงในพื้นที่เก็บข้อมูลระบบคลาวด์ได้
มีเพียงเครื่องมือจัดการการสำรองข้อมูลเท่านั้นที่จะเรียกเมธอด onBackup()
ของ Agent สำรองได้ ชิ้น
ทุกครั้งที่ข้อมูลแอปเปลี่ยนไป และคุณต้องการสำรองข้อมูล คุณต้อง
ขอการดำเนินการสำรองข้อมูลโดยการเรียกใช้
dataChanged()
โปรดดูข้อมูลเพิ่มเติมที่ขอข้อมูลสำรอง
เคล็ดลับ: ขณะพัฒนาแอป คุณจะเริ่มสำรองข้อมูลได้ทันที
จากเครื่องมือจัดการการสำรองข้อมูลที่มี bmgr
เครื่องมือ
เมื่อเครื่องมือจัดการข้อมูลสํารองเรียกใช้เมธอด onBackup()
ระบบจะส่งพารามิเตอร์ 3 รายการต่อไปนี้
oldState
- ไฟล์
ParcelFileDescriptor
แบบเปิดที่อ่านอย่างเดียวซึ่งชี้ไปที่สถานะการสำรองข้อมูลล่าสุดที่แอปของคุณระบุ ไม่ใช่ข้อมูลสำรองจากพื้นที่เก็บข้อมูลระบบคลาวด์ แต่เป็นการแสดงข้อมูลสำรองในพื้นที่เก็บข้อมูลในเครื่องเมื่อมีการเรียกใช้onBackup()
ครั้งล่าสุดตามที่ระบุโดยnewState
หรือจากonRestore()
เราจะกล่าวถึงonRestore()
ในส่วนถัดไป เพราะonBackup()
ไม่อนุญาตให้คุณอ่านข้อมูลสำรองที่มีอยู่ในระบบคลาวด์ คุณสามารถใช้การนำเสนอภายในเครื่องเพื่อพิจารณาว่าข้อมูลของคุณ เปลี่ยนแปลงไปจากการสำรองข้อมูลครั้งล่าสุด data
- ออบเจ็กต์
BackupDataOutput
ใช้เพื่อส่งข้อมูลสํารองไปยังเครื่องมือจัดการข้อมูลสํารอง newState
ParcelFileDescriptor
แบบอ่าน/เขียนที่เปิดอยู่ซึ่งชี้ไปยังไฟล์ที่คุณต้องใช้เขียนการนำเสนอข้อมูลที่ส่งไปยังdata
ต แสดงแทนได้ง่ายขึ้น เช่น การประทับเวลาที่แก้ไขล่าสุดสำหรับไฟล์ ออบเจ็กต์นี้จะแสดงผลเป็นoldState
ในครั้งถัดไปที่เรียกใช้ Backup Manager เมธอดonBackup()
หากคุณไม่ได้เขียนข้อมูลสำรองลงในnewState
จากนั้นoldState
จะชี้ไปที่ไฟล์ว่างเมื่อเรียกผู้จัดการสำรองในครั้งถัดไปonBackup()
ใช้พารามิเตอร์เหล่านี้และใช้เมธอด onBackup()
เพื่อทำสิ่งต่อไปนี้
ตรวจสอบว่าข้อมูลเปลี่ยนแปลงไปหรือไม่นับจากการสำรองข้อมูลครั้งล่าสุดโดยการเปรียบเทียบ
oldState
ไปยังข้อมูลปัจจุบันของคุณ วิธีอ่านข้อมูลในoldState
จะขึ้นอยู่กับวิธีเขียนข้อมูลไปยังnewState
เดิม (ดูขั้นตอนที่ 3) วิธีที่ง่ายที่สุดในการ บันทึกสถานะของไฟล์เป็นการประทับเวลาที่แก้ไขล่าสุด ตัวอย่างเช่น วิธีอ่านและเปรียบเทียบการประทับเวลาจากoldState
มีดังนี้Kotlin
val instream = FileInputStream(oldState.fileDescriptor) val dataInputStream = DataInputStream(instream) try { // Get the last modified timestamp from the state file and data file val stateModified = dataInputStream.readLong() val fileModified: Long = dataFile.lastModified() if (stateModified != fileModified) { // The file has been modified, so do a backup // Or the time on the device changed, so be safe and do a backup } else { // Don't back up because the file hasn't changed return } } catch (e: IOException) { // Unable to read state file... be safe and do a backup }
Java
// Get the oldState input stream FileInputStream instream = new FileInputStream(oldState.getFileDescriptor()); DataInputStream in = new DataInputStream(instream); try { // Get the last modified timestamp from the state file and data file long stateModified = in.readLong(); long fileModified = dataFile.lastModified(); if (stateModified != fileModified) { // The file has been modified, so do a backup // Or the time on the device changed, so be safe and do a backup } else { // Don't back up because the file hasn't changed return; } } catch (IOException e) { // Unable to read state file... be safe and do a backup }
หากไม่มีอะไรเปลี่ยนแปลงและคุณไม่จำเป็นต้องสำรองข้อมูล ให้ข้ามไปยังขั้นตอนที่ 3
หากข้อมูลมีการเปลี่ยนแปลงเมื่อเทียบกับ
oldState
ให้เขียนข้อมูลปัจจุบันลงในdata
เพื่อสำรองข้อมูลไปยังพื้นที่เก็บข้อมูลระบบคลาวด์คุณต้องเขียนข้อมูลแต่ละส่วนเป็นเอนทิตีใน
BackupDataOutput
CANNOT TRANSLATE เอนทิตีคือระเบียนข้อมูลไบนารีที่แยกเป็นหลายรายการซึ่งระบุโดยคีย์ที่ไม่ซ้ำกัน สตริง ดังนั้น ชุดข้อมูลที่คุณสำรองข้อมูลในแนวคิดชุด คู่คีย์-ค่าหากต้องการเพิ่มเอนทิตีไปยังชุดข้อมูลสำรอง คุณต้องดำเนินการดังนี้
โทรไปที่
writeEntityHeader()
โดยส่งคีย์สตริงที่ไม่ซ้ำกันสำหรับข้อมูลที่คุณกำลังจะเขียนและขนาดข้อมูลโทรไปที่
writeEntityData()
โดยส่งบัฟเฟอร์ไบต์ที่มีข้อมูลและจํานวนไบต์ที่จะเขียนจากบัฟเฟอร์ ซึ่งควรตรงกับขนาดที่ส่งไปยังwriteEntityHeader()
ตัวอย่างเช่น โค้ดต่อไปนี้จะผสานข้อมูลบางส่วนเป็นสตรีมไบต์และเขียนลงในเอนทิตีเดียว
Kotlin
val buffer: ByteArray = ByteArrayOutputStream().run { DataOutputStream(this).apply { writeInt(playerName) writeInt(playerScore) } toByteArray() } val len: Int = buffer.size data.apply { writeEntityHeader(TOPSCORE_BACKUP_KEY, len) writeEntityData(buffer, len) }
Java
// Create buffer stream and data output stream for our data ByteArrayOutputStream bufStream = new ByteArrayOutputStream(); DataOutputStream outWriter = new DataOutputStream(bufStream); // Write structured data outWriter.writeUTF(playerName); outWriter.writeInt(playerScore); // Send the data to the Backup Manager via the BackupDataOutput byte[] buffer = bufStream.toByteArray(); int len = buffer.length; data.writeEntityHeader(TOPSCORE_BACKUP_KEY, len); data.writeEntityData(buffer, len);
ดำเนินการนี้สำหรับข้อมูลแต่ละรายการที่ต้องการสำรองข้อมูล คุณแบ่งข้อมูลออกเป็นเอนทิตีอย่างไรก็ได้ คุณอาจใช้เอนทิตีเพียงรายการเดียวก็ได้
ไม่ว่าคุณจะสำรองข้อมูลหรือไม่ (ในขั้นตอนที่ 2) ให้เขียนการนำเสนอข้อมูลปัจจุบันลงใน
newState
ParcelFileDescriptor
Backup Manager จะเก็บออบเจ็กต์นี้ไว้ในเครื่องเพื่อแสดงข้อมูลที่สำรองข้อมูลไว้ในปัจจุบัน ครั้งต่อไปจะส่งข้อมูลนี้กลับมาให้คุณด้วยชื่อoldState
จะเรียกonBackup()
เพื่อให้คุณสามารถระบุได้ว่าข้อมูลสำรองอีกรายการหนึ่งคือ ตามขั้นตอนที่ 1 หากคุณไม่ได้เขียนสถานะข้อมูลปัจจุบันลงในไฟล์นี้oldState
จะว่างเปล่าระหว่างการเรียกกลับครั้งถัดไปตัวอย่างต่อไปนี้จะบันทึกการนำเสนอข้อมูลปัจจุบันลงใน
newState
ใช้การประทับเวลาที่แก้ไขล่าสุดของไฟล์:Kotlin
val modified = dataFile.lastModified() FileOutputStream(newState.fileDescriptor).also { DataOutputStream(it).apply { writeLong(modified) } }
Java
FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor()); DataOutputStream out = new DataOutputStream(outstream); long modified = dataFile.lastModified(); out.writeLong(modified);
ดำเนินการคืนค่า
เมื่อถึงเวลากู้คืนข้อมูลแอป ตัวจัดการข้อมูลสำรองจะเรียกใช้ข้อมูลสำรอง
เมธอด onRestore()
ของตัวแทน เมื่อเรียกใช้เมธอดนี้ เครื่องมือจัดการข้อมูลสำรองจะส่งข้อมูลสำรองให้คุณกู้คืนลงในอุปกรณ์
มีเพียงผู้จัดการสำรองเท่านั้นที่โทรหา onRestore()
ได้ ซึ่งจะเกิดขึ้นโดยอัตโนมัติ
เมื่อระบบติดตั้งแอปของคุณและพบข้อมูลสำรองที่มีอยู่
เมื่อผู้จัดการสำรองเรียกเมธอด onRestore()
เมธอดจะผ่านสาม
ได้แก่
data
- ออบเจ็กต์
BackupDataInput
ซึ่งช่วยให้คุณอ่านข้อมูลสำรองได้ appVersionCode
- จำนวนเต็มแสดงค่าของแอตทริบิวต์ไฟล์ Manifest ของแอป
android:versionCode
ตามที่บันทึกไว้เมื่อสำรองข้อมูลนี้ คุณใช้ เพื่อตรวจสอบเวอร์ชันปัจจุบันของแอปและดูว่ารูปแบบข้อมูล ที่เข้ากันได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ตัวเลือกนี้เพื่อจัดการข้อมูลการกู้คืนเวอร์ชันต่างๆ ได้ที่ตรวจสอบเวอร์ชันข้อมูลการกู้คืน newState
ParcelFileDescriptor
ที่เปิดอยู่ซึ่งอ่าน/เขียนซึ่งชี้ไปยังไฟล์ที่คุณ ต้องเขียนสถานะการสำรองข้อมูลสุดท้ายที่ให้ไว้กับdata
ระบบจะแสดงผลออบเจ็กต์นี้เป็นoldState
เมื่อเรียกใช้onBackup()
ในครั้งถัดไป โปรดทราบว่าคุณต้องเขียนออบเจ็กต์newState
เดียวกันในonBackup()
callback ด้วย ซึ่งการเขียนที่นี่จะช่วยให้ออบเจ็กต์oldState
ที่ส่งให้กับonBackup()
ใช้งานได้แม้ในครั้งแรกที่เรียกใช้onBackup()
หลังจากกู้คืนอุปกรณ์แล้ว
ในการใช้งาน onRestore()
คุณควรเรียกใช้
readNextHeader()
ในวันที่ data
เพื่อทำซ้ำผ่านเอนทิตีทั้งหมดในชุดข้อมูล สำหรับเอนทิตีแต่ละรายการ
ที่พบ ให้ทำตามขั้นตอนต่อไปนี้
- รับคีย์เอนทิตีด้วย
getKey()
เปรียบเทียบคีย์เอนทิตีกับรายการค่าคีย์ที่รู้จักซึ่งคุณควรมี ประกาศเป็นสตริงสุดท้ายแบบคงที่ภายในคลาส
BackupAgent
ของคุณ เมื่อคีย์ตรงกับสตริงคีย์ที่คุณรู้จัก ให้ป้อนคำสั่งเพื่อดึงข้อมูลเอนทิตีและบันทึกลงในอุปกรณ์- ดูขนาดข้อมูลเอนทิตีด้วย
getDataSize()
และสร้างไบต์อาร์เรย์ขนาดดังกล่าว - โทร
readEntityData()
แล้วส่งไบต์อาร์เรย์ ซึ่งเป็นจุดที่ข้อมูลจะไป และระบุ ออฟเซ็ตเริ่มต้นและขนาดที่จะอ่าน - ไบต์อาร์เรย์ของคุณเต็มแล้ว อ่านข้อมูลและเขียนลงในอุปกรณ์ อย่างไรก็ได้ตามที่คุณต้องการ
- ดูขนาดข้อมูลเอนทิตีด้วย
หลังจากที่อ่านและเขียนข้อมูลกลับไปยังอุปกรณ์แล้ว ให้เขียนสถานะ ข้อมูลลงในพารามิเตอร์
newState
เช่นเดียวกับที่ทำระหว่างonBackup()
ตัวอย่างวิธีคืนค่าข้อมูลที่สำรองไว้ในตัวอย่าง ส่วนก่อนหน้า:
Kotlin
@Throws(IOException::class) override fun onRestore(data: BackupDataInput, appVersionCode: Int, newState: ParcelFileDescriptor) { with(data) { // There should be only one entity, but the safest // way to consume it is using a while loop while (readNextHeader()) { when(key) { TOPSCORE_BACKUP_KEY -> { val dataBuf = ByteArray(dataSize).also { readEntityData(it, 0, dataSize) } ByteArrayInputStream(dataBuf).also { DataInputStream(it).apply { // Read the player name and score from the backup data playerName = readUTF() playerScore = readInt() } // Record the score on the device (to a file or something) recordScore(playerName, playerScore) } } else -> skipEntityData() } } } // Finally, write to the state blob (newState) that describes the restored data FileOutputStream(newState.fileDescriptor).also { DataOutputStream(it).apply { writeUTF(playerName) writeInt(mPlayerScore) } } }
Java
@Override public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException { // There should be only one entity, but the safest // way to consume it is using a while loop while (data.readNextHeader()) { String key = data.getKey(); int dataSize = data.getDataSize(); // If the key is ours (for saving top score). Note this key was used when // we wrote the backup entity header if (TOPSCORE_BACKUP_KEY.equals(key)) { // Create an input stream for the BackupDataInput byte[] dataBuf = new byte[dataSize]; data.readEntityData(dataBuf, 0, dataSize); ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf); DataInputStream in = new DataInputStream(baStream); // Read the player name and score from the backup data playerName = in.readUTF(); playerScore = in.readInt(); // Record the score on the device (to a file or something) recordScore(playerName, playerScore); } else { // We don't know this entity key. Skip it. (Shouldn't happen.) data.skipEntityData(); } } // Finally, write to the state blob (newState) that describes the restored data FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor()); DataOutputStream out = new DataOutputStream(outstream); out.writeUTF(playerName); out.writeInt(mPlayerScore); }
ในตัวอย่างนี้ ระบบจะไม่ใช้พารามิเตอร์ appVersionCode
ที่ส่งไปยัง onRestore()
แต่คุณอาจต้องใช้ฟีเจอร์นี้หากคุณเลือกที่จะสำรองข้อมูล
เมื่อเวอร์ชันแอปของผู้ใช้เลื่อนไปข้างหลังจริงๆ (เช่น
ผู้ใช้เปลี่ยนจากแอปเวอร์ชัน 1.5 ไปเป็น 1.0) ดูข้อมูลเพิ่มเติมได้ที่ส่วนถัดไป
ตรวจสอบเวอร์ชันข้อมูลการกู้คืน
เมื่อเครื่องมือจัดการการสำรองข้อมูลบันทึกข้อมูลลงในพื้นที่เก็บข้อมูลระบบคลาวด์ ระบบจะดำเนินการดังกล่าวโดยอัตโนมัติ
มีเวอร์ชันของแอปตามที่กำหนดโดยไฟล์ Manifest
android:versionCode
ก่อนที่ผู้จัดการข้อมูลสำรองจะเรียกใช้ข้อมูลสำรอง
Agent ของคุณเพื่อกู้คืนข้อมูล
มันจะดูที่ android:versionCode
ของ
แอปที่ติดตั้งแล้วเปรียบเทียบกับค่าที่บันทึกไว้ในชุดข้อมูลคืนค่า ถ้า
เวอร์ชันที่บันทึกไว้ในชุดข้อมูลคืนค่าใหม่กว่าเวอร์ชันแอปใน
อุปกรณ์ จากนั้นผู้ใช้ได้ดาวน์เกรดแอปของตน ในกรณีนี้ ข้อมูลสำรอง
ผู้จัดการจะล้มเลิกการดำเนินการกู้คืนแอปของคุณและไม่เรียกใช้
onRestore()
เนื่องจากชุดการคืนค่าถือว่าไม่มีความหมายสำหรับ
เวอร์ชันเก่า
คุณลบล้างลักษณะการทำงานนี้ได้ด้วยแอตทริบิวต์ android:restoreAnyVersion
ตั้งค่าแอตทริบิวต์นี้เป็น true
เพื่อระบุว่าคุณต้องการกู้คืนแอป
โดยไม่คำนึงถึงเวอร์ชันที่คืนค่าเวอร์ชัน ค่าเริ่มต้นคือ false
หากคุณ
ตั้งค่าเป็น true
จากนั้นเครื่องมือจัดการการสำรองข้อมูลจะไม่สนใจ
android:versionCode
และเรียกเมธอด onRestore()
ในทุกกรณี กำลังทำ
คุณจึงตรวจสอบความแตกต่างของเวอร์ชันด้วยตนเองได้ใน onRestore()
และดำเนินการตามขั้นตอนที่จำเป็นเพื่อทำให้ข้อมูลใช้งานร่วมกันได้หากเวอร์ชัน
ไม่ตรง
เพื่อช่วยคุณจัดการเวอร์ชันต่างๆ ในระหว่างดำเนินการกู้คืน
เมธอด onRestore()
จะส่งรหัสเวอร์ชันที่มาพร้อมกับข้อมูลการคืนค่าให้คุณ
ตั้งค่าเป็นพารามิเตอร์ appVersionCode
จากนั้นคุณสามารถค้นหารหัสเวอร์ชันของแอปปัจจุบันได้โดยใช้ช่อง PackageInfo.versionCode
เช่น
Kotlin
val info: PackageInfo? = try { packageManager.getPackageInfo(packageName, 0) } catch (e: PackageManager.NameNotFoundException) { null } val version: Int = info?.versionCode ?: 0
Java
PackageInfo info; try { String name = getPackageName(); info = getPackageManager().getPackageInfo(name, 0); } catch (NameNotFoundException nnfe) { info = null; } int version; if (info != null) { version = info.versionCode; }
จากนั้นเปรียบเทียบ version
ที่ได้จาก PackageInfo
กับ appVersionCode
ที่ส่งไปยัง onRestore()
ขอข้อมูลสํารอง
คุณขอให้ดำเนินการสำรองข้อมูลได้ทุกเมื่อโดยโทรไปที่หมายเลข dataChanged()
วิธีนี้จะแจ้งให้เครื่องมือจัดการการสำรองข้อมูลทราบว่าคุณต้องการสำรองข้อมูลโดยใช้ตัวแทนการสำรองข้อมูล จากนั้นเครื่องมือจัดการข้อมูลสำรองจะเรียกใช้เมธอด onBackup()
ของตัวแทนการสำรองข้อมูลในอนาคต โดยปกติแล้ว คุณควรขอการสํารองข้อมูลทุกครั้งที่มีการเปลี่ยนแปลงข้อมูล (เช่น เมื่อผู้ใช้เปลี่ยนค่ากําหนดของแอปที่คุณต้องการสํารองข้อมูล) หากคุณโทรหา dataChanged()
หลายหมายเลข
จำนวนครั้งก่อนที่เครื่องมือจัดการข้อมูลสำรองจะส่งคำขอข้อมูลสำรองจากตัวแทนของคุณ
ยังคงได้รับโทรศัพท์จาก onBackup()
เพียงครั้งเดียว
ขอกู้คืน
ในระหว่างการใช้งานแอปตามปกติ คุณไม่ควรต้องส่งคำขอการดำเนินการกู้คืน ระบบจะตรวจสอบข้อมูลสำรองโดยอัตโนมัติและดำเนินการ คืนค่าเมื่อมีการติดตั้งแอปของคุณ
ย้ายข้อมูลไปยังการสำรองข้อมูลอัตโนมัติ
คุณสามารถเปลี่ยนแอปเป็นการสำรองข้อมูลทั้งหมดได้โดยการตั้งค่า android:fullBackupOnly
เป็น true
ในองค์ประกอบ <application>
ในไฟล์ Manifest เมื่อทำงานในอุปกรณ์ที่ใช้ Android 5.1 (API ระดับ 22) หรือต่ำกว่า แอปจะละเว้นค่านี้ในไฟล์ Manifest และทำการสำรองข้อมูลคีย์-ค่าต่อไป เมื่อทำงาน
ในอุปกรณ์ Android 6.0 (API ระดับ 23) ขึ้นไป แอปของคุณจะใช้ Auto
การสำรองข้อมูลแทนคีย์-ค่าสำรอง
ความเป็นส่วนตัวของผู้ใช้
Google ทราบดีถึงความไว้วางใจจากผู้ใช้และหน้าที่ความรับผิดชอบในการปกป้องความเป็นส่วนตัวของผู้ใช้ Google จะส่งข้อมูลสํารองจากเซิร์ฟเวอร์ของ Google ไปยังเซิร์ฟเวอร์ของ Google และจากเซิร์ฟเวอร์ของ Google ไปยังเซิร์ฟเวอร์ของ Google อย่างปลอดภัยเพื่อให้บริการฟีเจอร์สํารองและคืนค่าข้อมูล Google จะถือว่าข้อมูลนี้เป็นข้อมูลส่วนบุคคลตามนโยบายความเป็นส่วนตัวของ Google
นอกจากนี้ ผู้ใช้ยังสามารถปิดใช้ฟังก์ชันการสำรองข้อมูลผ่าน การตั้งค่าการสำรองข้อมูลของระบบ เมื่อผู้ใช้ปิดใช้การสำรองข้อมูล Android Backup Service ลบข้อมูลสำรองที่บันทึกไว้ทั้งหมด ผู้ใช้สามารถเปิดใช้การสำรองข้อมูลบนอุปกรณ์อีกครั้ง แต่ Android Backup Service จะไม่กู้คืนข้อมูลที่ลบไปก่อนหน้านี้