Cómo crear una Copia de seguridad automática para los datos del usuario

La función Copia de seguridad automática para apps realiza copias de seguridad de los datos del usuario de las apps que se orientan a Android 6.0 (nivel de API 23) y se ejecutan en esa versión o en otras posteriores. Android conserva los datos de app subiéndolos en la unidad de Google Drive del usuario, donde están protegidos por las credenciales de su Cuenta de Google. La copia de seguridad se encripta de extremo a extremo en dispositivos con Android 9 o versiones posteriores mediante el PIN, el patrón o la contraseña del dispositivo. La cantidad de datos está limitada a 25 MB por usuario. No se cobra por almacenar datos de copia de seguridad. Tu app puede personalizar el proceso de copia de seguridad u optar por inhabilitarlo.

Para obtener una descripción general de las opciones de copia de seguridad de Android y orientación sobre qué datos incluir en una copia de seguridad y restablecimiento, consulta la descripción general de la copia de seguridad de datos.

Archivos con copia de seguridad

De forma predeterminada, la Copia de seguridad automática incluye archivos en la mayoría de los directorios que el sistema asigna a tu app:

La copia de seguridad automática excluye archivos en los directorios que muestran getCacheDir(), getCodeCacheDir() y getNoBackupFilesDir(). Los archivos guardados en estas ubicaciones solo se necesitan temporalmente y se excluyen de las operaciones de copia de seguridad de manera intencional.

Puedes configurar tu app para incluir y excluir archivos particulares. Para obtener más información, consulta la sección Cómo incluir y excluir archivos.

Ubicación de las copias de seguridad

Los datos de copia de seguridad se almacenan en una carpeta privada en el servicio de Google Drive del usuario, limitada a 25 MB por app. Los datos guardados no inciden en la cuota personal de Google Drive del usuario. Solo se almacena la copia de seguridad más reciente. Cuando se crea una copia de seguridad, se borra cualquier copia anterior. El usuario ni otras apps del dispositivo pueden leer los datos de la copia de seguridad.

Los usuarios pueden ver una lista de apps con copia de seguridad en la app de Google Drive para Android. En un dispositivo con Android, los usuarios pueden encontrar esta lista en el panel lateral de navegación de la app de Drive en Configuración > Crear copia de seguridad y restablecer.

Las copias de seguridad de cada conjunto de dispositivo, configuración y ciclo de vida se almacenan en conjuntos de datos por separado, como se describe en los siguientes ejemplos:

  • Si el usuario posee dos dispositivos, existe un conjunto de datos de copia de seguridad para cada uno.

  • Si el usuario restablece la configuración de fábrica de un dispositivo y, luego, lo configura con la misma cuenta, la copia de seguridad se almacena en un nuevo conjunto de datos. Los conjuntos de datos obsoletos se borran automáticamente después de un período de inactividad.

Cronograma de copia de seguridad

Las copias de seguridad se crean automáticamente cuando se cumplen todas estas condiciones:

  • El usuario habilitó la copia de seguridad en el dispositivo. En Android 9, esta configuración se encuentra en Configuración > Sistema > Copia de seguridad.
  • Transcurrieron al menos 24 horas desde la última copia de seguridad.
  • El dispositivo está inactivo.
  • El dispositivo está conectado a una red Wi-Fi (si el usuario del dispositivo no aceptó las copias de seguridad de datos móviles).

En la práctica, estas condiciones ocurren casi todas las noches, pero es posible que un dispositivo nunca cree una copia de seguridad (por ejemplo, si nunca se conecta a una red). Para conservar el ancho de banda de la red, la carga se realiza solo si cambian los datos de la app.

Durante la copia de seguridad automática, el sistema cierra la app para asegurarse de que ya no esté escribiendo en el sistema de archivos. De forma predeterminada, el sistema de copia de seguridad ignora las apps que se ejecutan en primer plano para evitar una experiencia del usuario deficiente. Puedes anular el comportamiento predeterminado configurando el atributo android:backupInForeground como verdadero.

Para simplificar las pruebas, Android incluye herramientas que te permiten iniciar una copia de seguridad de tu app de forma manual. Para obtener más información, consulta Cómo probar copias de seguridad y restablecimientos.

