1

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!

4 Answers 4

1

current version of android studio doesn't provide the NDK support. you can refer following link. https://developer.android.com/sdk/installing/studio.html

0

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

0

you can take help from this two links :

https://www.youtube.com/watch?v=kFtxo7rr2HQ http://ph0b.com/android-studio-gradle-and-ndk-integration/

0

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)

1
  • OMG THE SPELLING HURTS MY EYES Commented Nov 13, 2014 at 19:14

Not the answer you're looking for? Browse other questions tagged or ask your own question.