Android Studio - 找不到 native 方法 - 在构建中包含 .so 文件

标签 android android-ndk android-gradle-plugin

我刚开始使用 NDK,想用它编译我的第一个 hello-world 应用。

我的应用程序只是一个带有 Activity 的简单应用程序,我的 MainActivity 在 com.example.myapplication2.app 中

我想在其中使用本地方法,这是我所做的:

主 Activity .java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        TextView  tv = new TextView(this);
        tv.setText(stringFromJNI());
        setContentView(tv);
    }

    public native String  stringFromJNI();

    static {
        System.loadLibrary("hello-jni");
    }

在我的 jni 文件夹中:

安卓.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)

应用程序.mk

APP_ABI := all

你好-jni.c

#include <string.h>
#include <jni.h>

JNIEXPORT jstring JNICALL   Java_com_example_myapplication2_app_MainActivity_stringFromJNI(JNIEnv* env, jobject  thiz)
{
    return (*env)->NewStringUTF(env, "Hello from native code!");
}

在这里,我的 gradle:

apply plugin: 'android'

android {
    compileSdkVersion 19
    buildToolsVersion "19.0.3"

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }

    sourceSets.main {
        jniLibs.srcDir 'src/main/libs'
        jni.srcDirs = [] //disable automatic ndk-build call
    }

    productFlavors {
        x86 {
            versionCode Integer.parseInt("6" + defaultConfig.versionCode)
            ndk {
                abiFilter "x86"
            }
        }
        mips {
            versionCode Integer.parseInt("4" + defaultConfig.versionCode)
            ndk {
                abiFilter "mips"
            }
        }
        armv7 {
            versionCode Integer.parseInt("2" + defaultConfig.versionCode)
            ndk {
                abiFilter "armeabi-v7a"
            }
        }
        arm {
            versionCode Integer.parseInt("1" + defaultConfig.versionCode)
            ndk {
                abiFilter "armeabi"
            }
        }
        fat
    }
}

def getVersionCodeFromManifest() {
    def manifestFile = file(android.sourceSets.main.manifest.srcFile)
    def pattern = Pattern.compile("versionCode=\"(\\d+)\"")
    def matcher = pattern.matcher(manifestFile.getText())
    matcher.find()
    return Integer.parseInt(matcher.group(1))
}

task copyNativeLibs(type: Copy, dependsOn: 'buildNative') {
    // TODO fix deprecated
    dependsOn 'buildNative'
    from(new File('src/main/libs')) { include '**/*.so' }
    into new File(buildDir, 'native-libs')
}

tasks.withType(Compile) { compileTask -> compileTask.dependsOn copyNativeLibs }

clean.dependsOn 'cleanCopyNativeLibs'

tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->
    pkgTask.jniFolders = new HashSet<File>();
    pkgTask.jniFolders.add(new File(projectDir, 'native-libs'))
}

task buildNative(type: Exec) {
    if (System.env.ANDROID_NDK != null) {
        def ndkBuild = new File(System.env.ANDROID_NDK, 'ndk-build')
        workingDir "src/main/jni"
        commandLine 'cmd', '/c', '%ANDROID_NDK%\\ndk-build'
        //executable ndkBuild
    } else {
        doLast {
            println '##################'
            println 'Skipping NDK build'
            println 'Reason: ANDROID_NDK not set.'
            println '##################'
        }
    }
}

task nativeLibsToJar(
        type: Zip,
        description: 'create a jar archive of the native libs') {
    destinationDir file("$buildDir/native-libs")
    baseName 'native-libs'
    extension 'jar'
    from fileTree(dir: 'libs', include: '**/*.so')
    into 'lib/'
}

dependencies {
    compile 'com.android.support:appcompat-v7:+'
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

当我想运行我的项目时,我没有出现 C 错误(我之前有过,这就是为什么我确定编译已完成,并且正常)。

但是,当我想运行该应用程序时,出现错误:

java.lang.UnsatisfiedLinkError: Native method not found: com.example.myapplication2.app.MainActivity.stringFromJNI:()Ljava/lang/String;

我检查过的是(Android NDK Native method not found error):

  • com.example.myapplication2.app.MainActivity.stringFromJNI 和 Java_com_example_myapplication2_app_MainActivity_stringFromJNI 匹配
  • extern "C"不存在,因为我在使用它时遇到了这个错误:Error: "expected '(' before string constant"

你知道我为什么会遇到这个错误吗?

最佳答案

System.loadLibrary("hello-jni") 调用添加到您的应用程序启动。静态构造函数将是一个好地方。

关于Android Studio - 找不到 native 方法 - 在构建中包含 .so 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22568705/

相关文章:

Android 市场 - 在没有蓝牙的情况下无法在特定设备上找到应用程序

java - FloatingActionButton黑框

c++ - Opencv 过滤器导致图像上出现黑色衬里

c++ - 我的预制件不包含二进制文件或包含

android - 如何在 Android 应用程序中打开设备节点 (/dev/hidraw0)(通过 C++)?

android - Gradle 错误 : Could not get unknown property 'project' for ProductFlavor_Decorated

android - 在没有 Gradle 的情况下从 Eclipse 迁移到 Android Studio

java - Android 中的 TextView 的字符串不像以前在自定义适配器中那样显示

android - 旧项目与新项目的编译不一样。 (奇怪的行为/崩溃)

android - Gradle 排除 arm64 库