Android Question BLE Android 9 - Scanning stops when screen turned off

Discussion in 'Android Questions' started by Jmu5667, Feb 28, 2019.

  1. Jmu5667

    Jmu5667 Well-Known Member Licensed User

    Hello

    We are working with these devices, https://store.kontakt.io/next-generation/43-asset-tag-s18-3.html.

    We have a service that runs and is scanning:

    Code:
    #Region  Service Attributes
       
    #StartAtBoot: False
      
    #End Region

    Sub Process_Globals
       
    'These global variables will be declared once when the application starts.
       'These variables can be accessed from all modules.

       
    Private manager As BleManager2
       
    Private currentStateText As String = "UNKNOWN"
       
    Private currentState As Int
       
    Private scanning As Boolean
       
    Private bc As ByteConverter
          
       
    Private const TIME_TO_LIVE_SECONDS As Int = 30
      
       
    Private Timer1 As Timer
       
    Private rp As RuntimePermissions
       
    Private ManagerJO As JavaObject
       
    Private Adapter As JavaObject
       
    Private Scanner As JavaObject
       
    Private ScanCallback As JavaObject


    End Sub

    Sub Service_Create

       manager.Initialize(
    "manager")
       ManagerJO = manager
       Adapter = ManagerJO.GetField(
    "blueAdapter")
       Scanner = Adapter.RunMethod(
    "getBluetoothLeScanner"Null)
       ScanCallback.InitializeNewInstance(
    Application.PackageName & ".svc_ble_sos_le$MyScanCallback"Null)
      
       Timer1.Initialize(
    "hook",5000)

    End Sub

    Sub Service_Start (StartingIntent As Intent)
       Timer1.Enabled = 
    True
      
       StartScan_le
      
      
    End Sub

    Sub Service_Destroy
      
       StopScanWithLeScanner
      
       Timer1.Enabled = 
    False
       

    End Sub

    Sub hook_tick
      
       mod_functions.writelog(
    "hook_tick() Still Running")
      
    End Sub

    Sub Manager_StateChanged (State As Int)
       
    Select State
           
    Case manager.STATE_POWERED_OFF
               currentStateText = 
    "POWERED OFF"
           
    Case manager.STATE_POWERED_ON
               currentStateText = 
    "POWERED ON"
           
    Case manager.STATE_UNSUPPORTED
               currentStateText = 
    "UNSUPPORTED"
       
    End Select
       currentState = State

    End Sub

    Sub Manager_DeviceFound (Name As StringId As String, AdvertisingData As Map, RSSI As Double)
      
       
      
    End Sub

    ' // based on this answer: http://stackoverflow.com/questions/20416218/understanding-ibeacon-distancing
    Private Sub CalculateDistance(tx As Int, rssi As Double) As Double
       
    If rssi = 0 Then Return -1
       
    Dim ratio As Double = rssi / tx
       
    If ratio < 1 Then
           
    Return Power(ratio, 10)
       
    Else
           
    Return 0.89976 * Power(ratio, 7.7095) + 0.111
       
    End If
    End Sub

    #region "LE Scanner"

    Public Sub StartScan_le
       
    If manager.State <> manager.STATE_POWERED_ON Then
           
    Log("Not powered on.")
       
    Else If rp.Check(rp.PERMISSION_ACCESS_COARSE_LOCATION) = False Then
           
    Log("No location permission.")
       
    Else
           ScanWithLeScanner
       
    End If
    End Sub


    Private Sub Scan_Result (Result As Object)
      

       
    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)
      
       
    log("svc_ble_sos_le() Scan_Result > name : " & name & ", rssi : " & rssi & ", " & address)
      
    ' // not called yet as screen off issue
    '   Manager_DeviceFound(name, address, CreateMap(), rssi)
      
    End Sub

    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_POWER")))
      
       Scanner.RunMethod(
    "startScan"Array(Null, ScanSettingsBuilder.RunMethod("build"Null), ScanCallback))
    End Sub

    Private Sub StopScanWithLeScanner
       Scanner.RunMethod(
    "stopScan"Array(ScanCallback))
    End Sub


    #End Region


    #if Java
    import android.bluetooth.le.*;
    public static class MyScanCallback extends ScanCallback {
     public void onScanResult(int callbackType, ScanResult result) {
             processBA.raiseEvent(this, "scan_result", result);
        }

      

        /**
         * Callback when scan could not be started.
         *
         * @param errorCode Error code (one of SCAN_FAILED_*) for scan failure.
         */
        public void onScanFailed(int errorCode) {
           BA.Log("Error: " + errorCode);
        }
    }
    #End If
    We have noticed that on Android 9 when the screen is turned off no more Scan_Result events are fired, and when the screen is turn back on the scan results resume.

    We were using the standard Ble method that Erel provided, https://www.b4x.com/android/forum/threads/ble-2-bluetooth-low-energy.59937/#content

    We switched to the above code example to see if it made a difference, the result was the same. It functioned fine up to Android 8.

    Regards

    John.
     
  2. Erel

    Erel Administrator Staff Member Licensed User

  3. Jmu5667

    Jmu5667 Well-Known Member Licensed User

    No it is not a foreground service and there is not partial wake lock. I have a timer in the service that is serviced when the screen is off. There is a main service that is a foreground service and has a partial wake lock.

    Did I not read some where that if there was a foreground service that other service would inherit these properties ?
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    That's true. You should also check the logs and make sure that the service is not destroyed.
    Check the unfiltered logs. Might include more information.

    Are you limiting the BLE scanning with a filter list? Seems that it is required for background scanning: https://github.com/AltBeacon/android-beacon-library/issues/633
     
  5. Jmu5667

    Jmu5667 Well-Known Member Licensed User


    Yes, we want to limit it to 2 particular UUID's

    1. "F7826DA64FA24E988024BC5B71E0893E" - this is the device advertising itself
    2. "F7826DA64FA24E988024BC5B71E0893F" - this is same device but the button has been activated on it.

    In the app configuration the user selects the device they are using, and we use the MAC address to identify the correct one.

    I tried setting up the list in manager.Scan2(uuidlist, true) but did not get any devices. I downloaded an app fromt he app store Beacon Scanner, and it shows the UUID in lcase with the seperators, the above show in 1,2 are from the Blemanager2 library.

    Regards

    John.
     
  6. Jmu5667

    Jmu5667 Well-Known Member Licensed User

    In the service start:


    Code:
    Sub Service_Start (StartingIntent As Intent)
       
       
    Dim l As List
       
       l.Initialize
       l.Add(
    "f7826da6-4fa2-4e98-8024-bc5b71e0893e")
       l.Add(
    "f7826da6-4fa2-4e98-8024-bc5b71e0893f")
       
       manager.Scan2(l, 
    True)

    End Sub
    When this filtered list is applied I do not receive any Manager_DeviceFound events.

    Is the above code correct ?
     
  7. Erel

    Erel Administrator Staff Member Licensed User

    Are these the services uuids?
     
  8. Jmu5667

    Jmu5667 Well-Known Member Licensed User

    These are the only UUID's I can see. They are set here in the Kontakt dash board when you purchase them:

    upload_2019-3-1_8-39-26.png


    Here is the log data from the Manager_DeviceFound event:

    Code:
    03/01/2019 08:42:38.163 - Atlas SOS - Manager_DeviceFound() ID =E7:FA:C1:5D:B5:04 
    03/01/2019 08:42:38.169 - Atlas SOS - UUID F7826DA64FA24E988024BC5B71E0893E
    03/01/2019 08:42:38.174 - Atlas SOS - Unique ID F7826DA64FA24E988024BC5B71E0893EAE68A9FC
    Manager_DeviceFound function:

    Code:
    Sub Manager_DeviceFound (Name As StringId As String, AdvertisingData As Map, RSSI As Double)
       
       
    Dim key As Int = -1 'type is important. Must be Int.
       
       
       
    ' // NOTE: we will not process this is we do not have a selected MAC address
       mod_functions.writelog("Manager_DeviceFound() ID =" & Id)
       
    If AdvertisingData.ContainsKey(key) Then
           
    Dim b() As Byte = AdvertisingData.Get(key)
           
    If b.Length > 4 And b(0) = 0x4c And b(1) = 0 And b(2) = 0x02 And b(3) = 0x15 Then
               
               
               
               
    Dim beacon As Beacon
               beacon.Initialize
               
    Dim raf As RandomAccessFile
               raf.Initialize3(b, 
    False)
               
    Dim hex As String = bc.HexFromBytes(b)
               beacon.uuid = hex.SubString2(
    840'bytes 4 - 19
               beacon.uniqueid = hex.SubString2(848'this also includes the major and minor parts
               beacon.major = raf.ReadShort(20)
               beacon.minor = raf.ReadShort(
    22)
               
    Dim tx As Byte = raf.ReadSignedByte(24)
               beacon.distance = CalculateDistance(tx, RSSI)
               beacon.time = 
    DateTime.Now
               
    If Name = "" Then
                   Name = 
    "UNKNOWN "
               
    End If
               beacon.name = Name
               beacon.id = 
    Id
               
               
               
               
    ' // trap a button press
               If (beacon.uuid  = u1 Or beacon.uuid  = u2) And beacon.id = Main.APPSET.bleSOS.MacAddress  Then               
                   mod_functions.writelog(
    "UUID " & beacon.uuid)
                   mod_functions.writelog(
    "Unique ID " & beacon.uniqueid)
               
                   
                   
    ' // we have found a button press already
                   If Main.APPSET.bleSOS.Foundtime <> 0 Then
                       
    ' // this is not press, which is what we want
                       If beacon.uuid  <> u2 Then
                           
    ' // get the time period between now and the last time we got an 3F UUID
                           Dim dP As Period =  DateUtils.PeriodBetween(Main.APPSET.bleSOS.Foundtime, DateTime.Now)
                           
    ' // reset the u2 button press, if it was more then 2 seconds ago
                           If dP.Seconds > 2 Then
                               Main.APPSET.bleSOS.Foundtime = 
    0
                               Main.APPSET.bleSOS.PressTime = 
    0
                               Main.APPSET.bleSOS.StartNow = 
    False
                               mod_functions.writelog(
    "Button Pressed Reset")
                               
    Dim pv As PhoneVibrate
                               pv.Vibrate(
    250)
                               
    ToastMessageShow("BLE SOS BUTTON READY"True)
                           
    End If
                       
    End If
                   
    End If
                   
                   
                   
    ' // this a putton press UUID - 3F UUID
                   If beacon.uuid  = u2 Then
                       
    ' // record the last time we got a button press
                       Main.APPSET.bleSOS.Foundtime = DateTime.now
                       
    ' // have we caught this already
                       If (Main.APPSET.bleSOS.PressTime = 0And (Main.APPSET.alert_mode = 0Then
                           mod_functions.writelog(
    "Button Pressed")
                           Main.APPSET.bleSOS.PressTime = 
    DateTime.now
                           Main.APPSET.bleSOS.StartNow = 
    True
                           
    'Dim pw As PhoneWakeState
                           ' // turn the screen on
                           'pw.KeepAlive(True)
                           StartActivity(Main)                       
                       
    End If
                       
                   
    End If
               
    End If

           
    End If
       
    End If
       
    End Sub
    Screen shot from beacon scanner to verity that i am using the correct UUID.

    upload_2019-3-1_8-50-47.png

    Am I sending in the correct UUID's ?

    Regards

    John.
     
  9. Jmu5667

    Jmu5667 Well-Known Member Licensed User

    I have tried using the following code :

    Code:
    rivate 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_POWER")))
       
       
    ' // https://www.b4x.com/android/forum/threads/ble-custom-scanfilter-device-settings.99300/#post-625276
       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/os/ParcelUuid.html
       Dim ParcelUuidStatic As JavaObject
       ParcelUuidStatic.InitializeStatic(
    "android.os.ParcelUuid")
       
    Dim ParcelUuid As JavaObject
       ParcelUuid = ParcelUuidStatic.RunMethod(
    "fromString",Array("f7826da6-4fa2-4e98-8024-bc5b71e0893e"))
       
    Log("LOOK HERE => " & ParcelUuid.RunMethod("toString",Null))
       
       
    'https://developer.android.com/reference/android/bluetooth/le/ScanFilter.Builder
       ScanFilterBuilder.RunMethod("setServiceUuid"Array(ParcelUuid))
       
       
    ' // MAC Address
       'ScanFilterBuilder.RunMethod("setDeviceAddress", Array(Main.APPSET.bleSOS.MacAddress))
       
       
       
    Dim Filters As List = Array(ScanFilterBuilder.RunMethod("build"Null))
       
    ' // start the scanning   
       Scanner.RunMethod("startScan"Array(Filters, ScanSettingsBuilder.RunMethod("build"Null), ScanCallback))
       
    End Sub
    It works using the Mac Address, but while I dump the scan record I see this :

    Code:
    (ScanRecord) ScanRecord [mAdvertiseFlags=6, mServiceUuids=null, mManufacturerSpecificData={76=[221, -9, -126109, -9079, -9478, -104, -12836, -6891113, -32, -11962, -82104, -87, -4, -77]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=null]
    (ScanRecord) ScanRecord [mAdvertiseFlags=6, mServiceUuids=null, mManufacturerSpecificData={76=[2, 21, -9, -126, 109, -90, 79, -94, 78, -104, -128, 36, -68, 91, 113, -32, -119, 62, -82, 104, -87, -4, -77]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=null]
    (ScanRecord) ScanRecord [mAdvertiseFlags=6, mServiceUuids=null, mManufacturerSpecificData={76=[2, 21, -9, -126, 109, -90, 79, -94, 78, -104, -128, 36, -68, 91, 113, -32, -119, 62, -82, 104, -87, -4, -77]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=null]
    I am not sure if I have set the ParcelUuidStatic correctly.

    Regards

    John.
     
  10. Erel

    Erel Administrator Staff Member Licensed User

    A good explanation here: https://stackoverflow.com/a/50841523/971547

    You need to connect to the beacon. You can use the BLE example project for this. See which services are listed. The next step is to check whether one or more of these services are advertised. If so then you will be able to use the service as a filter.
     
    Jmu5667 likes this.
  11. Jmu5667

    Jmu5667 Well-Known Member Licensed User

    Thanks, I will check it out
     
  12. Jmu5667

    Jmu5667 Well-Known Member Licensed User


    Hi

    I got a list of services from a different beacon, (same manufacturer, as I could not connect to the one we want to use) using the BLE Example, put that as filtered list in the our app that wants to background scan and did not yield any results in the foreground no the background.

    I can see in the BLE example that the characteristics are listed, how are these interpreted ? Contact the Manufacturer ?


    Code:
    Sub Service_Start (StartingIntent As Intent)
       
       
    Dim l As List
       
       l.Initialize
       l.Add(
    "00001800-0000-1000-8000-00805f9b34fb")
       l.Add(
    "00001801-0000-1000-8000-00805f9b34fb")
       l.Add(
    "a1ea8130-0e1b-d4a1-b840-63f88c8da1ea")
       l.Add(
    "00001804-0000-1000-8000-00805f9b34fb")
       l.Add(
    "a1ea8110-0e1b-d4a1-b840-63f88c8da1ea")
       l.Add(
    "a1ea8120-0e1b-d4a1-b840-63f88c8da1ea")
       l.Add(
    "0000180a-0000-1000-8000-00805f9b34fb")
       l.Add(
    "0000180f-0000-1000-8000-00805f9b34fb")
       
       manager.Scan2(l, 
    True)

    End Sub
    Is is possible that none of these services are broadcasting ?

    Regards

    John.
     
  13. emexes

    emexes Well-Known Member Licensed User

    The UUIDs that end in 0000-1000-8000-00805f9b34fb are Bluetooth SIG (Special Interest Group aka bluetooth.org now bluetooth.com) assigned standard (common) services per https://www.bluetooth.com/specifications/gatt/services

    eg re: your list above are:

    0x1800 = "Generic Access" information, device name and type/class, plus some connection stuff that I've never used
    0x1801 = "Generic Attribute" changed services, also something I've never used
    0x1804 = "Tx Power" -100 to +20 dB (tempered by the specific device's hardware, no doubt)
    0x180a = "Device Information" manufacturer, model, serial number, revisions, etc.
    0x180f = "Battery Service" battery level 0..100% (but watch out for steps > 1%)

    What's more likely is that none of the nearby devices has *ALL* of those services, and thus none of them make it past the 8-UUID filter you listed. Perhaps just limit the filter to one service that you *know* your device has (I think every device has 0x180a) to get it working first, and then fine-tune it to let through fewer false matches (ie, devices that aren't the ones you're looking for).

    Having said that, I'm just off now to check whether the scan filter is must-have-at-least-one or must-have-all.
     
    Last edited: Mar 4, 2019
  14. Jmu5667

    Jmu5667 Well-Known Member Licensed User

    The list is just from 1 device
     
  15. emexes

    emexes Well-Known Member Licensed User

    I'm not having any success even just scanning for one service that I *know* exists on the Bluetooth sensor device sitting next to me.

    The BLE2 help says of Scan2:
    and now I'm wondering if perhaps devices don't necessarily advertise all their services... which would seem a reasonable thing to allow, because otherwise a device with many characteristics would soon have a flat battery from repeatedly sending out ginormous advertising packets.
     
    Jmu5667 likes this.
  16. Jmu5667

    Jmu5667 Well-Known Member Licensed User

    This is the same problem I have, the device that I want to use, only sends proximity UUID's not service UUID's as Erel pointed out, and the stack overflow article he pointed me to clearly state that you cannot background scan unless it is a service ID. The background scan works fine with no filter, just kill the battery.

    Seems like a dead end at the moment.
     
  17. emexes

    emexes Well-Known Member Licensed User

    I don't have a beacon, but I'm trying it with a iTag key finder thingo. When it gets disconnected, it beeps, and so I have just set it off. Hunted around the room trying to locate where the beeping was coming from, couldn't find it, gave up, sat back down, then realised it was in my pocket.

    Some of us take a little longer than others...

    :)
     
    Jmu5667 likes this.
  18. Jmu5667

    Jmu5667 Well-Known Member Licensed User

    ;)
     
  19. emexes

    emexes Well-Known Member Licensed User

    Ok, I've got that Scan2 thing going with a Service UUID filter. What I did was look through the advertising data of that device for one of its service UUIDs, and I was (momentarily) disappointed, but then I spotted a 16-bit byte-reversed match for one of the service UUIDs so I gave that a go and now we're in like Flynn.

    This is the list of four services available when connecting to the device:

    1000.000 Connect FF:FF:C0:20:9A:E5
    Discovering services.
    1003.579 Manager_Connected

    00001800-0000-1000-8000-00805f9b34fb
    0000180f-0000-1000-8000-00805f9b34fb
    00001802-0000-1000-8000-00805f9b34fb
    0000ffe0-0000-1000-8000-00805f9b34fb


    and this is the advertising data received when scanning:

    1002.841 Manager_DeviceFound FF:FF:C0:20:9A:E5 iTAG
    Key: 1 = 05
    Key: 10 = 00
    Key: 25 = C103
    Key: 2 = E0FF
    Key: 9 = 69544147202020202020202020202020
    Key: 0 = 020105020A000319C1030302E0FF110969544147202020202020202020202020000000000000000000000000000000000000000000000000000000000000


    and if your eyes are better than mine, then you will immediately spot that the EOFF in advertising data for Key: 0 is a possible match to the ffeo of the last listed service, and so wot I did's:

    Code:
    Dim ScanFilter As List
    ScanFilter.Initialize
    ScanFilter.Add(
    "0000ffe0-0000-1000-8000-00805f9b34fb")
    manager.Scan2(ScanFilter, 
    True)
    and I think we might be on to something here.

    Whilst it's reasonable that a device would not have to advertise *all* of its services, to keep within button-cell energy budgets, it is also reasonable that it should have to advertise at least one of its services. So perhaps go through those 8 service UUIDs of your device, one by one, and try each separately/alone as a filter.

    upload_2019-3-5_0-48-49.png
     
    Jmu5667 likes this.
  20. emexes

    emexes Well-Known Member Licensed User

    Also, I trust this makes up for my beeping brain-fade moment ;-)
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice