UnityにおけるAndroidアプリのパーミッション付与について

# 1.はじめに
先日Googleのポリシー変更が行われ、既存のリリースアプリで個人情報読み取り機能を使用するアプリに対し、
下記の遵守を求めるように各デベロッパーへの通知を行いました。
(1)HPでのセキュリティポリシーの掲載
(2)アプリ内でのセキュリティポリシーの掲載

上記は、不正なアプリを排除する狙いがあると思われますが、個人開発者にとっては、
「何のことかよく分かっていないけど、該当パーミッションを削除する対応を行う形で対処した」
という話を何件か聞きました。
対処としては間違っていませんが、そもそもパーミッションって何なの？という疑問が残ったままで
終わってしまっている状況がまずいと思い、分かる範囲で説明する事が出来ればと思ったのが今回の投稿の経緯です。
今回は概要に留めており、Android 6.0以降のパーミッション付与のハンドリング実装については触れておりません。
対象者は個人でUnityを使いAndroid向けにアプリを開発している方を想定しています。


# 2.Permissonとは
AndroidアプリにおけるPermissonとは許可の意味合い通り、
アプリで使用する機能についての許可のことを指します。
センサー、ネットワーク、ハードウェア機能を利用する際にユーザーに対し、
使用機能を明示する事で、ユーザーはどのような機能がアプリに備わっているか知ることが出来ると言った具合です。
歴史的な経緯で言うと、Android 2.xの頃は、GooglePlay(当時はAndroidMarketでしたが…）のアプリページの下の方にあるリンクから
記載されている事を確認できるのと、設定画面でアプリ情報を見た時に確認できる程度でした。
その後、Android 4.xではインストール前に危険なパーミッション（後述）を使用しているアプリのインストール前に
警告を表示する仕組みが導入されましたが、ユーザーが意図的に特定のパーミッションを許可することは出来ませんでした。
その後、Android 6.0以降でアプリインストール後、危険なパーミッションに該当する機能に始めてアクセスした際に
確認ダイアログが表示され、機能をブロックするかどうかをユーザー側で制御できるようになりました。
詳細については参考リンク(1)で挙げさせて頂いた記事を参照頂ければと思います。


# 3.危険なパーミッション
パーミッションはNormalパーミッション、Dangerousパーミッションの2つが定義されています。
https://developer.android.com/guide/topics/security/permissions.html?hl=ja#perm-groups

先述した危険なパーミッションはDangerousパーミッションの事を指します。
各パーミッションの特徴は下記のようになります。

・Normalパーミッション
ユーザーの個人情報には影響を及ぼさない程度のアクセス権限を持つもの、
システムの動作に影響を及ぼさない程度のものが存在し、システム側で権限が自動的に付与される

・Dangerousパーミッション
ユーザーの個人情報にアクセスが可能なもの、システム動作に影響を与え、
他のアプリの誤動作の原因になるような操作が可能なものが存在し、6.0以降ではユーザーに使用の際に確認が行われる
詳細については参考リンク(2)で挙げさせて頂いた記事を参照頂ければと思います。


# 4.Unityにおけるパーミッション
既に分かりやすい解説をされた記事がありましたので、
参考リンク(3)として挙げさせていただきます。

私なりに改めて説明させていただきますと、Unityにおけるパーミッションの付与条件は
いくつか存在し、新規のプロジェクトを作った状態でも数件付与されますが、
後述するバグを含んだバージョンを使用しない限りは
パーミッションを何も付けないアプリを作ることも可能となります。

パーミッションが付与される条件は下記のとおりです。

(1)C#スクリプトによる特定関数呼び出し
(2)プラグインフォルダのAndroidManifest.xml置き換え
(3)ビルド設定
(4)Unityのバグ

各項目について、簡単に説明していきます。
#### (1)C#スクリプトによる特定関数呼び出し
一番簡単な例ですとwwwが挙げられます。
ネットワーク機能を使ってるので、考えれば当たり前のような気もするのですが、
StreamingAssetsのローカルストレージアクセスを行わない場合でも付与されます。

注意点として、必ずしもC#スクリプトファイルとして存在していない可能性があることです。
実際に、外部アセットに含まれるDLL内でパーミッション付与該当関数が呼び出されていたというケースがありました。

※
Unityの関数とAndroidのパーミッションの紐付け一覧をドキュメント内から見つけることが出来ませんでした。
存在していない・・・？

#### (2)プラグインフォルダのAndroidManifest.xmlによるマージ
Unityではプラグインフォルダ（※）以下にAndroidManifest.xmlを置くことで
その記述内容を最終出力時にマージしてくれる機能があります。
前述のC#内での関数による自動付与の可能性があるため、
置き換えでは無いということに注意する必要があります。

#### (3)プレイヤー設定
『Build Settings』内の『Player Settings』に存在する下記の項目が対象です。
・Internet Access
  Autoの場合、(1)による関数呼び出しがなければ付与されない。
  Requireに設定すると強制的に付与
・Write Permission
  アプリの配置先を内部ストレージ(Internal)にするか、外部ストレージ(External)にするか設定可能。
  後者のExternalでストレージアクセス権限が必要のため付与される。

#### (4)Unityのバグ
Unityのエディタに起因するバグによって付与されるケースがありました。
対処方法としては、原則最新版のUnityを使うようにするか、
Export Projectで書き出したプロジェクトをAndroid Studioに読み込ませてAndroidManifestから
該当パーミッションを削除した上でapkをビルドする解決策があります。
ただ、後者はパーミッションに該当する機能を内部でいつ使うのか分からないため、
かなり危険な方法です。（最悪クラッシュの原因になるため）

###### (a)Unityサインインによる付与
この記事書くために検証してる中で発見したのですが、
少し前のバージョンでUnityにサインインしてると
上述の手順とは関係なく、勝手に付与される不具合が発生していました。
Offline Workにするとつかないことを確認したので、オフラインで使用するか、
修正版のUnityを使うの二択になります。
（修正確認バージョン: 5.4.5f1/5.5.3f1/5.6.0f3)

