近期在用maven,遇到了一个问题,用maven打出的apk有问题无法启动,但是用idea打包的就是正常的。

日志中显示的问题是,一个apklib形式的依赖包中的一个资源出现了问题。反编译对比maven包和idea包,找到了问题所在。

假设: 主模块包名为com.android.main

apklib依赖包包名为com.android.apklib

出问题的资源(layout)名为MyView

问题: apk打包后apklib依赖包的资源文件会与主模块的资源整合到一起,依赖包引用资源实际上是在主模块的R文件中查找对应资源。

1)maven包中: 在com.android.main下的R文件中MyView的值为0x7f050001;而在com.android.apklib下的R文件中MyView的值为0x7f070001,而且程序内使用该资源时的索引也是0x7f070001。这样程序运行到这段代码时,会去主模块的R文件中找0x7f070001,然而主模块中0x7f070001对应的资源并不是一个layout,所以就会出错。

2)idea包中:俩个R文件中MyView的值相同,所以能够正确的找到资源,程序不会出错。

这样就知道了问题,但是问题是如何出现的?

经过对maven打印日志查看,整理了一个打包的过程如下:

1)将所有依赖包拷贝到项目 /target/unpacked-libs 下,整合资源文件,然后生成主模块和各依赖包的R.java等文件

2)编译class文件,包括刚才生成的对应包的R文件。注意:编译com.android.apklib下的java文件时,代码中对应资源的索引与(1)生成的com.android.apklib包下的R文件一致

3)生成dex

4)生成apk

(maven打包可以用"mvn clean package"即可。不过也可以像上面那样细分成四步"mvn clean android:generate-sources compile android:dex android:apk")

这样我们就注意到,虽然运行时依赖包会在主模块R文件中查找资源,但是编译时还是会根据自己包下的R文件来编译。

用maven只处理资源(mvn clean android:generate-sources),以便查看生成的R.java文件,发现问题产生的原因:

生成的R.java文件,主模块与依赖包是有冲突的,同一个资源对应不同的索引。这样编译的时候依赖包代码中的资源索引就是有问题的,就会导致问题的出现。那么说明maven在生成R.java文件时是有问题的。

继续查看maven打印日志,找到了生成R,java文件对应的日志部分,是执行了aapt的命令。如下:

aapt.exe package -f --no-crunch -I D:\AndroidSDK\sdk\platforms\android-16\android.jar -M D:\项目目录\AndroidManifest.xml -S D:\项目目录\res -S D:\项目目录\target\unpacked-libs/依赖包名/res -A D:\项目目录\target\generated-sources\combined-assets\assets -m -J D:\项目目录\target\generated-sources\r --output-text-symbols D:\项目目录\target --auto-add-overlay aapt.exe package --non-constant-id -m -J D:\项目目录\target\generated-sources\r --custom-package 主模块包名 -M D:\项目目录\target\unpacked-libs\依赖包名\AndroidManifest.xml -S D:\项目目录\target\unpacked-libs\依赖包名\res --auto-add-overlay -A D:\项目目录\target\unpacked-libs\依赖包名\combined-assets -I D:\AndroidSDK\sdk\platforms\android-16\android.jar;

第一个命令就是生成主模块R文件的,第二个命令则生成依赖包R文件。

(这里简单介绍一下命令的主要组成:“-m -J D:\项目目录\target\generated-sources\r”是R.java文件生成的路径;“-M D:\项目目录\AndroidManifest.xml”是获取包名;“-A D:\项目目录\target\generated-sources\combined-assets\assets”是assets目录;“-S D:\项目目录\res”是res目录,有依赖包的话有多个,并注意顺序;“--non-constant-id”生成的R.java文件中字段不是final类型;“--auto-add-overlay”资源文件自动覆盖)

查看发现主模块的R文件一切正常,那么就是第二条命令出的问题。由于自己之前没有研究过打包,对aapt命令很不熟悉,所以一时也不知道该怎么修改。经过在网上查找,慢慢熟悉这条命令每部分的作用。第二条命令仅仅是生成依赖包的R文件,并未与主模块进行关联,这样其实是单独生成的,所以会起冲突。修改很简单,如下:

aapt.exe package --non-constant-id -m -J D:\项目目录\target\generated-sources\r --custom-package 主模块包名 -M D:\项目目录\target\unpacked-libs\依赖包名\AndroidManifest.xml -S D:\项目目录\res -S D:\项目目录\target\unpacked-libs\依赖包名\res --auto-add-overlay -A D:\项目目录\target\unpacked-libs\依赖包名\combined-assets -I D:\AndroidSDK\sdk\platforms\android-16\android.jar;

多加了主模块的res进去,这样其实生成的依赖包R文件与主模块的是一摸一样的,里面包含了所有资源,并不仅仅是依赖包的资源。这样再编译就不会有冲突的现象。

