Android JNI java.lang.UnsatisfiedLinkError - android

I'm trying to implement the method rotateBitmapCcw90 found at another question.
In order to use this method, I've created a java class, named Utils. This class is as simple as:
package com.test.jnitest;
import android.graphics.Bitmap;
public class Utils {
static {
System.loadLibrary("utils");
}
public static native Bitmap rotateBitmapCcw90(Bitmap bitmap);
}
rotateBitmapCcw90 is implemented inside com_test_jnitest_Utils.cpp under poject_path/jni. The content of this file is:
#include <jni.h>
#include <android/log.h>
#include <android/bitmap.h>
#include <stdio.h>
#include <stdlib.h>
#define LOG_TAG "libutils"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
extern "C" {
JNIEXPORT jobject JNICALL Java_com_test_jnitest_Utils_rotateBitmapCcw90(JNIEnv * env, jobject obj, jobject bitmap)
{
// same code of other question
...
}
};
My Android.mk is:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libutils
LOCAL_SRC_FILES := com_test_jnitest_Utils.cpp
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
LOCAL_LDLIBS += -ljnigraphics
include $(BUILD_SHARED_LIBRARY)
Everything compiles successfully (ndk-build and Eclipse project), but as soon as I call Utils.rotateBitmapCcw90 passing a Bitmap, I get an java.lang.UnsatisfiedLinkError. The log says:
03-15 14:46:48.243: D/dalvikvm(1936): Trying to load lib /data/data/com.example.jnitest/lib/libutils.so 0x40f77c98
03-15 14:46:48.253: D/dalvikvm(1936): Added shared lib /data/data/com.example.jnitest/lib/libutils.so 0x40f77c98
03-15 14:46:48.253: D/dalvikvm(1936): No JNI_OnLoad found in /data/data/com.example.jnitest/lib/libutils.so 0x40f77c98, skipping init
03-15 14:46:48.333: W/dalvikvm(1936): No implementation found for native Lcom/test/jnitest/Utils;.rotateBitmapCcw90:(Landroid/graphics/Bitmap;)Landroid/graphics/Bitmap;
Quetion is: what am I doing wrong? Is there anything wrong with my cpp file? I have also already tried to generate a header with javah and including it on my cpp, but the same error appears.

I finally got it to work after changing lib name from utils to bitmaputils.

Trying to do like this:
import android.graphics.Bitmap;
static {
System.loadLibrary("utils");
}
public class Utils {
public static native Bitmap rotateBitmapCcw90(Bitmap bitmap);
}

Your ndk code is in "com_test_jnitest_Utils.cpp",
but you add "com_test_jnitest_Utils.c" in "Android.mk".
If you change the file name extension, no error in this program.

in your .mk file should be like this:
LOCAL_MODULE := utils

Related

NDK - call a native function from .so file

I wrote a sample shared library in VS 2015 (NDK Cross Platform project)
Common.h:
#ifdef __cplusplus
extern "C" {
#endif
int first(int x, int y);
#ifdef __cplusplus
}
#endif
Common.cpp:
#include "Common.h"
int first(int x, int y)
{
return x + y;
}
so now i have a .so file and i want to create a project in Android Studio which link against that .so file and call first(x,y) with JNI.
hello_jni.c:
#include "Common.h"
#include <jni.h>
jint
Java_com_test_MainActivity_add( JNIEnv* env,
jobject thiz,
jint a,
jint b)
{
return (jint)first((int)a,(int)b);
}
So I put libCommon.so and Common.h in jni folder of the project
edited the android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := libCommon.so
LOCAL_MODULE := add_prebuilt
LOCAL_EXPORT_C_INCLUDES := Common.h
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_SRC_FILES := hello_jni.c
LOCAL_MODULE := hello_jni
LOCAL_SHARED_LIBRARIES := add_prebuilt
include $(BUILD_SHARED_LIBRARY)
(I added LOCAL_ALLOW_UNDEFINED_SYMBOLS := true since I got an error undefined reference to 'first')
Application.mk:
APP_ABI := armeabi-v7a
So now I have two .so files in src\main\libs\armeabi-v7a.
The application is crashed when I load libhello_jni.so
and it isn't crashed for loading libCommon.so
static
{
System.loadLibrary("Common");
System.loadLibrary("hello_jni");
}
Error log:
02-03 12:52:52.509 9685-9685/com.test E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.test, PID: 9685
java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "first" referenced by "libhello_jni.so"...
at java.lang.Runtime.loadLibrary(Runtime.java:364)
at java.lang.System.loadLibrary(System.java:526)
at com.test.MainActivity.<clinit>(MainActivity.java:23)
at java.lang.Class.newInstanceImpl(Native Method)
at java.lang.Class.newInstance(Class.java:1208)
at android.app.Instrumentation.newActivity(Instrumentation.java:1061)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2101)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
at android.app.ActivityThread.access$800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
I don't know what to do ... Why first function not found ?
Any ideas?
Thanks!

