自動バックアップでユーザーデータをバックアップする

「アプリの自動バックアップ」を使用すると、Android 6.0(API レベル 23)以降をターゲットとして実行するアプリから、ユーザーのデータを自動的にバックアップできます。Android では、アプリのデータをユーザーの Google ドライブにアップロードすることによって保持します。Google ドライブでは、ユーザーの Google アカウントの認証情報によってデータを保護します。Android 9 以降を搭載したデバイスでのバックアップは、デバイスの PIN、パターン、またはパスワードを使用してエンドツーエンドで暗号化されます。すべてのアプリは、アプリのユーザーごとに最大 25 MB のバックアップ データを割り当てることができます。バックアップ データは追加料金なしで保存できます。アプリでは、バックアップ プロセスをカスタマイズすることも、バックアップを無効にしてバックアップを無効にすることもできます。

Android のバックアップ オプションの概要と、バックアップおよび復元する必要があるデータに関するガイダンスについては、データのバックアップの概要をご覧ください。

バックアップ対象のファイル

デフォルトでは、自動バックアップの対象には、システムによってアプリに割り当てられているほとんどのディレクトリ内のファイルが含まれています。

自動バックアップでは、getCacheDir()getCodeCacheDir()getNoBackupFilesDir() から返されるディレクトリ内のファイルは除外されます。これらの場所に保存されているファイルは、一時的に必要なファイルで、バックアップ処理から意図的に除外されています。

アプリを設定して、特定のファイルを追加、除外できます。詳しくは、ファイルを追加または除外するをご覧ください。

バックアップの場所

バックアップ データは、ユーザーの Google ドライブ アカウントのプライベート フォルダに保存されます。容量はアプリ 1 つあたり 25 MB に制限されています。保存されたデータは、ユーザー個人の Google ドライブの容量にカウントされません。保存されるのは最新のバックアップのみです。バックアップが作成されると、以前のバックアップはすべて削除されます。ユーザーやデバイス上の他のアプリがバックアップ データを読み取ることはできません。

ユーザーは、Google ドライブの Android アプリでバックアップされたアプリの一覧を確認できます。アプリの一覧は、Google ドライブアプリのナビゲーション ドロワー([設定] > [バックアップとリセット])で確認できます。

以下の例に示すように、バックアップは、デバイス、設定、有効期間ごとに別々のデータセットに保存されます。

  • ユーザーが 2 台のデバイスを所有している場合は、各デバイス用のバックアップ データセットが存在します。

  • ユーザーがデバイスを出荷時の設定にリセットしてから、同じアカウントでデバイスをセットアップすると、バックアップは新しいデータセットに保存されます。古いデータセットは、アクセスされない状態が一定期間続くと自動的に削除されます。

バックアップ スケジュール

以下の条件をすべて満たしている場合、バックアップが自動的に行われます。

  • ユーザーによってデバイスでバックアップが有効化されている。Android 9 では、この設定は [設定] > [システム] > [バックアップ] にあります。
  • 前回のバックアップから少なくとも 24 時間経過している。
  • デバイスがアイドル状態である。
  • デバイスが Wi-Fi ネットワークに接続されている(デバイスのユーザーがモバイルデータのバックアップを有効にしていない場合)。

実際には、これらの条件はほぼ毎晩満たされますが、デバイスでバックアップが行われない可能性もあります(デバイスがネットワークにまったく接続されない場合など)。ネットワーク帯域幅を節約するため、アップロードはアプリデータが変更された場合にのみ行われます。

自動バックアップ中は、ファイル システムへの書き込みが行われないようにするために、システムによってアプリがシャットダウンされます。デフォルトでは、ユーザー エクスペリエンスの低下を防ぐため、バックアップ システムはフォアグラウンドで実行されているアプリを無視します。android:backupInForeground 属性を true に設定すると、このデフォルトの動作をオーバーライドできます。

