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.