[Android]INSTALL_FAILED_DUPLICATE_PERMISSIONでインストールできない場合の原因と対策

先日、独自のカスタムパーミッションを使用するアプリを開発していた時に見事にこの現象にハマったので対策方法をメモっておく。

検索しても意外と日本語の情報がなかったので誰かの参考になれば幸いです。

スポンサーリンク

Android5.0でINSTALL_FAILED_DUPLICATE_PERMISSION

まず最初に、この現象はAndroid5.0以降でしか起こらず、Android4.4(Kitkat)以前だと
全く同じ設定でも発生しない。

このエラーが発生する原因は、別々の開発者によって同一の名前で独自パーミッションが定義された場合、後からインストールしようとしたアプリはインストールさせないという制限がAndroid5.0から追加されたからである。

つまり、名前が同一の独自パーミッションαをマニフェストに定義しているアプリAとアプリBがあった場合、lolipop以降の端末ではアプリAをインストールしてからアプリBをインストールしようとした場合、INSTALL_FAILED_DUPLICATE_PERMISSIONのエラーが出てアプリBのインストールに失敗する。

同様に、アプリBをインストールしてからアプリAをインストールしようとしてもアプリAのインストールに失敗する。

この動作はKitkatからLolipopで変更された点で、よく調べてみるとリファレンスにもしっかり書いてある。

Uniqueness Requirement for Custom Permissions

〜略〜

Android 5.0 includes a behavior change to ensure that only one app can define a given custom permission, unless signed with the same key as other apps defining the permission.

〜略〜

Starting in Android 5.0, the system enforces a new uniqueness restriction on custom permissions for apps that are signed with different keys. Now only one app on a device can define a given custom permission (as determined by its name), unless the other app defining the permission is signed with the same key. If the user tries to install an app with a duplicate custom permission and is not signed with the same key as the resident app that defines the permission, the system blocks the installation.

https://developer.android.com/about/versions/android-5.0-changes.html#custom_permissions

上記の太字箇所に記載されている通り、Lolipop以降では別々の署名でビルドされたアプリで同一名称のパーミッションが定義されていた場合、後からインストールしようとしたアプリはインストールできないという仕様が追加された。

こんな現象は自分一人で開発しているとなかなか気が付かず、アプリをリリースしてから初めて発覚する類のもので、しかもアプリのインストールすらできないという最悪の結果をもたらすが、あまり広くは知られていないようである(そもそも独自パーミッションを必要とするもの自体がそんなにないけど)。

独自パーミッションの定義が同一になる場合

別々のアプリで独自パーミッションの定義が同一になるケースというのはあまりないが、実際に発生しそうな事例もリファレンスに記載されている。

Apps using duplicate custom permissions

Any app can define any custom permission it wants, so it can happen that multiple apps might define the same custom permission. For example, if two apps offer a similar capability, they might derive the same logical name for their custom permissions. Apps might also incorporate common public libraries or code examples that themselves include the same custom permission definitions.

https://developer.android.com/about/versions/android-5.0-changes.html#custom_permissions

上記の引用では独自パーミッション定義がカブる可能性について以下の3つが指摘されている。

  1. 似たような機能を持っている場合
  2. 独自パーミッションを定義するライブラリを使用する場合
  3. 独自パーミッションを定義しているサンプルコードを使用する場合

1についてはおそらくあまり気にする必要はないと思われる。
というのも、基本的にはパーミッション名はアプリパッケージ名のリバースドメイン方式で定義することがほとんどだと思われるので、全く別々の開発者がたまたま同一のパーミッションを定義してしまう可能性はおそらく非常に低いと考えられるからである。

2はかなり危ういケースで、実際に大きな問題が発生するとしたらこの場合なんじゃなかろうか。
自分は独自パーミッションを定義してるライブラリは知らないが、実際にこのケースで問題が発生した場合、使用するライブラリを変更するかライブラリをカスタマイズする必要が出てくるので影響範囲が大きそうである。

実際に一番起こりやすいのが3のケースである。検索して出てくるのはほとんどこのケースで、Google公式のGCMのサンプルで独自パーミッションが定義されているため、このサンプルコードをそのまま使っているアプリが5.0からインストールできなくなったという相談がstackoverflowに数多く挙げられている。

この場合は原因さえ知っていれば対策は簡単で、独自パーミッションの定義値を自分のアプリのパッケージ名のリバースドメイン方式等に変更すればいいだけである。
参考:http://stackoverflow.com/questions/27043933/install-failed-duplicate-permission-c2d-message

おまけ:なぜ独自パーミッションがカブると駄目なのか

最後に、なぜ4.4以前はOKだったのに5.0以降でこのようなインストール制限が追加されたのかについて補足しておく。

Android の OS は、カスタムパーミッションをその名前で追跡します。一度パーミッションが定義されると、他のアプリケーションはそれを変更できません。例えば、有名なアプリケーション「A」が、そのデータを保護するために、「permission-A」というパーミッションを signature の保護レベルで定義したとします。しかしユーザは、A をインストールする前に、不正なアプリケーション「B」をインストールしていました。もし、B が正規のアプリケーション A から情報を収集するよう設計されていたら、A よりも前に、B が permission-A を作成し、B には permission-A の許可が与えられます。アプリケーションA がインストールされると、B はアプリケーションA の保護されたデータを読み込む許可を得ます。

Androidのカスタムパーミッションで顧客情報流出のおそれ

上記はトレンドマイクロセキュリティブログからの引用であるが、要するに先にパーミッション名を押さえてしまえば後から同一の名前のパーミッションを持つアプリに対して、任意のデータを取得することができるからということである。

まぁ、要するにただのセキュリティホールだったわけです。それが5.0で対策された、と。

中国の商標登録ビジネスみたいな感じ?ですね。