簡単にバックアップをテストできるように、Android にはアプリのバックアップを手動で開始するためのツールが用意されています。詳しくは、バックアップと復元のテストをご覧ください。

復元スケジュール

データの復元は、アプリのインストール時に毎回行われます。アプリのインストールは Play ストアから行うか、デバイスのセットアップ時(以前にインストールしたアプリをシステムがインストールする場合)か、adb install の実行によって行います。復元処理は、APK のインストール後、ユーザーがアプリを起動できるようになる前に行われます。

最初のデバイス設定ウィザードで、利用可能なバックアップ データセットのリストがユーザーに表示され、どのデータセットからデータを復元するかを尋ねられます。選択したバックアップ データセットがデバイスの祖先データセットになります。デバイスは、自身のバックアップまたは祖先データセットから復元できます。両方のソースからのバックアップが利用可能な場合、デバイスは自身のバックアップを優先します。ユーザーがデバイス設定ウィザードを実行しなかった場合、デバイスは自身のバックアップからの復元のみを行えます。

簡単に復元をテストできるように、Android にはアプリの復元を手動で開始するためのツールが用意されています。詳しくは、バックアップと復元のテストをご覧ください。

バックアップを有効または無効にする

Android 6.0(API レベル 23)以上をターゲットとするアプリでは、自動的に自動バックアップが有効になります。バックアップを有効または無効にするには、アプリのマニフェスト ファイルでブール値 android:allowBackup を設定します。デフォルト値は true ですが、次の例に示すように、マニフェストで属性を明示的に設定することをおすすめします。

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

バックアップを無効にするには、android:allowBackupfalse に設定します。アプリがその状態を他のなんらかのメカニズムによって再現できる場合や、機密情報をアプリで扱っている場合は、このように設定することをおすすめします。

ファイルを追加または除外する

デフォルトでは、ほぼすべてのアプリデータがシステムによってバックアップされます。詳しくは、バックアップ対象のファイルのセクションをご覧ください。

このセクションでは、バックアップ対象のファイルを制御するカスタム XML ルールの定義方法について説明します。Android 12(API レベル 31)以降をターゲットとするアプリの場合、これらの Android バージョンを搭載するデバイスに導入されたバックアップと復元の変更点に対応するため、このセクションで説明するように、XML バックアップ ルールの追加セットを指定する必要があります。

Android 11 以下でバックアップを管理する

Android 11(API レベル 30)以下を搭載したデバイスでバックアップ対象のファイルを制御するには、このセクションの手順を行います。

  1. 次の例に示すように、AndroidManifest.xml ファイルで、android:fullBackupContent 属性を <application> 要素に追加します。この属性は、バックアップ ルールを含む XML ファイルを指します。

    <application ...
     android:fullBackupContent="@xml/backup_rules">
    </application>
    
  2. @xml/backup_rules という XML ファイルを res/xml/ ディレクトリ内に作成します。このファイルで、<include> 要素と <exclude> 要素を使用したルールを追加します。次のサンプルでは、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>
    

バックアップに必要なデバイスの条件を定義する

アプリがデバイスに機密情報を保存する場合、アプリのデータがユーザーのバックアップに含まれる条件を指定できます。Android 9(API レベル 28)以降では、以下の条件を追加できます。

  • clientSideEncryption: ユーザーのバックアップがクライアント側のシークレットで暗号化される。ユーザーが Android 9 以降でバックアップを有効化し、デバイスに画面ロック(PIN、パターン、パスワードのいずれか)を設定していれば、Android 9 以降を搭載したデバイスではこの形式の暗号化が有効になります。
  • deviceToDeviceTransfer: ユーザーが、デバイス間のローカル転送をサポートしている別のデバイス(Google Pixel など)にバックアップを転送する。

開発デバイスを Android 9 にアップグレードした場合、アップグレード後にデータのバックアップを無効にしてから再度有効にする必要があります。なぜならば、Android がクライアント側のシークレットを使用してバックアップを暗号化するには、事前に [設定] または設定ウィザードでユーザーに通知する必要があるからです。

