Nov 4, 2015
After updating to Android Studio 4.1.1 the uses-permission in the manifest no longer works. It does not produce any build error, but in the target device it acts like the uses-permission tags are just not there.

I first noticed something was wrong when my working Bluetooth LE project just stopped detecting any other devices in scanning. On a hunch I uninstalled the debug version from the device and built an signed APK of the release version. No errors yet. Then I transferred the APK file to the device and launched it and was surprised to see "This application does not require any special access." I know from experience that I should have been seeing a warning that the app requires ACCESS_FINE_LOCATION. So just to be sure, I added a really serious permission: ANSWER_PHONE_CALLS. Surprisingly, the install on the device still says "This app does not require any special access.". Fortunately I had saved an APK file that I built before I updated Android Studio, and when I install it on the same device, the "access precise location" warning pops up and the Bluetooth stuff works perfectly. I am targeting the same API as before, same compileSDK. I suspect that the Bluetooth functions are silently failing because part of the OS thinks I have not declared the proper permissions. Here is my module build.gradle and the relevant parts of my manifest:

apply plugin: 'com.android.application'

android {
compileSdkVersion 27
defaultConfig {
applicationId "com.realtimespecialties.watering"
minSdkVersion 21
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "watering-1.1.apk"

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
<uses-feature android:name="android.hardware.location.gps" />

<activity android:name=".Main">
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>


Last edited:
Update: Bluetooth Scanning is still failing silently. That's the real problem. I only assumed it was a manifest problem because of the strange absence of permission warnings on installation. Perhaps that is not it. But, turning to the initial problem, here is what I have. It is all very standard:

I get an instance of the BluetoothAdapter with:

mBluetoothAdapter = ((BluetoothManager) getSystemService(BLUETOOTH_SERVICE)).getAdapter();

I get a BluetoothLeScanner with:

mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();

I define my scan callback class as:

private class MyBleScanCallback extends ScanCallback {
public void onScanResult(int callbackType, ScanResult result) {
Log.i("mytag", "onScanResult was called");

public void onBatchScanResults(List<ScanResult> results) {
Log.i("mytag","onBatchScanResults was called");

public void onScanFailed(int errorCode) {
Log.i("mytag","onBatchScanResults was called");
. . . .

private void addScanResult(ScanResult result) {
mylog("addScanResults called");
. . . .
} //..end of MyBleScanCallback class definition

I create an instance of the callback class with:

mScanCallback = new MyBleScanCallback();

With all this setup, I initial a scan with:


I am using the simplest form of startScan() with no filters or special settings. As you see, I have Log.i statements on any possible scan results, included a scan failure. Although not shown, I also have Log.i statements if any of the objects created are null. I have checked every possible failure outcome and none of them trigger a log entry.

Again, this is exactly the same code that was working perfectly when compiled with the older version of Android Studio. Although the title says I am using Android Studio 4.0.1, that is a typo. It is actually 4.1.1. Sorry.

Anyway, what else could I check or try to resolve this issue?
Problem Solved! I was right that it had to do with permissions, but wrong about where the problem was. The problem is not in the manifest. It was my old working app was targeting SDK 22, and after updating Android Studio I targeted API 26. Starting with API 26, so called "dangerous permissions" like location must be established at run time. (Since Bluetooth can access location from external devices, location permission is required to scan for Bluetooth). What I was missing was that run-time code to ask the user for permission to access location. The relevant API calls are:

checkSelfPermission() to see if the permission has been granted already...

shouldShowRequestPermissionRationale() to check if I should display an educational dialog informing the user why I need the permission...

requestPermissions() to actually initiate the operating system dialog that asks the user if my app should be allowed that permission..

There is also a callback from the requestPermissions() call telling me if the user said yes or no.

If you search out these APIs you will find all the Google docs on how to properly request run-time permissions.

Since these APIs are not available for earlier Android systems, if you want to include those earlier systems, all these APIs must be wrapped in:


That's it. Once I implemented run-time permission checking, my app started working just like it did two years ago.