Android NDK开发基础知识

概要

Android NDK开发对于初学者来说,往往会有丈二和尚摸不着头脑之感,所以在此处理清一些基础知识,总体来说有以下几个方面:

  • ABI概念的理解。
  • 使用C++的两种方式(Android Studio)。
  • Gradle配置.so文件的格式。
  • 使用.so的注意事项。

ABI概念的理解

到目前为止,Android系统总共支持7种不同的CPU架构,分别是:

  • ARMv5
  • ARMv7
  • x86
  • MIPS
  • ARMV8
  • MIPS6
  • x86_64

每一种CPU架构对应一种ABI。所谓ABI(Application Binary Interface),即应用程序二进制接口。它的作用是定义二进制文件(.so文件,也叫动态链接库)怎样运行在不同架构的系统上。在Android Studio的目录结构中,它的表现形式如下:

这里写图片描述

很多手机设备支持不止一种ABI,但为了更好的用户体验和更好的性能,最好针对不同CPU架构提供专门的.so文件,即将不同的.so文件放入jniLibs对应的子目录中,在Android包管理器安装apk时,系统会自动选择对应的ABI预编译好的.so文件。

使用C++的两种方式

  • 引入预编译的二进制C++函数库(.so文件)
  • 直接从C++源码编译

1、引入预编译的二进制C++函数库
这种引入方式比较简单,只需要将.so文件放入到上面对应的ABI目录中,假设每个目录中有一个名为libhello.so文件,那么在代码中可以这样使用这个库:

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

注意:文件名和使用时名字的差别;如果该.so文件来自于第三方,需要拿到对应的native方法声明类,并且将该类放到原始的包下面,否则会报找不到方法实现错误。
2、直接从C++源码编译
在Android Studio中对C++源码编译生成.so文件的过程如下:

 1、 配置ndk.dir变量

打开工程根目录下的local.properties文件,在其中配置ndk目录,如下是我的环境自动生成的配置路径:

ndk.dir=D\:\\Android\\sdk\\ndk-bundle
sdk.dir=D\:\\Android\\sdk
 2、 在Gradle中配置NDK模块

为了让gradle对C/C++代码进行编译,需要配置module的build.gradle文件,如下:
这里写图片描述

 3、添加C/C++文件到指定目录

默认情况下,Gradle会到/src/main/jni目录查找C/C++文件进行编译,所以只需将C++文件放入该目录即可,当然可以在gradle中修改该默认选项,在build.gradle中,android项目下做如下设置

 sourceSets.main{
        jni.srcDirs 'src/main/source'
    }

使用.so文件的注意事项

  1. .so文件版本兼容性问题
    NDK平台是向前兼容的,所以不能将高版本的.so文件运行在低版本的设备上,当引入一个预编译的.so文件时,要检查它被编译所用的平台版本,对应App的minSdkVersion。
  2. 混合使用不同的C++运行时编译的.so文件
    当只有一个.so文件时,C++运行时没有问题,但存在多个.so文件时,应该让所有.so文件都动态链接相同的C++运行时,否则可能会发生很奇怪的Crash。
  3. 应该为每一个CPU架构提供专门的.so文件
  4. 只提供armeabi架构的.so文件而忽略其它ABIs
    所有设备都支持armeabi架构的.so文件,因此可以将armeabi架构的.so文件代替所有的CPU架构的.so文件,但是这将大大降低函数性能和兼容性,为了解决这一问题和减少APK包的大小,可以生成不同ABI版本的APK,可以做如下配置:
android {
    //....
    splits {
        abi {
            enable true
            reset()
            include 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'  //select ABIs to build APKs
            universalApk true  //generate an additional APK than contains all ABIs
        }
    }

    project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, 'mips': 5, 'mips64': 6, 'x86': 8, 'x86_64': 9]
    android.applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.versionCodeOverride = project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI),
                    0) * 1000000 + android.defaultConfig.versionCode
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值