昔対応した問題だったのだが、最近再度同じようなアプリを作成した時に忘れていてハマったので備忘を残しておく。
Google Maps Android API v2 で長時間同じ地図画面で待ち受けるようなアプリを作成する場合、地図を長時間触っていると StackOverflowError
で落ちる場合がある。
これが地図を拡大したりちょっとスクロールした際に突然落ちるのでプロダクションでこれが起きてしまうと「このアプリは地図をちょっと触っているだけで落ちる」という散々な評価をいただくことになるし、長時間触っていないと再現しないという関係上開発時に気づかないことが多い。
例えば以下のようなスタックトレースが吐かれる:
java.lang.StackOverflowError: at com.google.maps.api.android.lib6.gmm6.util.e.b(:com.google.android.gms.DynamiteModulesB@11746036:22)
at com.google.maps.api.android.lib6.gmm6.store.cache.s.a(:com.google.android.gms.DynamiteModulesB@11746036:8)
at com.google.maps.api.android.lib6.gmm6.store.n.a(:com.google.android.gms.DynamiteModulesB@11746036:49)
at com.google.maps.api.android.lib6.gmm6.indoor.o.a(:com.google.android.gms.DynamiteModulesB@11746036:80)
at com.google.maps.api.android.lib6.gmm6.indoor.o.a(:com.google.android.gms.DynamiteModulesB@11746036:70)
...
これは Google Maps Android API v2 の「インドア表示」で起こる。 ほとんどの要件ではインドア表示など不要だと思われるので、以下のように設定で OFF にすれば起きなくなるので地図を使用する画面では機械的に以下を入れてしまっていいのではないかと思う:
mapFragment.getMapAsync { it.isIndoorEnabled = false } // インドア表示 OFF
mapFragment.getMapAsync { it.uiSettings.isTiltGesturesEnabled = false } // チルト操作 (傾けて地図を 3D 表示) OFF
2 番目の「チルト操作 OFF」も可能であれば設定した方がいい。
確かこれも ON にしていると OutOfMemoryError
で落ちることがあった気がした (確証とれず)。
ちなみに OutOfMemoryError
で落ちる件に関しては Stack Overflow に書かれている通り AndroidManifest.xml
に largeHeap = true
を宣言するなり適切なタイミングで System.gc()
や GoogleMap.clear()
を呼ぶ必要が出てくるだろう。