Search code examples
androidflutterbluetoothandroid-permissionsandroid-12

Got "lacks permission android.permission.BLUETOOTH" on Specific device after android 12 update


So i have an application that connect to bluetooth printer. It is fine and running on all devices except these devices:

  • Xiaomi redmi note 10 Pro (Updated to android 12 with MIUI 13.0.1)
  • Oppo Reno 5 4G (model: CPH2159) (Updated to android 12 with Color Os 13)

Regarding Google developer, android 12 using these three permission

android.permission.BLUETOOTH_CONNECT
android.permission.BLUETOOTH_SCAN
android.permission.BLUETOOTH_ADVERTISE

but when i tried to connect on my printer, i got this error that makes me pulls my hair out.

2022-03-21 09:23:49.039 29022-29206/com.xxxx.xxxxx E/BThermalPrinterPlugin: UID 10324 / PID 29022 lacks permission android.permission.BLUETOOTH
    java.lang.SecurityException: UID 10324 / PID 29022 lacks permission android.permission.BLUETOOTH
        at android.os.Parcel.createExceptionOrNull(Parcel.java:2425)
        at android.os.Parcel.createException(Parcel.java:2409)
        at android.os.Parcel.readException(Parcel.java:2392)
        at android.os.Parcel.readException(Parcel.java:2334)
        at android.bluetooth.IBluetoothSocketManager$Stub$Proxy.connectSocket(IBluetoothSocketManager.java:227)
        at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:404)
        at id.kakzaki.blue_thermal_printer.BlueThermalPrinterPlugin.lambda$connect$1$id-kakzaki-blue_thermal_printer-BlueThermalPrinterPlugin(BlueThermalPrinterPlugin.java:544)
        at id.kakzaki.blue_thermal_printer.BlueThermalPrinterPlugin$$ExternalSyntheticLambda1.run(Unknown Source:6)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:920)

is this sort of ROM/platform/device specific problem. android.permission.BLUETOOTH supposed to be used on android 11 and below because android 12 and above replaces it with android.permission.BLUETOOTH_CONNECT, right? then why i got those specific device errors in the first place?

i have tried in Samsung A52 with android 12 and got no problem at all.

i have added necessary permission on manifest

AndroidManifest.xml

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

and runtime permission request


        var perm = arrayListOf(
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.CAMERA,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.RECORD_AUDIO,
            Manifest.permission.READ_PHONE_STATE,
            Manifest.permission.BLUETOOTH,
            Manifest.permission.BLUETOOTH_ADMIN
        )
        //permission
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { //  >= android 12
                perm.add(Manifest.permission.BLUETOOTH_CONNECT)
                perm.add(Manifest.permission.BLUETOOTH_SCAN)
                perm.add(Manifest.permission.BLUETOOTH_ADVERTISE)
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                requestPermissions(
                    perm.toTypedArray(), ActivityBase.REQ_PERM
                )
            }


Solution

  • As you already found, Xiaomi seems to have an incorrect implementation of the Bluetooth spec.

    I had the same problem as you do and solved it declaring android.permission.BLUETOOTH in AndroidManifest.xml, even for Android 12.

    So, instead of adding the following line, which the documentation suggests:

    <uses-permission android:name="android.permission.BLUETOOTH"
                 android:maxSdkVersion="30" />
    

    I added:

    <uses-permission android:name="android.permission.BLUETOOTH" tools:remove="android:maxSdkVersion" />
    

    I had to add the tools:remove attribute because the Bluetooth library I was using was adding the maxSdkVersion attribute already. So it was being included in my merged manifest even if I didn't add it myself.

    Also note that adding this permission in the manifest didn't cause any further problems or permission prompts on other Android 12 devices like Samsung.