I’m trying to open a PDF file on Android using JNI in Unreal Engine 5.2. The app crashes at runtime with a JNI exception. The error occurs when calling FindJavaClass or FindJavaClassGlobalRef. I’ve tried using FJavaWrapper and GameActivity, but the issue persists.
Here is the cpp code:
#if PLATFORM_ANDROID
include “Android/AndroidApplication.h”
include “Android/AndroidJNI.h”
include “Android/AndroidJava.h” // For FJavaWrapper
void OpenDocumentOnAnotherAppAndroid(FString FilePath)
{
if (JNIEnv* Env = FAndroidApplication::GetJavaEnv())
{
// Log the file path
UE_LOG(LogTemp, Log, TEXT(“Opening file: %s”), *FilePath);
// Get the Android activity
jobject Activity = FAndroidApplication::GetGameActivityThis();
// Convert Unreal FString to Java string
jstring jFilePath = Env->NewStringUTF(TCHAR_TO_UTF8(*FilePath));
if (Env->ExceptionCheck()) {
Env->ExceptionDescribe();
Env->ExceptionClear();
UE_LOG(LogTemp, Error, TEXT("Failed to convert file path to Java string!"));
return;
}
// Intent: new Intent()
jclass IntentClass = FJavaWrapper::FindClass(Env, "android/content/Intent", false);
if (Env->ExceptionCheck() || !IntentClass) {
Env->ExceptionDescribe();
Env->ExceptionClear();
UE_LOG(LogTemp, Error, TEXT("Failed to find Intent class!"));
return;
}
jmethodID IntentConstructor = Env->GetMethodID(IntentClass, "<init>", "()V");
jobject IntentObject = Env->NewObject(IntentClass, IntentConstructor);
if (Env->ExceptionCheck() || !IntentObject) {
Env->ExceptionDescribe();
Env->ExceptionClear();
UE_LOG(LogTemp, Error, TEXT("Failed to create Intent object!"));
return;
}
// Intent.setAction(Intent.ACTION_VIEW)
jmethodID SetActionMethod = Env->GetMethodID(IntentClass, "setAction", "(Ljava/lang/String;)Landroid/content/Intent;");
jstring ActionView = Env->NewStringUTF("android.intent.action.VIEW");
Env->CallObjectMethod(IntentObject, SetActionMethod, ActionView);
if (Env->ExceptionCheck()) {
Env->ExceptionDescribe();
Env->ExceptionClear();
UE_LOG(LogTemp, Error, TEXT("Failed to set Intent action!"));
return;
}
// Convert file path to Uri
jclass UriClass = FJavaWrapper::FindClass(Env, "android/net/Uri", false);
if (Env->ExceptionCheck() || !UriClass) {
Env->ExceptionDescribe();
Env->ExceptionClear();
UE_LOG(LogTemp, Error, TEXT("Failed to find Uri class!"));
return;
}
jmethodID ParseMethod = Env->GetStaticMethodID(UriClass, "parse", "(Ljava/lang/String;)Landroid/net/Uri;");
jobject UriObject = Env->CallStaticObjectMethod(UriClass, ParseMethod, jFilePath);
if (Env->ExceptionCheck() || !UriObject) {
Env->ExceptionDescribe();
Env->ExceptionClear();
UE_LOG(LogTemp, Error, TEXT("Failed to parse file path to Uri!"));
return;
}
// Intent.setDataAndType(Uri, "application/pdf")
jmethodID SetDataAndTypeMethod = Env->GetMethodID(IntentClass, "setDataAndType", "(Landroid/net/Uri;Ljava/lang/String;)Landroid/content/Intent;");
jstring MimeType = Env->NewStringUTF("application/pdf");
Env->CallObjectMethod(IntentObject, SetDataAndTypeMethod, UriObject, MimeType);
if (Env->ExceptionCheck()) {
Env->ExceptionDescribe();
Env->ExceptionClear();
UE_LOG(LogTemp, Error, TEXT("Failed to set Intent data and type!"));
return;
}
// Start Activity (this shows "Open With" dialog)
jclass GameActivityClass = FJavaWrapper::FindClass(Env, "com/epicgames/ue4/GameActivity", false);
if (Env->ExceptionCheck() || !GameActivityClass) {
Env->ExceptionDescribe();
Env->ExceptionClear();
UE_LOG(LogTemp, Error, TEXT("Failed to find GameActivity class!"));
return;
}
jmethodID StartActivityMethod = Env->GetMethodID(GameActivityClass, "startActivity", "(Landroid/content/Intent;)V");
Env->CallVoidMethod(Activity, StartActivityMethod, IntentObject);
if (Env->ExceptionCheck()) {
Env->ExceptionDescribe();
Env->ExceptionClear();
UE_LOG(LogTemp, Error, TEXT("Failed to start Activity!"));
return;
}
// Cleanup
Env->DeleteLocalRef(jFilePath);
Env->DeleteLocalRef(IntentObject);
Env->DeleteLocalRef(IntentClass);
Env->DeleteLocalRef(ActionView);
Env->DeleteLocalRef(UriObject);
Env->DeleteLocalRef(UriClass);
Env->DeleteLocalRef(MimeType);
Env->DeleteLocalRef(GameActivityClass);
}
}
#endif
And here are the error logs
[2025.03.04-19.02.32:052][651]LogTemp: Opening file: /storage/emulated/0/Documents/Exxar/ExxarCache/DUMMY/dam.pdf
[2025.03.04-19.02.32:053][651]LogOutputDevice: Warning:
Script Stack (1 frames) :
/Game/QMSInspection/QmsUI.QmsUI_C.ExecuteUbergraph_QmsUI
[2025.03.04-19.02.32:149][651]LogAndroid: Error: === Critical error: ===
[2025.03.04-19.02.32:150][651]LogAndroid: Error:
[2025.03.04-19.02.32:150][651]LogAndroid: Error: Assertion failed: false && “Java JNI call failed with an exception.” [File:./Runtime/Core/Private/Android/AndroidJavaEnv.cpp] [Line: 231]
[2025.03.04-19.02.32:150][651]LogAndroid: Error:
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x00000074016F6A90 libUnreal.so(0x000000000ECE6A90)!AndroidJavaEnv::FindJavaClass(char const*)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x00000074015C3C38 libUnreal.so(0x000000000EBB3C38)!OpenDocumentOnAnotherAppAndroid(FString)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x00000074015D106C libUnreal.so(0x000000000EBC106C)!UVizGameInstance::OpenDocumentAndroid(FString)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x0000007401579CA8 libUnreal.so(0x000000000EB69CA8)!UVizGameInstance::execOpenDocumentAndroid(UObject*, FFrame&, void*)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x000000740229A7A4 libUnreal.so(0x000000000F88A7A4)!UObject::execCallMathFunction(UObject*, FFrame&, void*)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x000000740229CF28 libUnreal.so(0x000000000F88CF28)!ProcessLocalScriptFunction(UObject*, FFrame&, void*)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x000000740229CAB8 libUnreal.so(0x000000000F88CAB8)!UObject::ProcessInternal(UObject*, FFrame&, void*)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x000000740202B438 libUnreal.so(0x000000000F61B438)!UFunction::Invoke(UObject*, FFrame&, void*)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x00000074022A22B8 libUnreal.so(0x000000000F8922B8)!UObject::ProcessEvent(UFunction*, void*)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x0000007406C24460 libUnreal.so(0x0000000014214460)!FLatentActionManager::TickLatentActionForObject(float, TMultiMap<int, FPendingLatentAction*, FDefaultSetAllocator, TDefaultMapHashableKeyFuncs<int, FPendingLatentAction*, true> >&, UObject*)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x0000007406C23694 libUnreal.so(0x0000000014213694)!FLatentActionManager::ProcessLatentActions(UObject*, float)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x0000007406C86754 libUnreal.so(0x0000000014276754)!UWorld::Tick(ELevelTick, float)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x00000074069A3E9C libUnreal.so(0x0000000013F93E9C)!UGameEngine::Tick(float, bool)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x00000073FE7D85CC libUnreal.so(0x000000000BDC85CC)!FEngineLoop::Tick()
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x00000073FE7D0F44 libUnreal.so(0x000000000BDC0F44)!AndroidMain(android_app*)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x00000073FE7DF4B8 libUnreal.so(0x000000000BDCF4B8)!android_main()
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x00000073FE8152B8 libUnreal.so(0x000000000BE052B8)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x0000007535B2BA84 libc.so(0x000000000010BA84)
[2025.03.04-19.02.32:150][651]LogAndroid: Error: [Callstack] 0x0000007535ABF694 libc.so(0x000000000009F694)
[2025.03.04-19.02.32:150][651]LogAndroid: Error:
[2025.03.04-19.02.32:150][651]LogAndroid: Error:
[2025.03.04-19.02.32:150][651]LogAndroid: Error:
[2025.03.04-19.02.32:150][651]LogAndroid: Error:
[2025.03.04-19.02.32:161][651]LogExit: Executing StaticShutdownAfterError
[2025.03.04-19.02.32:164][651]LogAndroid: FAndroidMisc::RequestExit(1)
i also added this in android manifest xml
and res/xml/file_paths.xml looks like this
<?xml version="1.0" encoding="utf-8"?>