USing Openssl to find PBKDF2WithHmacSHA1 in Android

I am also using sqlCipher in my application. They use openssl for calculating PKDF2 and I have read somewhere that openssl implementation is very faster than java implementation to find PKDF2. So my question is:
Is this true that openssl can give me better performace on android?
Can I use openssl implementation used in sqlCipher?
If yes how can I use find PKDF2 using openssl?
If No then how can I use openssl to find PBKDF2WithHmacSHA1 in
android. I have searched over the net but didn't found any example.
Thanks Nick for your suggestion
I have tried your suggestion and I am able to call c function using JNI in my java class.
Now I have one problem. How should I include openssl (Or call PKCS5_PBKDF2_HMAC_SHA1 in my c code). Here is my code:
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define KEY_LEN 32
#define KEK_KEY_LEN 20
#define ITERATION 1
JNIEXPORT jstring JNICALL
Java_com_example_testjni_MainActivity_someFunction(JNIEnv * env, jobject obj) {
// return 3;
size_t i;
unsigned char *out;
const char pwd[] = "password";
unsigned char salt_value[] = {'s','a','l','t'};
out = (unsigned char *) malloc(sizeof(unsigned char) * KEK_KEY_LEN);
printf("pass: %s\n", pwd);
printf("ITERATION: %u\n", ITERATION);
printf("salt: "); for(i=0;i<sizeof(salt_value);i++) { printf("%02x", salt_value[i]); } printf("\n");
if( PKCS5_PBKDF2_HMAC_SHA1(pwd, strlen(pwd), salt_value, sizeof(salt_value), ITERATION, KEK_KEY_LEN, out) != 0 )
{
printf("out: "); for(i=0;i<KEK_KEY_LEN;i++) { printf("%02x", out[i]); } printf("\n");
}
else
{
fprintf(stderr, "PKCS5_PBKDF2_HMAC_SHA1 failed\n");
}
return "";
}
Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := example
LOCAL_CFLAGS := -Werror
LOCAL_SRC_FILES := example.c
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
I am getting this error when I compile my c code using ndk-build:
C:/Users/Nauman/Downloads/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/p
rebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-
linux-androideabi/bin/ld.exe: ./obj/local/armeabi/objs/example/example.o: in fun
ction Java_com_example_testjni_MainActivity_someFunction:jni/example.c:25: error
: undefined reference to 'PKCS5_PBKDF2_HMAC_SHA1'
collect2: ld returned 1 exit status
make.exe: * [obj/local/armeabi/libexample.so] Error 1
EDIT
Here is the exception I get when loading libs:
07-22 10:04:26.083: E/AndroidRuntime(1952): FATAL EXCEPTION: Thread-156
07-22 10:04:26.083: E/AndroidRuntime(1952): java.lang.UnsatisfiedLinkError: Couldn't load stlport_shared from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.ebricks.cii-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.ebricks.cii-1, /system/lib]]]: findLibrary returned null
07-22 10:04:26.083: E/AndroidRuntime(1952): at java.lang.Runtime.loadLibrary(Runtime.java:355)
07-22 10:04:26.083: E/AndroidRuntime(1952): at java.lang.System.loadLibrary(System.java:525)
07-22 10:04:26.083: E/AndroidRuntime(1952): at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:112)
07-22 10:04:26.083: E/AndroidRuntime(1952): at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:107)
SQLCipher for Android does statically link OpenSSL, so PKCS5_PBKDF2_HMAC_SHA1 is included within the precompiled binaries. However if all you need is a call PKCS5_PBKDF2_HMAC_SHA1 directly, libcrypto.so is generally distributed with all Android platforms, however the version is often different on many platforms. To access PKCS5_PBKDF2_HMAC_SHA1, you will need to write a JNI interop library with the Android NDK that links to libcrypto, along with a Java wrapper class to load your native library and make the call into JNI. As a reference, I statically link OpenSSL within SQLCipher for Android here.

