2012/01/26

Android で アラートダイアログを表示しようとすると落ちる

AlertDialog.Builder を使ってアラートダイアログを表示しようとすると、
落ちてしまいました。
最初はスレッドの中で UI をいじるからおかしいのかなーとか初心者的に思ってたんですが、スレッドよくわからず・・・。

落ちるときは Android 端末にこんなダイアログがでます。

でその時のコード
package my.packagename;
import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.os.Handler;
public class ContextExampleActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Handler handler = new Handler();
handler.postDelayed(new TestHandler(), 1000);
}
class TestHandler implements Runnable {
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());
builder.setMessage("hoge");
builder.show();
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub


落ちた時 LogCat にこんなエラーメッセージがありました。
406050159201-26 01:06:50.074: E/AndroidRuntime(1979): android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application

ググってみたら stackoverflow に行き着いた。

どうも builder に渡してる Context に問題があると。

こう書き換えた。
package my.packagename;
import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
public class ContextExampleActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Handler handler = new Handler();
handler.postDelayed(new TestHandler(), 1000);
}
class TestHandler implements Runnable {
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(ContextExampleActivity.this);
builder.setMessage("hoge");
builder.show();
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub

成功した。

要するに
AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());

AlertDialog.Builder builder = new AlertDialog.Builder(ContextExampleActivity.this);
に書き換えた。
getApplicationContext() で返す Context には描画できないってことなんでしょうk?
アラートダイアログ生成の時に渡す Context は Activity がよさそうです。

しかし、
getApplication()
getApplicationContext()
getBaseApplication()
ClassName.this
ClassName.class
とか、いろいろあってどれを使えばいいのかわからんです。