1、官方推荐JNI构建方案

从Android studio 2.2 开始,Google推荐的JNI开发构建工具是CMake而不是NDK,参考官方文档:https://developer.android.com/studio/projects/add-native-code.html

CMake的编译配置参数参考一篇文章:https://www.jianshu.com/p/6332418b12b1

一个典型的使用CMake的Gradle配置如下:

 defaultConfig {
minSdkVersion 14 // 指定支持最低的API版本号,如果不指定就是支持所有的版本,这有可能导致某些高级语法函数不支持等
targetSdkVersion 23 // 指定目前API版本,这个是主要编译版本,推荐与compileSdkVersion版本保持一致
versionCode 1
versionName "1.0" externalNativeBuild { // 必要第(1)点,指定默认编译参数,cmake表示特指CMake工具链的参数
cmake {
cppFlags "-frtti -fexceptions" // 支持dynamic_cast与try等
abiFilters 'armeabi-v7a' // 指定编译架构
}
}
} buildTypes {
debug {
jniDebuggable true
}
} externalNativeBuild { // 必要第(2)点,指定CMake文件,也就是编译内容
cmake {
path "jni\\build\\android\\armeabi-v7a\\debug\\CMakeLists.txt"
}
}

Gradle编译的版本配置相关:https://www.jianshu.com/p/3645a7829502

但是,我们要求使用NDK-r9d,默认不携带CMake,会报错提示找不到make工具等。

关于Gradle插件NDK相关的用法,参考官方文档:http://tools.android.com/tech-docs/new-build-system/gradle-experimental

2、JNI构建过程

基本流程是:(1)在AS中配置好NDK路径;(2)创建Java工程,然后写一个Java类中声明Native方法;(3)编译一下Java类生成class;(4)用javah -d ../jni com.example.kuliuheng.myapplication.TestClass 就能自动生成native方法对应的C++头文件;(5)就在jni目录下去添加cpp文件或者c文件去实现;(6)如果用Gradle自动编译,那么在android.defaultConfig下添加一个ndk模块就可以了,写一个moduleName就行。

3、新的NDK工程构建方法

  上面描述的是AndroidStudio自带的NDK工程构建步骤,这里描述一种利用Experimental plugin 很方便地构建NDK工程的方法。在此之前,先搞清楚几个名词的关系:

3.1 Gradle 与 Android Plugin(for Gradle)

  首先来看下一个默认工程中这两者的关系:

  这两者什么关系呢?可以类比的理解为Gradle(包)是一个服务方,而AndroidPlugin是一个客户端,也叫作Gradle插件。这两个东东都是Android Studio自带默认就有的,可以说默认就是这两个在起作用。

<1> AndroidPlugin(Gradle插件)配置在AS工程的build.gradle中

<2> Gradle包配置在gradle-wrapper.properties 中

  当然也可以在工程设置中更改,指定为最新的或者自己下载好本地的Gradle包:

<3> AndroidPlugin(Gradle插件)的版本要求

  先看下官方文档对AndroidPlugin(for Gradle)的描述吧。可以看到这两者是有版本对应关系的:

Plugin version Required Gradle version
1.0.0 - 1.1.3 2.2.1 - 2.3
1.2.0 - 1.3.1 2.2.1 - 2.9
1.5.0 2.2.1 - 2.13
2.0.0 - 2.1.2 2.10 - 2.13
2.1.3 - 2.2.3 2.14.1+
2.3.0+ 3.3+

 3.2 Gradle 与 Gradle-Experimental plugin

  如果是用上面的两个东东来开发NDK呢,那就是前面所描述的那种比较复杂的JNI开发方法,还是比较麻烦的。这就引出了主角Gradle-Experimental plugin了,先看看官方文档的介绍。

其中,最开始的地方就给出了一个特别的说明:

CAVEAT: Note that this plugin is a preview of the plugin for feedback on performance and NDK integration.  The Gradle API for the new component model is not final, which means each plugin will only work with a specific version of Gradle.
Additionally, the DSL may also change.

  意思是说这个插件是为了预览体验性能和NDK集成开发的,它的API都不是最终版本,每一个版本的Gradle只能对应一个特定版本的插件。看看版本对应关系:

 Plugin Version  Gradle Version
 0.1.0  2.5
 0.2.0  2.5
 0.3.0-alpha3  2.6
 0.4.0  2.8
 0.6.0-alpha1  2.8
 0.6.0-alpha5  2.10
 0.7.0-alpha1  2.10 
 0.7.0  2.10
 0.7.3  2.14.1

  看官方文档上给的对应关系说明,好像是有点“跟不上进度”的样子,现在Gradle都到3.3版本了,这个插件才写了2.14.1的对应版本。不过,当配置好上图中的一个之后,AndroidStudio会自动提示升级,我这里自动升级到了Plugin 0.9.3 <--> Gradle 3.3

3.3 最重要的一节(怎么使用Gradle-Experimental plugin)

从传统的Android Gradle Plugin迁移到Experimental Plugin,需要進行一下的配置调整(下方的配置以Gradle Version为2.10的为例子,其他版本的配置类似)
.
├── app/
│ ├── app.iml
│ ├── build.gradle
│ └── src/
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew*
├── gradlew.bat
├── local.properties
├── MyApplication.iml
└── settings.gradle

  上方的目录视图显示了一个典型的AS项目的结构,这里一共有三个文件需要修改:

<1> gradle-wrapper.properties 配置Gradle版本

<2> 配置工程build.gradle

  这个时候不要急于的同步工程,一来是因为还没配置完,二来是使用了这个Experimental plugin之后很多语法会发生改变,所以还修改Gradle内部配置。此时同步工程会报错,说一些方法、包什么的找不到。

<3> 配置模块内部的build.gradle

  先给一个典型的配置吧,里面配置NDK的方法我看很实用,比如更改代码目录名、增加引用库关系等等都可以:

buildscript {
repositories {
jcenter()
}
dependencies {
// classpath 'com.android.tools.build:gradle:2.1.3'
classpath 'com.android.tools.build:gradle-experimental:0.8.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
apply plugin: 'com.android.model.application' model {
android {
compileSdkVersion =
buildToolsVersion = '23.0.3' defaultConfig {
applicationId "com.gala.uniplayer.androiddemotest"
minSdkVersion.apiLevel
targetSdkVersion.apiLevel
versionCode
versionName "1.0"
multiDexEnabled true
} buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file("proguard-rules.pro"))
}
} ndk {
platformVersion
moduleName "galauniplayersdkjni"
CFlags.add("")
cppFlags.addAll(["-std=c++11", "-frtti"])
cppFlags.addAll(['-I' + file('../../../../../uniplayersdk-pub/include/uniplayersdk'),
'-I' + file('../../../../../qyuniutil-pub/include'),
'-I' + file('src/main/cpp/include'),
]) abiFilters.add("armeabi")
CFlags.add("-DCUSTOM_DEFINE")
cppFlags.add("-DCUSTOM_DEFINE") File curDir = file('./')
curDir = file(curDir.absolutePath)
String libsDir = curDir.absolutePath + '/src/main/libs/armeabi'
String rootPath = curDir.absolutePath +"/../../../../../" ldFlags.add("-L" + libsDir)
ldFlags.add("-L" + rootPath+"qyuniutil-pub/libs/android/armeabi")
ldFlags.add("-L" + rootPath+"uniplayersdk-pub/libs/android/armeabi") ldLibs.add("mcto_media_player")
ldLibs.add("galauniutil")
ldLibs.add("galauniplayersdk") stl "gnustl_shared"
} sources {
main {
java {
source {
srcDir "src/main/java"
}
}
jni {
source {
srcDir "src/main/cpp"
}
}
jniLibs {
source {
srcDir "src/main/libs"
}
}
}
}
}
} dependencies {
compile fileTree(include: ['*.jar'], dir: 'src/main/libs')
compile files('src/main/libs/cupid_app_interface.jar')
compile files('src/main/libs/nativemediaplayersdk.jar')
compile files('src/main/libs/galauniplayersdk.jar')
// compile project(':uniplayer_lib')
} task copySoTask(type: Copy) {
from('../../../../../thirdparty-libs/libs/android/tvjson/shared/') {
include 'armeabi/*.so'
}
from('../../../../../thirdparty-libs/libs/android/puma_tv/shared/') {
include 'armeabi/*.so'
}
from('../../../../../thirdparty-libs/libs/android/puma_tv/jar/') {
include '*.jar'
}
from('../../../../../uniplayerdata-pub/libs/android/') {
include 'armeabi/*.so'
}
from('../../../../../uniplayersdk-pub/libs/android/') {
include 'armeabi/*.so'
}
from('../../../../../uniplayersdk-pub/libs/android/') {
include 'galauniplayersdk.jar'
}
from('../../../../../qyuniutil-pub/libs/android/') {
include 'armeabi/*.so'
}
into 'src/main/libs'
} tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn copySoTask
}

  使用了这个插件之后带来语法上的变化主要有以下几点:

  1. Plugin name is com.android.model.application instead of com.android.application. Or use apply plugin: “com.android.model.library” if you want to create an Android aar library. 
    使用com.android.model.application代替com.android.application;  使用com.android.model.library代替com.android.library
  2. Configuration is wrapped with the model { } block 
    所有的配置需要使用model{}包含起来
  3. Adding elements to a Collection should be done using the add method. 
    向集合添加元素时,需要使用add方法

  上图是官方文档给出来的需要变更语法的地方。

<4> 官方文档很重要

  好多NDK配置特性都能找到:http://tools.android.com/tech-docs/new-build-system/gradle-experimental

  一个歪果大牛写的入门Blog:https://ph0b.com/new-android-studio-ndk-support/

4、JNI类型映射

Java 类型                    

符号

Boolean

Z

Byte

B

Char

C

Short

S

Int

I

Long

J

Float

F

Double

D

Void

V

objects对象

以"L"开头,以";"结尾,中间是用"/" 隔开的包及类名。比如:Ljava/lang/String;如果是嵌套类,则用$来表示嵌套。例如 "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z"

[Android] AndroidStudio + JNI(NDK)开发相关总结的更多相关文章

  1. Android学Jni/Ndk 开发记录(一)

      治疗拖延症的唯一办法就是:一想起些什么 / 要做些什么就 TM 立马去做! 是的,突然想起我不会 JNI.NDK 开发.解决办法:立马去学! 一:配置 NDK 环境 下载 NDK 写入到配置文件 ...

  2. android Jni NDK开发环境搭建及其简单实例的编写

    android  Jni  NDK开发环境搭建及其简单实例的编写 由于工作需要,需要采用开发想要的JNI,由于之前没有接触过安卓的开发,所以更加网上的帖子,学习了下.遇到了些问题,然后总结下学习过程中 ...

  3. Android JNI/NDK开发教程

    JNI/NDK开发指南:http://blog.csdn.net/xyang81/article/details/41759643

  4. JNI/NDK开发指南(开山篇)

    转载请注明出处:http://blog.csdn.net/xyang81/article/details/41759643 相信很多做过Java或Android开发的朋友经常会接触到JNI方面的技术, ...

  5. AS2.2使用CMake方式进行JNI/NDK开发

    之前写过一篇比较水的文章Android手机控制电脑撸出HelloWorld 里面用到了JNI/NDK技术. 这篇文章给大家介绍下JNI/NDK开发.采用的是Android Studio2.2开发环境, ...

  6. JNI/NDK开发

    公司的新需求终于解决完了,离测试和发布还有段时间,第一次体验了下没需求没bug的感觉,真是舒爽~然后翻了翻有什么可以学的.无意翻到了Android后期发展的五大趋势.一.性能优化.二.高级UI.三.J ...

  7. Android JNI(NDK)开发总结

    早就知道Java有个jni可以调用本地化代码,一直没有动力去研究它,现在公司想通过在Android中调用本地化代码来申请较多的内存以突破Android对单个进程的内存限制,这确实是可行的:我的Nexu ...

  8. Android Native 代码NDK开发学习笔记

    引用:http://www.kunli.info/2011/08/21/android-native-code-study-note/ JNI,全称Java Native Interface,是用于让 ...

  9. Android -- Android下的NDK开发(一)

    1,NDK是什么?为什么要进行NDK开发? NDK:Native Development Kit.Android应用运行在Dalvik虚拟机中.NDK允许开发人员使用本地代码语言(例如C和C++)实现 ...

  10. 使用Android Studio进行ndk开发的准备

    1. gradle-ex2. ndk开发包3. 项目目录结构4. lldb调试器 1. 一般来说gradle不是必需的,gradle也是可以进行ndk编译的,然而你需要在编译时使用更多(多于一个)c+ ...