Android App crashs and show UnsatisfiedLinkError

I try run an Android application using ndk, i can build the library, but when i run give a exception.
follow the codes and error for help the solution
i use c code, instead cpp
primitive.c
#include <jni.h>
#include <android/log.h>
JNIEXPORT jboolean JNICALL Java_cookbook_chapter2_PassingPrimitiveActivity_passBooleanReturnBoolean(JNIEnv *pEnv, jobject pObj, jboolean pBooleanP){
__android_log_print(ANDROID_LOG_INFO, "native", "%d in %d bytes", pBooleanP, sizeof(jboolean));
return (!pBooleanP);}
Acitivity class: PassingPrimitiveActivity.java
public class PassingPrimitiveActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_passing_primitive);
StringBuilder strBuilder = new StringBuilder();
strBuilder.append("boolean: ").append(passBooleanReturnBoolean(false))");;
TextView tv = (TextView) findViewById(R.id.display_res);
tv.setText(strBuilder.toString());
}
private native boolean passBooleanReturnBoolean(boolean p);
static {
System.loadLibrary("PassingPrimitive");
} }
logcat file, with error. Show that don't have implementation, but in c code, have it
06-11 17:08:30.652 29603 29603 E AndroidRuntime: FATAL EXCEPTION: main
06-11 17:08:30.652 29603 29603 E AndroidRuntime: java.lang.UnsatisfiedLinkError: Native method not found: cookbook.chapter2.passingprimitive.PassingPrimitiveActivity.passBooleanReturnBoolean:(Z)Z
06-11 17:08:30.652 29603 29603 E AndroidRuntime: at cookbook.chapter2.passingprimitive.PassingPrimitiveActivity.passBooleanReturnBoolean(Native Method)
06-11 17:08:30.652 29603 29603 E AndroidRuntime: at cookbook.chapter2.passingprimitive.PassingPrimitiveActivity.onCreate(PassingPrimitiveActivity.java:15)
06-11 17:08:30.652 29603 29603 E AndroidRuntime: at android.app.Activity.performCreate(Activity.java:5184)
my Android.mk seens like it:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := PassingPrimitive
LOCAL_SRC_FILES := primitive.c
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
Everything compiles fine, creates a .so file and copies to the libs folder under my project, but when I run, logcat show UnsatisfiedLinkError and the app crash
What i can do for solve it?
Try generating a proper C header file from your compiled java code, like this:
javah -jni -classpath bin/classes com.whatever.PassingPrimitiveActivity
then include that header file in your C code. The function you define in C should match the one in the header file. The mapping is not always what you assume.
Your logcat suggests that the native function name should be
Java_cookbook_chapter2_passingprimitive_PassingPrimitiveActivity_passBooleanReturnBoolean

Android SDK app failed to load library

