Android P で APK を pm install する方法
デバッグ時にアプリを Android 端末にインストールしたい事は多々あると思います。
その際に実行するコマンドは大抵 adb install
だと思いますが、プロジェクトによっては pm install
をしなければならないことがあります。具体的には、インストール元のアプリを偽装したいときです。
アプリによっては、インストール元のアプリをチェックし、 Google PlayStore アプリ以外からインストールした場合は処理を変えるといった機能を実装することがあります。
デバッグ時に、実際に Google PlayStore からインストールするわけにはいかないので、以下のようなコマンドでインストール元アプリを Google PlayStore アプリに偽装することができます。
adb push XXX.apk /sdcard/XXX.apk adb shell pm install -i "com.android.vending" /sdcard/XXX.apk
しかし、 Android P から実行できなくなってしまいました…
$ adb shell pm install -i "com.android.vending" -r /sdcard/XXX.apk avc: denied { read } for scontext=u:r:system_server:s0 tcontext=u:object_r:sdcardfs:s0 tclass=file permissive=0 System server has no access to read file context u:object_r:sdcardfs:s0 (from path /sdcard/XXX.apk, context u:r:system_server:s0) Error: Unable to open file: /sdcard/XXX.apk Consider using a file under /data/local/tmp/ Error: Can't open file: /sdcard/XXX.apk Exception occurred while executing: java.lang.IllegalArgumentException: Error: Can't open file: /sdcard/XXX.apk at com.android.server.pm.PackageManagerShellCommand.setParamsSize(PackageManagerShellCommand.java:328) at com.android.server.pm.PackageManagerShellCommand.runInstall(PackageManagerShellCommand.java:906) at com.android.server.pm.PackageManagerShellCommand.onCommand(PackageManagerShellCommand.java:158) at android.os.ShellCommand.exec(ShellCommand.java:103) at com.android.server.pm.PackageManagerService.onShellCommand(PackageManagerService.java:21357) at android.os.Binder.shellCommand(Binder.java:634) at android.os.Binder.onTransact(Binder.java:532) at android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:2821) at com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:3866) at android.os.Binder.execTransact(Binder.java:731)
これエラーがめちゃくちゃ分かりにくいんですがよくよく読むとファイルを /data/local/tmp/
の下に置いてみるのはどうですか? っていわれているので、そのようにやってみます。
adb push XXX.apk /data/local/tmp/XXX.apk adb shell pm install -i "com.android.vending" /data/local/tmp/XXX.apk
すると、以下のような表示になり、インストールが成功します。めでたしめでたし。
Success
この件について以下の issue tracker でこの話がされているのだけど、そもそも pm install
では /data/local/tmp/
以外から APK をインストールすることは想定していない (いままでが何故か動いていた) と言う感じで、これは仕様なのだそうです。
ちなみに pm install
コマンド自体は deprecated になっていて、 cmd package install
というコマンドが Android 8.0 くらいから推奨されているらしい (別に pm install
コマンドは動くのでこのままで良いけれど) 。さらに言うと cmd package install
を使ったところで /data/local/tmp/
以外にある APK をインストールすようとすると同じエラーがでてしまいます。