Ionic/Capacitor app upgraded to Ionic 6, bluetooth permissions not working

is I have an Ionic Vue app, written 2 years ago, using the @ionic-natiove/bluetoothle plugin,
which is a wrapper for the cordova plugin…

the app works on IOS. never built the android side…

so, its time to make the android side work, and I build a new project on capacitor 6
and am slowly migrating all the code over to common code, no platform sensitive code…

all my bluetooth scanning works, but the difference in the scanresult caused too much code difference,
so I added the @capacitor-community/bluetooth-le plugin to handle all the scanning and read/write of characteristics… this works great… but this plugin only does central, it cannot be a peripheral.(cannot advertise)

that code worked before on IOS. it is unchanged.
compiles and runs, no crash… but doesn’t actually advertise. on IOS or Android.

on Android i see a complaint about a missing permission

java.lang.SecurityException: Need android.permission.BLUETOOTH_ADVERTISE permission for AttributionSource { uid = 10746, packageName = com.sd.CnConfig

but I have checked and ALL the AdroidManifests have the correct permission setting
like this for my app


    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
    <uses-permission android:name="android.permission.UWB_RANGING"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-feature android:name="android.hardware.location.gps" />

Sometimes I get prompted for the Location Permission when starting the app…(on android)
if I delete the app anyhow… but scanning works. and connect works… and read/write work.

i also have the permission in the ios Info.plist…

this IS android 14. (samsung z-fold5)

I also just tried to use the @awesome bluetooth wrapper instead of the ionic-native

and get the same results.

I can rebuild the older IOS only app and it works using the native plugin wrapper.

i need to advertise, as our hardware only wakes up when the app is detected. so I can’t scan it til then
but advertise doesn’t work.

I also built a new cap 6 plugin (to support UWB ranging) and it uses BT as the OOB carrier, and I used the new permissions annotations and plugin methods check/request permissions… and it works great (but doesn’t advertise) on adroid. (and the prior ios only code merged in for ios works great too. )

what am I missing… the doc says there is a requestPermissions() call on all these plugins(native, cordova, awesome)., but there is a reported not a function if I try to use it

well this turned out to be lots of things…

the parameter data for startAdvertising is different between iOS and Android.
services:[uuid] (ios), service: uuid (android)
there IS a requestPermissions api, but

I had to use bluetoothle (all lower case) not the documented BluetoothLE
(and not import… so have to add eslint-disable/enable around the calls.

on Android the name AND the 128 bit UUID causes a data too large error
so you have to set
“includeDeviceName”: false
on iOS, the “restoreKey” is invalid,

the api for initializePeripheral and startAdvertising are different than documented
one says it is a promise(mixed case, and import), the other(lower case) says most of the calls parms are (success_callback, error_callback, call_parameters)
the promise version does not work.
the callback version does work

once I got it working, there is a bug in the debug output for startAdvertising, which I wasted WAY too much time on…

I asked for NO name an supplied the service UUID.
however scanning FOUND the service BUT the name WAS supplied but the service UUID was not shown

{"device":{"deviceId":"42:3E:0A:9C:FE:DD","name":"ConfigApp"},"localName":"ConfigApp","rssi":-33,"txPower":127,"manufacturerData":{"76":{}},"serviceData":{},"uuids":[],"rawAdvertisement":{}} ids=[]

ConfigApp was stated NOT to appear… but it does locally…

in nRF connect the name does NOT show, but the UUIDs do show… and our devices wake us as expected, and are scanned…

// example of the call layout that works vs the promise based which does not work (no error, but advertising does not actually start)
LogIt is a local function to display on debug or send via socketio to log server for capture away from development IDEs

          /* eslint-disable */
           // this function is NOT on the awesome or ionic-native plugins
            bluetoothle.requestPermissionBtAdvertise((x) => { this.LogIt("advertise permission success") }, (x) => { this.LogIt("advertise permission failed") });
            let service_data = {
              name: "ConfigApp", 
              "includeDeviceName": false, 
              timeout: 0,
              services: [this.Service],   // ios
              service: this.Service,       // android
              connectable: true
            }            
            this.LogIt("service data =" + JSON.stringify(service_data))
            /* eslint-disable */
            bluetoothle.startAdvertising(  // this call order is not on the awesome ot native plugins, 
                                                              // and the promise/.then() version doesn't work 
              /* eslint-enable */
              () => {     // success callback
                this.LogIt("advertising started")
                // wait  a little before scanning 
                setTimeout(() => { this.launchScan(ScanTimeout) }, earlyAdvertiseTime); // wait a little before scanning til the devices wake up 
              },
              (error) => {   // error callback
                this.LogIt("advertise error=" + JSON.stringify(error))
              },
              service_data  // parms from above
            )