The Potential Cause
I double checked the manifest file to ensure someone didn't leave the external storage permission configured by accident. However, as expected, only the permissions I remembered were listed in the manifest. Needless to say I was momentarily confused.
I then remembered a post by Ian Lake I had read a while back talking about how the Google Play Services libraries were automatically adding certain content to the manifests such as registering the Google Play Services version. Perhaps a library was adding the permission on the apps behalf. Sure enough, the final merged manifest for the application had these lines merged into the application's manifest:
I then remembered a post by Ian Lake I had read a while back talking about how the Google Play Services libraries were automatically adding certain content to the manifests such as registering the Google Play Services version. Perhaps a library was adding the permission on the apps behalf. Sure enough, the final merged manifest for the application had these lines merged into the application's manifest:
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<android:uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature
android:glEsVersion="0x00020000" android:required="true" />
I immediately recognized the write external storage permission and the OpenGL v2 requirement as part of the Google Maps V2 API. However, my app was not using the Maps api, so I ran the following Gradle command to see which library was potentially including Maps:
./gradlew androidDependencies
which showed this snippit:
\--- com.google.android.gms:play-services-location:7.8.0
+--- com.google.android.gms:play-services-base:7.8.0
| \--- com.android.support:support-v4:23.0.0
| \--- LOCAL: internal_impl-23.0.0.jar
\--- com.google.android.gms:play-services-maps:7.8.0
\--- com.google.android.gms:play-services-base:7.8.0
\--- com.android.support:support-v4:23.0.0
\--- LOCAL: internal_impl-23.0.0.jar
\--- com.google.android.gms:play-services-location:7.8.0
+--- com.google.android.gms:play-services-base:7.8.0
| \--- com.android.support:support-v4:23.0.0
| \--- LOCAL: internal_impl-23.0.0.jar
\--- com.google.android.gms:play-services-maps:7.8.0
\--- com.google.android.gms:play-services-base:7.8.0
\--- com.android.support:support-v4:23.0.0
\--- LOCAL: internal_impl-23.0.0.jar
As you can see Google Play Location now depends on Maps V2. After a little research I determined that the smaller Google Play Service libraries are utilizing manifest merging to automatically add permissions and other attributes developers used to have to add manually. By updating to a newer version of the Location API, all applications that just use the location API will require new permissions added by its dependency on the maps API. Since most of the apps I had notice adding the external storage permission did use location in some form, I wonder if this is where the influx of external storage permissions is coming from.
Since the application I was testing wasn’t using Maps V2, what should be done about the extra permission? For Android 6.0 marshmallow, the permission would never be activated since the app wouldn’t directly request it. However, for Lollipop and below, the permission would have to be accepted by the user to just to install or update the app. This would potentially hold back automatic updates because they user would have to accept the new permissions in order to get the latest version. This is a tough ask when the new permissions are not even required for the app to operate correctly.
The Solution
After a little research, I discovered it is possible to prevent the inclusion of permissions by adding some lines to the application’s manifest file. Essentially the lines ask the development tools to "remove" the listed permissions as Gradle is generating the merged manifest.
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove"/>
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" tools:node="remove"/>
Notice that the application is removing both the write and read external storage permissions. This is due to the fact that manifest merging will automatically add the read permission if the write permission was added. You can read more about implicit permissions in the manifest merge guide.
After adding these lines I rechecked the application and everything was back to the explicit list of permissions in the manifest. Of course, you may want to comment why these lines exist to help remind you that you are removing the permission due to an implicit dependency to the maps library.
As of Google Play Services 8.3, the Maps API configuration indicates the WRITE_EXTERNAL_STORAGE permission is no longer required which solves this issue with respect to the Location API. If you are able to update to 8.3 I highly recommend it. This version is also recommended if you are targeting Android 6.0.
The solution would still apply for other 3rd party libraries that may add permissions that are not required for your application.
Update Nov 5, 2015
As of Google Play Services 8.3, the Maps API configuration indicates the WRITE_EXTERNAL_STORAGE permission is no longer required which solves this issue with respect to the Location API. If you are able to update to 8.3 I highly recommend it. This version is also recommended if you are targeting Android 6.0.
The solution would still apply for other 3rd party libraries that may add permissions that are not required for your application.
asddas
ReplyDelete