This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I load my own Java class in C on Android?
Application works in debug / run from Eclipse, but .APK gives .classNotFoundException when parsing XML layout that contains a custom View
In Android, I am accessing a native C library, by doing:
System.loadLibrary("testlib");
To load a native library.
In the JNI_OnLoad() function, it is trying to find a Java glue code class:
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env;
jclass k;
jint r;
r = vm->GetEnv ((void **) &env, JNI_VERSION_1_4);
k = env->FindClass ("com/test/android/aclass");
The FindClass() fails, and throws a NoClassDefFoundError exception.
Any idea why I cannot see my Java class from my C code?
I use this same library in another test application, and it works (so I am confident that the library works). I don't see why one app can find the java class, while the other cannot.
Found the answer.
My clue was that it would run fine if I ran it through eclipse, and only had this problem when I created a .apk file.
I found the solution here: Application works in debug / run from Eclipse, but .APK gives .classNotFoundException when parsing XML layout that contains a custom View
Related
I am working on a project using Android and native code through JNI.
Android Studio editor keeps telling me that it cannot resolve the native method yet it compiles an executes my program fine.
// In the Java file
private native void startROSNode();
// In the C++ file
JNIEXPORT void JNICALL Java_com_laas_lumusapp_ROSThread_startROSNode(JNIEnv* env, jobject obj)
Is there something I am missing ? (even if it is not project critical it bugs me to see that red line in my editor :))
Thank you in advance !
There might be several reasons, most likely this is due to the ndk 'experimental plugin' (Assuming you have not migrated to CMake). Take a look here, perhaps this will help you: Android Studio 2.0's inline compiler does no longer recognize native code
I have an NDK shared library and I want to do some tests against it. I currently used googletest to create an native executable that links to the library, followed instructions in the README.NDK. A dummy executable can run on a Android emulator. Good.
Now, the tricky thing is that the shared library calls a lot of functions of an JNIEnv instance, for example:
env->NewStringUTF()
...
The question is, how can an Android native executable get an instance of JNIEnv?
One method is to use the invocation API described below.
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/invocation.html
However, I looked at the jni.h of NDK, and it seems disallow the usages of this API:
/*
* VM initialization functions.
*
* Note these are the only symbols exported for JNI by the VM.
*/
#if 0 /* In practice, these are not exported by the NDK so don't declare them */
jint JNI_GetDefaultJavaVMInitArgs(void*);
jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*);
jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*);
#endif
Any suggestions are highly appreciated!
(I am new to Android so please correct me if I am wrong. Thanks!)
This is done via AttachCurrentThread().
It is benign to call this if the thread is already attached.
I'm creating a C++ Android APP based of the book Pro Android NDK and this tutorial (http://www.swig.org/Doc2.0/Android.html#Android_example_class)
I created a C++ class called Http that creates sockets to perform simple HTTP requests (mostly for learning purposes). The C++ app works on its own.
I compiled it to JNI (using Swig) and generated the appropriate JNI code and the Java "proxy" files which I can use to call the code.
My original C++ constructor has this signature:
Http::Http(const char * ip_address, int port)
1) In my AndroidStudio app I have an Activity called MainActivity. The Package containing the MainActivity and the generated JNI Java classes is com.zuzile. My default constructor looks like this SWIGEXPORT jlong JNICALL Java_com_zuzile_exampleJNI_new_1Http(JNIEnv *jenv, jclass jcls, jstring jarg1, jint jarg2) where "exampleJNI" is my Java class that contains the native method public final static native long new_Http(String jarg1, int jarg2);
2) After generating the appropriate JNI and corresponding Java classes I successfully compiled the JNI code into a .so file using NDK. I was able to load the .so file by calling System.loadLibrary("httpreq") httpreq is the name of my compiled module.
3) When I try to use my Module by calling Http("some IP address", "a port") I get the following error: java.lang.ClassNotFoundException: com.zuzile.MainActivity (as output by the Debugger).
If I remove the Http(...) declaration from my MainActivity.java my APP loads perfectly without crashing. But as soon as I use the Native code I generated it states it can't find com.zuzile.MainActivity.
I appreciate any help in advance as I've been stuck on this for 3 days now.
JNI is just an interface between JAVA and C/C++, you can't map directly c++ class to Jave class. you can just call mapped methods.
In your case, Http("some IP address", "a port") means java constructor, but you don't have a java class named "Http", right?
I'm trying to use short[] and jshortArray between C/JAVA as follows in Eclipse:
JNIEXPORT void JNICALL Java_com_testingForFun_testFunc
(JNIEnv *env, jclass clazz, jshort num, jshortArray data) {
jshort outCArray[] = {100, 200};
jshortArray outJNIArray = (*env)->NewShortArray(env, 2); // allocate
if (NULL == outJNIArray) return;
(*env)->SetShortArrayRegion(env, outJNIArray, 0 , 2, outCArray); // copy
//return outJNIArray;
}
I've created the header file using javah and included it. However, Eclipse says NewShortArray and SetShortArrayRegion are unresolved and I can't build the apk. However, not using arrays (jshort and short) works fine. I looked in jni.h and it seems that NewShortArray other related functions are defined if __cplusplus is defined, but I'm using C. I also built the apk on the command line using ndk-build and ant and I read outJNIArray[0] or [1] = 0 in the calling function, so it's not working there either. How do I resolve this issue?
Additionally, Eclipse can't resolve ANDROID_LOG_DEBUG in:
__android_log_print(ANDROID_LOG_DEBUG, "FibLib.c", "fibNI(%lld)", n);
even though
#include <android/log.h>
is at the beginning of the file.
I used Eclipse restart and seems to have cleared up these issues. But every time I edit my .c file, the unresolved errors pop up, and I need to restart. It's very annoying. Any fix for this?
The issue of outJNIArray[] not being set is a separate topic, so I will ask another question on the forum in the future if necessary.
My Android application comprises two parts: frontend written in Java and game written in C++ using NativeActivity NDK stuff. I have a problem integrating Flurry into my application. Flurry works fine from within Java part, but crashes from within C++.
More specifically, call
jni_env->FindClass("com/flurry/android/FlurryAgent");
results in ClassNotFoundException.
jni_env variable is not broken because I am able to get some Intent params using it.
FlurryAgent.jar is added to libs dir and into .classpath. I've even checked 'Order and Export' checkbox for FlurryAgent.jar (though I have no idea what does it mean). Nothing helps.
One more detail: my application is divided into Library and App parts. I have added FlurryAgent.jar to both parts and checked 'Order and Export' in both parts, but it still does not help. Clean & rebuild does does not help either. Did I miss something?
The answer is here: http://archive.is/QzA8
In other words, NativeActivity cannot find a third-party class and instead of
jni_env->FindClass("com/flurry/android/FlurryAgent");
one should use
jobject nativeActivity = state->activity->clazz;
jclass acl = jni_env->GetObjectClass(nativeActivity);
jmethodID getClassLoader = jni_env->GetMethodID(acl, "getClassLoader", "()Ljava/lang/ClassLoader;");
jobject cls = jni_env->CallObjectMethod(nativeActivity, getClassLoader);
jclass classLoader = jni_env->FindClass("java/lang/ClassLoader");
jmethodID findClass = jni_env->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
jstring strClassName = jni_env->NewStringUTF("com.flurry.android.FlurryAgent");
jclass flurryClass = (jclass)(jni_env->CallObjectMethod(cls, findClass, strClassName));
jni_env->DeleteLocalRef(strClassName);