INTERNETパーミッションが勝手につく等，UnityとAndroidManifestのよくわからないところ

# INTERNETパーミッションが勝手につく等，UnityとAndroidManifestのよくわからないところ

ネットワークアクセスしていないUnityで開発したAndroidゲームで，INTERNETパーミッションが勝手についてしまうことがあります。([Androidのパーミッションについて (Android Developers)](http://developer.android.com/guide/topics/security/permissions.html))

その(正直いけていない)解決法を(一応)紹介します。

※ この投稿はどちらかというとネイティブプラグインやAndroidManifest関連の情報の方が多いですし，そちらがメインです。
※ 投稿内容に関する公式ドキュメントが見つかりません。ご存知の方，コメントをいただけると嬉しいです。

【重要】Unity 4.3.4時点での情報です。それより新しいバージョンでは変わっている可能性があります。注意してください。

## 困ったことに勝手にINTERNETパーミッションがつく

Unityで制作したネットワークアクセスなど何もしていないAndroidのゲームに，INTERNETのパーミッションが設定されることがあります。

原因は，どうやらWWWクラスが利用されているコードがあると，Unityの仕様により勝手にINTERNETパーミッションが付与されるからのようです。自分自身でWWWクラスのコードを書いていなくても，利用しているアセットがWWWクラスのUtilityメソッドを定義していたりすると，その箇所が原因でINTERNETパーミッションが追加されてしまうことがあります。

※「WWWクラスを利用したコードがあるとINTERNETパーミッションがついてしまう」というのに関する公式ドキュメントをみつけられていません。ご存知の方教えていただけると嬉しいです。

## すこし話はそれてAndroidのネイティブプラグイン

すこし話はそれますが，Androidのネイティブプラグインというのがあります。
ネイティブプラグインを使えば，Android用に公開されているSDKをUnityのゲームで使ったり，バイブレーションや位置情報などの端末の機能を利用することが可能です。

[公式ドキュメント](http://docs.unity3d.com/Documentation/Manual/PluginsForAndroid.html)


下記は，UnityにおけるAndroidのネイティブプラグイン作成の時に非常に参考になるページ・スライドなどです。

[Unity ネイティブプラグインの作成について (SlideShare)](http://www.slideshare.net/tatsuhikoyamamura/unity-15594873)
[Androidネイティブ開発のすすめ (Qiita)](http://qiita.com/relzx/items/a35f7ab6dbacb48f7e26)
[[Unity]iPhone/Androidでネイティブプラグインを作るコツ…みたいなもの](http://terasur.blog.fc2.com/blog-entry-520.html) 

さてUnityを用いた開発に限らず，AndroidではBluetoothやバイブレーション，位置情報などを利用する場合，それに関連するパーミッションをAndroidManifestに加える必要があります。


Unityの開発でAndroidManifestにパーミッションを加えたい場合は，『Temp/StagingAreaのAndroidManifest.xmlをコピーしてきて，該当するパーミッションをそのファイルに追加し，Assets/Plugins/AndroidにそのManifestを置けばよい。』とされています。

※『Assets/Plugins/AndroidにAndroidManifestを置けばよい』というのは，[公式ドキュメント](http://docs.unity3d.com/Documentation/Manual/PluginsForAndroid.html)に記載されているのですが，Temp/StagingAreaのAndroidManifest.xmlに関してやパーミッションの追加の方法がこれでよいというのは公式ドキュメントでは見つけられていません。ご存知の方，教えていただけると嬉しいです。

## じゃあINTERNETパーミションのないAndroidManifestをおけばいいのでは．．．

さて話をもどします。INTERNETパーミッションが勝手について困っていました。

『INTERNETパーミッションが勝手につくのであれば，Plugins/AndroidにINTERNETパーミッションがついていないAndroidManifest.xmlを置いて，それがビルド結果に反映されるようにしてしまえばいいのでは』と考えました。

1回ビルドをして，Temp/StagingArea/AndroidManifest.xmlを作ります。それをPlugins/Androidにコピーし，INTERNETパーミッションを消します。

『これでWWWクラスを使っていても，Plugins/Android/AndroidManifest.xmlの内容にパーミッションが設定されて，INTERNETパーミッションはつかないはず！』と考え，試してみました。

結果は残念ながらうまくいきませんでした。
端末にインストールし確認すると，ゲームはINTERNETパーミッションが設定されており，Temp/StagingArea/AndroidManifeset.xmlにもINTERNETパーミッションの記述があります。

各種パーミッションの追加はできてもINTERNETパーミッションの削除はできないみたいです。
そしてどうやら，単純にPlugins/Androidに置いたAndroidManifest.xmlがそのままビルド結果のapk用のAndroidManifestとして使われるようではないようです。

## じゃあどうする？

WWWクラスがコード上にあり，ネットワークアクセスをしなくても，INTERNETパーミッションが追加されてしまう問題。Plugins/AndroidにAndroidManifestを置く方法では解決できないようです。

BuildSettings -> PlayerSettings -> Androidにおいて，Internet AccessはAutoとRequireのみです。ここでForbiddenなどの項目があればそれで解決なのですが，無いのでどうしようもありません。コード内にWWWクラスが存在する場合，INTERNETパーミッションがどうしてもついてしまいます。


解決策は二つあると思います。
ですが，どちらも問題があります。
正直どちらもいけていません。

### WWWクラスを使っている部分を削除する 
WWWクラスが使われているためINTERNETパーミッションが追加されるのであれば，そのWWWクラスを使用している箇所を消せばいいかと思います。

しかし，これが自分で作ったクラスではなく，AssetStoreで購入したライブラリ内でWWWクラスを利用している場合は厄介です。実際にNGUIにはWWWクラスを利用してるメソッドがあります。

### apkをビルドするのではなく，Google Android Projectを出力する用に変更
ビルドする対象をapkではなくGoogle Android Projectに変更して，その出力プロジェクトのAndroidManifestを編集する，という解決策もあります。この方法は事前に用意していたビルドスクリプトが使えなくなったり，別途ビルドスクリプトが必要になったり，単純にビルドするための手順が増えるなどの欠点がありますね。




## ビルド設定のコンフリクトを実験してみた

Plugins/Android/AndroidManifest.xmlのマニフェストファイルがビルド結果に直接反映されるわけではないことが分かりました。

そこで，ちょっとした実験をしてみました。

Unityは各種プラットフォームのバージョンなどのプロジェクトビルド設定を，GUI経由で設定することができます。Androidに関してもパッケージ名やバージョン，最小SDKバージョンを設定出来ます。これは普通のAndroidアプリケーションでは，AndroidManifest.xml内で設定します。

そこでPlugins/Android/AndroidManifest.xmlに設定した値とGUI経由で設定して値をわざとコンフリクトさせてビルドじてみたところ，どのようになるか確認してみました。


### 条件

Plugins/Androidに置いたAndroidManifest.xmlに記述した設定値

* パッケージ名(bundle identifier) com.mrstar.u_a_m
* バージョンネーム 2.0
* バージョンコード 200
* minSdkVersion(Minimum API Level) 16

BuildSettings -> PlayerSettings -> Androidから設定する設定値

* パッケージ名(bundle identifier) com.mrstar.unity_android_manifest_sample
* バージョンネーム 1.1
* バージョンコード 101
* minSdkVersion(Minimum API Level) 11

このようにして，AndroidManifestの内容とビルド設定の値をコンフリクトさせた状態でビルドすると，StagingAreaのAndroidManifestがどのようになるのかを調べてみました。

### 結果

さて，上記の設定でビルドすると，Temp/StagingArea内のAndroidManifest.xmlは次のようになりました。

```xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mrstar.unity_android_manifest_sample" android:theme="@android:style/Theme.NoTitleBar" android:versionName="1.1" android:versionCode="101" android:installLocation="preferExternal">
  <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
  <application android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false">
    <activity android:name="com.unity3d.player.UnityPlayerNativeActivity" android:label="@string/app_name" android:screenOrientation="portrait" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
      <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
      <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false" />
    </activity>
  </application>
  <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="19" />
  <uses-feature android:glEsVersion="0x00020000" />
</manifest>
```

* パッケージ名(bundle identifier) com.mrstar.unity_android_manifest_sample
* バージョンネーム 1.1
* バージョンコード 101
* minSdkVersion(Minimum API Level) 16

パッケージ名とバージョンコードとバージョンネームは，ビルド設定側が優先されていますが，minSdkVersionはPlugins/AndroidにおいたAndroidManifestの設定値が有効になっていますね。

全部が全部GUIのビルド設定で設定した値が優先であれば分かりやすいのですが，この点は注意が必要ですね。

ちなみにPlugins/Anroid/AndroidManifest.xmlを消した後，ビルドしなおすと，Temp/StagingArea/AndroidManifest.xmlのminSdkVersionはしっかりとMinimum API Levelで設定した11になりました。

# まとめ

* WWWクラスがコード内に存在すると，AndroidではINTERNETパーミッションが勝手に追加されてしまう。
* Plugins/Androidディレクトリ内にInternetパーミッションがないAndroidManifest.xmlを置いても，Internetパーミッションが出力apkには追加されてしまう。(StagingAreaのAndroidManifestも確かに追加されている。)
* BuildSettings -> PlayerSettings -> Androidから設定できるInternet AccessはAutoとRequireのみ。Forbiddenなどの項目もないので，コード内にWWWクラスが存在する場合，INTERNETパーミッションがどうしてもついてしまう。
* Plugins/Android/AndroidManifest.xmlが存在する時，そのAndroidManifest.xmlとプロジェクトのビルド設定との兼ね合いが変。このあたりの公式ドキュメントが見当たらない。
* 全体的にネイティブプラグインに関してドキュメントが少ない気がする。

公式情報見つけたという方，公式じゃないけれど詳しい情報見つけたよ，という方コメントいただけると嬉しいです。