You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Android中使用NDK?及转换com.android.model.application至com.android.application

1. 如何在Android中使用NDK?

在Android里用NDK主要是为了编写C/C++代码并编译成原生库供Java/Kotlin调用,下面是完整的实操步骤:

  • 第一步:搞定环境准备
    打开Android Studio的SDK Manager,切换到「SDK Tools」标签,勾选NDK (Side by side)CMake,点击应用完成安装。安装后Android Studio会自动配置NDK路径,你也可以手动在项目根目录的local.properties里指定:ndk.dir=/你的NDK安装路径

  • 第二步:创建JNI相关文件
    在项目的src/main目录下新建jni文件夹,把你的C/C源码(比如Test_Jni.c)和必要的头文件放进去。如果有外部的C/C文件,也可以放在这里或者后续在Gradle里指定其他路径。

  • 第三步:配置Gradle
    如果你用的是新版的com.android.application插件(也就是你要转换的目标),可以直接在模块级build.gradle里配置NDK参数,具体可以参考第二个问题的配置示例。要是需要更灵活的编译控制,也可以用CMakeLists.txt来管理,简单场景下直接Gradle配置就足够。

  • 第四步:编写JNI接口
    在Java类里声明native方法,比如:

    public class JniUtils {
        static {
            System.loadLibrary("Test_Jni"); // 这里的名字要和Gradle里的moduleName一致
        }
        public native String getNativeString();
    }
    

    之后可以用javah命令,或者Android Studio的「Generate JNI Headers」功能生成对应的头文件,再在C/C++文件里实现这个native方法。

  • 第五步:编译运行
    点击Android Studio的「Make Project」按钮,Gradle会自动编译C/C++代码生成.so库并打包进APK。运行App后就能调用native方法啦。


2. 转换com.android.model.applicationcom.android.application并解决CFlags.add问题

旧的com.android.model.application是Android Experimental插件的用法,现在已经被官方的com.android.application取代了,两者的配置语法差异不小,尤其是NDK部分。针对你的Gradle代码,修改后的版本如下,我会逐点说明改动:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    buildToolsVersion '27.0.0'

    defaultConfig {
        applicationId "com.update.myapp"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0.2"
        multiDexEnabled true

        // NDK核心配置移到defaultConfig的ndk块里
        ndk {
            moduleName "Test_Jni"
            ldLibs "log" // 直接指定需要链接的系统库
        }

        // C编译选项和头文件路径放在externalNativeBuild的ndkBuild块中
        externalNativeBuild {
            ndkBuild {
                // 替换原来的CFlags.add,直接用逗号分隔多个编译宏
                cFlags "-DCOMPANION_DEVICE", "-DDISABLE_LOGS"
                // 通过arguments传递头文件路径参数,对应原来的CFlags.addAll里的-I选项
                arguments "-I${file("src/main/jni/Folder1/")}".toString(),
                          "-I${file("src/main/jni/Folder2")}".toString(),
                          "-I${file("C:\\Program Files (x86)\\MyFile\\folder1_Cfiles/")}".toString(),
                          "-I${file("C:\\Program Files (x86)\\MyFile\\folder2_Cfiles/")}".toString()
            }
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    // 指定JNI源码的目录,替换原来的sources配置
    sourceSets {
        main {
            jni.srcDirs = [
                "src/main/jni",
                "C:\\Program Files (x86)\\MyFile\\folder1_Cfiles",
                "C:\\Program Files (x86)\\MyFile\\folder2_Cfiles"
            ]
        }
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:27.0.2'
    implementation 'com.android.support:multidex:1.0.3' // 开启multiDex后建议添加这个依赖,避免运行时崩溃
}

关键改动点说明:

  • 替换插件:把com.android.model.application换成官方标准的com.android.application
  • 移除model块:所有配置直接放在android块下,不再嵌套层级。
  • NDK配置迁移:原来android.ndk里的moduleNameldLibs移到defaultConfig.ndk块中。
  • CFlags语法调整:原来的CFlags.add换成externalNativeBuild.ndkBuild.cFlags,多个编译宏用逗号分隔;头文件路径通过arguments传递,对应原来的-I参数。
  • 源码路径配置:原来的android.sources.main.jni.source.srcDirs改成sourceSets.main.jni.srcDirs,用赋值方式指定多个目录。
  • 依赖更新:把旧的compile换成Gradle推荐的implementation;另外加上multidex依赖,因为你开启了multiDexEnabled,防止运行时出现类找不到的问题。

这样修改后,Gradle就能正确识别你的NDK配置,解决原来CFlags.add的语法问题了。

内容的提问来源于stack exchange,提问作者Anass Hb

火山引擎 最新活动