NDK环境搭建

前言

其实参考超级简单的Android Studio jni实现 这篇文章就可以完美的实现,java代码调用c++代码。
记得先下载ndk的官方包。

步骤

1.到谷歌官方网站下载NDK

NDK环境搭建_第1张图片
image.png

2.接着按照文中的步骤一步步完成即可。

3.对一些文件进行解释
JNI(Java Native Interface):Java本地接口。是为了方便Java调用c、c++等本地代码所封装的一层接口(也是一个标准)。大家都知道,Java的优点是跨平台,但是作为优点的同时,其在本地交互的时候就编程了缺点。Java的跨平台特性导致其本地交互的能力不够强大,一些和操作系统相关的特性Java无法完成,于是Java提供了jni专门用于和本地代码交互,这样就增强了Java语言的本地交互能力。上述部分文字摘自任玉刚的 Java JNI 介绍
NDK(Native Development Kit) : 原生开发工具包,即帮助开发原生代码的一系列工具,包括但不限于编译工具、一些公共库、开发IDE等。
NDK工具包中提供了完整的一套将 c/c++ 代码编译成静态/动态库的工具,而Android.mk和Application.mk,你可以认为是描述编译参数和一些配置的文件。比如指定使用c++11还是c++14编译,会引用哪些共享库,并描述关系等,还会指定编译的abi。只有有了这些NDK中的编译工具才能准确的编译 c/c++ 代码。
那 CMake 又是什么呢。脱离 Android 开发来看,c/c++ 的编译文件在不同平台是不一样的。Unix 下会使用 makefile 文件编译,Windows 下会使用 project 文件编译。而 CMake 则是一个跨平台的编译工具,它并不会直接编译出对象,而是根据自定义的语言规则(CMakeLists.txt)生成 对应 makefile 或 project 文件,然后再调用底层的编译。
在Android Studio 2.2 之后,工具中增加了 CMake 的支持,你可以这么认为,在 Android Studio 2.2 之后你有2种选择来编译你写的 c/c++ 代码。一个是 ndk-build + Android.mk + Application.mk 组合,另一个是 CMake + CMakeLists.txt 组合。这2个组合与Android代码和c/c++代码无关,只是不同的构建脚本和构建命令。本篇文章主要会描述后者的组合。(也是Android现在主推的)

  1. ABI 是什么
    ABI(Application binary interface)应用程序二进制接口。不同的CPU 与指令集的每种组合都有定义的ABI
    (应用程序二进制接口),一段程序只有遵循这个接口规范才能在该 CPU 上运行,所以同样的程序代码为了兼容多个不同的CPU,需要为不同的ABI
    构建不同的库文件。当然对于CPU来说,不同的架构并不意味着一定互不兼容。
    armeabi设备只兼容armeabi;
    armeabi-v7a设备兼容armeabi-v7a、armeabi;
    arm64-v8a设备兼容arm64-v8a、armeabi-v7a、armeabi;
    X86设备兼容X86、armeabi;
    X86_64设备兼容X86_64、X86、armeabi;
    mips64设备兼容mips64、mips;
    mips只兼容mips;

具体的兼容问题可以参见这篇文章。Android SO文件的兼容和适配
当我们开发 Android 应用的时候,由于 Java 代码运行在虚拟机上,所以我们从来没有关心过这方面的问题。但是当我们开发或者使用原生代码时就需要了解不同ABI
以及为自己的程序选择接入不同ABI
的库。(库越多,包越大,所以要有选择)

了解完 armeabi armeabi-v7a arm64-v8a mips mips64x86x86_64等abi的原理,会发现要想兼容所有cpu的abi必定会产生更大的apk文件,所以在这里直接简单粗暴的兼容armeabi就ok了,像微信就是这么粗暴的。
很多时候导很多abi的so文件还是会出现找不到so的情况,那么只兼容armeabi就可以了嘛!
在build.gradle的android里的defaultConfig内添加如下内容:

defaultConfig {    
    ndk {    
        abiFilters "armeabi"  
    }    
}    

或者再多加个armeabi-v7a都可以。
然后项目中只留armeabi就可以了。

如果报错

Error:(15, 1) A problem occurred evaluating project ':app'.  
> Error: NDK integration is deprecated in the current plugin.  Consider trying the new experimental plugin.  For details, see http://tools.android.com/tech-docs/new-build-system/gradle-experimental.  Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration.  

请在 gradle.properties 中 添加
android.useDeprecatedNdk=true

语法

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := MyLibrary
LOCAL_SRC_FILES =: MyLibrary.cpp
include $(BUILD_SHARED_LIBRARY)

其中LOCAL_PATH是C/C++代码所在目录,也就是我们的jni目录。
LOCAL_MODULE是要编译的库的名称。编译器会自动在前面加上lib,在后面加上.so。
LOCAL_SRC_FILES是要编译的C/C++文件。

Application.mk

APP_ABI := all

表示生成所有平台的动态库。

配置gradle

在defaultConfig下,配置ndk:

ndk{
      moduleName "MyLibrary"   // 生成的so名字
    }

在android标签内配置sourceSets:

sourceSets.main{
      jni.srcDirs = []
      jniLibs.srcDir "src/main/libs"}
  }

生成的so文件都在src/main/libs目录下。

总结

遵循以下步骤可以将一个本地方法链接到Java程序中

1.在Java类中声明一个本地方法
2.运行javah以获得包含该方法的C声明的头文件
3.用C实现该本地方法
4.将代码置于共享库中
5.在Java程序中加载该类库

后面可以了解和学习一下cmake

参考文章

http://blog.csdn.net/chuhongcai/article/details/52558049
https://developer.android.google.cn/ndk/downloads/index.html#rel
http://www.jianshu.com/p/6332418b12b1
http://blog.csdn.net/wwj_748/article/details/51274580(命令行的方式)

你可能感兴趣的:(NDK环境搭建)