Heyho. I've got the same error message as this guy:
"Android NDK app failed to load library"
and i'm trying to transfer these answers here on my situation for hours now, but it doesnt work.
Can someone help me?
It's this opensource project here, which i want to try to get it run on my emulator.
https://github.com/itskewpie/FreeRDP-android
FreeRDPActivity.java
package net.itskewpie.freerdp;
import android.app.Activity;
import android.os.Bundle;
public class FreeRDPActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
static {
System.loadLibrary("freerdp");
}
}
freerdp.c
#include <jni.h>
#include <stdio.h>
#include <freerdp/freerdp.h>
jstring Java_net_itskewpie_freerdp_FreeRDPActivity_test(JNIEnv* env, jobject thiz )
{
android_main();
return (*env)->NewStringUTF(env, "HELLO");
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
MY_LIBS_PATH=freerdp-1.0-nevo/libs/armeabi-v7a
LOCAL_MODULE := freerdp-utils
LOCAL_SRC_FILES := $(MY_LIBS_PATH)/libfreerdp-utils.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/freerdp-1.0-nevo/include
include $(PREBUILT_STATIC_LIBRARY)
...
Error Message:
FATAL EXCEPTION: main
java.lang.ExceptionInInitializerError
java.lang.Class.newInstanceImpl(Native Method)
java.lang.Class.newInstance(Class.java:1319)
android.app.Instrumentation.newActivity(Instrumentation.java:1054)
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2097)
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
android.app.ActivityThread.access$600(ActivityThread.java:141)
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
android.os.Handler.dispatchMessage(Handler.java:99)
android.os.Looper.loop(Looper.java:137)
android.app.ActivityThread.main(ActivityThread.java:5041)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:511)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
dalvik.system.NativeStart.main(Native Method)
java.lang.UnsatisfiedLinkError: Couldn't load freerdp from loader dalvik.system.PathClassLoader[dexPath=/data/app/net.itskewpie.freerdp-2.apk,libraryPath=/data/app-lib/net.itskewpie.freerdp-2]: findLibrary returned null
java.lang.Runtime.loadLibrary(Runtime.java:365)
java.lang.System.loadLibrary(System.java:535)
net.itskewpie.freerdp.FreeRDPActivity.<clinit>(FreeRDPActivity.java:16)
... 15 more
try out this open source project:
www.freerdp.com
Did you copy the Android.mk exactly as in the github project? Did you copy the relevant libraries too?
#
## libfreerdp.so
#
include $(CLEAR_VARS)
LOCAL_MODULE := freerdp
LOCAL_SRC_FILES := freerdp.c
LOCAL_ARM_MODE := arm
NDK_TOOLCHAIN_ROOT=/opt/android-toolchain
LOCAL_STATIC_LIBRARIES := freerdp-utils
LOCAL_STATIC_LIBRARIES += freerdp-locale
LOCAL_STATIC_LIBRARIES += freerdp-crypto
LOCAL_STATIC_LIBRARIES += freerdp-sspi
LOCAL_STATIC_LIBRARIES += freerdp-codec
LOCAL_STATIC_LIBRARIES += freerdp-core
LOCAL_STATIC_LIBRARIES += freerdp-cache
LOCAL_STATIC_LIBRARIES += freerdp-gdi
LOCAL_STATIC_LIBRARIES += freerdp-rail
LOCAL_STATIC_LIBRARIES += freerdp-channels
LOCAL_STATIC_LIBRARIES += rdpsnd_alsa
LOCAL_STATIC_LIBRARIES += cliprdr
LOCAL_STATIC_LIBRARIES += rdpsnd
LOCAL_STATIC_LIBRARIES += freerdp_android
In the Java side, it looks like you should load the other libraries as well, in the appropriate order:
static {
System.loadLibrary("freerdp-utils");
System.loadLibrary("freerdp-codec");
System.loadLibrary("freerdp-gdi");
System.loadLibrary("freerdp-core");
System.loadLibrary("freerdp-rail");
System.loadLibrary("freerdp-chche");
System.loadLibrary("freerdp-crypto");
System.loadLibrary("freerdp-sspi");
System.loadLibrary("freerdp-channels");
System.loadLibrary("rdpsnd_alsa");
System.loadLibrary("cliprdr");
System.loadLibrary("rdpsnd");
System.loadLibrary("freerdp_android");
System.loadLibrary("freerdp");
}

