AndroidStudio2.2 中 对于 ndk/jni 建议使用 cmake 进行编译 而对于纯粹的 android 程序员来说,cmake 不是经常接触的方案,我在遇到 jni 相关时也遇到了一些问题,这里抛砖引玉吧

开发环境

Android SDK/NDK Android Studio 2.2 图片 友情提示:更新请科学上网

准备工作

其实 demo 永远是最好的老师 我们直接自己创建一个 Project 图片 好在 AS 对于对于 ndk 的支持越来越友好 选中 c++支持,这样创建出来的 gradle 文件就会自动创建相关的,有助于我们学习

自动生成的核心文件

build.gradle MainActivity.java native-lib.cpp CMakelists.txt

MainActivity.java

MainActivity.java

    System.loadLibrary("native-lib"); //加载native-lib库
    ...
    public native String stringFromJNI();//指向cpp文件中的方法

图片 左边有一个箭头,这个点击可以直接跳到 cpp 文件中的方法

gradle

project 级别的和传统没有差别 看 module 级的

apply plugin: 'com.android.application'

android {
    ...
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
    }
   ...
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }


    ndk{
        abiFilters 'armeabi' //打包的cpu方案
    }
}

dependencies {
   ...
}

看到核心差别就是这几句 cppFlags 先不去管 这里有一个path "CMakeLists.txt" 这个指向了一个 txt 文件 打开这个文件

CmakeLists.txt

总体语法是 #为单行注释

指定最低版本号 添加库文件 找到指定的库 连接目标库


通过观察这里有 native-lib 的地方就是指定的几处

创建自己的 library

接下来模仿这个语法来写个自己的库 在 cpp 文件夹下,添加一个 math-lib.cpp math-lib.h

接着修改 cmake

...

cmake_minimum_required(VERSION 3.4.1)#最低版本号

...

add_library( ...
             native-lib  #库的名称

            ...
             SHARED  #是否设置为共享库

            ...
             src/main/cpp/native-lib.cpp #库文件的指向
             )

add_library(#这里是我自定义的demo库
            math-lib
            SHARED
            src/main/cpp/math-lib.cpp
            src/main/cpp/math-lib.h
            )
...

find_library( # Sets the name of the path variable.
              log-lib
...
              log )

...

target_link_libraries( # Specifies the target library.
                        native-lib
                        math-lib
                      ...
                       ${log-lib} )

在 native-lib 的位置填写自己的 library 名称,和文件位置 接着在 MainActivity 中写一个 native 方法 private native int add(int a,int b);

在静态代码块中 加载库 库的名称是 math-lib

static{
    System.loadLibrary("math-lib");
}

修改 cpp 文件

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

//
// Created by kikt on 2016/10/21.
//

#include "math-lib.h"
extern "C"
JNIEXPORT jint JNICALL
Java_com_kikt_ndkdemo1_MainActivity_add(JNIEnv *env, jobject instance, jint a, jint b) {
    return a+b;
}

这里比较简单,返回 a+b 的返回值就可以了

不会写 JNI 的 c 方法名的朋友,AS 现在已经可以通过提示自动生成的,好方便!

当然我们还是需要知道下如何自己生成,万一哪天 AS 抽风了呢 这里推荐一个我很久前看到的 blog使用 Javah 生成 C/C++头文件的误区

这里有一个特别要注意的地方,因为这个是 cpp 文件 和 c 文件不同的是 必须加上 extern “C” 防止编译器将方法改名,否则会造成 natvie 方法调用不到,抛出异常

后记

会写这个文章是因为头一阵研究视频编解码的时候引入了一个第三方库GPUImage的时候遇到了编译不通过,无奈换回 AS2.1 的问题正常编译运行的问题

因为 AndroidStudio 2.2 正式版刚刚开放加载一段时间,有一些朋友在 ndk 开发时可能会遇到各种问题,这里仅做一个入门的参考 欢迎留言交流