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.
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
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()).
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?
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)