随机推荐

  1. Python学习笔记第十四周

    目录: 一.HTML 1.概述 2.HTML 二.CSS 一.HTML 1.概述 HTML是英文Hyper Text Mark-up Lang(超文本标记语言)的缩写,他是一种制作万维网页面的标准语言 ...

  2. github上DQN代码的环境搭建,及运行(Human-Level Control through Deep Reinforcement Learning)conda配置

    最近师弟在做DQN的实验,由于是强化学习方面的东西,正好和我现在的研究方向一样于是我便帮忙跑了跑实验,于是就有了今天的这个内容. 首先在github上进行搜寻,如下图: 发现第一个星数最多,而且远高于 ...

  3. [opencvjichu]cv::Mat::type() 返回值

    opencv opencv中Mat存在各种类型,其中mat有一个type()的函数可以返回该Mat的类型.类型表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为CV_(位 ...

  4. Gym .101879 USP Try-outs (寒假自训第七场)

    B .Aesthetics in poetry 题意:给定N个数,(N<2000 ,a[i] <=1e9),让你找一个最大的K,使得N个数膜K的余数个数全都等于N/K个. 思路:我们找到N ...

  5. Gym.101908 Brazil Subregional Programming Contest(寒假自训第六场)

    这几天睡眠时间都不太够,室友晚上太会折腾了,感觉有点累,所以昨天的题解也没写,看晚上能不能补起来. B . Marbles 题意:给定N组数(xi,yi),玩家轮流操作,每次玩家可以选择其中一组对其操 ...

  6. guling code细节

    detect_hand.py 分水岭算法: 任何一幅灰度图像都可以被看成拓扑平面,灰度值高的区域可以被看成是山峰,灰度值低的区域可以被看成是山谷.我们向每一个山谷中灌不同颜色的水,随着水的位的升高,不 ...

  7. 2019寒假算法基础集训营1 - B 小a与"204"

    题目: 小a非常喜欢这个数字,因为. 现在他有一个长度为的序列,其中只含有这三种数字 设为序列中第个数,你需要重新排列这个数列,使得最大(公式的含义是:每个数与前一个数差的平方的和) 注意:我们默认 ...

  8. java中实现Comparable接口实现自定义排序

    class Student implements Comparable{ String name; int gpa; @Override public int compareTo(Object arg ...

  9. hdu3374 String Problem KMP+最大最小表示法

    Give you a string with length N, you can generate N strings by left shifts. For example let consider ...

  10. Go Example--map

    package main import "fmt" func main() { //初始化map make(map[类型][类型]) m:= make(map[string]int ...