summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothGattCharacteristic.java26
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java49
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java47
-rw-r--r--src/bluetooth/qlowenergycontroller_android.cpp3
4 files changed, 98 insertions, 27 deletions
diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothGattCharacteristic.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothGattCharacteristic.java
index c8779b00..375aebb5 100644
--- a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothGattCharacteristic.java
+++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothGattCharacteristic.java
@@ -4,7 +4,7 @@
package org.qtproject.qt.android.bluetooth;
import android.bluetooth.BluetoothGattCharacteristic;
-import android.util.Log;
+import android.os.Build;
import java.util.UUID;
@@ -17,4 +17,28 @@ public class QtBluetoothGattCharacteristic extends BluetoothGattCharacteristic {
}
public int minValueLength;
public int maxValueLength;
+ // Starting from API 33 Android Bluetooth deprecates characteristic local value caching by
+ // deprecating the getValue() and setValue() accessors. For peripheral role we store the value
+ // locally in the characteristic as a convenience - looking up the value on the C++ side would
+ // be somewhat complicated. This should be safe as all accesses to this class are synchronized.
+ // For clarity: For API levels below 33 we still need to use the setValue() of the base class
+ // because Android internally uses getValue() with APIs below 33.
+ public boolean setLocalValue(byte[] value) {
+ if (Build.VERSION.SDK_INT >= 33) {
+ m_localValue = value;
+ return true;
+ } else {
+ return setValue(value);
+ }
+ }
+
+ public byte[] getLocalValue()
+ {
+ if (Build.VERSION.SDK_INT >= 33)
+ return m_localValue;
+ else
+ return getValue();
+ }
+
+ private byte[] m_localValue = null;
}
diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java
index 8e8a0958..57accf3b 100644
--- a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java
+++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java
@@ -17,6 +17,7 @@ import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
+import android.bluetooth.BluetoothStatusCodes;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -345,8 +346,9 @@ public class QtBluetoothLE {
}
private synchronized void handleOnCharacteristicRead(BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic,
- int status)
+ BluetoothGattCharacteristic characteristic,
+ byte[] value,
+ int status)
{
int foundHandle = handleForCharacteristic(characteristic);
if (foundHandle == -1 || foundHandle >= entries.size() ) {
@@ -380,7 +382,7 @@ public class QtBluetoothLE {
leCharacteristicRead(qtObject,
characteristic.getService().getUuid().toString(),
foundHandle + 1, characteristic.getUuid().toString(),
- characteristic.getProperties(), characteristic.getValue());
+ characteristic.getProperties(), value);
} else {
if (isServiceDiscoveryRun) {
Log.w(TAG, "onCharacteristicRead during discovery error: " + status);
@@ -389,7 +391,7 @@ public class QtBluetoothLE {
" for service " + characteristic.getService().getUuid());
leCharacteristicRead(qtObject, characteristic.getService().getUuid().toString(),
foundHandle + 1, characteristic.getUuid().toString(),
- characteristic.getProperties(), characteristic.getValue());
+ characteristic.getProperties(), value);
} else {
// This must be in sync with QLowEnergyService::CharacteristicReadError
final int characteristicReadError = 5;
@@ -412,7 +414,8 @@ public class QtBluetoothLE {
}
private synchronized void handleOnCharacteristicChanged(android.bluetooth.BluetoothGatt gatt,
- android.bluetooth.BluetoothGattCharacteristic characteristic)
+ android.bluetooth.BluetoothGattCharacteristic characteristic,
+ byte[] value)
{
int handle = handleForCharacteristic(characteristic);
if (handle == -1) {
@@ -420,7 +423,7 @@ public class QtBluetoothLE {
return;
}
- leCharacteristicChanged(qtObject, handle+1, characteristic.getValue());
+ leCharacteristicChanged(qtObject, handle+1, value);
}
private synchronized void handleOnCharacteristicWrite(android.bluetooth.BluetoothGatt gatt,
@@ -651,12 +654,24 @@ public class QtBluetoothLE {
}
+ // API < 33
public void onCharacteristicRead(android.bluetooth.BluetoothGatt gatt,
android.bluetooth.BluetoothGattCharacteristic characteristic,
int status)
{
super.onCharacteristicRead(gatt, characteristic, status);
- handleOnCharacteristicRead(gatt, characteristic, status);
+ handleOnCharacteristicRead(gatt, characteristic, characteristic.getValue(), status);
+ }
+
+ // API >= 33
+ public void onCharacteristicRead(android.bluetooth.BluetoothGatt gatt,
+ android.bluetooth.BluetoothGattCharacteristic characteristic,
+ byte[] value,
+ int status)
+ {
+ // Note: here we don't call the super implementation as it calls the old "< API 33"
+ // callback, and the callback would be handled twice
+ handleOnCharacteristicRead(gatt, characteristic, value, status);
}
public void onCharacteristicWrite(android.bluetooth.BluetoothGatt gatt,
@@ -667,11 +682,22 @@ public class QtBluetoothLE {
handleOnCharacteristicWrite(gatt, characteristic, status);
}
+ // API < 33
public void onCharacteristicChanged(android.bluetooth.BluetoothGatt gatt,
android.bluetooth.BluetoothGattCharacteristic characteristic)
{
super.onCharacteristicChanged(gatt, characteristic);
- handleOnCharacteristicChanged(gatt, characteristic);
+ handleOnCharacteristicChanged(gatt, characteristic, characteristic.getValue());
+ }
+
+ // API >= 33
+ public void onCharacteristicChanged(android.bluetooth.BluetoothGatt gatt,
+ android.bluetooth.BluetoothGattCharacteristic characteristic,
+ byte[] value)
+ {
+ // Note: here we don't call the super implementation as it calls the old "< API 33"
+ // callback, and the callback would be handled twice
+ handleOnCharacteristicChanged(gatt, characteristic, value);
}
public void onDescriptorRead(android.bluetooth.BluetoothGatt gatt,
@@ -1527,7 +1553,7 @@ public class QtBluetoothLE {
+ " for service " + entry.characteristic.getService().getUuid());
leCharacteristicRead(qtObject, entry.characteristic.getService().getUuid().toString(),
handle + 1, entry.characteristic.getUuid().toString(),
- entry.characteristic.getProperties(), entry.characteristic.getValue());
+ entry.characteristic.getProperties(), null);
break;
case Descriptor:
Log.d(TAG,
@@ -1594,6 +1620,11 @@ public class QtBluetoothLE {
boolean result;
switch (nextJob.entry.type) {
case Characteristic:
+ if (Build.VERSION.SDK_INT >= 33) {
+ int writeResult = mBluetoothGatt.writeCharacteristic(
+ nextJob.entry.characteristic, nextJob.newValue, nextJob.requestedWriteType);
+ return (writeResult != BluetoothStatusCodes.SUCCESS);
+ }
if (mHandler != null || mCharacteristicConstructor == null) {
if (nextJob.entry.characteristic.getWriteType() != nextJob.requestedWriteType) {
nextJob.entry.characteristic.setWriteType(nextJob.requestedWriteType);
diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java
index f595dec0..6d4a1fa7 100644
--- a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java
+++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java
@@ -20,6 +20,7 @@ import android.bluetooth.le.AdvertiseData.Builder;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.os.ParcelUuid;
+import android.os.Build;
import android.util.Log;
import android.util.Pair;
@@ -389,15 +390,18 @@ public class QtBluetoothLEServer {
Log.w(TAG, "Ignoring characteristic read, server is disconnected");
return;
}
- byte[] dataArray;
+
+ byte[] characteristicData =
+ ((QtBluetoothGattCharacteristic)characteristic).getLocalValue();
+
try {
- dataArray = Arrays.copyOfRange(characteristic.getValue(),
- offset, characteristic.getValue().length);
+ byte[] dataArray = Arrays.copyOfRange(characteristicData,
+ offset, characteristicData.length);
mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS,
offset, dataArray);
} catch (Exception ex) {
Log.w(TAG, "onCharacteristicReadRequest: " + requestId + " "
- + offset + " " + characteristic.getValue().length);
+ + offset + " " + characteristicData.length);
ex.printStackTrace();
mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_FAILURE,
offset, null);
@@ -432,7 +436,7 @@ public class QtBluetoothLEServer {
+ value.length + ", min: " + minValueLen + ", max: " + maxValueLen);
resultStatus = BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH;
} else if (offset == 0) {
- characteristic.setValue(value);
+ ((QtBluetoothGattCharacteristic)characteristic).setLocalValue(value);
leServerCharacteristicChanged(qtObject, characteristic, value);
sendNotificationOrIndication = true;
} else {
@@ -559,8 +563,8 @@ public class QtBluetoothLEServer {
byte[] newValue = null;
// The target can be a descriptor or a characteristic
byte[] currentValue = (entry.target instanceof BluetoothGattCharacteristic)
- ? ((BluetoothGattCharacteristic)entry.target).getValue()
- : ((BluetoothGattDescriptor)entry.target).getValue();
+ ? ((QtBluetoothGattCharacteristic)entry.target).getLocalValue()
+ : ((BluetoothGattDescriptor)entry.target).getValue();
// Iterate writes and apply them to the currentValue in received order
for (Pair<byte[], Integer> write : entry.writes) {
@@ -607,7 +611,7 @@ public class QtBluetoothLEServer {
// Update value and inform the Qt/C++ side on the update
if (entry.target instanceof BluetoothGattCharacteristic) {
- ((BluetoothGattCharacteristic)entry.target).setValue(newValue);
+ ((QtBluetoothGattCharacteristic)entry.target).setLocalValue(newValue);
leServerCharacteristicChanged(
qtObject, (BluetoothGattCharacteristic)entry.target, newValue);
} else {
@@ -819,12 +823,25 @@ public class QtBluetoothLEServer {
// devices at the same time.
while (iter.hasNext()) {
final BluetoothDevice device = iter.next();
- final byte[] clientCharacteristicConfig = clientCharacteristicManager.valueFor(characteristic, device);
+ final byte[] clientCharacteristicConfig =
+ clientCharacteristicManager.valueFor(characteristic, device);
if (clientCharacteristicConfig != null) {
- if (Arrays.equals(clientCharacteristicConfig, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)) {
- mGattServer.notifyCharacteristicChanged(device, characteristic, false);
- } else if (Arrays.equals(clientCharacteristicConfig, BluetoothGattDescriptor.ENABLE_INDICATION_VALUE)) {
- mGattServer.notifyCharacteristicChanged(device, characteristic, true);
+ if (Arrays.equals(clientCharacteristicConfig,
+ BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)) {
+ if (Build.VERSION.SDK_INT >= 33) {
+ mGattServer.notifyCharacteristicChanged(device, characteristic, false,
+ ((QtBluetoothGattCharacteristic)characteristic).getLocalValue());
+ } else {
+ mGattServer.notifyCharacteristicChanged(device, characteristic, false);
+ }
+ } else if (Arrays.equals(clientCharacteristicConfig,
+ BluetoothGattDescriptor.ENABLE_INDICATION_VALUE)) {
+ if (Build.VERSION.SDK_INT >= 33) {
+ mGattServer.notifyCharacteristicChanged(device, characteristic, true,
+ ((QtBluetoothGattCharacteristic)characteristic).getLocalValue());
+ } else {
+ mGattServer.notifyCharacteristicChanged(device, characteristic, true);
+ }
}
}
}
@@ -832,7 +849,7 @@ public class QtBluetoothLEServer {
/*
Updates the local database value for the given characteristic with \a charUuid and
- \a newValue. If notifications for this task are enabled an approproiate notification will
+ \a newValue. If notifications for this task are enabled an appropriate notification will
be send to the remote client.
This function is called from the Qt thread.
@@ -869,7 +886,7 @@ public class QtBluetoothLEServer {
synchronized (this) // a value update might be in progress
{
- foundChar.setValue(newValue);
+ ((QtBluetoothGattCharacteristic)foundChar).setLocalValue(newValue);
// Value is updated even if server is not connected, but notifying is not possible
if (mGattServer != null)
sendNotificationsOrIndications(foundChar);
diff --git a/src/bluetooth/qlowenergycontroller_android.cpp b/src/bluetooth/qlowenergycontroller_android.cpp
index 2d7839ad..0350b163 100644
--- a/src/bluetooth/qlowenergycontroller_android.cpp
+++ b/src/bluetooth/qlowenergycontroller_android.cpp
@@ -1220,10 +1220,9 @@ void QLowEnergyControllerPrivateAndroid::addToGenericAttributeList(const QLowEne
QJniEnvironment env;
jbyteArray jb = env->NewByteArray(charData.value().size());
env->SetByteArrayRegion(jb, 0, charData.value().size(), (jbyte*)charData.value().data());
- jboolean success = javaChar.callMethod<jboolean>("setValue", jb);
+ jboolean success = javaChar.callMethod<jboolean>("setLocalValue", jb);
if (!success)
qCWarning(QT_BT_ANDROID) << "Cannot setup initial characteristic value for " << charData.uuid();
-
env->DeleteLocalRef(jb);
const QList<QLowEnergyDescriptorData> descriptorList = charData.descriptors();