Sauvegarder les données utilisateur avec la sauvegarde automatique

La fonctionnalité de sauvegarde automatique des applications sauvegarde automatiquement les données d'un utilisateur à partir d'applications ciblées et exécutées sur Android 6.0 (niveau d'API 23) ou version ultérieure. Android conserve les données de l'application en les important dans le Google Drive de l'utilisateur, où elles sont protégées par les identifiants de son compte Google. La sauvegarde est chiffrée de bout en bout sur les appareils équipés d'Android 9 ou version ultérieure, à l'aide du code, du schéma ou du mot de passe de l'appareil. Chaque application peut allouer jusqu'à 25 Mo de données de sauvegarde par utilisateur. Le stockage des données de sauvegarde se fait sans frais. Votre application peut personnaliser le processus de sauvegarde ou désactiver les sauvegardes en désactivant les sauvegardes.

Pour obtenir une présentation des options de sauvegarde d'Android et des conseils sur les données à sauvegarder et à restaurer, consultez la page Présentation de la sauvegarde de données.

Fichiers sauvegardés

Par défaut, la sauvegarde automatique inclut les fichiers de la plupart des répertoires attribués à votre application par le système :

La sauvegarde automatique exclut les fichiers des répertoires renvoyés par getCacheDir(), getCodeCacheDir() et getNoBackupFilesDir(). Les fichiers enregistrés à ces emplacements ne sont nécessaires que temporairement et sont intentionnellement exclus des opérations de sauvegarde.

Vous pouvez configurer votre application pour inclure et exclure des fichiers spécifiques. Pour en savoir plus, consultez la section Inclure et exclure des fichiers.

Emplacement de la sauvegarde

Les données de sauvegarde sont stockées dans un dossier privé du compte Google Drive de l'utilisateur, dans la limite de 25 Mo par application. Les données enregistrées ne sont pas comptabilisées dans le quota Google Drive personnel de l'utilisateur. Seule la sauvegarde la plus récente est stockée. Lorsqu'une sauvegarde est effectuée, toute sauvegarde précédente est supprimée. Les données de sauvegarde ne peuvent pas être lues par l'utilisateur ni par les autres applications de l'appareil.

Les utilisateurs peuvent voir la liste des applications qui ont été sauvegardées dans l'application Google Drive pour Android. Sur un appareil Android, les utilisateurs peuvent trouver cette liste dans le panneau de navigation de l'application Drive, sous Paramètres > Sauvegarder et réinitialiser.

Les sauvegardes de chaque ensemble appareil-configuration-cycle de vie sont stockées dans des ensembles de données distincts, comme décrit dans les exemples suivants:

  • Si l'utilisateur possède deux appareils, un ensemble de données de sauvegarde existe pour chacun d'eux.

  • Si l'utilisateur rétablit la configuration d'usine d'un appareil, puis le configure avec le même compte, la sauvegarde est stockée dans un nouvel ensemble de données. Les ensembles de données obsolètes sont automatiquement supprimés après une période d'inactivité.

Planning des sauvegardes

Les sauvegardes s'effectuent automatiquement lorsque toutes les conditions suivantes sont remplies :

  • L'utilisateur a activé la sauvegarde sur l'appareil. Sous Android 9, ce paramètre se trouve dans Paramètres > Système > Sauvegarde.
  • Au moins 24 heures se sont écoulées depuis la dernière sauvegarde.
  • L'appareil est inactif.
  • L'appareil est connecté à un réseau Wi-Fi (si l'utilisateur de l'appareil n'a pas activé les sauvegardes via les données mobiles).

