type
slug
category
status
date
summary
tags
icon
password
AI 摘要

前言

😀
说起来我也不是一个精益求精的人,最近越来越懒了,apk 的包越来越大了,不知不觉已经 367M 看了一下 添加电子书功能后 apk 陡增了 100 多 M,话不多说,这里只针对 福昕pdf SDK 进行 so 库的动态加载
建议你先度读以下文章末尾的参考文章,这样你会更好的理解这篇文章,本文以 福昕pdf SDK 为例子 librdk.so 为 so 文件,来讲解 so 动态加载的原理与实现。

🪡 so 是什么

以前学 Windows 编程的时候接触过 静态链接库动态链接库,Android 中的 so 库就是动态链接库,so 是 shared object 的缩写,so 库是一种共享库,它可以被多个应用程序共享,so 库是一种二进制文件,它包含了一些函数和数据,这些函数和数据可以被其他程序调用。 以前学的时候说静态库是把代码编译到程序中了,不管你是否已经使用了这个库,程序会变到很大,感觉有点像 Electron 的打包方式,你的程序里面包含里一个完整的浏览器内核,装个记事本都要 100M,不过 Android os 目前也有点这个意思,每个自研的播放器里都有 ffmpeg。 吐槽完了,我们来看看正常的 so 库是怎么使用的。 代码中是这么操作的,将用到的 so 库拷贝到 jniLibs 目录下,然后在代码中调用 System.loadLibrary("xxx") 加载 so 库,这样就可以调用 so 库中的函数了。

🔍 so 动态加载原理

因为是共享库,所以如果已经加载过了,再次加载如果已经加载过了,再次加载不会有任何效果,所以我们只需要将 so 分离出来,在调用 System.loadLibrary("xxx") 前加个拦截器,提前加载我们网络下载好的 so 库,这样就可以实现 so 的动态加载了。

🚀 so 动态加载实现

将 so 从 apk/aar 中提取出来

这个很好实现,直接用 7z 或者 winrar 打开 apk/aar 文件,然后找到 jniLibs 目录,将里面的 so 文件提取出来就行了。

打包时不再将 so 打包到 apk 中

这个也很简单,将 jniLibs 目录删除,或者将 jniLibs 目录下的 so 文件删除,然后打包就行了,等等,这样不好每次打包还要删除,我们可以在 build.gradle 中配置,不将 so 打包到 apk 中。

拦截器在调用 System.loadLibrary("xxx") 前加载 so

对于电子书来讲,他只要在他初始化方法之前就行,Library.initialize(Constants.PDF.foxitSN, Constants.PDF.foxitKey),只要在这个方法之前加载就行,其实这样就可以了。 但是目前这个初始化在 Application 总不能阻碍 App 启动吧,我们把他移动到 对应的 Activity 中,这样就可以了。 但是如果有多个 Activity 需要使用这个 so 库,那么就需要在每个 Activity 中都调用一次,这样就会有很多重复代码,我们可以使用拦截器的思想,将这个初始化方法放到一个单独的类中,然后在每个 ActivityonCreate 方法中调用这个类的初始化方法,这样就可以了。

拦截器思想

这块就涉及到我们项目的代码了,项目使用 ARouter 做的路由与组件化开发,这里可以增加一个 PdfLoadSoInterceptor 拦截器,在跳转 Activity 前下载和加载 so 库
你还可以通过 @Route 增加 extras Flag,来判断是否需要加载 so 库,我这里通过一个 ARouterProvider 来将 SDK 的代码与组件隔离

📎 参考文章

 
tmux GitLab 优化
Loading...
YunFei
YunFei
🪄作之不止,乃成君子