Cómo restablecer el programa

Los datos se restablecen cada vez que se instala la app, ya sea desde Play Store, durante la configuración del dispositivo (cuando el sistema instala apps instaladas previamente) o cuando se ejecuta la instalación de adb. La operación de restablecimiento ocurre después de instalar el APK, pero antes de que la app esté disponible para que el usuario la inicie.

Durante el asistente de configuración inicial del dispositivo, se muestra al usuario una lista de conjuntos de datos de copia de seguridad disponibles y se le pregunta de cuál desea restablecer datos. El conjunto de datos de copia de seguridad seleccionado se convierte en el conjunto de datos principal del dispositivo. El dispositivo se puede restablecer desde sus propias copias de seguridad o desde el conjunto de datos principal. Si las copias de seguridad de ambas fuentes están disponibles, el dispositivo prioriza la propia. Si el usuario no usó el asistente de configuración del dispositivo, solo podrá restablecerlo desde sus propias copias de seguridad.

Para simplificar las pruebas, Android incluye herramientas que te permiten iniciar un restablecimiento de tu app de forma manual. Para obtener más información, consulta Cómo probar copias de seguridad y restablecimientos.

Cómo habilitar e inhabilitar una copia de seguridad

Las apps que se segmentan a Android 6.0 (nivel de API 23) o versiones posteriores crean, de forma predeterminada, una copia de seguridad automática. En tu archivo de manifiesto de la app, configura el valor booleano android:allowBackup para habilitar o inhabilitar la copia de seguridad. El valor predeterminado es true, pero te recomendamos que configures de forma explícita el atributo en tu manifiesto, como se muestra en el siguiente ejemplo:

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

Puedes inhabilitar las copias de seguridad configurando android:allowBackup como false. Te recomendamos que lo hagas si tu app puede recrear su estado a través de algún otro mecanismo o si procesa información sensible.

Cómo incluir y excluir archivos

De forma predeterminada, el sistema crea copias de seguridad de casi todos los datos de apps. Para obtener más información, consulta la sección sobre archivos con copia de seguridad.

En esta sección, se muestra cómo definir reglas XML personalizadas para controlar el contenido que se incluye en una copia de seguridad. Si tu app se orienta a Android 12 (nivel de API 31) o versiones posteriores, debes especificar un conjunto adicional de reglas de copias de seguridad en formato XML, como se describe en esta sección, para admitir los cambios en el restablecimiento de copias de seguridad que se introdujeron en los dispositivos que ejecutan estas versiones de Android.

Cómo controlar las copias de seguridad en Android 11 y versiones anteriores

Sigue los pasos que se indican en esta sección para controlar de qué archivos se crea una copia de seguridad en dispositivos con Android 11 (nivel de API 30) o versiones anteriores.

  1. En el archivo AndroidManifest.xml, agrega el atributo android:fullBackupContent al elemento <application>, como se muestra en el siguiente ejemplo. Este atributo apunta a un archivo en formato XML que contiene reglas de copias de seguridad.

    <application ...
     android:fullBackupContent="@xml/backup_rules">
    </application>
    
  2. Crea un archivo en formato XML llamado @xml/backup_rules en el directorio res/xml/. En ese archivo, agrega reglas con los elementos <include> y <exclude>. En el siguiente ejemplo, se crea una copia de seguridad de todas las preferencias compartidas, excepto 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>
    

Cómo definir las condiciones del dispositivo necesarias para la copia de seguridad

Si tu app guarda información sensible en el dispositivo, puedes especificar las condiciones en las que se incluyen sus datos en la copia de seguridad del usuario. Puedes agregar las siguientes condiciones en Android 9 (nivel de API 28) o versiones posteriores:

Si actualizaste tus dispositivos de desarrollo a Android 9, debes inhabilitar y volver a habilitar la copia de seguridad de datos después de la actualización. Eso se debe a que Android solo encripta las copias de seguridad con un secreto del cliente después de informar a los usuarios en Configuración o en el asistente de configuración.

