summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@digia.com>2014-03-12 15:27:05 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-24 08:53:56 +0100
commit250d32fa832e5de1ce3e0961374a65bb84492a33 (patch)
tree713edf7b01fff6675e6a01c6ddc0686be0447ca6
parent08e2153a216a4f2cd4ec71a2013031e4d2d12197 (diff)
Android: Improve QBluetoothLocalDevice::connectedDevices()
There is no API to get the list of connected Bluetooth devices on Android. However there are service API's which return a list of their current clients. In this particular case we find the GATT related service connections. We use that info to complement the internal list of connected devices. Note that although this is using Bluetooth Low Energy related API's the Qt API does not support this feature at this point in time. Task-number: QTBUG-36764 Change-Id: Ia8266f3a9d24fd16afdd636ca2d3d0a0c6b2b499 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java52
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_android.cpp38
2 files changed, 88 insertions, 2 deletions
diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java
index ba96c0cf..20dbd78f 100644
--- a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java
+++ b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java
@@ -49,7 +49,10 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.List;
public class QtBluetoothBroadcastReceiver extends BroadcastReceiver
{
@@ -126,4 +129,53 @@ public class QtBluetoothBroadcastReceiver extends BroadcastReceiver
return true;
}
+ /*
+ * Returns a list of remote devices confirmed to be connected.
+ *
+ * This list is not complete as it only detects GATT/BtLE related connections.
+ * Unfortunately there is no API that provides the complete list.
+ *
+ * The function uses Android API v11 & v18. We need to use reflection.
+ */
+ static public String[] getConnectedDevices()
+ {
+ try {
+ //Bluetooth service name
+ Field f = Context.class.getField("BLUETOOTH_SERVICE");
+ String serviceValueString = (String)f.get(qtactivity);
+
+ Class btProfileClz = Class.forName("android.bluetooth.BluetoothProfile");
+
+ //value of BluetoothProfile.GATT
+ f = btProfileClz.getField("GATT");
+ int gatt = f.getInt(null);
+
+ //value of BluetoothProfile.GATT_SERVER
+ f = btProfileClz.getField("GATT_SERVER");
+ int gattServer = f.getInt(null);
+
+ //get BluetoothManager instance
+ Object bluetoothManager = qtactivity.getSystemService(serviceValueString);
+
+ Class[] cArg = new Class[1];
+ cArg[0] = int.class;
+ Method m = bluetoothManager.getClass().getMethod("getConnectedDevices", cArg);
+
+ List gattConnections = (List) m.invoke(bluetoothManager, gatt);
+ List gattServerConnections = (List) m.invoke(bluetoothManager, gattServer);
+
+ //process found remote connections but avoid duplications
+ HashSet<String> set = new HashSet<String>();
+ for (int i = 0; i < gattConnections.size(); i++)
+ set.add(gattConnections.get(i).toString());
+
+ for (int i = 0; i < gattServerConnections.size(); i++)
+ set.add(gattServerConnections.get(i).toString());
+
+ return set.toArray(new String[set.size()]);
+ } catch (Exception ex) {
+ //API is less than 18
+ return new String[0];
+ }
+ }
}
diff --git a/src/bluetooth/qbluetoothlocaldevice_android.cpp b/src/bluetooth/qbluetoothlocaldevice_android.cpp
index ff36837b..a6d2b5d6 100644
--- a/src/bluetooth/qbluetoothlocaldevice_android.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_android.cpp
@@ -437,8 +437,42 @@ void QBluetoothLocalDevice::pairingConfirmation(bool confirmation)
QList<QBluetoothAddress> QBluetoothLocalDevice::connectedDevices() const
{
- //TODO Support BLuetoothManager::getConnectedDevices(int) from API 18 onwards
- return d_ptr->connectedDevices;
+ /*
+ * Android does not have an API to list all connected devices. We have to collect
+ * the information based on a few indicators.
+ *
+ * Primarily we detect connected devices by monitoring connect/disconnect signals.
+ * Unfortunately the list may only be complete after very long monitoring time.
+ * However there are some Android APIs which provide the list of connected devices
+ * for specific Bluetooth profiles. QtBluetoothBroadcastReceiver.getConnectedDevices()
+ * returns a few connections of common profiles. The returned list is not complete either
+ * but at least it can complement our already detected connections.
+ */
+ QAndroidJniObject connectedDevices = QAndroidJniObject::callStaticObjectMethod(
+ "org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver",
+ "getConnectedDevices",
+ "()[Ljava/lang/String;");
+
+ if (!connectedDevices.isValid())
+ return d_ptr->connectedDevices;
+
+ jobjectArray connectedDevicesArray = connectedDevices.object<jobjectArray>();
+ if (!connectedDevicesArray)
+ return d_ptr->connectedDevices;
+
+ QAndroidJniEnvironment env;
+ QList<QBluetoothAddress> knownAddresses = d_ptr->connectedDevices;
+ QAndroidJniObject p;
+
+ jint size = env->GetArrayLength(connectedDevicesArray);
+ for (int i = 0; i < size; i++) {
+ p = env->GetObjectArrayElement(connectedDevicesArray, i);
+ QBluetoothAddress address(p.toString());
+ if (!address.isNull() && !knownAddresses.contains(address))
+ knownAddresses.append(address);
+ }
+
+ return knownAddresses;
}
QT_END_NAMESPACE