我使用LeScanCallback(无法使用更新的扫描方法,因为我正在为api 18开发。这并不重要,因为android 5.0 api也不提供此功能)来检测何时检测到附近的BLE设备:
private BluetoothAdapter.LeScanCallback bleCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice bluetoothDevice, int i, byte[] bytes) {
discoveredDevices.add(bluetoothDevice);
}
};
我没有与设备配对或连接,因为这不是必需的,我只是想看看附近有哪些设备。
我正在尝试创建一个服务,每隔5分钟左右,调用一个Web服务器来更新此时附近的设备。
棘手的是android设备将移动,所以现在附近的蓝牙设备可能不会在5分钟内移动。在这种情况下,我需要将其从发现的设备中删除。
理想情况下,当蓝牙设备以前在范围内,但现在不在范围内时,我希望收到回调。但此回调不存在。
(我知道android.bluetooth.device.action.ACL\u已连接和android.bluetooth.device.action.ACL\u已断开广播,但这些广播是用于连接到蓝牙设备时的,我不想要。)
一种选择是每5分钟进行一次新的扫描,但您无法判断附近的所有设备何时被发现,因此您必须进行定时扫描,例如扫描5秒,然后将收集到的数据发送到网络服务。
这听起来很脏而且很危险,因为您永远无法确定所有附近的设备都在分配的时间内被发现,所以我非常希望避免这样做。
还有别的方法吗?
编辑一些设备不断报告发现附近的蓝牙设备,即使之前已经发现了这些设备。如果该功能是通用的,我可以解决我的问题,但这是特定于设备的。
例如,我手机的蓝牙适配器只能发现一次附近的设备。我测试过的其他一些设备确实会不断报告相同的附近设备,但并不是所有设备都这样,所以不幸的是,我不能依赖它。
我可以推荐这种方法:
使用地图
然后在您的服务中(据我从问题中了解,将实现某种重复任务)只需根据检测到的时间提取实际设备。
你说得绝对正确,不能保证所有附近的设备都在规定的时间内被发现。尤其是Android设备。反过来,iOS设备还有另一个问题——它们可以在运行时更改Bluetooth设备的地址,而无需明显的外部原因。希望这将帮助您节省调试期间的时间。
编辑
由于对本课题的研究发现,本文对代码进行了讨论。谷歌。通用域名格式
这个问题仍然存在,似乎和硬件特性有关,无法通过编程解决。此外,即使在系统更新后,问题设备上的错误似乎仍会存在。因此,对于这种情况,定期重新启动扫描可能是可以接受的解决方法。
这听起来既脏又危险,因为你永远无法确定附近的所有设备都是在规定的时间内被发现的,所以我非常希望避免这样做。
这听起来是一个合理的假设,但它是错误的。
蓝牙低能量以特定的方式工作,BLE设备有一些限制。例如,它们有一个固定的可能广告频率范围,从20毫秒到10.24秒不等,步长为0.625毫秒。有关更多详细信息,请参阅此处和此处。
这意味着,在设备广播新的广告包之前,最多需要10.24秒。BLE设备通常(如果不总是)会为其所有者提供一种调整其广告频率的方法,因此频率当然会有所不同。
如果您定期收集有关附近设备(如您的设备)的数据,可以使用具有固定时间限制的扫描,将该数据保存在某处,重新启动扫描,收集新数据,与旧数据进行比较--
例如,如果在扫描1中发现一个设备,但在扫描2中没有发现,则可以得出结论,该设备在范围内,但不再在范围内<反之亦然:如果在扫描4中找到了一个设备,但在扫描3中没有找到,则它是一个新发现的设备<最后,如果在扫描5中找到了一个设备,但在扫描6中没有找到,但在扫描7中再次找到,则会重新发现该设备,并且可以根据需要进行处理。
因为我在这里回答了我自己的问题,所以我将添加我用来实现它的代码。
我在后台服务中完成扫描,并使用BroadcastReceivers与应用程序的其他部分进行通信。Asset
是我的一个自定义类,它保存一些数据。DataManager
是我的一个自定义类,它-你是怎么猜到的-管理数据。
public class BLEDiscoveryService extends Service {
// Broadcast identifiers.
public static final String EVENT_NEW_ASSET = "EVENT_NEW_ASSET ";
public static final String EVENT_LOST_ASSET = "EVENT_LOST_ASSET ";
private static Handler handler;
private static final int BLE_SCAN_TIMEOUT = 11000; // 11 seconds
// Lists to keep track of current and previous detected devices.
// Used to determine which are in range and which are not anymore.
private List<Asset> previouslyDiscoveredAssets;
private List<Asset> currentlyDiscoveredAssets;
private BluetoothAdapter bluetoothAdapter;
private BluetoothAdapter.LeScanCallback BLECallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice bluetoothDevice, int i, byte[] bytes) {
Asset asset = DataManager.getAssetForMACAddress(bluetoothDevice.getAddress());
handleDiscoveredAsset(asset);
}
};
@Override
public void onCreate() {
super.onCreate();
BluetoothManager manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
bluetoothAdapter = manager.getAdapter();
previouslyDiscoveredAssets = new ArrayList<>();
currentlyDiscoveredAssets = new ArrayList<>();
handler = new Handler();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Start scanning.
startBLEScan();
// After a period of time, stop the current scan and start a new one.
// This is used to detect when assets are not in range anymore.
handler.postDelayed(new Runnable() {
@Override
public void run() {
performRepeatingTask();
// Repeat.
handler.postDelayed(this, BLE_SCAN_TIMEOUT);
}
}, BLE_SCAN_TIMEOUT);
// Service is not restarted if it gets terminated.
return Service.START_NOT_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
handler.removeCallbacksAndMessages(null);
stopBLEScan();
super.onDestroy();
}
private void startBLEScan() {
bluetoothAdapter.startLeScan(BLECallback);
}
private void stopBLEScan() {
bluetoothAdapter.stopLeScan(BLECallback);
}
private void handleDiscoveredAsset(Asset asset) {
currentlyDiscoveredAssets.add(asset);
// Notify observers that we have a new asset discovered, but only if it was not
// discovered previously.
if (currentlyDiscoveredAssets.contains(asset) &&
!previouslyDiscoveredAssets.contains(asset)) {
notifyObserversOfNewAsset(asset);
}
}
private void performRepeatingTask() {
// Check if a previously discovered asset is not discovered this scan round,
// meaning it's not in range anymore.
for (Asset asset : previouslyDiscoveredAssets) {
if (!currentlyDiscoveredAssets.contains(asset)) {
notifyObserversOfLostAsset(asset);
}
}
// Update lists for a new round of scanning.
previouslyDiscoveredAssets.clear();
previouslyDiscoveredAssets.addAll(currentlyDiscoveredAssets);
currentlyDiscoveredAssets.clear();
// Reset the scan.
stopBLEScan();
startBLEScan();
}
private void notifyObserversOfNewAsset(Asset asset) {
Intent intent = new Intent();
intent.putExtra("macAddress", asset.MAC_address);
intent.setAction(EVENT_NEW_ASSET);
sendBroadcast(intent);
}
private void notifyObserversOfLostAsset(Asset asset) {
Intent intent = new Intent();
intent.putExtra("macAddress", asset.MAC_address);
intent.setAction(EVENT_LOST_ASSET);
sendBroadcast(intent);
}
}
这段代码并不完美,甚至可能有缺陷,但它至少会为您提供如何实现这一点的想法或示例。
我正在尝试在服务上检测附近的蓝牙低功耗设备。当服务启动时,会调用starLeScan(),然后在10秒后调用Stop LeScan()。即使start LeScan()返回true,并且我没有得到任何错误,LeScanCallback上的onLeScan也没有被调用。服务: 我尝试使用BluetoothLeScanner startScan()和stopScan(),并改用ScanCallback
我正在尝试在Sony SmartWatch 3上实现BluetoothGattServer。 我可以成功地打开Gatt服务器并做广告。 使用BLE扫描仪应用程序,我在发现我的自定义服务及其自定义特征时得到不一致的结果。 在三星Galaxy Note 8-Android 4.4-上,我可以正确检测自定义服务和自定义特性 这是我在Wear设备上运行的代码: 我还尝试使用自定义生成的UUID从https
问题内容: 我正在使用在Xcode上使用Swift的应用程序,该应用程序连接到蓝牙BLE外设。我已经建立了与设备的连接,并想从特定特征(特别是服务UUID FFF0中的FFF1)读取一些数据。 如果要查找其信息的特征是,我可以使用以下代码请求特征的读取: 我想知道的是:如何检查此读取值是否是我要的值。我希望能够执行if语句,以针对该特征的发现值检查我的值。 例如:如果发现的值为X,则执行其他操作;
在iOS中,无法获取CBP外围对象的mac地址。现在,我有很多不同UUID但外设名称相同的BLE设备。用户必须首先通过注册命令注册到BLE设备,该BLE设备的MAC地址将在二维码扫描时获得。但是,我如何才能获得设备用户正在进行注册,因为在iOS中,我在外围设备中没有获得MAC地址?
我试图用Jasmine为Angularjs编写单元测试。这是我的控制器: 和测试 测试失败,即使我试图测试期望(true). toBe(true); 茉莉花,因果报应,棱角分明的嘲弄都在我的索引里。jasmine调试页面中的html,还有测试脚本。 我发现如果删除beforeach()块,expect(true)。托比(真的)通过了。 下面是一个错误: