Answer the question
In order to leave comments, you need to log in
Why does QApplication inside a JNI call segfault an android application?
The task is to develop `.apk` in Android Studio, which calls a parallel native process in a lib, on board of which QtApplication is spinning with its event loop.
At first it was thought to develop Android archive (.aar) in QtCreator in order to easily link it to any `.apk` using Java - but this is a bad decision because QtCreator does not support android archives out of the box. However, I will mention that to build the android archive `.aar` instead of `.apk` we can simply edit build.gradle in the `cmake` build directory as shown in the picture:
Now it does not matter, we just take `.so` from the project created in the creator and dragging them into the Android Studio
Android Studio project
Now we create the application project in `AndroidStudio` and then the `SdkService` class with the definition of the native method `initSdk` - which should call the mentioned parallel, to be honest, hidden activity on board the lib. Such a class in my example is located in the following path: `AndroidStudioProjects/MyApplication7/app/src/main/java/io/company/companySdk/SdkService.java`
JNI header
We
generate a JNI header using `javac`:
bash
$ pwd
/home/rozhkov/AndroidStudioProjects/MyApplication7/app/src/main/java/io/company/companySdk
$ javac -h . SdkService.java
extern "C"
JNIEXPORT void JNICALL Java_io_company_companySdk_SdkService_initSdk
(JNIEnv *, jclass);
make_minimum_required(VERSION 3.5)
project(sample_service VERSION 0.1 LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Widgets REQUIRED)
set(PROJECT_SOURCES
main.cpp
)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(sample_service
MANUAL_FINALIZATION
${PROJECT_SOURCES}
)
endif()
target_link_libraries(sample_service PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
if(QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(sample_service)
endif()
#include <thread>
#include <memory>
#include <jni.h>
#include <android/log.h>
#include <QCoreApplication>
#include <QJniEnvironment>
extern "C"
JNIEXPORT void JNICALL
Java_io_company_companySdk_SdkService_initSdk(JNIEnv *, jclass);
class ServiceHolder
{
public:
typedef std::unique_ptr<std::thread> UniqueThreadPtr;
static void init_app_worker() {
if (_appThread)
return;
_appThread = std::make_unique<std::thread>([]() {
int argc = 0;
using namespace std::chrono_literals;
QCoreApplication app(argc, nullptr);
app.exec();
});
}
private:
static UniqueThreadPtr _appThread;
};
ServiceHolder::UniqueThreadPtr ServiceHolder::_appThread;
extern "C"
JNIEXPORT void JNICALL
Java_io_company_companySdk_SdkService_initSdk(JNIEnv * env, jclass)
{
int argc = 0;
__android_log_print(ANDROID_LOG_VERBOSE, "SdkConnect", "Java_io_company_companySdk_SdkService_initSdk");
if (QJniEnvironment::checkAndClearExceptions(env, QJniEnvironment::OutputMode::Verbose))
{
__android_log_print(ANDROID_LOG_VERBOSE, "SdkConnect", "Java environment checked");
}
else
{
__android_log_print(ANDROID_LOG_VERBOSE, "SdkConnect", "Java environment not checked");
}
ServiceHolder::init_app_worker();
}
jint JNI_OnLoad(JavaVM * aVm, void * aReserved)
{
__android_log_print(ANDROID_LOG_INFO, "SdkConnect", "Company sdk on load");
return JNI_VERSION_1_6;
}
$ pwd
/home/rozhkov/sources/android/sample_service/build-sample_service-Android_Qt_6_1_2_Clang_x86_64-Release/android-build/build/outputs/apk/debug
$ mkdir extracted
$ unzip -qod extracted/ android-build-debug.apk
$ cp extracted/lib/x86_64/* ~/AndroidStudioProjects/MyApplication7/app/src/main/jniLibs/x86_64/
$ mv ~/AndroidStudioProjects/MyApplication7/app/src/main/jniLibs/x86_64/libsample_service_x86_64.so ~/AndroidStudioProjects/MyApplication7/app/src/main/jniLibs/x86_64/libsample_service.so
$ ls ~/AndroidStudioProjects/MyApplication7/app/src/main/jniLibs/x86_64/
libc++_shared.so libplugins_imageformats_qjpeg_x86_64.so libplugins_styles_qandroidstyle_x86_64.so libQt6Network_x86_64.so
libplugins_imageformats_qgif_x86_64.so libplugins_networkinformationbackends_androidnetworkinformationbackend_x86_64.so libQt6Core_x86_64.so libQt6Widgets_x86_64.so
libplugins_imageformats_qico_x86_64.so libplugins_platforms_qtforandroid_x86_64.so libQt6Gui_x86_64.so libsample_service.so
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question