Android Question BLE Android 8.1 and higher

Philip Prins

Active Member
Licensed User
Longtime User
From Android 8.1 you can not do a Bluetooth scan without a filter when the screen is off.
In BLE manager you can only filter on UUID however this doesn't work on iBeacons.
Is there a way to filter on name or manufacturer ?



Regards
Philip
 

Philip Prins

Active Member
Licensed User
Longtime User
You can only filter by services UUIDs.

Have you tried it when there is a foreground service?
Yes ,
You can not scan without a filter from 8.1 and higher:

However you can not scan ibeacons based on their UUID , you have to scan on name or manufacturar ID.
But with BLEmanager2 you can only set an UUID as filter.
 
Upvote 0

Philip Prins

Active Member
Licensed User
Longtime User
Thanks Erel,

Got this working but now i want to add a second filter :
B4X:
Private Sub ScanWithLeScanner
    Dim ScanSettingsStatic As JavaObject
    ScanSettingsStatic.InitializeStatic("android.bluetooth.le.ScanSettings")
    Dim ScanSettingsBuilder As JavaObject
    ScanSettingsBuilder.InitializeNewInstance("android.bluetooth.le.ScanSettings.Builder", Null)
    'https://developer.android.com/reference/android/bluetooth/le/ScanSettings.Builder
    ScanSettingsBuilder.RunMethod("setScanMode", Array(ScanSettingsStatic.GetField("SCAN_MODE_LOW_LATENCY")))
    '----------------------------------------------------------------------
    
    Dim ScanFilterStatic As JavaObject
    ScanFilterStatic.InitializeStatic("android.bluetooth.le.ScanFilter")
    Dim ScanFilterBuilder As JavaObject
    ScanFilterBuilder.InitializeNewInstance("android.bluetooth.le.ScanFilter.Builder", Null)
    'https://developer.android.com/reference/android/bluetooth/le/ScanFilter.Builder
    'ScanFilterBuilder.RunMethod("setDeviceName", Array("CCheck"))
    '    Add Scan Filter
    Dim ParcelUuidStatic As JavaObject
    ParcelUuidStatic.InitializeStatic("android.os.ParcelUuid")
    Dim ParcelUuid As JavaObject
    ParcelUuid = ParcelUuidStatic.RunMethod("fromString",Array("00000001-0000-1000-8000-00805f9b34fb"))
    'Log("LOOK HERE => " & ParcelUuid.RunMethod("toString",Null))
  
    ScanFilterBuilder.RunMethod("setServiceUuid", Array(ParcelUuid))
    
    
'    ScanFilterBuilder.RunMethod("setDeviceName", Array("CCheck"))
    Dim Filters As List = Array(ScanFilterBuilder.RunMethod("build", Null))
    '---------------------------------------------------------------------------
    Scanner.RunMethod("startScan", Array(Filters, ScanSettingsBuilder.RunMethod("build", Null), ScanCallback))
End Sub

I want to add :ScanFilterBuilder.RunMethod("setDeviceName", Array("CCheck")) but when i insert this it will not work.
How can i add an extra filter item?
 
Upvote 0

Philip Prins

Active Member
Licensed User
Longtime User
In which way doesn't it work? Where is the error message?

With one scanfilter the scan filter works and finds the devices.

When i add the second it does not find any devices.
No error messages.


I assume i can only make scanlist for one type , so for example only UUID.
Not mixing between UUID and name in the same scanfilter.

Solved it by making 2 services, one for UUID and one for Name.
 
Last edited:
Upvote 0

Philip Prins

Active Member
Licensed User
Longtime User
One problem left , how to get the advertising data:

B4X:
Private Sub Scan_Result (Result As Object)
    'Log("Scan_Result")
    Dim ScanResult As JavaObject = Result
    Dim device As JavaObject = ScanResult.RunMethod("getDevice", Null)
    Dim address As String = device.RunMethod("getAddress", Null)
    ManagerJO.GetFieldJO("devices").RunMethod("put", Array(address, device))
    Dim name As String
    Dim o As Object = device.RunMethod("getName", Null)
    If o = Null Then name = "" Else name = o
    Dim ScanRecord As JavaObject = ScanResult.RunMethod("getScanRecord", Null)
    'Log(ScanRecord) 'you can extend the code to access the data.
    'https://developer.android.com/reference/android/bluetooth/le/ScanRecord
    Dim rssi As Double = ScanResult.RunMethod("getRssi", Null)
    [B]Manager_DeviceFound(name, address, CreateMap(), rssi)[/B]
