ゲームのデータを最新のAndroidへ移行したい!!!

昔やってたあるゲームを最新のAndroidでもデータ引き継いで使いたい!ということで、そのゲームにはそもそもデータの以降手段が用意されていないので、有名なadb backup/restoreを使ってAndroid 5のデータをAndroid 14に移行しようとしたのですができなかったのでどうしたかをメモで書き連ねます

以下ではゲームのパッケージ名はgame.no.package.nameとします。なんのゲームかは察してください

かなり殴り書きなのは許してください。

そもそも今まではどうやっていたか

そもそも、前述のように、今回のゲームにはデータの以降手段が用意されていないので、adb backup/restoreを使ってデータを移行するしかありませんでした。

  1. ADBがあらかじめ使えるようにしておきましょう(検索すればやりかたはいっぱい出てきます)
  2. 移行元デバイスをPCに接続します
  3. adb backup game.no.package.name をします
  4. 実行したフォルダにbackup.abができます
  5. 移行先のデバイスでそのゲームをPlayストアでインストールしておきます
  6. 移行先のデバイスをPCに接続します
  7. adb restore backup.ab をします

adb backup/restoreが使えるだけありがたかったのですが、移行先がAndroid 14だったからか、復元が完了しました、と出るのにアプリのデータが0のままで何かがうまくいっていない

調べてみる

ネットでいろいろ調べてみますが決定的な情報が全く出てこない
  • 新しいAndroidから古いAndroidに移行するときにはabファイルのバージョンが古くなるので、android-backup-extractorを使ってリパックしてやるとよい→今回は違う
  • Android 12から、adb backupはrootでないとできないらしい→今はbackupはうまくいっているらしいけどrestoreができてない
というわけで決定的な情報が全く出てこない

いろいろ試してみる

  • もしかしたら、インストールされているゲームのバージョンが、移行元と移行先で一致していないからエラーになるのかな?というわけで同じバージョンでそろえてやってみましたが、何も状況が変わらない
  • もしかしたら、移行先で仕事用プロフィールを使っていたせいか?とデータをバックアップしたうえで仕事用プロフィールを削除してやり直してみたが、何も状況が変わらない
  • もしかしたら、Android5からのデータだから問題だったのではないか?と、エミュレータを使ってAndroid 7に移行してみて(アプリをインストールしたうえでadb restore)、これは成功したのでここからさらにadb backupでAndroid7から新しくabファイルを抜いて、それをAndroid 14でadb restoreしてみるも、何も状況が変わらない
logcatでログを見た限りだと、
Restore manifest from but allowBackup=false
とでていました
ですがAndroidManifest.xmlをデコードしてもallowBackupなんてどこにも定義されていないんですよね
ここでこのメッセージが表示されていて、この前は
mPackageManager.getPackageInfo().applicationInfo.flags
のフラグを計算しているようですが
さすがにmPackageManager.getPackageInfoの中身まで見ると大変なので辞めました

というわけで諦めて他の手段を模索します

buコマンドを試す

adb backup/restore以外でデータを移行する方法がないかを調べてみました。
adb shellのなかで使えるbuというバイナリはadb backupとadb restoreと同じような挙動をするらしいので、adb pushでabファイルを/data/local/tmpに突っ込んでadb shellでbu restore backup.abをしてみたのですが、今度はこれが永遠に終わらない

というわけで別の手段を考えることにしました

また別の手段を模索する

buコマンドを調べている中でbmgrコマンドというものを見つけました
こっちもadb shellのなかで使えるコマンドで、Androidに搭載されているバックアップ機能をデバッグ目的で操作できるもののようです。
Android 5のadb shellでbmgrを呼び出そうとしたら、なぜかなにも反応がなかったので、さきほど使ったエミュにまずadb restoreでデータを復元したうえで、adb shellからbmgr backupnow game.no.package.nameを実行して即時バックアップをトリガーしてみました
しかしこれもだめでしたQuota Exceededと表示されました。
どうやらAndroidのバックアップ機能には容量制限があるようです。
公式のドキュメントによると、25MBまでらしいです。
この時点でそのゲームのデータは130MB程度あったので110MB程度削る必要があるようです
ここでandroid-backup-extractorの出番です
PCでbackup.abを手順に沿ってアンパックして、tarを展開して、ファイルディレクトリの容量分布をみてみると、apps/game.no.package.name/f/WebApiManagerというフォルダが容量の多くを占めているようです。これを消してもまだ25MBちょっとあったので、apps/game.no.package.name/fの中にある、ゲームの中に登場する動物()たちの写真を全部消しました
この状態でtarコマンドでファイルをまとめて(ちゃんとファイルの順番が正しくないとAndroidに認識してもらえないので、android-backup-extractorのREADMEを参照してちゃんとコマンドからたばねてください)、android-backup-extractorでパックしてデータを用意します
このデータを使ってエミュめがけてadb restoreしてやります
エミュ上でアプリは無事起動できました
ここでもう一度adb shellに入って、bmgr backupnow game.no.package.nameを実行したらうまくいきました
いままではLocalTransportにバックアップしていたので、Googleアカウントにバックアップしてみます。bmgr list transportsでGoogleアカウントへのTransportをたしかめ、bmgr transport <トランスポート名>でトランスポートを変更します
さらに、バックアップさきのGoogleアカウントを設定するため、Activity Launcherを使ってGoogle Play開発者サービスのなかにあるバックアップの設定を開き、適当なアカウントをバックアップ先に設定してやります。
そしたらbmgr backupnow game.no.package.nameを実行します
でもだめでした。こんどはTransport rejected packageとlogcatに出てきて全然ダメでした

最終手段

しかたないので最終手段です
ゲームのAPKをもってきて、デバッグをオンにしたうえで再コンパイルして、オレオレ証明書を使って署名して実機にインストールして、adb shellでrun-as パッケージ名 でパッケージとしてシェルを開き、データをfilesに直接移動するしかありません。
というわけでこれやったらできました
やりかたをざっと解説すると
  • apkpureかなんかでapkをとってくる
  • apktoolで逆コンパイルする
  • apktoolで-dオプションをつけてビルドする
  • Android SDKに入ってるapksignerでオレオレ証明書で署名
  • adb installでインストール
  • backup.abをandroid-backup-extractorでアンパック
  • tarを解凍
  • apps/game.no.package.name/fを/data/local/tmpにadb push
  • adb shellにはいってrun-as game.no.package.name
  • /data/local/tmpをアプリのデータフォルダーのfilesに突っ込む
アプリ内課金はできなくなるし、アップデートも毎回署名しなおさないといけないけど、とりあえずデータは移動できました
めでたしめでたし

コメント