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

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Android Studio 中使用 Gradle 构建工具进行编译和打包,生成 .so 动态链接库,可以按照以下步骤进行: 1. 在 Android Studio 中创建一个 C/C++ 模块,选择 File -> New -> New Module -> C/C++ Library,然后按照向导设置模块名称、语言类型和支持的 ABI。 2. 在模块的 build.gradle 文件中,添加以下配置: ```groovy android { // 指定支持的 ABI,包括 armeabi-v7a、arm64-v8a、x86、x86_64 等 ndk { abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } // 配置 CMakeLists.txt 文件路径 externalNativeBuild { cmake { path "CMakeLists.txt" } } } // 配置 CMake 版本 cmake { version "3.10.2" } ``` 3. 在模块的 src/main 目录下创建 jni 文件夹,并将 C/C++ 代码放入该文件夹中。 4. 在 jni 文件夹下创建 CMakeLists.txt 文件,并编写编译选项和链接选项,指定生成 .so 文件的名称和路径,以及引入其他依赖库等。例如: ```cmake # 设置编译选项 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # 设置源文件路径 file(GLOB_RECURSE SOURCE_FILES "*.cpp") # 设置头文件路径 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) # 配置动态库输出路径和名称 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}) set(CMAKE_LIBRARY_OUTPUT_NAME "native-lib") # 引入其他依赖库 find_library(log-lib log) # 生成动态库 add_library(native-lib SHARED ${SOURCE_FILES}) target_link_libraries(native-lib ${log-lib}) ``` 5. 点击 Android Studio 工具栏中的 Build -> Make Project,进行编译和打包,生成 .so 动态链接库。 6. 在模块的 build.gradle 文件中查看生成的 .so 文件路径,例如: ```groovy android { externalNativeBuild { cmake { path "CMakeLists.txt" } } sourceSets { main { jniLibs.srcDirs = ['src/main/jniLibs'] } } } ``` 以上就是在 Android Studio 中使用 Gradle 构建工具进行编译和打包,生成 .so 动态链接库的步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yechaoa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值