javah jni generated header has syntax error - Android NDK - eclipse

Android NDK, I used the following command to generate the jni header,
C:\eclipse_workspace\C_Google_FaceDetect\bin>javah -jni -verbose -classpath C:\Android_SDK\platforms\android-10;C:\eclipse_workspace\C_Google_FaceDetect\src;. -d C:\eclipse_workspace\C_Google_FaceDetect\jni c.google.facedetect.FaceDetect
The problem is
even though I set everything well, I'm getting the following error
No implementation found for native Lc/google/facedetect/FaceDetect;.decodeYUV([I[BII)V
threadid=1:thread exiting with uncaught exception (group=0x40018578)
FATAL EXCEPTION: main java.lang.UnsatisfiedLinkError: decodeYUV
I tried looking for what's wrong, and I found that in the c_google_facedetect_FaceDetect.h jni header file, I have a syntax error actually (even though it's generated)
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h> /* Header for class c_google_facedetect_FaceDetect */
#ifndef _Included_c_google_facedetect_FaceDetect
#define _Included_c_google_facedetect_FaceDetect
#ifdef __cplusplus extern "C" {
#endif
#undef c_google_facedetect_FaceDetect_CAMERA_WIDTH
#define c_google_facedetect_FaceDetect_CAMERA_WIDTH 480L
#undef c_google_facedetect_FaceDetect_CAMERA_HEIGHT
#define c_google_facedetect_FaceDetect_CAMERA_HEIGHT 320L
/*
* Class: c_google_facedetect_FaceDetect
* Method: decodeYUV
* Signature: ([I[BII)V
*/
JNIEXPORT void JNICALL Java_c_google_facedetect_FaceDetect_decodeYUV(JNIEnv *, jobject, jintArray, jbyteArray, jint, jint);
#ifdef __cplusplus }
#endif
#endif
The "JNIEXPORT void JNICALL ...." line has a syntax error, maybe that's what causing all the errors ?
My Android.mk file is as follows:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := face-detect
LOCAL_SRC_FILES := face-detect.c
include $(BUILD_SHARED_LIBRARY)
UPDATE
My one and only java file is called FaceDetect.java and includes the following code
public class FaceDetect extends Activity implements SurfaceHolder.Callback, Camera.PreviewCallback
{
static
{
Log.d("mytag", "before_lib");
System.loadLibrary("face-detect");
Log.d("mytag", "after_lib");
}
public static native void decodeYUV(int[] out, byte[] fg, int width, int height);
}
Also, Eclipse doesn't say what the syntax error is, it only underlines the JNIExport line and says syntax error
Another UPDATE to answer the question
I have indeed checked that the library is being loaded, here is the logcat
07-16 13:31:43.257: D/mytag(25188): before_lib
07-16 13:31:43.281: D/dalvikvm(25188): Trying to load lib /data/data/c.google.facedetect/lib/libface-detect.so 0x40517808
07-16 13:31:43.281: D/dalvikvm(25188): Added shared lib /data/data/c.google.facedetect/lib/libface-detect.so 0x40517808
07-16 13:31:43.281: D/dalvikvm(25188): No JNI_OnLoad found in /data/data/c.google.facedetect/lib/libface-detect.so 0x40517808, skipping init
07-16 13:31:43.281: D/mytag(25188): after_lib
There is no syntax error. Check that you are loading your native library and that it has loaded successfuly.

Categories

Resources