【Gradle-12】分析so文件和依赖的关系

news2025/3/13 7:15:45

1、前言

在包大小的占比中,so文件的占比往往是最高的,动辄几兆的大小多一个都会把包大小的指标打爆。
而在各厂商要求对手机CPU ARM架构进行分包适配的情况下,你更需要知道哪些依赖是没有适配v7a/v8a的,这将影响你的APP在应用市场的审核。
所以搞清楚so文件和依赖的关系,它不仅是一个技术指标归因的工具,也是应对厂商分包适配的利器。

2、分析APK

我们一般分析APK是通过Android Studio提供的Analyze APK工具,可以清晰的看到APK文件的组成部分,比如lib文件夹下有哪些so文件,但是却无法直观的看出这些so文件属于哪个依赖。
如下图:
analyze apk.png

3、so文件怎么来的

想要知道so文件是属于哪个依赖,那么得先搞清楚so文件是怎么来的。
如果你分析过apk里面的so文件,你会发现,除了项目中lib文件夹下手动添加的so文件之外,还有一些不知道是哪来的。
要想搞清楚这个,你还得知道我们的依赖是依赖的什么东西。

以okhttp为例:

implementation 'com.squareup.okhttp3:okhttp:4.10.0'

我们通过GAV坐标依赖的实际是square公司发布的jar/aar文件
jar.png
所以,除了你自己添加的so文件之外,其余的,都是通过依赖导进来的。

ok,整体思路我们捋一下:
Gradle管理依赖会自动去下载jar/aar,然后我们通过遍历所有依赖,拿到对应的jar/arr,再去获取其中对应的so文件。
听起来并不复杂,实际上也很简单,下面来实战一下。

4、实战

4.1、栗子

以阿里云音视频SDK为例,它一定是包含so文件的,我不信它不用FFmpeg🐶。
添加示例依赖:

    //8.全功能:直播推流(含超低延时直播、RTC连麦)+短视频+播放器+美颜特效
    implementation 'com.aliyun.aio:AliVCSDK_Premium:6.4.0'

其他配置就不赘述了,可以自行去看文档。

别忘了添加ndk配置,否则so打不进去。

    defaultConfig {
        ndk {
            abiFilters 'arm64-v8a', 'armeabi-v7a', 'armeabi-v8a'
        }
    }

4.2、遍历

ok,准备工作到位,写个插件遍历所有的依赖文件并打印出来。