Para declarar las condiciones de inclusión, configura el atributo requireFlags con uno o más valores elegidos en los elementos <include> dentro de tu conjunto de reglas de copias de seguridad:

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 tu app implementa un sistema de copia de seguridad de clave-valor o si implementas BackupAgent por tu cuenta, también puedes aplicar estos requisitos condicionales a la lógica de copia de seguridad mediante una comparación a nivel de bits entre el conjunto de marcas de transporte de un objeto BackupDataOutput y las marcas FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED o FLAG_DEVICE_TO_DEVICE_TRANSFER de tu agente de copias de seguridad personalizadas.

En el siguiente fragmento de código, se muestra un ejemplo de uso de este método:

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.
}

Cómo controlar las copias de seguridad en Android 12 o versiones posteriores

Si la app se orienta a Android 12 (nivel de API 31) o versiones posteriores, sigue los pasos que se indican en esta sección para controlar de qué archivos se crea una copia de seguridad en dispositivos que ejecutan Android 12 o versiones posteriores.

  1. En el archivo AndroidManifest.xml, agrega el atributo android:dataExtractionRules al elemento <application>, como se muestra en el siguiente ejemplo. Este atributo apunta a un archivo en formato XML que contiene reglas de copias de seguridad.

    <application ...
     android:dataExtractionRules="backup_rules.xml">
    </application>
    
  2. Crea un archivo en formato XML llamado backup_rules.xml en el directorio res/xml/. En ese archivo, agrega reglas con los elementos <include> y <exclude>. En el siguiente ejemplo, se crea una copia de seguridad de todas las preferencias compartidas, excepto 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>
    

Sintaxis de la configuración XML

La sintaxis XML para el archivo de configuración varía según la versión de Android en la que se ejecuta la app y a la que se orienta.

Android 11 o versiones anteriores

Usa la siguiente sintaxis XML para el archivo de configuración que controla la copia de seguridad de los dispositivos que ejecutan Android 11 o versiones anteriores.

<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 o versiones posteriores

Si la app se orienta a Android 12 (nivel de API 31) o versiones posteriores, usa la siguiente sintaxis XML para el archivo de configuración que controla la copia de seguridad de los dispositivos que ejecutan Android 12 o versiones posteriores.

<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>

Cada sección de la configuración (<cloud-backup>, <device-transfer>) incluye reglas que se aplican solo a ese tipo de transferencia. Por ejemplo, esta separación te permite excluir un archivo o directorio de las copias de seguridad en Google Drive mientras todavía lo estás transfiriendo durante transferencias de un dispositivo a otro (D2D). Esto es útil si tienes archivos que son demasiado grandes para crear una copia de seguridad en la nube, pero que se pueden transferir entre dispositivos sin problemas.

Si no hay reglas para un modo de copia de seguridad en particular, como si faltara la sección <device-transfer>, ese modo se habilita por completo para todo el contenido, excepto los directorios no-backup y cache, como se describe en la sección Archivos con copia de seguridad.

La app puede configurar la marca disableIfNoEncryptionCapabilities en la sección <cloud-backup> para asegurarse de que la copia de seguridad se cree solo si se puede encriptar, por ejemplo, cuando el usuario tiene una pantalla de bloqueo. Si estableces esta restricción, se evita que las copias de seguridad se envíen a la nube si el dispositivo del usuario no es compatible con la encriptación. Sin embargo, como las transferencias de D2D no se envían al servidor, seguirán funcionando incluso en dispositivos que no admiten la encriptación.

Sintaxis para incluir y excluir elementos

Dentro de las etiquetas <full-backup-content>, <cloud-backup> y <device-transfer> (según la versión de Android del dispositivo y targetSDKVersion de la app), puedes definir los elementos <include> y <exclude>:

<include>

Especifica un archivo o una carpeta que necesita copia de seguridad. De forma predeterminada, la Copia de seguridad automática incluye casi todos los archivos de la app. Si especificas un elemento <include>, el sistema ya no incluye ningún archivo de forma predeterminada y crea una copia de seguridad solo de los archivos especificados. Para incluir varios archivos, usa varios elementos <include>.

En Android 11 y versiones anteriores, este elemento también puede contener el atributo requireFlags, que se analiza en más detalle en la sección que describe cómo definir requisitos condicionales para la copia de seguridad.

