Android Backup Service bietet Cloud-Speicher-Back-up und Wiederherstellung für Schlüssel/Wert-Paare Daten in Ihrer Android-App. Während eines Schlüssel/Wert-Paar-Back-ups Daten an den Sicherungstransport des Geräts übergeben. Wenn auf dem Gerät der standardmäßige Google-Sicherungs-Transport verwendet wird, werden die Daten zur Archivierung an den Android-Sicherungsservice übergeben.
Die Daten sind auf 5 MB pro Nutzer Ihrer App beschränkt. Das Speichern ist kostenlos. Back-up-Daten.
Eine Übersicht über die Sicherungsoptionen von Android und Informationen dazu, welche Daten Sie sichern und wiederherstellen sollten, finden Sie im Hilfeartikel Datensicherung.
Schlüssel/Wert-Sicherung implementieren
Wenn Sie Ihre App-Daten sichern möchten, müssen Sie einen Sicherungsagenten implementieren. Der Sicherungsagent wird vom Sicherungsmanager sowohl bei der Sicherung als auch bei der Wiederherstellung aufgerufen.
Wenn Sie einen Sicherungsagenten implementieren möchten, müssen Sie Folgendes tun:
Deklarieren Sie Ihren Sicherungsagenten in Ihrer Manifestdatei mit dem Attribut
android:backupAgent
.So definieren Sie einen Sicherungsagenten:
-
Klasse
BackupAgent
stellt die zentrale Schnittstelle bereit, über die Ihre App mit dem Sicherungsmanager. Wenn Sie diese Klasse direkt erweitern, müssen SieonBackup()
undonRestore()
überschreiben, um die Sicherungs- und Wiederherstellungsvorgänge für Ihre Daten zu verarbeiten. BackupAgentHelper
wird verlängertDie Klasse
BackupAgentHelper
ist ein praktischer Wrapper für die KlasseBackupAgent
, wodurch die Menge des zu schreibenden Codes minimiert wird. In IhremBackupAgentHelper
müssen Sie ein oder mehrere Hilfsobjekte verwenden, die bestimmte Datentypen automatisch sichern und wiederherstellen, damit SieonBackup()
undonRestore()
nicht implementieren müssen. Es sei denn, Sie benötigen volle App-Sicherungen haben, empfehlen wir die Verwendung derBackupAgentHelper
die Back-ups Ihrer App zu verwalten.Android bietet derzeit Sicherungshilfen, mit denen vollständige Dateien aus
SharedPreferences
und dem internen Speicher gesichert und wiederhergestellt werden können.
-
Deklarieren Sie den Sicherungsagenten in Ihrem Manifest.
Nachdem Sie sich für den Klassennamen Ihres Sicherungs-Agenten entschieden haben, deklarieren Sie ihn in Ihrem Manifest mit dem Attribut android:backupAgent
im Tag <application>
.
Beispiel:
<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>
Zur Unterstützung älterer Geräte empfehlen wir, den API-Schlüssel <meta-data>
hinzuzufügen
in Ihre Android-Manifestdatei ein. Für den Android-Sicherungsservice ist kein Dienstschlüssel mehr erforderlich. Auf einigen älteren Geräten wird bei der Sicherung jedoch möglicherweise noch nach einem Schlüssel gesucht. Legen Sie android:name
auf com.google.android.backup.api_key
und android:value
auf unused
fest.
Die
android:restoreAnyVersion
verwendet einen booleschen Wert, um anzugeben, ob Sie die App wiederherstellen möchten
Daten unabhängig von der aktuellen App-Version im Vergleich zur Version,
die Backup-Daten erstellt haben. Der Standardwert ist false
. Weitere Informationen finden Sie unter Version der wiederherzustellenden Daten prüfen.
BackupAgentHelper erweitern
Sie sollten Ihren Sicherungsagenten mit BackupAgentHelper
erstellen, wenn Sie vollständige Dateien entweder aus SharedPreferences
oder aus dem internen Speicher sichern möchten.
Für die Erstellung eines Sicherungsagenten mit BackupAgentHelper
ist viel weniger Code erforderlich als für die Erweiterung von BackupAgent
, da Sie onBackup()
und onRestore()
nicht implementieren müssen.
Ihre Implementierung von BackupAgentHelper
muss mindestens eine Sicherungshilfe verwenden.
Ein Hilfsprogramm ist eine spezielle Komponente, die von BackupAgentHelper
beschwört wird
Sicherungs- und Wiederherstellungsvorgänge für einen bestimmten Datentyp ausführen. Das Android-Framework bietet derzeit zwei verschiedene Helfer:
SharedPreferencesBackupHelper
umSharedPreferences
Dateien zu sichern.FileBackupHelper
bis zurück Dateien aus dem internen Speicher hoch.
Du kannst in deinem BackupAgentHelper
mehrere Helfer hinzufügen, jedoch nur eine
Hilfsprogramm für jeden Datentyp benötigt. Wenn Sie also mehrere SharedPreferences
-Dateien haben, benötigen Sie nur eine SharedPreferencesBackupHelper
.
Führen Sie für jeden Helfer, den Sie BackupAgentHelper
hinzufügen möchten, die folgenden Schritte aus:
folgen während des
Methode onCreate()
:
- Instanziieren Sie eine Instanz der gewünschten Hilfsklasse. Im Klassenkonstruktor müssen Sie die Dateien angeben, die Sie sichern möchten.
- Rufen Sie
addHelper()
an, um den Helfer zu IhremBackupAgentHelper
hinzuzufügen.
In den folgenden Abschnitten wird beschrieben, wie Sie mit den einzelnen verfügbaren Helfern.
SharedPreferences sichern
Wenn Sie eine SharedPreferencesBackupHelper
-Instanz erstellen, müssen Sie den Namen einer oder mehrerer SharedPreferences
-Dateien angeben.
Um beispielsweise eine SharedPreferences
-Datei namens user_preferences
zu sichern,
Backup-Agent mit BackupAgentHelper
abschließen sieht so aus:
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); } }
Die SharedPreferencesBackupHelper
enthält den gesamten Code, der zum Sichern und Wiederherstellen einer SharedPreferences
-Datei erforderlich ist.
Wenn der Sicherungsmanager onBackup()
und onRestore()
aufruft, ruft BackupAgentHelper
Ihre Sicherungshilfen auf, um die angegebenen Dateien zu sichern und wiederherzustellen.
Andere Dateien sichern
Wenn Sie eine FileBackupHelper
-Instanz erstellen, müssen Sie den Namen einer oder mehrerer Dateien angeben, die gemäß getFilesDir()
im internen Speicher Ihrer App gespeichert werden. Das ist derselbe Speicherort, an dem openFileOutput()
Dateien schreibt.
Um beispielsweise zwei Dateien mit den Namen scores
und stats
zu sichern, einen Sicherungs-Agent
mit BackupAgentHelper
sieht so aus:
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
enthält den gesamten Code, der zum Sichern und Wiederherstellen
-Dateien, die im internen Speicher der App gespeichert werden.
Das Lesen und Schreiben von Dateien im internen Speicher ist jedoch nicht Thread-sicher. Damit Ihr Sicherungs-Agent Ihre Daten nicht liest oder schreibt, und Ihre Aktivitäten verwenden, müssen Sie synchronisierte Anweisungen verwenden. jedes Mal, wenn Sie einen Lese- oder Schreibvorgang ausführen. Bei jeder Aktivität, bei der Sie zum Lesen und Schreiben der Datei benötigen, benötigen Sie ein Objekt, das Sie als intrinsische Sperre für den synchronisierten Anweisungen:
Kotlin
// Object for intrinsic lock companion object { val sDataLock = Any() }
Java
// Object for intrinsic lock static final Object sDataLock = new Object();
Erstellen Sie dann bei jedem Lese- oder Schreibvorgang eine synchronisierte Anweisung mit dieser Sperre. die Dateien. Hier ist als Beispiel eine synchronisierte Anweisung zum Schreiben der aktuellen Punkte in einem Spiel in eine Datei hochladen:
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"); }
Sie sollten Ihre Leseanweisungen mit derselben Sperre synchronisieren.
Anschließend müssen Sie in BackupAgentHelper
onBackup()
und onRestore()
überschreiben, um die Sicherungs- und Wiederherstellungsvorgänge mit derselben intrinsischen Sperre zu synchronisieren. Für das Beispiel MyFileBackupAgent
oben sind beispielsweise die folgenden Methoden erforderlich:
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 erweitern
Bei den meisten Apps ist es nicht erforderlich, die Klasse BackupAgent
direkt zu erweitern. Stattdessen sollten Sie BackupAgentHelper
erweitern, um die integrierten Hilfsklassen zu nutzen, mit denen Ihre Dateien automatisch gesichert und wiederhergestellt werden.
Sie können BackupAgent
jedoch direkt erweitern, um Folgendes zu tun:
- Versionieren Sie Ihr Datenformat. Wenn Sie beispielsweise davon ausgehen, dass Sie das Format, in dem Sie Ihre App-Daten schreiben, überarbeiten müssen, können Sie einen Sicherungsagenten erstellen, der Ihre App-Version während eines Wiederherstellungsvorgangs prüft und alle erforderlichen Kompatibilitätsarbeiten ausführt, wenn sich die Version auf dem Gerät von der der Sicherungsdaten unterscheidet. Weitere Informationen finden Sie unter Die Wiederherstellung überprüfen. Datenversion.
- Geben Sie an, welche Daten gesichert werden sollen. Anstatt eine ganze Datei zu sichern, können Sie angeben, welche Daten gesichert werden sollen und wie jeder Teil dann auf dem Gerät wiederhergestellt wird. Dies kann Ihnen auch dabei helfen, verschiedene Versionen, da Sie Ihre Daten als eindeutige Entitäten lesen und schreiben als vollständige Dateien.
- Daten in einer Datenbank sichern Wenn Sie eine SQLite-Datenbank haben, die Sie wiederherstellen möchten, wenn der Nutzer Ihre App neu installiert, müssen Sie eine benutzerdefinierte
BackupAgent
erstellen, die die entsprechenden Daten während eines Sicherungsvorgangs liest, dann die Tabelle erstellt und die Daten während eines Wiederherstellungsvorgangs einfügt.
Wenn Sie keine der oben genannten Aufgaben ausführen müssen und vollständige Dateien aus SharedPreferences
oder dem internen Speicher sichern möchten, lesen Sie den Hilfeartikel BackupAgentHelper
erweitern.
Erforderliche Methoden
Wenn Sie eine BackupAgent
erstellen, müssen Sie die folgenden Rückrufmethoden implementieren:
onBackup()
- Der Backup Manager ruft diese Methode auf, nachdem Sie eine Back-up. Bei dieser Methode lesen Sie Ihre App-Daten aus dem und die zu sichernden Daten an den Backup Manager übergeben, wie unter Daten auf einem Pixel sichern oder wiederherstellen beschrieben.
onRestore()
Der Sicherungsmanager ruft diese Methode während eines Wiederherstellungsvorgangs auf. Bei dieser Methode werden Ihre Sicherungsdaten bereitgestellt, mit denen Ihre App ihren vorherigen Zustand wiederherstellen kann, wie unter Wiederherstellung ausführen beschrieben.
Das System ruft diese Methode auf, um Sicherungsdaten wiederherzustellen, wenn der Nutzer Ihre App neu installiert. Ihre App kann aber auch eine Wiederherstellung anfordern.
Sicherung durchführen
Eine Sicherungsanfrage führt nicht zu einem sofortigen Aufruf deiner onBackup()
-Methode. Stattdessen wartet der Sicherungsmanager auf einen angemessenen Zeitraum und dann
führt eine Sicherung für alle Apps aus, die seit der letzten
Sicherung durchgeführt. An dieser Stelle müssen Sie Ihre App-Daten an den Sicherungsmanager weitergeben, damit sie im Cloud-Speicher gespeichert werden können.
Nur der Sicherungsmanager kann die onBackup()
-Methode Ihres Sicherungsagenten aufrufen. Jedes Mal, wenn sich Ihre App-Daten ändern und Sie eine Sicherung durchführen möchten, müssen Sie einen Sicherungsvorgang anfordern, indem Sie dataChanged()
aufrufen.
Weitere Informationen finden Sie unter Sicherung anfordern.
Tipp: Während der Entwicklung Ihrer App können Sie sofort eine Sicherung starten.
über den Sicherungsmanager mit der bmgr
.
Wenn der Sicherungsmanager die Methode onBackup()
aufruft, werden drei
Parameter:
oldState
- Offene, schreibgeschützte Datei
ParcelFileDescriptor
, der zeigt in den letzten von Ihrer App bereitgestellten Sicherungsstatus. Dies sind nicht die Sicherungsdaten aus einem Cloud-Speicher, sondern eine lokale Darstellung der gesicherten Daten. Zeitpunkt, zu demonBackup()
zuletzt aufgerufen wurde (definiert durchnewState
oder vononRestore()
onRestore()
wird im nächsten Abschnitt behandelt. WeilonBackup()
lässt das Lesen vorhandener Sicherungsdaten in der Cloud nicht zu Speicher verwenden, können Sie anhand dieser lokalen Darstellung feststellen, sich seit der letzten Sicherung geändert hat. data
- Ein
BackupDataOutput
Objekt, mit dem Sie Ihre Sicherungsdaten an den Sicherungsmanager senden. newState
- Ein offener, nicht schreibgeschützter
ParcelFileDescriptor
, der auf eine Datei verweist, in der Sie muss eine Darstellung der Daten schreiben, die Sie andata
gesendet haben. A kann die Darstellung ganz einfach sein, zum Beispiel der Zeitstempel der letzten Änderung für Ihre Datei. Dieses Objekt wird alsoldState
zurückgegeben, wenn Backup Manager das nächste Mal aufruft. IhreonBackup()
-Methode. Wenn Sie Ihre Sicherungsdaten nicht innewState
schreiben, verweistoldState
das nächste Mal auf eine leere Datei, wenn Backup Manager das nächste Mal aufruftonBackup()
Implementieren Sie mithilfe dieser Parameter die Methode onBackup()
, um Folgendes zu tun:
Prüfen Sie, ob sich Ihre Daten seit der letzten Sicherung geändert haben, indem Sie
oldState
zu Ihren aktuellen Daten. Wie Sie Daten inoldState
lesen, hängt davon ab, wie Sie sie ursprünglich innewState
geschrieben haben (siehe Schritt 3). Am einfachsten lässt sich der Status einer Datei mit dem Zeitstempel der letzten Änderung erfassen. Beispiel: So kannst du einen Zeitstempel vonoldState
lesen und vergleichen: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 }
Wenn sich nichts geändert hat und Sie keine Sicherung benötigen, fahren Sie mit Schritt 3 fort.
Wenn sich Ihre Daten im Vergleich zu
oldState
geändert haben, schreiben Sie die aktuellen Daten indata
, um sie im Cloud-Speicher zu sichern.Sie müssen jeden Datenblock als Entität in den
BackupDataOutput
schreiben. Eine entity ist ein vereinfachter binärer Datensatz, der durch einen eindeutigen Schlüssel identifiziert wird. . Der von Ihnen gesicherte Datensatz besteht also aus einer Reihe von Schlüssel/Wert-Paaren.So fügen Sie Ihrem Sicherungs-Dataset eine Entität hinzu:
Anruf
writeEntityHeader()
, und übergeben einen eindeutigen Zeichenfolgenschlüssel für die Daten, die Sie schreiben möchten, und den der Datengröße.Rufen Sie
writeEntityData()
auf und übergeben Sie einen Byte-Puffer mit Ihren Daten und der Anzahl der Bytes, die aus dem Puffer geschrieben werden sollen. Diese Anzahl sollte der anwriteEntityHeader()
übergebenen Größe entsprechen.
Im folgenden Code werden beispielsweise einige Daten in einen Bytestream flachgelegt und in eine einzelne Entität geschrieben:
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);
Führen Sie diese Schritte für alle Datenelemente aus, die Sie sichern möchten. Wie Sie Ihre Daten in Entitäten unterteilen, bleibt Ihnen überlassen. Sie können auch nur eine Entität verwenden.
Unabhängig davon, ob Sie eine Sicherung durchführen (in Schritt 2), schreiben Sie eine Darstellung die aktuellen Daten für
newState
ParcelFileDescriptor
. Der Sicherungsmanager speichert dieses Objekt lokal als Darstellung der Daten, die gerade gesichert werden. Dieser Wert wird Ihnen beim nächsten Aufruf vononBackup()
alsoldState
zurückgegeben, damit Sie feststellen können, ob eine weitere Sicherung erforderlich ist, wie in Schritt 1 beschrieben. Wenn Sie den aktuellen Datenstatus nicht in diese Datei schreiben, istoldState
beim nächsten Rückruf leer.Im folgenden Beispiel wird eine Darstellung der aktuellen Daten
newState
mit dem Zeitstempel der letzten Änderung der Datei: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);
Wiederherstellung ausführen
Wenn es an der Zeit ist, Ihre App-Daten wiederherzustellen, ruft der Sicherungsmanager die onRestore()
-Methode Ihres Sicherungsagenten auf. Wenn diese Methode aufgerufen wird, stellt der Sicherungsmanager Ihre Sicherungsdaten bereit, damit Sie sie auf dem Gerät wiederherstellen können.
Nur der Sicherungsmanager kann onRestore()
aufrufen. Das geschieht automatisch, wenn das System Ihre App installiert und vorhandene Sicherungsdaten findet.
Wenn der Sicherungsmanager die Methode onRestore()
aufruft, werden drei
Parameter:
data
- Ein
BackupDataInput
-Objekt, mit dem Sie Ihre Sicherungsdaten lesen können. appVersionCode
- Eine Ganzzahl, die den Wert der Methode
android:versionCode
Manifest-Attribut so wie es war, als diese Daten gesichert wurden. So können Sie die aktuelle App-Version prüfen und feststellen, ob das Datenformat kompatibel ist. Weitere Informationen zur Verwendung dieser Funktion zum Umgang mit verschiedenen Versionen von Wiederherstellungsdaten finden Sie unter Version der Wiederherstellungsdaten prüfen. newState
- Eine offene, lese-/schreibbare
ParcelFileDescriptor
, die auf eine Datei verweist, in die Sie den endgültigen Sicherungsstatus schreiben müssen, der mitdata
bereitgestellt wurde. Dieses Objekt wird beim nächsten Aufruf vononBackup()
alsoldState
zurückgegeben. Wie du weißt, musst du dasselbenewState
-Objekt auch imonBackup()
-Callback schreiben. Wenn du das hier tust, ist dasoldState
-Objekt, das anonBackup()
übergeben wird, auch beim ersten Aufruf vononBackup()
nach der Wiederherstellung des Geräts gültig.
Bei der Implementierung von onRestore()
sollten Sie Folgendes aufrufen:
readNextHeader()
zu data
, um alle Entitäten im Dataset zu iterieren. Gehen Sie für jede gefundene Entität so vor:
- Rufen Sie den Entitätsschlüssel mit
getKey()
ab. Vergleichen Sie den Entitätsschlüssel mit einer Liste bekannter Schlüssel/Wert-Paare, die Sie haben sollten. als statische finale Strings in Ihrer
BackupAgent
-Klasse deklariert. Wenn der Parameter key mit einem Ihrer bekannten Schlüsselstrings übereinstimmt, geben Sie eine Anweisung ein, um und speichern Sie sie auf dem Gerät:- Entitätsdatengröße abrufen mit
getDataSize()
und erstellen ein Byte-Array dieser Größe. - Rufen Sie
readEntityData()
auf und übergeben Sie ihm das Byte-Array, in das die Daten gespeichert werden sollen. Geben Sie außerdem den Start-Offset und die Größe an, die gelesen werden soll. - Dein Byte-Array ist jetzt voll. Sie können die Daten beliebig lesen und auf das Gerät schreiben.
- Entitätsdatengröße abrufen mit
Nachdem Sie Ihre Daten auf das Gerät gelesen und geschrieben haben, schreiben Sie den Status Ihre Daten in den
newState
-Parameter, wie beionBackup()
.
So können Sie beispielsweise die Daten wiederherstellen, die durch das Beispiel in im vorherigen Abschnitt:
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); }
In diesem Beispiel ist der an onRestore()
übergebene Parameter appVersionCode
nicht
verwendet. Sie können sie jedoch verwenden, wenn Sie eine Sicherung durchführen, während die Version der App des Nutzers tatsächlich rückwärts gewechselt ist (z. B. von Version 1.5 Ihrer App zu Version 1.0). Weitere Informationen finden Sie im nächsten Abschnitt.
Version der wiederherzustellenden Daten prüfen
Wenn der Sicherungsmanager Ihre Daten im Cloud-Speicher speichert, wird automatisch die Version Ihrer App gemäß dem android:versionCode
-Attribut Ihrer Manifestdatei eingeschlossen. Bevor der Sicherungsmanager Ihren Sicherungsagenten zur Wiederherstellung Ihrer Daten aufruft, prüft er die android:versionCode
der installierten App und vergleicht sie mit dem im Datensatz für die Wiederherstellung aufgezeichneten Wert. Wenn die im Wiederherstellungsdatensatz aufgezeichnete Version neuer als die App-Version auf dem Gerät ist, hat der Nutzer ein Downgrade seiner App durchgeführt. In diesem Fall beendet der Sicherungsmanager den Wiederherstellungsvorgang für Ihre App und ruft Ihre onRestore()
-Methode nicht auf, da der Wiederherstellungssatz für eine ältere Version als bedeutungslos gilt.
Sie können dieses Verhalten mit dem Attribut android:restoreAnyVersion
überschreiben.
Legen Sie dieses Attribut auf true
fest, um anzugeben, dass Sie die App wiederherstellen möchten
unabhängig von der Version des Wiederherstellungssatzes. Der Standardwert ist false
. Wenn Sie
auf true
setzen, ignoriert der Sicherungsmanager die
android:versionCode
und rufen Sie in allen Fällen die Methode onRestore()
auf. In der Praxis
Sie können den Versionsunterschied in der Datei „onRestore()
“ also manuell prüfen.
und alle erforderlichen Schritte unternehmen, um die Daten kompatibel zu machen, wenn die Versionen
nicht übereinstimmen.
Zur Unterstützung verschiedener Versionen während eines Wiederherstellungsvorgangs
Die Methode onRestore()
übergibt Ihnen den Versionscode, der in den Wiederherstellungsdaten enthalten ist.
als appVersionCode
-Parameter festgelegt. Anschließend können Sie den Versionscode der aktuellen App mit dem Feld PackageInfo.versionCode
abfragen. Beispiel:
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; }
Vergleiche dann die version
, die von PackageInfo
abgerufen wurde, mit der appVersionCode
, die an onRestore()
übergeben wurde.
Sicherung anfordern
Sie können jederzeit eine Sicherung anfordern, indem Sie dataChanged()
aufrufen. Dieses
informiert den Sicherungsmanager darüber, dass Sie Ihre Daten mithilfe der
Ihren Backup-Agent. Der Sicherungsmanager ruft dann zu einem späteren Zeitpunkt die Methode onBackup()
Ihres Sicherungsagenten auf. Normalerweise sollten Sie jedes Mal, wenn sich Ihre Daten ändern, ein Back-up anfordern, z. B. wenn der Nutzer eine App-Einstellung ändert, die Sie sichern möchten. Wenn du dataChanged()
mehrmals anrufst, bevor der Sicherungsmanager ein Back-up von deinem Kundenservicemitarbeiter anfordert, erhält dieser nur einen Anruf an onBackup()
.
Wiederherstellung beantragen
Während der normalen Lebensdauer Ihrer App sollten Sie keine Wiederherstellung anfordern müssen. Das System sucht automatisch nach Sicherungsdaten und führt eine Wiederherstellung durch, wenn Ihre App installiert wird.
Zur automatischen Sicherung migrieren
Du kannst deine App auf vollständige Datensicherungen umstellen, indem du Folgendes konfigurierst:
android:fullBackupOnly
zu true
im <application>
-Element in der Manifestdatei. Wenn Ihre App auf einem Gerät mit Android 5.1 (API-Level 22) oder niedriger ausgeführt wird, wird dieser Wert im Manifest ignoriert und es werden weiterhin Schlüssel/Wert-Sicherungen durchgeführt. Wenn Ihre App auf einem Gerät mit Android 6.0 (API-Level 23) oder höher ausgeführt wird, führt sie ein automatisches Back-up anstelle eines Schlüssel/Wert-Back-ups durch.
Datenschutz
Wir bei Google sind uns des Vertrauens bewusst, das Nutzer uns entgegenbringen, und unserer Verantwortung, die Privatsphäre der Nutzer zu schützen. Google überträgt Sicherungsdaten sicher zwischen Google-Servern, um Sicherungs- und Wiederherstellungsfunktionen bereitzustellen. Google behandelt diese Daten gemäß der Datenschutzerklärung von Google als personenbezogene Daten.
Außerdem können Nutzer die Datensicherungsfunktion über die Sicherungseinstellungen des Android-Systems deaktivieren. Wenn ein Nutzer die Sicherung deaktiviert, wird der Android Backup Service werden alle gespeicherten Sicherungsdaten gelöscht. Nutzer können die Sicherung auf dem Gerät wieder aktivieren, aber der Android-Sicherungsdienst stellt keine zuvor gelöschten Daten wieder her.