Android Question [SOLVED] - Android 10 - Background GPS/Ble scans stop getting data after 1 hr

Jmu5667

Well-Known Member
Licensed User
EDIT #1: This does not work on SAMSUNG phone running API 29+
EDIT #2: See post #12
EDIT #3: There maybe a solution to this, both myself and @OliverA have been working on. Will let you know tommorrow.


Hello All

I have a gps service and a ble service. They run every 5 minutes from a main service which has all the necessary lock and notifications set for the app to run in the back ground. I have the SDK level set to 29 in the manifest with the following permissions:

The app is not in the foreground and the screen is off. When the screen is turned on again data is received from both services.

Both the BLE and GPS do not give any results for their scanning i.e No Beacons found and No GPS NMEA strings. (see logs)

This is a summary as some of the manifest data has special keys provided by some phone manufacturers.
B4X:
' // https://developer.android.com/guide/topics/manifest/uses-feature-element#hw-features
AddManifestText(<uses-feature android:name="android.hardware.bluetooth"/>)
AddManifestText(<uses-feature android:name="android.hardware.bluetooth_le"/>)
AddManifestText(<uses-feature android:name="android.hardware.location.gps"/>)
AddManifestText(<uses-feature android:name="android.hardware.camera"/>)
AddManifestText(<uses-feature android:name="android.hardware.camera.autofocus"/>)
AddManifestText(<uses-feature android:name="android.hardware.camera.flash" />)


AddPermission(android.permission.ACCESS_COARSE_LOCATION)
AddPermission(android.permission.ACCESS_COARSE_UPDATES)
AddPermission(android.permission.ACCESS_BACKGROUND_LOCATION)
AddPermission(android.permission.ACCESS_FINE_LOCATION)

AddPermission(android.permission.ACCESS_NETWORK_STATE)
AddPermission(android.permission.ACCESS_WIFI_STATE)
AddPermission(android.permission.BLUETOOTH)
AddPermission(android.permission.BLUETOOTH_ADMIN)
AddPermission(android.permission.CAMERA)
AddPermission(android.permission.CALL_PHONE)
AddPermission(android.permission.CALL_PRIVILEGED)
AddPermission(android.permission.CHANGE_NETWORK_STATE)
AddPermission(android.permission.CHANGE_WIFI_STATE)
AddPermission(android.permission.FLASHLIGHT)
AddPermission(android.permission.GET_TASKS)
AddPermission(android.permission.INTERNET)

AddPermission(android.permission.MODIFY_PHONE_STATE)
AddPermission(android.permission.MODIFY_AUDIO_SETTINGS)
AddPermission(android.permission.READ_EXTERNAL_STORAGE)
AddPermission(android.permission.READ_PHONE_STATE)
AddPermission(android.permission.READ_SMS)
AddPermission(android.permission.READ_CALL_LOG)
AddPermission(android.permission.RECEIVE_BOOT_COMPLETED)
AddPermission(android.permission.RECEIVE_SMS)
AddPermission(android.permission.SEND_SMS)
AddPermission(android.permission.UPDATE_DEVICE_STATS)
AddPermission(android.permission.VIBRATE)
AddPermission(android.permission.WAKE_LOCK)
AddPermission(android.permission.WRITE_EXTERNAL_STORAGE)
AddPermission(android.permission.WRITE_SECURE_SETTINGS)
AddPermission(android.permission.WRITE_SETTINGS)
AddPermission(android.permission.WRITE_SMS)
AddPermission(android.permission.PROCESS_OUTGOING_CALLS)
AddPermission(android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)


Application log data
B4X:
*** Service (svc_ble) Create ***
01/08/2021 10:12:07.395 - Atlas SOS - svc_ble(), Service_Create
** Service (svc_ble) Start **
01/08/2021 10:12:07.409 - Atlas SOS - svc_ble(), Service_Start
01/08/2021 10:12:07.414 - Atlas SOS - svc_ble(), StartScan, STATE = 12
01/08/2021 10:12:07.426 - Atlas SOS - svc_ble(), Manager_StateChanged, 12 POWERED ON
01/08/2021 10:12:17.428 - Atlas SOS - svc_ble() check_timeout, Scan Time Reached
01/08/2021 10:12:17.444 - Atlas SOS - svc_ble(), process_beacons, SCAN COMPLETE, Beacons Count = 3
01/08/2021 10:12:17.455 - Atlas SOS -  Beacon One - DESK FE:FF:1A:CE:57:B3 Kontakt 56440 1652 -86.0 -12
01/08/2021 10:12:17.478 - Atlas SOS -  Beacon Three - SERVERS E8:E9:11:48:09:76 Kontakt 16563 59525 -89.0 -12
01/08/2021 10:12:17.494 - Atlas SOS -  Beacon One - BOOKSHELF E1:BC:CB:CD:A7:9E Kontakt 61077 34408 -84.0 -12
01/08/2021 10:12:17.512 - Atlas SOS - svc_ble(), BEACONS = 564401652-86-1201656359525-89-1206107734408-84-120
01/08/2021 10:12:17.515 - Atlas SOS - svc_ble(), Created Beacon Packet  WIBD~12021/01/08 10:12:17866599043350697564401652-86-1201656359525-89-1206107734408-84-120
** Service (svc_ble) Destroy **
01/08/2021 10:12:17.519 - Atlas SOS - svc_ble(), Service_Destroy
01/08/2021 10:12:17.521 - Atlas SOS - svc_ble(), Service_Destroy, Next Run @ 10:17:17
01/08/2021 10:12:19.380 - Atlas SOS - svc_service(), tmrServiceHelper_tick, STARTING svc_gps SERVICE
*** Service (svc_gps) Create ***
01/08/2021 10:12:19.412 - Atlas SOS - svc_gps(), Service_Create
** Service (svc_gps) Start **
01/08/2021 10:12:19.419 - Atlas SOS - svc_gps(), Service_Start, GPS timeout set to 10:14:19
01/08/2021 10:12:19.423 - Atlas SOS - svc_gps(), Service_Start, GPS Location Intent android.settings.LOCATION_SOURCE_SETTINGS
01/08/2021 10:12:19.427 - Atlas SOS - svc_gps(), Service_Start, Location Providers Allowed gps,network
01/08/2021 10:12:20.236 - Atlas SOS - **** GPS STARTED ****
01/08/2021 10:12:20.242 - Atlas SOS - svc_gps(), aquire_position, GPS turned ON
01/08/2021 10:12:23.142 - Atlas SOS - svc_gps(),mGps_NMEA, RMC=$GPRMC,101220.00,A,5222.116603,N,00630.413579,W,0.3,297.2,080121,6.3,W,A,V*5F

01/08/2021 10:12:24.132 - Atlas SOS - svc_gps(),mGps_NMEA, RMC=$GPRMC,101221.00,A,5222.117767,N,00630.414598,W,0.0,,080121,6.3,W,A,V*77

01/08/2021 10:12:25.128 - Atlas SOS - svc_gps(),mGps_NMEA, RMC=$GPRMC,101222.00,A,5222.117829,N,00630.414643,W,0.0,,080121,6.3,W,A,V*74

01/08/2021 10:12:26.141 - Atlas SOS - svc_gps(),mGps_NMEA, RMC=$GPRMC,101223.00,A,5222.117995,N,00630.414695,W,0.0,,080121,6.3,W,A,V*78

01/08/2021 10:12:26.144 - Atlas SOS - svc_gps(), end of scheduled run
01/08/2021 10:12:26.150 - Atlas SOS - StopGps
** Service (svc_gps) Destroy **
01/08/2021 10:12:26.261 - Atlas SOS - StopGps
01/08/2021 10:12:26.264 - Atlas SOS - svc_gps(), Service_Destroy
01/08/2021 10:12:26.267 - Atlas SOS - mod_functions(), set_next_gps_update, Main.APPSET.RT_gps.next_update = 10:17:26
01/08/2021 10:12:26.268 - Atlas SOS - svc_gps(), Service_Destroy, Service Callback enabled, 10:17:26
.
. Everything is good so far
.
01/08/2021 11:03:44.147 - Atlas SOS - svc_gps(), Service_Start, GPS timeout set to 11:05:44
01/08/2021 11:03:44.150 - Atlas SOS - svc_gps(), Service_Start, GPS Location Intent android.settings.LOCATION_SOURCE_SETTINGS
01/08/2021 11:03:44.153 - Atlas SOS - svc_gps(), Service_Start, Location Providers Allowed gps,network
01/08/2021 11:03:44.222 - Atlas SOS - **** GPS STARTED ****
01/08/2021 11:03:44.229 - Atlas SOS - svc_gps(), aquire_position, GPS turned ON
01/08/2021 11:03:48.136 - Atlas SOS - svc_gps(),mGps_NMEA, RMC=$GPRMC,110345.00,A,5222.114914,N,00630.412939,W,0.0,,080121,6.3,W,A,V*7C

01/08/2021 11:03:49.145 - Atlas SOS - svc_gps(),mGps_NMEA, RMC=$GPRMC,110346.00,A,5222.114361,N,00630.413258,W,0.0,,080121,6.3,W,A,V*7A

01/08/2021 11:03:50.151 - Atlas SOS - svc_gps(),mGps_NMEA, RMC=$GPRMC,110347.00,A,5222.114454,N,00630.412964,W,0.0,,080121,6.3,W,A,V*7F

01/08/2021 11:03:51.148 - Atlas SOS - svc_gps(),mGps_NMEA, RMC=$GPRMC,110348.00,A,5222.113454,N,00630.412708,W,0.0,,080121,6.3,W,A,V*73

01/08/2021 11:03:51.150 - Atlas SOS - svc_gps(), end of scheduled run
01/08/2021 11:03:51.157 - Atlas SOS - StopGps
** Service (svc_gps) Destroy **
01/08/2021 11:03:51.246 - Atlas SOS - StopGps
01/08/2021 11:03:51.249 - Atlas SOS - svc_gps(), Service_Destroy
01/08/2021 11:03:51.251 - Atlas SOS - mod_functions(), set_next_gps_update, Main.APPSET.RT_gps.next_update = 11:08:51
01/08/2021 11:03:51.253 - Atlas SOS - svc_gps(), Service_Destroy, Service Callback enabled, 11:08:51
*** Service (svc_ble) Create ***
01/08/2021 11:03:52.139 - Atlas SOS - svc_ble(), Service_Create
** Service (svc_ble) Start **
01/08/2021 11:03:52.151 - Atlas SOS - svc_ble(), Service_Start
01/08/2021 11:03:52.156 - Atlas SOS - svc_ble(), StartScan, STATE = 12
01/08/2021 11:03:52.167 - Atlas SOS - svc_ble(), Manager_StateChanged, 12 POWERED ON
01/08/2021 11:04:02.168 - Atlas SOS - svc_ble() check_timeout, Scan Time Reached
01/08/2021 11:04:02.185 - Atlas SOS - svc_ble(), process_beacons, SCAN COMPLETE, Beacons Count = 3
01/08/2021 11:04:02.193 - Atlas SOS -  Beacon One - DESK FE:FF:1A:CE:57:B3 Kontakt 56440 1652 -91.0 -12
01/08/2021 11:04:02.213 - Atlas SOS -  Beacon Three - SERVERS E8:E9:11:48:09:76 Kontakt 16563 59525 -86.0 -12
01/08/2021 11:04:02.237 - Atlas SOS -  Beacon One - BOOKSHELF E1:BC:CB:CD:A7:9E Kontakt 61077 34408 -84.0 -12
01/08/2021 11:04:02.253 - Atlas SOS - svc_ble(), BEACONS = 564401652-91-1201656359525-86-1206107734408-84-120
01/08/2021 11:04:02.254 - Atlas SOS - svc_ble(), Created Beacon Packet  WIBD~12021/01/08 11:04:02866599043350697564401652-91-1201656359525-86-1206107734408-84-120
** Service (svc_ble) Destroy **
01/08/2021 11:04:02.258 - Atlas SOS - svc_ble(), Service_Destroy
01/08/2021 11:04:02.259 - Atlas SOS - svc_ble(), Service_Destroy, Next Run @ 11:09:02
01/08/2021 11:08:52.629 - Atlas SOS - svc_service(), tmrServiceHelper_tick, STARTING svc_gps SERVICE
'
' Now it begins to fail
'
*** Service (svc_gps) Create ***
01/08/2021 11:08:52.653 - Atlas SOS - svc_gps(), Service_Create
** Service (svc_gps) Start **
01/08/2021 11:08:52.657 - Atlas SOS - svc_gps(), Service_Start, GPS timeout set to 11:10:52
01/08/2021 11:08:52.660 - Atlas SOS - svc_gps(), Service_Start, GPS Location Intent android.settings.LOCATION_SOURCE_SETTINGS
01/08/2021 11:08:52.662 - Atlas SOS - svc_gps(), Service_Start, Location Providers Allowed gps,network
01/08/2021 11:08:52.869 - Atlas SOS - **** GPS STARTED ****
01/08/2021 11:08:52.876 - Atlas SOS - svc_gps(), aquire_position, GPS turned ON
*** Service (svc_ble) Create ***
01/08/2021 11:09:02.686 - Atlas SOS - svc_ble(), Service_Create
** Service (svc_ble) Start **
01/08/2021 11:09:02.701 - Atlas SOS - svc_ble(), Service_Start
01/08/2021 11:09:02.706 - Atlas SOS - svc_ble(), StartScan, STATE = 12
01/08/2021 11:09:02.719 - Atlas SOS - svc_ble(), Manager_StateChanged, 12 POWERED ON
01/08/2021 11:09:12.717 - Atlas SOS - svc_ble() check_timeout, Scan Time Reached
01/08/2021 11:09:12.731 - Atlas SOS - svc_ble(), process_beacons, SCAN COMPLETE, Beacons Count = 0
01/08/2021 11:09:12.736 - Atlas SOS - svc_ble(), No Beacons found
01/08/2021 11:09:12.740 - Atlas SOS - svc_ble(), Created Beacon Packet, packet is too old
01/08/2021 11:09:12.743 - Atlas SOS - svc_ble(), Created Beacon Packet  WIBD~12021/01/08 11:09:12866599043350697NOBEACONFIX
** Service (svc_ble) Destroy **
01/08/2021 11:09:12.750 - Atlas SOS - svc_ble(), Service_Destroy
01/08/2021 11:09:12.753 - Atlas SOS - svc_ble(), Service_Destroy, Next Run @ 11:14:12
01/08/2021 11:10:53.107 - Atlas SOS - svc_gps(), perform_timeout, unable To get GPS Fix
01/08/2021 11:10:53.126 - Atlas SOS - StopGps
01/08/2021 11:10:53.134 - Atlas SOS - svc_gps(), perform_timeout, GPS turned OFF
** Service (svc_gps) Destroy **
01/08/2021 11:10:53.141 - Atlas SOS - StopGps
01/08/2021 11:10:53.144 - Atlas SOS - svc_gps(), Service_Destroy
01/08/2021 11:10:53.147 - Atlas SOS - mod_functions(), set_next_gps_update, Main.APPSET.RT_gps.next_update = 11:15:53
01/08/2021 11:10:53.150 - Atlas SOS - svc_gps(), Service_Destroy, Service Callback enabled, 11:15:53
*** Service (svc_ble) Create ***
01/08/2021 11:14:13.308 - Atlas SOS - svc_ble(), Service_Create
** Service (svc_ble) Start **
01/08/2021 11:14:13.319 - Atlas SOS - svc_ble(), Service_Start
01/08/2021 11:14:13.323 - Atlas SOS - svc_ble(), StartScan, STATE = 12
01/08/2021 11:14:13.334 - Atlas SOS - svc_ble(), Manager_StateChanged, 12 POWERED ON
01/08/2021 11:14:23.351 - Atlas SOS - svc_ble() check_timeout, Scan Time Reached
01/08/2021 11:14:23.367 - Atlas SOS - svc_ble(), process_beacons, SCAN COMPLETE, Beacons Count = 0
01/08/2021 11:14:23.374 - Atlas SOS - svc_ble(), No Beacons found
01/08/2021 11:14:23.379 - Atlas SOS - svc_ble(), Created Beacon Packet, packet is too old
01/08/2021 11:14:23.382 - Atlas SOS - svc_ble(), Created Beacon Packet  WIBD~12021/01/08 11:14:23866599043350697NOBEACONFIX
** Service (svc_ble) Destroy **
01/08/2021 11:14:23.388 - Atlas SOS - svc_ble(), Service_Destroy
01/08/2021 11:14:23.391 - Atlas SOS - svc_ble(), Service_Destroy, Next Run @ 11:19:23
01/08/2021 11:15:53.494 - Atlas SOS - svc_service(), tmrServiceHelper_tick, STARTING svc_gps SERVICE
*** Service (svc_gps) Create ***
01/08/2021 11:15:53.524 - Atlas SOS - svc_gps(), Service_Create
** Service (svc_gps) Start **
01/08/2021 11:15:53.529 - Atlas SOS - svc_gps(), Service_Start, GPS timeout set to 11:17:53
01/08/2021 11:15:53.531 - Atlas SOS - svc_gps(), Service_Start, GPS Location Intent android.settings.LOCATION_SOURCE_SETTINGS
01/08/2021 11:15:53.534 - Atlas SOS - svc_gps(), Service_Start, Location Providers Allowed gps,network
01/08/2021 11:15:53.752 - Atlas SOS - **** GPS STARTED ****
01/08/2021 11:15:53.758 - Atlas SOS - svc_gps(), aquire_position, GPS turned ON
'
'
'

