Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. Qt Android Problem
Forum Updated to NodeBB v4.3 + New Features

Qt Android Problem

Scheduled Pinned Locked Moved Solved Mobile and Embedded
9 Posts 3 Posters 4.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • I Offline
    I Offline
    Ibrahim
    wrote on last edited by
    #1

    Hi;
    I am working Qt for Android. But I don't understand somethings. Qt doc means about QAndroidJniObject QtAndroid::androidActivity() member function: Returns a handle to this applications main Activity. But which is activity? Which is main activity? My application created with QML and QML windows are not Activity, activities defined on Android (Java) only. I want to define toast message function:

    package com.xxx.android;
    
    import android.content.Context;
    import android.widget.Toast;
    
    import org.qtproject.qt5.android.bindings.QtActivity;
    
    public class MyActivity extends QtActivity
    {
      public void makeText(Context context, CharSequence text, int duration)
      {
        Toast.makeText(context, text, duration).show();
      }
    }
    

    And I want to call this method in Qt:

    ...
    void TestClass::toast_message(/*I don't know Context class in Qt*/const QString& text, int duration)
    {
      QAndroidJniObject mytext = QAndroidJniObject::fromString(text);
      QAndroidJniObject::callObjectMethod("com/xxx/android/MyActivity",
                                          "makeText", "(Ljava/lang/String;I)V",
                                          mytext.object<jstring>(), duration);
    }
    ...
    

    But my text type is CharSequence, not String. But defined jstring in Qt. Then I want to put parameter this member function as Context context but I could not do it. How can I understand struction of Qt for Android? I know Java for Android.

    1 Reply Last reply
    0
    • V Offline
      V Offline
      Violet Giraffe
      wrote on last edited by Violet Giraffe
      #2

      You can pass String instead of CharSequence since String is CharSequence. As for the context, the activity is a Context subclass.

      Java:

      public void makeText(String text, int duration)
      {
          Toast.makeText(this, text, duration).show();
      }
      

      C++:

      void TestClass::toast_message(const QString& text, int duration)
      {
        QAndroidJniObject mytext = QAndroidJniObject::fromString(text);
        QAndroidJniObject::callObjectMethod("com/xxx/android/MyActivity",
                                            "makeText", "(Ljava/lang/String;I)V",
                                            mytext.object<jstring>(), duration);
      }
      
      I 1 Reply Last reply
      0
      • V Violet Giraffe

        You can pass String instead of CharSequence since String is CharSequence. As for the context, the activity is a Context subclass.

        Java:

        public void makeText(String text, int duration)
        {
            Toast.makeText(this, text, duration).show();
        }
        

        C++:

        void TestClass::toast_message(const QString& text, int duration)
        {
          QAndroidJniObject mytext = QAndroidJniObject::fromString(text);
          QAndroidJniObject::callObjectMethod("com/xxx/android/MyActivity",
                                              "makeText", "(Ljava/lang/String;I)V",
                                              mytext.object<jstring>(), duration);
        }
        
        I Offline
        I Offline
        Ibrahim
        wrote on last edited by Ibrahim
        #3

        @Violet-Giraffe Thanks but that code doesn't run. Did you try?
        I wrote this code (I look KDAB webpage):

        // testclass.h
        class TestClass : public QObject
        {
          Q_OBJECT
        public:
          enum Duration {
            SHORT = 0,
            LONG = 1
          };
        
          explicit TestClass(QObject *parent = 0);
          Q_INVOKABLE void toast_message(const QString& text, Duration duration);
        
        signals:
        
        public slots:
        };
        
        // testclass.cpp
        #include "testclass.h"
        
        TestClass::TestClass(QObject *parent) : QObject(parent)
        {
        }
        
        void TestClass::toast_message(const QString& text, Duration duration = SHORT)
        {
          QAndroidJniObject _text = QAndroidJniObject::fromString(text);
          QAndroidJniObject toast = QAndroidJniObject::callStaticObjectMethod("android/widget/Toast", "makeText",
                                              "(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;",
                                              QtAndroid::androidActivity().object(), _text.object(), jint(duration));
          toast.callMethod<void>("show");
        }
        

        I put this code in main.cpp: qmlRegisterType<TestClass>("com.xxx.TestClass", 1, 0, "TestClass");

        // .qml file:
        import QtQuick 2.7
        import QtQuick.Dialogs 1.2
        import com.xxx.TestClass 1.0
        
        Page1Form {
          TestClass {
            id: test_class
          }
        
          button1.onClicked: {
            test_class.toast_message("Hello World!")
          }
        }
        

        I run this application and I click the button then I get this error message on the log window: W/libQt_App.so(11956): qrc:/Page1.qml:17 ((null)): qrc:/Page1.qml:17: Error: Unknown method parameter type: Duration
        What is the problem?

        1 Reply Last reply
        0
        • kd_walaK Offline
          kd_walaK Offline
          kd_wala
          wrote on last edited by kd_wala
          #4

          @Ibrahim ,I think you need declare Q_ENUM(Duration) to register with Qt's meta object system, and using qRegisterMetaType
          pls see link: http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#enumeration-types
          and http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#enumeration-types-as-signal-and-method-parameters

          I 1 Reply Last reply
          1
          • kd_walaK kd_wala

            @Ibrahim ,I think you need declare Q_ENUM(Duration) to register with Qt's meta object system, and using qRegisterMetaType
            pls see link: http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#enumeration-types
            and http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#enumeration-types-as-signal-and-method-parameters

            I Offline
            I Offline
            Ibrahim
            wrote on last edited by
            #5

            @kd_wala Thanks I added Q_ENUM(Duration) and I run the app. Then I get this message on the Android device: Unfortunately app has stopped.
            Then I get this warning message on the log window: F/libc (27047): Fatal signal 11 (SIGSEGV) at 0x0000002c (code=1), thread 27218 (project.example)
            I understand I need to use thread but how can I use thread for this member function (toast_message)?
            Code:

            void TestClass::toast_message(const QString& text, Duration duration)
            {
              std::thread run([&]
              {
                QAndroidJniObject _text = QAndroidJniObject::fromString(text);
                QAndroidJniObject toast = QAndroidJniObject::callStaticObjectMethod(
                    "android/widget/Toast", "makeText",
                    "(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;",
                    QtAndroid::androidActivity().object(), _text.object(), jint(duration));
                toast.callMethod<void>("show");
              });
              run.join();
            }
            

            This code is not running.

            1 Reply Last reply
            0
            • kd_walaK Offline
              kd_walaK Offline
              kd_wala
              wrote on last edited by kd_wala
              #6

              I think it a problem when you call from Qt thread to Android thread,
              on this link : http://www.kdab.com/qt-android-episode-7/
              have a diagram about architecture between Android & Qt thread,
              this link will help you solve problem, : https://www.kdab.com/qt-android-use-android-toast/
              or if you have install Qt5.7, it already support some function for running on UI Android thread from c++.

              I 1 Reply Last reply
              1
              • kd_walaK kd_wala

                I think it a problem when you call from Qt thread to Android thread,
                on this link : http://www.kdab.com/qt-android-episode-7/
                have a diagram about architecture between Android & Qt thread,
                this link will help you solve problem, : https://www.kdab.com/qt-android-use-android-toast/
                or if you have install Qt5.7, it already support some function for running on UI Android thread from c++.

                I Offline
                I Offline
                Ibrahim
                wrote on last edited by Ibrahim
                #7

                @kd_wala Thanks.
                You said: if you have install Qt5.7, it already support some function for running on UI Android thread from c++.
                What are some functions? I want to control all threads in Qt/C++, is this possible? I don't want running thread for Android in Java, can I do it in C++?
                KDAB::Android::runOnAndroidThread() member function is using thread from Java:

                void runOnAndroidThread(const Runnable &runnable)
                {
                    s_pendingRunnablesMutex.lock();
                    bool triggerRun = s_pendingRunnables.empty();
                    s_pendingRunnables.push_back(runnable);
                    s_pendingRunnablesMutex.unlock();
                    if (triggerRun) {
                        QtAndroid::androidActivity().callMethod<void>("runOnUiThread", // This is Java Class.
                                                                      "(Ljava/lang/Runnable;)V",
                                                                      QAndroidJniObject("com/kdab/android/utils/Runnable").object());
                    }
                }
                

                But I want to use all threads in C++ (std::thread, std::async, QThread etc.). Is this possible?

                1 Reply Last reply
                0
                • kd_walaK Offline
                  kd_walaK Offline
                  kd_wala
                  wrote on last edited by
                  #8

                  Hi @Ibrahim ,
                  in QtAndroidExtras, have include "qandroidfunctions.h", this file have some function that equal to KDAB::Android::runOnAndroidThread(),
                  You want to control all threads in Qt/C++, i think it ok, in c++ thread, you just call java via jni,
                  but if you want to access on UI of Android (in your case, show toast UI) you need run this code on main thread of Java,
                  One note is Qt event loop vs Android event loop run in different thread (https://www.kdab.com/qt-on-android-episode-1/)

                  I 1 Reply Last reply
                  1
                  • kd_walaK kd_wala

                    Hi @Ibrahim ,
                    in QtAndroidExtras, have include "qandroidfunctions.h", this file have some function that equal to KDAB::Android::runOnAndroidThread(),
                    You want to control all threads in Qt/C++, i think it ok, in c++ thread, you just call java via jni,
                    but if you want to access on UI of Android (in your case, show toast UI) you need run this code on main thread of Java,
                    One note is Qt event loop vs Android event loop run in different thread (https://www.kdab.com/qt-on-android-episode-1/)

                    I Offline
                    I Offline
                    Ibrahim
                    wrote on last edited by
                    #9

                    @kd_wala Thanks. I solved the problem:

                    void TestClass::toast_message(const QString& text, Duration duration)
                    {
                      QtAndroid::runOnAndroidThread([&]
                      {
                        QAndroidJniObject _text = QAndroidJniObject::fromString(text);
                        QAndroidJniObject toast = QAndroidJniObject::callStaticObjectMethod(
                            "android/widget/Toast", "makeText",
                            "(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;",
                            QtAndroid::androidActivity().object(), _text.object(), jint(duration));
                        toast.callMethod<void>("show");
                      });
                    }
                    

                    This is running!

                    1 Reply Last reply
                    1

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved