From afc2ee52eba5dcfad04c462fee31d307e47311ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Fran=C4=8De=C5=A1kin?= Date: Tue, 5 Feb 2019 17:51:29 +0100 Subject: [PATCH] Detect bluetooth gamepad connect/disconnect events --- android/AndroidManifest.xml | 2 + .../mavlink/qgroundcontrol/QGCActivity.java | 11 ++++ src/Joystick/JoystickAndroid.cc | 59 ++++++++++++++++++- src/Joystick/JoystickAndroid.h | 4 +- src/Joystick/JoystickManager.cc | 16 ++++- src/Joystick/JoystickManager.h | 4 ++ 6 files changed, 90 insertions(+), 6 deletions(-) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 28751cdc9..4cfc93760 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -7,6 +7,8 @@ + + diff --git a/android/src/org/mavlink/qgroundcontrol/QGCActivity.java b/android/src/org/mavlink/qgroundcontrol/QGCActivity.java index a716392e6..c3f4fbe8b 100644 --- a/android/src/org/mavlink/qgroundcontrol/QGCActivity.java +++ b/android/src/org/mavlink/qgroundcontrol/QGCActivity.java @@ -48,6 +48,7 @@ import android.util.Log; import android.os.PowerManager; import android.view.WindowManager; import android.os.Bundle; +import android.bluetooth.BluetoothDevice; import com.hoho.android.usbserial.driver.*; import org.qtproject.qt5.android.bindings.QtActivity; @@ -133,6 +134,12 @@ public class QGCActivity extends QtActivity } } } + + try { + nativeUpdateAvailableJoysticks(); + } catch(Exception e) { + Log.e(TAG, "Exception nativeUpdateAvailableJoysticks()"); + } } }; @@ -140,6 +147,7 @@ public class QGCActivity extends QtActivity private static native void nativeDeviceHasDisconnected(int userData); private static native void nativeDeviceException(int userData, String messageA); private static native void nativeDeviceNewData(int userData, byte[] dataA); + private static native void nativeUpdateAvailableJoysticks(); // Native C++ functions called to log output public static native void qgcLogDebug(String message); @@ -171,8 +179,11 @@ public class QGCActivity extends QtActivity // Register for USB Detach and USB Permission intent IntentFilter filter = new IntentFilter(); + filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); filter.addAction(ACTION_USB_PERMISSION); + filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); + filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); _instance.registerReceiver(_instance._usbReceiver, filter); // Create intent for usb permission request diff --git a/src/Joystick/JoystickAndroid.cc b/src/Joystick/JoystickAndroid.cc index d66f0c0b9..3a1a1da31 100644 --- a/src/Joystick/JoystickAndroid.cc +++ b/src/Joystick/JoystickAndroid.cc @@ -134,7 +134,6 @@ QMap JoystickAndroid::discover(MultiVehicleManager* _multiVe env->ReleaseIntArrayElements(jarr, buff, 0); - return ret; } @@ -171,7 +170,6 @@ bool JoystickAndroid::handleGenericMotionEvent(jobject event) { return true; } - bool JoystickAndroid::_open(void) { return true; } @@ -199,8 +197,14 @@ uint8_t JoystickAndroid::_getHat(int hat,int i) { return 0; } +static JoystickManager *_manager = nullptr; + //helper method -bool JoystickAndroid::init() { +bool JoystickAndroid::init(JoystickManager *manager) { + if (_manager == nullptr) { + setNativeMethods(manager); + } + //this gets list of all possible buttons - this is needed to check how many buttons our gamepad supports //instead of the whole logic below we could have just a simple array of hardcoded int values as these 'should' not change @@ -239,3 +243,52 @@ bool JoystickAndroid::init() { return true; } +static const char kJniClassName[] {"org/mavlink/qgroundcontrol/QGCActivity"}; + +static void jniUpdateAvailableJoysticks(JNIEnv *envA, jobject thizA) +{ + Q_UNUSED(envA); + Q_UNUSED(thizA); + + if (_manager != nullptr) { + qCDebug(JoystickLog) << "jniUpdateAvailableJoysticks triggered"; + emit _manager->updateAvailableJoysticksSignal(); + } +} + +void JoystickAndroid::setNativeMethods(JoystickManager *manager) +{ + qCDebug(JoystickLog) << "Registering Native Functions"; + + _manager = manager; + + // REGISTER THE C++ FUNCTION WITH JNI + JNINativeMethod javaMethods[] { + {"nativeUpdateAvailableJoysticks", "()V", reinterpret_cast(jniUpdateAvailableJoysticks)} + }; + + QAndroidJniEnvironment jniEnv; + if (jniEnv->ExceptionCheck()) { + jniEnv->ExceptionDescribe(); + jniEnv->ExceptionClear(); + } + + jclass objectClass = jniEnv->FindClass(kJniClassName); + if(!objectClass) { + qWarning() << "Couldn't find class:" << kJniClassName; + return; + } + + jint val = jniEnv->RegisterNatives(objectClass, javaMethods, sizeof(javaMethods) / sizeof(javaMethods[0])); + + if (val < 0) { + qWarning() << "Error registering methods: " << val; + } else { + qCDebug(JoystickLog) << "Native Functions Registered"; + } + + if (jniEnv->ExceptionCheck()) { + jniEnv->ExceptionDescribe(); + jniEnv->ExceptionClear(); + } +} diff --git a/src/Joystick/JoystickAndroid.h b/src/Joystick/JoystickAndroid.h index 78defedf5..329194ed6 100644 --- a/src/Joystick/JoystickAndroid.h +++ b/src/Joystick/JoystickAndroid.h @@ -19,7 +19,7 @@ public: ~JoystickAndroid(); - static bool init(); + static bool init(JoystickManager *manager); static QMap discover(MultiVehicleManager* _multiVehicleManager); @@ -27,6 +27,8 @@ private: bool handleKeyEvent(jobject event); bool handleGenericMotionEvent(jobject event); + static void setNativeMethods(JoystickManager *manager); + virtual bool _open(); virtual void _close(); virtual bool _update(); diff --git a/src/Joystick/JoystickManager.cc b/src/Joystick/JoystickManager.cc index 2383a4b6a..1cac13960 100644 --- a/src/Joystick/JoystickManager.cc +++ b/src/Joystick/JoystickManager.cc @@ -59,11 +59,13 @@ void JoystickManager::init() { } _setActiveJoystickFromSettings(); #elif defined(__android__) - if (!JoystickAndroid::init()) { + if (!JoystickAndroid::init(this)) { return; } + connect(this, &JoystickManager::updateAvailableJoysticksSignal, this, &JoystickManager::restartJoystickCheckTimer); #endif connect(&_joystickCheckTimer, &QTimer::timeout, this, &JoystickManager::_updateAvailableJoysticks); + _joystickCheckTimerCounter = 5; _joystickCheckTimer.start(1000); } @@ -185,7 +187,7 @@ void JoystickManager::setActiveJoystickName(const QString& name) /* * TODO: move this to the right place: JoystickSDL.cc and JoystickAndroid.cc respectively and call through Joystick.cc */ -void JoystickManager::_updateAvailableJoysticks(void) +void JoystickManager::_updateAvailableJoysticks() { #ifdef __sdljoystick__ SDL_Event event; @@ -207,6 +209,16 @@ void JoystickManager::_updateAvailableJoysticks(void) } } #elif defined(__android__) + _joystickCheckTimerCounter--; _setActiveJoystickFromSettings(); + if (_joystickCheckTimerCounter <= 0) { + _joystickCheckTimer.stop(); + } #endif } + +void JoystickManager::restartJoystickCheckTimer() +{ + _joystickCheckTimerCounter = 5; + _joystickCheckTimer.start(1000); +} diff --git a/src/Joystick/JoystickManager.h b/src/Joystick/JoystickManager.h index 6418886b4..f6736ff8a 100644 --- a/src/Joystick/JoystickManager.h +++ b/src/Joystick/JoystickManager.h @@ -45,6 +45,8 @@ public: QString activeJoystickName(void); void setActiveJoystickName(const QString& name); + void restartJoystickCheckTimer(void); + // Override from QGCTool virtual void setToolbox(QGCToolbox *toolbox); @@ -55,6 +57,7 @@ signals: void activeJoystickChanged(Joystick* joystick); void activeJoystickNameChanged(const QString& name); void availableJoysticksChanged(void); + void updateAvailableJoysticksSignal(); private slots: void _updateAvailableJoysticks(void); @@ -70,6 +73,7 @@ private: static const char * _settingsGroup; static const char * _settingsKeyActiveJoystick; + int _joystickCheckTimerCounter; QTimer _joystickCheckTimer; }; -- 2.22.0