[细节控]--超详细的编译so库教程

似此星辰非昨夜,为谁风露立中宵

Posted by JadynAi on April 3, 2018

开发环境:

硬件:Mac Pro

软件:Android Studio 3.0.1

开发环境:办公室(大弦嘈嘈如急雨,小弦切切如私语)

这次学习编译so库,在网上找了很多教程文章,但都是不成功。最后还是参考官网下的文档成功编译了。遂将此次经历记录下来。

本细节帝主要以本次成功案例为准,详细说明如何使用AS成功编写so库。大道三千,非只有此一条路可走。

这里先贴出本次Jni的测试Demo地址,谨供参考:JniDemo

配置NDK

  • 下载NDK,首先在AS中打开sdk manager。然后选择SDK Tools,再选择NDK即可。AS会自动把ndk相关的东西下载到你SDK目录下的ndk-bundle文件夹中。

  • 配置NDK开发环境
    • Mac上配置NDK环境很简单,帖上一篇文章Mac 配置ndk
    • 配置完成后,打开终端运行ndk-build,显示如下则表示配置成功。
  • 打开根目录下的local.properties文件,配置sdk以及ndk的路径
ndk.dir=ndk路径
sdk.dir=sdk路径
  • 打开项目根目录下的gradle.properties文件,配置以下属性
android.useDeprecatedNdk=true

各类相关文件准备

带有native方法的java类

生成.h文件
  • java类定义好之后,进入Build --> Rebuild项目,然后生成class文件。
  • 然后打开终端,进入到debug目录,执行如下命令,生成.h文件:
javah -classpath . -jni 包名.类名

c++文件
  • 将.h文件拷贝到项目src目录下的jni包下,和c++文件放到一起,同文件夹下还有Android.mkApplication.mk文件:
  • .h文件生成的函数头可以在c++文件中直接使用,加上参数名即可:
  • 需要注意的是,c++文件中必须引用到.h文件的路径
Android.mkApplication.mk文件
  • 这两个文件是ndk-build的关键所在。当时也是在这里遇到的坑最多。
  • 将这两个文件放到c++和.h的文件夹内
  • 其实官方文档这里写的很是详细,但需要梯子,贴出来Android.mk 以及 Application.mk
  • Android.mk
//以下两行为固定写法,照抄即可
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

//生成的so库的名字
LOCAL_MODULE := jni
//照抄
LOCAL_LDFLAGS := -W1,--build-id
//c++文件的文件名
LOCAL_SRC_FILES := jni.cpp
//此行代码在ndk-build时会打印c++代码的错误
LOCAL_CPP_FEATURES := exceptions

//必须要的代码,一个字母都不能错
include $(BUILD_SHARED_LIBRARY)

  • Application.mk
//照抄
#APP_CPPFLAGS := -frtti -fexceptions
//选择你需要的cpu架构类型,all即是所有
APP_ABI := all
//ndk支持的platform,我下载的ndk提示必须不能小于android-14
APP_PLATFORM := android-14

gradle 配置

  • 在app的build.gradle中这样配置:
apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.example.test.jnitest"
        minSdkVersion 16
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        ndk{
        	  //so文件名字和Android.mk内的MODULE名称一致
            moduleName "jni"
            //需要的CPU架构
            abiFilters "armeabi", "armeabi-v7a"
        }
        
    }

	//so生成的目标文件夹
    sourceSets.main {
        jni.srcDirs = ['libs']
    }
    
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

执行ndk-build命令

  • 到此为止,所有必须的文件以及配置都已经准备完毕。然后接下来执行ndk的命令即可。但我的AS不知道出什么问题,AS带的终端执行ndk-build命令总是提示不存在。
  • 没办法,最后只能打开Mac终端,cd到项目中c++文件的jni目录下,执行ndk-build命令.
    哒哒,大功告成!