Solved Qt platform dependent code
-
Hello,
I've been trying to extend my current Qt application, which is being developed for both Android and iOS, by adding local push notifications.
The example application QtNotifier worked for me on Android. This example calls Java code to make the notifications work. However, using this code in my application makes it unbuildable for iOS.
Do you guys see any solution which enables me to have the native Android code working for Android builds, but also enable me to build for iOS (in the iOS build the Android code does not need to work).
Any thoughts on the matter would be extremely helpful!
Thanks in advance :)
-
There are multiple solutions to that problem. You can either use one class that handles both the iOs and android stuff. Then in the methods you are using ifdef's to implement the platform specific stuff:
void MyClass::doSomething(){ #ifdef Q_OS_ANDROID // android specific stuff goes here #else // everything else #endif }
Or you could create multiple classes (in different namespaces) that contain the platform specific stuff.
e.q: You create a class MyClass in the namespace ios that contains the ios specific implementation. And a android specific class MyClass in the namespace android that contains the android specific implementation. Now you can either use the android or ios specific class depending on the preprocessor flag:
#ifdef Q_OS_ANDROID android::MyClass myClass; #else ios::MyClass myClass; #endif
In QML you can check the platform with:
if(Qt.platform.os === "android"){ //.... } else{ //.... }
-
@PJanissen I'm working on this, too (and thanks to @Schluchti for suggestions). You may want to use .pro file, too, or maybe you even must use it. See http://doc.qt.io/qt-5/qmake-tutorial.html for how to change configurations depending on the target platform.
-
@Schluchti BTW: thx for your ios push blog. will the android part follow ?
-
I use a message dispatcher class for this purpose. The communication between QML/C++ and Java/Objective-C is restricted to use this component. It takes a QVariantMap as the message then convert to Java Map object and vice versa. The receiver should register a callback. In the desktop, it won't have any class to process the message so the function is not usable but still compilable. Such that I don't need to use lots of #ifdef...#endif to just make it compilable for different platform.
Implementation in Android
benlau/androidnative.pri: Calling Android functions from Qt without using JNIImplementation in iOS
quickios/qisystemdispatcher.h at master · benlau/quickios
quickios/qisystemutils.mm at master · benlau/quickios -
@benlau thx - will take a look at your work next weeks
-
@ekkescorner Thanks for the reminder. :) I will probably start this saturday - hope to get it done by mid of next week :)
-
Some interesting advanced material here. Meanwhile, I got the Qt notification example working on desktop. First, move the android-specific stuff in the .pro file to android{}:
QT += quick SOURCES += \ main.cpp \ notificationclient.cpp OTHER_FILES += \ qml/main.qml RESOURCES += \ main.qrc HEADERS += \ notificationclient.h target.path = $$[QT_INSTALL_EXAMPLES]/androidextras/notification INSTALLS += target android { QT += androidextras ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android-sources OTHER_FILES += \ android-sources/src/org/qtproject/example/notification/NotificationClient.java \ android-sources/AndroidManifest.xml }
Put the android code in notificationclient.cpp inside #ifdef:
#ifdef Q_OS_ANDROID #include <QtAndroidExtras/QAndroidJniObject> #endif ... #ifdef Q_OS_ANDROID QAndroidJniObject javaNotification = QAndroidJniObject::fromString(m_notification); QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/notification/NotificationClient", "notify", "(Ljava/lang/String;)V", javaNotification.object<jstring>()); #endif
Now you can compile and run the project in a desktop, although it obviously does nothing.
-
Hi @PJanissen,
for local push notifications on iOS and Android, you can also have a look at V-Play Engine, which offers a Local Notification Plugin and also plugins for server-triggered notifications.
import VPlayApps 1.0 import VPlayPlugins 1.0 App { NotificationManager { id: notificationManager } Notification { id: idleNotification notificationId: "idleNotification" message: "Anyone here? Haven't seen you in a while..." timeInterval: (24 * 60 * 60) // in seconds } Component.onCompleted: { // Cancel old notification if scheduled notificationManager.cancelNotification(idleNotification.notificationId) // Schedule idleNotification notificationManager.scheduleNotification(idleNotification) } }
The plugins already take care of the platform-specific code and offer easy usage with QML. Plugins are available with the paid plan, which is also possible on a monthly basis.
Best,
GT