void LocalDeviceBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobject intent) { Q_UNUSED(context); Q_UNUSED(env); QAndroidJniObject intentObject(intent); const QString action = intentObject.callObjectMethod("getAction", "()Ljava/lang/String;").toString(); qCDebug(QT_BT_ANDROID) << QStringLiteral("LocalDeviceBroadcastReceiver::onReceive() - event: %1").arg(action); if (action == valueForStaticField(JavaNames::BluetoothAdapter, JavaNames::ActionScanModeChanged).toString()) { const QAndroidJniObject extrasBundle = intentObject.callObjectMethod("getExtras","()Landroid/os/Bundle;"); const QAndroidJniObject keyExtra = valueForStaticField(JavaNames::BluetoothAdapter, JavaNames::ExtraScanMode); int extra = extrasBundle.callMethod<jint>("getInt", "(Ljava/lang/String;)I", keyExtra.object<jstring>()); if (previousScanMode != extra) { previousScanMode = extra; if (extra == hostModePreset[0]) emit hostModeStateChanged(QBluetoothLocalDevice::HostPoweredOff); else if (extra == hostModePreset[1]) emit hostModeStateChanged(QBluetoothLocalDevice::HostConnectable); else if (extra == hostModePreset[2]) emit hostModeStateChanged(QBluetoothLocalDevice::HostDiscoverable); else qCWarning(QT_BT_ANDROID) << "Unknown Host State"; } } else if (action == valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionBondStateChanged).toString()) { //get BluetoothDevice QAndroidJniObject keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraDevice); const QAndroidJniObject bluetoothDevice = intentObject.callObjectMethod("getParcelableExtra", "(Ljava/lang/String;)Landroid/os/Parcelable;", keyExtra.object<jstring>()); //get new bond state keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraBondState); const QAndroidJniObject extrasBundle = intentObject.callObjectMethod("getExtras","()Landroid/os/Bundle;"); int bondState = extrasBundle.callMethod<jint>("getInt", "(Ljava/lang/String;)I", keyExtra.object<jstring>()); QBluetoothAddress address(bluetoothDevice.callObjectMethod<jstring>("getAddress").toString()); if (address.isNull()) return; if (bondState == bondingModePreset[0]) emit pairingStateChanged(address, QBluetoothLocalDevice::Unpaired); else if (bondState == bondingModePreset[1]) ; //we ignore this as Qt doesn't have equivalent API value else if (bondState == bondingModePreset[2]) emit pairingStateChanged(address, QBluetoothLocalDevice::Paired); else qCWarning(QT_BT_ANDROID) << "Unknown BOND_STATE_CHANGED value:" << bondState; } else if (action == valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionAclConnected).toString() || action == valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionAclDisconnected).toString()) { const QString connectEvent = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionAclConnected).toString(); const bool isConnectEvent = action == connectEvent ? true : false; //get BluetoothDevice const QAndroidJniObject keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraDevice); QAndroidJniObject bluetoothDevice = intentObject.callObjectMethod("getParcelableExtra", "(Ljava/lang/String;)Landroid/os/Parcelable;", keyExtra.object<jstring>()); QBluetoothAddress address(bluetoothDevice.callObjectMethod<jstring>("getAddress").toString()); if (address.isNull()) return; emit connectDeviceChanges(address, isConnectEvent); } else if (action == valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionPairingRequest).toString()) { QAndroidJniObject keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraPairingVariant); int variant = intentObject.callMethod<jint>("getIntExtra", "(Ljava/lang/String;I)I", keyExtra.object<jstring>(), -1); int key = -1; switch (variant) { case -1: //ignore -> no pairing variant set return; case 2: //BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION { keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraPairingKey); key = intentObject.callMethod<jint>("getIntExtra", "(Ljava/lang/String;I)I", keyExtra.object<jstring>(), -1); if (key == -1) return; keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraDevice); QAndroidJniObject bluetoothDevice = intentObject.callObjectMethod("getParcelableExtra", "(Ljava/lang/String;)Landroid/os/Parcelable;", keyExtra.object<jstring>()); //we need to keep a reference around in case the user confirms later on pairingDevice = bluetoothDevice; QBluetoothAddress address(bluetoothDevice.callObjectMethod<jstring>("getAddress").toString()); //User has choice to confirm or not. If no confirmation is happening //the OS default pairing dialog can be used or timeout occurs. emit pairingDisplayConfirmation(address, QString::number(key)); break; } default: qCWarning(QT_BT_ANDROID) << "Unknown pairing variant: " << variant; return; } } }
void DeviceDiscoveryBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobject intent) { Q_UNUSED(context); Q_UNUSED(env); QAndroidJniObject intentObject(intent); const QString action = intentObject.callObjectMethod("getAction", "()Ljava/lang/String;").toString(); qCDebug(QT_BT_ANDROID) << "DeviceDiscoveryBroadcastReceiver::onReceive() - event:" << action; if (action == valueForStaticField(JavaNames::BluetoothAdapter, JavaNames::ActionDiscoveryFinished).toString()) { emit finished(); } else if (action == valueForStaticField(JavaNames::BluetoothAdapter, JavaNames::ActionDiscoveryStarted).toString()) { } else if (action == valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionFound).toString()) { //get BluetoothDevice QAndroidJniObject keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraDevice); const QAndroidJniObject bluetoothDevice = intentObject.callObjectMethod("getParcelableExtra", "(Ljava/lang/String;)Landroid/os/Parcelable;", keyExtra.object<jstring>()); 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; QBluetoothDeviceInfo info(deviceAddress, deviceName, classType); info.setRssi(rssi); emit deviceDiscovered(info); } }