Configuration configuration = project.getConfigurations().getByName(applicationVariant.getName() + "CompileClasspath");
configuration.forEach(file -> {
    System.out.println(TAG + "file " + file.getName());
    String fineName = file.getName();
    if (fineName.endsWith(".jar") || fineName.endsWith(".aar")) {
        try {
            JarFile jarFile = new JarFile(file);
            for (Enumeration enums = jarFile.entries(); enums.hasMoreElements(); ) {
                JarEntry jarEntry = (JarEntry) enums.nextElement();
                System.out.println(TAG + "jarEntry " + jarEntry.getName());
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
});

这里在Project评估完成之后,获取Configuration对象,然后遍历所有的依赖文件,最后通过JarEntry把文件里面所有的子文件打出来。
输出:
输出1.png
可以看到,已经把所有的子文件都打出来了,包括jni/、res/、assets/等等。

4.3、优化

上面的输出还不够直观,我们在过滤一下,只打印so文件,然后优化一下打印的格式。

configuration.forEach(file -> {
    String fineName = file.getName();
    System.out.println(TAG + "fine name = " + fineName);
    if (fineName.endsWith(".jar") || fineName.endsWith(".aar")) {
        try {
            JarFile jarFile = new JarFile(file);
            for (Enumeration enums = jarFile.entries(); enums.hasMoreElements(); ) {
                JarEntry jarEntry = (JarEntry) enums.nextElement();
                if (jarEntry.getName().endsWith(".so")){
                    System.out.println(TAG + "----- so name = " + jarEntry.getName());
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
});

最终效果:

//...
GradleXPlugin >>>>> fine name = AliVCSDK_Premium-6.4.0.aar
GradleXPlugin >>>>> ----- so name = jni/arm64-v8a/libMNN_CL.so
GradleXPlugin >>>>> ----- so name = jni/arm64-v8a/libalivcffmpeg.so
GradleXPlugin >>>>> ----- so name = jni/arm64-v8a/liball_in_one.so
GradleXPlugin >>>>> ----- so name = jni/arm64-v8a/libMNN.so
GradleXPlugin >>>>> ----- so name = jni/armeabi-v7a/libMNN_CL.so
GradleXPlugin >>>>> ----- so name = jni/armeabi-v7a/libalivcffmpeg.so
GradleXPlugin >>>>> ----- so name = jni/armeabi-v7a/liball_in_one.so
GradleXPlugin >>>>> ----- so name = jni/armeabi-v7a/libMNN.so
//...

是不是还挺简单的~

5、最后

如果你不想自己写,这个插件我也发布远端了,按照下面三步走,即可使用。
Step 1. Add the JitPack repository to your build file

repositories {
	...
	maven { url 'https://jitpack.io' }
}

Step 2. Add the dependency

dependencies {
    classpath('com.github.yechaoa.GradleX:plugin:1.2')
}

Step 3. Add the Plugin Id to your build file and configure the gradleX{ } dsl

plugins {
    id 'com.yechaoa.plugin.gradleX'
}

gradleX {
    printDependencies = false
    analysisSo = true
}

ok,以上即是本文介绍内容,学废了吗,写作不易,快来三连~

6、GitHub

https://github.com/yechaoa/GradleX

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1197556.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为dns mapping配置案例

解决内网PC用公网的dns用域名方法访问公司内网的web服务器: 原理是用DNS mapping方式解决 配置过程:域名——出口公网IP地址——公网端口——协议类型 公司内网client用户填公网dns, 公网上的dns上面已注册有公司对外映射的web服务器的公网…

管理能力测评,如何提升管理能力?

管理能力是综合能力的体现,通常也解读为组织管理能力,如果要再细分的话,可能还包括有沟通能力,协调能力,组织能力,执行力和专业能力等等。不过没有办法说的太细节,因为每个部分铺开了都是一个独…

AI 绘画 | Stable Diffusion 进阶 Embeddings(词嵌入)、LoRa(低秩适应模型)、Hypernetwork(超网络)

前言 Stable Diffusion web ui,除了依靠文生图(即靠提示词生成图片),图生图(即靠图片提示词生成图片)外,这两种方式还不能满足我们所有的绘图需求,于是就有了 Embeddings&#xff0…

Echarts柱状体实现滚动条动态滚动

当我们柱状图中X轴数据太多的时候,会自动把柱形的宽度挤的很细,带来的交互非常不好,因此就有一个属性来解决:dataZoom 我这里只是实现了一个简易的版本,横向滚动。 dataZoom: {show: true, // 为true 滚动条出现realti…

自主开发刷题应用网站H5源码(无需后端无需数据库)

该应用使用JSON作为题库的存储方式,层次清晰、结构简单易懂。 配套的word模板和模板到JSON转换工具可供使用,方便将题库从word格式转换为JSON格式。 四种刷题模式包括顺序刷题、乱序刷题、错题模式和背题模式,可以根据自己的需求选择适合的模…

Activiti6工作流引擎:Form表单

表单约等于流程变量。StartEvent 有一个Form属性,用于关联流程中涉及到的业务数据。 一:内置表单 每个节点都可以有不同的表单属性。 1.1 获取开始节点对应的表单 Autowired private FormService formService;Test void delopyProcess() {ProcessEngi…

stm32超声波测距不准的解决方法(STM32 delay_us()产生1us)

首先要说明一下原理:使用stm32无法准确产生1us的时间,但是超声波测距一定要依赖时间,时间不准,距离一定不准,这是要肯定的,但是在不准确的情况下,要测量一个比较准确的时间,那么只能…

RK3568平台 查看内存的基本命令

一.free命令 free命令显示系统使用和空闲的内存情况,包括物理内存、交互区内存(swap)和内核缓冲区内存。共享内存将被忽略。 Mem 行(第二行)是内存的使用情况。 Swap 行(第三行)是交换空间的使用情况。 total 列显示系统总的可用物理内存和交换空间大小。 used 列显…

学习c#的第四天

目录 C# 变量 C# 中的变量定义与初始化 接受来自用户的值 C# 中的 Lvalues 和 Rvalues 不同类型变量进行运算 静态变量 局部变量 C# 常量 整数常量 浮点常量 字符常量 字符串常量 定义常量 扩展知识 Convert.ToDouble 与 Double.Parse 的区别 静态常量和动态常…

SpringBoot_01

Spring https://spring.io/ SpringBoot可以帮助我们非常快速的构建应用程序、简化开发、提高效率。 SpringBootWeb入门 需求:使用SpringBoot开发一个web应用,浏览器发起请求/hello后,给浏览器返回字符串"Hello World~~~"。 步骤…

数据结构:树的基本概念(二叉树,定义性质,存储结构)

目录 1.树1.基本概念1.空树2.非空树 2.基本术语1.结点之间的关系描述2.结点、树的属性描述3.有序树、无序树4.森林 3.树的常考性质 2.二叉树1.基本概念2.特殊二叉树1.满二叉树2.完全二叉树3.二叉排序树4.平衡二叉树 3.常考性质4.二叉树的存储结构1.顺序存储2.链式存储 1.树 1.…

MYSQL5.7和MYSQL8配置主从

1、创建专门主从的账号 #登录 mysql -u root -p #创建用户 我这里用户名为test5,注意这里的ip是从库服务器的ip CREATE USER test5192.168.1.20 IDENTIFIED WITH mysql_native_password BY xxxxx; #给主从复制账号授权 grant replication slave on *.* to test5192…

Java程序设计2023-第八次上机练习

8-1简单文本编辑器 编写简单文本编辑器,该程序可以新建、打开、编辑和保存文本文件。当用户点击New时,新建一个文件,用户可以编辑文件内容,然后点击Save保存文件。用户点击Open时,选择一个已有文件,然后可…

SDWAN(Software Defined Wide Area Network)概述与优势分析

文章目录 SDWAN简介SDWAN技术优势简化网络部署和维护安全传输灵活网络拓扑极致体验 SD-WAN关联技术STUNIPsec智能选路SaaS路径优化 典型组网多总部分支组网云管理组网 推荐阅读 SDWAN简介 SDWAN(Software Defined Wide Area Network,软件定义广域网&…

Revit 平面的圆弧,空间的椭圆弧

大家对Revit的空间曲线那么理解,如何用代码创建空间的椭圆弧,,上看是圆弧,正面看是椭圆? 直接放代码: Document doc = commandData.Application.ActiveUIDocument.Document; Autodesk.Revit.DB.XYZ center = new Autodesk.Revit.DB.XYZ(0, 0, 0); …

Vue3 源码解读系列(三)——组件渲染

组件渲染 vnode 本质是用来描述 DOM 的 JavaScript 对象,它在 Vue 中可以描述不同类型的节点,比如:普通元素节点、组件节点等。 vnode 的优点: 抽象:引入 vnode,可以把渲染过程抽象化,从而使得组…

漏刻有时百度地图API实战开发(4)显示指定区域在移动端异常的解决方案

漏刻有时百度地图API实战开发(1)华为手机无法使用addEventListener click 的兼容解决方案漏刻有时百度地图API实战开发(2)文本标签显示和隐藏的切换开关漏刻有时百度地图API实战开发(3)自动获取地图多边形中心点坐标漏刻有时百度地图API实战开发(4)显示指定区域在移动端异常的解…

Linux文件系统——重定向

文章目录 1. 文件描述符分配规则2. 重定向接口dup2自定义shell重定向(补充) 3. 标准输出和标准错误4. 如何理解一切接文件 本章代码gitee地址:文件重定向 1. 文件描述符分配规则 文件描述符的分配规则是从0下标开始,寻址最小的没有使用的数组位置&#…

飞机社交软件开发:重新定义社交媒体的空中交互体验

【导语】 随着互联网技术的快速发展,社交媒体平台的界限也逐渐模糊。飞机社交软件应运而生,打破传统的地面社交模式,为空中旅行的旅客提供全新的交流平台。本文将从市场需求、技术实现、用户体验和未来发展等方面,深入探讨飞机社交…

探索内存函数的奥秘【memcpy、memmove、memset、memcmp】

目录 一,memcpy函数 1,memcpy函数简介 2,memcpy函数的原理 3,memcpy函数的用法 4,注意事项 5,memcpy函数模拟实现 二,memmove函数 1,memmove函数简介 2,memmove函…