如何在 Xamarin/Android 上启用多个 BLE 特征通知?
Posted
技术标签:
【中文标题】如何在 Xamarin/Android 上启用多个 BLE 特征通知?【英文标题】:How to enable multiple BLE characteristic notifications on Xamarin/Android? 【发布时间】:2016-04-11 03:42:52 【问题描述】:我正在尝试使用 Xamarin/android 为多个 BLE 特性启用通知,但似乎无法这样做。如果我尝试一次启用多个事件,该应用似乎停止接收任何 BLE 事件。
谁能确认这是否可以使用 Tamarin/Android。我们有一个原生 ios 应用程序,它可以在启用多个通知的情况下正常工作。我们使用的基本步骤如下:
-
扫描设备
连接到设备
发现服务
对于每个发现的服务,遍历特征并启用所需的特征
在 BLE 回调中处理每个异步回调事件
每当我们尝试启用多个特征的通知时,我们都不会再收到任何事件。
我也找不到任何启用多个特性的示例。
我希望我只是在这里错过了使用 Xamarin/Android API 的一些基本知识。
public override void OnServicesDiscovered (BluetoothGatt gatt, GattStatus status)
base.OnServicesDiscovered (gatt, status);
foreach (BluetoothGattService service in gatt.Services)
string uuid = service.Uuid.ToString ().ToUpper();
if (uuid.Equals (BLEServices.HRService.ToUpper()))
_Adap.LogMessage ("HRService discovered");
foreach(BluetoothGattCharacteristic characteristic in service.Characteristics)
string c_uuid = characteristic.Uuid.ToString ().ToUpper ();
_Adap.LogMessage (" HRCharacteristic: " + c_uuid);
if (c_uuid.Equals(_Adap.useCharacteristic.ToUpper()))
_Adap.LogMessage (" enabling HRCharacteristic");
gatt.SetCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor (Java.Util.UUID.FromString (BLEServices.CLIENT_CHARACTERISTIC_CONFIG), GattDescriptorPermission.Write | GattDescriptorPermission.Read);
characteristic.AddDescriptor (descriptor);
descriptor.SetValue (BluetoothGattDescriptor.EnableNotificationValue.ToArray ());
gatt.WriteDescriptor (descriptor);
_Adap.StartTimer ();
else if (uuid.Equals (BLEServices.BatteryService.ToUpper()))
_Adap.LogMessage ("BatteryService discovered");
foreach (BluetoothGattCharacteristic characteristic in service.Characteristics)
string c_uuid = characteristic.Uuid.ToString ().ToUpper ();
_Adap.LogMessage (" BatteryService: " + c_uuid);
if (c_uuid.Equals (_Adap.useCharacteristic.ToUpper ()))
_Adap.LogMessage (" reading batteryCharacteristic");
// This may only be reported when the battery level changes so get the level first by doing a read
gatt.ReadCharacteristic (characteristic);
//gatt.SetCharacteristicNotification (characteristic, true);
//BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor (Java.Util.UUID.FromString (BLEServices.CLIENT_CHARACTERISTIC_CONFIG), GattDescriptorPermission.Write | GattDescriptorPermission.Read);
//characteristic.AddDescriptor (descriptor);
//descriptor.SetValue (BluetoothGattDescriptor.EnableNotificationValue.ToArray ());
//gatt.WriteDescriptor (descriptor);
else if (uuid.Equals (BLEServices.DeviceInfoService.ToUpper()))
_Adap.LogMessage ("DeviceInfoService discovered");
foreach (BluetoothGattCharacteristic characteristic in service.Characteristics)
string c_uuid = characteristic.Uuid.ToString ().ToUpper ();
_Adap.LogMessage (" DeviceInfoService: " + c_uuid);
if (c_uuid.Equals (BLEServices.kModelNumberCharacteristicUuidString.ToUpper ()))
//gatt.ReadCharacteristic (characteristic);
else if (uuid.Equals (BLEServices.kHxM2CustomServiceUuidString.ToUpper()))
_Adap.LogMessage ("HxM2CustomService discovered");
foreach (BluetoothGattCharacteristic characteristic in service.Characteristics)
string c_uuid = characteristic.Uuid.ToString ().ToUpper ();
_Adap.LogMessage (" HxM2CustomCharacteristic: " + c_uuid);
if (c_uuid.Equals (_Adap.useCharacteristic.ToUpper ()))
_Adap.LogMessage (" enabling HxM2 characteristic: "+_Adap.useCharacteristic);
gatt.SetCharacteristicNotification (characteristic, true);
BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor (Java.Util.UUID.FromString (BLEServices.CLIENT_CHARACTERISTIC_CONFIG), GattDescriptorPermission.Write | GattDescriptorPermission.Read);
characteristic.AddDescriptor (descriptor);
descriptor.SetValue (BluetoothGattDescriptor.EnableNotificationValue.ToArray ());
gatt.WriteDescriptor (descriptor);
// Start a timer to make sure that we can recover if we never receive any data from the device
_Adap.StartTimer ();
else
_Adap.LogMessage ("Unknown Service "+uuid+" discovered");
谁能解释以下几行的含义
BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor (Java.Util.UUID.FromString (BLEServices.CLIENT_CHARACTERISTIC_CONFIG), GattDescriptorPermission.Write | GattDescriptorPermission.Read);
characteristic.AddDescriptor (descriptor);
descriptor.SetValue (BluetoothGattDescriptor.EnableNotificationValue.ToArray ());
gatt.WriteDescriptor (descriptor);
【问题讨论】:
终于找到了可行的方法:***.com/questions/17910322/…***.com/questions/21278993/… 【参考方案1】:除了您找到的解决方案:请注意,您不能听无限数量的特征。最大值限制在 android 源代码中硬编码为 BTA_GATTC_NOTIF_REG_MAX
。
因此,您的应用所依赖的通知特性的数量不应超过您支持的最低 Android 版本的最大数量。
【讨论】:
【参考方案2】:有很多可用的选项,但我习惯于用下面的逻辑来实现这个特性,它会真正起作用,请尝试一下:
public ConnectThread(BluetoothDevice device, BluetoothDeviceConnector deviceConnector)
_mmDevice = device;
BluetoothSocket tmp = null;
_deviceConnector = deviceConnector;
Log.Info(Tag, "calling device.createRfcommSocket with channel 1 ...");
try
//tmp = device.CreateRfcommSocketToServiceRecord(UUID.FromString("00001101-0000-1000-8000-00805F9B34FB"));
//tmp = device.CreateRfcommSocketToServiceRecord(device.GetUuids()[0].Uuid);
deviceConnector.BluetoothAdapter.CancelDiscovery();
var createRfcommSocket = JNIEnv.GetMethodID(device.Class.Handle, "createInsecureRfcommSocket", "(I)Landroid/bluetooth/BluetoothSocket;");
var socket = JNIEnv.CallObjectMethod(device.Handle, createRfcommSocket, new JValue(1));
tmp = GetObject<BluetoothSocket>(socket, JniHandleOwnership.TransferLocalRef);
var uuidList = device.GetUuids();
if (uuidList != null)
foreach (var uuid in uuidList)
try
tmp = device.CreateInsecureRfcommSocketToServiceRecord(uuid.Uuid);
tmp.Connect();
if (tmp.IsConnected)
break;
catch (Exception)
// ignored
Log.Info(Tag, "setting socket to result of createRfcommSocket");
catch (Exception e)
Log.Error(Tag, e.Message, e);
_mmSocket = tmp;
【讨论】:
以上是关于如何在 Xamarin/Android 上启用多个 BLE 特征通知?的主要内容,如果未能解决你的问题,请参考以下文章
如何在xamarin android中启用浮动通知和锁屏通知(Java或Kotlin都可以)
Xamarin Android 保留来自 Linking 的方法
为啥我的 Xamarin.Android 项目不能在启用 Proguard 的情况下构建:“java.exe”退出代码 1
如何在 listView Xamarin Android 中使用具有多个 Textview 列的 ArrayAdapter