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

アプリの自動バックアップでは、Android 6.0(API レベル 23)以降を対象とし、その上で実行されているアプリからユーザーのデータを自動的にバックアップします。Android では、アプリのデータをユーザーの Google ドライブにアップロードすることによって保持します。Google ドライブでは、ユーザーの Google アカウントの認証情報によってデータが保護されます。データの量はアプリのユーザー 1 人あたり 25 MB に制限されており、バックアップ データは無料で保存することができます。また、アプリでのバックアップ プロセスのカスタマイズや、バックアップの無効化によるオプトアウトが行えます。

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

また、自動バックアップの設定方法については、Android の自動バックアップ コードラボをご覧ください。

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

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

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

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

注: Android では、コンポーネントの設定をユーザーデータとして扱いません。アプリの実行中にそのマニフェスト内の特定のコンポーネントをアプリで有効または無効にしても、自動バックアップではその設定の保存と復元は行われません。設定の状態を保持するには、共有の環境設定に保存して、復元時に共有の環境設定を復元します。アプリで設定の状態を保存する場合は、共有の環境設定に状態を保存して、復元時に共有の環境設定を復元します。

バックアップの場所

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

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

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

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

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

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

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

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

自動バックアップ中は、ファイル システムへの書き込みが行われないようにするために、システムによってアプリがシャットダウンされます。デフォルトでは、バックアップ システムはフォアグラウンドで実行されているアプリを無視します(アプリがシャットダウンされたことにユーザーが気づくため)。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 に設定します。アプリがその状態を他のなんらかのメカニズムによって再現できる場合や、Android でバックアップすべきでない機密情報をアプリで扱っている場合は、このように設定することをおすすめします。

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

デフォルトでは、ほぼすべてのアプリデータがシステムによってバックアップされます。詳しくは、バックアップ対象のファイルをご覧ください。このセクションでは、バックアップ対象のファイルを制御するカスタムの XML ルールの定義方法について説明します。

  1. AndroidManifest.xml で、android:fullBackupContent 属性を <application> 要素に追加します。この属性で、バックアップ ルールを格納する XML ファイルを指定します。次に例を示します。
        <application ...
            android:fullBackupContent="@xml/my_backup_rules">
        </application>
        
  2. my_backup_rules.xml という 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>
        

構成ファイルの XML 構文

構成ファイルの XML 構文を以下に示します。

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

<full-backup-content> タグ内で、<include> 要素と <exclude> 要素を定義できます。

  • <include> - バックアップするファイルまたはフォルダを指定します。デフォルトでは、ほぼすべてのアプリファイルが自動バックアップの対象に含まれています。<include> 要素を指定すると、デフォルトではどのファイルもバックアップの対象に含まれなくなり、指定したファイルだけがバックアップされるようになります。複数のファイルをバックアップの対象に含めるには、複数の <include> 要素を使用します。

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

  • <exclude> - バックアップ時に除外するファイルまたはフォルダを指定します。通常、以下のファイルはバックアップから除外します。
    • デバイス固有の ID(サーバーから発行された、またはデバイスで生成された ID)が指定されているファイル。たとえば、Google クラウド メッセージング(GCM)では、ユーザーがアプリを新しいデバイスにインストールするたびに登録トークンを生成する必要があります。古い登録トークンが復元されると、アプリが予想外の動作をすることがあります。
    • アカウントの認証情報やその他の機密情報。こうした情報をバックアップに保存できるようにするのではなく、復元したアプリを初めて起動するときにユーザーに再認証を求めることを検討してください。
    • アプリのデバッグに関連するファイル。
    • アプリの 25 MB のバックアップ容量を超えるサイズの大きいファイル。

注: 構成ファイルで両方の要素を指定すると、<include> 要素で指定した内容から <exclude> 要素で指定したリソースを除いたすべてがバックアップされます。つまり、<exclude> が優先されます。

各要素には以下の 2 つの属性を含める必要があります。

  • domain - リソースの場所を指定します。この属性の有効な値は以下のとおりです。
    • rootroot - このアプリに属するすべてのプライベート ファイルが保存される、ファイル システム上のディレクトリ。
    • file - getFilesDir() が返すディレクトリ。
    • database - getDatabasePath() が返すディレクトリ。 SQLiteOpenHelper で作成されたデータベースはここに格納されます。
    • sharedpref - SharedPreferences が格納されるディレクトリ。
    • external - getExternalFilesDir() が返すディレクトリ。
  • 注: 上記以外の場所にあるファイルはバックアップできません。

  • path: バックアップの対象に含める、または対象から除外するファイルまたはフォルダを指定します。以下の点に注意してください。
    • この属性は、ワイルドカードや正規表現の構文をサポートしていません。
    • . を使用して現ディレクトリを参照できますが、セキュリティ上の理由から親ディレクトリ .. を参照することはできません。
    • ディレクトリを指定すると、そのディレクトリ内のすべてのファイルと再帰的サブディレクトリにルールが適用されます。

include 要素に requiredFlags 属性を含めることもできます。詳しくは、バックアップに必要なデバイスの条件を定義するをご覧ください。

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

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

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

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

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

my_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 MyCustomBackupAgent : 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 MyCustomBackupAgent 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.
    }
    

BackupAgent を実装する

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

  • バックアップ イベント(onRestoreFinished()onQuotaExceeded(long, long) など)の通知を受け取りたい場合。これらのコールバック メソッドは、アプリが実行されていない場合でも実行されます。
  • XML ルールでは、バックアップするファイルセットを簡単に表現できない場合。このようなレアケースでは、BackupAgent の実装で、目的のファイルを保存するように onFullBackup(FullBackupDataOutput) を上書きします。システムのデフォルトの実装を保持するには、スーパークラスで super.onFullBackup() を使用して対応するメソッドを呼び出します。

BackupAgent を実装すると、システムはデフォルトで、アプリが Key-Value 形式のバックアップと復元を実行することを期待します。代わりにファイルベースの自動バックアップを使用するには、アプリケーション マニフェスト内の android:fullBackupOnly 属性を true に設定します。

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

注意: エラーを回避するために、制限付きモードで実行するアプリの機能(主に BackupAgent)が、同じアプリ内のコンテンツ プロバイダにアクセスしたり、Application オブジェクトをキャストしたりしないようにしてください。 これができない場合は、Key-Value 形式のバックアップを実装するか、バックアップ全体を無効にすることを検討してください。

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

詳しくは、BackupAgent の拡張をご覧ください。

参考情報

自動バックアップについて詳しくは、次のリソースをご覧ください。

コードラボ