[Solved] Problem calling QAndroidJniObject::callStaticMethod("a/java/static/method/MyClass", "myStaticMethod" ) ?



    • I am trying to implement a java class and access from C++.
    • As a first step I created a static java method that prints "hello".
    • When callStaticMethod() is used to call "helloWorld" it does not print "hello".
    • No "hello" message is printed when running on Android device using Qt Debugger.
      ** Or maybe it does works but I can not see print message in debugger?

    Questions:

    What path to the Java class does callStaticMethod use?

    Should Java class path match the java class package name?

    Should Java class path match the AndroidManfiest.xml activity name?

    Should Java class path use '/' or '.' separators?

    C++ Call of helloWorld Java Static Method:
    @
    //Test static call
    qDebug("Calling: AndroidJniObject::callStaticMethod<void>("com/ditchwitch/tsr/platform/AndroidHelper", "helloWorld")");
    QAndroidJniObject::callStaticMethod<void>("com/ditchwitch/tsr/platform/AndroidHelper", "helloWorld");
    qDebug("test complete");
    @

    File: platform/android/AndroidHelper.java
    @
    package com.ditchwitch.tsr.platform;

    import org.qtproject.qt5.android.bindings.QtApplication;
    import org.qtproject.qt5.android.bindings.QtActivity;

    import android.app.AlertDialog;
    import android.bluetooth.BluetoothAdapter;
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import java.lang.String;

    //public class AndroidHelper extends QtActivity
    public class AndroidHelper extends QtActivity {

        private static final String ACTIVITY_TAG="AndroidHelper";
        private static AndroidHelper m_instance;
    
        public AndroidHelper() {
                m_instance = this;
                System.out.println("Constructor AndroidHelper");
                Log.d(AndroidHelper.ACTIVITY_TAG, \
                     "Constructor AndroidHelper");
        }
    
        // Static method to test C++ to Java interop
        public static void helloWorld() {
                System.out.println("Java Hello World");
                Log.d(AndroidHelper.ACTIVITY_TAG, 
                        "Java Hello World");
        }
    

    }
    @

    File: tsr.pro
    @
    android-g++ {
    message ("****************** android-g++ ***********************" )
    ANDROID_PACKAGE_SOURCE_DIR = $$PWD/platform/android
    QT += androidextras
    }
    @

    File: AndroidManifest.xml
    @
    <?xml version="1.0"?>
    <manifest package="com.ditchwitch.tsr" xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
    <application android:hardwareAccelerated="true"
    android:name="org.qtproject.qt5.android.bindings.QtApplication"
    <activity android:allowTaskReparenting="true"
    android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="@string/app_name"
    android:screenOrientation="sensor" android:launchMode="singleTop">
    <intent-filter>
    <action android:name="android.intent.action.MAIN"/>
    <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
    @



    1. "/" is correct. Sorry, I cannot answer the other 3 questions. I used JNI only to call bluetooth classes that are part of the Android system. So they were already known to the class loader.

    However, checking the status after the Java call might help:

    @#include <QAndroidJniObject>
    #include <QAndroidJniEnvironment>

    QAndroidJniObject result=QAndroidJniObject::callStaticObjectMethod...

    if (env->ExceptionCheck()) {
        env->ExceptionDescribe();
        env->ExceptionClear();
        qCritical("Exception in ....");
    }
    else if (!result.isValid()) {
        qCritical("Invalid object returned by ....");
    }@


  • My Huawei phone logs only error messages. To enable debug level, I had to follow this instruction:

    @ dial ##2846579##
    An old style menu appears.
    select 'ProjectMenu'
    select 'Background Setting'
    select 'Log Setting'
    select 'Log Switch'
    enable 'LOG on'
    Select 'Log level setting'
    enable 'DEBUG'
    Press the 'Back' key
    select 'Dump and Log'
    enable 'Open Dump and Log'
    Press 'Back' key 5 times to return to home screen.
    Reboot the phone.
    LogCat should now work.@

    Mabe that helps also in your case.



  • Thank you for your reply.

    I added ExceptionCheck which returned false ( no exception ).
    I also changed helloWorld to return an int value of 33 but I always receive 0.

    I made my java class path match the java package name and replaced '.' separators with '/' separators. I am using a Nexus 7 tablet for my test device.

    It behaves as QAndroidJniObject::callStaticMethod is not even executing?

    All I need to do is locate my Java source here and it gets deployed automatically correct?
    @
    ANDROID_PACKAGE_SOURCE_DIR = $$PWD/platform/android
    @

    C++ Call With ExceptionCheck
    @
    //Test static call
    qDebug("------------------------");
    qDebug("test call java static method");
    jint result = -1;
    result = QAndroidJniObject::callStaticMethod<jint>("com/ditchwitch/tsr/AndroidHelper", "helloWorld");
    {
    QAndroidJniEnvironment env;
    if (env->ExceptionCheck())
    {
    // Handle exception here.
    qDebug("*** JNI exception ***");
    env->ExceptionDescribe();
    env->ExceptionClear();
    env->ExceptionClear();
    }
    else
    {
    qDebug("result = %i", result);
    }
    }

    @

    And changed helloWorld to return a number 33.
    @
    public static int helloWorld() {
    System.out.println("*** Dbg: Java Hello World ");
    //Log.d(AndroidHelper.ACTIVITY_TAG, "
    Dbg: Java Hello World ***");

                return 33;
        }
    

    @



  • Thank your for your help. I am good now.

    I could not figure out what I was doing wrong so I started over and made a copy of the Qt Notifier example. I changed it to a QWidget app, added a button to call the java notify method and a little Qt icon magically appeared in the top task bar on my Nexus 7 tablet.

    Then I added a new static java int method and a second button to call it. When pressed a message box appeared with the expected return value of 3.

    All is good in JNI land.

    -Ed

    http://qt-project.org/doc/qt-5/qtandroidextras-notification-example.html

    @
    void MainWindow::on_pushButton_clicked()
    {
    QString m_notification = "hello";
    QAndroidJniObject javaNotification = QAndroidJniObject::fromString(m_notification);
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/notification/NotificationClient",
    "notify",
    "(Ljava/lang/String;)V",
    javaNotification.object<jstring>());
    }

    void MainWindow::on_pushButton_2_clicked()
    {
    jint result = QAndroidJniObject::callStaticMethod<jint>("org/qtproject/example/notification/NotificationClient",
    "return3");
    QMessageBox::information(this, tr("Java Called"),
    tr("Result: %1.").arg(result));
    }
    @

    Java:
    @
    public static int return3()
    {
    return 3;
    }
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.