お気持ちの表明

思考を雑に外出していきます

Androidで不要そうなPermissionが取得されているので消した話@React Native Advent Calendar 2017

このブログは、React Native Advent Calendar 2017 - Qiitaの7日目の記事です。

私はAndroidがもうそろ1年ぐらいになるエンジニアです。
最近、ReactNativeを触ってアプリを書いていまして、
その際に気になった、AndroidのPermissionの話を書いてみようと思います。

Permissionが取られていることに気づいた

ReactNativeの新規プロジェクトを立ち上げて、
AndroidのmergeされたManifestを見てみると、
以下の3つのPermissionが取られていることに気づきました。

  • WRITE_EXTERNAL_STORAGE
  • READ_PHONE_STATE
  • READ_EXTERNAL_STORAGE

自身のManifestに追加したわけでもないのにな〜〜〜。

あと、以下のPermissionが自分のアプリのManifestに追加されました。

  • SYSTEM_ALERT_WINDOW

「なんだこいつら」
「必要なPermissionなんかコレ」
と調べたところ、いらなそうなんで消しときましょうという話です

なんで謎なPermissionが3つ取られているのか

まずは、以下の3つの権限の話からです

  • WRITE_EXTERNAL_STORAGE
  • READ_PHONE_STATE
  • READ_EXTERNAL_STORAGE

ひとまずReactnativeのリポジトリを見てみたところ、
早速それっぽいIssueを見つけたので読んでみました。

以下はざっくりしたまとめです。

謎にPermissionが取得されている原因

  • 問題の3つの権限は、 org.webkit.android_jsc から取られていた
    • これはAndroid StudioMerged Manifest を見てみるとわかるよ!
  • org.webkit.android_jscAndroid Manifestには、 minSdkVersiontargetSdkVersion が設定されていなかった
  • そのせいで、デフォルト値が適用され、 minSdkVersion=1 targetSdkVersion=1 となっていた
    • 以下はドキュメントからの引用です
      • android:minSdkVersion 警告: この属性を宣言しないと、既定値の「1」と見なされ、アプリがすべてのバージョンの Android と互換性があるものとして扱われます。 アプリにすべてのバージョンとの互換性があるわけではない場合(たとえば、アプリが API レベル 3 で導入された API を使用、など)、適切な minSdkVersion を宣言しないと、API レベルが 3 未満の端末にインストールしたとき、使用できない API にアクセスしようとして実行時にアプリがクラッシュします。 このため、必ず minSdkVersion 属性で適切な API レベルを宣言するようにしてください。 uses-sdk | Android Developers

      • android:targetSdkVersion アプリのターゲットとなる API レベルを指定する整数。設定しない場合、既定値は minSdkVersion で指定した値になります。 uses-sdk | Android Developers

  • minSdkVersiontargetSdkVersion3以下の場合、問題の3つの権限が暗黙的に付与されるようになっていた

解決策

  • 解決方法は、org.webkit.android_jscAndroid Manifestに minSdkVersiontargetSdkVersion を設定すること

以下、かなしいお話

  • 実は、その旨のPRは既に出していて、mergeもされている
  • PRはmergeされているものの、リリースがされていない 😇
  • PRのmerge後に続くコメントを読んだところ、こんなかんじだった
    • FBの人「最初のリリース以降、更新してないからリリースフローがないんすわ 😇」
      • 最初にリリースした人にメンションつけて、どうすればいいんや、と聞く
    • 最初にリリースした人「やる気あったら、あんたリリースしちゃってくれ 😇」
    • そのまま放置.....
  • その後も、FB組に「進捗どう?」的なコメントを投げるも音沙汰なし 😇

対応策

現状、属性マーカー(Attribute Marker)を利用して消すしかなさそう 😇

以下を参考に、実例

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="xxx.xxx.xxx">

  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:node="remove" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove" />
  <uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove"/>

というわけで、とりあえずこれで対応することにします 😇

SYSTEM_ALERT_WINDOWは必要なのか...?

次は、SYSTEM_ALERT_WINDOWの話です。
この権限は、WarningやCrashをデバッグ時に画面に表示するために取られていたPermissionのようです。
つまり、デバッグビルドのときは欲しいけど、リリースビルドでは特に必要のないものです。
消してしまいましょう!!!!

以下を参考に、実例

app/src/release/AndroidManifest.xmlにRelease Build用のmanifestをつくる 中身は以下のような感じ

<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    >

    <uses-permission tools:node="remove" android:name="android.permission.SYSTEM_ALERT_WINDOW" />
</manifest>

これで、リリース時にはSYSTEM_ALERT_WINDOWのPermission消せる

まとめ

ReactNativeで最初から付与されているPermission群の削除は、
app/src/main/AndroidManifest.xmlを以下のようにすると消せるよ

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="xxx.xxx.xxx">

  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:node="remove" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove" />
  <uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />
  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

  ...

</manifest>

SYSTEM_ALERT_WINDOWのPermissionは、デバッグ時以外は不要なので、
以下の内容でapp/src/release/AndroidManifest.xmlにRelease Build用のManifestをつくるといいよ

<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    >

    <uses-permission tools:node="remove" android:name="android.permission.SYSTEM_ALERT_WINDOW" />
</manifest>