Android:随笔——新的 NDK/JNI 调用方式

转载请标明地址 QuincySx: http://www.jianshu.com/p/c6108131ba0f

众所周知现在 Android 开发已经到了 Android Studio 的时代,那么 JNI 的调用方式也经过了好几代

  1. 在eclipse 时代就存在的 ndk-build 方式
  1. 使用 Google 官方的 com.android.tools.build:gradle-experimental 简书地址
  2. CMake 方式,支持断点调试,这也是今天要说的是一种方式

使用 CMake 这种方式有几个条件

  1. Android Studio 2.2 或更高版本
  1. Android Plugin for Gradle 版本 2.2.0 或更高版本

好了下面需要下点必要工具 下载 NDK 和构建工具 要为您的应用编译和调试原生代码,您需要以下组件:
Android 原生开发工具包 (NDK):这套工具集允许您为 Android 使用 C 和 C++ 代码,并提供众多平台库,让您可以管理原生 Activity 和访问物理设备组件,例如传感器和触摸输入。
CMake:一款外部构建工具,可与 Gradle 搭配使用来构建原生库。如果您只计划使用 ndk-build,则不需要此组件。
LLDB:一种调试程序,Android Studio 使用它来调试原生代码。

Android:随笔——新的 NDK/JNI 调用方式
Paste_Image.png

如图显示的三个 就是需要下载的三个

使用 CMake 有两种方式

  1. 第一种方式 是在项目创建的时候
  1. 第二种是在现有项目上添加

第一种方式

我们先介绍第一种方式 : 是建立新项目的时候

Android:随笔——新的 NDK/JNI 调用方式
创建项目

复选 include C++ support 然后和正常项目一样一直 Next 下一步

Android:随笔——新的 NDK/JNI 调用方式
配置项目
  • C++ Standard:使用下拉列表选择您希望使用哪种 C++ 标准。选择 Toolchain Default 会使用默认的 CMake 设置。
  • Exceptions Support:如果您希望启用对 C++ 异常处理的支持,请选中此复选框。如果启用此复选框,Android Studio 会将 -fexceptions 标志添加到模块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。
  • Runtime Type Information Support:如果您希望支持 RTTI,请选中此复选框。如果启用此复选框,Android Studio 会将 -frtti 标志添加到模块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。

根据自己情况选取 饭后点击 Finish

在这种情况下 如果没有安装 CMake Android Studio 会提示安装

Android:随笔——新的 NDK/JNI 调用方式

这是项目结构


Android:随笔——新的 NDK/JNI 调用方式
项目结构

第二种方式

第二种方式是 : 在原有想的基础上添加

这种方式有三个步骤

  • 创建新的原生源文件并将其添加到您的 Android Studio 项目中。如果您已经拥有原生代码或想要导入预构建的原生库,则可以跳过此步骤。
  • 创建 CMake 构建脚本将您的原生源代码构建到库中。如果导入和关联预构建库或平台库,您也需要此构建脚本。如果您的现有原生库已经拥有CMakeLists.txt构建脚本或者使用 ndk-build 并包含Android.mk构建脚本,则可以跳过此步骤。
  • 提供一个指向您的 CMake 或 ndk-build 脚本文件的路径,将 Gradle 关联到您的原生库。Gradle 使用构建脚本将源代码导入您的 Android Studio 项目并将原生库(SO 文件)打包到 APK 中。

首先在自己的模块下新建 JNI 目录

Android:随笔——新的 NDK/JNI 调用方式
Paste_Image.png

然后切换显示模式为 project 在 src > main 下会出现一个 jni 的目录 创建c文件 名字随意

Android:随笔——新的 NDK/JNI 调用方式

然后在新建的文件夹下创建 C 的文件

Android:随笔——新的 NDK/JNI 调用方式

如果需要头文件 则需要勾选 Create an associated header

然后创建 CMakeLists.txt 文件 在模块根目录下创建(名字一定要是 CMakeLists.txt)

然后我们需要在文件中添加 cmake_minimum_required() 与 add_library() 两个方法

#指定 CMake 的最小版本
cmake_minimum_required(VERSION 3.4.1)

add_library( 
             #模块名 
             native

             #设置模块是可共享的
             SHARED

             #C 文件的具体路径 注意确认文件名后缀
             src/main/jni/native.cpp )

# 指定头文件路径 这里我没有创建 头文件先注释掉
# include_directories(src/main/jni/)

然后关联 CMake 与 Gradle

自动的方式
Android:随笔——新的 NDK/JNI 调用方式
Paste_Image.png
Android:随笔——新的 NDK/JNI 调用方式

选择我们创建的 CMakeLists.txt 文件 点击完成等待

手动方式
android {
  ...
  defaultConfig {...}
  buildTypes {...}

  // Encapsulates your external native build configurations.
  externalNativeBuild {
    // Encapsulates your CMake build configurations.
    cmake {
      // Provides a relative path to your CMake build script.
      path "CMakeLists.txt"
    }
  }
}

然后在 JAVA 中调用

在 Java 代码中 调用的时候 添加 这里的名字一定要和上面一致

static {
        System.loadLibrary("native");
    }

private native String getStr();

然后在书写一下 C 文件 (这里我创建的是 C++ 文件)

#include <jni.h>

JNIEXPORT jstring JNICALL
Java_com_a21vianet_quincysx_demo_jnidemo_MainActivity_getStr(JNIEnv *env, jclass type) {
    char str[] = "我是C";
    return (*env).NewStringUTF(str);
}

总结

这只是最简单的一个 小例子,我水平不高也在学习,深入学习后会有更多的文章分享给大家

水平问题,难免会有错误,多谢各位指正

参考资料


上一篇:【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 三 | 等待远程函数执行完毕 | 寄存器获取返回值 )


下一篇:C++中一些特殊函数的使用