但是这仅仅是在命令层面解决问题,maven打包使用的是android-maven-plugin(com.jayway.maven.plugins.android.generation2),上面的命令都是由这个插件来执行的。不过还好这个插件是开源的,在github上可以找到。在github上找到这个开源项目,找到对应部分的代码后发现构建的命令是正确的,原来已经有高手在5月中旬解决这个问题了。。。

原来是我的插件版本落后了,去中心仓库查看发现android-maven-plugin最新版本是3.9.0-rc.3,这个版本已经解决该bug了。更新一下打包测试,一切正常。

虽然最后只是更新一下版本就解决了,但是也学到了不少东西,熟悉了打包流程,另外有兴趣的话可以看看github上对应部分的代码,

maven(android-maven-plugin3.8.0)打包apk无法启动,apklib依赖包的资源索引出错(R文件与主模块冲突)问题解析相关推荐

  1. android服务器打包jar,Android Studio打包apk,aar,jar包方法

    文本我们将讲解android studio打包apk,aar,jar包的相关知识.apk包就是android系统的安装包,这里没什么好说的,aar包是android中独有的类库包,而jar包是java ...

  2. Android Studio 使用教程(5)---打包apk

    Android Studio 使用教程(5)---打包apk 本章节讲述使用Android studio 打包apk的过程 1.Build -> Generate Signed APK...,打 ...

  3. java 手动编译打包_Maven 手动添加第三方依赖包及编译打包和java命令行编译JAVA文件并使用jar命令打包...

    一,实例:新建了一个Maven项目,在eclipse中通过 build path –> configure path-.将依赖包添加到工程中后,eclipse不报错了.但是用Maven命令 mv ...

  4. servlet4.0.1与jsp2.3.3依赖包的导入

    servlet4.0.1与jsp2.3.3依赖包的导入 <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-a ...

  5. android studio关于命令行打包apk

    前言: 最近刚接触studio,由于项目需要打包apk,就尝试用命令行来进行打包.下面做一下总结: 第一:需要在studio项目中配置 signingConfigs { config { keyAli ...

  6. Android Studio创建签名文件,打包apk,多渠道打包

    如果这些内容可以帮到你是我的荣幸 1,点击标题栏上面的Build 2,再点击Generate Signed APK 3,如果已经有签名文件了,就直接用:如果第一次用就创建一个,点击Create new ...

  7. 【Android开发】jarsigner重新打包apk

    签名(sign):在应用程序的特定字段写入特定的标记信息,表示该软件已经通过了签署者的审核. 过程:使用私有密钥数字地签署一个给定的应用程序. 作用: 识别应用程序作者: 检測应用程序是否发生改变: ...

  8. 关于maven打包时,没有将依赖包打进来的问题

    开发了一个工具给第三方调用,采用maven父子模块的方式组织项目.打包后,发现缺少对应的class文件,导致无法使用. maven打包时,默认不会将第三方依赖包打进来.可以在pom.xml中添加mav ...

  9. ios自动化打包 替换icon 启动图 bid appname 额外资源

    ios自动化打包脚本 下载地址https://github.com/gwh111/package 打开后自行替换 icon 启动图 bid appname 额外资源 原理:最新的脚本还是一个个替换后再 ...

最新文章

  1. 第一篇:text preprocessing文本预处理
  2. NetScaler的部署实验之二NetScaler的传输环路值的设定
  3. Apache的443端口被占用解决方法
  4. 任务间资源共享问题示例
  5. 新手入门深度学习 | 3-3:神经网络层Layers
  6. linux 内存清理 释放命令,Linux系统中的内存清理和释放命令总结
  7. CentOS安装php mbstring的扩展
  8. CPU profiling
  9. codeforces contest 1140(D~G)
  10. 电商企业怎样用好大数据
  11. anaconda base环境_如何在最新版的Anaconda下安装Tensorflow 1.9
  12. 大话重构7:重构是一系列的等量变换
  13. 郑州it java_郑州Java网站开发
  14. iOS中 openGL常用函数记录(部分)
  15. lazada发货_Lazada 怎么发货:Lazada 订单发货流程
  16. APIO2010巡逻(树上带权直径)
  17. allow_pickle什么意思_如何修复草图算法中“当allow_pickle=False时无法加载对象数组”...
  18. 通信感知一体化概述(IMT-2030 6G)
  19. python 面向对象全面详解
  20. 高一 Unit2 动名词

热门文章

  1. OpenCV条码(6)简单实现
  2. 修改了一下voddown.py
  3. ARM开发软件及实用软件介绍
  4. Asp.net動態添加控件(转)
  5. Spring学习(八)AOP详解
  6. Conversations
  7. css教程–十步学会用css建站(全)
  8. webpack最简单的入门教程里bundle.js之运行单步调试的原理解析
  9. 玩转小程序转发——小程序探索
  10. Codepen 每日精选(2018-4-22)