1

I have created an app in which I want to discover Bluetooth devices and connect to one of them.

This app works perfectly fine on a smartphone with Android 10 and a smartphone with Android 12. However, I have a problem on a tablet with Android 11.

I have all needed permissions in the manifest. (Note: I have tried it both with and without android:maxSdkVersion="28" for the ACCESS_COARSE_LOCATION permission)

<!--Before Android 12-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" android:maxSdkVersion="30"/>
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<!--From Android 12-->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

But when it comes to using BluetoothAdapter.startDiscovery(), there seems to be a problem, since it returns false when used on the Android 11 tablet.

public void startDiscoveryOfBTDevices() {
    Log.d(TAG, "startDiscoveryOfBTDevices: Looking for unpaired devices.");

    if (mBluetoothAdapter.isDiscovering()) {
        mBluetoothAdapter.cancelDiscovery();
        Log.d(TAG, "startDiscoveryOfBTDevices: Canceling discovery.");
    }

    if (mBluetoothAdapter.startDiscovery()) {

        Log.d(TAG, "DISCOVERY STARTED");

        IntentFilter discoverDevicesIntent = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(broadcastReceiver2, discoverDevicesIntent);
        Log.d(TAG, "AFTER: " + discoverDevicesIntent);
    } else {
        Log.d(TAG, "DISCOVERY DOESN'T WORK");
    }

}

I check for and request all the needed location and bluetooth permissions on runtime. And I even checked the location permissions directly before calling startDiscovery, just to make sure:

if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    Log.d(TAG, "NOT GRANTED");
    return;
}

That was all fine.

I even checked if it was caused by the GPS_PROVIDER not being turned on, as suggested in this answer, but no change in behavior. The smartphones with Android 10 and Android 12 worked fine, but the tablet with Android 11 didn't, although all three devices had the GPS disabled.

I did all of those things based on answers of similar questions here on SO and Google.

Now my question is, if there is a way to find out what causes the error in startDiscovery. Is there something like an error object or log, which could give me more information?

In case it might be important, the problem occurs on a Teclast M40 Pro with Android 11.

EDIT

I looked into the source code for startDiscovery:

public boolean startDiscovery() {
    if (getState() != STATE_ON) return false;
    try {
        synchronized(mManagerCallback) {
            if (mService != null) return mService.startDiscovery();
        }
    } catch (RemoteException e) {Log.e(TAG, "", e);}
    return false;
}

Looking at it, you can see, that there are only two places from which it returns false.

I checked the state directly before calling startDiscovery with BluetoothAdapter.getState() and it returned 12, which is the value of the constant STATE_ON. So, that doesn't seem to be the place from where it returns false.

That means, it returns false at the end of the function. But that should only occur, if there is a RemoteException, which gets caught, or if mService == null, if I understand the code correctly.

I didn't see any error from the BluetoothAdapter in Logcat, so mService would need to be null. But the only time it becomes null is in onBluetoothServiceDown. And as far as I could find out, that only occurs, when

  • Bluetooth is off
  • Maximum name/address remote retrieval retry exceeded
  • Bluetooth service disconnected

But Bluetooth is on, and it is the initial try to discover Bluetooth devices.

So, I am still not closer to knowing, why it returns false.

EDIT #2

I realized through Kozmotronik's comment, that I didn't point out the following before.

I check if the Bluetooth is active, before calling startDiscoveryOfBTDevices() with the following function:

public void checkBluetooth() {
    if (mBluetoothAdapter == null) {
        Log.d(TAG, "checkBluetooth: Does not have BT capabilities.");
    } else if (!mBluetoothAdapter.isEnabled()) {
        Log.d(TAG, "checkBluetooth: enabling BT.");
        Intent enableBTIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivity(enableBTIntent);

        IntentFilter BTIntent = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
        registerReceiver(broadcastReceiver1, BTIntent);
    } else {
        Log.d(TAG, "checkBluetooth: BT already on.");
        // Start discovery
        startDiscoveryOfBTDevices();
    }
}
Geshode
  • 3,600
  • 6
  • 18
  • 32
  • Have you tried to check using [isEnabled()](https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#isEnabled()) method prior to `startDiscovery()` method? – Kozmotronik Nov 18 '22 at 08:15
  • I check `BluetoothAdapter.isEnabled` before calling `startDiscoveryOfBTDevices`, but just to make sure, I also checked it directly before `startDiscovery` just now and it returns `true`, as expected. So, the Bluetooth is definitely on and ready. – Geshode Nov 18 '22 at 09:05
  • I see, well if it doesn't throw any exception, seems like the mService is the only doubtful here. Somehow it may become null because of a consequence of some invocation in your app? – Kozmotronik Nov 18 '22 at 11:34
  • If that is the case, why does it work correctly on the two smartphones with Android 10 and Android 12? Is there something specific about Android 11, that could cause behavior like that? – Geshode Nov 18 '22 at 12:43
  • Hi @Geshode, any advancements on the matter so far? – Kozmotronik Dec 01 '22 at 14:05
  • @Kozmotronik No changes. I feel like it has to do with the tablet specifically, but I haven't been able to get my hands on another Android 11 device, so I couldn't make sure. – Geshode Dec 02 '22 at 04:04
  • I see, hey look, what I tell you. My smart phone is running a modified version of the Android 11 called Lineage OS. We can give your code a try in my device if you'd like to. – Kozmotronik Dec 02 '22 at 05:43

1 Answers1

1

I got it to work after manually turning on location services.

I am not sure, why it was necessary to turn them on manually, since it worked fine on my phones without having to turn them on manually.

The permissions to access location were given correctly. But it seems, that it isn't possible to use the location services on this tablet, if they haven't been turned on, even if the permissions were given.

Geshode
  • 3,600
  • 6
  • 18
  • 32