diff options
author | Alex Blasche <alexander.blasche@digia.com> | 2014-10-20 08:39:04 +0200 |
---|---|---|
committer | Alex Blasche <alexander.blasche@digia.com> | 2014-10-28 13:59:43 +0100 |
commit | 04cb0d4af57cecdb6e47a6e2235083035580fa0d (patch) | |
tree | bcf62e2329f5aad1346f00b53e77c393dcc7961e /src/bluetooth/android | |
parent | a7b0b599775864743d1436d3cbd9513f92eb2d06 (diff) |
Android: Add BluetoothLE device scan
Change-Id: Ibbb1e9f141d494327082aebaf9e34ffe44039115
Reviewed-by: Timur Pocheptsov <Timur.Pocheptsov@digia.com>
Reviewed-by: Alex Blasche <alexander.blasche@digia.com>
Diffstat (limited to 'src/bluetooth/android')
6 files changed, 95 insertions, 46 deletions
diff --git a/src/bluetooth/android/androidbroadcastreceiver_p.h b/src/bluetooth/android/androidbroadcastreceiver_p.h index 347cd968..e09eb6e0 100644 --- a/src/bluetooth/android/androidbroadcastreceiver_p.h +++ b/src/bluetooth/android/androidbroadcastreceiver_p.h @@ -69,6 +69,8 @@ public: protected: friend void QtBroadcastReceiver_jniOnReceive(JNIEnv *, jobject, jlong, jobject, jobject); virtual void onReceive(JNIEnv *env, jobject context, jobject intent) = 0; + friend void QtBluetoothLE_leScanResult(JNIEnv *, jobject, jlong, jobject, jint); + virtual void onReceiveLeScan(JNIEnv *env, jobject jBluetoothDevice, jint rssi) = 0; QAndroidJniObject activityObject; diff --git a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp index db02bc46..4818fa0f 100644 --- a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp +++ b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp @@ -96,6 +96,7 @@ DeviceDiscoveryBroadcastReceiver::DeviceDiscoveryBroadcastReceiver(QObject* pare addAction(valueForStaticField(JavaNames::BluetoothAdapter, JavaNames::ActionDiscoveryFinished)); } +// Runs in Java thread void DeviceDiscoveryBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobject intent) { Q_UNUSED(context); @@ -125,62 +126,84 @@ void DeviceDiscoveryBroadcastReceiver::onReceive(JNIEnv *env, jobject context, j if (!bluetoothDevice.isValid()) return; - const QString deviceName = bluetoothDevice.callObjectMethod<jstring>("getName").toString(); - const QBluetoothAddress deviceAddress(bluetoothDevice.callObjectMethod<jstring>("getAddress").toString()); keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraRssi); - int rssi = intentObject.callMethod<jshort>("getShortExtra", "(Ljava/lang/String;S)S", keyExtra.object<jstring>(), 0); - const QAndroidJniObject bluetoothClass = bluetoothDevice.callObjectMethod("getBluetoothClass", - "()Landroid/bluetooth/BluetoothClass;"); - if (!bluetoothClass.isValid()) - return; - int classType = bluetoothClass.callMethod<jint>("getDeviceClass"); - - - static QList<qint32> services; - if (services.count() == 0) - services << QBluetoothDeviceInfo::PositioningService - << QBluetoothDeviceInfo::NetworkingService - << QBluetoothDeviceInfo::RenderingService - << QBluetoothDeviceInfo::CapturingService - << QBluetoothDeviceInfo::ObjectTransferService - << QBluetoothDeviceInfo::AudioService - << QBluetoothDeviceInfo::TelephonyService - << QBluetoothDeviceInfo::InformationService; - - //Matching BluetoothClass.Service values - qint32 result = 0; - qint32 current = 0; - for (int i = 0; i < services.count(); i++) { - current = services.at(i); - int id = (current << 16); - if (bluetoothClass.callMethod<jboolean>("hasService", "(I)Z", id)) - result |= current; - } - result = result << 13; - classType |= result; + const QBluetoothDeviceInfo info = retrieveDeviceInfo(env, bluetoothDevice, rssi); + if (info.isValid()) + emit deviceDiscovered(info, false); + } +} - QBluetoothDeviceInfo info(deviceAddress, deviceName, classType); - info.setRssi(rssi); +// Runs in Java thread +void DeviceDiscoveryBroadcastReceiver::onReceiveLeScan( + JNIEnv *env, jobject jBluetoothDevice, jint rssi) +{ + qCDebug(QT_BT_ANDROID) << "DeviceDiscoveryBroadcastReceiver::onReceiveLeScan()"; + const QAndroidJniObject bluetoothDevice(jBluetoothDevice); + if (!bluetoothDevice.isValid()) + return; + + const QBluetoothDeviceInfo info = retrieveDeviceInfo(env, bluetoothDevice, rssi); + if (info.isValid()) + emit deviceDiscovered(info, true); +} - if (QtAndroidPrivate::androidSdkVersion() >= 18) { - jint javaBtType = bluetoothDevice.callMethod<jint>("getType"); +QBluetoothDeviceInfo DeviceDiscoveryBroadcastReceiver::retrieveDeviceInfo(JNIEnv *env, const QAndroidJniObject &bluetoothDevice, int rssi) +{ + const QString deviceName = bluetoothDevice.callObjectMethod<jstring>("getName").toString(); + const QBluetoothAddress deviceAddress(bluetoothDevice.callObjectMethod<jstring>("getAddress").toString()); + + const QAndroidJniObject bluetoothClass = bluetoothDevice.callObjectMethod("getBluetoothClass", + "()Landroid/bluetooth/BluetoothClass;"); + if (!bluetoothClass.isValid()) + return QBluetoothDeviceInfo(); + int classType = bluetoothClass.callMethod<jint>("getDeviceClass"); + + + static QList<qint32> services; + if (services.count() == 0) + services << QBluetoothDeviceInfo::PositioningService + << QBluetoothDeviceInfo::NetworkingService + << QBluetoothDeviceInfo::RenderingService + << QBluetoothDeviceInfo::CapturingService + << QBluetoothDeviceInfo::ObjectTransferService + << QBluetoothDeviceInfo::AudioService + << QBluetoothDeviceInfo::TelephonyService + << QBluetoothDeviceInfo::InformationService; + + //Matching BluetoothClass.Service values + qint32 result = 0; + qint32 current = 0; + for (int i = 0; i < services.count(); i++) { + current = services.at(i); + int id = (current << 16); + if (bluetoothClass.callMethod<jboolean>("hasService", "(I)Z", id)) + result |= current; + } - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - env->ExceptionClear(); - } else { - info.setCoreConfigurations(qtBtTypeForJavaBtType(javaBtType)); - } - } + result = result << 13; + classType |= result; + + QBluetoothDeviceInfo info(deviceAddress, deviceName, classType); + info.setRssi(rssi); + + if (QtAndroidPrivate::androidSdkVersion() >= 18) { + jint javaBtType = bluetoothDevice.callMethod<jint>("getType"); - emit deviceDiscovered(info); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + env->ExceptionClear(); + } else { + info.setCoreConfigurations(qtBtTypeForJavaBtType(javaBtType)); + } } + + return info; } QT_END_NAMESPACE diff --git a/src/bluetooth/android/devicediscoverybroadcastreceiver_p.h b/src/bluetooth/android/devicediscoverybroadcastreceiver_p.h index 4ed7027d..5378e9aa 100644 --- a/src/bluetooth/android/devicediscoverybroadcastreceiver_p.h +++ b/src/bluetooth/android/devicediscoverybroadcastreceiver_p.h @@ -59,10 +59,15 @@ class DeviceDiscoveryBroadcastReceiver : public AndroidBroadcastReceiver public: DeviceDiscoveryBroadcastReceiver(QObject* parent = 0); virtual void onReceive(JNIEnv *env, jobject context, jobject intent); + virtual void onReceiveLeScan(JNIEnv *env, jobject jBluetoothDevice, jint rssi); signals: - void deviceDiscovered(const QBluetoothDeviceInfo &info); + void deviceDiscovered(const QBluetoothDeviceInfo &info, bool isLeScanResult); void finished(); + +private: + QBluetoothDeviceInfo retrieveDeviceInfo(JNIEnv *env, const QAndroidJniObject& bluetoothDevice, + int rssi); }; QT_END_NAMESPACE diff --git a/src/bluetooth/android/jni_android.cpp b/src/bluetooth/android/jni_android.cpp index faeb411a..061d6ce2 100644 --- a/src/bluetooth/android/jni_android.cpp +++ b/src/bluetooth/android/jni_android.cpp @@ -183,12 +183,23 @@ static void QtBluetoothInputStreamThread_readyData(JNIEnv */*env*/, jobject /*ja reinterpret_cast<InputStreamThread*>(qtObject)->javaReadyRead(buffer, bufferLength); } +void QtBluetoothLE_leScanResult(JNIEnv *env, jobject, jlong qtObject, jobject bluetoothDevice, jint rssi) +{ + reinterpret_cast<AndroidBroadcastReceiver*>(qtObject)->onReceiveLeScan( + env, bluetoothDevice, rssi); +} + static JNINativeMethod methods[] = { {"jniOnReceive", "(JLandroid/content/Context;Landroid/content/Intent;)V", (void *) QtBroadcastReceiver_jniOnReceive}, }; +static JNINativeMethod methods_le[] = { + {"leScanResult", "(JLandroid/bluetooth/BluetoothDevice;I)V", + (void *) QtBluetoothLE_leScanResult}, +}; + static JNINativeMethod methods_server[] = { {"errorOccurred", "(JI)V", (void *) QtBluetoothSocketServer_errorOccurred}, @@ -218,12 +229,18 @@ static bool registerNatives(JNIEnv *env) jclass clazz; FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver"); - if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0) { __android_log_print(ANDROID_LOG_FATAL, logTag, "RegisterNatives for BraodcastReceiver failed"); return false; } + FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/bluetooth/QtBluetoothLE"); + if (env->RegisterNatives(clazz, methods_le, sizeof(methods_le) / sizeof(methods_le[0])) < 0) { + __android_log_print(ANDROID_LOG_FATAL, logTag, "RegisterNatives for QBLuetoothLE failed"); + return false; + } + + FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer"); if (env->RegisterNatives(clazz, methods_server, sizeof(methods_server) / sizeof(methods_server[0])) < 0) { __android_log_print(ANDROID_LOG_FATAL, logTag, "RegisterNatives for SocketServer failed"); diff --git a/src/bluetooth/android/localdevicebroadcastreceiver_p.h b/src/bluetooth/android/localdevicebroadcastreceiver_p.h index 190ae631..c3830c8c 100644 --- a/src/bluetooth/android/localdevicebroadcastreceiver_p.h +++ b/src/bluetooth/android/localdevicebroadcastreceiver_p.h @@ -58,6 +58,7 @@ public: explicit LocalDeviceBroadcastReceiver(QObject *parent = 0); virtual ~LocalDeviceBroadcastReceiver() {} virtual void onReceive(JNIEnv *env, jobject context, jobject intent); + virtual void onReceiveLeScan(JNIEnv *, jobject, jint) {} bool pairingConfirmation(bool accept); signals: diff --git a/src/bluetooth/android/servicediscoverybroadcastreceiver_p.h b/src/bluetooth/android/servicediscoverybroadcastreceiver_p.h index 273af121..3e9e9c7f 100644 --- a/src/bluetooth/android/servicediscoverybroadcastreceiver_p.h +++ b/src/bluetooth/android/servicediscoverybroadcastreceiver_p.h @@ -60,6 +60,7 @@ class ServiceDiscoveryBroadcastReceiver : public AndroidBroadcastReceiver public: ServiceDiscoveryBroadcastReceiver(QObject* parent = 0); virtual void onReceive(JNIEnv *env, jobject context, jobject intent); + virtual void onReceiveLeScan(JNIEnv *, jobject, jint) {} static QList<QBluetoothUuid> convertParcelableArray(const QAndroidJniObject &obj); |