开发一款 SDK 需要注意哪些问题

1、版本冲突

1.1、Java 版本问题

当业务方的 Java 环境是 1.8 时,如果 SDK 是使用 Java 11 编译,则调用 SDK 相关代码的地方在编译时将会报错:

类文件具有错误的版本 55.0(jdk 11), 应为 52.0(jdk 8)

所以,SDK 在非必要情况下,Java 版本尽量兼容到最低,除非遇到特殊情况,例如 SDK 需要适配 Android 12,但 Deprecated 的 ElementType�.MODULE 标明需要 Java 9 才支持,SDK 被迫要升级 Java 版本,这种情况也能允许,但对外提供的接入文档最好明确标明最低的 Java 版本。

1.2、kotlin 版本问题

META-INF/xxxx_release.kotlin_module: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.9.0, expected version is 1.7.1.

上面这类错误相信遇到的应该不少,Java 有一套自己的 JDK 判断准则,Kotlin 也有,Kotlin metadata 的版本来自 KGP 版本,也即意味着,当你的 SDK 使用高版本的 KGP 编译时,业务方要么编译不过,要么被迫升级 KGP 版本,这会使业务方因为升级 Kotlin 而带来其他业务的不稳定性。 所以,如果非必要的情况下,尽量保持低版本的 KGP 版本,与 Java 版本类似;或是,SDK 就不要使用 Kotlin 来开发,减少影响业务方的变量。

参考文档:

1.3、minSdkVersion 版本问题

组件依赖的 AndroidManifest.xml 会保留 minSdkVersion 与 targetSdkVersion, 业务方在打包时,如果 SDK(23) 的 minSdkVersion 比业务方(21)高的话,打包将会报错:

Manifest merger failed : uses-sdk:minSdkVersion 21 cannot be smaller than version 23 declared in library

如果业务方被迫升级 23 的话,将会导致业务项目机型覆盖面出现很大的问题,所以,在保障 SDK 兼容性的情况下,尽量将 minSdkVersion 调整到合适的版本

1.4、题外话

Dependency 'androidx.compose.ui:ui-geometry:1.3.0' requires libraries and applications that depend on it to compile against version 33 or later of the Android APIs. :app is currently compiled against android-32. Recommended action: Update this project to use a newer compileSdkVersion of at least 33, for example 33.

上面这个报错是在接入 Compose 依赖后报错的一个 app 工程 compileSDK 版本过低的问题,升级到 33 即可,这时我就在想了,一个依赖组件是怎么影响主工程的 compileSDK 版本的。从 External Libraries 也看不出来啥,只好看了下 transformed,惊喜发现:

可以通过 minCompileSdk 来控制主工程的最低 compileSDK 版本,这算是一个依赖版本的反向应用了。

2、依赖混淆

配置 proguard-rules.pro 混淆,keep 住对外的接口与方法,混淆实现类,SDK 发布时,不带上 sourceJar,外部只能查看 class 文件,进一步增加外部观摩 SDK 核心代码难度

3、向下兼容

SDK 对外方法尽量向下兼容,如遇到必须要移除的,可提前几个版本将方法标注 @Deprecated 过期,并提供的新的调用方法,例如:

  • 使用注解 @Deprecated 标注方法废弃,since 标明从哪个版本开发废弃,forRemoval 标明未来将会删除该方法
  • 注释使用 @deprecated 标注提供新的替换方法

调用效果如下,将鼠标移至方法处会提示:

  • 可以使用快捷键来实现一键替换
  • 使用新的方法进行代替

4、非空处理

对外接口必须标明入参与返回值的可空与非空,避免业务方发生 NPE 问题,下面列个对比:

kotlin 调用效果:

  • getName 编译时不会报错,但在运行时会发生 NPE 异常
  • getAddress 在编译时会提前报错,及时发现问题

Java 调用效果:

  • getName 编译时不会报错,但在运行时会发生 NPE 异常
  • getAddress 编译时不会报错,但会告警提示,运行时依然会发生 NPE(这也体现了 kotlin 非空的好处)

5、清晰的注释

一个方法最基本的注释包括:

  • 方法功能描述
  • 参数描述:@param
  • 返回值描述: @return

例如:

参考文档:

6、版本统一

如果对外提供的 SDK 有多个依赖,并且不同版本可能会出现兼容性问题,则可以使用 Bom 来管理版本,例如官方示例 Using the Bill of Materials

kotlin 复制代码
dependencies {
    // Import the Compose BOM
    implementation platform('androidx.compose:compose-bom:2024.01.00')
    implementation 'androidx.compose.material3:material3'
    implementation 'androidx.compose.foundation:foundation'
}

material3 与 foundation 将会使用 compose-bom 定义的版本,未来 SDK 升级或是版本修复,都只需提供 compose-bom 的版本即可。

7、DIP 依赖倒置原则

SDK 提供抽象接口,业务方依赖接口调用,这么做的好处是,业务方面向接口调用使用简单,还能避免使用不稳定的内部实现,并且,内部实现可以进行混淆。

8、系统兼容判断

如果 SDK 有针对一些系统版本兼容的处理,则不仅仅通过 Build.VERSION.SDK_INT 来判断机型版本就够了,还要判断应用的 targetSdkVersion 版本,避免业务方使用的 targetSdkVersion 比系统兼容版本低而导致没有效果的现象。

例如 Android 12 新增的 BLUETOOTH_SCAN 权限,SDK 内部判断 SDK_INT 是否大于 Android 12,可业务方的 targetSdkVersion 并没有适配 12,清单文件也不会申明该权限,因此,该判断可能会发生不可预知的错误,所以,这里最好再做下 targetSdkVersion 的判断。

参考文档:

9、依赖冲突

SDK 难免会依赖一些三方库,如果业务方依赖的三方库版本比 SDK 依赖的三方库高,并且三方库兼容性差,则可能会出现 SDK 使用到三方库的一些 api 调用发生类找不到、方法找不到等异常,这似乎并没有好的解决办法,但也不是不能解:

  1. 尽量减少三方库依赖
  2. 如果三方库极其不稳定又不得不用,则可以下载其源码,更改包名,重新编译依赖,提供给 SDK 开发使用,更改包名是为了避免 duplicate class
相关推荐
Clockwiseee17 分钟前
PHP之伪协议
android·开发语言·php
小林爱22 分钟前
【Compose multiplatform教程08】【组件】Text组件
android·java·前端·ui·前端框架·kotlin·android studio
小何开发1 小时前
Android Studio 安装教程
android·ide·android studio
开发者阿伟2 小时前
Android Jetpack LiveData源码解析
android·android jetpack
weixin_438150992 小时前
广州大彩串口屏安卓/linux触摸屏四路CVBS输入实现同时显示!
android·单片机
CheungChunChiu3 小时前
Android10 rk3399 以太网接入流程分析
android·framework·以太网·eth·net·netd
木头没有瓜3 小时前
ruoyi 请求参数类型不匹配,参数[giftId]要求类型为:‘java.lang.Long‘,但输入值为:‘orderGiftUnionList
android·java·okhttp
键盘侠0073 小时前
springboot 上传图片 转存成webp
android·spring boot·okhttp
江上清风山间明月4 小时前
flutter bottomSheet 控件详解
android·flutter·底部导航·bottomsheet
Crossoads6 小时前
【汇编语言】外中断(一)—— 外中断的魔法:PC机键盘如何触发计算机响应
android·开发语言·数据库·深度学习·机器学习·计算机外设·汇编语言