概要
Android開発でGoogleMapを導入した時に、
MapViewがクラッシュ・フリーズすることがありました。
クラッシュログは、出力されたりされなかったり...
その時の対応方法を書きます。
問題が起きた時のパターン
- 画面がフリーズする → 応答なしダイアログ表示
- アプリが強制終了する(強制終了ダイアログ表示)
- アプリが強制終了する(強制終了ダイアログが表示されない)
問題が起きた時のログ
強制終了のダイアログが表示されるパターンでのみ、Logcatのエラーログを確認できました。
根気よく、再現を試してください。
!!! FAILED BINDER TRANSACTION !!! (parcel size = 3124236)
W/art: Suspending all threads took: 5.218ms
E/AndroidRuntime: Error reporting crash
android.os.TransactionTooLargeException: data parcel size 3124236 bytes
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:503)
at android.app.ActivityManagerProxy.handleApplicationCrash(ActivityManagerNative.java:4425)
at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:90)
at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)
原因は...情報量が多すぎる!?
TransactionTooLargeException
ということなので、
大きすぎるデータの受け渡しがされているらしい。。
GoogleMapの内部で。。。
よくわからんけど。
確かに、タブレットのNexus7だと再現率がめっちゃ高い。
しかも、なぜか東京駅周辺で発生する。。
なんかそんな気がするけど、本当に!?w
対応方法
下記のように、インドアマップを取得しないようにしました。
根本解決ではないです。が、手元での再現は0になりました。
@Override
public void onMapReady(GoogleMap map) {
this.map = map;
this.map.setOnMarkerClickListener(this);
// 情報量が多すぎでMapViewが android.os.TransactionTooLargeException を吐いて
// 勝手にクラッシュする(Nexus7で再現)
// MapView内部処理なので何も手出しができなかったから、この設定で情報量を制限している
this.map.setIndoorEnabled(false);
最新のGoogleMapで再現してます
問題が発生していたアプリの開発環境です。
ちなみに、MapFragment,MapViewの両方とも再現してました。
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
minSdkVersion 15
targetSdkVersion 25
...
}
dependencies {
# 2017/4/1時点で最新
com.google.android.gms:play-services-maps:10.2.1
...
}
対応後の愚痴
この問題、一番凶悪だなーって思ったのが、AndroidのGoogleMapサンプルで再現しないんです。
それは、なぜか?サンプルはオーストラリアのシドニーあたりを参照しているから。
東京と比べてデータ量が少ないんだと思います。
サンプルプロジェクトで位置情報だけを東京に変更すると、同じ問題が再現しました。ぐぬぬ。
(知ってて隠してたんじゃないのか...Google様よ)
かなり手強い不具合でした。
これを読んで、同じ問題にぶち当たっている開発者を救えたら幸いです。