如何用Android Beacon Library扫描读取EM Microelectronic EMBC02信标?
Hey there! Let's work through this step by step—getting the Android Beacon Library to reliably detect your EMBC02 beacons boils down to configuring the correct beacon layout and setting up targeted scanning. Here's how to do it:
一、核心:配置正确的BeaconLayout
The biggest issue you're likely facing is that the library doesn't recognize EMBC02's proprietary broadcast format out of the box. We need to define a custom BeaconLayout that matches the beacon's data structure.
1. 先确认EMBC02的广播结构
Grab a BLE debugging app like nRF Connect, scan your EMBC02 beacon, and look for the Manufacturer Specific Data entry. A typical EMBC02 broadcast might look like this (hex format):
0A 00 01 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 00 01 02 03 C8 64
Break down this data to map it to the library's syntax:
- Bytes 0-1:
0A 00→ EM Microelectronic's manufacturer code (0x000A, stored in little-endian) - Byte 2:
01→ Beacon frame type (filters out other EM device broadcasts) - Bytes 3-18: 16-byte UUID
- Bytes 19-20: 2-byte Major value
- Bytes 21-22: 2-byte Minor value
- Byte 23:
C8→ TX Power (converts to -56dBm) - Byte 24:
64→ Battery level (100%)
2. 编写对应的BeaconLayout
Using the structure above, here's the correct layout string for EMBC02:
new BeaconParser().setBeaconLayout("m:0-1=0a00,i:2-2=01,i:3-18,i:19-20,i:21-22,p:23-23,d:24-24")
Let's break down what each part means:
m:0-1=0a00: Matches the manufacturer code in the first two bytes of the manufacturer-specific datai:2-2=01: Only detects frames marked as beacon type (0x01)i:3-18: Extracts the 16-byte UUID as an identifieri:19-20: Extracts the 2-byte Major valuei:21-22: Extracts the 2-byte Minor valuep:23-23: Reads the TX Power fieldd:24-24: Captures the battery level as extra data
二、完整集成步骤
1. 添加依赖
Add the Android Beacon Library to your module-level build.gradle:
dependencies { implementation 'org.altbeacon:android-beacon-library:2.21.4' }
2. 配置权限
Update your AndroidManifest.xml with the necessary BLE permissions (for Android 12+ compatibility):
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" /> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
Note: Android 12+ doesn't require location permissions for BLE scanning, but older devices might.
3. 初始化扫描逻辑
Set up the beacon manager in your Application class to handle scanning in foreground and background:
import android.app.Application; import android.util.Log; import org.altbeacon.beacon.Beacon; import org.altbeacon.beacon.BeaconManager; import org.altbeacon.beacon.BeaconParser; import org.altbeacon.beacon.Region; import org.altbeacon.beacon.powersave.BackgroundPowerSaver; import org.altbeacon.beacon.startup.BootstrapNotifier; import org.altbeacon.beacon.startup.RegionBootstrap; import org.altbeacon.beacon.ranging.BeaconConsumer; import org.altbeacon.beacon.ranging.RangeNotifier; import java.util.Collection; public class MyApp extends Application implements BootstrapNotifier, BeaconConsumer { private static final String TAG = "EMBC02Scanner"; private RegionBootstrap regionBootstrap; private BeaconManager beaconManager; private BackgroundPowerSaver backgroundPowerSaver; @Override public void onCreate() { super.onCreate(); beaconManager = BeaconManager.getInstanceForApplication(this); // Clear default parsers to only scan EMBC02 beaconManager.getBeaconParsers().clear(); // Add our custom EMBC02 parser BeaconParser embc02Parser = new BeaconParser() .setBeaconLayout("m:0-1=0a00,i:2-2=01,i:3-18,i:19-20,i:21-22,p:23-23,d:24-24"); beaconManager.getBeaconParsers().add(embc02Parser); // Configure foreground scanning (adjust for your needs) beaconManager.setForegroundScanPeriod(1000); // Scan for 1 second each cycle beaconManager.setForegroundBetweenScanPeriod(0); // No gap between scans // Enable background power saving (optional but recommended) backgroundPowerSaver = new BackgroundPowerSaver(this); // Monitor all EMBC02 beacons (use specific UUID/Major/Minor to narrow it down) Region embc02Region = new Region("embc02-region", null, null, null); regionBootstrap = new RegionBootstrap(this, embc02Region); // Bind to receive ranging data beaconManager.bind(this); } @Override public void didEnterRegion(Region region) { Log.d(TAG, "EMBC02 beacon detected! Starting ranging..."); beaconManager.startRangingBeaconsInRegion(region); } @Override public void didExitRegion(Region region) { Log.d(TAG, "No EMBC02 beacons in range"); beaconManager.stopRangingBeaconsInRegion(region); } @Override public void didDetermineStateForRegion(int state, Region region) { Log.d(TAG, "Beacon region state changed: " + state); } @Override public void onBeaconServiceConnect() { beaconManager.addRangeNotifier((beacons, region) -> { for (Beacon beacon : beacons) { Log.d(TAG, String.format( "EMBC02 Data: UUID=%s, Major=%d, Minor=%d, Distance=%.2fm, Battery=%d%%", beacon.getId1(), beacon.getId2().toInt(), beacon.getId3().toInt(), beacon.getDistance(), beacon.getExtraDataFields().get(0) )); } }); } @Override public void onDestroy() { super.onDestroy(); beaconManager.unbind(this); } }
三、仅扫描EMBC02信标的方案
To ensure you only detect EMBC02 beacons:
- Clear default parsers: Call
beaconManager.getBeaconParsers().clear()before adding your EMBC02 parser—this removes support for iBeacon, Eddystone, etc. - Narrow down the Region: If your beacons use a fixed UUID, specify it when creating the Region to filter results:
Region embc02Region = new Region("embc02-region", Identifier.parse("00112233-4455-6677-8899-AABBCCDDEEFF"), null, null); - Adjust scan parameters: Tune the scan period and interval to balance detection reliability and battery life (foreground settings are more aggressive, background settings are more power-efficient).
四、排查不稳定检测的技巧
- Check permissions: Make sure you've requested runtime permissions for BLUETOOTH_SCAN, BLUETOOTH_CONNECT, and (for older devices) ACCESS_FINE_LOCATION.
- Validate the layout: Cross-check the beacon's actual broadcast data (from nRF Connect) against your
BeaconLayout—a single byte offset will break detection. - Reduce interference: Test in a low-BLE-traffic environment, and ensure your beacons have enough battery and are broadcasting at a sufficient power level.
内容的提问来源于stack exchange,提问作者Amine Harbaoui

