Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    Unsolved Qt Android: How to call Toast.makeText from Java?

    Mobile and Embedded
    3
    12
    5681
    Loading More Posts
    • 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
      Ibrahim last edited by Ibrahim

      Hi; I want to call Toast.makeText method from Java in Qt / C++. Codes:
      I added QT += androidextras in .pro file.

      Toast.java:

      package com.classes.java;
      
      public class Toast {
        public static void makeText(String text, int duration) {
          Toast.makeText(getApplicationContext(), text, duration).show();
        }
      }
      

      toast.h:

      #ifndef TOAST_H
      #define TOAST_H
      
      #include <QObject>
      #include <QAndroidJniObject>
      
      class Toast : public QObject
      {
        Q_OBJECT
      public:
        explicit Toast(QObject* parent = 0);
        Q_INVOKABLE void make_text(QString& text, int duration);
      
      signals:
      
      public slots:
      };
      
      #endif // TOAST_H
      
      

      toast.cpp:

      #include "toast.h"
      
      Toast::Toast(QObject* parent) : QObject(parent)
      {
      }
      
      void Toast::make_text(QString& text, int duration)
      {
        QAndroidJniObject txt = QAndroidJniObject::fromString(text);
        QAndroidJniObject::callStaticObjectMethod(
            "com/classes/java/Toast",
            "makeText",
            "(Ljava/lang/String;I)V",
            txt.object<jstring>(), duration);
      }
      

      main.cpp:

      #include <QGuiApplication>
      #include <QQmlApplicationEngine>
      #include <QtQml>
      
      #include "toast.h"
      
      int main(int argc, char* argv[])
      {
        QGuiApplication app(argc, argv);
      
        QQmlApplicationEngine engine;
        qmlRegisterType<Toast>("java.class", 1, 0, "Toast");
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
      
        return app.exec();
      }
      

      main.qml:

      import QtQuick 2.6
      import QtQuick.Window 2.2
      import Qt.labs.controls 1.0
      import java.class 1.0;
      
      Window {
        visible: true
      
        Toast {
          id: toast
        }
      
        Button {
          id: button
          text: "Click Me!"
          onClicked: toast.make_text("Hello World!", 2000)
        }
      }
      

      I get this error message:

      UserPath\build-QtMobileTest-Android_for_armeabi_v7a_GCC_4_9_Qt_5_6_0-Release\android-build\src\com\classes\java\Toast.java:9: error: cannot find symbol
          Toast.makeText(getApplicationContext(), text, duration).show();
                         ^
        symbol:   method getApplicationContext()
        location: class Toast
      Note: UserPath\build-QtMobileTest-Android_for_armeabi_v7a_GCC_4_9_Qt_5_6_0-Release\android-build\__qt5__android__files__\src\org\qtproject\qt5\android\bindings\QtActivity.java uses or overrides a deprecated API.
      Note: Recompile with -Xlint:deprecation for details.
      1 error
      :compileDebugJava FAILED
      
      FAILURE: Build failed with an exception.
      
      * What went wrong:
      Execution failed for task ':compileDebugJava'.
      > Compilation failed; see the compiler error output for details.
      
      * Try:
      Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
      
      BUILD FAILED
      

      I think I need android context for getApplicationContext() but I do not know how can I get context? How can I call Toast.makeText method using Qt / C++ JNI? Thanks.

      1 Reply Last reply Reply Quote 0
      • C
        Carmoneer last edited by Carmoneer

        You need to create a static instance of your main java class object and call the method that way. So in your 'JavaMain':

        public class MyJavaMain extends QtActivity {
        
            // Singleton Instance
            public  static MyJavaMain mInstance;
        
            ...
        
            public MyJavaMain () {
                Log.d(QtApplication.QtTAG, "Java constructor called.");
                mInstance = this;
            }
        
            ...
        
            public static MyMethodCallToast(final String message) {
                 mInstance.runOnUiThread(new Runnable() {
                    public void run() {
                       Toast.makeText(mInstance.getApplicationContext(),
                                      message,
                                      Toast.LENGTH_SHORT).show();
                   }
                });
            }  
        }
        

        Hopefully that helps. Cheers!

        I 1 Reply Last reply Reply Quote 0
        • I
          Ibrahim @Carmoneer last edited by

          @Carmoneer Thanks, I get this error:

          W/dalvikvm( 7847): Exception thrown (Ljava/lang/NullPointerException;) while throwing internal exception (Ljava/lang/NullPointerException;)
          W/InputMethodManagerService(  589): Starting input on non-focused client com.android.internal.view.IInputMethodClient$Stub$Proxy@429dfe58 (uid=10170 pid=7847)
          

          NullPointerException error?

          1 Reply Last reply Reply Quote 0
          • C
            Carmoneer last edited by

            I think it may be an issue with the signature call on the .cpp side, specifically "(Ljava/lang/String;I)V". Try:

            QString toastMessage = "My message";
            QAndroidJniObject javaMessage = QAndroidJniObject::fromString(toastMessage);
            QAndroidJniObject::callStaticMethod<void>("com/app/myApp/MyJavaMain",
                                                      "MyMethodCallToast",
                                                      "(Ljava/lang/String;)V",
                                                      javaMessage.object<jstring>());
            
            I 1 Reply Last reply Reply Quote 0
            • I
              Ibrahim @Carmoneer last edited by

              @Carmoneer Thanks, but I get same error again. This NullPointerException is text.

              1 Reply Last reply Reply Quote 0
              • I
                Ibrahim last edited by

                I tried:

                // ToastMessage.java file
                ...
                public static void makeText(final String text) {
                    mInstance.runOnUiThread(new Runnable() {
                      public void run() {
                        Toast.makeText(mInstance.getApplicationContext(), "text", Toast.LENGTH_LONG).show();
                      }
                    });
                  }
                ...
                

                This code give error. I put the string ("text") but I get still NullPointerException error.

                1 Reply Last reply Reply Quote 0
                • C
                  Carmoneer last edited by Carmoneer

                  The only other thing I can think of is maybe because you have a separate 'Toast' class, it's calling that nullpointerexception. I don't have a separate class for my Toast calls.

                  Maybe

                  Toast.makeText(Classname.class, message, Toast.LENGTH_SHORT).show();
                  

                  is what you need to do?

                  I simply import android.widget.Toast and make my Toast calls.

                  I 1 Reply Last reply Reply Quote 0
                  • I
                    Ibrahim @Carmoneer last edited by

                    @Carmoneer My ToastMessage.java file:

                    package com.classes.java;
                    
                    import org.qtproject.qt5.android.bindings.QtActivity;
                    import android.widget.Toast;
                    
                    public class ToastMessage extends QtActivity {
                      public static ToastMessage mInstance;
                    
                      public ToastMessage() {
                        mInstance = this;
                      }
                    
                      public static String msg() {
                        return "<HELLO WORLD!>";
                      }
                    
                      public static void makeText(final String text) {
                        mInstance.runOnUiThread(new Runnable() {
                          public void run() {
                            Toast.makeText(mInstance.getApplicationContext(), "text", Toast.LENGTH_LONG).show();
                          }
                        });
                      }
                    }
                    

                    I want to learn how to call java codes from C++. Have you an example project for the android toast message?

                    1 Reply Last reply Reply Quote 0
                    • C
                      Carmoneer last edited by Carmoneer

                      This is how I extend the framework for QtActivity:

                      package com.app.myapp;
                      
                      import org.qtproject.qt5.android.bindings.QtApplication;
                      import org.qtproject.qt5.android.bindings.QtActivity;
                      
                      
                      import android.widget.Toast;
                      
                      
                      /** --------------------------------------------------------------------------
                      ** @MyJavaNatives
                      ** Static methods called from .cpp side. Sends data to .cpp
                      ** -------------------------------------------------------------------------*/
                      class MyJavaNatives
                      {
                          public static native void showToast(final String message);
                      }
                      
                      /** --------------------------------------------------------------------------
                      ** @JavaMain (Only one class can extend QtActivity)
                      ** -------------------------------------------------------------------------*/
                      public class JavaMain extends QtActivity {
                          // Singleton Instance
                          public  static JavaMain mInstance;
                      
                          public JavaMain() {
                              Log.d(QtApplication.QtTAG, "Java constructor called.");
                              mInstance = this;
                          }
                      
                          // Called at the start of the full lifetime.
                          @Override
                          public void onCreate(Bundle savedInstanceState) {
                              super.onCreate(savedInstanceState);
                              Log.d(QtApplication.QtTAG, "onCreate Called");
                          }
                      
                      
                          // Called at the start of the visible lifetime.
                          @Override
                          protected void onStart() {
                              super.onStart();
                          }
                      
                          // Called at the start of the active lifetime.
                          @Override
                          public synchronized void onResume() {
                              super.onResume();
                          }
                      
                          // Called at the end of the active lifetime.
                          @Override
                          protected synchronized void onPause() {
                              super.onPause();
                          }
                      
                          // Called at the end of the full lifetime.
                          @Override
                          protected void onDestroy() {
                              // Clean up any resources including ending threads,
                              // closing database connections etc.
                              super.onDestroy();
                          }
                      
                          // Called at the end of the visible lifetime.
                          @Override
                          protected void onStop() {
                              // Suspend remaining UI updates, threads, or processing
                              // that aren’t required when the Activity isn’t visible.
                              // Persist all edits or state changes
                              // as after this call the process is likely to be killed.
                              super.onStop();
                       
                          }
                      
                          // Called before subsequent visible lifetimes
                          // for an activity process.
                          @Override
                          protected void onRestart() {
                              // Load changes knowing that the activity has already
                              // been visible within this process.
                              super.onRestart();
                          }
                      
                      
                          /** ------------------------------------------------------------------------
                          ** @Toast
                          ** Show toast messge.
                          ** -----------------------------------------------------------------------*/
                          public static void showToast(final String message) {
                              mInstance.runOnUiThread(new Runnable() {
                                 public void run() {
                                     Toast.makeText(mInstance.getApplicationContext(),
                                                    message,
                                                    Toast.LENGTH_SHORT).show();
                                 }
                              });
                          }
                      }
                      

                      and then on the .cpp to call the message:

                                  QAndroidJniObject::callStaticMethod<void>("com/app/myapp/JavaMain",
                                                                            "showToast",
                                                                            "(Ljava/lang/String;)V",
                                                                            QAndroidJniObject::fromString("This is my toast message!").object<jstring>());
                      

                      That is the basics to setting up a 'Main' java class that extends QtActivity. Hopefully that should at least steer you in the right direction. Good luck :)

                      I 1 Reply Last reply Reply Quote 0
                      • I
                        Ibrahim @Carmoneer last edited by

                        @Carmoneer Ohh thanks. I tried this project, but it give same error:

                        W/dalvikvm(18212): Exception thrown (Ljava/lang/NullPointerException;) while throwing internal exception (Ljava/lang/NullPointerException;)
                        I/InputDispatcher(  589): Delivering touch to (18212): action: 0x0, toolType: 1
                        I/InputDispatcher(  589): Delivering touch to (18212): action: 0x1, toolType: 1
                        

                        I am sharing this project source codes: Project Source Codes.

                        1 Reply Last reply Reply Quote 0
                        • douyw
                          douyw last edited by

                          There is an android-extra example called 'notification' in Qt SDK examples. Just change the notify function in NotificationClient.java to display the toast. Maybe it will work.

                          I 1 Reply Last reply Reply Quote 0
                          • I
                            Ibrahim @douyw last edited by

                            @douyw thanks, I tried this method and it is work. Interesting! I do not understand. What is the problem? How can I learn it?

                            1 Reply Last reply Reply Quote 0
                            • First post
                              Last post