The above log data is from an OnePlus 7T but we have had the same results other Android 10 Devices, namely Samsung XCover.

The ble service has the following code for background scanning:

B4X:
Sub Process_Globals()

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

    Dim SCAN_FAILED_ALREADY_STARTED As Int = 1
    Dim SCAN_FAILED_APPLICATION_REGISTRATION_FAILED As Int = 2
    Dim SCAN_FAILED_FEATURE_UNSUPPORTED As Int = 4
    Dim SCAN_FAILED_INTERNAL_ERROR As Int = 3
    Dim SCAN_TIMEOUT As Int = 10

    Dim tmrClock As Timer
    Dim mfinished, scanComplete, restartNow As Boolean
    ' // class's
    Dim ws_sck As cls_sockets
    Dim ca As cls_assets
    Dim comI As mComms
    Dim sf As StringFunctions
    Dim dieNow As Boolean

    Private manager             As BleManager2
    Private Scanner             As JavaObject
    Private ScanCallback         As JavaObject
    Private ManagerJO             As JavaObject
    Private Adapter             As JavaObject

    Dim iBeacons As Map
    Dim bc As ByteConverter

End Sub


Sub Service_Create

   Main.APPSET.RT_iBeacon.next_update = 0

    ' // main data is not available
    If Not(Main.APPSET.IsInitialized) Then
        dieNow = True
        Return
    End If

    mfinished = False
    scanComplete = False

    mod_functions.writelog("svc_ble(), Service_Create")
    Try
        tmrClock.Initialize("tmrClock",1000)
        comI.Initialize
        ca.Initialize
        ws_sck.Initialize(Me,"svc_ble","socket")

        manager.Initialize("manager")
        ManagerJO = manager
        Adapter = ManagerJO.GetField("blueAdapter")
        Scanner = Adapter.RunMethod("getBluetoothLeScanner", Null)
        ScanCallback.InitializeNewInstance(Application.PackageName & ".svc_ble$MyScanCallback", Null)
    Catch
        mod_functions.writelog("svc_ble(), Service_Create, error - " & LastException.Message )
        StopService(Me)
    End Try
  

End Sub
Private Sub ScanWithLeScanner

    Dim ScanSettingsStatic As JavaObject
    ScanSettingsStatic.InitializeStatic("android.bluetooth.le.ScanSettings")

    ' // https://punchthrough.com/android-ble-guide/
    ' // https://developer.android.com/reference/android/bluetooth/le/ScanSettings.Builder
    ' // https://developer.android.com/reference/android/bluetooth/le/ScanSettings#SCAN_MODE_LOW_POWER

    Dim ScanSettingsBuilder As JavaObject
    ScanSettingsBuilder.InitializeNewInstance("android.bluetooth.le.ScanSettings.Builder", Null)

    ' // 2021.01.07 -
    ScanSettingsBuilder.RunMethod("setScanMode", Array(ScanSettingsStatic.GetField("SCAN_MODE_LOW_POWER")))

    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 iBeacon

    Dim Filters As List = Array(ScanFilterBuilder.RunMethod("build", Null))
    Scanner.RunMethod("startScan", Array(Filters, ScanSettingsBuilder.RunMethod("build", Null), ScanCallback))
    comI.scanning = True

End Sub


Private Sub Scan_Failed (Result As Int)

    Dim res As String

    Select Case Result
  
        Case 1
            res = "SCAN_FAILED_ALREADY_STARTED"
        Case 2
            res = "SCAN_FAILED_APPLICATION_REGISTRATION_FAILED"
        Case 3
            res = "SCAN_FAILED_INTERNAL_ERROR"
        Case 4
            res = "SCAN_FAILED_FEATURE_UNSUPPORTED"
    End Select

    mod_functions.writeLog($"svc_ble(), Scan_Failed, ${Result} ${res} "$)

    Dim btm As BluetoothAdmin
    btm.Initialize("")
    btm.Disable

    Main.APPSET.RT_iBeacon.timeout = 0
    scanComplete = True


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 ScanRecord As JavaObject = ScanResult.RunMethod("getScanRecord", Null)
    Dim data() As Byte = ScanRecord.RunMethod("getManufacturerSpecificData", Array(76)) '76 = apple id
  
    If data <> Null Then
  
        Try
            Private bc As ByteConverter
            Dim raf As RandomAccessFile
            Dim ib As mBeacon
            raf.Initialize3(data, False)
            ' // load beacons props
            ib.Initialize
            ib.name = ScanRecord.RunMethod("getDeviceName",Null)
            ib.uniqueid = address
            ib.major =  Bit.And(0xFFFF,raf.ReadShort(18))
            ib.minor =  Bit.And(0xFFFF,raf.ReadShort(20))
            ib.rssi = ScanResult.RunMethod("getRssi", Null)
            ib.TX = ScanRecord.RunMethod("getTxPowerLevel",Null)
            ' // https://www.b4x.com/android/forum/threads/iot-beaconparser-discover-ibeacons-and-eddystone-beacons.61127/post-450458
            ib.distance = CalculateDistance(ib.tx, ib.rssi)
            ib.time = DateTime.Now
            iBeacons.Put(ib.uniqueid, ib)
        Catch
            'mod_functions.writelog($"Scan_Result, Error ${LastException.Message}"$)
            'mod_functions.writelog(ScanRecord.RunMethod("toString", Null))
        End Try  
        'Log($" ${ib.uniqueid} ${ib.major} ${ib.minor} ${ib.rssi} ${ib.TX} "$)
  
    End If

End Sub


#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) { 
       processBA.raiseEvent(this, "scan_failed", errorCode);
    }
}
#End If


I am not sure what is going on, so any help would be appreciated. This is an SOS app and is currently used by thousands' of users and this problem will prevent it from doing is job, protecting people.

Regards

John.
 
Last edited:

Jmu5667

Well-Known Member
Licensed User
Added to manifest:

B4X:
SetServiceAttribute(svc_ble, android:foregroundServiceType, "location")
SetServiceAttribute(svc_gps, android:foregroundServiceType, "location")

Seems good so far !
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
I left my one plus 7 (api29) running over night and I was successful with both GPS and BLE services getting NMEA and Beacons. The services are run every 5 minutes and are both launched by my main background service (svc_service). To achieve this both the GPS and BLE services create their own notification icon and described in the Google docs. I am expecting delivery of a Samsung XCover device (API 29) and will try it on that, as that is the device that a new customer is using.

I will close this thread after the Samsung test.
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
It won't matter.

Keeping BLE working in the background will be difficult and likely unreliable.

The background location example does run fine on many devices, while in the background.

