有关 Android Studio 重复引入包的问题和解决方案
虽然相同包名相同类名的文件在不同 SDK 中出现的概率极低,但是一旦出现,处理起来就比较棘手。最好的解决方案就是联系提供 SDK 的技术人员反映问题,让其通过修改源码重新打包一个新的 Jar 包。
还有一个解决办法就是,重新命名 Jar 包里的包名或者文件名。网上也有一个工具:jarjar.jar,可以帮助我们重命名包名和文件名,以及 Jar 包中的相关代码引用路径。参考地址如下:
- GitHub 源码:https://github.com/shevek/jarjar
- Jar 文件下载:https://code.google.com/archive/p/jarjar/downloads
该工具提供有多种使用方式,最简单实用的就是通过命令行使用。举个例子,打开命令行工具,执行:
作者:唠嗑008
链接:https://www.jianshu.com/p/dd5d4fda1df8
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
随着产品功能需求的增加,我们开发的安卓项目不得不入引入越来越多的第三方库。这些三方库可能以 Jar 包的形式放置在 libs 目录下,可能以 Gradle 远程依赖的形式下载引入,也可能是以 Library Module 的形式放置在工程目录下,等等。
随之而来的问题是,复杂的依赖关系很可能导致重复引入包的问题。比较常见的使用场景就是 support-v4 包的重复引入。这样就会导致,执行 Run 操作打包生成 Apk 文件时出现类似这样的 DexException 错误提示,导致编译失败:
Error:Execution failed for task ':app:transformClassesWithDexForDebug'.
> com.android.build.api.transform.TransformException:
com.android.ide.common.process.ProcessException:
java.util.concurrent.ExecutionException: com.android.dex.DexException:
Multiple dex files define Landroid/support/v4/app/ActivityCompatHoneycomb; 有多种使用场景会出现这种问题。根据解决方案的不同,大体上可以分为两种:本地 Jar 包重复嵌入和 Gradle 远程重复依赖。 第一种,比较好理解。比如 app module 与 library module 各自 libs 目录中嵌入了相同的 Jar 包。这种情况也比较好解决,只需要将 app module 下的重复 jar 包删除即可。 第二种,稍微复杂一点。比如对于 Gradle 远程依赖的两个第三方库,他们内部同时依赖相同的另一个辅助第三方库。这个时候我们就没办法像第
一种情况那样手动删除本地文件。好在 Gradle 插件提供了相应的解决方案,即使用 exclude 语法,如: compile 'com.yifeng.example:example-1:1.0'
compile ('com.yifeng.example:example-2:1.0') {
exclude group: 'com.android.support', module: 'support-v4'
}
如例子中所示,远程依赖的第三方库 example-1 与 example-2 内部同时引入 support-v4 包,那么只需要在其中一个的引入地方添加 exclude 语句,根据 group 和 module 过滤规则,将相同引入的 v4 包剔除在外即可。
当需要在一个依赖中去除多个递归依赖项时,可以使用多条 exclude 语句,比如:
compile ('com.wdullaer:materialdatetimepicker:3.2.2') {
exclude group: 'com.android.support', module: 'support-v4'
exclude group: 'com.android.support', module: 'design'
}
还有一种更简单的写法,使用 Groove 语言的循环语句,模板如下(同样适用于 module 规则):
compile() { dep ->
[group1, group2].each{ group -> dep.exclude group: group }
}
对于上面的例子,便可以改造成:
compile() { dep ->
['support-v4', 'support-v13', 'design'].each{ module -> dep.exclude module: module }
}
以上两种场景算是比较好处理的。还有一种特殊情况,就是不同第三方库内部出现相同包名相同文件名的 java 类。这种情况出现的概率很低,但是不幸的是我在工作中就遇见过。
当时项目中引入的 友盟统计 和 移动统一认证 的 SDK 出现重复引入问题,执行 Run 操作编译打包时出现 duplicate entry 错误,如图:
通过错误提示,很容易就找到错误出处,我们看下两个 SDK 中的 jar 包源码:
虽然相同包名相同类名的文件在不同 SDK 中出现的概率极低,但是一旦出现,处理起来就比较棘手。最好的解决方案就是联系提供 SDK 的技术人员反映问题,让其通过修改源码重新打包一个新的 Jar 包。
还有一个解决办法就是,重新命名 Jar 包里的包名或者文件名。网上也有一个工具:jarjar.jar,可以帮助我们重命名包名和文件名,以及 Jar 包中的相关代码引用路径。参考地址如下:
- GitHub 源码:https://github.com/shevek/jarjar
- Jar 文件下载:https://code.google.com/archive/p/jarjar/downloads
该工具提供有多种使用方式,最简单实用的就是通过命令行使用。举个例子,打开命令行工具,执行:
java -jar jarjar-1.4.jar process rule.txt example.jar example_output.jar
其中,rule.txt 是包含重命名规则的文件,内容如下:
rule p.rn.asm.** com.yifeng.example.@
我们看一下重命名前后 Jar 包内容的代码对比图:
可以看到,不仅包名改变,Jar 包中的相关类引用路径也自动改变。这种 Jar 包重命名的方式虽然能解决重复引入包的问题,但不是长久之计,需要后续持续关注 SDK 的升级替换。
不同 Jar 包包含相同文件(路径也相同)的情况还有一种,就是 duplicate files 错误。多个 Jar 包包含重复的文件。这种情况在网上看到过,出自 StackOverFlow,错误提示类似:
Error:duplicate files during packaging of APK E:\Code\iDoc\app\build\outputs\apk\app-debug-unaligned.apk
Path in archive: META-INF/license.txt
Origin : E:\Code\iDoc\app\libs\spring-core-3.1..RELEASE.jar
Origin : E:\Code\iDoc\app\libs\spring-web-3.1..RELEASE.jar
You can ignore those files in your build.gradle:
android {
packagingOptions {
exclude 'META-INF/license.txt'
}
}
可以看到,解决方案已经在错误提示中有给出,使用 packagingOptions 配置的 exclude 语句删除重复文件即可,比如:
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
}
最后再补充一点,关于 Gradle 依赖的 Scope 问题。通常依赖某个第三方库我们使用的都是 compile 关键字,实际上,还有一个 Provided 关键字偶尔也会用到。
打开 Project Structure,查看 Modules 的 Dependencies 内容时,可以看到每一个依赖项的右边有个 Scope 选项:

