Catatan: Untuk sebagian besar aplikasi,
Auto Backup harus digunakan untuk
mengimplementasikan pencadangan dan pemulihan. Aplikasi hanya dapat mengimplementasikan Pencadangan Otomatis
atau pencadangan nilai kunci, bukan keduanya. Pencadangan Otomatis tidak memerlukan kode dan akan mencadangkan
seluruh file, sementara pencadangan nilai kunci mengharuskan Anda menulis kode untuk menentukan
konten cadangan secara eksplisit dalam bentuk key-value pair.
Sebelumnya, developer mendaftarkan aplikasi untuk mendapatkan kunci layanan. Anda tidak
perlu lagi mendaftarkan aplikasi untuk pencadangan nilai kunci.
Android Backup Service menyediakan pencadangan dan pemulihan penyimpanan cloud untuk data nilai kunci di aplikasi Android. Selama operasi pencadangan nilai kunci, data pencadangan aplikasi diteruskan ke Backup Transport perangkat. Jika perangkat menggunakan Google Backup Transport default, data akan diteruskan ke Android Backup Service untuk pengarsipan.
Jumlah data dibatasi hingga 5 MB per pengguna aplikasi dan penyimpanan data cadangan dapat dilakukan secara gratis.
Untuk ringkasan mengenai opsi pencadangan Android dan panduan terkait data apa saja yang sebaiknya Anda cadangkan dan pulihkan, 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
. - Menentukan agen pencadangan baik dengan:
- Memperluas BackupAgent
Class
BackupAgent
menyediakan antarmuka terpusat yang digunakan aplikasi Anda untuk berkomunikasi dengan Pengelola Pencadangan. Jika Anda memperluas class ini secara langsung, Anda harus menggantionBackup()
danonRestore()
untuk menangani operasi pencadangan dan pemulihan untuk data Anda. - Memperluas BackupAgentHelper
Class
BackupAgentHelper
menyediakan wrapper yang cocok dengan classBackupAgent
, yang meminimalkan jumlah kode yang harus Anda tulis. DiBackupAgentHelper
, 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
dan penyimpanan internal.
Atau
- Memperluas BackupAgent
Mendeklarasikan agen pencadangan dalam manifes
Ini adalah langkah termudah, setelah memutuskan nama class untuk
agen pencadangan, deklarasikan agen pencadangan dalam manifes dengan 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. 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 lain yang dapat Anda gunakan adalah android:restoreAnyVersion
. Atribut ini memerlukan nilai boolean untuk menunjukkan apakah Anda
ingin memulihkan data aplikasi terlepas dari versi aplikasi saat ini dibandingkan dengan
versi yang membuat data cadangan. (Nilai defaultnya adalah "false
".) Untuk informasi selengkapnya, lihat Memeriksa versi data pemulihan.
Android Backup Service
Google menyediakan Backup Transport dengan Android Backup Service untuk sebagian besar perangkat Android yang menjalankan Android 2.2 atau yang lebih baru.
Catatan: Backup Transport yang disediakan oleh Android Backup Service tidak dijamin tersedia di semua perangkat Android yang mendukung pencadangan. Sebagian perangkat mungkin mendukung pencadangan menggunakan transport berbeda, sebagian perangkat mungkin tidak mendukung pencadangan sama sekali, dan aplikasi tidak dapat mengetahui transport yang digunakan di perangkat.
Memperluas BackupAgentHelper
Anda harus membuat agen pencadangan menggunakan BackupAgentHelper
jika ingin mencadangkan
semua file (baik dari SharedPreferences
atau penyimpanan internal).
Membuat agen pencadangan dengan BackupAgentHelper
membutuhkan kode yang jauh lebih sedikit
daripada memperluas BackupAgent
, karena Anda tidak perlu mengimplementasikan
onBackup()
dan onRestore()
.
Penerapan BackupAgentHelper
harus
menggunakan satu atau beberapa helper pencadangan. Helper pencadangan adalah komponen khusus
yang digunakan BackupAgentHelper
untuk melakukan operasi pencadangan dan
pemulihan untuk 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 Anda memiliki beberapa file
SharedPreferences
, Anda hanya memerlukan satu
SharedPreferencesBackupHelper
.
Untuk setiap helper yang ingin ditambahkan ke BackupAgentHelper
, Anda harus
melakukan hal berikut selama metode onCreate()
:
- Membuat instance class helper yang diinginkan. Dalam constructor class, Anda harus menentukan file tertentu yang ingin dicadangkan.
- Panggil
addHelper()
untuk menambahkan helper keBackupAgentHelper
Anda.
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
dan 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); } }
Selesai. SharedPreferencesBackupHelper
menyertakan semua kode yang diperlukan untuk mencadangkan dan memulihkan file SharedPreferences
.
Saat Pengelola Pencadangan memanggil onBackup()
dan onRestore()
, BackupAgentHelper
akan memanggil helper cadangan Anda untuk melakukan
pencadangan dan pemulihan file tertentu.
Catatan: Metode SharedPreferences
aman bagi thread, sehingga
Anda dapat dengan aman membaca dan menulis file preferensi yang dibagikan dari agen pencadangan dan
aktivitas lainnya.
Mencadangkan file lainnya
Saat membuat instance FileBackupHelper
, Anda harus menyertakan nama
satu atau beberapa file yang disimpan ke penyimpanan internal
aplikasi Anda (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
, dan 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 pada penyimpanan internal tidak aman bagi thread. Untuk memastikan bahwa agen pencadangan tidak membaca atau menulis file bersamaan dengan aktivitas Anda, Anda harus menggunakan pernyataan tersinkron setiap kali Anda melakukan proses baca atau tulis. Misalnya, di Aktivitas mana pun tempat 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 laporan 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 backup 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 backup 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); } }
Hanya ini yang Anda butuhkan untuk mencadangkan dan memulihkan data dengan
BackupAgentHelper
.
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 mungkin harus memperluas BackupAgent
secara langsung jika Anda diperlukan:
- Menetapkan versi format data Anda. Misalnya, jika Anda 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 pada perangkat berbeda dengan data cadangan. Untuk informasi selengkapnya, lihat Memeriksa versi data pemulihan.
- Daripada mencadangkan seluruh file, Anda dapat menentukan bagian data yang perlu dicadangkan dan bagaimana nantinya setiap bagian dipulihkan ke perangkat. (Hal ini juga dapat membantu Anda mengelola versi yang berbeda, karena Anda membaca dan menulis data sebagai entitas unik, bukan satu file utuh).
- 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 buat tabel dan masukkan 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 di bawah ini dalam Melakukan pencadangan.
onRestore()
- Pengelola Pencadangan memanggil metode ini selama operasi pemulihan.
Metode ini mengirimkan data cadangan, yang dapat digunakan aplikasi Anda untuk memulihkan
status sebelumnya, seperti yang dijelaskan di bawah ini pada
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
Jika waktu untuk mencadangkan data aplikasi Anda sudah tiba, Pengelola Pencadangan akan memanggil metode onBackup()
Anda. Inilah saatnya untuk 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). 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.
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 disediakan aplikasi Anda. Ini bukan data backup dari penyimpanan cloud, tetapi representasi lokal dari data yang dicadangkan terakhir kali saatonBackup()
dipanggil (seperti yang ditetapkan olehnewState
, di bawah, atau darionRestore()
— ini dibahas selengkapnya 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 dikirim kedata
(representasi boleh sederhana 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.
Untuk menggunakan parameter ini, Anda harus mengimplementasikan metode onBackup()
untuk melakukan hal berikut:
- Memeriksa apakah data Anda telah berubah sejak pencadangan terakhir dengan membandingkan
oldState
dengan data Anda saat ini. Cara membaca data dalamoldState
tergantung pada bagaimana Anda menulisnya kenewState
(lihat langkah 3). Cara termudah untuk mencatat status file adalah dengan stempel waktu terakhir diubahnya. Berikut adalah contoh cara 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 kumpulan key-value pair.Untuk menambahkan entitas ke set data cadangan, Anda harus:
- Memanggil
writeEntityHeader()
, meneruskan kunci string unik untuk data yang akan Anda tulis beserta ukuran datanya. - Memanggil
writeEntityData()
, meneruskan buffer byte yang berisi data dan jumlah byte yang akan ditulis dari buffer (yang seharusnya sesuai dengan ukuran yang diteruskan kewriteEntityHeader()
).
Misalnya, kode berikut menyederhanakan beberapa data 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. Anda dapat menentukan cara membagi data menjadi entitas (dan Anda dapat menggunakan satu entitas saja).
- Memanggil
- Baik Anda melakukan pencadangan atau 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 sebagaioldState
saat Anda memanggilonBackup()
, 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
ini akan kosong selama callback berikutnya.Contoh berikut menyimpan representasi data saat ini ke
newState
menggunakan stempel waktu terakhir diubah file: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);
Perhatian: Jika data aplikasi Anda disimpan ke file, pastikan Anda menggunakan pernyataan tersinkron saat mengakses file agar agen pencadangan tidak membaca file saat Aktivitas di aplikasi Anda sedang menulis file.
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 secara otomatis saat sistem menginstal aplikasi Anda dan
menemukan data cadangan yang ada.
Catatan: Saat mengembangkan aplikasi, Anda juga dapat meminta
operasi pemulihan dengan alat bmgr
.
Saat Pengelola Pencadangan memanggil metode onRestore()
Anda, metode ini akan meneruskan tiga parameter:
data
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 untuk menangani versi data pemulihan yang berbeda, lihat bagian di bawah ini tentang 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
saat Anda memanggilonBackup()
. Pastikan untuk menulis objeknewState
yang sama di callbackonBackup()
—menuliskannya di sini memastikan bahwa objekoldState
yang diberikan kepadaonBackup()
valid bahkan saatonBackup()
pertama kali dipanggil setelah perangkat dipulihkan.
Saat mengimplementasikan onRestore()
, Anda harus memanggil readNextHeader()
pada
data
untuk mengiterasi
semua entitas dalam set data. Untuk setiap entitas yang ditemukan, lakukan hal berikut:
- Dapatkan kunci entitas dengan
getKey()
. - Bandingkan kunci entitas dengan daftar nilai kunci yang diketahui yang harus Anda deklarasikan sebagai string final statis
dalam class
BackupAgent
. Apabila kunci cocok dengan salah satu string utama 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, tempat tujuan data, lalu tentukan offset awal dan ukuran untuk dibaca. - Array byte Anda sekarang penuh dan Anda dapat membaca data dan menulisnya 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()
.
Berikut adalah contoh cara 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 dapat menggunakannya
jika Anda memilih untuk melakukan pencadangan saat versi aplikasi pengguna benar-benar telah
di-downgrade (misalnya, pengguna beralih dari versi 1.5 aplikasi Anda ke versi 1.0). Untuk informasi selengkapnya, lihat
bagian Memeriksa versi data pemulihan.
Memeriksa versi data pemulihan
Saat Pengelola pencadangan menyimpan data Anda ke penyimpanan cloud, versi aplikasi Anda
akan otomatis disertakan, seperti yang ditentukan oleh atribut android:versionCode
file manifes Anda. Sebelum Pengelola Pencadangan memanggil agen pencadangan untuk memulihkan data, Pengelola Pencadangan
akan melihat android:versionCode
aplikasi yang diinstal dan membandingkannya dengan nilai
yang dicatat dalam set data pemulihan. Jika versi yang dicatat dalam set data pemulihan
adalah versi yang lebih baru dari 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
. Atribut ini dapat berupa "true
" atau "false
" untuk menunjukkan apakah Anda ingin memulihkan aplikasi terlepas dari
versi set pemulihan. Nilai defaultnya adalah "false
". Jika Anda menetapkan ini ke "true
", Pengelola Pencadangan
akan mengabaikan android:versionCode
dan memanggil metode onRestore()
Anda dalam kasus apa pun. Dengan demikian, Anda dapat memeriksa perbedaan versi secara manual di metode onRestore()
dan melakukan hal apa pun yang diperlukan untuk membuat data kompatibel jika versinya bertentangan.
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; }
Kemudian cukup bandingkan version
yang diperoleh dari PackageInfo
ke appVersionCode
yang diteruskan ke onRestore()
.
Perhatian: Pastikan Anda memahami konsekuensi menetapkan
android:restoreAnyVersion
ke "true
" untuk aplikasi Anda. Jika setiap versi aplikasi Anda
yang mendukung pencadangan tidak mempertimbangkan dengan tepat variasi format data Anda selama
onRestore()
, data di perangkat tersebut dapat disimpan dalam format yang tidak kompatibel dengan versi yang saat ini
diinstal di perangkat.
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. Kemudian Pengelola Pencadangan
akan memanggil metode onBackup()
agen pencadangan Anda pada waktu yang tepat di masa 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 secara berurutan, sebelum Pengelola
Pencadangan meminta pencadangan dari agen Anda, agen Anda tetap menerima satu panggilan saja untuk onBackup()
.
Catatan: Saat mengembangkan aplikasi, Anda dapat meminta
pencadangan dan memulai operasi pencadangan langsung dengan alat bmgr
.
Meminta pemulihan
Selama aplikasi Anda berfungsi dengan normal, Anda tidak perlu meminta operasi pemulihan. Sistem secara otomatis memeriksa data backup dan melakukan pemulihan saat aplikasi Anda diinstal.
Catatan: Saat mengembangkan aplikasi, Anda dapat meminta
operasi pemulihan dengan alat bmgr
.
Bermigrasi ke pencadangan otomatis
Anda dapat melakukan transisi aplikasi ke pencadangan data menyeluruh dengan menetapkan
android:fullBackupOnly
ke true
dalam elemen <application>
di file manifes. Saat
dijalankan di perangkat yang menggunakan Android 5.1 (API level 22) atau lebih yang rendah, aplikasi Anda mengabaikan nilai ini
dalam manifes, dan tetap melakukan pencadangan nilai kunci. Saat
dijalankan di perangkat yang menggunakan Android 6.0 (API level 23) atau lebih yang tinggi, aplikasi Anda melakukan
pencadangan otomatis, bukan pencadangan nilai kunci.
Privasi pengguna
Di Google, kami sangat menyadari kepercayaan pengguna yang telah diberikan kepada kami dan kami bertanggung jawab untuk 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 cadangan 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.