我正在创建一个Android项目,我必须将android wearable智能手表作为游戏控制器,它可以向连接到该智能手表的手持设备上运行的游戏发送命令BLE(Bluetooth Low Energy).
我在可穿戴设备上设计了控制器垫,可以在控制器键盘的软按钮上发送一些硬编码文本到手持设备应用程序.问题是,我必须用手持设备上运行的游戏所期望的游戏命令格式替换该文本.并且,在手持设备上运行的应用程序可以通过可穿戴服务来收听文本.我知道,第三方游戏不会运行任何可穿戴服务,因此第三方游戏将如何接受/收听可穿戴智能手表发送的命令.
我正在开发一个应用程序,我可以在其中查找和配置BLE设备.我使用标准的Android BLE API,但最近我遇到了一些奇怪的问题.
当我打开我的应用程序时,BLE扫描工作正常.我正在扫描使用:
mBluetoothAdapter.startLeScan(mLeScanCallback); // for Kitkat and below
Run Code Online (Sandbox Code Playgroud)
和
mBluetoothAdapter.getBluetoothLeScanner().startScan(mScanCallback); // for Lollipop and above
Run Code Online (Sandbox Code Playgroud)
在Logcat中我收到以下消息(我猜这对于这个问题很重要):
D/BluetoothAdapter: onClientRegistered() - status=0 clientIf=5
Run Code Online (Sandbox Code Playgroud)
在我的应用程序中,我还可以从我的BLE设备中读取某些特征(例如电池状态).我使用以下命令连接到设备以在单独的片段中读取此特征:
mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = mBluetoothManager.getAdapter();
mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(mMacAddress);
mBluetoothGatt = mBluetoothDevice.connectGatt(mContext, false, mGattCallback);
Run Code Online (Sandbox Code Playgroud)
正确读取特征.在onCharacteristicRead回调中我也断开并关闭Gatt:
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
Run Code Online (Sandbox Code Playgroud)
每次打开一个片段来读取一个特征(无论它是否是同一个设备),clientIf值都会增加.我可以在LogCat中看到:
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=6
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=7
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=8
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=9
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=10
Run Code Online (Sandbox Code Playgroud)
一切正常,直到clientIf值等于10. BLE扫描停止查找任何设备,我无法连接到我的任何设备读取任何特征等.而LogCat无限显示这些消息:
D/BluetoothGatt: unregisterApp() - mClientIf=0 …Run Code Online (Sandbox Code Playgroud) 我有Android应用程序暴露BLE服务器.我连接BluetoothGattServer#connect.它有效 - 我的应用程序通过STATE_CONNECTED调用BluetoothGattServerCallback#onConnectionStateChange.当我完成客户端后,我尝试使用BluetoothGattServer#cancelConnection与我的应用程序断开连接.
但我没有接到对BluetoothGattServerCallback#onConnectionStateChange的调用,似乎连接仍然处于活动状态,因为我的BLE客户端没有开始做广告(当没有任何连接时它就会这样做).
在logcat中我只看到:
BluetoothGattServer: cancelConnection() - device: XX:XX:XX:XX:XX:XX
Run Code Online (Sandbox Code Playgroud)
有趣的是,我的应用程序在完全关闭BT后立即调用BluetoothGattServerCallback#onConnectionStateChange和STATE_DISCONNECTED.
android bluetooth-lowenergy android-bluetooth gatt android-ble
我目前正在测试 Android配套设备配对,但我不确定如何从REQUEST_COMPANION_RUN_IN_BACKGROUND权限中受益。
在 Google 文档的一部分中说:
设备配对后,设备可以利用 REQUEST_COMPANION_RUN_IN_BACKGROUND 和 REQUEST_COMPANION_USE_DATA_IN_BACKGROUND 权限从后台启动应用程序。例如,您可以使用这种配对设备的方法对支持 BLE 的智能手表进行初始配置。
在许可本身中:
允许配套应用在后台运行。
在CompanionDeviceManager文档中,它说:
如果您的应用需要从电池优化中排除(在后台运行)或具有不受限制的数据访问(在后台使用数据),您可以分别声明您使用 android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND 和。
有人可以解释(或指向一些示例代码)如何利用此权限在后台运行应用程序?理想情况下,我想从配对的蓝牙 LE 外围设备触发配套应用程序中的操作。
android bluetooth-lowenergy android-bluetooth android-ble wear-os
如何应对Android中的定向广告(ADV_DIRECT_IND == 0001)?
有一个BLE小工具可以向Android手机发送定向广告(目前使用手机的硬编码MAC地址),在我的Android应用中,我想做出反应并启动与小工具的连接并阅读org.bluetooth.小工具中的characteristic.location_and_speed值:
请通过Android 5 API告知是否可行.
android bluetooth bluetooth-lowenergy android-bluetooth android-ble
我正在使用设备名称过滤器连接到特定的 BLE 设备。但是我的扫描回调没有执行。当我使用 MAC 地址作为过滤器时,它工作正常。这是已知问题还是错误?我正在使用 Android 6.0 的华硕平板电脑进行测试。当我从设备名称数据库读取要使用的扫描过滤器时,我没有使用 MAC 地址的替代方法。
//这不起作用
ScanFilter scanFilter = (new android.bluetooth.le.ScanFilter.Builder())
.setDeviceName(device_name).build();
Run Code Online (Sandbox Code Playgroud)
//这有效
ScanFilter scanFilter = new ScanFilter.Builder()
.setDeviceAddress(dev_mac_address).build();
Run Code Online (Sandbox Code Playgroud) 我有一个自定义BLE外围设备,它发布这样的数据:
换句话说,我的BLE外设会在已发布的服务数据中发布与唯一标识符关联的服务UUID,但不会将该服务UUID添加到已发布的服务列表中,因为如果这样做,则BLE框架中没有空间在需要时添加电池电量。
在iOS上,我可以使用基于服务UUID的过滤器进行扫描,并查看我的外围设备。但是在Android上,使用以下扫描过滤器,我看不到外围设备:
val scanSettingsBuilder = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setReportDelay(0L)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
scanSettingsBuilder
.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
.setNumOfMatches(ScanSettings.MATCH_NUM_ONE_ADVERTISEMENT)
}
bluetoothAdapter?.bluetoothLeScanner?.startScan(
arrayListOf(ScanFilter.Builder().setServiceUuid(ParcelUuid(UUID.fromString("00004865-726f-6e54-7261-636b2d475053"))).build()),
scanSettingsBuilder.build(),
leScanCallback
)
Run Code Online (Sandbox Code Playgroud)
是否有人有更多关于基于serviceUUID的扫描过滤器如何工作的详细信息,并且外围设备必须满足哪些条件才能被过滤器接受?
Android 上的蓝牙扫描似乎有很多“隐藏功能”。对于初学者来说,有一个“30 秒限制”(Android 7.0 ble scan no result)。然后你必须在后台模式下设置一个 ScanFilter 否则你不会得到任何结果(找不到这个的参考)。
最近我发现,当我在 Android 10 上使用以下扫描模式启用扫描并关闭屏幕(大约 30 秒后)时,我没有得到任何扫描结果(我在 Google Pixel 3 和 Google Pixel 4 上观察到了这种行为) ,它在较旧的 Android 上运行良好):
/**
* Perform Bluetooth LE scan in balanced power mode. Scan results are returned at a rate that
* provides a good trade-off between scan frequency and power consumption.
*/
public static final int SCAN_MODE_BALANCED = 1;
Run Code Online (Sandbox Code Playgroud)
还有另一种扫描模式(我还没有尝试过):
/**
* Perform Bluetooth LE scan in low power mode. This is the …Run Code Online (Sandbox Code Playgroud) 最初我设置了一个BroadcastReceiver接收来自Nearby Messages API的意图.
class BeaconMessageReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Nearby.getMessagesClient(context).handleIntent(intent, object : MessageListener() {
override fun onFound(message: Message) {
val id = IBeaconId.from(message)
Timber.i("Found iBeacon=$id")
sendNotification(context, "Found iBeacon=$id")
}
override fun onLost(message: Message) {
val id = IBeaconId.from(message)
Timber.i("Lost iBeacon=$id")
sendNotification(context, "Lost iBeacon=$id")
}
})
}
private fun sendNotification(context: Context, text: String) {
Timber.d("Send notification.")
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notification = NotificationCompat.Builder(context, Notifications.CHANNEL_GENERAL)
.setContentTitle("Beacons")
.setContentText(text)
.setSmallIcon(R.drawable.ic_notification_white)
.build() …Run Code Online (Sandbox Code Playgroud) android android-intentservice android-ble beacon google-nearby
我有一个扫描 BLE 设备的应用程序。它在 Android 10 上运行良好,但自从我将手机更新到Android 11后,如果我将应用程序置于后台或锁定屏幕,则onScanResult 永远不会被调用。
这很烦人。我还没有找到任何可能导致这种情况的合理想法。我在 Android 11 中没有发现任何表明此行为发生变化的差异。如果您将应用程序定位到 api 级别 31,则 Android 12 具有新的 BT 权限,但我确实将我的应用程序定位到 api 级别 30,并且我确实在 Android 11 上运行我的应用程序。
我完全一无所知。我尝试了不同的扫描模式,以及添加扫描过滤器,但没有任何改变。
我的扫描设置:
ScanSettings ss = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_POWER).build();
List<ScanFilter> filterList = new ArrayList<>();
filterList.add(new ScanFilter.Builder().setManufacturerData(Constants.HARDWARE_MANUFACTURER_ID, new byte[]{}).build());
BluetoothUtil.getBluetoothLeScannerInstance().startScan(filterList, ss, leScanCallback);
Run Code Online (Sandbox Code Playgroud)
onScanResult当应用程序位于前台且设备屏幕未锁定时,通话效果良好。一旦我将应用程序推到后台或锁定屏幕,我就不再收到任何回调onScanResult
15:47:15 com.myapp.co I/BL_START: ...Starting BL scan. (Start of current window)
15:47:17 com.myapp.co I/SCANNED_: onScanResult ran!
15:47:21 com.myapp.co I/SCANNED_: onScanResult ran! …Run Code Online (Sandbox Code Playgroud) android ×10
android-ble ×10
wear-os ×2
android-10.0 ×1
beacon ×1
bluetooth ×1
gatt ×1
google-pixel ×1