Android So库添加和生成
Android So库添加和生成
一:前言
日常开发我们经常会使用到第三库,涉及到底层的语音,视频等都需要添加so库。
而so库的体积一般来说非常的大,不搞清楚随意添加会导致apk体积暴增。
上面问题:
Android提供abifilters为我们提供了解决方案abifilters为我们提供了选择适配指定CPU架构的能力,只需要在app下的build.gradle添加如下配置:
android{
defaultConfig{
ndk {
//选择要添加的对应cpu类型的.so库。
abiFilters 'arm64-v8a','armeabi', 'armeabi-v7a', 'x86_64','x86'
}
}
}
为何大厂APP如微信、支付宝等只适配了armeabi-v7a/armeabi?
https://mp.weixin.qq.com/s/jn...
Android中的so文件是动态链接库,是二进制文件,即ELF文件。多用于NDK开发中
二:什么是ABI
ABI是英文Application Binary Interface的缩写,即应用二进制接口。
不同Android设备,使用的CPU架构可能不同,因此支持不同的指令集。
CPU 与指令集的每种组合都有其自己的应用二进制界面(或 ABI),ABI非常精确地定义了应用程序的机器代码应如何在运行时与系统交互。
您必须为要与您的应用程序一起使用的每种CPU架构指定一个ABI(Application Binary Interface)
Android 目前支持7种ABIs:arm64-v8a,armeabi, armeabi-v7a,X86, X86–64,mips, mips64
三:CPU架构
文章图片
文章图片
总结:
(1)只适配arm64-v8a 可以运行在arm64-v8a上
优点: 性能最佳
缺点:只能运行在arm64-v8上,要放弃部分老旧设备用户
(2)只适配armeabi-v7a可以运行在armeabi-v7a和arm64-v8a
只是又筛掉了一部分老旧设备,在性能和兼容二者中比较平衡
(3)只适配armeabi的APP可以跑在armeabi,x86,x86_64,armewabi-v7a,arm64-v8上
优点:基本上适配了全部CPU架构(除了淘汰的mips和mips_64)
缺点:性能低,相当于在绝大多数手机上都是需要辅助ABI或动态转码来兼容
文章图片
未来只需要适配一款cpu架构arm64-v8a,这些慢慢已经淘汰了,主流是cpu架构arm64-v8a
四:ADB查看手机的CPU架构
F:\soudaoProject\MyGitignore>adb shell
onc:/ $ cat /proc/cpuinfo
Processor: AArch64 Processor rev 4 (aarch64)//这里可以看出手机是CPU架构是ARM v8 64位
processor: 0
BogoMIPS: 38.40
Features: fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x51
CPU architecture: 8
CPU variant: 0xa
CPU part: 0x801
CPU revision: 4processor: 1
BogoMIPS: 38.40
Features: fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x51
CPU architecture: 8
CPU variant: 0xa
CPU part: 0x801
CPU revision: 4processor: 2
BogoMIPS: 38.40
Features: fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x51
CPU architecture: 8
CPU variant: 0xa
CPU part: 0x801
CPU revision: 4processor: 3
BogoMIPS: 38.40
Features: fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x51
CPU architecture: 8
CPU variant: 0xa
CPU part: 0x801
CPU revision: 4processor: 4
BogoMIPS: 38.40
Features: fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x51
CPU architecture: 8
CPU variant: 0xa
CPU part: 0x800
CPU revision: 2
五:Android Studio添加So库
方法一:在src/main中新建jniLibs文件夹,把.so复制进去
我这是ijkplayer的so库
文章图片
方法二:是在app/中新建libs文件夹,把.so复制进去
文章图片
这需要在app下build.gradle中添加五行脚本即可(注:以下脚本意思是会把libs文件夹当成jniLibs文件夹,可以直接用so库了)
android{sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
六.Android So库生成
JNI是Java Native Interface的缩写,它的主要作用是提供了若干API来实现Java和其他语言的通信(主要是C和C++)。
NDK是一系列工具的集合,它可以帮助开发者快速开发C(或者C++)的动态库(也称So库),并So库和Java应用一起打包。
JNI的使用就是需要将C(或者C++)代码编译成动态库供Java方法调用
生成SO库(方式一)
第一步:下载NDK,配置NDK,下载CMake,这个是写C语言的
File-->Settings
文章图片
![上传中...]()
文章图片
下载完NDK后,去local.properties文件中查看是否定义了ndk的存储路径,
文章图片
然后到gradle.properties文件中添加android.useDeprecateNdk=true,表示我们的应用需要使用NDK
文章图片
第二步:NDK开发建立一个C++项目
文章图片
早android结构下
文章图片
查看CMakeLists.txt并修改
cmake_minimum_required(VERSION 3.4.1)# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.add_library( # Sets the name of the library.
demo//默认是native-lib# Sets the library as a shared library.
SHARED# Provides a relative path to your source file(s).
demo.cpp //默认是native-lib.cpp)# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.find_library( # Sets the name of the path variable.
log-lib# Specifies the name of the NDK library that
# you want CMake to locate.
log )# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.target_link_libraries( # Specifies the target library.
demo//默认是native-lib# Links the target library to the log library
# included in the NDK.
${log-lib} )
在这里你可以发现app下的build.gradle已经编译生成了
android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
defaultConfig {
applicationId "com.randao.myproject"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
//这里是创建C++项目默认生成的
externalNativeBuild {
cmake {
cppFlags ""
}
}
//这个是我自己添加去匹配cPU架构
ndk{
abiFilters 'arm64-v8a'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
//默认生成去构建CMakeLists.txt
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
}
}
}
【Android So库添加和生成】第三步:编写Java调用类
/*
* JNI测试类*/
public class TestJNI {
static {
System.loadLibrary("demo");
}
public native void set();
//C语言中实现,输出这就是一个JNI的调用
}
Java调用类的说明:
1、静态代码块表明了该Java类需要加载哪一个So库,例子中的demo是So库的名称。(注意:实际上NDK生成的So库的名称为libdemo.so,但是So库的名称就是demo)
2、native关键字声明了set()方法,这个方法需要在C(或者C++)中实现。
第四步:生成.h头文件,编写C(或者C++)代码
打开demo.cpp文件编写
#include
#include extern "C"
JNIEXPORT jstring JNICALL
Java_com_randao_myproject_TestJNI_set(JNIEnv *env, jobject thiz) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
//Java_com_randao_myproject_TestJNI_set(JNIEnv *env, jobject thiz)
//Java+项目名+类名+方法名结果是输出Hello from C++
文章图片
第五步:调用在Activity
String aa=new TestJNI().set();
//调用方法输出
Toast.makeText(this,aa,Toast.LENGTH_SHORT).show();
第六步:查看生成的so库
文章图片
1.什么是CMake?
定义:允许开发者编写一种平台无关的 CMakeList.txt 文件来定制整个编译流程,然后再根据目标用户的平台进一步生成所需的本地化 Makefile 和工程文件,如 Unix 的 Makefile 或 Windows 的 Visual Studio 工程。从而做到“Write once, run everywhere”。
2.如果我想JNI中增加一个方法
/*
* JNI测试类*/
public class TestJNI {
static {
System.loadLibrary("demo");
}
public native void set();
//C语言中实现,输出这就是一个JNI的调用public native void add(int x,int y);
//demo.cpp实现add
对应的demo.cpp下方法
#include
#include extern "C"
JNIEXPORT jstring JNICALL
Java_com_randao_myproject_TestJNI_set(JNIEnv *env, jobject thiz) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_randao_myproject_TestJNI_add(JNIEnv *env, jobject thiz,jint x,jint y){
//具体操作add
}
END:未来可期
推荐阅读
- Docker应用:容器间通信与Mariadb数据库主从复制
- android第三方框架(五)ButterKnife
- 太平之莲
- Android中的AES加密-下
- 带有Hilt的Android上的依赖注入
- thinkphp|thinkphp 3.2 如何调用第三方类库
- 我正在参加安特思库共读一本书干法。
- android|android studio中ndk的使用
- Python爬虫|Python爬虫 --- 1.4 正则表达式(re库)
- Android事件传递源码分析