Reputation: 29
I have created JNI folder inside src/main and successfully generate c header file with javah. Then I implemented it as following:
#include <jni.h>
#include <string.h>
JNIEXPORT jstring JNICALL Java_com_kxiaozao_kxz_KXZSDK_KXZSDKInterface_encode (JNIEnv *env, jobject thisz, jstring jsonString) {
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
and my Android.mk file is:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := kxz_encoder
LOCAL_SRC_FILES := kxz_encoder.c
include $(BUILD_SHARED_LIBRARY)
After running ndk-build, .so file is generated inside libs/armeabi
In addition, I have add the following lines inside my activity.
static {
System.loadLibrary("kxz_encoder");
}
This application crash when running on Kitkat with following error:
java.lang.UnsatisfiedLinkError: Couldn't load kxz_encoder from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.kxiaozao.kxz-2.apk"],nativeLibraryDirectories=[/data/app-lib/com.kxiaozao.kxz-2, /vendor/lib, /system/lib]]]: findLibrary returned null
at java.lang.Runtime.loadLibrary(Runtime.java:358)
at java.lang.System.loadLibrary(System.java:526)
at com.kxiaozao.kxz.KXZFrontEnd.ViewController.KXZRecommendationVC.<clinit>(KXZRecommendationVC.java:258)
at java.lang.reflect.Constructor.newInstance(Native Method)
at java.lang.Class.newInstance(Class.java:1559)
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.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
I have checked the function that error occurs which is inside Runtime.java
void loadLibrary(String libraryName, ClassLoader loader) {
if (loader != null) {
String filename = loader.findLibrary(libraryName);
if (filename == null) {
throw new UnsatisfiedLinkError("Couldn't load " + libraryName +
" from loader " + loader +
": findLibrary returned null");
}
String error = doLoad(filename, loader);
if (error != null) {
throw new UnsatisfiedLinkError(error);
}
return;
}
String filename = System.mapLibraryName(libraryName);
List<String> candidates = new ArrayList<String>();
String lastError = null;
for (String directory : mLibPaths) {
String candidate = directory + filename;
candidates.add(candidate);
if (IoUtils.canOpenReadOnly(candidate)) {
String error = doLoad(candidate, loader);
if (error == null) {
return; // We successfully loaded the library. Job done.
}
lastError = error;
}
}
if (lastError != null) {
throw new UnsatisfiedLinkError(lastError);
}
throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates);
}
It seems that in the third line, filename is null. Could anyone help me solve this problem? Thanks!
Upvotes: 1
Views: 4374
Reputation: 889
I think that you can't. Android studio doesn't support/include NDK as of now. You can't write & test jni code. Instead, you can use so file (if already built)
Upvotes: 0
Reputation: 131
you can take help from this two links :
https://www.youtube.com/watch?v=kFtxo7rr2HQ http://ph0b.com/android-studio-gradle-and-ndk-integration/
Upvotes: 0
Reputation: 1031
You need to create another dummy C file within the JNI folder. NDK is not currently supported, but there is a workaround to use NDK with Android Studio. Create another C file within the JNI folder and leave it the C file empty. Also all your .mk files are ignored.. You can make Android Studio/gradle reuse them by deactivating the default NDK integration, make it call ndk-build(.cmd) by itself, and use standard libs/ location for integrating .so files:
import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'android'
android {
compileSdkVersion 19
buildToolsVersion "19.0.3"
defaultConfig{
minSdkVersion 15
targetSdkVersion 19
versionCode 101
versionName "1.0.1"
}
sourceSets.main {
jniLibs.srcDir 'src/main/libs'
jni.srcDirs = [] //disable automatic ndk-build call
}
// call regular ndk-build(.cmd) script from app directory
task ndkBuild(type: Exec) {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine 'ndk-build.cmd', '-C', file('src/main').absolutePath
} else {
commandLine 'ndk-build', '-C', file('src/main').absolutePath
}
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
}
For detailed walk through follow this video tutorial https://www.youtube.com/watch?v=okLKfxfbz40
Upvotes: 0
Reputation: 4577
current version of android studio doesn't provide the NDK support. you can refer following link. https://developer.android.com/sdk/installing/studio.html
Upvotes: 1