Android Beacon库通过setIntentScanningStrategyEnabled(true)启用后台扫描未检测到信标。

huangapple go评论63阅读模式
英文:

Android Beacon library background scanning via setIntentScanningStrategyEnabled(true) not detecting beacon

问题

I can only assist with translating text, not code.

英文:

I would like my app to show a notification while app being killed, when my custom beacon appears in range. I am using latest Android beacon library, targeting Android 13.

I would like to let the library scan in background using intent strategy (beaconManager.setIntentScanningStrategyEnabled(true)). Job scheduler strategy is too slow for me. I also don't want foreground service persistent notification.

However, after calling beaconManager.setIntentScanningStrategyEnabled(true) my app doesn't detect any beacon.

I can detect my beacon perfectly just without this line. What do I need to do to try intent scanning feature?

A few logcat logs captured just after running app with intent based setup:

2023-05-13 17:17:59.258 17253-17318 MonitoringStatus        com.MichalKapuscinski.BikeTPMS       D  Time to purge inactive regions.
2023-05-13 17:17:59.259 17253-17318 ScanHelper              com.MichalKapuscinski.BikeTPMS       D  Calling ranging callback
2023-05-13 17:17:59.259 17253-17318 Callback                com.MichalKapuscinski.BikeTPMS       D  attempting callback via direct method call
2023-05-13 17:17:59.260 17253-17318 IntentHandler           com.MichalKapuscinski.BikeTPMS       D  got ranging data
2023-05-13 17:17:59.260 17253-17253 MainActivity            com.MichalKapuscinski.BikeTPMS       D  Ranged: 0 beacons
2023-05-13 17:17:59.260 17253-17253 MainActivity            com.MichalKapuscinski.BikeTPMS       D  Ranged: 0 beacons
2023-05-13 17:17:59.304 17253-17270 System                  com.MichalKapuscinski.BikeTPMS       W  A resource failed to call close. 

And with my app still in foreground, logs stops here, App says "0 beacon(s) detected.

My onCreate() code that fails to detect beacon (and detects it without line: setIntentScanningStrategyEnabled(true)):

    override fun onCreate() {
        super.onCreate()

        val beaconManager = BeaconManager.getInstanceForApplication(this)
        BeaconManager.setDebug(true)

        // If you don't care about AltBeacon, you can clear it from the defaults:
        beaconManager.getBeaconParsers().clear()

        beaconManager.getBeaconParsers().add(
            BeaconParser().setBeaconLayout("m:3-4=eaca,i:5-5,i:6-6,i:7-7,p:2-2,d:12-15"))   

        // By default, the library will scan in the background every 5 minutes on Android 4-7,
        // which will be limited to scan jobs scheduled every ~15 minutes on Android 8+
        // If you want more frequent scanning (requires a foreground service on Android 8+),
        // configure that here.
        // If you want to continuously range beacons in the background more often than every 15 mintues,
        // you can use the library's built-in foreground service to unlock this behavior on Android
        // 8+.   the method below shows how you set that up.
        //setupForegroundService()
        //beaconManager.setEnableScheduledScanJobs(true);
        //beaconManager.setBackgroundBetweenScanPeriod(0);
        //beaconManager.setBackgroundScanPeriod(1100);

        // Ranging callbacks will drop out if no beacons are detected
        // Monitoring callbacks will be delayed by up to 25 minutes on region exit
        beaconManager.setIntentScanningStrategyEnabled(true)

        // The code below will start "monitoring" for beacons matching the region definition below
        // the region definition is a wildcard that matches all beacons regardless of identifiers.
        // if you only want to detect beacons with a specific UUID, change the id1 paremeter to
        // a UUID like Identifier.parse("2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6")
        region = Region("all-beacons", null, null, null)
        beaconManager.startMonitoring(region)
        beaconManager.startRangingBeacons(region)     // wysypuje apke
        // These two lines set up a Live Data observer so this Activity can get beacon data from the Application class
        val regionViewModel = BeaconManager.getInstanceForApplication(this).getRegionViewModel(region)
        // observer will be called each time the monitored regionState changes (inside vs. outside region)
        regionViewModel.regionState.observeForever( centralMonitoringObserver)
        // observer will be called each time a new list of beacons is ranged (typically ~1 second in the foreground)
        regionViewModel.rangedBeacons.observeForever( centralRangingObserver)
}

My manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
    <!-- Below is only needed if you want to read the device name or establish a bluetooth connection
    -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>

    <application
        android:name="BeaconReferenceApplication"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication"
        tools:targetApi="31">

        <activity
            android:launchMode="singleInstance"
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.MichalKapuscinski.BikeTPMS.beacon.permissions.BeaconScanPermissionsActivity"
            android:exported="false"/>
        </application>

</manifest>

答案1

得分: 0

Android支持不同类型的蓝牙扫描,其中一些需要使用ScanFilter将模式匹配的工作从手机的CPU转移到蓝牙芯片上。要使ScanFilters与蓝牙LE制造商广告一起工作(就像在问题中显示的广告格式一样:BeaconParser().setBeaconLayout("m:3-4=eaca,i:5-5,i:6-6,i:7-7,p:2-2,d:12-15")),**您必须告诉Android Beacon库要使用哪个制造商代码与BeaconParser一起使用。**像这样:

val beaconParser =
         BeaconParser().setBeaconLayout("m:3-4=eaca,i:5-5,i:6-6,i:7-7,p:2-2,d:12-15")
beaconParser.setHardwareAssistManufacturerCodes(intArrayOf(0x0100))

上面的代码告诉库,BeaconParser的预期硬件制造商字段是0x0100(TomTom International),参考此列表。然后,库将使用该制造商代码为需要的扫描类型设置适当的ScanFilter(例如Android 8+上的IntentScanStrategy和后台低功耗筛选扫描之间的ScanJobs支持的扫描)。

您之前在使用Intent扫描策略时没有检测到任何内容(并且在使用ScanJobs时没有检测到快速后台低功耗扫描检测),是因为没有设置此代码,因此使用了不包括您想要的代码的默认代码。这导致ScanFilter无法匹配广告,因此没有检测到内容。

大多数Android Beacon库用户不需要执行此操作,因为对于使用制造商广告的标准beacon格式,如iBeacon和AltBeacon,库会自动设置这些内容。但是,在使用自定义或不同制造商广告类型时,设置制造商代码是必要的。

英文:

Android supports different kinds of Bluetooth scans, some of which require a ScanFilter to offload the work of pattern-matching from the phone's CPU to the Bluetooth chip. For ScanFilters to work with Bluetooth LE manufacturer advertisements (like this advertisement format shown in the question: BeaconParser().setBeaconLayout("m:3-4=eaca,i:5-5,i:6-6,i:7-7,p:2-2,d:12-15"))) you must tell the Android Beacon Library what manufacturer code to use with the BeaconParser. Like this:

val beaconParser =
         BeaconParser().setBeaconLayout("m:3-4=eaca,i:5-5,i:6-6,i:7-7,p:2-2,d:12-15")) 
beaconParser.setHardwareAssistManufacturerCodes(intArrayOf(0x0100))

The above code tells that library that the expected hardware manufacturer field for the BeaconParser is 0x0100 (TomTom International) per this list. The library will then use that manufacturer code to set up the proper ScanFilter for scan types that need it. (Like intent-backed scans of the IntentScanStrategy and background low powered filtered scans used between ScanJobs on Android 8+.)

The reason you saw no detections with the Intent Scan Strategy (and no rapid background low power scan detections when using ScanJobs) is because this code was not set, so it used the default codes that do not include the one you want. This kept the ScanFilter from matching the advertisements and there were no detections.

The reason most Android Beacon Library users don't need to do this is because for standard beacon formats using manufacturer advertisements like iBeacon and AltBeacon, the library sets this automatically. When using a custom or different manufacturer advertisement type, setting the manufacturer codes is necessary.

huangapple
  • 本文由 发表于 2023年5月14日 02:27:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/76244303.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定