近期在学习so相关的编程,发现每次写了新方法之后,还需要到相对应的java文件目录下执行一些java脚本,帮助我们生成在jni中会用到的一些C++的头文件。后来觉得每次这么写太麻烦,有没有简单点的处理办法呢,后来发现AndroidStudio有一个叫External Tools的东西,可以帮助我们实现。

    1.首先,如果想要学习NDK的话,那么相关的NDK的环境肯定要先配置好的。如果你已经配置好的话,那么项目框架下的ndk-bundle会显示出来,如果没有,也没关系,AS提供有自动下载的功能,就在显示路径的地方,到时候点击就可以下载了。

 




android gradle拉取代码 android gradle exclude_androidStudio


 

2.其次,我们先在自己的工程目录的main目录下创建一个名为jni的目录,用于存放我们的C++代码。

android gradle拉取代码 android gradle exclude_NDK_02

3.声明我们将要写在C++中的方法,这个方法将输出一个hello world。

android gradle拉取代码 android gradle exclude_Android_03

4.接下来,本来我们的工作是进入到MyJni.java的目录下执行javah的命令,现在我们使用另外一种方法实现,配置External Tools。

android gradle拉取代码 android gradle exclude_NDK_04

5.配置完了javah,那么我们接下来配置ndk相关的东西。

首先配置一下ndk build clean 命令

android gradle拉取代码 android gradle exclude_JNI_05

然后配置ndk-bundle的命令

android gradle拉取代码 android gradle exclude_JNI_06

最终的结果就是我们的External Tools会多出三个选项,如下图所示

android gradle拉取代码 android gradle exclude_JNI_07

 

6.配置了一大堆,怎么用呢?这是个问题,现在我们来看一下重点,用法:右键我们的MyJni.java这个文件会出下如下选项:

android gradle拉取代码 android gradle exclude_androidStudio_08

点击之前首先要Make project一下,然后再javah,如果之前路径都没问题的话,那么会显示:

[Creating file RegularFileObject[com_example_administrator_myapplication2_MyJni.h]]

Process finished with exit code 0

代表已经生成头文件,在你的moudle/src/main/jni路径下

7.之后我们来写两个文件Android.mk和Application.mk

Application.mk(最新版本的NDK需要新增APP_PLATFORM,且已经不支持armeabi

APP_MODULES := JniTest
APP_ABI := armeabi-v7a
APP_PLATFORM := android-16

文件中的JniTest就是我们生成so的名字,armeabi-v7a就是我们要编译出来api的版本,可以有多个。

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := JniTest
LOCAL_SRC_FILES =: main.cpp
include $(BUILD_SHARED_LIBRARY)

文件中的main.cpp就是我们创建的实现头文件的C++源码:

//
// Created by Administrator on 2018/7/15.
//

#include "com_example_administrator_myapplication2_MyJni.h"

/*
 * Class:     com_example_administrator_myapplication2_MyJni
 * Method:    sayHello
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_administrator_myapplication2_MyJni_sayHello
  (JNIEnv *env, jclass jobj) {
    return (*env).NewStringUTF("hello world");
  }

很简单的实现,分为两部,第一引入头文件,第二返回一个hello world字符串。

8.写好了之后我们就可以开始编译so,来到最后一步了是不是很开心?

android gradle拉取代码 android gradle exclude_Android_09

执行完ndk-build命令之后,so文件已经在我们项目中生成了

android gradle拉取代码 android gradle exclude_Android_10

9.调用so方法,终于到最后了,也是最简单的一步。

android gradle拉取代码 android gradle exclude_androidStudio_11

然后就可以看到日志,打印了,赶快运行一下吧。

 

Tips:学习的过程中也遇到了困难,给大家分享下
1.mac的情况下D:\AndroidStudio\ndk-bundle\ndk-build.cmd最后的.cmd是不需要的

2.在配置External Tools的过程中,双$符号内的都是变量,可以通过后面的Insert Macros查找添加,手动写貌似没用

3.在使用javah是报了一个Exception in thread "main" java.lang.IllegalArgumentException: Not a valid class name: Files\Android\Android,看了下是路径中含有了空格,去掉就Ok。

谢谢大家