Android Studio NDK无法加载库

时间:2014-08-20 04:13:12

标签: android android-ndk

我在src / main中创建了JNI文件夹,并使用javah成功生成了c头文件。然后我实现如下:

#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 !");
}

我的Android.mk文件是:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := kxz_encoder
LOCAL_SRC_FILES := kxz_encoder.c
include $(BUILD_SHARED_LIBRARY)

运行ndk-build后,在libs / armeabi

中生成.so文件

另外,我在活动中添加了以下几行。

static {
    System.loadLibrary("kxz_encoder");
}

在Kitkat上运行此应用程序时出现以下错误:

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)

我检查了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);
    }

似乎在第三行中,filename为null。谁能帮我解决这个问题? 谢谢!

4 个答案:

答案 0 :(得分:1)

当前版本的android studio不提供NDK支持。你可以参考以下链接。 https://developer.android.com/sdk/installing/studio.html

答案 1 :(得分:0)

我认为你不能。截至目前,Android工作室不支持/包含NDK。你不能写&amp;测试jni代码。相反,您可以使用so文件(如果已经构建)

答案 2 :(得分:0)

您需要在JNI文件夹中创建另一个虚拟C文件。目前不支持NDK,但有一种解决方法可以将NDK与Android Studio配合使用。在JNI文件夹中创建另一个C文件,并将C文件留空。此外,您的所有.mk文件都会被忽略。您可以通过停用默认的NDK集成使Android Studio / gradle重用它们,让它自己调用ndk-build(.cmd),并使用标准的libs / location来集成.so文件:

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

详情请参阅此视频教程https://www.youtube.com/watch?v=okLKfxfbz40

答案 3 :(得分:0)