[Calabash] Understanding calabash-android do resign apk

凌晨12:27

Understanding calabash-android do resign apk

瞭解 Calabash-android 是如何辦到 resign apk

故事是這樣開始的, 團隊使用 calabash-android 這套自動化測試工具也已經一年半了, 而一切都活在美好的烏托邦裡面…
一直到上個星期…
來自客戶的一個修改登入功能的需求, Android APP 需要箝入了一個 3rd Party 的 lib, 因此自動化測試的版本在每次 launch 的時候就會發生 Crash !!!!

Crash !!

Crash !!

Crash !!

換句話說, 這件事對我們團隊來說就變成一件很緊急的事情了. 至於小弟我呢? 因為跟這個工具也有點感情了, 所以就跳下來看問題啦. (非常感謝 Developer 傾囊相授啊~)
在調查問題的過程中, 發現一件有趣的事情, 就是每次 calabash-android 做完 resign 之後, apk 檔案的 size 都會變小, 也就是說變成一個新的 apk 了.
calabash-android resign < apk_path >
李組長眉頭一皺, 發現案情不單純!



首先先了解一下 Andriod 是怎麼做打包的吧.
Android應用使用的 APK 文件就是一個帶簽名信息的 zip 文件, 根據 zip 文件格式規範, 每個文件的最後都必須有一個叫 Central Directory Record 的部分, 這個CDR的最後部分叫「End of Central Directory Record」, 這一部分包含一些元數據, 它的末尾是 zip 文件的注釋. 注釋包含 Comment Length 和 File Comment 兩個欄位. 前者表示注釋的長度, 後者是注釋的內容, 正確修改這一部分不會對 zip 文件造成破壞, 利用這個欄位, 我們可以添加一些自定義數據.

接者, 我們就直接來看 resign 的 code:
../lib/calabash-android/helpers.rb:112

def resign_apk(app_path)
  Dir.mktmpdir do |tmp_dir|
    log "Resign apk"
    unsigned_path = File.join(tmp_dir, 'unsigned.apk')
    unaligned_path = File.join(tmp_dir, 'unaligned.apk')
    FileUtils.cp(app_path, unsigned_path)
    unsign_apk(unsigned_path)
    sign_apk(unsigned_path, unaligned_path)
    zipalign_apk(unaligned_path, app_path)
  end
end
calabash-android 會透過 aapt 把 META-INF/foo/bar 下面的檔案 remove 掉.
aapt remove < apk_path > xxxx
緊接著, 再透過 jarsigner 把 debug.keystore 的簽章進去 app.
jarsigner, ‘-sigfile’, ‘CERT’, ‘-sigalg’, signing_algorithm, ‘-digestalg’, digest_algorithm, ‘-signedjar’, dest_path, ‘-storepass’, password, ‘-keystore’, location, apk_path, keystore_alias
最後, 就會再用 zipalign 重新打包一個 apk.
zipalign -f 4 “#{inpath}” “#{outpath}

通常 calabash-android 這時會拿一個沒有 sign 過的 test_server.apk 做一次 resign 的動作, 目的是為了讓待測試的 apk 與 test_server.apk 的簽章對齊, 也就是為什麼 resign 後會產生一個新的 apk.
所以知道這一切之後, 就突破盲腸啦!! 為什麼 APP 在 launch 的時候會 crash 呢? 因為新箝入了一個 3rd Party 的 lib 在 init 時會做 security checked, 只要發現跟當初 Android Studio sign 的 key 不同就會吐 exception!
因此, 解法變得很簡單, 就是把 debug key 跟 calabash resign 時的 key 放成同一把就行了. 結案! 打完收工!!
結論: 沒事別亂用不安全的鑰匙

You Might Also Like

0 意見