###### (b)特定バージョン使用によるバグ
本来、起こるはずないと思っていたのですが実際に起きてしまったので、経緯を説明しますと
Unity5.1よりマルチプレイヤーのネットワーク機能が追加されました。(UNETと呼ばれるものです）
その影響であると推測されますが、前述の関数の付与の有無、ビルド設定の有無に関わらずUnityから出力されるapkは
全ての条件で、ユーザー情報を取得するREAD_PHONE_STATE、ネットワーク機能を利用するINTERNETが付与されるようになりました。
READ_PHONE_STATEについてはその後のPatchで、INTERNETについては5.3のベータ版以降で修正されました。

# 5.権限の確認方法について
一番シンプルなのは、apkを端末にインストールし、設定画面から
アプリ情報を閲覧し、確認する方法です。

別の方法として、apkからAndroidManifestを抽出し、
その中に含まれる権限を読み取る方法です。
この方法ではAndroidManifestの記述内容についてある程度の理解が必要になるため、
基本推奨されませんので詳細については割愛いたしますが、
興味がある場合は「android apk manifest 確認」などで検索してみると
手順を知ることが出来ると思います。

# 6.まとめ
駆け足でしたが、UnityでAndroidアプリにおけるパーミッションについて説明してきました。
この記事が、何かのお役に立たれば幸いです。


# 7.参考リンク
.参考リンク
(1)Androidのパーミッションと6.0での処理の流れを今さら説明してみる
http://qiita.com/imaizume/items/178cb540b697cd9419fd

(2)Android 6.0からリクエストが必要なパーミッション一覧 (Dangerous Permissions) 
https://feel-log.net/android/marshmallow-permissions-runtime-request/

(3)INTERNETパーミッションが勝手につく等，UnityとAndroidManifestのよくわからないところ
http://qiita.com/RyotaMurohoshi/items/c8aa78d5db13c31da152