End Sub

ManagerDevice found expect a map:

In the log the scanrecord : (ScanRecord) ScanRecord [mAdvertiseFlags=6, mServiceUuids=null, mManufacturerSpecificData={76=[2, 21, -3, -91, 6, -109, -92, -30, 79, -79, -81, -49, -58, -21, 7, 100, 120, 37, 18, 94, 86, 120, -61]}, mServiceData={00007364-0000-1000-8000-00805f9b34fb=[1, -86, -69, -52, -35, -18, -1, 0, 17, 34, 51, 68, 85]}, mTxPowerLevel=4, mDeviceName=CCheck]

When i get the manufacturer specific date like this :
B4X:
Dim B As Object =  ScanRecord.RunMethod("getManufacturerSpecificData", Null)

Result:{76=[B@39da68d}

How do i convert the result in a similar map like the advertising data from BLEmanager2 so i can parse it by the BeaconParser?
(MyMap) {1=[B@da87e20, -1=[B@3eba3d9, 10=[B@a17119e, 22=[B@164d47f, 9=[B@9e75c4c, 0=[B@469a495}
 
Last edited:
Upvote 0

Philip Prins

Active Member
Licensed User
Longtime User
Ok

For other people that want to scan for iBeacons in the background with Android 8.1 and up:

First create a scanfilter :
Scanfilter:
Private Sub ScanWithLeScanner
    
    Dim ScanSettingsStatic As JavaObject
    ScanSettingsStatic.InitializeStatic("android.bluetooth.le.ScanSettings")
    Dim ScanSettingsBuilder As JavaObject
    ScanSettingsBuilder.InitializeNewInstance("android.bluetooth.le.ScanSettings.Builder", Null)
    'https://developer.android.com/reference/android/bluetooth/le/ScanSettings.Builder
    ScanSettingsBuilder.RunMethod("setScanMode", Array(ScanSettingsStatic.GetField("MATCH_NUM_ONE_ADVERTISEMENT")))
    '----------------------------------------------------------------------
    
    Dim ScanFilterStatic As JavaObject
    ScanFilterStatic.InitializeStatic("android.bluetooth.le.ScanFilter")
    Dim ScanFilterBuilder As JavaObject
    ScanFilterBuilder.InitializeNewInstance("android.bluetooth.le.ScanFilter.Builder", Null)
    ScanFilterBuilder.RunMethod("setManufacturerData", Array(76,Null)) 'Apple ID
    Dim Filters As List = Array(ScanFilterBuilder.RunMethod("build", Null))
    '---------------------------------------------------------------------------
    Scanner.RunMethod("startScan", Array(Filters, ScanSettingsBuilder.RunMethod("build", Null), ScanCallback))
    Scanactive = True
    
End Sub

Then handle the result:
Scan result:
Private Sub Scan_Result (Result As Object)
    'Log("Scan_Result")
    Dim ScanResult As JavaObject = Result
    Dim device As JavaObject = ScanResult.RunMethod("getDevice", Null)
    Dim address As String = device.RunMethod("getAddress", Null)
    ManagerJO.GetFieldJO("devices").RunMethod("put", Array(address, device))
    Dim name As String
    Dim o As Object = device.RunMethod("getName", Null)
    If o = Null Then name = "" Else name = o
    Dim ScanRecord As JavaObject = ScanResult.RunMethod("getScanRecord", Null)
    Log(ScanRecord) 'you can extend the code to access the data.
    Dim data() As Byte = ScanRecord.RunMethod("getManufacturerSpecificData", Array(76)) '76 = apple id
 
    If data <> Null Then
        
        Private bc As ByteConverter
        
        
        Dim tx As Byte
        
        Dim raf As RandomAccessFile
        Dim ib As iBeacon
        raf.Initialize3(data, False)
        Dim hex As String = bc.HexFromBytes(data)
        Log(hex)
        ib.uuid = hex.SubString2(4, 36) 'bytes 4 - 19
'        beacon1.uniqueid = hex.SubString2(4, 46) 'this also includes the major and minor parts
        ib.major = raf.ReadShort(18)
        ib.minor = raf.ReadShort(20)
        tx = raf.ReadSignedByte(22)
        
        
        Log(ib.Uuid)
        Log(ib.Major)
        Log(ib.Minor)
    
    End If
    Dim rssi As Double = ScanResult.RunMethod("getRssi", Null)
    Manager_DeviceFound(name, address, ib, rssi)
    
End Sub
 
Last edited:
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…