解决fir-cli上传apk报错问题(上)

一直在用fir.im作为测试APP分发,最近遇到了上传失败的问题,看看到底是什么原因导致的。

fir(<1.7.0) 上传报错,且无法正确获取APP姓名和icon等
fir(>=1.7.0) 上传正常,但无法正确获取APP姓名和icon等

fir(1.7.0以下) 上传报错,日志如下

fir p /Users/Jenkins/Home/workspace/Android/Prod/app/build/outputs/apk/Release/app-release.apk -T tokentokentokentokentokentoken -Q
undefined method `attributes' for nil:NilClass
/Library/Ruby/Gems/2.3.0/gems/ruby_android-0.7.7/lib/android/manifest.rb:222:in `label'
/Library/Ruby/Gems/2.3.0/gems/ruby_android-0.7.7/lib/android/apk.rb:176:in `label'
/Library/Ruby/Gems/2.3.0/gems/fir-cli-1.6.12/lib/fir/util/parser/apk.rb:27:in `basic_info'
/Library/Ruby/Gems/2.3.0/gems/fir-cli-1.6.12/lib/fir/util/parser/apk.rb:17:in `full_info'
/Library/Ruby/Gems/2.3.0/gems/fir-cli-1.6.12/lib/fir/util/info.rb:34:in `apk_info'
/Library/Ruby/Gems/2.3.0/gems/fir-cli-1.6.12/lib/fir/util/publish.rb:13:in `publish'
/Library/Ruby/Gems/2.3.0/gems/fir-cli-1.6.12/lib/fir/cli.rb:118:in `publish'
/Library/Ruby/Gems/2.3.0/gems/thor-0.20.3/lib/thor/command.rb:27:in `run'
/Library/Ruby/Gems/2.3.0/gems/thor-0.20.3/lib/thor/invocation.rb:126:in `invoke_command'
/Library/Ruby/Gems/2.3.0/gems/fir-cli-1.6.12/lib/fir/cli.rb:183:in `invoke_command'
/Library/Ruby/Gems/2.3.0/gems/thor-0.20.3/lib/thor.rb:387:in `dispatch'
/Library/Ruby/Gems/2.3.0/gems/thor-0.20.3/lib/thor/base.rb:466:in `start'
/Library/Ruby/Gems/2.3.0/gems/fir-cli-1.6.12/bin/fir:8:in `'

查看源码
https://github.com/FIRHQ/fir-cli

/Library/Ruby/Gems/2.3.0/gems/fir-cli-1.6.12/lib/fir/util/parser/apk.rb:27:in `basic_info'

fir官方处理办法:rescue捕获错误,不抛出异常
这样但导致应用名称,icon等信息获取不到,解决办法并不完美,有没有更好的解决办法呢?

//fir
//## 更新记录
//  - (1.7.0) 过期了ipa_build 功能, 增加了对 android manifest instant run 的兼容
def fetch_label
  @apk.label
rescue NoMethodError
  nil
end

有没有更好的办法,继续挖
fir-cli引用了ruby_android-0.7.7库

查看源码
ruby_apk

/Library/Ruby/Gems/2.3.0/gems/ruby_android-0.7.7/lib/android/manifest.rb:222:in `label'

通过代码定位attributes

def label(lang=nil)
  label = @doc.elements['/manifest/application'].attributes['label']
  ...
end

@doc.elements['/manifest/application'] 为nil

看到这里,就需要清除manifest文件结构了,
参考https://bbs.pediy.com/thread-194206.htm

还要了解下Big Endian 和 Little Endian
参考https://blog.csdn.net/sunshine1314/article/details/2309655

image.png

定位到https://github.com/SecureBrain/ruby_apk/blob/master/lib/android/axml_parser.rb

通过解析文件数据,发现

//通常的结构如下
TAG_START_DOC

TAG_START

TAG_START
TAG_END

TAG_START
TAG_END

TAG_END

TAG_END_DOC

出问题的apk解析如下

TAG_START

TAG_START
TAG_END

TAG_START_DOC
TAG_START
TAG_END
TAG_END_DOC

TAG_START
TAG_END

...
TAG_END_DOC

此处出现了多个TAG_END_DOC

再来看源码,当遇到TAG_END_DOC就break终止了遍历,导致文件解析终止,也就无法解析到label等信息了。
尝试注释掉break,果然信息就可以正常解析了。

代码如下
https://github.com/sparkrico/ruby_apk

...
when TAG_END
    @parents.pop
when TAG_END_DOC
    //break
when TAG_TEXT
...

虽然解决了问题,但仍有不解之处,为何这个apk包有多个TAG_END_DOC?等下一篇找到这个答案

参考资料
Ruby String#unpack

你可能感兴趣的:(解决fir-cli上传apk报错问题(上))