I want to use FFMpeg on android. I'm really new to this topic. I build libraries with this tutorial]1. Now I have .so and .h files but I dont know how to use them in my project. I probably need to link it in my Android.mk file. Here is my .mk and .c file in my project:
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE := ndksetup
LOCAL_SRC_FILES := native.c
include $(BUILD_SHARED_LIBRARY)
native.c
#include <jni.h>
#include <string.h>
#include <android/log.h>
#define DEBUG_TAG "NDKSetupActivity"
void Java_com_example_ndksetup_MainActivity_printLog(JNIEnv *env, jobject this, jstring logString)
{
jboolean isCopy;
const char * szLogString = (*env)->GetStringUTFChars(env, logString, &isCopy);
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: %s", szLogString);
(*env)->ReleaseStringUTFChars(env, logString, szLogString);
}
jint Java_com_example_ndksetup_MainActivity_fibonacci(JNIEnv * env, jobject this, jint value)
{
if (value <= 1) return value;
return Java_com_example_ndksetup_MainActivity_fibonacci(env, this, value-1)
+ Java_com_example_ndksetup_MainActivity_fibonacci(env, this, value-2);
}
Can anyone tell me how I can use .so and .h files in my native.c file?
This how you would make calls to lib files in your JNI folder from your native C file
JNIEXPORT jstring JNICALL Java_*(JNIEnv *pEnv, jobject pObj) {
char* lCodecName = gVideoCodecCtx->codec->name;
return (*pEnv)->NewStringUTF(pEnv, lCodecName);
}
and this is how you link the native libraries from your Java code
static {
System.loadLibrary("<native jni lib file name>");
}
Related
I tried to use a prebuild shared library in JNI.
But when I built JNI library, it always complain function undefined reference.
Here is my Android.mk file.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mtestlib
LOCAL_SRC_FILES := mtest/arm64-v8a/lib/libtest.so
LOCAL_EXPORT_C_INCLUDES := mtest/arm64-v8a/include
LOCAL_EXPORT_LDLIBS := mtest/arm64-v8a/lib/libtest.so
LOCAL_PRELINK_MODULE := true
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := myJNI
LOCAL_SRC_FILES := myJNI.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/mtest/arm64-v8a/include
LOCAL_SHARED_LIBRARY := mtestlib
include $(BUILD_SHARED_LIBRARY)
This is my JNI file.
#include "lucien_example_com_jtest_myNDK.h"
#include <android/log.h>
#include <iostream>
#include <iostream>
#include "Mtest.h"
JNIEXPORT jint JNICALL Java_lucien_example_com_jtest_myNDK_test
(JNIEnv *env, jobject, jstring tmp){
const char* str;
str = env->GetStringUTFChars(tmp,false);
std::cout<< str << std::endl;
env->ReleaseStringUTFChars(tmp,str);
mtest(str);
}
Mtest.h Header:
#include <stdio.h>
#include <stdlib.h>
#include <cutils/properties.h>
#include <utils/Log.h>
int mtest(const char *str);
mtest source file:
#include "Mtest.h"
#define LOG_TAG "Test"
int mtest(const char *str){
ALOGE("[Lucien] test(%s)", str);
return 0;
}
I don't know why I got complain undefined reference when JNI load mtest() function.
The header and prebuild lib are already included.
Which wrong step causes this error?
Please help me, thanks.
The name of your function are not the same in .h file and source file:
int mtest(const char *str);
int mjpeg(const char *str){
ALOGE("[Lucien] test(%s)", str);
return 0;
}
try calling mtest in your source file:
int mtest(const char *str){
ALOGE("[Lucien] test(%s)", str);
return 0;
}
To match with your jni call:
JNIEXPORT jint JNICALL Java_lucien_example_com_jtest_myNDK_test
(JNIEnv *env, jobject, jstring tmp){
...
mtest(str);
}
EDIT 1
Your jni function expect to return a jint but you aren't returning anything. Try with a return statement at the end of the function:
JNIEXPORT jint JNICALL Java_lucien_example_com_jtest_myNDK_test
(JNIEnv *env, jobject, jstring tmp){
const char* str;
str = env->GetStringUTFChars(tmp,false);
std::cout<< str << std::endl;
env->ReleaseStringUTFChars(tmp,str);
mtest(str);
//Example:
return 0;
}
I just started to use NDK and i ran Hello_Jni and i know how that works but i wanted to try do something like this and cant get it to work (Im doing this manually)
simple.c
#include "simple.h"
#include <jni.h>
JNIEXPORT jdouble JNICALL
Java_com_example_Test_round_decimals (JNIEnv * env, jobject obj, jdouble value, jint decimals) {
double m = pow (10, decimals);
return (double) round (value * m) / m;
}
JNIEXPORT jstring JNICALL Java_com_example_Test_hello(JNIEnv* env, jobject javaThis) {
return (*env)->NewStringUTF(env, "Hello from ME!");
}
simple.h
#include <stdio.h>
#include <stdlib.h>
#include "math.h"
#include <string.h>
#include <jni.h>
JNIEXPORT jdouble JNICALL Java_com_example_Test_round_decimals (JNIEnv * env, jobject obj,jdouble value, jint decimals);
JNIEXPORT jstring JNICALL Java_com_example_Test_hello(JNIEnv* env, jobject javaThis);
Activity
public class Test{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
double test = round_decimals(10.1234,2);
double test2 = hello();
Log.i("Round","Number" + test); // i would like to get this
Log.i("String","hello? " + test2); // this works it shows "Hello From ME!"
}
public native double round_decimals(double value, int decimals);
public native String hello();
static {
System.loadLibrary("simple");
}
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := simple
LOCAL_SRC_FILES := simple.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)
android.mk, simple.c and simple.h are in JNI folder of my Activity.
And also running Build-ndk in folder of my Activity shows no errors
But when i try to build it on my tablet i get this error.
java.lang.UnsatisfiedLinkError:round_decimals
You generated the .h file from a version of the .java that had a package statement in it, then you modified the .java file to remove the package statement, then you compiled and ran, and nothing matched up.
There's something else wrong here. The method signature should be (JNIEnv*, jobject, jdouble, jint) if you've generated the files correctly.
Regenerate the .h file and adjust the .c file accordingly.
i Found the problem it was with Java_com_example_Test_round_decimals had to rename it to
Java_com_example_Test_roundDecimals and with that i had to rename public native double round_decimals(double value, int decimals); to public native double roundDecimals(double value, int decimals);
You had an underscore (_) inside your method name and underscores are name delimiters in JNI convention.
Changing the java method name to camel case is a solution but you can also escape underscores using _1 in your native method name, like so: Java_com_example_Test_round_1decimals.
It looks like it is the popular problem,
And I still not find out the solution.
package name : app.cloudstringers
Java file : Completed.java
static {
try {
System.loadLibrary("ffmpeg");
} catch (UnsatisfiedLinkError e) {
Log.d("", "Error : " + e.toString());
}
}
// Define native method
public native int getString();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.page_completed);
// Call native method
Log.d("", "" + getString());
C++ file : ffmpeg.cpp
#include <jni.h>
#include <android/log.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jstring JNICALL Java_app_cloudstringers_Completed_getString(JNIEnv* env, jobject thiz)
{
jstring strRet = env->NewStringUTF("HelloWorld from JNI !");
return strRet;
}
#ifdef __cplusplus
}
#endif
Android.mk file
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES := ffmpeg.cpp
include $(BUILD_SHARED_LIBRARY)
I run application but still get the error exception UnsatisfiedLinkError : getString
People who know the how to fix this problem,
Please tell me,
Thanks
UPDATE
Follow #dextor answer. Sorry because I get the mistake. Only thing I need for this question is change from public native int getString() to public native String getString().
It works now.
Not sure (didn't actually try), but the only wrong thing I've noticed is the return type of your method declarations.
Java-side
public native int getString()
NDK-side
JNIEXPORT jstring JNICALL Java_app_cloudstringers_Completed_getString(JNIEnv* env, jobject thiz)
In Java, you have an int. On the C-side, you have a jstring.
I am implementing Android camera app where I am processing preview frames in JNI. I have processImage.cpp file where I do all the native processing and it worked until now when I have discovered that if I do any change to the native file, it does not change the behaviour of the app.
Maybe it could be connected to the static linking of OpenCV library that I've added recently and where I load the native library.
package fit.vutbr.faceswap;
// OpenCV static initialization
static {
if (!OpenCVLoader.initDebug()) {
// Handle initialization error
Log.d(TAG, "OpenCV init error");
}
else {
System.loadLibrary("processImage");
//System.loadLibrary("detection_based_tracker");
}
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# OpenCV
OPENCV_LIB_TYPE:=STATIC
OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on
include C:\Users\Acer\Projects\OpenCV\OpenCV-2.4.6-android-sdk\sdk\native\jni\OpenCV.mk
LOCAL_C_INCLUDE:= C:\Users\Acer\Projects\OpenCV\OpenCV-2.4.6-android-sdk\sdk\native\jni\include
LOCAL_LDLIBS += -llog -ldl
LOCAL_MODULE := processImage
LOCAL_SRC_FILES := processImage.cpp
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi-v7a
APP_MODULES := processImage
Declaration of the native method:
private native int[] kalmanFilterNative(int center_x, int center_y);
Definition in processImage.cpp:
jintArray Java_fit_vutbr_faceswap_CameraPreview_kalmanFilterNative( JNIEnv* env, jobject thiz, jint center_x, jint center_y)
{
// code
return ret;
}
And on call ret = kalmanFilterNative(center_x, center_y); I get UnsatisfiedLinkError: Native method not found.
Does anybody have a clue where is the problem?
Try to modify your native method to :
extern "C" {
JNIEXPORT jintArray JNICALL Java_fit_vutbr_faceswap_CameraPreview_kalmanFilterNative( JNIEnv* env, jobject thiz, jint center_x, jint center_y);
};
JNIEXPORT jintArray JNICALL Java_fit_vutbr_faceswap_CameraPreview_kalmanFilterNative( JNIEnv* env, jobject thiz, jint center_x, jint center_y)
{
// code
return ret;
}
im attempting to build c++ code with ndk-build but i keep getting this error base operand of '->' has non-pointer type 'JNIEnv <aka _JNIEnv>'
i have tried every solution on the first 2 pages of google with no luck, the ndk just isnt being good to me.
nativemain.h
#ifndef NATIVEMAIN_H
#define NATIVEMAIN_H
#include <string.h>
#include <jni.h>
extern "C"
{
JNIEXPORT jstring JNICALL Java_com_ndktest3_MyRenderer_stringFromJNI( JNIEnv* env,
jobject thiz );
}
#endif
nativemain.cpp
#include <nativemain.h>
JNIEXPORT jstring JNICALL Java_com_ndktest3_MyRenderer_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return env->NewStringUTF("Hello from JNI !");
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := nativemain
LOCAL_SRC_FILES := nativemain.cpp
include $(BUILD_SHARED_LIBRARY)
Try changing your syntax slightly
I believe the error is the miss-use of the '->' operator
"
{
return env->NewStringUTF("Hello from JNI !");
}
try casting env as a pointer like so
{
return (*env)->NewStringUTF(env, str);
}
where str is a predefined string such as your hello message.
check this post as a cross reference: Do I need to clean up the char* passed to NewStringUTF?