_edit: see https://medium.com/@applification/fixing-react-native-android-permissions-9e78996e9865 for a workaround -@hramos_
It seems like Read/Write external storage and Read phone state permissions are automatically added to the manifest on building the android apk. Are these necessary for all React Native android apps? Is there any way to remove these permissions?
android:uses-permission#android.permission.READ_EXTERNAL_STORAGE
android:uses-permission#android.permission.WRITE_EXTERNAL_STORAGE
It feels weird that I'll see these permissions being requested if I install the app from the Play store if I'm not using them.
Hey lucidrains, thanks for reporting this issue!
React Native, as you've probably heard, is getting really popular and truth is we're getting a bit overwhelmed by the activity surrounding it. There are just too many issues for us to manage properly.
react-native
or for more real time interactions, ask on Discord in the #react-native channel.Just remove them from your AndroidManifest.xml
if you don't need them. I believe these are for AsyncStorage
.
There's an awesome place to post code / ask question first before filing an issue: StackOverflow. It's the best system for Q&A. Many people from the community hang out there and will be able to see and answer your question. This lets us use the github bug tracker for bugs.
I'm posting this here because github issues haven't been working very well for us and because StackOverflow is so much better. Thanks for reading! :)
@mkonicek aren't they added at build time? In that case it's not easy to remove them
+1
Even when you don't have the READ and WRITE permissions in your AndroidManifest they still show up on build. Do you just have to remove AsyncStorage completely?
I have similar problem when I generated release apk.
Before install, it asked for permissions:
but I confirmed I removed AsyncStorage completely and only have
<uses-permission android:name="android.permission.INTERNET" />
in my AndroidManifest
@mkonicek @satya164 @bestander Could this issue be re-opened please? I digged around a bit, I couldn't find where those permissions were added. So far there are :
<android:uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<android:uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<android:uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Which I'm not sure what they do, but I don't think there are actually used because it wouldn't work on Android 6.+ (run-time permissions). Also it seems strange to force permissions to use a module since in NetInfoModule on Android, React-native requires YOU to add the needed permission to your manifest (See NetInfoModule.java#L38).
Anyway it's not for AsyncStorage
as it uses a SQLite DB under the hood, which doesn't require any permission. Even if it used another method of storage like SharedPreferences
or the internal storage to store files, it shouldn't require any permission (See Storage Options).
I'm sure this is coming from React-native, I tried on a fresh project with no other permission, and there were here once the APK generated. I also looked at every Android app in the showcase and every app has those permissions, except one which doesn't have READ_PHONE_STATE
at least : Facebook Ads manager (See _Permissions: View details_ at the bottom).
Also not completely related, but this is a permission too:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
This permission (Draw over other apps) is needed in debug mode to show the error redbox, but is still present
in release mode, which is quite scary for the user (even though it is not used). I could probably submit a PR for that (have 2 different manifests for debug and release, only uses the permission in the debug one).
Sorry for the long post, but my company is in the process of releasing our new Android app, and we would really like to ship it without un-needed permissions since that's not some the Android community really likes.
Thanks for your attention.
Maybe gradle does that?
I can't find any string with READ_PHONE_STATE
in the code.
I don't mind reopening this but could you help us investigating this?
@facebook-github-bot reopen
Okay, reopening this issue.
@bestander Yeah I think it's added automatically by Android/gradle since I couldn't find any mention of them in the code, but I'm really not sure why. I'll try to investigate quickly and get back to you/submit a PR as soon as I find something.
I forgot to check the manifest merger log... Turns out the problem is quite obvious:
IMPLIED from /Users/mayouk/Dev/tmp/AwesomeProject/android/app/src/main/AndroidManifest.xml:1:1-23:12 reason: org.webkit.android_jsc has a targetSdkVersion < 4
android:uses-permission#android.permission.READ_PHONE_STATE
IMPLIED from /Users/mayouk/Dev/tmp/AwesomeProject/android/app/src/main/AndroidManifest.xml:1:1-23:12 reason: org.webkit.android_jsc has a targetSdkVersion < 4
android:uses-permission#android.permission.READ_EXTERNAL_STORAGE
IMPLIED from /Users/mayouk/Dev/tmp/AwesomeProject/android/app/src/main/AndroidManifest.xml:1:1-23:12 reason: org.webkit.android_jsc requested WRITE_EXTERNAL_STORAGE
Because android-jsc
doesn't provide a targetSdkVersion
, the manifest merger added the permissions for various reasons (See Implicit permissions). Apparently @astuetz already fixed this in https://github.com/facebook/android-jsc/pull/12 but either the new version of android-jsc
wasn't published or it isn't used in React-native currently. If you can contact the maintainers of android-jsc
to solve this, that would be fantastic!
@brentvatne ping, is it possible to publish new android-jsc?
@Bhullnatik what we're doing until a new version of android-jsc will be released is just stripping away the unwanted permissions in our apps' manifest like this:
<uses-permission
android:name="android.permission.READ_PHONE_STATE"
tools:node="remove"/>
@astuetz I was looking at the manifest merger on how to fix this until it gets solved, thanks for the heads-up 😄
@bestander - sure I can do that, we might also want to update to r189384 as well @kmagiera?
@astuetz thanks, it helped me, justto add to this info I had to declare the tools attribut in
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.bepaw.esportninja">.
By default there is only xmlns:android, no xmlns:tools
@bestander @brentvatne Hey! Any update on this?
👍 +1 for this.
I feel like the removal of SYSTEM_ALERT_WINDOW
from release builds is far more critical than the other permissions being discussed.
@marcshilling It's all equally important to remove them in my opinion, but this one is a little more tricky. The easiest way to remove it is to remove it in the release AndroidManifest.xml
, but the configuration is a little bit heavy to include in every React Native project.
The other way would be to remove the usage, thus not needing the permission anymore. For that I'm not sure where/for what it is used, but I didn't see any particular need that couldn't be fulfilled with something else. I could be wrong though.
For those who want to exclude SYSTEM_ALERT_WINDOW
from release builds without separate Manifest files:
In your manifest:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" tools:remove="${excludeSystemAlertWindowPermission}"/>
In app/build.gradle
:
buildTypes {
debug {
manifestPlaceholders = [excludeSystemAlertWindowPermission: "false"]
}
release {
manifestPlaceholders = [excludeSystemAlertWindowPermission: "true"]
}
}
Seems to work well.
@marcshilling Perfect! Thank you! It's been kind of embarrassing to have to explain that to users because I couldn't figure out how to remove it. 😕
Hi, I've been alerted about READ_PHONE_STATE by a user of one of my apps.
I'm getting the same reason in the build log
reason: org.webkit.android_jsc has a targetSdkVersion < 4
Hopefully it gets solved in a future release.
For the time being, I'm using the permission removal workarounds mentioned here
astuetz - READ_PHONE_STATE - https://github.com/facebook/react-native/issues/5886#issuecomment-200869879
marcshilling - SYSTEM_ALERT_WINDOW - https://github.com/facebook/react-native/issues/5886#issuecomment-224397883
As well as adding the namespace as explained by mouneyrac (https://github.com/facebook/react-native/issues/5886#issuecomment-209218936)
So, I wasn't being able to remove SYSTEM_ALERT_WINDOW with the solution above.
Had to resort to a hack (after much prodding and poking).
in AndroidManifest.xml
<uses-permission android:name="${permissionName}" tools:node="remove"/>
in app/build.gradle
buildTypes {
debug {
manifestPlaceholders = [permissionName: "android.permission.ACCESS_FINE_LOCATION"]
...
}
release {
manifestPlaceholders = [permissionName: "android.permission.SYSTEM_ALERT_WINDOW"]
...
}
}
In debug mode, I remove ACCESS_FINE_LOCATION, since I don't use (neither in dev nor in prod). Any other non-essential permission could be used (BIND_TV_INPUT?).
In release mode, I remove SYSTEM_ALERT_WINDOW. If you don't forcibly remove it, it will get merged in.
Hacky, but effective 😂
If you use this solution https://github.com/facebook/react-native/issues/5886#issuecomment-224397883, don't forget to add xmlns:tools
as described here: https://github.com/facebook/react-native/issues/5886#issuecomment-209218936
@marcshilling I think this is something we can have in the generator template by default.
@marcshilling Your solution didn't work for me as well but the one from @jbrodriguez did.
One thing I noticed was that instead of using a real permission which will be removed, you can also use a non-existing permission name like REMOVE_ME
.
Quick comment: after updating from 0.30 to 0.32 it seems react-native now suddenly adds the permission com.google.android.c2dm.permission.RECEIVE I've seen this in two apps now. I doubt it needs this new permission either.
The use of @marcshilling 's tools:remove
doesn't work for me either.
My solution to avoid unnecessary permissions (a mix of the above) is:
In the app/src/main/AndroidManifest.xml
, I added:
<uses-permission tools:node="remove" android:name="android.permission.READ_PHONE_STATE" />
And in a newly-created app/src/release/AndroidManifest.xml
, I put:
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
<!-- These are added by React Native for debug mode, but actually aren't needed in releasemode -->
<uses-permission tools:node="remove" android:name="android.permission.SYSTEM_ALERT_WINDOW" />
</manifest>
Variable substitution inside a tools:node
doesn't work for me, so something like tools:node="${someManifestPlaceholder}"
wouldn't work. So the above approach of multiple AndroidManifest.xml files that merge together seems like a better method of adding/removing certain permissions on a debug
vs release
basis (or the default main
).
@marcshilling your solution didn't work for me, so I've used @jbrodriguez's combined with @astuetz's
u guys think it's worth creating a script to automate this?
maybe create a npm package that makes this on install and then remove itself?
Never done something like that tho I believe it is possible.
@mikelambert, regarding your approach, is anything else needed to make it work?
does gradle automagically merges app/src/release/AndroidManifest.xml
into app/src/main/AndroidManifest.xml
?
that seems like the cleaner approach to me
Thoughts and comments appreciated! :)
Yes, it automatically merges the AndroidManifest.xml
files. I believe it's all that was necessary to make it work for me, but let me know if I've missed anything!
@mikelambert also worked for me. I've got multiple release buildTypes though, so I needed release{X}/AndroidManifest.xml
for each build-type in order to get it working.
Not sure how you could capture something like that in a npm package..
The proper fix (IMO) would be to set this up as part of the project when react-native init
is run. ie, something similar to how this gets used in the initial project setup:
https://github.com/facebook/react-native/blob/master/local-cli/templates/HelloWorld/android/app/src/main/AndroidManifest.xml
@freakinruben everything u do manually can b done in a script ;)
the first version of the script would be basic, and just support release/debug versions
later we can prompt user for more configurations
@mikelambert for sure man, we r all hacking this thing here until a proper solution would b merged by the react-native team :)
<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"/>
Hi all,
Be careful with letting RN add this permission for you android.permission.READ_PHONE_STATE
. If you try to publish an app to the Google Play store with such permission (among others), it will warn you with:
Your app has an apk with version code X that requests the following permission(s): android.permission.READ_PHONE_STATE. Apps using these permissions in an APK are required to have a privacy policy set.
More info: https://play.google.com/intl/en-US_ALL/about/privacy-security/additional-requirements/. So yeah, be careful and ensure to delete this permission if you don't need it till this is fixed in RN. I feel this should be documented somewhere for now just so people with releasing intentions are aware.
@mikelambert solution worked for me. Thank you.
@mikelambert Thank you for the best solution.
@ferrannp it was actually the reason why I got here. :) and the solutions worked fine.
Small recap since March 15 is approaching:
@mmazzarolo what happens on March 15 (tomorrow)?
@antoinerousseau: Google Play’s New Privacy Policy Rule Goes into Effect on March 15th, and READ_PHONE_STATE is one of the permissions that will force you to publish a Privacy Policies document in both the Play Store and app itself.
build.gradle
classpath 'com.android.tools.build:gradle:1.2.3' // For Android 5.1
Following rule craches on 5.1:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" tools:node="remove"/>
06-02 15:06:54.102: E/AndroidRuntime(18353): android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@f03a0a2 -- permission denied for this window type
06-02 15:06:54.102: E/AndroidRuntime(18353): at android.view.ViewRootImpl.setView(ViewRootImpl.java:704)
06-02 15:06:54.102: E/AndroidRuntime(18353): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:289)
06-02 15:06:54.102: E/AndroidRuntime(18353): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
06-02 15:06:54.102: E/AndroidRuntime(18353): at android.app.Dialog.show(Dialog.java:311)
06-02 15:06:54.102: E/AndroidRuntime(18353): at com.facebook.react.devsupport.DevSupportManagerImpl.showProgressDialog(DevSupportManagerImpl.java:762)
06-02 15:06:54.102: E/AndroidRuntime(18353): at com.facebook.react.devsupport.DevSupportManagerImpl.reloadJSFromServer(DevSupportManagerImpl.java:767)
06-02 15:06:54.102: E/AndroidRuntime(18353): at com.facebook.react.devsupport.DevSupportManagerImpl.handleReloadJS(DevSupportManagerImpl.java:658)
06-02 15:06:54.102: E/AndroidRuntime(18353): at com.facebook.react.XReactInstanceManagerImpl$3$1.run(XReactInstanceManagerImpl.java:412)
06-02 15:06:54.102: E/AndroidRuntime(18353): at android.os.Handler.handleCallback(Handler.java:815)
06-02 15:06:54.102: E/AndroidRuntime(18353): at android.os.Handler.dispatchMessage(Handler.java:104)
06-02 15:06:54.102: E/AndroidRuntime(18353): at android.os.Looper.loop(Looper.java:194)
06-02 15:06:54.102: E/AndroidRuntime(18353): at android.app.ActivityThread.main(ActivityThread.java:5631)
06-02 15:06:54.102: E/AndroidRuntime(18353): at java.lang.reflect.Method.invoke(Native Method)
06-02 15:06:54.102: E/AndroidRuntime(18353): at java.lang.reflect.Method.invoke(Method.java:372)
06-02 15:06:54.102: E/AndroidRuntime(18353): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
06-02 15:06:54.102: E/AndroidRuntime(18353): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)
Solution is to remove:
tools:node="remove
@iegik , I'm not sure whose solution/code you were trying, but adding a SYSTEM_ALERT_WINDOW
permission to release builds is not a solution I would recommend to others.
Please try my suggestion above, if you don't want to require that permission in your release builds.
@mikelambert I have to request SYSTEM_ALERT_WINDOW permission from users, because our app crashes somewhere on getting permissions :(
@iegik From what I understand, normal release-mode apps shouldn't need SYSTEM_ALERT_WINDOW
, and it's only useful for development-mode apps. Do you have a log of said crash, that show where this "somewhere" is?
Of course, you're welcome to do that if it suits your needs and isn't worth debugging for you... I just didn't want future readers of this thread to think they need to request that permission too, since this thread is about how to not request unnecessary permissions. :)
Adding this line, makes my app crash.
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />
@npaez, thats right
thats not what node="remove " is doing. Its removing the permission from the generated manifest, because other libraries, for example, can add permissions. This makes sure the permission will definitely not be there.
— Heron at Discord
@marcshilling 's method worked. (y)
This should not be closed as RN is still adding this permission implicitly:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
which is a super nasty I have your phone number and IMEI if you install my app sort of permission. I wouldn't want to install any apps that request this...
@johnculviner by the way, does it work when you try to retrieve IMEI? because i tried using react-native-device-info and it is not working, i tried using react-native-Imei which has been deprecated since RN 0.47 give me error of not override or implemented method, do you have any solution for my problem?
@koswarabilly I'm pretty sure the above permission is one of the requirements for IMEI which definitely is a pretty elevated thing to request given it uniquely identifies the phone forever
@johnculviner i know the permission give me access to the device info , i have tried to get the imei through react-native-imei package but when i run-android it prompt me saying error override or not implemented method, have you ever successfully get IMEI number of your device
Or have anyone successfully retrieve imei number here? Because i believe that it is a possible task
I am using React Native v0.44.0 and tried upgrading to SDK 26, but android system doesn't allow SYSTEM_ALERT_WINDOW to be used anymore even in debug mode. SYSTEM_ALERT_WINDOW can only be used by system level apps in Oreo. Any ideas on how I can make this work?
For anyone trying to solve this, in this post the guy use the solution listed here but very well explained.
https://medium.com/@applification/fixing-react-native-android-permissions-9e78996e9865
@mikelambert Thanks, your solution works perfectly
The Solution for me was to modify the
./android/app/src/main/AndroidManifest.xml
I had to add the following lines
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
// Added this
xmlns:tools="http://schemas.android.com/tools"
package="de.democracydeutschland.app"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
// Added tools:node="remove"
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove"/>
// Added READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE both with tools:node="remove"
<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-sdk
android:minSdkVersion="16"
android:targetSdkVersion="22" />
...
For Debug Purposes: ./android/app/build/outputs/logs/manifest-merger-***-report.txt
This removes the App-Permission Dialog when installing via PlayStore
The one thing I dont get:
Why do I have to add rights to remove them while the app itself does not even require permission?
Grüße Ulf
<3
The "correction" will be added in any next version of React-native ?
Our app has multiple build types (4 as of now), and we wanted to remove SYSTEM_ALERT_WINDOW permissions from all of them EXCEPT debug
.
I didn't want to hack up permission names through manifest placeholders, nor create 3 extra AndroidManifests with equal content.
So, in the end I remove the permission in main/AndroidManifest.xml using:
<manifest xmlns:tools="http://schemas.android.com/tools" ...>
<uses-permission tools:node="remove" android:name="android.permission.SYSTEM_ALERT_WINDOW" />
...
and then in a separate debug/AndroidManifest.xml, I add it back:
<manifest xmlns:tools="http://schemas.android.com/tools" ...>
<uses-permission tools:node="merge" android:name="android.permission.SYSTEM_ALERT_WINDOW" />
...
Because the debug
AndroidManifest has a higher priority than the main
one (see Merge Priorities), it will override the removal and add the permission.
Sounds strange, but seems to work well (judging from the output of aapt d permissions <apk file>
).
Congress should have asked Zuck what's up with these permissions.
I think the solution is create another android/app/src/release/AndroidManifest.xml
like this:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.facebook.react.demo">
<uses-permission
android:name="android.permission.SYSTEM_ALERT_WINDOW"
tools:node="remove" />
<uses-permission
android:name="android.permission.READ_PHONE_STATE"
tools:node="remove" />
<application>
</application>
</manifest>
And edit android/app/build.gradle
like this:
android {
...
sourceSets.release {
manifest.srcFile 'release/AndroidManifest.xml'
}
}
Closing this issue, because unnecessary permissions are removed. Please see https://github.com/facebook/react-native/blob/master/local-cli/templates/HelloWorld/android/app/src/main/AndroidManifest.xml
@dulmandakh This is not relevant to the issue at all. The permissions are added to the Manifest when building an APK, they are not present in the default template (as mentioned in the original issue and in https://github.com/facebook/react-native/issues/5886#issuecomment-200862582). Can you please re-open the issue?
@dulmandakh this shouldn't have been closed. The permissions are added at build time, unrelated to your linked file
This seems to be the official guide on removing default permissions:
http://facebook.github.io/react-native/docs/removing-default-permissions
i don't know if this related to this forum or not.
so because recent change of google play console permissions rules. Google will check our manifest to see android permissions we used.
although i have use 'tools:node="remove"' in every unused permissions and in release apps the permission not shown. Google still doesn't let me to publish my apps in google play console.
anyone have some problem like this? i got this problem 27-01-2019.
As a followup on this our currently used Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="de.democracydeutschland.app">
<uses-permission android:name="android.permission.INTERNET" />
<!-- Default permissions which are added silently and not needed by us - hence we remove them -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:node="remove" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove" />
<!-- This needs to be added in dev mode but removed in all others
since this config is used for production aswell we need to remove it here -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" tools:node="remove" />
<!-- included from rn-fetch-blob - implications of removal are unknown -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" tools:node="remove" />
...
</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="de.democracydeutschland.app">
<!-- This needs to be added in dev mode but removed in all others -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" tools:node="replace" />
</manifest>
Above mentioned permissions are implicitly added by Android SDK because old JSC or JavaScriptCore was targeting SDK 4. In the master we have new JSC and will be used default in 0.59. So there is nothing we can do about it. Please see https://developer.android.com/studio/build/manifest-merge
Heads up the only way to remove SYSTEM_ALERT_WINDOW
is to follow the official react instructions on creating a new manifest file for release.
Perhaps it used to work by using manifestPlaceholders but there must have been a change or build tool versions that is breaking it.
@hammadzz thank you for reminding us about the unused permission, and I created a PR to fix this https://github.com/facebook/react-native/pull/23504. I hope that it'll land soon in the master and cherry picked for 0.59.
Most helpful comment
@Bhullnatik what we're doing until a new version of android-jsc will be released is just stripping away the unwanted permissions in our apps' manifest like this: