読者です 読者をやめる 読者になる 読者になる

リソース差替&apk再署名でハマったメモ

意識が高い方々は殆どMacerなので気にもしないと思うんですが

実は、Windowsで デフォルト状態でgradle実行すると

  • CPUが高い位置で張り付く
    • 重くて操作できない
    • buildも結果的に時間かかる

みたいな話になる。

TLでよくAS重い/ビルド遅い言ってるのはWinユーザがほとんどじゃないかなーと思う。

まあそこら編の話は主旨でないので、末尾の追記で別記載する

実は仕事で

  • 鯖側が未完成なので通信疎通ができない
  • assetsに通信キャッシュデータみたいなの持たせてテスト
    • テスト項目によりそれを何度も書き換えてテスト
  • 毎回 gradle assembleDebug してると死ぬ

ということで

  1. aapt removeで assets/testdata/hoge.txt 削除
  2. aapt add で assets/testdata/hoge.txt を再追加
  3. jarsignerで再署名

でビルドしないで効率をあげようとしたわけだが、apkが署名エラーが出る・・

なお話か?と思って調べたが、build.gradleでdebug時も
debug.keystoreを明示的に指定してるのでどうも違う。

で結論から言うと

  • gradle task で作られる署名
META-INF/MANIFEST.MF
META-INF/CERT.SF
META-INF/CERT.RSA
  • jarsignerで作られる署名 *1
META-INF/MANIFEST.MF
META-INF/ANDROIDD.SF
META-INF/ANDROIDD.RSA

でそのまま実行すると SF/RSAが上書かれず複数保持されるわけで
署名エラーになるわけだ。。

でこれに対応するには署名データを一回消さないと駄目と。。

で結論的に作ったbat

  • mod_assets.bat
set APK_FILE=hoge.apk
set DATA_FILE=assets/testdata/hoge.txt

rem ===署名情報を消す===
aapt remove -v %APK_FILE%  META-INF/MANIFEST.MF
aapt remove -v %APK_FILE%  META-INF/CERT.SF
aapt remove -v %APK_FILE%  META-INF/CERT.RSA
aapt remove -v %APK_FILE%  META-INF/ANDROIDD.SF
aapt remove -v %APK_FILE%  META-INF/ANDROIDD.RSA

rem ===テストデータの差し替え===
aapt remove -v %APK_FILE% %DATA_FILE%
aapt add -v %APK_FILE% %DATA_FILE%

rem ===対話設定済み再署名===
echo android|jarsigner -sigalg SHA1withRSA -digestalg SHA1 -keystore debug.keystore -v %APK_FILE% androiddebugkey

理想を言えば

  • META-INF/*.SF

みたいに消せればいいんですけどね
ディレクトリ消去自体も上手く出来なかったorz

なんかうまい方法がないのかな。。

apk のinstall自体は勿論pecoでやります。じゃないとgradle buildの出力先の階層深くて死ぬよね。。(苦笑



追記)
windows環境で gradleでデフォルトだと CPUが張り付く/遅い問題

Windowsな業務用PCだと、この頃はやっと8Gマシーンが使えるようになったとはいえ

  • IS◎S関連で監視系のソフト/ウイルス駆除ソフト系が常に常駐してる
    • ユーザ権限しかないので最新のJDKとか入れられない 処も。。 *2
  • windowsなので基本Outlook等のメーラは常駐して最新情報に敏感にしておけといわれる
  • Excel/wordの仕様書を開きながら作業 *3

な状況でデフォルト状態だと、IDE開発環境とかまともに動かせない感じじゃないかなーと思う昨今だったりします *4

  • ADT/ASが重い
    • => Xms1024m/Xmx1024m に初期メモリ変更しましょう

というノウハウが必ずググるとまず出てくるわけで、これを修正してしまうと
ますます足りない。*5

下手に確保しようとするより、スワップするほうが激遅になります。
その状態であれば、小さめに設定して動かすほうがまだ速い状態です

  • gradle.properties
#org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.jvmargs=-Xms512m  -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

org.gradle.workers.max=4 //☆
org.gradle.java.home=c:/opt/jdk8 //☆☆
  1. ☆ 自分が実行した体感だと512M/スレッド数4ぐらいが限界かと
    1. メモリに関しては逆に小さすぎるとコンパイル自体ができない状態
    2. スレット数4はCPUコア数と同じぐらいが基準

> Runtime.getRuntime().availableProcessors() 辺りで算出も可能

  1. org.gradle.parallel=true とかはfalseにするとandroid gradle pluginのチェック処理でエラーにされます
  2. org.gradle.daemon=trueをfalseにするのはjenkinsビルドでは必須です。*6
  1. ☆☆ 最新のjava8はJRockitと統合されて従来より2−3割速いので変更する価値はあり。ただその場合は org.gradle.jvmargsは下記のように書き換えたほうが良い *7
org.gradle.jvmargs=-Xms512m  -Xmx512m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
    1. インストーラでJDK8がいれられれない環境の場合は Windows版JDKをインストールせずに使用する。 - Qiita を参考に導入
  • build.gradle
android{
   dexOptions{
       incremental = true
       preDexLibraries = true
       jumboMode = true
       threadCount=4 //☆追加
   }
}

*1:alias名.SF/alias名.RSA という仕様がでてて androiddebugkey.SF とかだと思ってたが8文字で省略される仕様の話を見つけるまで、なんでーと悩んでたのは内緒><

*2:レジストリ弄るAdmin権限が必要なソフトとか。。

*3:複数開きながらがデフォなので重さ倍増。。

*4:iOS開発者はMacノートと2台持ちなので全然快適でしょうが。。。

*5:よく2048mな記述が載ってたりしますが、Windowsだと一つのアプリにそんなに確保できないんじゃないかな? JDK/eclipseが古いと特に・・

*6:gradlew cleanが必須なのと、常駐ビルド自体が意味が無い&下手するとビルドキャッシュ不正でdeamonプロセスがだんまりしてビルド失敗することがあるからです

*7: PermSize =>MetaspaceSize に変更