V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Moyudawang
V2EX  ›  Android

Android 项目多个 Jar 包有命名空间冲突,有办法解决吗?

  •  
  •   Moyudawang · 178 天前 · 2798 次点击
    这是一个创建于 178 天前的主题,其中的信息可能已经有所发展或是发生改变。

    简单来说,同一个芯片的 SDK 被两个硬件组装厂家做了封装,我们的项目添加两个 Module 分别引用两个厂家封装后的 SDK(jar 、so),然后他们引用的芯片 SDK 就出现命名空间冲突了,而且他们用的芯片 SDK 版本还不一样,让厂家修改也不现实。
    现在就一直报错几个 Module 引用的 Jar 文件中有相同的内容,
    尝试把 Module 编译成 dex 动态加载,可是 dex 不能把 jar 和 so 打包进去,
    有没有大佬遇到过这种问题?望赐教

    38 条回复    2021-04-22 11:59:39 +08:00
    HongJay
        1
    HongJay   178 天前
    jar 不能编辑么。gradle 不是有排除语法么
    Moyudawang
        2
    Moyudawang   178 天前
    @HongJay 厂家的 SDK,不能编辑,因为用的版本不同,也不能排除
    xne110
        3
    xne110   178 天前
    如果就是个 Jar 的话,我倒是遇到过,我是直接用 zip 打开 Jar 把里面重复的东西直接删了 ,在导入就 ok 了
    Moyudawang
        4
    Moyudawang   178 天前
    @xne110 是硬件厂家引用了芯片厂家的 so 和 Jar,我们再引用硬件厂家的 Jar
    Moyudawang
        5
    Moyudawang   178 天前
    @xne110 而且他们用的芯片 Sdk 版本也不一样,直接删除不行
    wsxyeah
        6
    wsxyeah   178 天前 via iPhone
    改 bytecode,参考下 Android X 的做法
    cache
        7
    cache   178 天前
    我记得有个工具专门干这个事
    好像叫 jarjar
    xne110
        8
    xne110   178 天前
    就是有两三方包里引用了 同一个不同版本的三方包 两个直接删了,在自己项目里引用那个相同三方包 不就好了,如果他们混淆了 那就没办法了 ,我可能想的比较简单哈
    Moyudawang
        9
    Moyudawang   178 天前
    @wsxyeah 看一眼头大,慢慢研究一下
    @cache 我去试试
    @xne110 不同版本不一定向下兼容,命名一样,实现不一定一样
    actar
        10
    actar   178 天前
    你们是多种设备吗,每种设备使用不同的 SDK 。如果是这样的话,可以考虑多维度打包。每种设备只打入自己需要的包。关键字:flavorDimensions,productFlavors 。这样每种设备打出来的包是不一样的。缺点就是每一种设备都会打一个包,后续更新会需要维护多种设备的安装包。但是打包的时候会将多种设备的安装包同时打出来,不需要一个一个的打包。
    Moyudawang
        11
    Moyudawang   178 天前
    @actar 是的,适配多种设备,现用的也是这种办法,不过还是想只打包到一个 App 里,这样发布到商店也简单点
    wms
        12
    wms   178 天前
    把两个 SDK 用到的部分做成两个独立的服务, 主 APP 去跟这个两个服务通信
    Moyudawang
        13
    Moyudawang   178 天前
    @wms 那这两个服务不也是 App 启动的吗?现在编译通不过
    wms
        14
    wms   178 天前
    @Moyudawang 每个服务做一个 APK, 将三个 APK 打包成一个
    qwe520liao
        15
    qwe520liao   178 天前
    自己实现一个类加载器,加载不同 SDK 的 jar 可行性如何?
    就是说把厂商 SDK 的 jar 当做文件资源,不直接通过 gradle 打包,而是使用动态加载的方式载入需要的依赖。
    lawfun
        16
    lawfun   178 天前
    我觉得 @qwe520liao 说的可行。

    原文中的
    “尝试把 Module 编译成 dex 动态加载,可是 dex 不能把 jar 和 so 打包进去”
    可以把 so 都打进 主 APP 里。

    破解 jar 看源码,分析代码自己再实现下应该也行,不过可能会很费时。
    Moyudawang
        17
    Moyudawang   178 天前
    @wms 我还没试过这种,可以尝试一下
    @qwe520liao android 不能动态加载 jar 吧,只能先编译成 dex,第三方的 jar 我试了,编译成 dex 失败
    @lawfun 这个确实太费时了,因为厂家的 jar 包不止包含芯片的功能,还有厂家其他硬件的功能
    Moyudawang
        18
    Moyudawang   178 天前
    @cache 试了不行,Jar 里含有 Jni 方式加载 So 里的方法,所以命名空间不能改,
    mmrx
        19
    mmrx   178 天前
    @Moyudawang #14 的方案感觉可行,俩库的 apk 当做服务,用哪个装哪个 apk,然后用 AIDL 通信
    Moyudawang
        20
    Moyudawang   178 天前
    @mmrx 嗯,这个方式我需要花时间尝试一下
    kingiis
        21
    kingiis   178 天前
    看你说涉及到了 so 文件
    只能从源码层面 二次开发重新导出
    ParfoisMeng
        22
    ParfoisMeng   178 天前   ❤️ 1
    为啥让厂家修改不现实……
    p2pCoder
        23
    p2pCoder   178 天前
    maven 有 maven-shade,gradle 应该也有类似的工具
    Moyudawang
        24
    Moyudawang   178 天前
    @kingiis 没有源码,也没有这个能力
    @ParfoisMeng 因为让他们改过,有的改过也不行,有的说改不了,例如设备上的扫描头模块,很多组装厂家用的是一样的模块,但是为了连接他们的硬件又把扫描头的 sdk 封装了一层,要改大家全都一起改,太难了
    @p2pCoder 这还真不知道
    Moyudawang
        25
    Moyudawang   178 天前
    @ParfoisMeng 也怪我们采购了太多种类的设备,厂家提供的 sdk 都是大一统集成在一起的(RFID 、NFC 、条码扫描头),用起来是方便,冲突了就麻烦了
    xFrye
        26
    xFrye   178 天前
    没有包名检测的话,用 jarjar 就好,之前接一个第三方库也有个冲突的,给他命名空间改了
    Moyudawang
        27
    Moyudawang   178 天前
    @xFrye 有些方法是用 JNI 调用的,包名不能改
    2bab
        28
    2bab   178 天前
    1. 编译期解决的话,改命名空间最快
    2. 运行期解决的话,我依旧推荐动态加载 + 区分 Classloader,打不出 Dex 多半只是姿势问题,懒得研究的话,你可以直接建一个全空的 Android 工程,就引用这个 SDK,然后打了 APK 再把 Dex 给解压出来
    Moyudawang
        29
    Moyudawang   178 天前
    @2bab 嗯,我也觉得动态加载才是根本解决办法,我再研究研究 dex,多谢提醒
    ParfoisMeng
        30
    ParfoisMeng   178 天前
    @Moyudawang 如果是版本不统一属实难搞,可以和每个厂家约定统一使用最新稳定版本。然后都打 without 包( compileOnly )出来,你自己去依赖指定版本。
    littlewing
        32
    littlewing   178 天前
    @xne110 并不是,而是两个同名的包是不同功能,而且两个都需要用到
    limbo0
        33
    limbo0   177 天前
    maven-shade 正解, 把 A 厂家的包 shade 成 a.com.x.x , B 厂家的包 shade 成 b.com.x.x, build 完后引入你的项目, 互不影响
    Moyudawang
        34
    Moyudawang   177 天前
    @ParfoisMeng 有的设备都是几年前的了,厂家懒得搞

    @humpy 感谢指点
    @limbo0 谢谢 我会去试试
    lqw3030
        35
    lqw3030   177 天前 via iPhone
    独立类加载器加载
    Aviciii
        36
    Aviciii   177 天前
    我遇到过项目需要引用不同版本的 jar 包,最后用的 jarjar.jar 改的包名,然后把相关引用也改掉。不知道对你有没有帮助。
    gam2046
        37
    gam2046   177 天前
    假设 a.jar 包含 com.sample.MyClass,b.jar 包含 com.sample.MyClass,
    a 与 b 的功能完全不同,则可以考虑在编译时,不引入 a.jar 与 b.jar

    在使用期间(运行期间)通过不同的 ClassLoader 分别加载 a 与 b 即可
    对应到 Android 即 BaseDexClassLoader 。

    缺点是需要通过反射调用 a 与 b 的方法,当然如果他们有共同实现的接口或共同的父类,可以把这个这个接口或类放到主 jar 中,可以方便调用。
    Wounmay9976
        38
    Wounmay9976   177 天前 via Android
    感觉#14 是开发最优,要是能接受这样最简单快捷。
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1516 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 17:11 · PVG 01:11 · LAX 10:11 · JFK 13:11
    ♥ Do have faith in what you're doing.