Я пишу приложение для Android с Xamarin.Android, но ответ на родном Android также будет оценен. В моем приложении для Android есть характеристика записи BLE, на которую устройства могут записывать. Это работает, но я не могу отправить больше 20 байтов, остальное обрезается. Мой код для создания и добавления услуги / характеристики:
BluetoothGattService service = new BluetoothGattService(Java.Util.UUID.FromString(MyServiceUuid), GattServiceType.Primary);
// write characteristic (write-only, supports subscriptions)
BluetoothGattCharacteristic writeCharacteristic = new BluetoothGattCharacteristic(Java.Util.UUID.FromString(MyCharacteristicUuid), GattProperty.WriteNoResponse | GattProperty.Notify, GattPermission.Write);
service.AddCharacteristic(writeCharacteristic);
_bluetoothGattServer.AddService(service);
Мой код на стороне, которая пишет в характеристику:
public override void OnServicesDiscovered(BluetoothGatt gatt, [GeneratedEnum] GattStatus status)
{
base.OnServicesDiscovered(gatt, status);
characteristic = gatt.GetService(Java.Util.UUID.FromString(MyServiceUuid))
.GetCharacteristic(Java.Util.UUID.FromString(MyCharacteristicUuid));
if(characteristic.Properties.HasFlag(GattProperty.WriteNoResponse))
{
Log?.Invoke("writing characteristic...");
characteristic.SetValue(MyVeryLongString);
characteristic.WriteType = GattWriteType.NoResponse;
gatt.WriteCharacteristic(characteristic);
}
}
И на стороне, которая принимает запрос на запись:
public override void OnCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, bool preparedWrite, bool responseNeeded, int offset, byte[] value)
{
base.OnCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
Log?.Invoke("OnCharacteristicWriteRequest");
string data = System.Text.Encoding.UTF8.GetString(value);
Log?.Invoke(data);
if(responseNeeded)
{
BluetoothGattServer.SendResponse(device, requestId, GattStatus.Success, 0, Encoding.ASCII.GetBytes("ok"));
}
}
Я вижу, что есть offset
, но эта функция вызывается только один раз. Должно быть, я что-то упускаю с одной стороны?
Самое смешное, что когда я тестирую это Android-приложение с iOS-версией своего приложения, у меня нет этой проблемы. У меня проблема возникает только тогда, когда оба устройства являются Android.
EDIT
Моя новая реализация OnCharacteristicWriteRequest
:
public override void OnCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, bool preparedWrite, bool responseNeeded, int offset, byte[] value)
{
base.OnCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
Log?.Invoke("OnCharacteristicWriteRequest");
string data = System.Text.Encoding.UTF8.GetString(value);
Log?.Invoke(data);
Guid characteristicId = new Guid(characteristic.Uuid.ToString());
var record = _writeCharacteristicsReceived.FirstOrDefault(c => c.DeviceAddress == device.Address && c.CharacteristicId == characteristicId);
if(record != null)
{
record.Data += data;
}
else
{
record = new CharacteristicWriteReceived()
{
CharacteristicId = characteristicId,
DeviceAddress = device.Address,
Data = data
};
_writeCharacteristicsReceived.Add(record);
}
if (record?.Data.EndsWith(Constants.WriteCharacteristicEndDelimiter) == true)
{
_writeCharacteristicsReceived.Remove(record);
record.Data = record.Data.Substring(0, record.Data.Length - Constants.WriteCharacteristicEndDelimiter.Length); // remove the end delimeter
Log?.Invoke(record.Data);
OnCharacteristicWriteReceived?.Invoke(record);
}
if (responseNeeded)
{
BluetoothGattServer.SendResponse(device, requestId, GattStatus.Success, offset, value);
}
}