The BLE service runs every 5 minutes and does a scan for no more then 10 seconds, then the service is terminated.
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Here are the unfiltered logs from a brand new Samsung xcover 4S (API29). The log info show the start of my ble service to the end of the services run. Please not the screen is off, so this is proper background ble scan. The same service work fine on other device with the same API level.

B4X:
*** Service (svc_ble) Create ***
01/13/2021 11:46:50.260 - Atlas SOS - svc_ble(), Service_Create
STATE_ON
** Service (svc_ble) Start **
isStatusBarNotificationAllowedAsUser: packageName = com.is.vitllinkSOS,userId = 0
getContainerInfo: value is
isStatusBarNotificationAllowedAsUser: packageName = com.is.vitllinkSOS,userId = 0
getContainerInfo: value is
isStatusBarNotificationAllowedAsUser: packageName = com.is.vitllinkSOS,userId = 0
getContainerInfo: value is
isStatusBarNotificationAllowedAsUser: packageName = com.is.vitllinkSOS,userId = 0
getContainerInfo: value is
01/13/2021 11:46:50.342 - Atlas SOS - svc_ble(), Service_Start
01/13/2021 11:46:50.362 - Atlas SOS - svc_ble(), StartScan, STATE = 12
SFWD update time=1509214775072
STATE_ON
STATE_ON
Start Scan with callback
add() - appUid: 10225, appName: com.is.vitllinkSOS
[INFO:gatt_api.cc(953)] GATT_Register 4d8e26af-d0f4-440c-b0ca-3c00aa8e958a
[INFO:gatt_api.cc(990)] allocated gatt_if=7
onScannerRegistered() - status=0 scannerId=7 mScannerId=0
STATE_ON
setExpandState() isExpand = true, mLockscreenPageState = EXPAND, notificationCount = 0, mNotificationCount = 0
01/13/2021 11:46:50.411 - Atlas SOS - svc_ble(), Manager_StateChanged, 12 POWERED ON
STATE_ON
Cannot start unfiltered scan in screen-off. This scan will be resumed later: 7
getCallState - callingPid : 17348 / processName : sts
0|com.is.vitllinkSOS|1966|null|10225: granting content://settings/system/notification_sound
onNotificationPosted : com.is.vitllinkSOS number : 1966 listener : null
shouldBeFilteredOut : com.is.vitllinkSOS missingTitleAndText : false isGroupHeader : false
onNotificationPosted : com.is.vitllinkSOS number : 1966 listener : null
shouldBeFilteredOut : com.is.vitllinkSOS missingTitleAndText : false isGroupHeader : false
Notification for foreground service is posted, 0|com.is.vitllinkSOS|1966|null|10225
setExpandState() isExpand = true, mLockscreenPageState = EXPAND, notificationCount = 0, mNotificationCount = 0
uid=1000 system_server identical 3 lines
0|com.is.vitllinkSOS|1966|null|10225: granting content://settings/system/notification_sound
!@ 179,0 r 77868 4394322 w 18333 377672 d 1565 180944 f 2743 6644 iot 50432 40355 th 51200 0 0 pt 0 inp 0 0 1509.635
getCallState - callingPid : 17348 / processName : sts
uid=10058(com.android.systemui) identical 1 line
setExpandState() isExpand = true, mLockscreenPageState = EXPAND, notificationCount = 0, mNotificationCount = 0
onSignalStrengthsChanged signalStrength=SignalStrength:{mCdma=Invalid,mGsm=Invalid,mWcdma=CellSignalStrengthWcdma: ss=-97 ber=99 rscp=-89 ecno=0 level=2,mTdscdma=Invalid,mLte=Invalid,mNr=Invalid,SignalBarInfo{ wcdmaLevel=3 },P,rat=3,primary=CellSignalStrengthWcdma} level=3
getMobileIconGroup(): 0
getCallState - callingPid : 17348 / processName : sts
!@Sync 50 [2021-01-13 11:46:54.404] FD count : 524, wdog_way : softdog
Sending ACTION_BATTERY_CHANGED. scale:100, info:{.chargerAcOnline = false, .chargerUsbOnline = true, .chargerWirelessOnline = false, .maxChargingCurrent = 0, .maxChargingVoltage = 0, .batteryStatus = CHARGING, .batteryHealth = GOOD, .batteryPresent = true, .batteryLevel = 53, .batteryVoltage = 4009, .batteryTemperature = 223, .batteryCurrent = 0, .batteryCycleCount = 0, .batteryFullCharge = 3000000, .batteryChargeCounter = 1500800, .batteryTechnology = Li-ion}
online:4, current avg:495, charge type:1, POGO powered:false, power sharing:false, high voltage charger:false, charger_type:0, capacity:280000, misc_event:0, current_event:0, current_now:506
stay LED for charging
Plugged
  mCableConnection= 1
set cable connected : mGripEnabled = false
ACTION_BATTERY_CHANGED - Level=53, status=2
received broadcast android.intent.action.BATTERY_CHANGED
handleBatteryUpdate
received ACTION_BATTERY_CHANGED
Intent : android.intent.action.BATTERY_CHANGED
handleMessage -> MSG_UPDATE_CHARGING_STATE: mUsbCharging=true
updateUsbNotification(false): mConnected=true mConfigured=true mCurrentFunctions=mtp,adb mHostConnected=false mSourcePower=false mSinkPower=true mUsbCharging=true mUseUsbNotification=true
Set mCurrentFunctionsForNoti=mtp
priorPlugType = 2 mPlugType = 2 priorBatteryStatus = 2 mBatteryStatus = 2
isDexModeOn() : false
isSemiDexModeOn() : false
id=27 mUsbNotificationId=27
Intent : android.intent.action.BATTERY_CHANGED
showChargingNotice oldChargingType : 1 currentChargingType : 1 oldChargingTime : -1 mChargingTime : -1
There is no change about charging status, so return!
Battery swelling mode - priorBatterySwellingMode = 0 mBatterySwellingMode = 0 mBatteryStatus = 2
getDisplayHeight portrait? true  displayHeight= 1280
01/13/2021 11:46:55.362 - Atlas SOS - svc_ble() check_timeout, Scan Time Reached
STATE_ON
Stop Scan with callback
remove() - id: 7
remove() - removed: 7
01/13/2021 11:46:55.382 - Atlas SOS - svc_ble(), process_beacons, SCAN COMPLETE, Beacons Count = 0
[GSIM LOG]: gsimLogHandler, msg: MESSAGE_SCAN_STOP, appName: com.is.vitllinkSOS, scannerId: 7, reportDelayMillis=0
01/13/2021 11:46:55.393 - Atlas SOS - svc_ble(), No Beacons found
01/13/2021 11:46:55.403 - Atlas SOS - svc_ble(), Created Beacon Packet, packet is too old
01/13/2021 11:46:55.412 - Atlas SOS - svc_ble(), Created Beacon Packet  WIBD~12021/01/13 11:46:55355523116710742NOBEACONFIX
setExpandState() isExpand = true, mLockscreenPageState = EXPAND, notificationCount = 0, mNotificationCount = 0
** Service (svc_ble) Destroy **

You will notice the message at line 27. It's rather confusing since a filtered scan was created for this.

I hope this information is of help to anyone battling with a Samsung Device API29+. The solution we came up with was to turn the screen on. just before the scan.

Regards

John.
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Ok, here is the update, it seems to be working.

Here the is updated scannerLe code:

B4X:
Private Sub ScanWithLeScanner
    
    Dim ScanSettingsStatic As JavaObject
    ScanSettingsStatic.InitializeStatic("android.bluetooth.le.ScanSettings")
    
    ' // https://punchthrough.com/android-ble-guide/
    ' // https://developer.android.com/reference/android/bluetooth/le/ScanSettings.Builder
    ' // https://developer.android.com/reference/android/bluetooth/le/ScanSettings#SCAN_MODE_LOW_POWER
    
    Dim ScanSettingsBuilder As JavaObject
    ScanSettingsBuilder.InitializeNewInstance("android.bluetooth.le.ScanSettings.Builder", Null)
    
    ' // 2021.01.07 - 
    ScanSettingsBuilder.RunMethod("setScanMode", Array(ScanSettingsStatic.GetField("SCAN_MODE_LOW_POWER")))
    
    Dim ScanFilterStatic As JavaObject
    ScanFilterStatic.InitializeStatic("android.bluetooth.le.ScanFilter")
    
    ' // set the scan filter for iBeacons
    Dim ScanFilterBuilder1 As JavaObject
    ScanFilterBuilder1.InitializeNewInstance("android.bluetooth.le.ScanFilter.Builder", Null)
    ScanFilterBuilder1.RunMethod("setManufacturerData", Array(76,Array As Byte())) 'Apple ID
    
                                
    Dim Filters As List = Array(ScanFilterBuilder1.RunMethod("build", Null))
    If Filters.Size > 0 Then
        Dim aScanFilterJO As JavaObject = Filters.Get(0)
        mod_functions.writelog($"svc_ble::ScanWithLeScanner, Filter=${aScanFilterJO.RunMethod("toString", Null)}"$)
    End If
    Scanner.RunMethod("startScan", Array(Filters, ScanSettingsBuilder.RunMethod("build", Null), ScanCallback))
    comI.scanning = True
    
End Sub

The solution seems be this:
B4X:
ScanFilterBuilder1.RunMethod("setManufacturerData", Array(76,Array As Byte())) 'Apple ID

not this:
B4X:
ScanFilterBuilder1.RunMethod("setManufacturerData", Array(76,Null)) 'Apple ID

when using setManufacturerData set the setManufacturerData second parameter to an empty byte array not NULL as you may have seen in other posts. Much credit goes to
@OliverA for discovering this.

Hope this is of help to others

Regards

John.
 
Upvote 0

mike1967

Member
Licensed User
Ok, here is the update, it seems to be working.

Here the is updated scannerLe code:

B4X:
Private Sub ScanWithLeScanner
   
    Dim ScanSettingsStatic As JavaObject
    ScanSettingsStatic.InitializeStatic("android.bluetooth.le.ScanSettings")
   
    ' // https://punchthrough.com/android-ble-guide/
    ' // https://developer.android.com/reference/android/bluetooth/le/ScanSettings.Builder
    ' // https://developer.android.com/reference/android/bluetooth/le/ScanSettings#SCAN_MODE_LOW_POWER
   
    Dim ScanSettingsBuilder As JavaObject
    ScanSettingsBuilder.InitializeNewInstance("android.bluetooth.le.ScanSettings.Builder", Null)
   
    ' // 2021.01.07 -
    ScanSettingsBuilder.RunMethod("setScanMode", Array(ScanSettingsStatic.GetField("SCAN_MODE_LOW_POWER")))
   
    Dim ScanFilterStatic As JavaObject
    ScanFilterStatic.InitializeStatic("android.bluetooth.le.ScanFilter")
   
    ' // set the scan filter for iBeacons
    Dim ScanFilterBuilder1 As JavaObject
    ScanFilterBuilder1.InitializeNewInstance("android.bluetooth.le.ScanFilter.Builder", Null)
    ScanFilterBuilder1.RunMethod("setManufacturerData", Array(76,Array As Byte())) 'Apple ID
   
                               
    Dim Filters As List = Array(ScanFilterBuilder1.RunMethod("build", Null))
    If Filters.Size > 0 Then
        Dim aScanFilterJO As JavaObject = Filters.Get(0)
        mod_functions.writelog($"svc_ble::ScanWithLeScanner, Filter=${aScanFilterJO.RunMethod("toString", Null)}"$)
    End If
    Scanner.RunMethod("startScan", Array(Filters, ScanSettingsBuilder.RunMethod("build", Null), ScanCallback))
    comI.scanning = True
   
End Sub

The solution seems be this:
B4X:
ScanFilterBuilder1.RunMethod("setManufacturerData", Array(76,Array As Byte())) 'Apple ID

not this:
B4X:
ScanFilterBuilder1.RunMethod("setManufacturerData", Array(76,Null)) 'Apple ID

when using setManufacturerData set the setManufacturerData second parameter to an empty byte array not NULL as you may have seen in other posts. Much credit goes to
@OliverA for discovering this.

Hope this is of help to others

Regards

John.

Hello, i also try to create a service in order to scan beacon also in background and in doze mode. I tri out your code but there are some reference library and class thath i dont know resolve. Please can you provide me a sample project in order to make that with the library and class reference ? Please help me, thanks in advance
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Hello, i also try to create a service in order to scan beacon also in background and in doze mode. I tri out your code but there are some reference library and class thath i dont know resolve. Please can you provide me a sample project in order to make that with the library and class reference ? Please help me, thanks in advance
Can you post the error logs please
 
Upvote 0

mike1967

Member
Licensed User
Can you post the error logs please
Please can provide me sample projects in order to Work ? I dont know hot to use this code, on wich ble example is based ? If yo cannot provide me sample projects can give me the link ? Where i fond cls_sockets,mComms and cls_assets class ? Thanks in advance
 
Last edited:
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Please can provide me sample projects in order to Work ? I dont know hot to use this code, on wich ble example is based ? If yo cannot provide me sample projects can give me the link ? Where i fond cls_sockets,mComms and cls_assets class ? Thanks in advance
Will post tomorrow morning
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
put this code in a module
B4X:
Type mBeacon (uniqueid As String, name As String, uuid As String, _
                    minor As Int, major As Int, TX As Int, battery As Int, _
                    rssi As Double, distance As Double, TIME As Long, knowBeacon As Boolean)

put this code in a service
B4X:
' // IMPORTANT
' // https://stackoverflow.com/questions/50840378/how-to-scan-and-connect-to-ibeacon-using-ble-services-in-the-background/50841523#50841523
' // https://stackoverflow.com/questions/58428763/android-10-not-working-with-ble-bluetooth-scanning

' // https://developer.android.com/guide/components/foreground-services **
' // https://developer.android.com/reference/android/bluetooth/le/ScanFilter.Builder#setManufacturerData(int,%20byte[])
' // https://developer.android.com/reference/android/bluetooth/le/ScanSettings
' // https://support.kontakt.io/hc/en-gb/articles/201492492-iBeacon-advertising-packet-structure
' // https://github.com/NordicSemiconductor/Android-Scanner-Compat-Library/blob/master/scanner/src/main/java/no/nordicsemi/android/support/v18/scanner/ScanSettings.java
' // https://github.com/AltBeacon/android-beacon-library/pull/936 **

' // https://www.b4x.com/android/forum/threads/ble-android-9-scanning-stops-when-screen-turned-off.103249/#content
' // https://www.b4x.com/android/forum/threads/iot-beaconparser-discover-ibeacons-and-eddystone-beacons.61127/#content
' // https://www.b4x.com/android/forum/threads/ble-android-8-1-and-higher.113180/#post-706362
' // https://www.b4x.com/android/forum/threads/ble-scansettings.94908/#post-600231
' // https://www.b4x.com/android/forum/threads/background-task-with-blemanager2-and-beacon.117707/#content
' // https://www.b4x.com/android/forum/threads/ble-scansettings.94908/
' // https://www.b4x.com/android/forum/threads/background-location-tracking.99873/
' // https://www.b4x.com/android/forum/threads/android-10-background-gps-ble-scans-stop-getting-data-after-1-hr.126303/

Sub Process_Globals()

    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
   
    Dim SCAN_FAILED_ALREADY_STARTED As Int = 1
    Dim SCAN_FAILED_APPLICATION_REGISTRATION_FAILED As Int = 2
    Dim SCAN_FAILED_FEATURE_UNSUPPORTED As Int = 4
    Dim SCAN_FAILED_INTERNAL_ERROR As Int = 3

    Dim tmrClock As Timer   
    Dim mfinished, scanComplete, restartNow As Boolean   
    Dim dieNow         As Boolean
   
    Private manager             As BleManager2
    Private Scanner             As JavaObject
    Private ScanCallback         As JavaObject
    Private ManagerJO             As JavaObject
    Private Adapter             As JavaObject
   
    Dim iBeacons As Map
   
    Private nID As Int = 1966
    Private n As Notification
   
    Private btm         As BluetoothAdmin
    Private pwAlive        As Boolean
    Private pw            As PhoneWakeState
    private scanTimeOut As long
   
