Android Backup Service fornisce il backup e il ripristino dello spazio di archiviazione sul cloud per le coppie chiave-valore nella tua app per Android. Durante un'operazione di backup di una coppia chiave-valore, il backup vengono trasmessi al trasporto di backup del dispositivo. Se il dispositivo utilizza il metodo di trasporto del backup di Google predefinito, i dati vengono trasmessi al Servizio di backup di Android per l'archiviazione.
I dati sono limitati a 5 MB per utente della tua app. Lo stoccaggio degli dati di backup non comporta costi.
Per una panoramica delle opzioni di backup di Android e indicazioni su quali dati eseguire il backup e il ripristino, consulta la sezione Backup Panoramica.
Implementare il backup delle coppie chiave-valore
Per eseguire il backup dei dati dell'app, devi implementare un agente di backup. L'agente di backup viene chiamato da Backup Manager sia durante il backup sia durante il ripristino.
Per implementare un agente di backup, devi:
Dichiara l'agente di backup nel file manifest con
android:backupAgent
.Per definire un agente di backup, svolgi una delle seguenti operazioni:
-
La classe
BackupAgent
fornisce l'interfaccia centrale utilizzata dalla tua app per comunicare con Backup Manager. Se estendi direttamente questa classe, devi sostituireonBackup()
eonRestore()
per gestire le operazioni di backup e ripristino per i tuoi dati. -
La classe
BackupAgentHelper
fornisce un pratico wrapper per la classeBackupAgent
, minimizzando la quantità di codice da scrivere. Nel tuoBackupAgentHelper
, devi utilizzare uno o più oggetti helper, che eseguire automaticamente il backup e il ripristino di determinati tipi di dati, in modo che devono implementareonBackup()
eonRestore()
. A meno che tu non abbia bisogno del controllo completo dei backup della tua app, ti consigliamo di utilizzareBackupAgentHelper
per gestirli.Android attualmente fornisce assistenti per il backup e il ripristino completa i file da
SharedPreferences
e archiviazione interna.
-
Dichiara l'agente di backup nel file manifest
Una volta deciso il nome della classe per l'agente di backup, dichiaralo nel manifest utilizzando l'attributo android:backupAgent
nel tag <application>
.
Ad esempio:
<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>
Per supportare i dispositivi meno recenti, ti consigliamo di aggiungere la chiave API <meta-data>
al tuo file manifest Android. Android Backup Service non richiede più
chiave di servizio, ma alcuni dispositivi meno recenti potrebbero comunque verificare la presenza di una chiave durante il backup
verso l'alto. Imposta android:name
su com.google.android.backup.api_key
e android:value
su unused
.
La
android:restoreAnyVersion
assume un valore booleano per indicare se vuoi ripristinare l'app
di dati a prescindere dalla versione corrente dell'app rispetto alla versione
generato i dati di backup. Il valore predefinito è false
. Per ulteriori informazioni, consulta Verificare la versione dei dati di ripristino.
Estendi BackupAgentHelper
Se vuoi, devi creare il tuo agente di backup utilizzando BackupAgentHelper
esegui il backup di file completi da SharedPreferences
o dalla memoria interna.
La creazione dell'agente di backup con BackupAgentHelper
richiede molto meno codice rispetto
estendendo BackupAgent
, perché non devi implementare onBackup()
onRestore()
.
La tua implementazione di BackupAgentHelper
deve utilizzare uno o più helper di backup.
Un helper di backup è un componente specializzato che BackupAgentHelper
richiama per eseguire operazioni di backup e ripristino per un determinato tipo di dati. La
Il framework Android al momento fornisce due diversi tipi di supporto:
SharedPreferencesBackupHelper
per eseguire il backup diSharedPreferences
file.FileBackupHelper
per eseguire il backup dei file dalla memoria interna.
Puoi includere più helper in BackupAgentHelper
, ma è necessario un solo
helper per ogni tipo di dati. Vale a dire che se disponi di più
SharedPreferences
file, ti serve solo uno
SharedPreferencesBackupHelper
.
Per ogni aiutante che vuoi aggiungere al tuo BackupAgentHelper
, devi eseguire le
seguire durante
Metodo onCreate()
:
- Crea un'istanza della classe di helper desiderata. Nel constructor della classe, devi specificare i file di cui vuoi eseguire il backup.
- Chiama
addHelper()
per aggiungere l'assistente al tuoBackupAgentHelper
.
Le sezioni seguenti descrivono come creare un agente di backup utilizzando ciascuno degli aiutanti disponibili.
Esegui il backup di SharedPreferences
Quando crei un'istanza di SharedPreferencesBackupHelper
, devi includere il nome di uno o più file SharedPreferences
.
Ad esempio, per eseguire il backup di un file SharedPreferences
denominato user_preferences
, viene eseguita
l'agente di backup completo utilizzando BackupAgentHelper
ha il seguente aspetto:
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); } }
Il file SharedPreferencesBackupHelper
include tutto il codice necessario per eseguire il backup e il recupero di un file SharedPreferences
.
Quando Gestione backup chiama onBackup()
e onRestore()
,
BackupAgentHelper
chiama gli assistenti di backup per eseguire il backup e ripristinare il tuo
nei file specificati.
Esegui il backup di altri file
Quando esegui l'inizializzazione di un FileBackupHelper
, devi includere il nome di uno o più file salvati nello spazio di archiviazione interno dell'app, come specificato da getFilesDir()
, che è la stessa posizione in cui openFileOutput()
scrive i file.
Ad esempio, per eseguire il backup di due file denominati scores
e stats
, un agente di backup
utilizzando BackupAgentHelper
ha il seguente aspetto:
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
include tutto il codice necessario per il backup e il ripristino
salvati nella memoria interna dell'app.
Tuttavia, la lettura e la scrittura su file nella memoria interna non sono thread-safe. Per assicurarti che l'agente di backup non legga o scriva i file contemporaneamente alle tue attività, devi utilizzare istruzioni sincronizzate ogni volta che esegui una lettura o una scrittura. Ad esempio, in qualsiasi attività in cui leggi e scrivi il file, devi avere un oggetto da utilizzare come blocco intrinseco per le istruzioni sincronizzate:
Kotlin
// Object for intrinsic lock companion object { val sDataLock = Any() }
Java
// Object for intrinsic lock static final Object sDataLock = new Object();
Quindi, crea un'istruzione sincronizzata con questo blocco ogni volta che leggi o scrivi i file. Ad esempio, di seguito è riportato un'istruzione sincronizzata per scrivere in un file il punteggio più recente di una partita:
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"); }
Devi sincronizzare le istruzioni di lettura con lo stesso blocco.
Poi, in BackupAgentHelper
, devi sostituire onBackup()
e
onRestore()
per sincronizzare le operazioni di backup e ripristino con lo stesso
blocco intrinseco. Ad esempio, l'esempio MyFileBackupAgent
delle esigenze precedenti
utilizza i seguenti metodi:
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); } }
Estendi BackupAgent
La maggior parte delle app non dovrebbe dover estendere direttamente la classe BackupAgent
, ma dovrebbe invece estendere BackupAgentHelper
per sfruttare le classi di assistenza integrate che eseguono automaticamente il backup e il ripristino dei file.
Tuttavia, puoi estendere BackupAgent
direttamente per:
- Esegui la versione del formato dei dati. Ad esempio, se prevedi di dover revisionare il formato in cui scrivi i dati dell'app, puoi creare un agente di backup per verificare la versione dell'app durante un'operazione di ripristino ed eseguire eventuali operazioni di compatibilità necessarie se la versione sul dispositivo è diversa da quella dei dati di backup. Per ulteriori informazioni, vedi Verificare la versione dei dati di ripristino.
- Specifica le parti di dati di cui eseguire il backup. Anziché eseguire il backup di un intero file, puoi specificare le parti di dati di cui eseguire il backup e la modalità di ripristino di ciascuna parte sul dispositivo. Questo può anche aiutarti a gestire versioni diverse, perché leggi e scrivi i dati come entità univoche anziché come file completi.
- Esegui il backup dei dati in un database. Se vuoi usare un database SQLite
da ripristinare quando l'utente reinstalla la tua app, devi creare un
BackupAgent
che legge i dati appropriati durante un'operazione di backup, poi crea la tabella e inserisci i dati durante un'operazione di ripristino.
Se non devi eseguire nessuna delle attività indicate sopra e vuoi eseguire il backup
completa i file da SharedPreferences
o dalla memoria interna, consulta Estensione
BackupAgentHelper
.
Metodi obbligatori
Quando crei un BackupAgent
, devi implementare i seguenti metodi callback:
onBackup()
- Il Gestore backup chiama questo metodo dopo che hai richiesto un di backup. Con questo metodo, leggi i dati dell'app dal dispositivo e passa i dati di cui vuoi eseguire il backup a Gestione backup, come descritto in Eseguire un backup.
onRestore()
Il Gestore backup chiama questo metodo durante un'operazione di ripristino. Questo metodo fornisce i tuoi dati di backup, che l'app può utilizzare per ripristinare i dati precedenti come descritto in Eseguire un ripristino.
Il sistema chiama questo metodo per ripristinare i dati di backup quando l'utente reinstalla l'app, ma quest'ultima può anche richiedere una ripristina.
Esegui un backup
Una richiesta di backup non comporta una chiamata immediata al metodo onBackup()
. Backup Manager attende invece il momento opportuno, quindi esegue un backup di tutte le app che ne hanno richiesto uno dall'ultimo backup. A questo punto devi fornire i dati dell'app
in Gestione backup per poterlo salvare nello spazio di archiviazione sul cloud.
Solo Backup Manager può chiamare il metodo onBackup()
dell'agente di backup. Ciascuna
volta che i dati dell'app vengono modificati ed eseguire il backup, devi
per richiedere un'operazione di backup chiamando
dataChanged()
Per saperne di più, vedi Richiedere un backup.
Suggerimento: durante lo sviluppo dell'app, puoi avviare un backup immediato
dell'operazione da Gestione backup con bmgr
strumento.
Quando Backup Manager chiama il metodo onBackup()
, passa tre parametri:
oldState
- Un indirizzo aperto di sola lettura
ParcelFileDescriptor
con destinazione all'ultimo stato di backup fornito dall'app. Questi non sono i dati di backup da spazio di archiviazione sul cloud, ma una rappresentazione locale dei dati di cui è stato eseguito il backup L'ultima volta che è stata chiamataonBackup()
, come definito danewState
o daonRestore()
.onRestore()
verrà trattato nella sezione successiva. PoichéonBackup()
non consente di leggere i dati di backup esistenti nel cloud di archiviazione, puoi utilizzare questa rappresentazione locale per determinare se i tuoi dati è cambiato rispetto all'ultimo backup. data
- Un
BackupDataOutput
utilizzato per caricare i dati di backup in Gestione backup. newState
- Un
ParcelFileDescriptor
aperto in lettura/scrittura che rimanda a un file in cui devi scrivere una rappresentazione dei dati che hai inviato adata
. R una rappresentazione può essere semplice come il timestamp dell'ultima modifica del file. Questo oggetto viene restituito comeoldState
alla successiva chiamata del metodoonBackup()
da parte di Backup Manager. Se non scrivi i dati di backup sunewState
, alloraoldState
punterà a un file vuoto la prossima volta che chiamerà Gestione backuponBackup()
.
Utilizzando questi parametri, implementa il metodo onBackup()
per:
Controlla se i dati sono cambiati dall'ultimo backup confrontandoli con quelli attuali.
oldState
La modalità di lettura dei dati inoldState
dipende da come l'hai scritto originariamente innewState
(vedi il passaggio 3). Il modo più semplice registra lo stato di un file con il timestamp dell'ultima modifica. Ad esempio: Per leggere e confrontare un timestamp dioldState
, procedi nel seguente modo: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 }
Se non è cambiato nulla e non devi eseguire il backup, vai al passaggio 3.
Se i dati sono cambiati rispetto a
oldState
, scrivi i dati attuali indata
per eseguirne il backup nello spazio di archiviazione sul cloud.Devi scrivere ogni blocco di dati come entità in
BackupDataOutput
. Un L'entità è un record di dati binario appiattito identificato da una chiave univoca stringa. Pertanto, il set di dati di cui esegui il backup è concettualmente un insieme coppie chiave-valore.Per aggiungere un'entità al set di dati di backup, devi:
Chiama
writeEntityHeader()
, passando una chiave di stringa univoca per i dati che stai per scrivere e le dimensioni dei dati.Chiama
writeEntityData()
, passare un buffer di byte che contiene i tuoi dati e il numero di byte scrivere dal buffer, che deve corrispondere alla dimensione passatawriteEntityHeader()
.
Ad esempio, il seguente codice appiattisce alcuni dati in uno stream di byte e li scrive in una singola entità:
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);
Esegui questa operazione per ogni dato di cui vuoi eseguire il backup. Come dividi trasforma i tuoi dati in entità. Puoi anche utilizzare una sola entità.
Indipendentemente dal fatto che tu abbia eseguito o meno un backup (nel passaggio 2), scrivi una rappresentazione i dati attuali al
newState
ParcelFileDescriptor
. Backup Manager conserva questo oggetto localmente come rappresentazione dei dati di cui viene eseguito il backup. Te lo ritrasmette comeoldState
la prossima volta chiamaonBackup()
per consentirti di determinare se un altro backup viene necessario, come gestito nel passaggio 1. Se non scrivi lo stato corrente dei dati in questo file,oldState
sarà vuoto durante il successivo callback.L'esempio seguente salva una rappresentazione dei dati correnti in
newState
utilizzando il timestamp dell'ultima modifica del 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);
Esegui un ripristino
Quando è il momento di ripristinare i dati delle app, Backup Manager chiama il metodo onRestore()
dell'agente di backup. Quando chiama questo metodo, Gestione backup
invia i dati di backup per ripristinarli sul dispositivo.
Solo il gestore backup può chiamare onRestore()
. Questa operazione viene eseguita automaticamente
Quando il sistema installa l'app e trova i dati di backup esistenti.
Quando Gestione backup chiama il metodo onRestore()
, passa tre
parametri:
data
- Un oggetto
BackupDataInput
, che ti consente di leggere i dati di backup. appVersionCode
- Un numero intero che rappresenta il valore del parametro
android:versionCode
, come avveniva al momento del backup di questi dati. Puoi utilizzare questo per eseguire un controllo incrociato della versione corrente dell'app e determinare se il formato dei dati è compatibili. Per ulteriori informazioni sull'utilizzo di questa opzione per gestire diverse versioni dei dati di ripristino, consulta Verificare la versione dei dati di ripristino. newState
- Un file
ParcelFileDescriptor
aperto in lettura/scrittura che punta a un file in cui deve scrivere lo stato del backup finale fornito condata
. Questo oggetto viene restituito comeoldState
alla successiva chiamata dionBackup()
. Ricorda devi anche scrivere lo stesso oggettonewState
inonBackup()
il callback; in questo caso si garantisce che l'oggettooldState
sia stato assegnatoonBackup()
è valido anche la prima volta cheonBackup()
viene chiamato dopo il viene ripristinato sul tuo dispositivo.
Nell'implementazione di onRestore()
, devi chiamare
readNextHeader()
su data
per eseguire l'iterazione di tutte le entità nel set di dati. Per ogni entità ritrovata:
- Recupera la chiave dell'entità con
getKey()
Confronta la chiave dell'entità con un elenco di valori di chiavi noti che dovresti aver dichiarato come stringhe finali statiche all'interno della classe
BackupAgent
. Quando corrisponde a una delle stringhe di chiavi note, inserisci un'istruzione per estrarre i dati dell'entità e salvarli sul dispositivo:- Ottieni le dimensioni dei dati dell'entità con
getDataSize()
e crea un array di byte di queste dimensioni. - Chiama
readEntityData()
e passa l'array di byte, dove verranno memorizzati i dati, e specifica lo spostamento iniziale e le dimensioni da leggere. - L'array di byte è ora completo. Leggi i dati e scrivili sul dispositivo come preferisci.
- Ottieni le dimensioni dei dati dell'entità con
Dopo aver letto e scritto di nuovo i dati sul dispositivo, scrivi lo stato dei dati nel parametro
newState
come faresti duranteonBackup()
.
Ad esempio, ecco come ripristinare i dati di cui è stato eseguito il backup nell'esempio sezione precedente:
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 questo esempio, il parametro appVersionCode
passato a onRestore()
non viene utilizzato. Tuttavia, ti consigliamo di utilizzarlo se hai scelto di eseguire un backup quando la versione dell'app dell'utente è effettivamente passata a una precedente (ad esempio, l'utente è passato dalla versione 1.5 della tua app alla 1.0). Per ulteriori informazioni, vedi
nella prossima sezione.
Controlla la versione dei dati di ripristino
Quando Gestione backup salva i dati nello spazio di archiviazione sul cloud,
include la versione dell'app, come definita dall'interfaccia utente
Attributo android:versionCode
. Prima che Gestione backup chiami il tuo backup
di ripristino dei dati, viene esaminato il android:versionCode
installata e lo confronta con il valore registrato nel set di dati di ripristino. Se
la versione registrata nel set di dati di ripristino è più recente rispetto alla versione dell'app sul
sul dispositivo, l'utente ha eseguito il downgrade dell'app. In questo caso, il token di backup
Il gestore interromperà l'operazione di ripristino per la tua app e non chiamerà il tuo
onRestore()
, perché il set di ripristino è considerato privo di significato per un
precedente.
Puoi ignorare questo comportamento con l'attributo android:restoreAnyVersion
.
Imposta questo attributo su true
per indicare che vuoi ripristinare l'app
a prescindere dalla versione del set di ripristino. Il valore predefinito è false
. Se lo imposti su true
, Backup Manager ignorerà true
e chiamerà il metodo onRestore()
in tutti i casi. In questo modo, puoi controllare manualmente la differenza di versione nel metodo onRestore()
e adottare le misure necessarie per rendere i dati compatibili se le versioni non corrispondono.
Per aiutarti a gestire versioni diverse durante un'operazione di ripristino,
Il metodo onRestore()
ti trasmette il codice di versione incluso nei dati di ripristino
impostato come parametro appVersionCode
. Puoi quindi eseguire una query sul codice della versione dell'app corrente con il campo PackageInfo.versionCode
. Ad esempio:
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; }
Poi confronta i valori di version
acquisiti da
PackageInfo
al
appVersionCode
è passato a onRestore()
.
Richiedere un backup
Puoi richiedere un'operazione di backup in qualsiasi momento chiamando dataChanged()
. Questo metodo informa Backup Manager che vuoi eseguire il backup dei dati utilizzando il tuo agente di backup. Backup Manager chiama quindi il metodo onBackup()
dell'agente di backup in un momento successivo. In genere, devi richiedere un backup ogni volta che i dati cambiano (ad esempio quando l'utente modifica una preferenza dell'app di cui vuoi eseguire il backup). Se chiami dataChanged()
più volte
volte prima che Gestore backup richieda un backup all'agente, quest'ultimo
riceve comunque una sola chiamata al numero onBackup()
.
Richiedere un ripristino
Durante il normale ciclo di vita dell'app, non dovrebbe essere necessario richiedere un ripristino operativa. Il sistema controlla automaticamente i dati di backup ed esegue una ripristinare l'app una volta installata l'app.
Esegui la migrazione al backup automatico
Puoi eseguire la transizione dell'app ai backup completi dei dati impostando
android:fullBackupOnly
a true
nell'elemento <application>
del file manifest. Durante l'esecuzione
su un dispositivo con Android 5.1 (livello API 22) o versioni precedenti, la tua app ignora questo
nel file manifest e continui a eseguire backup delle coppie chiave-valore. Quando viene eseguita su un dispositivo con Android 6.0 (livello API 23) o versioni successive, l'app esegue il backup automatico anziché il backup delle chiavi.
Privacy degli utenti
Google è consapevole della fiducia che gli utenti ripongono in noi e della nostra responsabilità di proteggere la loro privacy. Google trasmette in sicurezza i dati di backup da e verso i server di Google al fine di fornire funzionalità di backup e ripristino. Google tratta questi dati come informazioni personali, in conformità alle Norme sulla privacy.
Inoltre, gli utenti possono disattivare la funzionalità di backup dei dati tramite Android impostazioni di backup del sistema. Quando un utente disattiva il backup, Android Backup Service elimina tutti i dati di backup salvati. Un utente può riattivare il backup sul dispositivo, ma Android Backup Service non ripristinerà i dati precedentemente eliminati.