I am creating an Android library (.aar file) and I need to use JNI. (I am very well aware of Google's discouragement of using JNI/NDK if possible, but in this case, it's not possible).
I started with a standalone hello-jni example APP (to first learn JNI), with the following files:
HelloJni.java
public class HelloJni extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
tv.setText( stringFromJNI() );
setContentView(tv);
}
public native String stringFromJNI();
static {
System.loadLibrary("hello-jni");
}
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_ABI := all
hello-jni.c
#include <string.h>
#include <jni.h>
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI!");
}
The following builds fine as an app (apk) and I am able to run it on my device, which prints "Hello from JNI!" as expected.
Now, I did the same thing, but instead of an apk, I built a library project to produce an aar. I kept all the files the same except HelloJni.java, which I changed to the following:
HelloJni.java
public class HelloJni {
public native String stringFromJNI();
static {
System.loadLibrary("hello-jni");
}
}
The aar builds fine, but when I import the aar into a separate app project, and try to run it on my device, it crashes on app start and I get the following error logcat message:
com.test.sample.mysampleapplication E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: com.test.sample.mysampleapplication, PID: 20047 java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.test.sample.mysampleapplication-1/base.apk"],nativeLibraryDirectories=[/data/app/com.test.sample.mysampleapplication-1/lib/arm, /vendor/lib, /system/lib]]] couldn't find "libhello-jni.so" at java.lang.Runtime.loadLibrary(Runtime.java:366) at java.lang.System.loadLibrary(System.java:988) ...
What in the world is this "libhello-jni.so" file? And why do I need it? I was able to run this perfectly fine as an apk. But can anyone explain why it doesn't work when I make it into an aar, and import it to an app project to use it? Am I missing some additional steps needed to make it into a library (and use it)? Thanks!
EDIT:
This is how I imported my aar to my app. 1. Click "File" -> "New" -> "New Module". 2. Select "Import .JAR or .AAR Package" as module type. 3. Set my aar file as new module 4. And then open "File" -> "Project Structure" 5. In the "Dependencies" tab, add "Module dependency" and select my aar file If that's not a good way to import aar to my app, then also please let me know. Thank you!
Turns out I had to add some NDK config in my build.gradle file inside my AAR module directory.
build.gradle:
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
// This determines the .so filename
ndk {
moduleName "hello-jni"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Not having that added in build.gradle will produce an .so file that's defaulted to your project's name, in my case "libsample-aar.so". With that config above, the generated .so file will then be "libhello-jni.so".