有关 Android Studio 重复引入包的问题和解决方案的更多相关文章
- Android Studio导出Jar包
这篇博客将介绍一下如何用Android Studio导出jar包,希望能给大家带来帮助. 首先需要修改build.gradle文件,在Android Studio中会显示多个build.gradle文 ...
- Android Studio没有导包快捷键怎么办
Android Studio没有导包快捷键,那怎么办呢? 在使用Eclipse开发Android应用时,开发者往往会使用Shift+Ctrl+O快捷键来快速导入所有的包,和移除未使用的包.但这个快捷键 ...
- android studio 自动导入包
android studio 自动导入包 一.Android studio 的导单个包的快捷键是Alt+Enter (需要选中要导入包的类名再按快捷键才起作用): 二.Android studio 可 ...
- android studio生成aar包
android studio生成aar包并在其他工程引用aar包 http://blog.csdn.net/getchance/article/details/47257389 用Android st ...
- Android Studio V4 V7 包冲突的问题
最近被包冲突的问题搞奔溃了,特别是V4,V7 V4和V7包冲突的解决方式就是!版本要一致!! 比如我的一个项目中应用本来是这样引用包的 compile 'com.android.support:sup ...
- Android Studio 如何引入.jar文件和.so文件?
最近刚从Eclipse投入Android Studio的怀抱,可是在开发一个地图有关的应用,添加高德地图API的.jar和.so库文件时,遇到了问题.在Eclipse中只要简单地复制粘贴就可以了,但是 ...
- android studio 使用jar包,arr包和怎么使用githup开源项目中的aar包或module
我这里的android studio的版本是2.2.3版本 一.现在大家都用android studio了,就有人问怎么使用jar包 其实使用jar包比较简单 直接吧jar放入工程的app目录下的li ...
- android studio 生成aar包并在其他工程引用 (导入)aar包
1.aar包是Android studio下打包android工程中src.res.lib后生成的aar文件,aar包导入其他android studio 工程后,其他工程可以方便引用源码和资源文件 ...
- Android Studio导出Jar包并混淆
在Android Studio中,自带反编译查看class文件,如果没有混淆的话,class文件跟java文件基本没有区别了,为了保护,还是混淆的好. 网上看了不少资料,都是直接下载proguard额 ...
随机推荐
- Jenkins配置项目
前提:服务器上部署了jenkins+Tomcat,并且安装了所需插件 1.新建项目 -- 项目配置 2.配置git地址 出现上述错误是因为该git地址,在jenkins服务器上无权限访问.在git上开 ...
- 如何在Ubuntu 14.04上利用jexus搭建支持php+mysql数据库的网站服务
准备部分:sudo apt-get update sudo apt-get install unzip -y第一部分:安装jexus 在终端运行以下命令 cd /tm ...
- shell 终端terminfo命令 tput
tput命令 tput 可以更改终端功能,如移动或更改光标,更改文本属性,清除终端屏幕的特定区域等. 光标属性 在shell脚本或命令行中,可以利用tput命令改变光标属性. tput clear # ...
- IDEA快捷键--与Eclipse快捷键的对比--IDEA快捷键设置成Eclipse默认快捷键
部分内容转载于:http://blog.csdn.net/dc_726/article/details/9531281 IntelliJ Idea 常用快捷键列表 Ctrl+Alt+t 选择代码块 t ...
- NIO基础之同步、异步、阻塞、非阻塞
这里区分几个概念,也是常见但是容易混淆的概念,就是标题中的同步.异步.阻塞.非阻塞. 一.同步与异步 同步与异步,关心的是消息通信的机制.也就是调用者和被调用者之间,消息是如何进行通知的.如果是调用者 ...
- 滚动条事件window.onscroll
例:统战滚动条位置随高度变化 // 答题卡位置随滚动条变化 window.onscroll = function(){ var a = document.documentElement.scrollT ...
- 读书笔记(05) - 事件 - JavaScript高级程序设计
HTML依托于JavaScript来实现用户与WEB网页之间的动态交互,接收用户操作并做出相应的反馈,而事件在此间则充当桥梁的重要角色. 日常开发中,经常会为某个元素绑定一个事件,编写相应的业务逻辑, ...
- 【Java初探实例篇01】——Java语言基础
示例系列,将对每节知识辅以实际代码示例,通过代码实际编写,来深入学习和巩固学习的知识点. IDE:intellij IDEA: 语言:Java 本次示例:Java语言基础知识的应用. 创建包day_4 ...
- 到网上收集了一个“高大上”的CSS3登入表单和大家分享一下
要求 必备知识 基本了解CSS语法,初步了解CSS3语法知识. 开发环境 Adobe Dreamweaver CS6 演示地址 演示地址 预览截图(抬抬你的鼠标就可以看到演示地址哦): 制作步骤: 一 ...
- 编码算法-Base64
Base64是一种编码算法,因为这种算法只支持64个[可打印字符],所以叫做Base64. 为了保证所输出的编码位可读字符,Base64制定了一个编码表,以便进行统一转换.编码表的大小为2^6=64, ...