En pratique, ces conditions se produisent environ toutes les nuits, mais un appareil peut ne jamais effectuer de sauvegarde (par exemple, s'il ne se connecte jamais à un réseau). Pour préserver la bande passante réseau, l'importation n'a lieu que si les données de l'application ont changé.

Pendant la sauvegarde automatique, le système arrête l'application pour s'assurer qu'elle n'écrit plus dans le système de fichiers. Par défaut, le système de sauvegarde ignore les applications qui s'exécutent au premier plan pour éviter une mauvaise expérience utilisateur. Vous pouvez remplacer le comportement par défaut en définissant l'attribut android:backupInForeground sur "true".

Pour simplifier les tests, Android inclut des outils qui vous permettent de lancer manuellement une sauvegarde de votre application. Pour en savoir plus, consultez la section Tester la sauvegarde et la restauration.

Planning des restaurations

Les données sont restaurées chaque fois que l'application est installée, que ce soit à partir du Play Store, lors de la configuration de l'appareil (lorsque le système installe des applications déjà installées) ou en exécutant l'installation adb. L'opération de restauration a lieu après l'installation de l'APK, mais avant que l'utilisateur puisse lancer l'application.

Lors de l'assistant de configuration initial de l'appareil, la liste des ensembles de données de sauvegarde disponibles s'affiche, et l'utilisateur est invité à choisir celui à partir duquel restaurer les données. L'ensemble de données de sauvegarde sélectionné devient l'ensemble de données ancêtre de l'appareil. L'appareil peut effectuer une restauration à partir de ses propres sauvegardes ou de l'ensemble de données ancêtre. Si des sauvegardes des deux sources sont disponibles, l'appareil donne la priorité à sa propre sauvegarde. Si l'utilisateur n'a pas utilisé l'assistant de configuration de l'appareil, l'appareil ne peut effectuer de restauration qu'à partir de ses propres sauvegardes.

Pour simplifier les tests, Android inclut des outils qui vous permettent de lancer manuellement une restauration de votre application. Pour en savoir plus, consultez la section Tester la sauvegarde et la restauration.

Activer et désactiver la sauvegarde

Les applications qui ciblent Android 6.0 (niveau d'API 23) ou une version ultérieure participent automatiquement à la sauvegarde automatique. Dans le fichier manifeste de votre application, définissez la valeur booléenne android:allowBackup pour activer ou désactiver la sauvegarde. La valeur par défaut est true, mais nous vous recommandons de définir explicitement l'attribut dans votre fichier manifeste, comme illustré dans l'exemple suivant:

<manifest ... >
    ...
    <application android:allowBackup="true" ... >
        ...
    </application>
</manifest>

Vous pouvez désactiver les sauvegardes en définissant android:allowBackup sur false. Cela peut être utile si votre application peut recréer son état via un autre mécanisme ou si elle traite des informations sensibles.

Inclure et exclure des fichiers

Par défaut, le système sauvegarde presque toutes les données de l'application. Pour en savoir plus, consultez la section sur les fichiers sauvegardés.

Cette section vous explique comment définir des règles XML personnalisées pour contrôler ce qui est sauvegardé. Si votre application cible Android 12 (niveau d'API 31) ou une version ultérieure, vous devez spécifier un ensemble supplémentaire de règles de sauvegarde XML, comme décrit dans cette section, afin de prendre en charge les modifications apportées à la restauration des sauvegardes qui ont été introduites pour les appareils exécutant ces versions d'Android.

Contrôler la sauvegarde sur Android 11 ou version antérieure

Suivez les étapes de cette section pour contrôler les fichiers sauvegardés sur les appareils exécutant Android 11 (niveau d'API 30) ou une version antérieure.

  1. Dans votre fichier AndroidManifest.xml, ajoutez l'attribut android:fullBackupContent à l'élément <application>, comme indiqué dans l'exemple suivant. Cet attribut renvoie vers un fichier XML contenant des règles de sauvegarde.

    <application ...
     android:fullBackupContent="@xml/backup_rules">
    </application>
    
  2. Créez un fichier XML appelé @xml/backup_rules dans le répertoire res/xml/. Dans ce fichier, ajoutez des règles avec les éléments <include> et <exclude>. L'exemple suivant sauvegarde toutes les préférences partagées, à l'exception de device.xml :

    <?xml version="1.0" encoding="utf-8"?>
    <full-backup-content>
     <include domain="sharedpref" path="."/>
     <exclude domain="sharedpref" path="device.xml"/>
    </full-backup-content>
    

Définir les conditions de l'appareil requises pour la sauvegarde

Si votre application enregistre des informations sensibles sur l'appareil, vous pouvez spécifier les conditions selon lesquelles les données de votre application sont incluses dans la sauvegarde de l'utilisateur. Vous pouvez ajouter les conditions suivantes sous Android 9 (niveau d'API 28) ou version ultérieure:

Si vous avez mis à niveau vos appareils de développement vers Android 9, vous devez désactiver, puis réactiver la sauvegarde de données après la mise à niveau. En effet, Android ne chiffre les sauvegardes qu'à l'aide d'un secret côté client, après en avoir informé les utilisateurs dans les paramètres ou l'assistant de configuration.

Pour déclarer les conditions d'inclusion, définissez l'attribut requireFlags sur une ou plusieurs valeurs choisies dans les éléments <include> de votre ensemble de règles de sauvegarde:

backup_rules.xml

<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
    <!-- App data isn't included in user's backup
         unless client-side encryption is enabled. -->
    <include domain="file" path="."
             requireFlags="clientSideEncryption" />
</full-backup-content>

Si votre application implémente un système de sauvegarde par clé-valeur ou si vous implémentez vous-même BackupAgent, vous pouvez également appliquer ces exigences conditionnelles à votre logique de sauvegarde en effectuant une comparaison au niveau du bit entre l'ensemble d'indicateurs de transport d'un objet BackupDataOutput et les indicateurs FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED ou FLAG_DEVICE_TO_DEVICE_TRANSFER de votre agent de sauvegarde personnalisé.

L'extrait de code suivant présente un exemple d'utilisation de cette méthode :

Kotlin

class CustomBackupAgent : BackupAgent() {
    override fun onBackup(oldState: ParcelFileDescriptor?,
            data: BackupDataOutput?, newState: ParcelFileDescriptor?) {
        if (data != null) {
            if ((data.transportFlags and
                    FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED) != 0) {
                // Client-side backup encryption is enabled.
            }

            if ((data.transportFlags and FLAG_DEVICE_TO_DEVICE_TRANSFER) != 0) {
                // Local device-to-device transfer is enabled.
            }
        }
    }

    // Implementation of onRestore() here.
}

Java

public class CustomBackupAgent extends BackupAgent {
    @Override
    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
            ParcelFileDescriptor newState) throws IOException {
        if ((data.getTransportFlags() &
                FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED) != 0) {
            // Client-side backup encryption is enabled.
        }

        if ((data.getTransportFlags() &
                FLAG_DEVICE_TO_DEVICE_TRANSFER) != 0) {
            // Local device-to-device transfer is enabled.
        }
    }

    // Implementation of onRestore() here.
}

Contrôler la sauvegarde sous Android 12 ou version ultérieure

Si votre application cible Android 12 (niveau d'API 31) ou une version ultérieure, suivez les étapes de cette section pour contrôler les fichiers sauvegardés sur les appareils équipés d'Android 12 ou version ultérieure.

  1. Dans votre fichier AndroidManifest.xml, ajoutez l'attribut android:dataExtractionRules à l'élément <application>, comme indiqué dans l'exemple suivant. Cet attribut renvoie vers un fichier XML contenant des règles de sauvegarde.

    <application ...
     android:dataExtractionRules="backup_rules.xml">
    </application>
    
  2. Créez un fichier XML appelé backup_rules.xml dans le répertoire res/xml/. Dans ce fichier, ajoutez des règles avec les éléments <include> et <exclude>. L'exemple suivant sauvegarde toutes les préférences partagées, à l'exception de device.xml :

    <?xml version="1.0" encoding="utf-8"?>
    <data-extraction-rules>
     <cloud-backup [disableIfNoEncryptionCapabilities="true|false"]>
       <include domain="sharedpref" path="."/>
       <exclude domain="sharedpref" path="device.xml"/>
     </cloud-backup>
    </data-extraction-rules>
    

Syntaxe de la configuration XML

La syntaxe XML du fichier de configuration varie en fonction de la version d'Android ciblée et exécutée par votre application.

Android 11 ou version antérieure

Utilisez la syntaxe XML suivante pour le fichier de configuration qui contrôle la sauvegarde pour les appareils équipés d'Android 11 ou version antérieure.

<full-backup-content>
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"
    requireFlags=["clientSideEncryption" | "deviceToDeviceTransfer"] />
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string" />
</full-backup-content>

Android 12 ou version ultérieure

Si votre application cible Android 12 (niveau d'API 31) ou une version ultérieure, utilisez la syntaxe XML suivante pour le fichier de configuration qui contrôle la sauvegarde pour les appareils équipés d'Android 12 ou version ultérieure.

<data-extraction-rules>
  <cloud-backup [disableIfNoEncryptionCapabilities="true|false"]>
    ...
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
  </cloud-backup>
  <device-transfer>
    ...
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
  </device-transfer>
</data-extraction-rules>

Chaque section de la configuration (<cloud-backup>, <device-transfer>) contient des règles qui ne s'appliquent qu'à ce type de transfert. Cette séparation vous permet, par exemple, d'exclure un fichier ou un répertoire des sauvegardes Google Drive, tout en continuant à le transférer pendant les transferts d'appareil à appareil (D2D). Cela peut être utile si vous avez des fichiers trop volumineux pour être sauvegardés dans le cloud, mais qui peuvent être transférés d'un appareil à un autre sans problème.

S'il n'existe aucune règle pour un mode de sauvegarde particulier, par exemple si la section <device-transfer> est manquante, ce mode est entièrement activé pour tous les contenus, à l'exception des répertoires no-backup et cache, comme décrit dans la section Fichiers sauvegardés.

Votre application peut définir l'indicateur disableIfNoEncryptionCapabilities dans la section <cloud-backup> pour que la sauvegarde ne se produise que si elle peut être chiffrée, par exemple lorsque l'utilisateur dispose d'un écran de verrouillage. Définir cette contrainte empêche l'envoi des sauvegardes dans le cloud si l'appareil de l'utilisateur n'est pas compatible avec le chiffrement. Toutefois, étant donné que les transferts D2D ne sont pas envoyés au serveur, ils continueront à fonctionner même sur les appareils qui ne sont pas compatibles avec le chiffrement.

Syntaxe des éléments include et exclude

Dans les balises <full-backup-content>, <cloud-backup> et <device-transfer> (en fonction de la version d'Android de l'appareil et de la targetSDKVersion de votre application), vous pouvez définir des éléments <include> et <exclude> :

<include>

Permet de spécifier un fichier ou un dossier à sauvegarder. Par défaut, la sauvegarde automatique inclut presque tous les fichiers d'application. Si vous spécifiez un élément <include>, le système n'inclut plus de fichiers par défaut et ne sauvegarde que les fichiers spécifiés. Pour inclure plusieurs fichiers, utilisez plusieurs éléments <include>.

Sous Android 11 ou version antérieure, cet élément peut également contenir l'attribut requireFlags, que la section décrivant comment définir des exigences conditionnelles pour la sauvegarde aborde plus en détail.

Les fichiers se trouvant dans des répertoires renvoyés par getCacheDir(), getCodeCacheDir() ou getNoBackupFilesDir() sont toujours exclus, même si vous essayez de les inclure.

<exclude>

Permet de spécifier un fichier ou un dossier à exclure lors de la sauvegarde. Voici quelques fichiers généralement exclus de la sauvegarde:

  • Fichiers possédant des identifiants propres à l'appareil, émis par un serveur ou générés sur l'appareil. Par exemple, Firebase Cloud Messaging (FCM) doit générer un jeton d'enregistrement chaque fois qu'un utilisateur installe votre application sur un nouvel appareil. Si l'ancien jeton d'enregistrement est restauré, l'application peut se comporter de manière inattendue.

  • Fichiers liés au débogage de l'application.

  • Fichiers volumineux entraînant le dépassement du quota de sauvegarde de 25 Mo par l'application.

Chaque élément <include> et <exclude> doit inclure les deux attributs suivants :

domain

Permet de spécifier l'emplacement de la ressource. Les valeurs valides pour cet attribut sont les suivantes:

  • root: répertoire du système de fichiers où sont stockés tous les fichiers privés appartenant à cette application.
  • file: répertoires renvoyés par getFilesDir().
  • database: répertoires renvoyés par getDatabasePath(). Les bases de données créées avec SQLiteOpenHelper sont stockées ici.
  • sharedpref: répertoire dans lequel les SharedPreferences sont stockés.
  • external: répertoire renvoyé par getExternalFilesDir().
  • device_root: comme root, mais pour l'espace de stockage protégé par l'appareil.
  • device_file: comme file, mais pour l'espace de stockage protégé par l'appareil.
  • device_database: comme database, mais pour l'espace de stockage protégé par l'appareil.
  • device_sharedpref: comme sharedpref, mais pour le stockage protégé par l'appareil.
path

Permet de spécifier un fichier ou un dossier à inclure dans la sauvegarde ou à exclure de celui-ci. Notez les points suivants:

  • Cet attribut n'est pas compatible avec les caractères génériques ou les expressions régulières.
  • Vous pouvez référencer le répertoire actuel à l'aide de ./, mais vous ne pouvez pas référencer le répertoire parent, par exemple à l'aide de .., pour des raisons de sécurité.
  • Si vous spécifiez un répertoire, la règle s'applique à tous les fichiers du répertoire et aux sous-répertoires récursifs.

Implémenter BackupAgent

Les applications qui implémentent la sauvegarde automatique n'ont pas besoin d'implémenter un BackupAgent. Toutefois, si vous le souhaitez, vous pouvez implémenter un BackupAgent personnalisé. En général, deux raisons peuvent expliquer cela:

  • Vous souhaitez recevoir des notifications d'événements de sauvegarde, tels que onRestoreFinished() et onQuotaExceeded(long, long). Ces méthodes de rappel sont exécutées même si l'application n'est pas en cours d'exécution.

  • Vous ne parvenez pas à exprimer facilement l'ensemble des fichiers à sauvegarder à l'aide de règles XML. Dans ces rares cas, vous pouvez implémenter un BackupAgent qui remplace onFullBackup(FullBackupDataOutput) pour stocker ce que vous souhaitez. Pour conserver l'implémentation par défaut du système, appelez la méthode correspondante sur la super-classe avec super.onFullBackup().

Si vous implémentez un BackupAgent, le système s'attend par défaut à ce que votre application effectue une sauvegarde et une restauration clé-valeur. Si vous préférez utiliser la sauvegarde automatique basée sur les fichiers, définissez l'attribut android:fullBackupOnly sur true dans le fichier manifeste de votre application.

Lors des opérations de sauvegarde automatique et de restauration, le système lance l'application en mode restreint pour empêcher l'application d'accéder aux fichiers susceptibles de provoquer des conflits et pour autoriser l'application à exécuter des méthodes de rappel dans son BackupAgent. Dans ce mode restreint, l'activité principale de l'application n'est pas automatiquement lancée, ses fournisseurs de contenu ne sont pas initialisés et la classe de base Application est instanciée au lieu de toute sous-classe déclarée dans le fichier manifeste de l'application.

Votre BackupAgent doit implémenter les méthodes abstraites onBackup() et onRestore(), qui sont utilisées pour la sauvegarde clé-valeur. Si vous ne souhaitez pas effectuer de sauvegarde clé-valeur, vous pouvez simplement laisser l'implémentation de ces méthodes vide.

Pour en savoir plus, consultez la section Étendre BackupAgent.