バックアップ対象の条件を宣言するには、一連のバックアップ ルール内の <include> 要素で requireFlags 属性を選択した値に設定します。

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>

アプリでKey-Value バックアップ システムを実装している場合や、自分で BackupAgent を実装している場合は、BackupDataOutput オブジェクトのトランスポートのフラグセットとカスタム バックアップ エージェントの FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED フラグまたは FLAG_DEVICE_TO_DEVICE_TRANSFER フラグをビット単位で比較することで、これらの条件付き要件をバックアップ ロジックに適用することもできます。

次のコード スニペットは、この方法の使用例を示しています。

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

Android 12 以上でバックアップを管理する

アプリが Android 12(API レベル 31)以上をターゲットにしている場合、Android 12 以上を搭載したデバイスでバックアップ対象のファイルを追加または削除するには、このセクションの手順を行います。

  1. 次の例に示すように、AndroidManifest.xml ファイルで、android:dataExtractionRules 属性を <application> 要素に追加します。この属性で、バックアップ ルールを格納する XML ファイルを指定します。

    <application ...
     android:dataExtractionRules="backup_rules.xml">
    </application>
    
  2. backup_rules.xml という XML ファイルを res/xml/ ディレクトリ内に作成します。このファイルで、<include> 要素と <exclude> 要素を使用したルールを追加します。次のサンプルでは、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>
    

構成ファイルの XML 構文

構成ファイルの XML 構文は、アプリがターゲットとし実行する Android のバージョンによって異なります。

Android 11 以下

Android 11 以下を搭載したデバイスのバックアップを制御する構成ファイルには、次の XML 構文を使用します。

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

アプリが Android 12(API レベル 31)以上をターゲットにしている場合、Android 12 以上を搭載したデバイスのバックアップを制御する構成ファイルには次の XML 構文を使用します。

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

構成の各セクション(<cloud-backup><device-transfer>)には、そのタイプの転送にしか適用されないルールが含まれます。このように分けることで、たとえば、あるファイルやディレクトリを Google ドライブのバックアップから除外しつつ、デバイス間(D2D)転送には含めるといったことが可能になります。これは、クラウドにバックアップするには大きすぎるがデバイス間での転送は問題なくできるファイルがある場合に便利です。

<device-transfer> セクションがないなど、特定のバックアップ モードに関するルールがない場合、バックアップ対象のファイル セクションに記載されているように、no-backup ディレクトリと cache ディレクトリを除くすべてのコンテンツに対して、そのモードが完全に有効になります。

アプリでは、<cloud-backup> セクションに disableIfNoEncryptionCapabilities フラグを設定することで、ユーザーがロック画面を表示した場合など、暗号化可能な場合にのみバックアップが行われるようにできます。この制約を設定すると、ユーザーのデバイスが暗号化をサポートしていない場合、バックアップはクラウドに送信されなくなりますが、D2D 転送はサーバーに送信されないため、暗号化をサポートしていないデバイスでも動作し続けます。

要素の追加と除外の構文

<full-backup-content> タグ、<cloud-backup> タグ、<device-transfer> タグ(デバイスの Android バージョンとアプリの targetSDKVersion によって異なります)内で、<include> 要素と <exclude> 要素を次のように定義します。

<include>

バックアップするファイルまたはフォルダを指定します。デフォルトでは、ほぼすべてのアプリファイルが自動バックアップの対象に含まれています。<include> 要素を指定すると、システムはデフォルトでファイルを含めず、指定されたファイルのみをバックアップします。複数のファイルを含めるには、複数の <include> 要素を使用します。

Android 11 以下では、この要素に requireFlags 属性を含めることもできます。この属性について詳しくは、バックアップに必要なデバイスの条件を定義する方法についてのセクションをご覧ください。

getCacheDir()getCodeCacheDir()getNoBackupFilesDir() から返されたディレクトリ内のファイルは、対象に含めようとしても必ず除外されます。