End Sub

Sub Service_Create

    Service.AutomaticForegroundMode=Service.AUTOMATIC_FOREGROUND_NEVER
   
   
    If Not(btm.IsInitialized) Then
        btm.Initialize("")       
    End If
   
    Try
        ' // https://www.b4x.com/android/forum/threads/isinitialized-for-blemanager2.126591/#content
        If Not(manager.IsInitialized) Then
            manager.Initialize("manager")
        End If
        ' // 2021.04.18
        ManagerJO = manager
        Adapter = ManagerJO.GetField("blueAdapter")
        Scanner = Adapter.RunMethod("getBluetoothLeScanner", Null)
        ScanCallback.InitializeNewInstance(Application.PackageName & ".svc_ble$MyScanCallback", Null)
       
    Catch       
        log($"svc_ble::Service_Create, manager.IsInitialized, error - ${LastException.Message}"$ )
    End Try       
   
    mfinished = False
    scanComplete = False

    tmrClock.Initialize("tmrClock",1000)
    tmrStart.Initialize("tmrStart",1000)       
   
End Sub

Sub Service_Start (StartingIntent As Intent)

    Service.StartForeground(nID,CreateNotification("Atlas SOS","BLE Scan in progress","ic_bluetooth_searching_white_48dp",Main,False,False,n,nID))
   
    pw.KeepAlive(True)
    pwAlive = True
    ToastMessageShow("BLE Scan Started",False)
       
   
    If Not(btm.IsEnabled) Then
        btm.Enable
    End If
       
    ' // 10 seconds - YOU CAN CHANGE THIS
    scanTimeOut = DateTime.Now + (DateTime.TicksPerSecond * 10)
    iBeacons.Initialize   
    tmrClock.Enabled = True
    StartScan
       
End Sub

Sub Service_Destroy
   
    Service.stopForeground(nID)
   
    If pwAlive Then
        pw.releaseKeepAlive       
    End If
       
    mfinished = False
    scanComplete = False
    restartNow = False
   
End Sub


Sub tmrClock_tick

    check_timeout

    ' // we are done
    If scanComplete Then
        mfinished = True
    End If
   
    ' // we are done
    If mfinished Then
        tmrClock.Enabled = False
        StopService(Me)
    End If
   
End Sub

Sub check_timeout
   
    Try
        ' // we need to check a timeout here, if we timeout then restart the WIFI service
        If scanTimeOut < DateTime.Now Then           
            ' // stop the ble scan
            Scanner.RunMethod("stopScan", Array(ScanCallback))
            manager.StopScan
            manager.Disconnect
            ' // process beacond found
            process_beacons
            scanComplete = True
            mfinished = True
        End If
    Catch
        scanComplete = True
        mfinished = True
        mod_functions.writelog("svc_ble() check_timeout, error - " & LastException.Message)
    End Try
   
End Sub

Sub process_beacons()
   
    log($"svc_ble::process_beacons, SCAN COMPLETE, Beacons Count = ${iBeacons.Size}"$)
    ' // Got Beacons
    If iBeacons.Size > 0 Then           
        ' // process the beason list
        For Each k As String In iBeacons.Keys
           
            Dim bcn As mBeacon = iBeacons.Get(k)
                       
            log($"${bcn.uniqueid} ${bcn.name} ${bcn.Major} ${bcn.Minor} ${bcn.rssi} ${bcn.TX}"$)
           
           
        Next
       
    Else
        log("svc_ble::No Beacons found " )       
    End If
       
End Sub


Sub StartScan
   
    scanComplete = False
    ' // start ble backgrouns scanning   
    ScanWithLeScanner
   
End Sub

Sub Manager_StateChanged (State As Int)
   
    Dim currentStateText As String
   
    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
   
    Log($"svc_ble::Manager_StateChanged, ${State} ${currentStateText} "$)
   
   
End Sub

Private Sub ScanWithLeScanner
  
   
    Try
        Dim ScanSettingsStatic As JavaObject
        ScanSettingsStatic.InitializeStatic("android.bluetooth.le.ScanSettings")
       
        ' // https://punchthrough.com/android-ble-guide/
        ' // https://developer.android.com/reference/android/bluetooth/le/ScanSettings.Builder
        ' // https://developer.android.com/reference/android/bluetooth/le/ScanSettings#SCAN_MODE_LOW_POWER
       
        Dim ScanSettingsBuilder As JavaObject
        ScanSettingsBuilder.InitializeNewInstance("android.bluetooth.le.ScanSettings.Builder", Null)
       
        ' // 2021.01.07 -
        ScanSettingsBuilder.RunMethod("setScanMode", Array(ScanSettingsStatic.GetField("SCAN_MODE_LOW_POWER")))
       
        Dim ScanFilterStatic As JavaObject
        ScanFilterStatic.InitializeStatic("android.bluetooth.le.ScanFilter")
       
        ' // set the scan filter for iBeacons
        Dim ScanFilterBuilder1 As JavaObject
        ScanFilterBuilder1.InitializeNewInstance("android.bluetooth.le.ScanFilter.Builder", Null)
        ScanFilterBuilder1.RunMethod("setManufacturerData", Array(76,Array As Byte())) 'Apple ID
                                           
        Dim Filters As List = Array(ScanFilterBuilder1.RunMethod("build", Null))
        If Filters.Size > 0 Then
            Dim aScanFilterJO As JavaObject = Filters.Get(0)
            log($"svc_ble::ScanWithLeScanner, Filter=${aScanFilterJO.RunMethod("toString", Null)}"$)
        End If
        Scanner.RunMethod("startScan", Array(Filters, ScanSettingsBuilder.RunMethod("build", Null), ScanCallback))       
    Catch
        log($"svc_ble::ScanWithLeScanner, error=${LastException.Message}"$)       
        scanComplete = True
    End Try
       
End Sub


Private Sub Scan_Failed (Result As Int)
   
    Dim res As String
   
    Select Case Result
       
        Case 1
            res = "SCAN_FAILED_ALREADY_STARTED"
        Case 2
            res = "SCAN_FAILED_APPLICATION_REGISTRATION_FAILED"
        Case 3
            res = "SCAN_FAILED_INTERNAL_ERROR"
        Case 4
            res = "SCAN_FAILED_FEATURE_UNSUPPORTED"
    End Select
   
    mod_functions.writeLog($"svc_ble::Scan_Failed, ${Result} ${res} "$)
   
    Dim btm As BluetoothAdmin
    btm.Initialize("")
    btm.Disable
    scanComplete = True
   
   
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 ScanRecord As JavaObject = ScanResult.RunMethod("getScanRecord", Null)   
    Dim data() As Byte = ScanRecord.RunMethod("getManufacturerSpecificData", Array(76)) '76 = apple id
       
    If data <> Null Then
       
        Try
            Private bc As ByteConverter
            Dim raf As RandomAccessFile
            Dim ib As mBeacon
            raf.Initialize3(data, False)
            ' // load beacons props
            ib.Initialize
            ib.name = ScanRecord.RunMethod("getDeviceName",Null)
            ib.uniqueid = address
            ib.major =  Bit.And(0xFFFF,raf.ReadShort(18))
            ib.minor =  Bit.And(0xFFFF,raf.ReadShort(20))
            ib.rssi = ScanResult.RunMethod("getRssi", Null)
            ib.tx = ScanRecord.RunMethod("getTxPowerLevel",Null)
                       
            ' // https://www.b4x.com/android/forum/threads/iot-beaconparser-discover-ibeacons-and-eddystone-beacons.61127/post-450458
            ib.distance = CalculateDistance(ib.tx, ib.rssi)
            ib.time = DateTime.Now
            iBeacons.Put(ib.uniqueid, ib)
            Log($"${DateTime.Time(ib.time)} - ${ib.name} ${ib.uniqueid} ${ib.tx} ${ib.rssi} ${ib.distance} "$)
        Catch
            log($"Scan_Result, Error ${LastException.Message}"$)
            log(ScanRecord.RunMethod("toString", Null))
        End Try       
               
    End If
   
