こんにちは、まっさん(@Tera_Msaki)です。
この記事は Android スマホ用のアプリ開発の中で、
今後の開発で再使用性が高いと思われるコーディングをまとめたものです。
Java での開発経験、XML 構文規則、Android のアプリ開発経験がある方を対象としています。
Android のアプリ開発でお役にたててれば、嬉しいです。
(これから Android のアプリ開発や Java での開発を始めたい方への案内は、記事の最後で紹介します)
ポイント
UIスレッドで実行した処理が5秒以上応答がない場合、Input event dispatching timed outのANRエラーが発生します。
これを防ぐには、UIスレッドとは別スレッドで処理を実行する必要があります。
対応前
UIスレッドで実行した処理が5秒以上応答がない場合にANRエラーが発生します。
(ANRダイアログで「wait」を選択すれば、アプリ自体は落ちません)
◎Javaコーディング【対応前】
ActivityResultLauncher.launchで処理を呼び出します。
結果は、ActivityResultContracts.StartActivityForResultで受け取ります。
処理中のUIコンポーネントを無効化し、処理を実行する。
(無効化したUIコンポーネントを有効化は、処理終了後に行う)
:
//バックアップ
private final ActivityResultLauncher<Intent> activityResultLauncher1 = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
if (result.getData() != null) {
download.setVisibility(View.INVISIBLE);
upload.setVisibility(View.INVISIBLE);
progressBar.setVisibility(android.widget.ProgressBar.VISIBLE);
new Thread(new Runnable(){
@Override
public void run() {
getArchiveDatabase().dbExport(context, result.getData().getData());
}}).start();
}}
});
:
◎Logcat出力結果
2021-12-13 09:20:36.633 19608-19608/? D/Documents: shouldRestrictStorageAccessFramework = true, packageName = com.gymtec.archivepro
2021-12-13 09:21:00.102 1724-2299/? I/WindowManager: Input event dispatching timed out sending to com.gymtec.archivepro/com.gymtec.archivepro.view.SystemActivity. Reason: 9dc79eb com.gymtec.archivepro/com.gymtec.archivepro.view.SystemActivity (server) is not responding. Waited 5003ms for FocusEvent(hasFocus=true)
2021-12-13 09:21:00.149 1724-2299/? W/InputDispatcher: Canceling events for 9dc79eb com.gymtec.archivepro/com.gymtec.archivepro.view.SystemActivity (server) because it is unresponsive
2021-12-13 09:21:00.657 30829-30842/com.gymtec.archivepro I/mtec.archivepr: Thread[3,tid=30842,WaitingInMainSignalCatcherLoop,Thread*=0xb400007588473010,peer=0x12dc0318,"Signal Catcher"]: reacting to signal 3
2021-12-13 09:21:00.726 30829-30842/com.gymtec.archivepro I/mtec.archivepr: Wrote stack traces to tombstoned
2021-12-13 09:21:01.986 1724-2299/? I/InputDispatcher: 9dc79eb com.gymtec.archivepro/com.gymtec.archivepro.view.SystemActivity (server) spent 6888ms processing FocusEvent(hasFocus=true)
2021-12-13 09:21:06.016 1724-31369/? E/ActivityManager: ANR in com.gymtec.archivepro (com.gymtec.archivepro/.view.SystemActivity)
PID: 30829
Reason: Input dispatching timed out (9dc79eb com.gymtec.archivepro/com.gymtec.archivepro.view.SystemActivity (server) is not responding. Waited 5003ms for FocusEvent(hasFocus=true))
Parent: com.gymtec.archivepro/.view.SystemActivity
Load: 0.0 / 0.0 / 0.0
----- Output from /proc/pressure/memory -----
some avg10=0.00 avg60=0.00 avg300=0.00 total=14703203
full avg10=0.00 avg60=0.00 avg300=0.00 total=4851181
----- End output from /proc/pressure/memory -----
CPU usage from 0ms to 5816ms later (2021-12-13 09:21:00.150 to 2021-12-13 09:21:05.966):
34% 30829/com.gymtec.archivepro: 18% user + 15% kernel / faults: 8823 minor
14% 30860/RenderThread: 7.4% user + 7% kernel
13% 30829/mtec.archivepro: 5.8% user + 7.9% kernel
1.5% 30846/HeapTaskDaemon: 1.5% user + 0% kernel
1.2% 30842/Signal Catcher: 1% user + 0.1% kernel
0.1% 30847/ReferenceQueueD: 0.1% user + 0% kernel
0.1% 30851/Binder:30829_2: 0.1% user + 0% kernel
0.1% 30853/Binder:30829_3: 0% user + 0.1% kernel
+0% 31409/pool-15-thread-: 0% user + 0% kernel
0.3% 1557/media.codec: 0.1% user + 0.1% kernel / faults: 46878 minor
0% 1557/omx@1.0-service: 0% user + 0% kernel
0% 16672/HwBinder:1557_C: 0% user + 0% kernel
0% 16842/HwBinder:1557_1: 0% user + 0% kernel
0% 17025/HwBinder:1557_1: 0% user + 0% kernel
0% 3606/HwBinder:1557_3: 0% user + 0% kernel
0% 16235/HwBinder:1557_6: 0% user + 0% kernel
0% 16677/HwBinder:1557_E: 0% user + 0% kernel
0% 16843/HwBinder:1557_1: 0% user + 0% kernel
0% 1618/Binder:1557_2: 0% user + 0% kernel
0% 16236/HwBinder:1557_7: 0% user + 0% kernel
0% 16805/HwBinder:1557_1: 0% user + 0% kernel
0% 1612/Binder:1557_1: 0% user + 0% kernel
0% 16238/HwBinder:1557_8: 0% user + 0% kernel
0% 16680/HwBinder:1557_1: 0% user + 0% kernel
0% 17023/HwBinder:1557_1: 0% user + 0% kernel
0% 1653/HwBinder:1557_2: 0% user + 0% kernel
0% 16676/HwBinder:1557_D: 0% user + 0% kernel
0% 16678/HwBinder:1557_F: 0% user + 0% kernel
0% 16681/HwBinder:1557_1: 0% user + 0% kernel
0% 16867/HwBinder:1557_1: 0% user + 0% kernel
0% 16239/HwBinder:1557_9: 0% user + 0% kernel
0% 16671/HwBinder:1557_B: 0% user + 0% kernel
0% 16679/HwBinder:1557_1: 0% user + 0% kernel
0% 16682/HwBinder:1557_1: 0% user + 0% kernel
0% 16726/HwBinder:1557_1: 0% user + 0% kernel
0% 16727/HwBinder:1557_1: 0% user + 0% kernel
0% 16804/HwBinder:1557_1: 0% user + 0% kernel
0% 16844/HwBinder:1557_1: 0% user + 0% kernel
0% 17024/HwBinder:1557_1: 0% user + 0% kernel
0% 1628/HwBinder:1557_1: 0% user + 0% kernel
0% 3671/HwBinder:1557_4: 0% user + 0% kernel
0% 16231/HwBinder:1557_5: 0% user + 0% kernel
0% 16240/HwBinder:1557_A: 0% user + 0% kernel
0% 16868/HwBinder:1557_1: 0% user + 0% kernel
24% 1724/system_server: 13% user + 11% kernel / faults: 8548 minor
7.5% 31369/AnrConsumer: 1.8% user + 5.6% kernel
6.2% 14553/Binder:1724_1F: 4.1% user + 2% kernel
3.6% 1739/Signal Catcher: 2.4% user + 1.2% kernel
3.2% 13275/Binder:1724_13: 2.2% user + 1% kernel
0.6% 1743/HeapTaskDaemon: 0.6% user + 0% kernel
0.5% 1724/Binder:1724_3: 0.3% user + 0.1% kernel
0.5% 13253/Binder:1724_11: 0.5% user + 0% kernel
0.5% 14550/Binder:1724_1C: 0.3% user + 0.1% kernel
0.1% 1744/ReferenceQueueD: 0.1% user + 0% kernel
0.1% 2015/android.ui: 0% user + 0.1% kernel
0.1% 2016/android.io: 0.1% user + 0% kernel
0.1% 2025/ActivityManager: 0.1% user + 0% kernel
0.1% 2286/Binder:1724_4: 0.1% user + 0% kernel
0.1% 3426/WifiHandlerThre: 0% user + 0.1% kernel
0.1% 20804/RenderThread: 0.1% user + 0% kernel
20% 1210/surfaceflinger: 9.8% user + 10% kernel / faults: 536 minor
10% 1210/surfaceflinger: 6.2% user + 4.4% kernel
1.7% 1451/app: 0.5% user + 1.2% kernel
1.5% 1249/Binder:1210_2: 0.1% user + 1.3% kernel
1.2% 1449/TimerDispatch: 0.3% user + 0.8% kernel
2021-12-13 09:21:06.016 1724-31369/? E/ActivityManager: CPU usage from 129ms to 486ms later (2021-12-13 09:21:00.278 to 2021-12-13 09:21:00.635):
57% 1724/system_server: 14% user + 42% kernel / faults: 697 minor
28% 31369/AnrConsumer: 0% user + 28% kernel
25% 14553/Binder:1724_1F: 17% user + 7.1% kernel
3.5% 3426/WifiHandlerThre: 0% user + 3.5% kernel
67% 30829/com.gymtec.archivepro: 27% user + 40% kernel / faults: 875 minor
45% 30829/mtec.archivepro: 18% user + 27% kernel
18% 30860/RenderThread: 4.5% user + 13% kernel
4.5% 30846/HeapTaskDaemon: 4.5% user + 0% kernel
4.5% 30847/ReferenceQueueD: 4.5% user + 0% kernel
20% 1210/surfaceflinger: 6.7% user + 13% kernel
10% 1210/surfaceflinger: 10% user + 0% kernel
3.3% 1247/surfaceflinger: 3.3% user + 0% kernel
3.3% 1249/Binder:1210_2: 0% user + 3.3% kernel
3.3% 1451/app: 0% user + 3.3% kernel
3.3% 2104/Binder:1210_3: 3.3% user + 0% kernel
3.3% 29619/Binder:1210_2: 3.3% user + 0% kernel
23% 13212/com.google.android.providers.media.module: 0% user + 23% kernel
3.8% 8440/Thread-14: 0% user + 3.8% kernel
3.8% 26751/Thread-18: 0% user + 3.8% kernel
3.8% 28788/Thread-29: 3.8% user + 0% kernel
3.8% 31071/Thread-28: 0% user + 3.8% kernel
6.4% 1053/android.hardware.graphics.composer@2.4-service: 3.2% user + 3.2% kernel
6.4% 1053/composer@2.4-se: 3.2% user + 3.2% kernel
7.2% 3505/com.android.systemui: 3.6% user + 3.6% kernel / faults: 10 minor
7.2% 3505/ndroid.systemui: 3.6% user + 3.6% kernel
9% 30526/kworker/u16:3: 0% user + 9% kernel
3% 506/crtc_commit:134: 0% user + 3% kernel
26% TOTAL: 10% user + 14% kernel + 0.7% irq + 0.3% softirq
対応後
UIスレッドで実行した処理が5秒以上応答がない場合でもANRエラーが発生しません。
◎Javaコーディング【対応①】
UIスレッドとは別スレッドで処理を実行する。
しかし、この実装で別スレッドで実行した処理でUIコンポーネントを操作すると別のエラーが発生します。
UIコンポーネントを操作しない場合は、この実装でも問題ないと思います。
:
//バックアップ
private final ActivityResultLauncher<Intent> activityResultLauncher1 = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
if (result.getData() != null) {
download.setVisibility(View.INVISIBLE);
upload.setVisibility(View.INVISIBLE);
progressBar.setVisibility(android.widget.ProgressBar.VISIBLE);
new Thread(new Runnable(){
@Override
public void run() {
getArchiveDatabase().dbExport(context, result.getData().getData());
}
}).start();
}
}
});
:
◎Logcat出力結果
別スレッドでUI操作を行うと、Can’t create handler inside thread that has not called Looper.prepareのエラーが発生します。
別スレッドで実行した処理でUI操作する場合、UIスレッドのキューにジョブを投入する実装が必要です。
2021-12-13 09:28:19.249 32509-32678/com.gymtec.archivepro E/AndroidRuntime: FATAL EXCEPTION: Thread-3
Process: com.gymtec.archivepro, PID: 32509
java.lang.RuntimeException: Can't create handler inside thread Thread[Thread-3,5,main] that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:227)
at android.os.Handler.<init>(Handler.java:129)
at android.app.Activity.<init>(Activity.java:886)
at androidx.core.app.ComponentActivity.<init>(ComponentActivity.java:48)
at androidx.activity.ComponentActivity.<init>(ComponentActivity.java:220)
at androidx.fragment.app.FragmentActivity.<init>(FragmentActivity.java:102)
at androidx.appcompat.app.AppCompatActivity.<init>(AppCompatActivity.java:94)
at com.gymtec.archivepro.utility.ArchiveUtilities.<init>(ArchiveUtilities.java:43)
at com.gymtec.archivepro.utility.ExternalStorageWriter.<init>(ExternalStorageWriter.java:57)
at com.gymtec.archivepro.database.ArchiveDatabaseHelper.dbExport(ArchiveDatabaseHelper.java:406)
at com.gymtec.archivepro.view.SystemActivity$1.run(SystemActivity.java:73)
at java.lang.Thread.run(Thread.java:923)
◎Javaコーディング【対応②】
UIスレッドのキューにジョブを投入する場合、Handlerを使用します。
private final Handler handler = new Handler(Looper.getMainLooper());
:
//バックアップ
private final ActivityResultLauncher<Intent> activityResultLauncher1 = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
if (result.getData() != null) {
download.setVisibility(View.INVISIBLE);
upload.setVisibility(View.INVISIBLE);
progressBar.setVisibility(android.widget.ProgressBar.VISIBLE);
new Thread(new Runnable() {
@Override
public void run() {
handler.post(() -> getArchiveDatabase().dbExport(context, result.getData().getData()));
}
}).start();
}
}
});
:
今回は、ここまでです。
手になじむ、大きさが秀逸です♪
誤字脱字、意味不明でわかりづらい、
もっと詳しく知りたいなどのご意見は、
このページの最後にあるコメントか、
こちらから、お願いいたします♪
ポチッとして頂けると、
次のコンテンツを作成する励みになります♪
これからAndroidのアプリ開発やJavaでの開発を始めたい方へ
アプリケーション開発経験がない方や、アプリケーション開発経験がある方でも、Java や C# などのオブジェクト指向言語が初めての方は、Android のアプリ開発ができるようになるには、かなりの時間がかかります。
オンラインスクールでの習得を、強くおススメします。
未経験者からシステムエンジニアを目指すのに最適かと、まずは無料相談から♪
未経験者からプログラマーを目指すのに最適かと、まずは無料カウンセリングから♪
カリキュラムとサポートがしっかりしています、お得なキャンペーンとかいろいろやっています♪
ゲーム系に強いスクール、UnityやUnrealEngineを習得するのに最適かと、まずは無料オンライン相談から♪
参考になったら、💛をポッチとしてね♪
コメント欄