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?
Related
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.
We are using Android NDK to write a c++ library on android and the library needs use JavaVM and AAssetManager. The problem is that we find no way to access JavaVM and AAssetManager inside our library.
What I know is:
In native host application, we can get them from ANativeActivity
AAssetManager_fromJava if java
jint JNI_OnLoad(JavaVM* vm, void* reserved)
It seems it can't work if the host application is also native c++
The library will be delivered to our users. It won't be elegant to force our users to set JavaVM and AAssetManager. Do you have any idea? thanks
If you want to cover both cases in the same way ("typical" and "native" app) - the only way is next:
Add MyLibrary.java to your library. That file should declare native method MyLibrary.init(AssetManager am);. Implementation of that method must be placed in your C++ code, where you get java reference to asset manager and then can obtain AAssetManager *
Add JNI_OnLoad() to your library in order to obtain JavaVM*
Build your library as separate .so to allow system to invoke your JNI_OnLoad()
Usage looks next:
Client app declares custom Application class in its manifest
Implementation of this custom class overrides onAttachBaseContext() method, which implementation invokes System.loadLibrary("mylibrary") and then your MyLibrary.init(getAssets()).
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);
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
I have built FFMPEG executables and libraries as provided by Bambuser (http://bambuser.com/opensource). So I managed to build the Android executables and libraties. How can I link these libs in my Eclipse project and invoke the FFmpeg functions from Java? The open source code includes the C header-files.
I am new to native coding for Android, and I could not find an easy answer for this. In basic : having a bunch of Android compatible libraries and some C header files what do I have to do to reuse those libaries' functionality from java (+Android SDK)?
Any help would be appreciated.
Kind regards,
WhyHow
You have to write some C glue code using the JNI conventions to expose the FFmpeg functionalities to Java code. Here's an example of a JNI method implemented in C from the Android NDK samples:
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
You also need some Java code to load the library and declare the native method.
public class HelloJni
{
public native String stringFromJNI();
static {
System.loadLibrary("hello-jni");
}
}
I found this project on sourceforge which already has implemented some JNI interface to ffmpeg to integrate it with the Java Media Framework. You may find it useful.
There's another Java FFI technology called JNA (Java Native Access) that allows you to declare native function prototypes in Java and call them directly. Using it may require less boilerplate code. See this project for an Android implementation. (I have never used it myself)