End Sub

Sub CalculateDistance(txPower As Int, rssi As Double) As Double
 
    Dim ratio As Double, tx As Int
       
    If txPower = -12 Then
        tx = -77
    Else
        tx = txPower
    End If

    If (rssi = 0) Then
        Return -1.0
    End If

    ratio = rssi*1.0/tx

    If (ratio < 1.0) Then
        Return Round2(Power(ratio,10),2)
    Else
        Return Round2((0.89976) * Power(ratio,7.7095) + 0.111,2)
    End If
   
   
End Sub

Private Sub CreateNotification(Title As String, Content As String, Icon As String, TargetActivity As Object, _
                                    Sound As Boolean, Vibrate As Boolean, pN As Notification,pNID As Int) As Notification
   
   
    Dim p As Phone
   
   
    If p.SdkVersion >= 21 Then
        Dim nb As NotificationBuilder
        Dim Channel As NotificationChannelBuilder
        Dim ChannelID As String = "ies_atlas_sos_ble_scan"
        Dim ChannelName As String = "Atlas SOS Ble Scan"
       
        ' // Build a Channel
   
        If Channel.ChannelsSupported Then
            Channel.Initialize(ChannelID, ChannelName, Channel.IMPORTANCE_LOW)
            Channel.Build
        End If
       
        nb.Initialize(ChannelID)
        nb.AutoCancel = False
        nb.OnGoingEvent = True
        nb.DefaultSound = Sound
        nb.DefaultVibrate = Vibrate
        nb.DefaultLight = False
        nb.ContentTitle = Title
        nb.ContentText = Content
        nb.setActivity(TargetActivity)
        nb.SmallIcon = Icon
        nb.Number = pNID
        ' //set the return object for the notification object (n1) in this service
        pN = nb.GetNotification
    Else
        pN.Initialize
        pN.Number = pNID
        pN.Light = False
        pN.Vibrate = Vibrate
        pN.Sound = Sound
        pN.OnGoingEvent = True
        pN.Icon = Icon
        pN.SetInfo(Title, Content, TargetActivity)
    End If
    pN.Notify(pNID)
    Return pN
   
End Sub
#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) {      
       processBA.raiseEvent(this, "scan_failed", errorCode);
    }
}
#End If

The above service code is a stripped down version of what our app uses. I have not tested the above code, you can do this and it should work. I strongly suggest that you read all the links in the code. If you are developing an app for commerical use and plan to sell it, you need to fully understand what the above code does and do some futher research.

Best of luck.

John.
 
Upvote 0

mike1967

Member
Licensed User
put this code in a module
B4X:
Type mBeacon (uniqueid As String, name As String, uuid As String, _
                    minor As Int, major As Int, TX As Int, battery As Int, _
                    rssi As Double, distance As Double, TIME As Long, knowBeacon As Boolean)

put this code in a service
B4X:
' // IMPORTANT
' // https://stackoverflow.com/questions/50840378/how-to-scan-and-connect-to-ibeacon-using-ble-services-in-the-background/50841523#50841523
' // https://stackoverflow.com/questions/58428763/android-10-not-working-with-ble-bluetooth-scanning

' // https://developer.android.com/guide/components/foreground-services **
' // https://developer.android.com/reference/android/bluetooth/le/ScanFilter.Builder#setManufacturerData(int,%20byte[])
' // https://developer.android.com/reference/android/bluetooth/le/ScanSettings
' // https://support.kontakt.io/hc/en-gb/articles/201492492-iBeacon-advertising-packet-structure
' // https://github.com/NordicSemiconductor/Android-Scanner-Compat-Library/blob/master/scanner/src/main/java/no/nordicsemi/android/support/v18/scanner/ScanSettings.java
' // https://github.com/AltBeacon/android-beacon-library/pull/936 **

' // https://www.b4x.com/android/forum/threads/ble-android-9-scanning-stops-when-screen-turned-off.103249/#content
' // https://www.b4x.com/android/forum/threads/iot-beaconparser-discover-ibeacons-and-eddystone-beacons.61127/#content
' // https://www.b4x.com/android/forum/threads/ble-android-8-1-and-higher.113180/#post-706362
' // https://www.b4x.com/android/forum/threads/ble-scansettings.94908/#post-600231
' // https://www.b4x.com/android/forum/threads/background-task-with-blemanager2-and-beacon.117707/#content
' // https://www.b4x.com/android/forum/threads/ble-scansettings.94908/
' // https://www.b4x.com/android/forum/threads/background-location-tracking.99873/
' // https://www.b4x.com/android/forum/threads/android-10-background-gps-ble-scans-stop-getting-data-after-1-hr.126303/

Sub Process_Globals()

    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
  
    Dim SCAN_FAILED_ALREADY_STARTED As Int = 1
    Dim SCAN_FAILED_APPLICATION_REGISTRATION_FAILED As Int = 2
    Dim SCAN_FAILED_FEATURE_UNSUPPORTED As Int = 4
    Dim SCAN_FAILED_INTERNAL_ERROR As Int = 3

    Dim tmrClock As Timer  
    Dim mfinished, scanComplete, restartNow As Boolean  
    Dim dieNow         As Boolean
  
    Private manager             As BleManager2
    Private Scanner             As JavaObject
    Private ScanCallback         As JavaObject
    Private ManagerJO             As JavaObject
    Private Adapter             As JavaObject
  
    Dim iBeacons As Map
  
    Private nID As Int = 1966
    Private n As Notification
  
    Private btm         As BluetoothAdmin
    Private pwAlive        As Boolean
    Private pw            As PhoneWakeState
    private scanTimeOut As long
  
End Sub

Sub Service_Create

    Service.AutomaticForegroundMode=Service.AUTOMATIC_FOREGROUND_NEVER
  
  
    If Not(btm.IsInitialized) Then
        btm.Initialize("")      
    End If
  
    Try
        ' // https://www.b4x.com/android/forum/threads/isinitialized-for-blemanager2.126591/#content
        If Not(manager.IsInitialized) Then
            manager.Initialize("manager")
        End If
        ' // 2021.04.18
        ManagerJO = manager
        Adapter = ManagerJO.GetField("blueAdapter")
        Scanner = Adapter.RunMethod("getBluetoothLeScanner", Null)
        ScanCallback.InitializeNewInstance(Application.PackageName & ".svc_ble$MyScanCallback", Null)
      
    Catch      
        log($"svc_ble::Service_Create, manager.IsInitialized, error - ${LastException.Message}"$ )
    End Try      
  
    mfinished = False
    scanComplete = False

    tmrClock.Initialize("tmrClock",1000)
    tmrStart.Initialize("tmrStart",1000)      
  
End Sub

Sub Service_Start (StartingIntent As Intent)

    Service.StartForeground(nID,CreateNotification("Atlas SOS","BLE Scan in progress","ic_bluetooth_searching_white_48dp",Main,False,False,n,nID))
  
    pw.KeepAlive(True)
    pwAlive = True
    ToastMessageShow("BLE Scan Started",False)
      
  
    If Not(btm.IsEnabled) Then
        btm.Enable
    End If
      
    ' // 10 seconds - YOU CAN CHANGE THIS
    scanTimeOut = DateTime.Now + (DateTime.TicksPerSecond * 10)
    iBeacons.Initialize  
    tmrClock.Enabled = True
    StartScan
      
End Sub

Sub Service_Destroy
  
    Service.stopForeground(nID)
  
    If pwAlive Then
        pw.releaseKeepAlive      
    End If
      
    mfinished = False
    scanComplete = False
    restartNow = False
  
End Sub


Sub tmrClock_tick

    check_timeout

    ' // we are done
    If scanComplete Then
        mfinished = True
    End If
  
    ' // we are done
    If mfinished Then
        tmrClock.Enabled = False
        StopService(Me)
    End If
  
End Sub

