2017/10/27 shibuya.apk #19で発表したスライドです。 SmartNewsアプリについての簡単な紹介と、主にtargetSdkVersionを上げた時に遭遇した問題とその対応についての説明です。
SmartNews 5.0ちょっと苦労した話2017/10/27shibuya.apk #19SmartNews Inc.Hideo Ohashi
View Slide
About Me● Androidアプリエンジニア@スマートニュース株式会社● 2010年(Android 2.2 Froyoが出始めたあたり)からずっとAndroidアプリエンジニアしてます2
About SmartNews3
4
SmartNews 5.0● スライダーの導入● 一部マテリアルデザインっぽく● targetSdkVersionのバージョンアップv4.1.15 v5.0.5 5
v4.1.15 v5.0.56
ちょっと苦労したこと7
SmartNewsのtargetSdkVersion● 約2年ほど前からtargetSdkVersionが22(Android 5.1Lollipop MR1)のままだった● バージョンをあげよう8
SmartNewsのminSdkVersion● SmartNewsのminSdkVersionは8(Android 2.2 Froyo)○ SmartNewsユーザの過半数はAndroid 6.0以上○ 一方でAndroid 3.0以下のユーザも約1%ながら存在9
想定していなかったこと● targetSdkVersionを上げたらいろいろ起きました1. Support LibraryのminSdkVersionが92. Display size変更してもdensityが以前のまま3. Applicationクラスが呼ばれないことがある10
1.Support LibraryのminSdkVersionが9 (1)● compileSdkVersionとSupport Libraryのバージョンが違うとAndroid Studio上でエラー表示になる● Support Libraryのバージョンをあげるとビルドエラー○ > Manifest merger failed : uses-sdk:minSdkVersion 8 cannot be smallerthan version 9 declared in library [com.android.support:support-v4:25.3.1]● 24.2.0からAPI level 8以下はサポート外になってました11
1.Support LibraryのminSdkVersionが9 (2)● できることならminSdkVersionは8のままキープしたい● 幸いなことにがっつりSupport Libraryを使っていなかった● Support Librayへの依存を切り、必要なクラスを実装しました12
2.Display size変更してもdensityが以前のまま (1)● targetSdkVersionを上げると、Display sizeの設定を変えてもdensityが以前のままで計算されて文字などが意図しないサイズで表示されてしまうことがあった● API level 24以上だとDisplay sizeを変更してもプロセスは生き残ったままらしく、それが影響しているっぽい13
2.Display size変更してもdensityが以前のまま (2)● よく見ると問題が起きるActivityと起きないActivityがある● シンプルなサンプルアプリでは起きない● 諦めようかな14
2.Display size変更してもdensityが以前のまま (3)● View周りのソースコードを読んだりreflectionを使ってprivate memberの中身を覗いてみたりしたところ、TypedArray#mMetricsのdensityが変わっていなかった● そこからオブジェクトの所有関係を辿っていき、WebViewを生成していることがdensityが変わらなくなる条件の1つであることを突き止めました 15
2.Display size変更してもdensityが以前のまま (4)● 実際にWebViewの生成をやめてみると問題が起きなくなった● WebViewの生成をやめるわけにはいかないので、TypedArrayのキャッシュを追い出すworkaroudを入れることで対応しました16
2.Display size変更してもdensityが以前のまま (5)public class MyActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODE.N) {Resources res = getResources();for (int i = 0; i < 5; i++) {res.obtainTypedArray(R.array.dummy)}}super.onCreate(savedInstanceState);}}17
3.Applicationクラスが呼ばれないことがある (1)● targetSdkVersionをあげたものをリリースして1週間ほど経ったくらいに、1人のユーザから「アプリが起動できない」という報告が届く● Crashlyticsには特にそれらしきバグが見当たらない● そのときは再インストール&端末の再起動を案内し、現象が解決した18
3.Applicationクラスが呼ばれないことがある (2)● 数日後、別のユーザから同じような報告が届く● Google Developer Consoleを見てみると日に日に増えているクラッシュがあった● Applicationを継承したクラスのonCreate()が呼ばれていないと思われるようなクラッシュだった○ onCreate()でCrashlyticsの初期化を行なっているので、検出されないのも辻褄があう● ApplicationのonCreate()が呼ばれないことがある?19
3.Applicationクラスが呼ばれないことがある (3)● あった● 自動バックアップ処理が実行されるときはAndroidManifest.xmlにApplicationクラスを設定していても素のApplicationクラスが使われる○ https://android.googlesource.com/platform/frameworks/base/+/android-6.0.0_r7/services/core/java/com/android/server/am/ActivityManagerService.java#6070 LoadedApk.java20
3.Applicationクラスが呼ばれないことがある (4)● しかし自動バックアップのための何かをした覚えはない● targetSdkVersionを上げたことが影響してました21
3.Applicationクラスが呼ばれないことがある (5)● コマンドラインからのバックアップ実行とアプリ起動をぶつけてみる○ adb shell bmgr fullbackup ● クラッシュが発生し、同じコールスタックが取れた○ クラッシュ発生以降、普通に起動してもクラッシュが発生する状態になった(おそらくActivityManagerService側のフラグ管理がおかしくなったため)22
3.Applicationクラスが呼ばれないことがある (6)● 以前からallowBackup=”true”だったが特にバックアップ機能を意識して使ってはいなかったので、falseに変更した● クラッシュが落ち着きました23
いろいろありましたが無事解決できました24
ご静聴ありがとうございました25