Los archivos de los directorios que muestran getCacheDir(), getCodeCacheDir() o getNoBackupFilesDir() siempre se excluyen, incluso si intentas incluirlos.

<exclude>

Especifica un archivo o una carpeta para excluir durante la copia de seguridad. Estos son algunos archivos que, por lo general, se excluyen de la copia de seguridad:

  • Archivos que tienen identificadores específicos del dispositivo, emitidos por un servidor o generados en el dispositivo. Por ejemplo, Firebase Cloud Messaging (FCM) necesita generar un token de registro cada vez que un usuario instala tu app en un dispositivo nuevo. Si se restablece el token de registro anterior, es posible que la app se comporte de forma inesperada.

  • Archivos relacionados con la depuración de app

  • Archivos grandes que hacen que la app exceda la cuota de copia de seguridad de 25 MB.

Cada elemento <include> y <exclude> debe incluir los siguientes dos atributos:

domain

Especifica la ubicación del recurso. Los valores válidos para este atributo incluyen lo siguiente:

  • root: Es el directorio del sistema de archivos donde se almacenan todos los archivos privados que pertenecen a esta app.
  • file: Los directorios que muestra getFilesDir().
  • database: Los directorios que muestra getDatabasePath(). Las bases de datos creadas con SQLiteOpenHelper se almacenan aquí.
  • sharedpref: Es el directorio en el que se almacena SharedPreferences.
  • external: El directorio que muestra getExternalFilesDir().
  • device_root: Es similar a root, pero para el almacenamiento protegido por el dispositivo.
  • device_file: Es similar a file, pero para el almacenamiento protegido por el dispositivo.
  • device_database: Es similar a database, pero para el almacenamiento protegido por el dispositivo.
  • device_sharedpref: Es similar a sharedpref, pero para el almacenamiento protegido por el dispositivo.
path

Especifica un archivo o una carpeta para incluir o excluir de la copia de seguridad. Ten en cuenta lo siguiente:

  • Este atributo no admite comodines ni sintaxis de expresiones regulares.
  • Puedes hacer referencia al directorio actual con ./, pero no puedes hacer referencia al directorio superior, como .., por motivos de seguridad.
  • Si especificas un directorio, la regla se aplicará a todos los archivos del directorio y los subdirectorios recursivos.

Cómo implementar BackupAgent

Las apps que implementan la Copia de seguridad automática no necesitan implementar un BackupAgent. Sin embargo, de forma opcional, puedes implementar un BackupAgent personalizado. Por lo general, existen dos motivos para hacer esto:

  • Deseas recibir notificaciones de eventos de copia de seguridad, como onRestoreFinished() y onQuotaExceeded(long, long). Esos métodos de devolución de llamada ocurren incluso si la app no se está ejecutando.

  • No puedes expresar fácilmente el conjunto de archivos para los que quieres crear una copia de seguridad con reglas XML. En esos casos poco frecuentes, puedes implementar un BackupAgent que anule a onFullBackup(FullBackupDataOutput) para almacenar lo que deseas. Para retener la implementación predeterminada del sistema, llama al método correspondiente en la superclase con super.onFullBackup().

Si implementas BackupAgent, el sistema, de forma predeterminada, espera que tu app cree una copia de seguridad de clave-valor y un restablecimiento. Si, en cambio, deseas utilizar la Copia de seguridad automática basada en archivos, configura el atributo android:fullBackupOnly como true en el manifiesto de tu app.

Durante las operaciones de copia de seguridad automática y restablecimiento, el sistema inicia la app en modo restringido para evitar que acceda a archivos que podrían causar conflictos y permitir que ejecute métodos de devolución de llamada en su BackupAgent. En este modo restringido, la actividad principal de la app no se inicia automáticamente, no se inicializan sus proveedores de contenido y se crea una instancia de Application de la clase base en lugar de cualquier subclase declarada en el manifiesto de la app.

Tu BackupAgent debe implementar los métodos abstractos onBackup() y onRestore(), que se usan para la copia de seguridad de clave-valor. Si no deseas crear una copia de seguridad de los pares clave-valor, puedes dejar en blanco la implementación de esos métodos.

Para obtener más información, consulta Cómo extender BackupAgent.