Here's the scenario. My app (A) is using a library (B).
My app (A) is using permission READ_PHONE_STATE and it's declared in manifest.xml as
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
While library (B) is also using the same permission READ_PHONE_STATE, but with maxSdkVersion set to 22.
<uses-permission
android:name="android.permission.READ_PHONE_STATE"
android:maxSdkVersion="22"/>
So now the problem is when app is built and in the final _merged_manifest_ I'm having maxSdkVersion="22" set, and because of this my current device which is running nougat can't request for this particular permission.
Currently I found a solution to override this value in my app (A) manifest.xml
<uses-permission
tools:replace="android:maxSdkVersion"
android:name="android.permission.READ_PHONE_STATE"
android:maxSdkVersion="28"/>
But this requires me to update maxSdkVersion every time I update the sdk version in my app (A).
So my question is
Is there a way to ignore maxSdkVersion set by library (B) using some namespace in my manifest.xml like tools:ignore
Set maxSdkVersion to latest sdkVersion in build.gradle automatically without manually changing it
Use tools:remove attribute on your own AndroidManifest.xml:
<uses-permission
android:name="android.permission.READ_PHONE_STATE"
tools:remove="android:maxSdkVersion"/>
Related
My app (code on GitHub) was rejected by Google Play with reason:
Please remove the background location permission requested and submit an update to your app.
However, my app does not declare the ACCESS_BACKGROUND_LOCATION permission:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
<uses-permission android:name="android.permission.REORDER_TASKS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="com.google.android.apps.photos.permission.GOOGLE_PHOTOS" />
<uses-permission android:name="android.permission.SET_WALLPAPER"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
I first suspected Mapbox, as my app includes these libraries:
implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:9.1.0'
implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-localization-v8:0.11.0'
implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-scalebar-v9:0.4.0'
implementation 'com.mapbox.mapboxsdk:mapbox-android-telemetry:6.1.0'
However my app checks location only when the app is running fully visible on the screen.
Also, the merged manifest shown by Android Studio does not include ACCESS_BACKGROUND_LOCATION:
It seems that setting android:minSdkVersion="29" would circumvent the issue, but I can't do it as I have thousands of important users below that.
I also tried adding a popup disclaiming that the app uses location in the background (even though it does not), but that gets rejected too, with this reason:
It is possible to deliver a similar experience without access to location in the background.
Question: What could be making someone think that I use location in the background?
From the official Privacy changes in Android 10
Access granted automatically when targeting Android 9 or lower
If your app runs on Android 10 or higher but targets Android 9 (API level 28) or lower, the platform applies the following behavior:
If your app declares a <uses-permission> element for either ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION, the system automatically adds a element for ACCESS_BACKGROUND_LOCATION during installation.
If your app requests either ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION, the system automatically adds ACCESS_BACKGROUND_LOCATION to the request.
Access when device is upgraded to Android 10
If a user grants your app access to device location – either ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION – then upgrades their device from Android 9 to Android 10, the system automatically updates the set of location-based permissions granted to your app. The set of permissions that your app receives after the upgrade depends on its target SDK version and its defined permissions, as shown in the following table: here
In other words, it all depends on your Target platform version.
I'm building an application for Android that is partitioned around SDK version 29. For compatibility reasons, the app must implement a feature differently on SDK versions < 29 and >= 29. These two versions require a different set of permissions. Currently, the application automatically switches the feature depending on the active SDK version. My application is getting rejected by the Play Store because all permissions are declared for both app versions. The >= 29 version for example does not need as many (sensitive) permissions as the < 29 version but is rejected for not actively using these permissions.
I've read about manifest merging, but I'm not sure if it can achieve what I'd like (conditional permission declaration).
I would like to maintain only one apk that handles both app versions. Is it possible to declare conditional manifest permissions, something like:
<if minSdkVersion="29">
<!-- Arbitrary permissions -->
<uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
</if>
<uses-permission android:name="android.permission.BLUETOOTH" />
Use the built in maxSdkVersion:
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"
android:maxSdkVersion="28"/>
I bumped into a very strange problem, the studio compiles all the manifest permissions except one:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Tested in other compilers - the permissions successfully compiled.
How can you solve this truly strange problem?
My full list of permissions:
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
If the app targets API level 23 or higher, the app user must explicitly grant this permission to the app through a permission management screen. The app requests the user's approval by sending an intent with action ACTION_MANAGE_OVERLAY_PERMISSION. The app can check whether it has this authorization by calling Settings.canDrawOverlays().
I solved this problem by modifying the build.gradle file.
I changed targetSdkVersion from 26 to 19 (any version that <19)
But I'm not sure if this is the best solution
You cannot use SYSTEM_ALERT_WINDOW permission, because it has signature protection level.
See signature protection level - clarifying
and see https://developer.android.com/guide/topics/manifest/permission-element.html
Also you cannot use BIND_ACCESSIBILITY_SERVICE permission, it has signature protection level too.
What is the difference between these two syntaxes.
android:uses-permission and uses-permission. For example:
<android:uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
The first one was automatically added to the manifest by Android Studio when I created an activity that reads from storage. Also why did it add an android:maxSdkVersion attribute and specifically set it to 18 when I have targetSdkVersion for the project set as 21.
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
Actually this permission is required for API level 18 and lower, Android 4.4 (API level 19), it's no longer necessary for your app to request the WRITE_EXTERNAL_STORAGE permission when your app wants to write to its own application-specific directories on external storage (the directories provided by getExternalFilesDir().
I noticed the READ_PHONE_STATE permission when I uploaded the apk to google play.
I have not added it and it is not written anywhere in my manifest or any other file of my project. (I looked through all libraries for this permission)
My app did not have this permission in my previous build with same libraries. Since last build I updated android studio to version 1, updated my android sdk and made a few changes (in code) to my app. I don't request the device ID in my app.
My app has minSDK 14 and no ads.
Here are my manifest permissions:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Here's the apk file
I was able to resolve the problem. It's similar to the solution of reneph.
I found that one library had no minSDK specified neither in the build.gradle nor in the manifest file. After adding
defaultConfig {
minSdkVersion 14
targetSdkVersion 21
}
the permission was gone. I don't know why it worked without the permission on my previous build (also no minSDK specified). Must have been either the Android Studio 1.0 or the Android SDK update.
Android developer documentation for READ_PHONE_STATE permission:
Note: If both your minSdkVersion and targetSdkVersion values are set to 3 or lower, the system implicitly grants your app this permission. If you don't need this permission, be sure your targetSdkVersion is 4 or higher.
I found the issue.
I had another library included that had minSdkVersion="4" (its not my library, but my app requires minSdkVersion="14").
I just changed the minSdkVersion of the additional library to 14 and the permission disappeared!
I declared the following permissions in my app:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<permission-group android:name="android.permission-group.STORAGE" />
--- WORKED FOR ME!--
I tried so many things on manifest, which mentioned here and other forums.
At the last, I noticed that the error message, The apk upload error message wants to add "Privacy Policy URL" into Store listing / Privacy policy section. (which checked "Not submitting a privacy policy URL at this time").
So, I add my privacy policy URL from my website, then submit. later, I successfully uploaded my apk.
One cause could be a (transitive) dependency, i.e. a library, that declares a minimum required Android SDK level below 4. In this case the "manifest merger tool" will add those permissions implicitly.
Lower-priority manifest declares Permissions added to the merged manifest
targetSdkVersion <= 3 WRITE_EXTERNAL_STORAGE, READ_PHONE_STATE
targetSdkVersion <= 15 and using READ_CONTACTS READ_CALL_LOG
targetSdkVersion <= 15 and using WRITE_CONTACTS WRITE_CALL_LOG
Source: https://developer.android.com/studio/build/manifest-merge#implicit_system_permissions
Look into the manifest-merger-*-report.txt log, found in build/outputs/logs if this was case.