アプリが起動し続けない
アプリが起動直後、またはセッション中にクラッシュし、Androidが画面にダイアログを表示します:「アプリ」が繰り返し停止しています。ユーザーがOKをタップする。また落ちる。再びOKをタップする。深夜2時にSlackの通知が届く。
このダイアログは、AndroidランタイムがハンドルされていないExceptionまたはANR(Application Not Responding)を検知してプロセスを強制終了したときに表示されます。原因は、キャッシュの破損からOOMキル、不完全なAPKインストールまで多岐にわたります。まったく異なる3つの問題が、同じダイアログを表示させるのです。だからこそ、最初のステップは必ずログを読むことです。
クイックデバッグ:まずクラッシュログを読む
設定はまだ触らないでください。デバイスを接続し、USBデバッグを有効にして、logcatを取得します。答えはたいてい最初の10行に書いてあります。
# Connect device, enable USB debugging, then:
adb logcat -d | grep -E "(FATAL|AndroidRuntime|E/ActivityManager)" | tail -50
# If the app crashes on launch, watch live:
adb logcat *:E | grep -v "^-"
典型的なクラッシュはこのように見えます:
E AndroidRuntime: FATAL EXCEPTION: main
E AndroidRuntime: java.lang.NullPointerException: ...
E AndroidRuntime: at com.yourapp.MainActivity.onCreate(MainActivity.java:42)
このスタックトレースは正確な行番号を示しています。OutOfMemoryErrorとNullPointerExceptionでは対処法がまったく異なります。このステップを飛ばさないでください。
ANRは別途確認する
# ANR traces on older Android versions:
adb pull /data/anr/traces.txt .
# On Android 11+:
adb bugreport bugreport.zip
unzip bugreport.zip && grep -r "ANR" bugreport/
修正1:アプリのキャッシュとデータをクリアする
キャッシュの破損は最も一般的な原因です。特にOTAアップデート後や、古いバイトコードが残った状態でインストールが中断された場合に発生しやすくなります。
# Via ADB — this clears BOTH cache and user data:
adb shell pm clear com.example.yourapp
# To clear cache only (non-root), use the UI:
# Settings → Apps → [App Name] → Storage → Clear Cache
注意:pm clearはログインセッションや設定を含むすべてのデータを消去します。完全にクリーンな状態にしたいときに使用してください。ユーザーデータを保持したい場合は、上記のUI操作を使用してください。
**確認:**アプリを起動します。クリーンに起動した場合、原因はキャッシュでした。まだクラッシュする場合、ログには古い状態に隠されていない新しいエラーが表示されます。
修正2:強制停止してから再起動する
プロセスがスタックしている可能性があります。書き込みの途中でクラッシュしてファイルロックを保持していたり、初期化が途中の状態で止まっていたりするケースです。強制停止でプロセスをクリーンに終了させます。
# Force stop via ADB:
adb shell am force-stop com.example.yourapp
# Relaunch:
adb shell monkey -p com.example.yourapp -c android.intent.category.LAUNCHER 1
強制停止後にクラッシュが解消した場合、スレッドのバグや前のセッションからのリソースリークが疑われます。自然に直ることはありませんが、調査の糸口がつかめました。
修正3:APKを再インストールする
インストールに失敗すると、起動のたびにエラーを引き起こす破損したAPKがディスク上に残ることがあります。よくある原因は、ダウンロードの中断、インストール途中のストレージ不足、ファイルシステムの破損などです。
# Uninstall cleanly:
adb uninstall com.example.yourapp
# Reinstall:
adb install -r yourapp.apk
# Or from Play Store: uninstall → reinstall from scratch
Play Storeのアプリの場合、夜間の自動アップデートで壊れたバージョンが配信されていないか確認してください。該当アプリの自動更新を一時的に無効にし、APKMirrorなどの信頼できるミラーサイトから以前のバージョンのAPKをダウンロードしてダウングレードしましょう。
修正4:使用可能なストレージを確認する
ディスクが満杯になると、静かに問題が起き始めます。/dataがほぼ満杯の場合、Androidはデータベースの書き込み、dexファイルの展開、一時ファイルの作成ができなくなります。しかもクラッシュログには、その原因が明示されないことが多いです。
adb shell df -h /data
# Example output:
# Filesystem Size Used Avail Use% Mounted on
# /dev/block/... 64G 63G 0.4G 99% /data ← This will cause problems
使用率が95%を超えている場合は、複数のアプリのキャッシュをクリアするか、ファイルをオフロードしてから再テストしてください。SamsungやXiaomiのデバイスでは、「ストレージ不足」の通知がクラッシュの閾値を超えるまで表示されないことがあります。
修正5:OOMキル(開発者ビルド向け)
logcatにきれいなスタックトレースが残っていない場合、プロセスがクラッシュしたのではなく、Androidのメモリ不足キラー(low memory killer)によって強制終了された可能性があります。
# Check if OOM killer was involved:
adb logcat -d | grep -i "lowmemory\|lmk\|killed"
# Look for entries like:
I ActivityManager: Killing 12345:com.example.yourapp/u0a123 (adj 900): cached #1
これはクラッシュではありません。強制退去です。アプリのメモリフットプリントを削減し、onTrimMemory()コールバックを実装してビットマップやキャッシュを積極的に解放するか、RAM 4GB以上のデバイスでテストしてください。開発中の一時的な回避策として、エミュレータのRAMアロケーションを増やす方法もあります。
修正6:OSアップデート後の互換性問題
OSアップデート後のクラッシュは、APIの変更に追随できていないアプリに多く発生します。まずターゲットSDKを確認しましょう:
adb shell dumpsys package com.example.yourapp | grep -E "(targetSdk|versionCode|versionName)"
Android 6(API 23)をターゲットにしたアプリがAndroid 14(API 34)上で動作している場合、8つのメジャーバージョン分の動作変更にまたがっています。バックグラウンドプロセスの制限、パーミッション処理、インテントの制限はこれらのリリースを通じて大幅に厳格化されています。アプリを更新するか、正確なOSバージョンとデバイスモデルを添えて開発者に報告しましょう。
確認チェックリスト
- キャッシュ/データをクリア後、ダイアログなしでアプリが起動する
adb logcatでそのパッケージのFATAL EXCEPTIONが表示されない- バックグラウンド→フォアグラウンド遷移(Homeボタンを押して戻る)後もアプリが正常動作する
- 画面回転後もアプリが正常動作する(該当する場合)
- 通常使用中にlogcatで
lmk/OOMのエントリが記録されない
学んだこと
「アプリ」が繰り返し停止していますというダイアログは、プロセスの終了に対するAndroidの包括的なエラー表示です。クラッシュ、ANR、OOMキル——ユーザーには3つともまったく同じように見えます。デバイスの設定を触る前にlogcatを読んでください。修正方法は、ほぼ必ずスタックトレースの最初の10行に書いてあります。
本番環境では、バグレポートを待ってはいけません。Thread.setDefaultUncaughtExceptionHandlerを設定するか、Firebase CrashlyticsやSentryを導入してください。クラッシュレポートのセットアップにかかる時間は約5分です。それなしでサイレントクラッシュをローカルで再現しようとすると、数日かかることもあります。

