Android Backup Service menyediakan pencadangan dan pemulihan penyimpanan cloud untuk data nilai kunci di aplikasi Android Anda. Selama operasi pencadangan nilai kunci berlangsung, data pencadangan aplikasi diteruskan ke backup transport perangkat. Jika perangkat menggunakan Google Backup Transport default, data akan diteruskan ke Android Backup Service untuk pengarsipan.
Data dibatasi hingga 5 MB per pengguna aplikasi. Tidak ada biaya untuk penyimpanan data cadangan.
Untuk ringkasan opsi pencadangan Android dan panduan terkait data apa saja yang harus dicadangkan dan dipulihkan, baca Ringkasan pencadangan data.
Mengimplementasikan pencadangan nilai kunci
Untuk mencadangkan data aplikasi, Anda perlu mengimplementasikan agen pencadangan. Agen pencadangan dipanggil oleh Pengelola Pencadangan selama proses pencadangan dan pemulihan.
Untuk mengimplementasikan agen pencadangan, Anda harus:
Mendeklarasikan agen pencadangan dalam file manifes dengan atribut
android:backupAgent
.Tentukan agen pencadangan dengan melakukan salah satu tindakan berikut:
-
Class
BackupAgent
menyediakan antarmuka pusat yang digunakan aplikasi untuk berkomunikasi dengan Pengelola Pencadangan. Jika langsung memperluas class ini, Anda harus menggantionBackup()
danonRestore()
untuk menangani operasi pencadangan dan pemulihan data Anda. -
Class
BackupAgentHelper
menyediakan wrapper yang tepat di sekitar classBackupAgent
, sehingga meminimalkan jumlah kode yang perlu Anda tulis. DalamBackupAgentHelper
, Anda harus menggunakan satu atau beberapa objek helper, yang otomatis mencadangkan dan memulihkan jenis data tertentu, sehingga Anda tidak perlu mengimplementasikanonBackup()
danonRestore()
. Kecuali jika Anda memerlukan kontrol penuh atas cadangan aplikasi, sebaiknya gunakanBackupAgentHelper
untuk menangani cadangan aplikasi Anda.Saat ini, Android menyediakan helper pencadangan yang akan mencadangkan dan memulihkan seluruh file dari
SharedPreferences
and penyimpanan internal.
-
Mendeklarasikan agen pencadangan dalam manifes
Setelah Anda menentukan nama class untuk agen pencadangan, deklarasikan agen pencadangan tersebut
dalam manifes menggunakan atribut android:backupAgent
dalam
tag <application>
.
Contoh:
<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>
Untuk mendukung perangkat yang lebih lama, sebaiknya tambahkan kunci API <meta-data>
ke file manifes Android Anda. Android Backup Service tidak lagi memerlukan kunci
layanan, tetapi beberapa perangkat yang lebih lama mungkin masih memeriksa kunci saat melakukan
pencadangan. Tetapkan android:name
ke com.google.android.backup.api_key
, dan
android:value
ke unused
.
Atribut
android:restoreAnyVersion
memerlukan nilai boolean untuk menunjukkan apakah Anda ingin memulihkan data
aplikasi, terlepas dari versi aplikasi saat ini dibandingkan dengan
versi yang menghasilkan data cadangan. Nilai defaultnya adalah false
. Lihat Memeriksa versi data
pemulihan untuk informasi selengkapnya.
Memperluas BackupAgentHelper
Anda harus membuat agen pencadangan menggunakan BackupAgentHelper
jika ingin mencadangkan
seluruh file dari SharedPreferences
atau penyimpanan internal.
Membuat agen pencadangan dengan BackupAgentHelper
memerlukan kode yang jauh lebih sedikit
daripada memperluas BackupAgent
, karena Anda tidak perlu mengimplementasikan
onBackup()
dan onRestore()
.
Implementasi BackupAgentHelper
harus menggunakan satu atau beberapa helper pencadangan.
Helper pencadangan adalah komponen khusus yang digunakan BackupAgentHelper
untuk
melakukan operasi pencadangan dan pemulihan jenis data tertentu. Framework
Android saat ini menyediakan dua helper yang berbeda:
SharedPreferencesBackupHelper
untuk mencadangkan fileSharedPreferences
.FileBackupHelper
untuk mencadangkan file dari penyimpanan internal.
Anda dapat menyertakan beberapa helper di BackupAgentHelper
, tetapi hanya
satu helper yang diperlukan untuk setiap jenis data. Artinya, jika memiliki beberapa file
SharedPreferences
, Anda hanya memerlukan satu
SharedPreferencesBackupHelper
.
Untuk setiap helper yang ingin ditambahkan ke BackupAgentHelper
, Anda harus
melakukan tindakan berikut selama metode
onCreate()
:
- Membuat instance class helper yang diinginkan. Di konstruktor class, Anda harus menentukan file yang ingin dicadangkan.
- Panggil
addHelper()
untuk menambahkan helper keBackupAgentHelper
.
Bagian berikut menjelaskan cara membuat agen pencadangan menggunakan masing-masing helper yang tersedia.
Mencadangkan SharedPreferences
Saat membuat instance SharedPreferencesBackupHelper
, Anda harus
menyertakan nama satu atau beberapa file SharedPreferences
.
Misalnya, untuk mencadangkan file SharedPreferences
bernama user_preferences
, agen
pencadangan lengkap menggunakan BackupAgentHelper
yang terlihat seperti ini:
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
menyertakan semua kode yang diperlukan untuk mencadangkan dan
memulihkan file SharedPreferences
.
Saat Pengelola Pencadangan memanggil onBackup()
dan onRestore()
,
BackupAgentHelper
akan memanggil helper pencadangan Anda untuk mencadangkan dan memulihkan
file yang ditentukan.
Mencadangkan file lainnya
Saat membuat instance FileBackupHelper
, Anda harus menyertakan nama
satu atau beberapa file yang disimpan ke penyimpanan internal aplikasi, seperti yang ditentukan oleh
getFilesDir()
, yakni lokasi yang sama tempat
openFileOutput()
menulis file.
Misalnya, untuk mencadangkan dua file bernama scores
dan stats
, agen
pencadangan menggunakan BackupAgentHelper
yang terlihat seperti ini:
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
menyertakan semua kode yang diperlukan untuk mencadangkan dan
memulihkan file yang disimpan ke penyimpanan internal aplikasi Anda.
Namun, membaca dan menulis file di penyimpanan internal tidak aman bagi thread. Untuk memastikan agen pencadangan tidak membaca atau menulis file bersamaan dengan aktivitas Anda, gunakan pernyataan tersinkron setiap kali Anda melakukan proses baca atau tulis. Misalnya, dalam aktivitas apa pun saat Anda membaca dan menulis file, Anda memerlukan objek untuk digunakan sebagai kunci intrinsik untuk pernyataan tersinkron:
Kotlin
// Object for intrinsic lock companion object { val sDataLock = Any() }
Java
// Object for intrinsic lock static final Object sDataLock = new Object();
Lalu, buat pernyataan tersinkron dengan kunci ini setiap kali Anda membaca atau menulis file. Misalnya, berikut adalah pernyataan tersinkron untuk menulis skor terbaru dalam game ke file:
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"); }
Anda harus menyinkronkan pernyataan baca dengan kunci yang sama.
Lalu, di BackupAgentHelper
, Anda harus mengganti onBackup()
dan
onRestore()
untuk menyinkronkan operasi pencadangan dan pemulihan dengan kunci intrinsik
yang sama. Misalnya, contoh MyFileBackupAgent
di atas memerlukan
metode berikut:
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); } }
Memperluas BackupAgent
Sebagian besar aplikasi tidak perlu memperluas class BackupAgent
secara langsung, tetapi perlu memperluas BackupAgentHelper
untuk memanfaatkan
class helper bawaan yang otomatis mencadangkan dan memulihkan file Anda.
Namun, Anda dapat memperluas BackupAgent
secara langsung untuk melakukan tindakan berikut:
- Menetapkan versi format data Anda. Misalnya, jika mengantisipasi kebutuhan untuk memperbaiki format yang digunakan untuk menulis data aplikasi, Anda dapat membuat agen pencadangan untuk memeriksa versi aplikasi selama operasi pemulihan dan melakukan pekerjaan kompatibilitas apa pun yang diperlukan jika versi di perangkat berbeda dengan data cadangan. Untuk informasi selengkapnya, lihat Memeriksa versi data pemulihan.
- Menentukan bagian data yang akan dicadangkan. Daripada mencadangkan seluruh file, Anda dapat menentukan bagian data yang akan dicadangkan dan cara setiap bagian tersebut dipulihkan ke perangkat. Tindakan ini juga dapat membantu mengelola versi yang berbeda karena Anda membaca dan menulis data sebagai entitas unik, bukan seluruh file.
- Mencadangkan data di database. Jika memiliki database SQLite yang ingin dipulihkan saat
pengguna menginstal ulang aplikasi, Anda perlu membuat
BackupAgent
kustom yang membaca data yang sesuai selama operasi pencadangan, lalu membuat tabel dan memasukkan data selama operasi pemulihan.
Jika Anda tidak perlu melakukan salah satu tugas di atas dan ingin mencadangkan
seluruh file dari SharedPreferences
atau penyimpanan internal, lihat Memperluas
BackupAgentHelper
.
Metode yang diperlukan
Saat membuat BackupAgent
, Anda
harus mengimplementasikan metode callback berikut:
onBackup()
- Pengelola Pencadangan memanggil metode ini setelah Anda meminta pencadangan. Dalam metode ini, Anda membaca data aplikasi dari perangkat dan meneruskan data yang ingin dicadangkan ke Pengelola Pencadangan, seperti yang dijelaskan dalam Melakukan pencadangan.
onRestore()
Pengelola Pencadangan memanggil metode ini selama operasi pemulihan. Metode ini mengirimkan data cadangan, yang dapat digunakan aplikasi untuk memulihkan status sebelumnya, seperti yang dijelaskan dalam Melakukan pemulihan.
Sistem memanggil metode ini untuk memulihkan data cadangan apa pun saat pengguna menginstal ulang aplikasi Anda, tetapi aplikasi Anda juga dapat meminta pemulihan.
Melakukan pencadangan
Permintaan pencadangan tidak menghasilkan panggilan langsung ke metode
onBackup()
Anda. Sebaliknya, Pengelola Pencadangan menunggu waktu yang tepat, lalu melakukan
pencadangan untuk semua aplikasi yang telah meminta pencadangan sejak pencadangan
terakhir dilakukan. Ini adalah titik saat Anda harus memberikan data aplikasi ke
Pengelola Pencadangan agar dapat disimpan ke penyimpanan cloud.
Hanya Pengelola Pencadangan yang dapat memanggil metode onBackup()
agen pencadangan Anda. Setiap
kali data aplikasi berubah dan Anda ingin melakukan pencadangan, Anda harus
meminta operasi pencadangan dengan memanggil dataChanged()
.
Lihat Meminta pencadangan untuk informasi selengkapnya.
Tips: Saat mengembangkan aplikasi, Anda dapat memulai operasi pencadangan
langsung dari Pengelola Pencadangan dengan alat
bmgr
.
Saat Pengelola Pencadangan memanggil metode onBackup()
Anda, metode ini akan meneruskan tiga
parameter:
oldState
ParcelFileDescriptor
hanya baca terbuka yang mengarah ke status pencadangan terakhir yang diberikan oleh aplikasi Anda. Ini bukan data cadangan dari penyimpanan cloud, tetapi representasi lokal dari data yang dicadangkan saat terakhir kalionBackup()
dipanggil, seperti yang didefinisikan olehnewState
atau darionRestore()
.onRestore()
dibahas di bagian berikutnya. KarenaonBackup()
tidak mengizinkan Anda membaca data cadangan yang ada di penyimpanan cloud, Anda dapat menggunakan representasi lokal ini untuk menentukan apakah data Anda telah berubah sejak pencadangan terakhir.data
- Objek
BackupDataOutput
, yang Anda gunakan untuk mengirimkan data cadangan ke Pengelola Pencadangan. newState
ParcelFileDescriptor
baca/tulis terbuka yang mengarah ke file tempat Anda harus menulis representasi dari data yang dikirimkan kedata
. Representasi dapat semudah seperti stempel waktu yang terakhir diubah untuk file Anda. Objek ini ditampilkan sebagaioldState
saat Pengelola Pencadangan memanggil metodeonBackup()
Anda lagi. Jika Anda tidak menulis data cadangan kenewState
,oldState
akan mengarah ke file kosong saat Pengelola Pencadangan memanggilonBackup()
lagi.
Dengan menggunakan parameter ini, implementasikan metode onBackup()
Anda untuk melakukan hal berikut:
Memeriksa apakah data telah berubah sejak pencadangan terakhir dengan membandingkan
oldState
terhadap data saat ini. Cara membaca data dalamoldState
bergantung pada cara Anda awalnya menulisnya kenewState
(lihat langkah 3). Cara termudah untuk mencatat status file adalah dengan stempel waktu terakhir diubahnya. Misalnya, berikut contoh cara Anda dapat membaca dan membandingkan stempel waktu darioldState
: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 }
Jika tidak ada yang berubah dan Anda tidak perlu melakukan pencadangan, lanjutkan ke langkah 3.
Jika data Anda berubah, dibandingkan dengan
oldState
, tulis data saat ini kedata
untuk mencadangkannya ke penyimpanan cloud.Anda harus menulis setiap bagian data sebagai entitas dalam
BackupDataOutput
. Entitas adalah rekaman data biner yang disederhanakan yang diidentifikasi dengan string kunci unik. Jadi, set data yang Anda cadangkan secara konseptual adalah set key-value pair.Untuk menambahkan entitas ke set data cadangan, Anda harus:
Memanggil
writeEntityHeader()
, yang meneruskan kunci string unik untuk data yang akan Anda tulis beserta ukuran datanya.Memanggil
writeEntityData()
, yang meneruskan buffer byte berisi data dan jumlah byte yang akan ditulis dari buffer, yang seharusnya sesuai dengan ukuran yang diteruskan kewriteEntityHeader()
.
Misalnya, kode berikut menyederhanakan data tertentu menjadi aliran byte dan menulisnya menjadi satu entitas:
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);
Lakukan ini untuk setiap bagian data yang ingin Anda cadangkan. Cara Anda membagi data menjadi beberapa entitas bergantung pada Anda. Anda bahkan dapat menggunakan satu entitas saja.
Baik Anda melakukan pencadangan maupun tidak (dalam langkah 2), tulis representasi data saat ini ke
newState
ParcelFileDescriptor
. Pengelola Pencadangan mempertahankan objek ini secara lokal sebagai representasi data yang saat ini sedang dicadangkan. Pengelola Pencadangan mengembalikan objek tersebut kepada Anda sebagaioldState
saatonBackup()
dipanggil lagi, sehingga Anda dapat menentukan apakah pencadangan lainnya diperlukan sebagaimana dijelaskan di langkah 1. Jika Anda tidak menulis status data saat ini ke file ini,oldState
akan kosong selama callback berikutnya.Contoh berikut menyimpan representasi data saat ini ke
newState
menggunakan stempel waktu terakhir diubah file tersebut: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);
Melakukan pemulihan
Jika waktu untuk memulihkan data aplikasi Anda sudah tiba, Pengelola Pencadangan memanggil
metode onRestore()
agen pencadangan Anda. Saat memanggil metode ini, Pengelola Pencadangan akan mengirim data cadangan Anda, sehingga
Anda dapat memulihkannya ke perangkat.
Hanya Pengelola Pencadangan yang dapat memanggil onRestore()
, yang terjadi otomatis saat sistem menginstal aplikasi Anda dan
menemukan data cadangan yang ada.
Saat Pengelola Pencadangan memanggil metode onRestore()
Anda, metode ini akan
meneruskan tiga parameter:
data
- Objek
BackupDataInput
, yang memungkinkan Anda membaca data cadangan. appVersionCode
- Bilangan bulat yang merepresentasikan nilai atribut manifes
android:versionCode
aplikasi Anda, seperti saat data ini dicadangkan. Anda dapat menggunakannya untuk memeriksa versi aplikasi saat ini dan menentukan apakah format data tersebut kompatibel. Untuk informasi selengkapnya tentang cara menggunakan ini guna menangani versi data pemulihan yang berbeda, lihat Memeriksa versi data pemulihan. newState
ParcelFileDescriptor
baca/tulis terbuka yang mengarah ke file tempat Anda harus menulis status pencadangan terakhir yang diberikan dengandata
. Objek ini ditampilkan sebagaioldState
saatonBackup()
dipanggil lagi. Pastikan Anda juga harus menulis objeknewState
yang sama di callbackonBackup()
—menuliskannya di sini akan memastikan objekoldState
yang diberikan keonBackup()
valid bahkan saatonBackup()
pertama kali dipanggil setelah perangkat dipulihkan.
Saat mengimplementasikan onRestore()
, Anda harus memanggil
readNextHeader()
di data
untuk mengiterasi semua entitas dalam set data. Untuk setiap entitas
yang ditemukan, lakukan hal berikut:
- Mendapatkan kunci entitas dengan
getKey()
. Bandingkan kunci entitas dengan daftar nilai kunci yang diketahui yang harus Anda deklarasikan sebagai string final statis dalam class
BackupAgent
. Bila kunci cocok dengan salah satu string kunci yang diketahui, masukkan ke dalam pernyataan untuk mengekstrak data entitasnya, lalu simpan ke perangkat:- Dapatkan ukuran data entitas dengan
getDataSize()
dan buat array byte dari ukuran tersebut. - Panggil
readEntityData()
dan teruskan array byte, yakni tempat tujuan data. Lalu, tentukan offset awal dan ukuran untuk dibaca. - Array byte Anda kini penuh. Baca data dan tulis ke perangkat sesuai keinginan Anda.
- Dapatkan ukuran data entitas dengan
Setelah membaca dan menulis data kembali ke perangkat, tulis status data Anda ke parameter
newState
, sama seperti yang Anda lakukan selamaonBackup()
.
Misalnya, berikut cara Anda dapat memulihkan data yang dicadangkan dengan contoh di bagian sebelumnya:
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); }
Dalam contoh ini, parameter appVersionCode
yang diteruskan ke onRestore()
tidak
digunakan. Namun, Anda mungkin ingin menggunakannya jika telah memilih untuk melakukan pencadangan
saat versi aplikasi pengguna benar-benar telah di-downgrade (misalnya,
pengguna beralih dari aplikasi versi 1.5 ke 1.0). Untuk informasi selengkapnya, lihat
bagian berikutnya.
Memeriksa versi data pemulihan
Saat Pengelola pencadangan menyimpan data Anda ke penyimpanan cloud, versi aplikasi
akan otomatis disertakan, seperti yang ditentukan oleh atribut android:versionCode
file manifes Anda. Sebelum memanggil agen pencadangan
Anda untuk memulihkan data, Pengelola Pencadangan akan melihat android:versionCode
aplikasi
terinstal dan membandingkannya dengan nilai yang dicatat dalam set data pemulihan. Jika
versi yang dicatat dalam set data pemulihan lebih baru daripada versi aplikasi
di perangkat, maka pengguna telah men-downgrade versi aplikasinya. Dalam kasus ini, Pengelola
Pencadangan akan membatalkan operasi pemulihan untuk aplikasi Anda dan tidak akan memanggil
metode onRestore()
, karena set pemulihan dianggap tidak dapat digunakan untuk
versi yang lebih lama.
Anda dapat mengganti perilaku ini dengan atribut android:restoreAnyVersion
.
Setel atribut ini ke true
untuk menunjukkan bahwa Anda ingin memulihkan aplikasi,
apa pun versi set pemulihannya. Nilai defaultnya adalah false
. Jika Anda
menyetelnya ke true
, Pengelola Pencadangan akan mengabaikan
android:versionCode
dan memanggil metode onRestore()
Anda dalam semua kasus. Dengan begitu,
Anda dapat memeriksa perbedaan versi secara manual di metode onRestore()
dan melakukan langkah yang diperlukan untuk membuat data kompatibel jika versi tidak
cocok.
Untuk membantu menangani versi yang berbeda selama operasi pemulihan,
metode onRestore()
meneruskan kode versi yang disertakan dengan set
data pemulihan sebagai parameter appVersionCode
. Lalu, Anda dapat mengkueri kode versi aplikasi saat ini
dengan kolom
PackageInfo.versionCode
. Contoh:
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; }
Lalu, bandingkan version
yang diperoleh dari
PackageInfo
ke
appVersionCode
yang diteruskan ke onRestore()
.
Meminta pencadangan
Anda dapat meminta operasi pencadangan kapan saja dengan memanggil dataChanged()
. Metode
ini memberi tahu Pengelola Pencadangan bahwa Anda ingin mencadangkan data menggunakan
agen pencadangan. Selanjutnya, Pengelola Pencadangan akan memanggil metode onBackup()
agen pencadangan Anda di waktu mendatang. Biasanya, Anda harus
meminta pencadangan setiap kali data Anda berubah (misalnya saat pengguna mengubah preferensi aplikasi
yang ingin Anda cadangkan). Jika Anda memanggil dataChanged()
beberapa kali sebelum Pengelola Pencadangan meminta pencadangan dari agen Anda, agen Anda
akan tetap menerima satu panggilan saja untuk onBackup()
.
Meminta pemulihan
Selama aplikasi Anda berfungsi dengan normal, Anda tidak perlu meminta operasi pemulihan. Sistem akan otomatis memeriksa data pencadangan dan melakukan pemulihan saat aplikasi Anda diinstal.
Bermigrasi ke Pencadangan Otomatis
Anda dapat melakukan transisi aplikasi ke pencadangan data menyeluruh dengan menyetel
android:fullBackupOnly
ke true
dalam elemen <application>
di file manifes. Saat
berjalan di perangkat yang menggunakan Android 5.1 (API level 22) atau yang lebih lama, aplikasi Anda mengabaikan nilai ini
dalam manifes, dan tetap melakukan pencadangan nilai kunci. Saat
berjalan di perangkat yang menggunakan Android 6.0 (API level 23) atau yang lebih baru, aplikasi Anda melakukan
Pencadangan Otomatis, bukan pencadangan nilai kunci.
Privasi pengguna
Di Google, kami sangat menyadari kepercayaan pengguna yang telah diberikan kepada kami dan tanggung jawab kami dalam melindungi privasi pengguna. Google secara aman mengirim data cadangan ke dan dari server Google untuk memberikan fitur pencadangan dan pemulihan. Google memperlakukan data ini sebagai informasi pribadi sesuai dengan Kebijakan Privasi Google.
Selain itu, pengguna dapat menonaktifkan fungsi pencadangan data melalui setelan pencadangan sistem Android. Saat pengguna menonaktifkan pencadangan, Android Backup Service akan menghapus semua data cadangan yang disimpan. Pengguna dapat mengaktifkan kembali pencadangan di perangkat, tetapi Android Backup Service tidak akan memulihkan data yang telah dihapus sebelumnya.