<exclude>

バックアップ時に除外するファイルまたはフォルダを指定します。通常、以下のファイルはバックアップから除外します。

  • デバイス固有の ID(サーバーにより発行された ID またはデバイスで生成された ID)が指定されているファイル。たとえば、Firebase Cloud Messaging(FCM)では、ユーザーがアプリを新しいデバイスにインストールするたびに登録トークンを生成する必要があります。古い登録トークンが復元されると、アプリが予期しない動作をする可能性があります。

  • アプリのデバッグに関連するファイル。

  • アプリの 25 MB のバックアップ容量を超えるサイズの大きいファイル。

<include> 要素と <exclude> 要素にはそれぞれ、以下の 2 つの属性を含める必要があります。

domain

リソースの場所を指定します。この属性の有効な値は以下のとおりです。

  • root: このアプリに属するすべてのプライベート ファイルが保存される、ファイル システム上のディレクトリ。
  • file: getFilesDir() が返すディレクトリ。
  • database: getDatabasePath() が返すディレクトリ。SQLiteOpenHelper で作成されたデータベースはここに格納されます。
  • sharedpref: SharedPreferences が格納されるディレクトリ。
  • external: getExternalFilesDir() が返すディレクトリ。
  • device_root: root に似ていますが、デバイス保護ストレージに使用します。
  • device_file: file に似ていますが、デバイス保護ストレージに使用します。
  • device_database: database に似ていますが、デバイス保護ストレージに使用します。
  • device_sharedpref: sharedpref に似ていますが、デバイス保護ストレージに使用します。
path

バックアップの対象に含める、または対象から除外するファイルまたはフォルダを指定します。次の点に注意してください。

  • この属性は、ワイルドカードや正規表現の構文をサポートしていません。
  • ./ を使用して現ディレクトリを参照できますが、セキュリティ上の理由から、.. などを使用して、親ディレクトリを参照することはできません。
  • ディレクトリを指定すると、そのディレクトリ内のすべてのファイルと再帰的サブディレクトリにルールが適用されます。

BackupAgent を実装する

自動バックアップを実装するアプリでは、BackupAgent を実装する必要はありません。ただし、必要に応じてカスタムの BackupAgent を実装できます。通常、以下のような場合に BackupAgent を実装します。

  • バックアップ イベント(onRestoreFinished()onQuotaExceeded(long, long) など)の通知を受け取りたい場合。これらのコールバック メソッドは、アプリが実行されていない場合でも実行されます。

  • XML ルールでは、バックアップするファイルセットを簡単に表現できない場合。このようなレアケースでは、onFullBackup(FullBackupDataOutput) をオーバーライドする BackupAgent を実装し、目的のファイルを保存します。システムのデフォルトの実装を保持するには、スーパークラスで super.onFullBackup() を使用して対応するメソッドを呼び出します。

デフォルトでは、BackupAgent を実装すると、アプリが Key-Value ペアのバックアップと復元を行うものと想定されます。代わりにファイルベースの自動バックアップを使用するには、アプリのマニフェストで android:fullBackupOnly 属性を true に設定します。

自動バックアップおよび復元処理が行われている間、システムはアプリを制限付きモードで起動して、競合を引き起こす可能性があるファイルにアプリがアクセスしないようにするとともに、アプリが BackupAgent でコールバック メソッドを実行できるようにします。この制限付きモードでは、アプリのメイン アクティビティは自動的に開始されず、コンテンツ プロバイダは初期化されません。また、アプリのマニフェストで宣言されたサブクラスではなく、基本クラス Application がインスタンス化されます。

BackupAgent には、Key-Value バックアップで使用される抽象メソッド onBackup() および onRestore() を実装する必要があります。Key-Value バックアップを実行しない場合は、これらのメソッドの実装を空のままにしておくことができます。

詳細については、BackupAgent を拡張するをご覧ください。