2013/01/28
Android の「問題が発生したため~を終了します」を表示しないことは可能か?
UncaughtExceptionHandler の存在を知ると、例外が発生じた際に処理が出来るのだから、例の「問題が発生したため~を終了します」を表示しないように出来るのではないか?と思うのは人情だと思います。
しかし、結論から言いますと、技術的には可能だけど、しないほうが良いと思います。
以下、その理由です。
とりあえず、実現するだけであれば以下のように書けば可能です。
詳細は、昨日のエントリを読んでいただくとわかると思いますが、本来 RuntimeInit.UncaughtHandler の中でやるべき処理を自分で書いてしまうわけです。
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { private volatile boolean mCrashing = false; @Override public void uncaughtException(Thread thread, Throwable ex) { if (mCrashing) { return; } mCrashing = true; Process.killProcess(Process.myPid()); System.exit(10); } });
しかし、この方法は以下の様な理由でよくありません。
- 本当に最後に呼ばれた UncaughtExceptionHandler なのかどうかわからない
setDefaultUncaughtExceptionHandler() は既に設定されている UncaughtExceptionHandler を上書きします。
上記のような書き方をしてしまうと、以後呼ばれるはずであった全ての UncaughtExceptionHandler を無視することになってしまいます。
昨日のエントリを参照してもらうとわかると思いますが、DefaultUncaughtExceptionHandler は紳士協定のようなもので数珠つなぎに呼ばれていき、最後に RuntimeInit.UncaughtHandler が呼ばれることで成り立っています。
この数珠つなぎを勝手に断ち切ってしまうのは大変危険です。
例えば、使用しているライブラリの中で先に設定されているかもしれませんし、同僚(とか未来の自分)が別の所で先に設定するよう書き換えてしまうかもしれません。
その処理がとても重要なものだった場合、それを呼ばないということが問題になってくることは容易に想像出来ます。 - Android OS がバージョンアップした場合に追従できない
もし、アプリケーションの中で setDefaultUncaughtExceptionHandler() を一度しか呼んでいないということを保証出来たとします。
その場合、次に呼ばれるのは RuntimeInit.UncaughtHandler であることがわかっていますから、その処理(の一部)を自分で記述しても良いということになります。
しかし、例えそうだとしても上記のように記述するのは良くありません。
なぜならば、RuntimeInit.UncaughtHandler が、今後 Android OS のバージョンアップに伴ってどのように変化していくのかわからないからです。
また、スマフォメーカーによっては、ここに独自の処理を入れているかもしれません。
その処理を行わないとアプリに不具合をもたらすようなものである可能性もあるわけです。
つまり、RuntimeInit.UncaughtHandler を呼ばないという選択肢はとても危険だということです。
以上が、「問題が発生したため~を終了します」を表示しないでアプリを終了するのを止めておいたほうが良いと思う理由です。(再起動なども同じです)
やはり、キャッチされない例外を作らないように設計し、万が一、発生してしまったらバグレポートを真摯に受け止める。というのが正しい姿かと思います。
独り言
バグレポート送ってくれれば、まだありがたいんですけどねぇ"Crashed." の一言で星1つとか、ちょっと悲しくなります。
そういうのに限ってデバイス名 Other とかだったりして、「機種依存なんじゃないか?」とか思ったり…
いかんいかん。最近愚痴っぽいな…
0 件のコメント:
コメントを投稿