这里记录的案例,虽说确实是编译原因导致的,但问题真正发生是在运行时。开发工具:Android Studio 3.4.1,运行环境:Android 5.1.1。
问题现象
话说为了选择个文件,使用了第三方库com.leon:lfilepickerlibrary:1.8.0
,由于这个库和原来的项目同时引用了com.android.support:appcompat-v7
,但版本不一致,可能出现Duplicate class的问题,所以,使用排除传递依赖项的方法,排除了这个库对com.android.support
的引用,关于Duplicate class的问题参考这里。在初始的build.gradle里具有这样的配置:
1 | compileSdkVersion 28 |
编译一切正常,安装到手机上运行并使用这个库提供的功能时,应用出现停止运行,查看logcat,具有如下内容:
1 | java.lang.RuntimeException: Unable to start activity ComponentInfo{.../com.leon.lfilepickerlibrary.ui.LFilePickerActivity}: android.view.InflateException: Binary XML file line #62: Error inflating class com.leon.lfilepickerlibrary.widget.EmptyRecyclerView} |
解决过程
-
从
ClassNotFoundException
看起,使用JadX反编译了生成的apk,发现com.leon.lfilepickerlibrary.widget.EmptyRecyclerView
确实存在于apk内,路径也完全一致,看来不是这个问题。 -
在网上搜索
Apk ClassNotFoundException
和Apk Error inflating class
看了一些相关的内容后,发现都和这里的不同。 -
不得已,回到项目重新思考引用这个库的方式,怀疑可能是依赖存在问题,于是做了以下尝试:
首先,删除了
exclude group: 'com.android.support'
这一段,这时,Android Studio会在implementation 'com.android.support:appcompat-v7:28.0.0'
这一行上会显示红色波浪线,鼠标点击后,即时提示告知:“All com.android.support libraries must use the exact same version specification (mixing versions can lead to runtime crashes). Found versions 28.0.0, 25.0.0.”。可见,这个第三方库引用了com.android.support 25.0.0
的版本。其次,根据提示,把
compileSdkVersion、targetSdkVersion、com.android.support:appcompat-v7
的版本都从28改到了25后,编译并运行,发现功能正常。 -
推断依赖存在问题,那么,
com.leon:lfilepickerlibrary:1.8.0
的依赖到底应该是怎样的呢?查看这个包的pom文件就可以知道了,在本地缓存里(一般是当前用户主目录的.gradle/caches目录下)搜索到对应的pom文件,查看依赖节具有如下内容:1
2
3
4
5
6
7
8
9
10
11
12
13
14<dependencies>
<dependency>
<groupId>com.android.support</groupId>
<artifactId>appcompat-v7</artifactId>
<version>25.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.android.support</groupId>
<artifactId>recyclerview-v7</artifactId>
<version>25.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies>这里的内容显示:除了
appcompat-v7
模块外,这个库还依赖于recyclerview-v7
模块,而使用exclude group: 'com.android.support'
排除了所有groupId是com.android.support
的模块。 -
了解了原因后,解决起来就简单了,
compileSdkVersion、targetSdkVersion、com.android.support:appcompat-v7
仍使用28版本,但是在build.gradle的dependencies节里增加一行implementation 'com.android.support:recyclerview-v7:28.0.0'
。这里,recyclerview-v7
的版本应当和appcompat-v7
的版本完全一致。最终,build.gradle中的dependencies按照下面的写法即可:
1 | dependencies { |
- 最后,这些模块都可以通过浏览https://maven.google.com找到,也可以在Android Studio中找到并添加,操作路径是:选中相应的Project,按F4打开Project Structure,点击左侧的Dependencies,然后添加Library Dependency,在出现的对话框中输入
com.android.support
并搜索,搜索结果出来后,选中recyclerview-v7
对应的版本即可添加,具体如下图:
除此之外,不直接添加对recyclerview-v7
的引用,而是仅排除可能产生冲突的模块也是可以的,使用exclude时指定module即可,在这里,就是如下列所示:
1 | implementation('com.leon:lfilepickerlibrary:1.8.0') { |
但是这会导致引用了不同版本的com.android.support
组的模块,因此,并不推荐这种方式。
Related Issues not found
Please contact @OakChen to initialize the comment