I have created a pre-built Native library libNative.so, that has a JNI function to be called from the Android application.
libNative.so is located in the device at /system/x86_64.
Now, I want to call the JNI function implemented in my pre-built Native library from Android application. I am following below Procedure.
1> Load the Native lib in MainActivity:
static { System.loadLibrary("Native"); }
2> Declared the native method as:
public native int Init();
3> Function definition in the shared lib is:
JNIEXPORT jint Java_App_PACKAGE_NAME_MainActivity_Init(JNIEnv* env, jobject callingObject){
return 0;
}
4>I'm calling the native function in onCreate:
int i = Init();
Now If I build and run the application. I get the error as:
AndroidRuntime: java.lang.UnsatisfiedLinkError: No implementation found for int App_PACKAGE_NAME_MainActivity.Init() (tried Java_App_PACKAGE_NAME_MainActivity_Init and Java_App_PACKAGE_NAME_MainActivity_Init__)
Please help me to resolve the above error.
Why is it that I get linker error even though loading of the library is success.
Thanks in advance !
I found the mistake I was doing.The definition of JNI function in the native library was wrong. I changed as below and everything started working!.
extern "C" JNIEXPORT jint JNICALL
Java_App_PACKAGE_NAME_MainActivity_Init(JNIEnv* env, jobject callingObject){
}
Related
I'm try to make Android Native C++ project in Android Studio 2020.3.1.
Here and here provided common tips for using RegisterNatives in JNI_OnLoad. But in this examples i can't understand what is nativeFoo and nativeBar ? These are methods or functions of c++ code? And what is doing MyClass in example ? I want more full and clear code example for Android NDK C++ native. Thank you!
Going backwards from the RegisterNatives call in the first link, it hooks up native C++ methods to the following Java class:
package com.example.app.package;
class MyClass {
public native void nativeFoo();
public native bool nativeBar(String, int);
}
and it expects that you defined the following C++ functions earlier:
JNIEXPORT void JNICALL nativeFoo(JNIEnv *env, jobject object) { ... }
JNIEXPORT jboolean JNICALL nativeBar(JNIEnv *env, jobject object, jstring a, jint b) { ... }
Android Studio is showing this error. Here's a snippet of the relevant code:
public class MainActivity extends AppCompatActivity {
...
static native void runTests(String path);
static {
System.loadLibrary("TestLib");
}
}
In that first line, runTests is highlit in red and if you hover over it, you see the message "Cannot resolve corresponding JNI function"
To be clear, the app does build and run just fine. It's just that Android Studio thinks that this symbol can't be resolved.
OK, I figured it out. If my function is defined using the standard naming convention, e.g.
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_runTests(JNIEnv *env, jclass cls, jstring path)
Then Android Studio figures it out.
My problem was that I was just defining it as
static void
runTests(JNIEnv *env, jclass cls, jstring path)
and using env->RegisterNatives() to link it into Java. It was too much to ask of Android Studio to figure that out.
I use follow code to handle JNI array in Android and JNI.
However I found return "jobjectArray" cannot complete on API 21/22 (Android 5.0) but works on API 19. (Android 4.4)
(cannot complete mean it return on JNI part but it hang and no response on Java)
Here is the pseudo code I try to implement in my Android App.
jobjectArray Java_com_test_Simplejni(JNIEnv* env, jobject thisObj)
jclass localClass = env->FindClass("java/lang/Object");
jclass objClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass));
args = env->NewObjectArray(len, objClass, 0);
return args;
}
The java part function as follow:
String[] Simplejni();
The error message as follow:
JNI DETECTED ERROR IN APPLICATION: attempt to return an instance of java.lang.Object[] from com.test.Simplejni
Please advise any suggestion how to investigate this issue, thank you.
Update: 20150427
I try to simpreturn empty jobjectArray which works in Android 4.4 but failed in Android 5.0 (with the same code)
My IDE is Android Studio
I found a way to solve this:
you just replace java/lang/Object with your java object class on API 21+, for example,
jclass localClass = env->FindClass("com/example/YourLocalClass");,
From the logs, we can know the object class is not the instance of yourJavaLocalObject class.
I'm trying to run and understand ths example: http://answers.oreilly.com/topic/2689-how-to-use-the-android-ndk-to-improve-performance/
It's a quite simple example with the following files:
FibActivity.java - main activity file
FibLib - class implementing and calling the native functions
fib.c - the C source file with the native functions and code
FibLib.h - the C header file, automatically created from the FibLib class
Android.mk - the makefile
I've implemented the example exactly as described. Still, when I run it, I get this (UnsatisfiedLinkError) error when the app tries to access the native code:
12-21 11:31:53.042: D/dalvikvm(1491): Trying to load lib /data/data
/com.frank.android.ndk/lib/libfib.so 0x405143b8
12-21 11:31:53.042: D/dalvikvm(1491): Added shared lib /data/data/com.frank.android.ndk
/lib/libfib.so 0x405143b8
12-21 11:31:53.042: D/dalvikvm(1491): No JNI_OnLoad found in /data/data
/com.frank.android.ndk/lib/libfib.so 0x405143b8, skipping init
12-21 11:31:53.093: W/dalvikvm(1491): No implementation found for native Lcom/frank
/android/ndk/FibLib;.fibN (I)J
12-21 11:31:53.102: D/AndroidRuntime(1491): Shutting down VM
12-21 11:31:53.102: W/dalvikvm(1491): threadid=1: thread exiting with uncaught
exception (group=0x40015560)
12-21 11:31:53.112: E/AndroidRuntime(1491): FATAL EXCEPTION: main
12-21 11:31:53.112: E/AndroidRuntime(1491): java.lang.UnsatisfiedLinkError: fibN
12-21 11:31:53.112: E/AndroidRuntime(1491): at
com.frank.android.ndk.FibLib.fibN(Native Method)
12-21 11:31:53.112: E/AndroidRuntime(1491): at
com.frank.android.ndk.JavaNativeFibonacciAct
ivity.onClick(JavaNativeFibonacciActivity.java:52)
The only strange thing I notice is, according to the logcat, that eclipse tries to load the library from the /lib folder, while the automatically created folder is called /libs. However, renaming the /lib folder to /libs and rebuilding everything makes no difference.
Anyone got any ideas? I've been trying for days to get examples to work that include using javah to create a header file. Creating only the main activity and the c file, and then calling the native code from the main activity seems to work, but as soon as I begin using header file(s) I get the UnsatisfiedLinkError.
UPDATE:
From FibLib.java:
// Native implementation
static {
System.loadLibrary("fib"); //
}
// Native implementation - recursive
public static native long fibN (int n);
// Native implementation - iterative
public static native long fibNI (int n);
The fib.c file:
#include "com_frank_android_ndk_FibLib.h" /* */
/* Recursive Fibonacci Algorithm */
long fibN(long n) {
if(n<=0) return 0;
if(n==1) return 1;
return fibN(n-1) + fibN(n-2);
}
/* Iterative Fibonacci Algorithm */
long fibNI(long n) {
long previous = -1;
long result = 1;
long i=0;
int sum=0;
for (i = 0; i <= n; i++) {
sum = result + previous;
previous = result;
result = sum;
}
return result;
}
/* Signature of the JNI method as generated in header file */
JNIEXPORT jlong JNICALL Java_com_frank_android__ndk_fibN (JNIEnv *env, jclass obj, jlong n) {
return fibN(n);
}
/* Signature of the JNI method as generated in header file */
JNIEXPORT jlong JNICALL Java_com_frank_android__ndk_fibNI (JNIEnv *env, jclass obj, jlong n) {
return fibNI(n);
}
The Andoid.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := fib
LOCAL_SRC_FILES := fib.c
include $(BUILD_SHARED_LIBRARY)
Your Java package name appears to be named "com.frank.android.ndk" and your Java class name appears to be named "FibLib" and in turn the name of the C function matching FibN should be Java_com_frank_android_ndk_FibLib_fibN. This page is referened by the Android docs and details the JNI naming convention for C functions.
Does it only seem, or your C function names really use double underscore before word ndk? It should be single underscore IMHO.
It can't find Lcom/frank/android/ndk/FibLib;.fibN. The log indicates that the library was loaded successfully.
The method should be called Java_com_frank_android_ndk_FibLib_fibN; in the question you have a double underscore and you're missing the class name. If you have two different methods that resolve to the same thing, you can differentiate them by encoding the arguments as well, but that doesn't seem necessary here.
You said this is a C program, but sometimes people conflate C and C++, so I'll also point out that if this is a ".cpp" file you'll need to put extern "C" in the declaration or C++ will "mangle" the function name.
See also http://developer.android.com/training/articles/perf-jni.html#faq_ULE
have you complied the JNi Code Using ndk-build ?
the class Name Should be same as Described in JNI and in Java
Java_com_qualcomm_QCARSamples_VideoPlayback_VideoPlayback_initApplicationNative
the initApplicationNative is method name that should be same on both Java and JNi
if not then you will get this error
I'm looking for clues why my Android app sporadically throws an UnsatisfiedlinkError exception on a specific ndk call:
I have an Android app that loads one native library through ndk.
The native library is written in C++ and uses STL (in my makefile I have set APP_STL := stlport_static). No other libraries are used or required. The native library has about 300 native methods for about 20 java classes.
All works fine, most of the time. But every now and then my users get an UnsatisfiedLinkError exception. The exception is always triggered at the same spot with the same native function call, but strangely enough it is not even the first call to a native function, not even the first call to that specific native function.
Any clue would be welcome why one specific native call could fails. Can ndk easily be corrupted? How do you debug for such a problem?
Simple test programs with the same call work just fine. Nevertheless here's some parts of the source code:
Here's the problem ndk function in Java:
public class Server {
...
static private native long longObserveError( );
...
}
Here's the header file:
extern "C" {
...
JNIEXPORT jlong JNICALL Java_be_gentgo_tetsuki_Server_longObserveError
(JNIEnv *, jclass);
...
}
And here's the implementation:
IGSProtocol *server = 0; // initialized later...
JNIEXPORT jlong JNICALL Java_be_gentgo_tetsuki_Server_longObserveError
(JNIEnv *env, jclass)
{
Messenger &mess = server->ObserveError( );
return (long)(&mess);
}
What is the name of your library file? I came across another SO post (https://stackoverflow.com/a/18024816) where the guy had a library name that was conflicting with a system library that was only present on some devices. Renaming his library fixed the problem.