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)
Related
I have an Android native library (C++ code base) called:
libserverapp.so
And I cannot get the Android build to find it:
"DllNotFoundException: serverapp"
I am using an internal build system, but when I parse the output of the build process, I can see many calls of the form:
android-ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/arm-linux-androideabi-g++.exe -march=armv7-a
After building my Android app, I inspect the resulting APK (renaming to .zip and extracting), and can see my library file here:
lib/armeabi-v7a/libserverapp.so
I can confirm that "ARMv7" is the target architecture in the Android Player settings, and I access the library, in C#, via:
[DllImport("serverapp", CallingConvention = CallingConvention.Cdecl)]
private static extern void run_sim(StringBuilder matchInput, StringBuilder results, int randomSeed);
I have built a Windows DLL of the C++ code, to use in the Editor, and everything works great. However, when I move to Android, the .so cannot be found. The import settings for libserverapp.so are:
Platform: Android; CPU: ARMv7; Path: Assets/Plugins/Android/libserverapp.so; Type: Native
Given that the final APK includes the .so where I expect it to be (lib/armeabi-v7a/), I assume my Unity settings are correct? Also, I am not using IL2CPP for the Android build.
Finally, when I do an object dump of the library file (using arm-linux-androideabi-objdump.exe), the file format of the library file is "elf32-littlearm".
I feel that the issue here is simply finding the .so, not the functionality within it. Any ideas on what's going on here?
Thanks!
I ended up solving the problem. I mentioned that was using an internal build system. Well, there seems to be a bug in it. I ported things over to official Android NDK makefiles, and then it "just worked". So in this case, the library could be found, but its contents weren't valid.
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.
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?