Sub check_timeout
  
    Try
        ' // we need to check a timeout here, if we timeout then restart the WIFI service
        If scanTimeOut < DateTime.Now Then          
            ' // stop the ble scan
            Scanner.RunMethod("stopScan", Array(ScanCallback))
            manager.StopScan
            manager.Disconnect
            ' // process beacond found
            process_beacons
            scanComplete = True
            mfinished = True
        End If
    Catch
        scanComplete = True
        mfinished = True
        mod_functions.writelog("svc_ble() check_timeout, error - " & LastException.Message)
    End Try
  
End Sub

Sub process_beacons()
  
    log($"svc_ble::process_beacons, SCAN COMPLETE, Beacons Count = ${iBeacons.Size}"$)
    ' // Got Beacons
    If iBeacons.Size > 0 Then          
        ' // process the beason list
        For Each k As String In iBeacons.Keys
          
            Dim bcn As mBeacon = iBeacons.Get(k)
                      
            log($"${bcn.uniqueid} ${bcn.name} ${bcn.Major} ${bcn.Minor} ${bcn.rssi} ${bcn.TX}"$)
          
          
        Next
      
    Else
        log("svc_ble::No Beacons found " )      
    End If
      
End Sub


Sub StartScan
  
    scanComplete = False
    ' // start ble backgrouns scanning  
    ScanWithLeScanner
  
End Sub

Sub Manager_StateChanged (State As Int)
  
    Dim currentStateText As String
  
    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
  
    Log($"svc_ble::Manager_StateChanged, ${State} ${currentStateText} "$)
  
  
End Sub

Private Sub ScanWithLeScanner
 
  
    Try
        Dim ScanSettingsStatic As JavaObject
        ScanSettingsStatic.InitializeStatic("android.bluetooth.le.ScanSettings")
      
        ' // https://punchthrough.com/android-ble-guide/
        ' // https://developer.android.com/reference/android/bluetooth/le/ScanSettings.Builder
        ' // https://developer.android.com/reference/android/bluetooth/le/ScanSettings#SCAN_MODE_LOW_POWER
      
        Dim ScanSettingsBuilder As JavaObject
        ScanSettingsBuilder.InitializeNewInstance("android.bluetooth.le.ScanSettings.Builder", Null)
      
        ' // 2021.01.07 -
        ScanSettingsBuilder.RunMethod("setScanMode", Array(ScanSettingsStatic.GetField("SCAN_MODE_LOW_POWER")))
      
        Dim ScanFilterStatic As JavaObject
        ScanFilterStatic.InitializeStatic("android.bluetooth.le.ScanFilter")
      
        ' // set the scan filter for iBeacons
        Dim ScanFilterBuilder1 As JavaObject
        ScanFilterBuilder1.InitializeNewInstance("android.bluetooth.le.ScanFilter.Builder", Null)
        ScanFilterBuilder1.RunMethod("setManufacturerData", Array(76,Array As Byte())) 'Apple ID
                                          
        Dim Filters As List = Array(ScanFilterBuilder1.RunMethod("build", Null))
        If Filters.Size > 0 Then
            Dim aScanFilterJO As JavaObject = Filters.Get(0)
            log($"svc_ble::ScanWithLeScanner, Filter=${aScanFilterJO.RunMethod("toString", Null)}"$)
        End If
        Scanner.RunMethod("startScan", Array(Filters, ScanSettingsBuilder.RunMethod("build", Null), ScanCallback))      
    Catch
        log($"svc_ble::ScanWithLeScanner, error=${LastException.Message}"$)      
        scanComplete = True
    End Try
      
End Sub


Private Sub Scan_Failed (Result As Int)
  
    Dim res As String
  
    Select Case Result
      
        Case 1
            res = "SCAN_FAILED_ALREADY_STARTED"
        Case 2
            res = "SCAN_FAILED_APPLICATION_REGISTRATION_FAILED"
        Case 3
            res = "SCAN_FAILED_INTERNAL_ERROR"
        Case 4
            res = "SCAN_FAILED_FEATURE_UNSUPPORTED"
    End Select
  
    mod_functions.writeLog($"svc_ble::Scan_Failed, ${Result} ${res} "$)
  
    Dim btm As BluetoothAdmin
    btm.Initialize("")
    btm.Disable
    scanComplete = True
  
  
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 ScanRecord As JavaObject = ScanResult.RunMethod("getScanRecord", Null)  
    Dim data() As Byte = ScanRecord.RunMethod("getManufacturerSpecificData", Array(76)) '76 = apple id
      
    If data <> Null Then
      
        Try
            Private bc As ByteConverter
            Dim raf As RandomAccessFile
            Dim ib As mBeacon
            raf.Initialize3(data, False)
            ' // load beacons props
            ib.Initialize
            ib.name = ScanRecord.RunMethod("getDeviceName",Null)
            ib.uniqueid = address
            ib.major =  Bit.And(0xFFFF,raf.ReadShort(18))
            ib.minor =  Bit.And(0xFFFF,raf.ReadShort(20))
            ib.rssi = ScanResult.RunMethod("getRssi", Null)
            ib.tx = ScanRecord.RunMethod("getTxPowerLevel",Null)
                      
            ' // https://www.b4x.com/android/forum/threads/iot-beaconparser-discover-ibeacons-and-eddystone-beacons.61127/post-450458
            ib.distance = CalculateDistance(ib.tx, ib.rssi)
            ib.time = DateTime.Now
            iBeacons.Put(ib.uniqueid, ib)
            Log($"${DateTime.Time(ib.time)} - ${ib.name} ${ib.uniqueid} ${ib.tx} ${ib.rssi} ${ib.distance} "$)
        Catch
            log($"Scan_Result, Error ${LastException.Message}"$)
            log(ScanRecord.RunMethod("toString", Null))
        End Try      
              
    End If
  
End Sub

Sub CalculateDistance(txPower As Int, rssi As Double) As Double

    Dim ratio As Double, tx As Int
      
    If txPower = -12 Then
        tx = -77
    Else
        tx = txPower
    End If

    If (rssi = 0) Then
        Return -1.0
    End If

    ratio = rssi*1.0/tx

    If (ratio < 1.0) Then
        Return Round2(Power(ratio,10),2)
    Else
        Return Round2((0.89976) * Power(ratio,7.7095) + 0.111,2)
    End If
  
  
End Sub

Private Sub CreateNotification(Title As String, Content As String, Icon As String, TargetActivity As Object, _
                                    Sound As Boolean, Vibrate As Boolean, pN As Notification,pNID As Int) As Notification
  
  
    Dim p As Phone
  
  
    If p.SdkVersion >= 21 Then
        Dim nb As NotificationBuilder
        Dim Channel As NotificationChannelBuilder
        Dim ChannelID As String = "ies_atlas_sos_ble_scan"
        Dim ChannelName As String = "Atlas SOS Ble Scan"
      
        ' // Build a Channel
  
        If Channel.ChannelsSupported Then
            Channel.Initialize(ChannelID, ChannelName, Channel.IMPORTANCE_LOW)
            Channel.Build
        End If
      
        nb.Initialize(ChannelID)
        nb.AutoCancel = False
        nb.OnGoingEvent = True
        nb.DefaultSound = Sound
        nb.DefaultVibrate = Vibrate
        nb.DefaultLight = False
        nb.ContentTitle = Title
        nb.ContentText = Content
        nb.setActivity(TargetActivity)
        nb.SmallIcon = Icon
        nb.Number = pNID
        ' //set the return object for the notification object (n1) in this service
        pN = nb.GetNotification
    Else
        pN.Initialize
        pN.Number = pNID
        pN.Light = False
        pN.Vibrate = Vibrate
        pN.Sound = Sound
        pN.OnGoingEvent = True
        pN.Icon = Icon
        pN.SetInfo(Title, Content, TargetActivity)
    End If
    pN.Notify(pNID)
    Return pN
  
End Sub
#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) {     
       processBA.raiseEvent(this, "scan_failed", errorCode);
    }
}
#End If

The above service code is a stripped down version of what our app uses. I have not tested the above code, you can do this and it should work. I strongly suggest that you read all the links in the code. If you are developing an app for commerical use and plan to sell it, you need to fully understand what the above code does and do some futher research.

Best of luck.

John.
Very very thanks
 
Upvote 0
Top