diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 49581f61050e4c8ec5fc6946ab805384f7cbcd9c..1f309baa47c404a4d88cbbbc85f8d6cc42025398 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 f76242f5e67adfc71d7e3d5d362f693c0faf5ff4..9923c8f4f24145ffdc5563b4459f41613c452715 100644 --- a/android/src/org/mavlink/qgroundcontrol/QGCActivity.java +++ b/android/src/org/mavlink/qgroundcontrol/QGCActivity.java @@ -55,6 +55,8 @@ import android.os.PowerManager; import android.os.Bundle; import android.app.PendingIntent; 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; @@ -162,6 +164,12 @@ public class QGCActivity extends QtActivity } } } + + try { + nativeUpdateAvailableJoysticks(); + } catch(Exception e) { + Log.e(TAG, "Exception nativeUpdateAvailableJoysticks()"); + } } }; @@ -169,6 +177,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); @@ -200,8 +209,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 d66f0c0b928499271c248b828c3b99196092c408..3a1a1da31d9bbd9f277ef3cefc2551b35955b684 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 78defedf51fc568d22a0cf084c1374e5d6ba9fdf..329194ed65d9273ba216abc6736504829a5777ce 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 2383a4b6ac19cce9ee77e92d34b6e8d65d35d48e..1cac13960e590b2b8424914a6e0a0b3d713a5f44 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 6418886b404868e3fcfe07f39baa785a373b4af1..f6736ff8a91b094c5a8b7db776e5a9ad927548f0 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; };