Android Backup Service は、Android アプリ内の Key-Value データについて、クラウド ストレージによるバックアップと復元を提供します。Key-Value バックアップの操作時、アプリのバックアップ データはデバイスのバックアップ トランスポートに渡されます。デバイスがデフォルトの Google Backup Transport を使用している場合、データは Android Backup Service に渡されてアーカイブされます。
データは、アプリのユーザーごとに 5 MB に制限されます。バックアップ データは無料で保存できます。
Android のバックアップ オプションの概要と、バックアップおよび復元する必要があるデータに関するガイダンスについては、データのバックアップの概要をご覧ください。
Key-Value バックアップを実装する
アプリデータをバックアップするには、バックアップ エージェントを実装する必要があります。バックアップ エージェントは、バックアップと復元の両方でバックアップ マネージャーによって呼び出されます。
バックアップ エージェントを実装するには、以下を行う必要があります。
マニフェスト ファイルで
android:backupAgent
属性を使用してバックアップ エージェントを宣言する。次のいずれかの方法でバックアップ エージェントを定義する。
-
BackupAgent
クラスは、アプリがバックアップ マネージャーとの通信に使用する中央インターフェースを提供します。このクラスを直接拡張する場合、onBackup()
とonRestore()
をオーバーライドしてデータのバックアップと復元のオペレーションを処理する必要があります。 -
BackupAgentHelper
クラスは、BackupAgent
クラスを中心とした便利なラッパーを提供し、記述する必要があるコードの量を最小限に抑えます。BackupAgentHelper
では、onBackup()
とonRestore()
を実装する必要がないように、特定の種類のデータを自動的にバックアップおよび復元する 1 つ以上のヘルパー オブジェクトを使用する必要があります。アプリのバックアップを完全に制御する必要がない場合は、BackupAgentHelper
を使用してアプリのバックアップを処理することをおすすめします。現在、Android は
SharedPreferences
と内部ストレージからファイル一式をバックアップして復元するバックアップ ヘルパーを提供しています。
-
マニフェストでバックアップ エージェントを宣言する
バックアップ エージェントのクラス名を決定したら、マニフェストで <application>
タグ内の android:backupAgent
属性を使用して宣言します。
例:
<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>
古いデバイスをサポートする場合は、API キー <meta-data>
を Android マニフェスト ファイルに追加することをおすすめします。Android Backup Service ではサービスキーが不要になりましたが、一部の古いデバイスでは、まだバックアップ時にキーが確認されることがあります。android:name
を com.google.android.backup.api_key
に設定し、android:value
を unused
に設定します。
android:restoreAnyVersion
属性は、バックアップ データを生成したバージョンと比較した現在のアプリのバージョンにかかわらず、アプリデータを復元するかどうかを示すブール値を取得します。デフォルト値は false
です。詳細については、復元データのバージョンを確認するをご覧ください。
BackupAgentHelper を拡張する
ファイル一式を(SharedPreferences
または内部ストレージから)バックアップする場合、BackupAgentHelper
を使用してバックアップ エージェントをビルドする必要があります。BackupAgentHelper
を使用してバックアップ エージェントをビルドする場合、onBackup()
と onRestore()
を実装する必要がないため、BackupAgent
を拡張するよりもはるかに少ないコードで済みます。
BackupAgentHelper
を実装する場合、バックアップ ヘルパーを 1 つ以上使用する必要があります。バックアップ ヘルパーは、BackupAgentHelper
が特定の種類のデータのバックアップおよび復元処理を実行するために呼び出す特殊なコンポーネントです。Android フレームワークでは現在、以下の 2 つのヘルパーが提供されています。
SharedPreferences
をバックアップするSharedPreferencesBackupHelper
。- 内部ストレージからファイルをバックアップする
FileBackupHelper
。
BackupAgentHelper
に複数のヘルパーを含めることができますが、各データタイプに必要なヘルパーは 1 つのみです。つまり、複数の SharedPreferences
ファイルがある場合、必要となるのは SharedPreferencesBackupHelper
1 つだけです。
BackupAgentHelper
に追加するヘルパーごとに、onCreate()
メソッドで次の処理を行う必要があります。
- 目的のヘルパークラスのインスタンスをインスタンス化する。クラス コンストラクタに、バックアップするファイルを指定する必要があります。
addHelper()
を呼び出してBackupAgentHelper
にヘルパーを追加する。
以下のセクションでは、使用可能な各ヘルパーを使用してバックアップ エージェントを作成する方法について説明します。
SharedPreferences をバックアップする
SharedPreferencesBackupHelper
をインスタンス化するときは、1 つ以上の SharedPreferences
ファイルの名前を含める必要があります。
たとえば、user_preferences
という名の SharedPreferences
ファイルをバックアップする場合、BackupAgentHelper
を使用する完全なバックアップ エージェントは次のようになります。
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); } }
SharedPreferencesBackupHelper
には SharedPreferences
ファイルのバックアップと復元に必要なコードがすべて含まれています。
バックアップ マネージャーが onBackup()
と onRestore()
を呼び出すと、BackupAgentHelper
がバックアップ ヘルパーを呼び出して指定したファイルのバックアップと復元を行います。
他のファイルをバックアップする
FileBackupHelper
をインスタンス化するときは、openFileOutput()
がファイルを書き込む場所と同じ getFilesDir()
で指定されているとおり、アプリの内部ストレージに保存されている 1 つ以上のファイルの名前を含める必要があります。
たとえば、scores
と stats
という名前の 2 つのファイルをバックアップする場合、BackupAgentHelper
を使用するバックアップ エージェントは次のようになります。
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
には、アプリの内部ストレージに保存されているファイルをバックアップおよび復元するために必要なすべてのコードが含まれています。
しかし、内部ストレージ上のファイルの読み書きはスレッドセーフではありません。バックアップ エージェントがアクティビティと同時にファイルを読み書きしないようにするには、読み取りや書き込みを実行するたびに同期ステートメントを使用する必要があります。たとえば、ファイルを読み書きするアクティビティの場合、同期ステートメントの組み込みロックとして使用するオブジェクトが必要です。
Kotlin
// Object for intrinsic lock companion object { val sDataLock = Any() }
Java
// Object for intrinsic lock static final Object sDataLock = new Object();
次に、ファイルを読み書きするたびに、このロックを使用して同期ステートメントを作成します。たとえば、ゲームの最新スコアをファイルに書き込むための同期ステートメントは次のとおりです。
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"); }
同じロックを使用して読み取りステートメントを同期する必要があります。
次に、BackupAgentHelper
で onBackup()
と onRestore()
をオーバーライドし、同じ組み込みロックを使用してバックアップと復元の処理を同期します。たとえば、上の MyFileBackupAgent
の例には次のメソッドが必要です。
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); } }
BackupAgent を拡張する
ほとんどのアプリでは、BackupAgent
クラスを直接拡張する必要はありませんが、代わりに BackupAgentHelper
を拡張して、ファイルを自動的にバックアップおよび復元する組み込みヘルパークラスを利用する必要があります。ただし、次のようにすることで、BackupAgent
を直接拡張できます。
- データ形式をバージョニングする。たとえば、アプリデータの書式を変更する必要がある場合、バックアップ エージェントをビルドして復元処理時にアプリのバージョンをクロスチェックし、デバイスのバージョンがバックアップ データと異なる場合に互換性を保つうえで必要な作業を行います。詳細については、復元データのバージョンを確認するをご覧ください。
- バックアップするデータの部分を指定する。ファイル全体をバックアップする代わりに、バックアップするデータの部分と各部分のデバイスへの復元方法を指定できます。これは、ファイル一式ではなく、一意のエンティティとしてデータを読み書きするため、さまざまなバージョンの管理にも役立ちます。
- データベースのデータをバックアップする。ユーザーがアプリを再インストールしたときに復元する SQLite データベースがある場合、バックアップ処理中に適切なデータを読み取るカスタム
BackupAgent
をビルドし、復元処理中にテーブルを作成してデータを挿入する必要があります。
上記のいずれかのタスクを実行する必要がなく、SharedPreferences
または内部ストレージからファイル一式をバックアップしたい場合は、BackupAgentHelper
を拡張するをご覧ください。
必須メソッド
BackupAgent
の作成時に、以下のコールバック メソッドを実装する必要があります。
onBackup()
- バックアップをリクエストすると、バックアップ マネージャーがこのメソッドを呼び出します。このメソッドでは、デバイスからアプリデータを読み取り、バックアップするデータをバックアップ マネージャーに渡します。詳しくは、バックアップを実行するをご覧ください。
onRestore()
バックアップ マネージャーは、復元処理時にこのメソッドを呼び出します。このメソッドにより、バックアップ データが配信され、アプリで以前の状態を復元するために使用できます。詳しくは、復元を実行するをご覧ください。
ユーザーがアプリを再インストールすると、システムはこのメソッドを呼び出してバックアップ データを復元しますが、アプリで復元をリクエストすることもできます。
バックアップを実行する
バックアップ リクエストによって onBackup()
メソッドがすぐに呼び出されるわけではありません。バックアップ マネージャーは適切な時間だけ待機し、最後にバックアップが実行された時点以降にバックアップをリクエストしたすべてのアプリについてバックアップを実行します。この時点でクラウド ストレージに保存できるように、バックアップ マネージャーにアプリデータを渡す必要があります。
バックアップ マネージャーのみがバックアップ エージェントの onBackup()
メソッドを呼び出すことができます。アプリデータが変更され、バックアップを実行するたびに、dataChanged()
を呼び出してバックアップ処理をリクエストする必要があります。詳細については、バックアップをリクエストするをご覧ください。
ヒント: アプリの開発中に、bmgr
ツールを使用して、バックアップ マネージャーからすぐにバックアップ処理を開始できます。
バックアップ マネージャーは onBackup()
メソッドを呼び出す際、次の 3 つのパラメータを渡します。
oldState
- アプリが提供する最後のバックアップ状態を指す、オープンな、読み取り専用の
ParcelFileDescriptor
。これは、クラウド ストレージからのバックアップ データではなく、newState
によって、またはonRestore()
で定義されているように、onBackup()
が前回呼び出されたときにバックアップされたデータのローカル表現です。onRestore()
については次のセクションで説明します。onBackup()
はクラウド ストレージ内の既存のバックアップ データを読み取ることができないため、このローカル表現を使用して、前回のバックアップ以降にデータが変更されたかどうかを判別します。 data
BackupDataOutput
オブジェクト。バックアップ マネージャーにバックアップ データを渡すために使用します。newState
data
に配信したデータの表現を書き込む必要があるファイルを指している、オープンで、読み書き可能なParcelFileDescriptor
。表現は、ファイルの最終変更タイムスタンプと同じくらいシンプルにできます。このオブジェクトは、次回バックアップ マネージャーがonBackup()
メソッドを呼び出すときにoldState
として返されます。バックアップ データをnewState
に書き込まない場合、oldState
はバックアップ マネージャーが次回onBackup()
を呼び出すときに空のファイルを指します。
これらのパラメータを使用して、onBackup()
メソッドを実装して以下を行います。
oldState
と現在のデータを比較して、最後のバックアップ以降にデータが変更されたかどうかを確認します。oldState
でデータを読み取る方法は、newState
に最初に書き込んだ方法によって異なります(ステップ 3 を参照)。ファイルの状態を記録する最も簡単な方法は、最後に変更されたタイムスタンプを使用することです。oldState
からタイムスタンプを読み取って比較する方法の例を以下に示します。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 }
何も変更されておらず、バックアップする必要がない場合は、ステップ 3 に進みます。
oldState
と比較してデータが変更されている場合、現在のデータをdata
に書き込んで、クラウド ストレージにバックアップします。BackupDataOutput
にデータの各チャンクをエンティティとして書き込む必要があります。エンティティは、一意のキー文字列で識別されるフラット化されたバイナリデータ レコードです。したがって、バックアップするデータセットは、概念的には Key-Value ペアのセットになります。エンティティをバックアップ データセットに追加するには:
writeEntityHeader()
を呼び出して、書き込むデータの一意の文字列キーとデータサイズを渡します。writeEntityData()
を呼び出して、データを含むバイトバッファとバッファから書き込むバイト数(writeEntityHeader()
に渡されるサイズと一致する必要があります)を渡します。
次のコードは、一部のデータをバイト ストリームに変換し、1 つのエンティティに書き込む例を示します。
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);
これは、バックアップするデータごとに実行します。データをエンティティに分割する方法は自由に決めることができます。エンティティを 1 つだけ使用することもできます。
バックアップ(ステップ 2)を実行するかどうかにかかわらず、現在のデータの表現を
newState
ParcelFileDescriptor
に書き込みます。バックアップ マネージャーは、このオブジェクトを、現在バックアップされているデータの表現としてローカルで保持します。次にonBackup()
を呼び出すときに、これをoldState
として返します。これにより、別のバックアップが必要かどうかを判断できます(ステップ 1 で処理)。現在のデータ状態をこのファイルに書き込まない場合、次のコールバック中にoldState
は空になります。次の例では、ファイルの最終変更タイムスタンプを使用して、現在のデータの表現を
newState
ファイルに保存します。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);
復元を実行する
アプリデータを復元するときは、バックアップ マネージャーがバックアップ エージェントの onRestore()
メソッドを呼び出します。このメソッドを呼び出すと、バックアップ マネージャーによりバックアップ データが提供され、デバイスに復元できます。
バックアップ マネージャーのみが onRestore()
を呼び出すことができます。この呼び出しは、アプリがインストールされ、既存のバックアップ データが検出されたときに自動的に行われます。
バックアップ マネージャーは onRestore()
メソッドを呼び出す際、次の 3 つのパラメータを渡します。
data
BackupDataInput
オブジェクト。これにより、バックアップ データを読み取ることができます。appVersionCode
- アプリの
android:versionCode
マニフェスト属性の値を表す整数。バックアップ時と同じデータになります。これを使用して、現在のアプリのバージョンをクロスチェックし、データ形式に互換性があるかどうかを判断できます。異なるバージョンの復元データを処理する方法については、復元データのバージョンを確認するをご覧ください。 newState
- オープンされている、読み書き可能な
ParcelFileDescriptor
。data
で提供された最終的なバックアップ状態を書き込む必要のあるファイルを指します。このオブジェクトは、次回onBackup()
が呼び出されたときにoldState
として返されます。また、onBackup()
コールバックで同じnewState
オブジェクトを書き込む必要があります。書き込むことで、onBackup()
に指定されたoldState
オブジェクトは、デバイスの復元後に初めてonBackup()
が呼び出された場合でも有効になります。
onRestore()
の実装で、data
に対して readNextHeader()
を呼び出して、データセット内のすべてのエンティティを反復処理する必要があります。検出されたエンティティごとに、以下を行います。
getKey()
を使用してエンティティ キーを取得する。エンティティ キーを、
BackupAgent
クラス内で静的な最終文字列として宣言する必要がある既知の Key-Value リストと比較します。キーが既知のキー文字列のいずれかと一致したら、ステートメントを入力してエンティティ データを抽出し、デバイスに保存します。getDataSize()
を使用してエンティティ データのサイズを取得し、そのサイズのバイト配列を作成します。readEntityData()
を呼び出して、データの格納先となるバイト配列を渡し、開始オフセットと読み取るサイズを指定します。- バイト配列がいっぱいになりました。自由にデータを読み取って、デバイスに書き込みます。
データを読み取り、デバイスに書き戻した後、
onBackup()
のときと同じように、データの状態をnewState
パラメータに書き込みます。
前のセクションの例でバックアップされたデータを復元する方法を以下に示します。
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); }
この例では、onRestore()
に渡される appVersionCode
パラメータは使用されません。ただし、ユーザーのアプリのバージョンが実際にダウングレードしたとき(ユーザーがアプリのバージョンを 1.5 から 1.0 に移行した場合など)に、バックアップを実行するように選択した場合に使用できます。詳細については、次のセクションをご覧ください。
復元データのバージョンを確認する
バックアップ マネージャーは、データをクラウド ストレージに保存する際、マニフェスト ファイルの android:versionCode
属性で定義されているとおり、自動的にアプリのバージョンを含めます。バックアップ マネージャーは、バックアップ エージェントを呼び出してデータを復元する前に、インストールされているアプリの android:versionCode
を確認し、復元データセットに記録されている値と比較します。復元データセットに記録されたバージョンがデバイス上のアプリのバージョンよりも新しい場合、ユーザーはアプリをダウングレードしています。この場合、バックアップ マネージャーはアプリの復元処理を中止し、onRestore()
メソッドを呼び出しません。これは、復元セットが古いバージョンにとって意味がないと見なされるためです。
android:restoreAnyVersion
属性を使用すると、この動作をオーバーライドできます。この属性を true
に設定して、復元セット バージョンにかかわらずアプリを復元することを示します。デフォルト値は false
です。これを true
に設定した場合、バックアップ マネージャーは android:versionCode
を無視し、すべての場合で onRestore()
メソッドを呼び出します。そうすることにより、onRestore()
メソッドでバージョンの違いを手動で確認し、バージョンが一致しない場合にデータの互換性を保つために必要な手順を踏むことができます。
復元処理時にさまざまなバージョンを処理できるように、onRestore()
メソッドは、復元データセットに含まれているバージョン コードを appVersionCode
パラメータとして渡します。これで、PackageInfo.versionCode
フィールドを使用して、現在のアプリのバージョン コードに対してクエリを行うことができます。次に例を示します。
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; }
次に、PackageInfo
から取得した version
を onRestore()
に渡された appVersionCode
と比較します。
バックアップをリクエストする
dataChanged()
を呼び出して、いつでもバックアップ処理をリクエストできます。このメソッドは、バックアップ エージェントを使用してデータをバックアップすることをバックアップ マネージャーに通知します。その後、ある時点で、バックアップ エージェントの onBackup()
メソッドが呼び出されます。通常、データが変更されるたびに(バックアップするアプリの設定を変更した場合など)、バックアップをリクエストする必要があります。バックアップ マネージャーがエージェントからのバックアップをリクエストする前に dataChanged()
を数回呼び出した場合も、エージェントは onBackup()
の呼び出しを 1 回だけ受け取ります。
復元をリクエストする
アプリの通常使用中は、復元処理をリクエストする必要はありません。バックアップ データが自動的にチェックされ、アプリのインストール時に復元が実行されます。
自動バックアップに移行する
アプリをフルデータ バックアップに移行するには、マニフェスト ファイルの <application>
要素で android:fullBackupOnly
を true
に設定します。Android 5.1(API レベル 22)以前のデバイスでは、マニフェストのこの値は無視され、Key-Value のバックアップが続行されます。デバイスで Android 6.0(API レベル 23)以降を実行している場合、Key-Value バックアップの代わりに自動バックアップがアプリで実行されます。
ユーザーのプライバシー
Google は、ユーザーの皆様からお寄せいただいている信頼と、ユーザーの皆様のプライバシーを保護する責任を深く認識しています。Google はバックアップと復元の機能を提供するために Google サーバーとの間でバックアップ データを安全に送信します。Google のプライバシー ポリシーに沿って、上記データは個人情報として扱われます。
また、Android システムのバックアップ設定でデータのバックアップ機能を無効にすることもできます。ユーザーがバックアップを無効にすると、Android Backup Service は保存したバックアップ データをすべて削除します。デバイスのバックアップは再び有効にできますが、Android Backup Service が以前に削除したデータは復元されません。