Sporadically UnsatisfiedLinkError with Android NDK - android

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.

Related

Android NDK RegisterNatives more full example

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 spurious "Cannot resolve corresponding JNI function"

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.

A simple way to build with the Android NDK

I started out writing a simple C++ program that tried to get the handle of a service using
defaultServiceManager()->getService(String16('ServiceName'));
Which has now snowballed into this terrible dependency recursion. Ultimately what I need is:
libbinder for defaultServiceManager and getService
libutils for String16
Neither of these are available in the NDK. Their sources are in the SDK along with all the appropriate headers. I can get everything to behave nicely until link time:
undefined reference to `android::defaultServiceManager()'
undefined reference to `android::String16::String16(char const*)'
undefined reference to `android::String16::~String16()'
undefined reference to `android::String16::~String16()'
Is it required to build this as a part of AOSP? Perhaps through something like ndk-build? What I am building is more of a toy application that only needs access to those (and related, e.g. service->transact APIs) APIs along with Parcel.
Perhaps building AOSP once and using -L to include a search path to the generated libs.
libbinder and libutils are not part of the app API surface. https://developer.android.com/ndk/reference/group/ndk-binder is the NDK binder API.
This (dirty hack) is working fine for me:
#include <android/binder_ibinder.h>
typedef AIBinder* (*AServiceManager_getService_func)(const char* instance);
extern "C"
JNIEXPORT void JNICALL
Java_com_irsl_greedybinder_MainActivity_testService(JNIEnv *env, jclass clazz) {
void* binder_ndk = dlopen("/system/lib/libbinder_ndk.so", RTLD_LAZY);
if (binder_ndk == nullptr) {
ALOGI("Unable to load libbinder_ndk.so");
return;
}
AServiceManager_getService_func AServiceManager_getService;
AServiceManager_getService = (AServiceManager_getService_func) dlsym(binder_ndk, "AServiceManager_getService");
if(AServiceManager_getService == nullptr) {
ALOGI("Failed to look up AServiceManager_getService");
return;
}
ALOGI("AServiceManager_getService symbol found at: %p", AServiceManager_getService);
AIBinder* binder = AServiceManager_getService("activity");
if (binder == nullptr) {
ALOGI("Unable to obtain Activity Manager service");
return;
}
ALOGI("We got the binder to the Activity Manager!: %p", binder);
}
Disclaimer by Dan Albert applies: They exist for vendor and APEX users. Those domains do not carry the same guarantees that are needed for apps to use them reliably, so they are not exposed to apps.

Calling native function from the Android API level 28 Application

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){
}

Android NDK C++ JNI (no implementation found for native...)

I'm trying to use the NDK with C++ and can't seem to get the method naming convention correct. my native method is as follows:
extern "C" {
JNIEXPORT void JNICALL Java_com_test_jnitest_SurfaceRenderer_drawFromJni
(JNIEnv* env, jclass c)
{
//
}
}
with a header wrapped in extern "C" {} aslo.
Everything compiles fine, creates a .so file and copies to the libs folder under my project, but when I debug and run in Eclipse I keep getting a log cat message that of "no implementation found for native...". Is there something i'm missing as all the NDK examples are in C?
Thanks.
There are a couple of things that can lead to "no implementation found". One is getting the function prototype name wrong, another is failing to load the .so at all. Are you sure that System.loadLibrary() is being called before the method is used?
If you don't have a JNI_OnLoad function defined, you may want to create one and have it spit out a log message just to verify that the lib is getting pulled in successfully.
You already dodged the most common problem -- forgetting to use extern "C" -- so it's either the above or some slight misspelling. What does the Java declaration look like?
An additional cause for this error: your undecorated native method name must not contain an underscore!
For example, I wanted to export a C function named AudioCapture_Ping(). Here is my export declaration in C:
JNI_EXPORT int Java_com_obsidian_mobilehashhost_MainActivity_AudioCapture_Ping(JNIEnv *pJniEnv, jobject object); //Notice the underscore before Ping
Here was my Java class importing the function:
package com.obsidian.mobileaudiohashhost;
...
public class MainActivity extends Activity {
private native int AudioCapture_Ping(); // FAILS
...
I could not get Android to dynamically link to my native method until I removed the underscore:
JNI_EXPORT int Java_com_obsidian_mobilehashhost_MainActivity_AudioCapturePing(JNIEnv *pJniEnv, jobject object);
package com.obsidian.mobileaudiohashhost;
...
public class MainActivity extends Activity {
private native int AudioCapturePing(); // THIS WORKS!
...
I had the same problem, but to me the error was in the file Android.mk. I had it:
LOCAL_SRC_FILES := A.cpp
LOCAL_SRC_FILES := B.cpp
but should have this:
LOCAL_SRC_FILES := A.cpp
LOCAL_SRC_FILES += B.cpp
note the detail += instead :=
I hope that helps.
Called extern "C" as provided in the automatically-generated Studio example, but forgot to wrap the entire rest of the file, including following functions, in {} brackets. Only the first function worked.
An additional reason: Use LOCAL_WHOLE_STATIC_LIBRARIES instead of LOCAL_STATIC_LIBRARIES in android.mk. This stops the library from optimizing out unused API calls because the NDK cannot detect the use of the native bindings from java code.
There is a cpp example under apps in ndk:
https://github.com/android/ndk-samples/blob/master/hello-gl2/app/src/main/cpp/gl_code.cpp
Use javah (part of Java SDK). Its the tool exactly for this (generates .h header from .class file).
If your package name includes _ character, you should write 1(one) after _ character as shown below:
MainActivity.java
package com.example.testcpp_2;
native-lib.cpp
JNICALL
Java_com_example_testcpp_12_MainActivity_stringFromJNI(
I try all above solutions, but no one can solved my build error(jni java.lang.UnsatisfiedLinkError: No implementation found for...),
at last I found that I forget to add my verify.cpp source file to CMakeList.txt add_library segement(verify.cpp is auto generate by Ctrl + Enter short key, maybe other file name), hope my response can help some one.
my build environment: Gradle + CMake
I Faced the same problem, and in my case the reason was that I had underscore in package name "RFID_Test"
I renamed the Package and it worked.
Thanks user1222021
I faced the same problem twice. It happened, that the phone I tried to start the app from Android Studio used an API level that I haven't downloaded yet in Android Studio.
Upgrade Android Studio to the latest version
Download the necessary API from within Android Studio

Categories

Resources