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
中都调用一次,这样就会有很多重复代码,我们可以使用拦截器的思想,将这个初始化方法放到一个单独的类中,然后在每个 Activity
的 onCreate
方法中调用这个类的初始化方法,这样就可以了。拦截器思想
这块就涉及到我们项目的代码了,项目使用 ARouter 做的路由与组件化开发,这里可以增加一个
PdfLoadSoInterceptor
拦截器,在跳转 Activity 前下载和加载 so 库你还可以通过
@Route
增加 extras
Flag,来判断是否需要加载 so 库,我这里通过一个 ARouter
的 Provider
来将 SDK 的代码与组件隔离📎 参考文章
- 作者:YunFei
- 链接:https://blog.yunfei.online/article/android-dynamic-load-so
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。