使用MAC OS X将hello-neon(ndk示例)导入Android Studio



我是NDK、gradle和Android Studio(AS)的新手,在将hello-neon(NDK示例)导入AS时遇到了一些问题。我的操作系统是MAC OS X Yosemite。

local.properties中设置了ndk.dirsdk.dir,并将android.useDeprecatedNdk=true写入gradle.properties之后,我仍然无法制作此程序,因为我在helloneon.c中找不到cpu-features.h

我找了几种方法。唯一有效的方法是添加

sourceSets.main {
    jni.srcDirs = []
}

至CCD_ 8。

之后,我们可以制作项目并将其安装在安卓虚拟机上。但是,当我打开应用程序时,它会崩溃。为了找到原因,我发现HelloNeon.javapublic native String stringFromJNI()无法链接到helloneon.c的实现。("无法解析相应的Jni函数")

仍然按照stackoverflow提供的说明,我使用ndk构建来构建源代码(需要添加指向cpufeatures的环境变量),并将.so文件添加到该项目中,比如我的项目结构的屏幕截图

这样做(添加.so文件)后,在HelloNeon.java的stringFromJNI中仍然说"无法解析相应的Jni函数"。但它可以是"制作项目",可以在我的虚拟机上成功运行

我不知道这是否是一个好的解决方案,因为即使可以编译,AS仍然会在HelloNeon.java报告错误

然后我尝试在build.gradle 中添加以下句子

sourceSets.main {
    jniLibs.srcDir 'src/main/jinLibs' 
}

它不会改变任何事情。(这些代码可以删除。--通过bullsy)

我还尝试将cpu-features.hcpu-features.c复制到/main/jni,然后我们可以找到cpu-features.h,但错过了其他文件。

因此,我来到这里寻求帮助。你能帮我们指出我们犯的错误以及解决错误的正确方法吗?尽管这对该领域的专家来说是一个幼稚的问题,但我真的很感激你作为一个新人在该领域的帮助。

非常感谢!


这是我的build.gradle(模块:应用程序):

apply plugin: 'com.android.application'
android {
    compileSdkVersion 21
    buildToolsVersion "23.0.3"
    defaultConfig {
        applicationId "com.example.neon"
        minSdkVersion 4
        targetSdkVersion 4
        ndk {
            moduleName "helloneon"
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
    sourceSets.main {
        jni.srcDirs = []
    }
    sourceSets.main {
        jniLibs.srcDir 'src/main/jinLibs' // <-- Set your folder here!
    }
}

这是我的另一个build.gradle(项目:你好霓虹灯):

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.5.0'
    }
}
allprojects {
    repositories {
        jcenter()
    }
}

这是我的settings.gradle:

include ':app'
include ':cpufeatures'

我的Android Studio版本是1.5.1

我的ndk版本(./ndk-build -version)是GNU Make 3.81

再次感谢。


更新

谢谢你。我在build.gradle中添加了以下代码:

task ndkBuild(type: Exec) {
    commandLine 'ndk-build', '-C', commandLine 'ndk-build', '-C', file('/Users/zhu/AndroidStudioProjects/hello-neon/app/src/main')
}
tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn ndkBuild
}

并在ndk-build:中获取了"制作项目"时的一些错误信息

Information:Gradle tasks [:app:generateDebugSources, :app:generateDebugAndroidTestSources, :app:compileDebugSources, :app:compileDebugAndroidTestSources]
:app:preBuild UP-TO-DATE
:app:preDebugBuild UP-TO-DATE
:app:checkDebugManifest
:app:prepareDebugDependencies
:app:compileDebugAidl UP-TO-DATE
:app:compileDebugRenderscript UP-TO-DATE
:app:generateDebugBuildConfig UP-TO-DATE
:app:generateDebugAssets UP-TO-DATE
:app:mergeDebugAssets UP-TO-DATE
:app:generateDebugResValues UP-TO-DATE
:app:generateDebugResources UP-TO-DATE
:app:mergeDebugResources UP-TO-DATE
:app:processDebugManifest UP-TO-DATE
:app:processDebugResources UP-TO-DATE
:app:generateDebugSources UP-TO-DATE
:app:preDebugAndroidTestBuild UP-TO-DATE
:app:prepareDebugAndroidTestDependencies
:app:compileDebugAndroidTestAidl UP-TO-DATE
:app:processDebugAndroidTestManifest UP-TO-DATE
:app:compileDebugAndroidTestRenderscript UP-TO-DATE
:app:generateDebugAndroidTestBuildConfig UP-TO-DATE
:app:generateDebugAndroidTestAssets UP-TO-DATE
:app:mergeDebugAndroidTestAssets UP-TO-DATE
:app:generateDebugAndroidTestResValues UP-TO-DATE
:app:generateDebugAndroidTestResources UP-TO-DATE
:app:mergeDebugAndroidTestResources UP-TO-DATE
:app:processDebugAndroidTestResources UP-TO-DATE
:app:generateDebugAndroidTestSources UP-TO-DATE
:app:ndkBuild
make: *** /Users/zhu/AndroidStudioProjects/hello-neon/app/main: No such file or directory.  Stop.
Error:Execution failed for task ':app:ndkBuild'.
> Process 'command 'ndk-build'' finished with non-zero exit value 2
Information:BUILD FAILED

然后我使用/Applications/Android Studio.app/Contents/MacOS/studio启动AS,这样AS就可以从bash中读取环境变量,这些代码就可以工作了!

但是,这个.so文件将存储在"/Users/zhu/AndroidStudioProjects/hello-neon/app/src/main/libs"中,并且这些.so文件无法直接加载(看起来项目只会在jniLibs/中加载.so文件)。

因此,我应该添加吗

sourceSets.main {
    jniLibs.srcDir 'src/main/libs' 
}

如果没有,我该怎么办?

删除此代码:

sourceSets.main {
    jniLibs.srcDir 'src/main/jinLibs' // <-- Set your folder here!
}

因为您使用的是Android.mk,所以将jniLibs.srcDir设置为空是正确的。这告诉构建系统不要覆盖你的Android.mk文件。为了正确构建,您需要从build.gradle调用ndk-build,并将其指向jni目录。设置对ndk-build的调用可能如下所示:

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

这些示例摘自ph0b关于使用旧版本NDK的优秀教程。如果你有兴趣在未来的某个时候,当你稍微舒服一点的时候,尝试实验性的NDK支持,ph0b也发布了一些很棒的东西。

最新更新