I’m currently trying to extend the java part of a game i’m developing for Android. We need to access photo gallery and camera from the device. So we have added a few java classes to Build/Android/src/…/ folder to call from c++.
However, when we tried to access the classes, we are receiving a not found error on jni.
We created a simple java class, and tried to call it from an emptry project with also no luck.
We need help for solving this problem…
I added a few lines to proguard-project.txt to keep the class if it was being removed, yet it was not. I can see that the class exists in dex file.
There is also another problem. We cannot add any files under Build/Android folder (custom proguard file, build file, extended manifest, etc), as it crashes the UnrealBuildTool with a “pak file not found error”, or sometimes, “file already exists”… but that is a different problem
So… here are the codes that you can use to re-create the circumstances:
proguard-project.txt (C:\Program Files\Epic Games\4.13\Engine\Build\Android\Java)
-keep class com.markakod.hitme.Tools {
public *;
}
This is our simple test class:
package com.markakod.hitme;
import android.content.Context;
import android.widget.Toast;
public class Tools {
public static void openPhotoGallery(Context context, String fileLocation){
Toast.makeText(context, fileLocation, Toast.LENGTH_LONG).show();
}
public static void openCamera(Context context, String fileLocation){
Toast.makeText(context, fileLocation, Toast.LENGTH_LONG).show();
}
}
And this is the code we are using to call the class (exception occurs in FindClass line):
#if PLATFORM_ANDROID
#include "Android/AndroidApplication.h"
#endif
void UCaller::CallPhotoGallery(FString Location)
{
UE_LOG(HITMELOG, Error, TEXT("[UCaller::CallPhotoGallery] For %s"), *Location);
CreateFolder();
FString CurrentLocation = LocalImageFolder() + "/" + Location;
FString ClassName = "[Lcom/markakod/hitme/Tools;";
FString MethodName = "openPhotoGallery";
FString MethodSignature = "(Landroid/content/Context;Ljava/lang/String;)V";
#if PLATFORM_ANDROID
UE_LOG(HITMELOG, Error, TEXT("[UCaller::CallPhotoGallery] Get java environment..."));
JNIEnv* Env = FAndroidApplication::GetJavaEnv(false);
FAndroidApplication::CheckJavaException();
UE_LOG(HITMELOG, Error, TEXT("[UCaller::CallPhotoGallery] Get main activity"));
jobject Activity = FAndroidApplication::GetGameActivityThis();
FAndroidApplication::CheckJavaException();
UE_LOG(HITMELOG, Error, TEXT("[UCaller::CallPhotoGallery] Get class %s"), *ClassName);
jclass Class = Env->FindClass(TCHAR_TO_ANSI(*ClassName));
FAndroidApplication::CheckJavaException();
if (Class != NULL) {
UE_LOG(HITMELOG, Error, TEXT("[UCaller::CallPhotoGallery] Get static method %s"), *MethodName);
jmethodID Method = Env->GetStaticMethodID(Class, TCHAR_TO_ANSI(*MethodName), TCHAR_TO_ANSI(*MethodSignature));
FAndroidApplication::CheckJavaException();
if (Method != NULL) {
UE_LOG(HITMELOG, Error, TEXT("[UCaller::CallPhotoGallery] Create string from %s"), *CurrentLocation);
jstring jLocation = Env->NewStringUTF(TCHAR_TO_ANSI(*CurrentLocation));
UE_LOG(HITMELOG, Error, TEXT("[UCaller::CallPhotoGallery] Call static method %s"), *MethodName);
Env->CallStaticVoidMethod(Class, Method, Activity, jLocation);
FAndroidApplication::CheckJavaException();
UE_LOG(HITMELOG, Error, TEXT("[UCaller::CallPhotoGallery] Done..."));
Env->DeleteLocalRef(jLocation);
}
}
#endif
}
From the crash log…
12-28 10:53:08.001 13360 13380 W System.err: java.lang.ClassNotFoundException: Didn't find class "com.markakod.hitme.Tools" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
12-28 10:53:08.001 13360 13380 W System.err: at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
12-28 10:53:08.001 13360 13380 W System.err: at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
12-28 10:53:08.001 13360 13380 W System.err: at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
12-28 10:53:08.001 13360 13380 W System.err: Suppressed: java.lang.ClassNotFoundException: com.markakod.hitme.Tools
12-28 10:53:08.001 13360 13380 W System.err: at java.lang.Class.classForName(Native Method)
12-28 10:53:08.001 13360 13380 W System.err: at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
12-28 10:53:08.001 13360 13380 W System.err: at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
12-28 10:53:08.001 13360 13380 W System.err: at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
12-28 10:53:08.001 13360 13380 W System.err: ... 1 more
12-28 10:53:08.001 13360 13380 W System.err: Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available
And at last, this is from the dexdump of classes.dex:
dexdump.exe classes.dex | findstr Tools
Class descriptor : 'Lcom/markakod/hitme/Tools;'
#0 : (in Lcom/markakod/hitme/Tools;)
0x0000 - 0x0004 reg=0 this Lcom/markakod/hitme/Tools;
#1 : (in Lcom/markakod/hitme/Tools;)
#2 : (in Lcom/markakod/hitme/Tools;)
source_file_idx : 14003 (Tools.java)
Decompiling the apk proves again that the Tools class exists.
.class public Lcom/markakod/hitme/Tools;
.super Ljava/lang/Object;
.source "Tools.java"
and the static method signature we are using is true
.method public static openPhotoGallery(Landroid/content/Context;Ljava/lang/String;)V