diff options
author | Alex Blasche <alexander.blasche@digia.com> | 2014-03-12 15:27:05 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-03-24 08:53:56 +0100 |
commit | 250d32fa832e5de1ce3e0961374a65bb84492a33 (patch) | |
tree | 713edf7b01fff6675e6a01c6ddc0686be0447ca6 | |
parent | 08e2153a216a4f2cd4ec71a2013031e4d2d12197 (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.java | 52 | ||||
-rw-r--r-- | src/bluetooth/qbluetoothlocaldevice_android.cpp | 38 |
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 |