Hey, Where Did My Permission Go?
Some developers wonder where extra permissions in their app come from.
Other developers wonder why they are not getting the permissions that they
are asking for. If you have a <uses-permission>
element, and you are
encountering SecurityExceptions
or other symptoms that suggest that you
do not actually hold the permission that you asked for, there are a few
possible culprits.
You Have the Element in the Wrong Place
The <uses-permission>
elements should be inside the <manifest>
element, but outside the <application>
element. In other words, this
is fine:
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="com.commonsware.android.something.something"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="INTERNET"/>
<uses-permission android:name="ACCESS_NETWORK_STATE"/>
<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<!-- cool stuff goes here -->
</application>
</manifest>
but this is not:
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="com.commonsware.android.something.something"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<uses-permission android:name="INTERNET"/>
<uses-permission android:name="ACCESS_NETWORK_STATE"/>
<!-- cool stuff goes here -->
</application>
</manifest>
While Android Studio will report this if you manually analyze your manifest (Analyze > Inspect Code… from the main menu), it will not automatically show a warning just by having the elements in the wrong spot.
You Cannot Hold That Permission
Some permissions that used to be in the Android SDK, such as BRICK
,
cannot be held by ordinary Android applications. They usually
require your app to be signed by the signing key that signed the
device firmware (i.e., be part of a custom ROM). Some might alternatively
allow your app to hold the permission if your app is installed on the /system
partition (i.e., be part of a custom ROM or have been moved there by
a rooted device user).
However, you are not told at build time that the <uses-permission>
element
you have in your manifest
is tied to a permission that you are unlikely to be able to hold.
Your targetSdkVersion Is 23 or Higher
The big reason for not getting your permission nowadays is because
your project has a targetSdkVersion
of 23 or higher, and the permission
that you are requesting is “dangerous”. In Android 6.0, this includes:
ACCESS_COARSE_LOCATION
ACCESS_FINE_LOCATION
ADD_VOICEMAIL
BODY_SENSORS
CALL_PHONE
CAMERA
GET_ACCOUNTS
PROCESS_OUTGOING_CALLS
READ_CALENDAR
READ_CALL_LOG
READ_CELL_BROADCASTS
READ_CONTACTS
READ_EXTERNAL_STORAGE
READ_PHONE_STATE
READ_SMS
RECEIVE_MMS
RECEIVE_SMS
RECEIVE_WAP_PUSH
RECORD_AUDIO
SEND_SMS
USE_SIP
WRITE_CALENDAR
WRITE_CALL_LOG
WRITE_CONTACTS
WRITE_EXTERNAL_STORAGE
For these permissions, not only does your targetSdkVersion
23+ app
need to have the <uses-permission>
element(s), but you also have
to ask for those permissions at runtime from the user on Android 6.0+
devices, using methods like checkSelfPermission()
and
requestPermissions()
.
As a temporary workaround, drop your targetSdkVersion
below 23.
However, eventually, you will have some reason to want your
targetSdkVersion
to be 23 or higher. At that time, you will need
to adjust your app to use the new runtime permission system.
The Android 6.0 preview documentation has
a page dedicated to this topic,
and my book has a lot of material on how to make this work
in your app.