Failed to Call java function from C++ on Android
-
Hi, Can anyone please help me. I am unable to call java function from c++,
please CMakeLists.txt below
cmake_minimum_required(VERSION 3.16) project(testing VERSION 0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 6.5 REQUIRED COMPONENTS Quick Widgets Core) qt_standard_project_setup(REQUIRES 6.5) qt_add_executable(apptesting main.cpp ) qt_add_qml_module(apptesting URI testing VERSION 1.0 QML_FILES Main.qml RESOURCES android/AndroidManifest.xml android/build.gradle android/res/values/libs.xml android/res/xml/qtprovider_paths.xml android/gradle/wrapper/gradle-wrapper.jar android/gradle/wrapper/gradle-wrapper.properties android/gradle.properties android/gradlew android/gradlew.bat android/src/org/qtproject/example/file/MathOperations.java SOURCES mathbridge.h mathbridge.cpp ) # Set Android source directory set(android_package_dir "${CMAKE_SOURCE_DIR}/android") # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. # If you are developing for iOS or macOS you should consider setting an # explicit, fixed bundle identifier manually though. set_target_properties(apptesting PROPERTIES # MACOSX_BUNDLE_GUI_IDENTIFIER com.example.apptesting MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} MACOSX_BUNDLE TRUE WIN32_EXECUTABLE TRUE ) target_link_libraries(apptesting PRIVATE Qt6::Quick PRIVATE Qt6::Widgets PRIVATE Qt6::Core ) include(GNUInstallDirs) install(TARGETS apptesting BUNDLE DESTINATION . LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} )
code implementation to call the java function
#include "mathbridge.h" #include <QJniObject> #include <QDebug> QString MathBridge::addNumbers() { QJniObject result = QJniObject::callStaticObjectMethod( "org/qtproject/example/file/MathOperations", // Fully qualified Java class name "add", // Java method name "()Ljava/lang/String;" // JNI method signature ); if (result.isValid()) { QString value = result.toString(); qDebug() << "Addition Result:" << value; return value; } else { qDebug() << "Failed to call add() in Java"; return "Error"; } } QString MathBridge::multiplyNumbers() { QJniObject result = QJniObject::callStaticObjectMethod( "org/qtproject/example/file/MathOperations", // Fully qualified Java class name "multiply", // Java method name "()Ljava/lang/String;" // JNI method signature ); if (result.isValid()) { QString value = result.toString(); qDebug() << "Multiplication Result:" << value; return value; } else { qDebug() << "Failed to call multiply() in Java"; return "Error"; } }
below is the folder structure
I have been struggling to get this done for the past one week, i am not able to get this worked. Please the error below.
W libapptesting_x86_64.so: java.lang.ClassNotFoundException: Didn't find class "org.qtproject.example.file.MathOperations" on path: DexPathList[[zip file "/data/app/~~8CDaDhFP1VCP5LeUpwjwoQ==/org.qtproject.example.apptesting-Ltr2ET7MHeEnfYKGtla3Zw==/base.apk"],nativeLibraryDirectories=[/system/lib64, /system_ext/lib64]] W libapptesting_x86_64.so: at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259) W libapptesting_x86_64.so: at java.lang.ClassLoader.loadClass(ClassLoader.java:379) W libapptesting_x86_64.so: at java.lang.ClassLoader.loadClass(ClassLoader.java:312) W libapptesting_x86_64.so: at org.qtproject.qt.android.QtNative.startQtApplication(Native Method) W libapptesting_x86_64.so: at org.qtproject.qt.android.QtNative$$ExternalSyntheticLambda4.run(D8$$SyntheticClass:0) W libapptesting_x86_64.so: at org.qtproject.qt.android.QtThread$1.run(QtThread.java:25) W libapptesting_x86_64.so: at java.lang.Thread.run(Thread.java:1012) 11-25 20:46:31.682 12976 13041 W libapptesting_x86_64.so: D libapptesting_x86_64.so: Failed to call add() in Java W libapptesting_x86_64.so: java.lang.ClassNotFoundException: Didn't find class "org.qtproject.example.file.MathOperations" on path: DexPathList[[zip file "/data/app/~~8CDaDhFP1VCP5LeUpwjwoQ==/org.qtproject.example.apptesting-Ltr2ET7MHeEnfYKGtla3Zw==/base.apk"],nativeLibraryDirectories=[/system/lib64, /system_ext/lib64]] W libapptesting_x86_64.so: at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259) W libapptesting_x86_64.so: at java.lang.ClassLoader.loadClass(ClassLoader.java:379) W libapptesting_x86_64.so: at java.lang.ClassLoader.loadClass(ClassLoader.java:312) W libapptesting_x86_64.so: at org.qtproject.qt.android.QtNative.startQtApplication(Native Method) W libapptesting_x86_64.so: at org.qtproject.qt.android.QtNative$$ExternalSyntheticLambda4.run(D8$$SyntheticClass:0) W libapptesting_x86_64.so: at org.qtproject.qt.android.QtThread$1.run(QtThread.java:25) W libapptesting_x86_64.so: at java.lang.Thread.run(Thread.java:1012) 11-25 20:46:31.713 12976 13041 W libapptesting_x86_64.so: D libapptesting_x86_64.so: Failed to call multiply() in Java
You help will be much appreciated.
Thanks,
-
@Adla said in Failed to Call java function from C++ on Android:
org/qtproject/example/file/MathOperations
Where is this Java class implemented?
-
@jsulm , Here is MathOperations Java class
package org.qtproject.example.file; import android.app.Activity; import android.widget.Toast; import org.qtproject.qt.android.QtNative; public class MathOperations { public static String add() { return "This is a test for addition"; } public static String multiply() { return "This is a test for multiplication"; } }
-
@Adla said in Failed to Call java function from C++ on Android:
or is this issue because i am using free Qt version
This has nothing to do with this.
You added android/src/org/qtproject/example/file/MathOperations.java to your resources!
How is this supposed to work? You have to build your Java code and deploy the result as part of your app. -
@jsulm I am new to Qt C++ and learning it.
android/src/org/qtproject/example/file/MathOperations.java is added on its own, when i tried to remove from the resources then the folder structure is also deleted.
Could you please explain what does "You have to build your Java code and deploy the result as part of your app" mean, How can i build and deploy it. Thanks -
@Adla said in Failed to Call java function from C++ on Android:
Could you please explain what does "You have to build your Java code and deploy the result as part of your app" mean
Java is not an interpreted language. You have to compile Java code just like you do with C++ code.
Take a look at https://www.qt.io/blog/unstringifying-android-development-with-qt-6.4 -
Based on some other posts and this discussion, android/src/org/qtproject/example/file/MathOperations.java directory should not be in RESOURCES in CMakeLists.txt.
But when i add the java file sub directory to the android directory in QT creator using "Add Existing directory...", then sub directory is added in the RESOURCES on its own, and when i removed this sub directory from the RESOURCES and then i save the file then the java sub directory gets deleted from the android directory without my intervention.
Then i have below doubts,
1). Should src/org/qtproject/example/file/MathOperations.java be added to android directory using "Add Existing Directory.." in Qt Creator?
2).If this sub directory is supposed to be added inside android , then how to avoid it from being added to RESOURCES in CMakeLists.txt ?
3). Is my CMakeLists.txt file wrong, that is why the java file is not being complied and not being added to the android app?
4). If src/org/qtproject/example/file/MathOperations.java is not supposed to be added inside android in Qt Creator, then where should i specify in either CMakeList.txt or build.gradle file to compile the java file and to load in to the android app?
-
@Adla I suggest you take a look at this example: https://doc.qt.io/qt-6/qtcore-platform-androidnotifier-example.html
https://code.qt.io/cgit/qt/qtbase.git/tree/examples/corelib/platform/androidnotifier/CMakeLists.txt?h=6.8 -