VS 2022 17.1.0
Xamarin Android SDK 12.2.0.4
We have a Xamarin Forms project that includes an Android target. That Android target has recently been updated to have a targetSdkVersion 31 (Android 12)
We are now getting the following errors when trying to upload our Signed APK to Google Play
Duplicate declarations of permission
android.permission.ACCESS_COARSE_LOCATION with different
maxSdkVersions. Duplicate declarations of permission
android.permission.ACCESS_FINE_LOCATION with different maxSdkVersions.
If I look at the signed APK created by VS2022 build I can see these entries in AndroidManifest.xml
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission-sdk-23
android:name="android.permission.ACCESS_COARSE_LOCATION"
android:maxSdkVersion="30" />
<uses-permission-sdk-23
android:name="android.permission.ACCESS_FINE_LOCATION"
android:maxSdkVersion="30" />
How can I see what is causing these permission values to be merged into our AndroidManifest?
Our currently released build has a targetSdkVersion of 30 (Android 11) and whilst these duplicate permissions are present in the merged manifest for that relesase, Google Play does not complain.
Other AndroidManifest values that might be important are
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="3.7.0"
android:installLocation="0"
android:compileSdkVersion="31"
android:compileSdkVersionCodename="12"
package="com.OurCompany.OurApp"
platformBuildVersionCode="31"
platformBuildVersionName="12">
<uses-sdk
android:minSdkVersion="24"
android:targetSdkVersion="31" />
OTHER VALUES REMOVED
</manifest>
I finally managed to trace which component was adding ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION permission entries.
The only way I found to track it down was from all the entries in the "obj" folder under "lp" e.g. \obj\Debug\120\lp
This was wear the various libraries I was using would unpack themselves. I search that folder for occurences of "ACCESS_COARSE_LOCATION" and that gave me the library name that was the problem
The change I made in our AndroidManifest was
<uses-permission-sdk-23
android:name="android.permission.ACCESS_FINE_LOCATION"
tools:node="remove"
android:maxSdkVersion="30" /
Note the use of the tools:node attribute, the Android docs for this are here, https://developer.android.com/studio/build/manage-manifests
Related
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"/>
We are trying to update Google Play Install Referrer Library and
Internally it's adding some external read write permissions.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Do we really need to stick with the permissions ?
dependency implementation 'com.android.installreferrer:installreferrer:1.1
Source https://developer.android.com/google/play/installreferrer/library.html
Install referrer adds this permission due to the fact that the targetSdkVersion is a value lower than the version in which the restriction was added.
If you take a look at generated manifest-merger-report in the build folder of your app, you can see this information:
uses-permission#android.permission.READ_PHONE_STATE
IMPLIED from android/app/src/main/AndroidManifest.xml:1:1-130:12 reason: com.android.installreferrer has a targetSdkVersion < 4
Information on how this implicit system permission works on Android can be found in this documentation :
https://developer.android.com/studio/build/manifest-merge#inspect_the_merged_manifest_and_find_conflicts
Quoting from this answer (and completing):
Version 1.1 and 1.1.1 are missing "minSdkVersion". This would automatically add those permissions (because the default SDK < 4 as said by #thiagolr). See similar issue here: Google Play Services 12.0.1.
Solution
Version 1.1.2 solves this issue.
Details
Manifest.xml for v1.0 (from https://mvnrepository.com/artifact/com.android.installreferrer/installreferrer/1.0)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.installreferrer" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="22" />
<uses-permission android:name="com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE" />
<application />
</manifest>
Manifest.xml for v1.1 (from https://mvnrepository.com/artifact/com.android.installreferrer/installreferrer/1.1)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.installreferrer">
<uses-permission android:name="com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE" />
<application />
</manifest>
I've also come across this issue.
But in my case, the 1.1 version is also adding the READ_PHONE_STATE permission
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
I've decompiled the .aar file for installreferrer:1.1 and checked the manifest and pom file, there is nothing in those files to indicate that these permissions should be added.
The library manifest file only adds this permission (which is always has in previous versions):
<uses-permission android:name="com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE"/>
I haven't been able to find any official information regarding this.
But other Google libraries have had issues in the past with adding additional, unneeded, permissions, which have then been removed in a hotfix version shortly after.
For example, this:
Why has the READ_PHONE_STATE permission been added?
So i hope the same is gonna happen here.
Edit: Solution: Version 1.1.2 (and above) solves this issue.
From this answer:
This is because they have added a dependency to
com.google.android.gms:play-services-measurement:17.2.1
Which adds those permissions.
You can find it on the file: manifest-merger-blame-debug-report.txt which is under "yourApp/build/intermediates/manifest_merge_blame_file/debug"
It's a bug. Also, installreferrer 1.1.1 doesn't solve it.
Solution:
Update to installreferrer 1.1.2 or any version above (current version is 2.1`)
Obsolete:
Easiest solution is to downgrade installreferrer back to 1.0 for now.
But if you need this version, you can add:
<uses-permission android:name="<permission_name>" tools:node="remove" />
To disable it.
But know that if you'll use any API which needs it inside the library, it could lead to a crash, so I won't recommend doing so.
These permissions are added because com.android.installreferrer has a targetSdkVersion < 4. You can see it on the manifest-merger-release-report.txt file located on Temp\gradleOut\build\outputs\logs folder inside your project. This is a bug and it will probably be fixed on a newer version.
In order to fix this, you need to find out which plugin is adding com.android.installreferrer as dependency.
In my project, the culprit was the Facebook plugin. It uses the com.facebook.android:facebook-core:5.15.x package which is responsible for adding the com.android.installreferrer:installreferrer:1.1 dependency.
The solution was to rollback to com.facebook.android:facebook-core:5.13.0, which doesn't have a com.android.installreferrer dependency.
Edit the file FacebookSDK/Plugins/Editor/Dependencies.xml and change these packages to:
<androidPackage spec="com.facebook.android:facebook-core:[5,5.13.0)" />
<androidPackage spec="com.facebook.android:facebook-applinks:[5,5.13.0)" />
<androidPackage spec="com.facebook.android:facebook-login:[5,5.13.0)" />
<androidPackage spec="com.facebook.android:facebook-share:[5,5.13.0)" />
Next, don't forget to resolve the dependencies again: Assets > Play Services Resolver > Android Resolver > Force Resolve
1.1.2 is released, it adds minSdkVersion correctly.
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="22" />
One could theoretically remove them altogether with the manifest-merger:
<manifest
xmlns:tools="http://schemas.android.com/tools">
<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" />
</manifest>
But if the library will then still work as expected is another story -
it's rather an exception, that a Google library requires unnecessary permissions.
The release notes and the documentation do not mention permissions.
We are currently trying to update our System to the newest Android Studio/Gradle Tools and are expieriencing some errors on the way.
We do have 2 libraries using the permission.C2D_MESSAGE, namely Firebase and XtremePush. The problem is, as soon as we want to build our application the Manifest Merger fails the build because he wasn't able to complete the merge with the error "No records found. (This is a bug in the manifest merger.)".
When we looked into the issue we found following definitions:
Firebase
<permission android:name="${applicationId}.permission.C2D_MESSAGE"
android:protectionLevel="signature"/>
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE"/>
XtremePush
<permission
android:name=".permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name=".permission.C2D_MESSAGE" />
As both definitions are in external libraries, we are not able to set merging rules or change the manifest details. Also, both libraries are up to date as of today, so there seems to be no solution either on the respective developers side. Setting the permission in our manifest also did not change anything.
Thanks a lot!
In your Android Manifest file add:
<uses-sdk tools:overrideLibrary="com.example.firebase, com.example.xtremepush"/>
I solved the problem by first finding out which libraries do clash. For me it was XtremePush with the package name 'ie.imobile.extremepush' and Firebase with the package name 'com.google.firebase'.
Then i change my implementation to..
<permission
android:name="${applicationId}.permission.C2D_MESSAGE"
android:protectionLevel="signature"
tools:overrideLibrary="com.google.firebase, ie.imobile.extremepush" />
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE"
tools:overrideLibrary="com.google.firebase, ie.imobile.extremepush"/>
..so that my manifest would override both manifests, which were clashing and resulted in the merging issue. This was no problem as they both already were nearly identical in function.
I am compiling a project that does not explicitly request the READ_PHONE_STATE permission, but when I compile I am seeing the permission in my compiled Android Manifest file. I'm assuming some library that's being pulled in is adding it explicitly or forgot to set its minimum SDK version (which would add it).
The only thing I have to go on is that in the final manifest, the permissions I requested myself look like this:
<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.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
And the READ_PHONE_STATE looks like this:
<android:uses-permission android:name="android.permission.READ_PHONE_STATE" />
Does the android prefix mean anything?
Is there any way to narrow down which library is adding this permission?
You can exactly see if a (or because of) library adds some extra Permission to your manifest. Check at file generated (see below) during build process and look for the unwanted permission within the file!
Go to your project folder and look for this path:
[ProjectFolder]/build/outputs/logs/manifest-merger---report.txt
open the file and search for the permission
In my case I found these lines at the
uses-permission#android.permission.READ_PHONE_STATE IMPLIED from
C:\..\...\AppFolder\src\..\AndroidManifest.xml:2:1-14:12 reason:
com.some.evil.library has a targetSdkVersion < 4
This generated file show the output of the merge process described here in Android Developers site.
I would look at:
Android Library Manifest vs. App Manifest
This isn't really a duplicate so I won't flag, however I think he covers the topic fairly well in his answer to that question.
After that and assuming you can't figure it out, I would do the following:
Locate your gradle cache
Crack open the artifacts of each of your dependences (rename to .zip and extract is the easiest way to do this)
check if they have manifests included and see whats in the,
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.