web-dev-qa-db-ja.com

Android:ProgressDialog.show()がgetApplicationContextでクラッシュする

なぜこれが起こっているのか理解できないようです。このコード:

mProgressDialog = ProgressDialog.show(this, "", getString(R.string.loading), true);

うまく動作します。ただし、このコード:

mProgressDialog = ProgressDialog.show(getApplicationContext(), "", getString(R.string.loading), true);

次の例外をスローします。

W/WindowManager(  569): Attempted to add window with non-application token WindowToken{438bee58 token=null}.  Aborting.
D/AndroidRuntime( 2049): Shutting down VM
W/dalvikvm( 2049): threadid=3: thread exiting with uncaught exception (group=0x4001aa28)
E/AndroidRuntime( 2049): Uncaught handler: thread main exiting due to uncaught exception
E/AndroidRuntime( 2049): Java.lang.RuntimeException: Unable to start activity ComponentInfo{com.tastekid.TasteKid/com.tastekid.TasteKid.YouTube}: Android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
E/AndroidRuntime( 2049):    at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:2401)
E/AndroidRuntime( 2049):    at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.Java:2417)
E/AndroidRuntime( 2049):    at Android.app.ActivityThread.access$2100(ActivityThread.Java:116)
E/AndroidRuntime( 2049):    at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1794)
E/AndroidRuntime( 2049):    at Android.os.Handler.dispatchMessage(Handler.Java:99)
E/AndroidRuntime( 2049):    at Android.os.Looper.loop(Looper.Java:123)
E/AndroidRuntime( 2049):    at Android.app.ActivityThread.main(ActivityThread.Java:4203)
E/AndroidRuntime( 2049):    at Java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 2049):    at Java.lang.reflect.Method.invoke(Method.Java:521)
E/AndroidRuntime( 2049):    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:791)
E/AndroidRuntime( 2049):    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:549)
E/AndroidRuntime( 2049):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 2049): Caused by: Android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
E/AndroidRuntime( 2049):    at Android.view.ViewRoot.setView(ViewRoot.Java:460)
E/AndroidRuntime( 2049):    at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:177)
E/AndroidRuntime( 2049):    at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:91)
E/AndroidRuntime( 2049):    at Android.app.Dialog.show(Dialog.Java:238)
E/AndroidRuntime( 2049):    at Android.app.ProgressDialog.show(ProgressDialog.Java:107)
E/AndroidRuntime( 2049):    at Android.app.ProgressDialog.show(ProgressDialog.Java:90)
E/AndroidRuntime( 2049):    at com.tastekid.TasteKid.YouTube.onCreate(YouTube.Java:45)
E/AndroidRuntime( 2049):    at Android.app.Instrumentation.callActivityOnCreate(Instrumentation.Java:1123)
E/AndroidRuntime( 2049):    at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:2364)
E/AndroidRuntime( 2049):    ... 11 more

これが起こっている理由は何ですか?これをonCreateメソッドから呼び出しています。

108
Felix

どのAPIバージョンを使用していますか?問題が正しい場合、Android 1.6(APIバージョン4)で修正されました。

getApplicationContext()がnullを指すポイントのみを返すオブジェクト参照のように見えます。ウィンドウが実際に構築される前にonCreate()のコードの一部が実行されているという点で、私が抱えていた問題と同様の問題を抱えていると思います。これはハックになりますが、ProgressDialogを開き、必要な他のものを開始する数百ミリ秒で新しいスレッドを起動してみてください(IIRC:300-400は私にとってはうまくいくようですが、いじくり回す必要があります)例:ネットワークIO)。このようなもの:

@Override
public void onCreate(Bundle savedInstanceState) {
    // do all your other stuff here

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            mProgressDialog = ProgressDialog.show(
               YouTube.this.getApplicationContext(), "",
               YouTube.this.getString(R.string.loading), true);

            // start time consuming background process here
        }
    }, 1000); // starting it in 1 second
}
42
Jeremy Logan

APIレベル7でAndroidバージョン2.1を使用しています。この(または同様の)問題に直面し、これを使用して解決しました。

Dialog dialog = new Dialog(this);

これの代わりに:

Dialog dialog = new Dialog(getApplicationContext());

お役に立てれば :)

127
Taner

私にとっては変化しました

builder = new AlertDialog.Builder(getApplicationContext());

builder = new AlertDialog.Builder(ThisActivityClassName.this);

奇妙なことは、最初のものはグーグルのチュートリアルで見つけることができ、人々はこれについてエラーを得るということです。

64
wtk

これはnullアプリケーションコンテキストに関するタイミングの問題ではないと思います

アプリ内でアプリケーションを拡張してみてください(または既にお持ちの場合はそのまま使用してください)

public class MyApp extends Application

インスタンスをプライベートシングルトンとして使用可能にします。これはnever null

private static MyApp appInstance;

MyAppで静的ヘルパーを作成します(シングルトンを使用します)

    public static void showProgressDialog( CharSequence title, CharSequence message )
{
    prog = ProgressDialog.show(appInstance, title, message, true); // Never Do This!
}

BOOM !!

また、次のAndroidエンジニアの回答もご覧ください。 WindowManager $ BadTokenException

このエラーの原因の1つは、アクティビティではないコンテキストを介してアプリケーションウィンドウ/ダイアログを表示しようとしていることです。

今、私は同意します、メソッドがアクティビティではなくコンテキストパラメータを取ることは意味がありません。

23
alienjazzcat

上記の答えを読んで、私は私の状況で次のことが問題を解決したことを発見しました。

これはエラーを投げました

myButton.setOnClickListener(new OnClickListener(){
    public void onClick(View v) {
        MyDialogue dialog = new MyDialogue(getApplicationContext());
        dialog.show();              
    }
});

コンテキストが間違っていることを示唆した以前の回答に基づいて、getApplicationContext()を変更して、ボタンonClickメソッドに渡されたビューからコンテキストを取得しました。

myButton.setOnClickListener(new OnClickListener(){
    public void onClick(View v) {
        MyDialogue dialog = new MyDialogue(v.getContext());
        dialog.show();              
    }
});

Javaの動作を完全に理解していないので、間違っている可能性がありますが、特定の状況では、上記のスニペットがAbstractアクティビティクラス。おそらくgetApplicationContext()が有効なコンテキストを返さないという事実に寄与した、多くのアクティビティによって継承および使用されますか? (推測だけ)。

10
Emile

項目別のオーバーレイを使用してマップビューを作成しています。私はmapActivityからこのようなitemizedoverlayを作成していました:

OCItemizedOverlay currentLocationOverlay = new OCItemizedOverlay(pin,getApplicationContext);

ItemizedoverlayのonTapメソッドがトリガーされたとき(マップビューで場所がタップされたとき)に、「Android.view.WindowManager $ BadTokenException:ウィンドウを追加できません-トークンnullはアプリケーション用ではありません」例外が発生することがわかりました。

「getApplicationContext()」の代わりに「this」をコンストラクタに渡すだけで、問題は解決することがわかりました。これは、alienjazzcatの結論を裏付けているようです。変だ。

6
cipherz

TabActivities内に表示されるアクティビティには、getParent()を使用します

final AlertDialog.Builder builder = new AlertDialog.Builder(getParent());

の代わりに

final AlertDialog.Builder builder = new AlertDialog.Builder(this);
4
salcosand

Android 2.2の場合
次のコードを使用します。

//activity is an instance of a class which extends Android.app.Activity
Dialog dialog = new Dialog(activity);

このコードの代わりに:

// this code produces an ERROR:
//Android.view.WindowManager$BadTokenException: 
//Unable to add window -- token null is not for an application
Context mContext = activity.getApplicationContext();
Dialog dialog = new Dialog(mContext);

注:カスタムダイアログはactivity.onCreateDialog(int dialogId)メソッドの外部で作成されます。

3
jm_java

試してください-

AlertDialog.Builder builder = new AlertDialog.Builder(getParent());
3
eyal

getActivity()内でProgressDialog.show()を使用するとクラッシュする(互換性)フラグメントにも同様の問題がありました。私はそれがタイミングのためであることに同意します。

考えられる修正:

mContext = getApplicationContext();

if (mContext != null) {
    mProgressDialog = ProgressDialog.show(mContext, "", getString(R.string.loading), true);
}

使用する代わりに

mProgressDialog = ProgressDialog.show(getApplicationContext(), "", getString(R.string.loading), true);

MContextをできるだけ早く配置して、コンテキストを取得する時間を増やします。これが機能するという保証はまだありません。クラッシュの可能性を減らすだけです。それでも機能しない場合は、タイマーハック(後でダイアログを閉じるなどのタイミングの問題を引き起こす可能性があります)に頼らなければなりません。

もちろん、thisまたはActivityName.thisを使用できる場合は、thisが既に何かを指しているため、より安定しています。しかし、特定のフラグメントアーキテクチャのように、場合によってはオプションではありません。

2
Muz

(将来の参照用)

ここで説明するように、アプリケーションコンテキストとアクティビティコンテキストに違いがあるためだと思います。 http://www.doubleencore.com/2013/06/context/

これは、アプリケーションコンテキストを使用してダイアログを表示できないことを意味します。それでおしまい。

2
vtloc

アクティビティ内でダイアログを使用するには、次のようにします。

private Context mContext;
private AlertDialog.Builder mBuilder;

@Override
protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     mContext = this;

     //using mContext here refering to activity context
     mBuilder = new AlertDialog.Builder(mContext);
     //...
     //rest of the code
     //...
}

フラグメント内でダイアログを使用するには、次のようにします。

private Context mContext;
private AlertDialog.Builder mBuilder;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
      View mRootView = inflater.inflate(R.layout.fragment_layout, container, false);
      mContext = getActivity();

      //using mContext here refering to fragment's hosting activity context
      mBuilder = new AlertDialog.Builder(mContext);
      //...
      //rest of the code
      //...
      return mRootView;
}

それだけです^ _ ^

2
blueware

これを回避するために行ったのは、グローバルデータを保存するすべてのアクティビティの基本クラスを作成することでした。最初のアクティビティでは、次のようにベースクラスの変数にコンテキストを保存しました。

基本クラス

public static Context myucontext; 

基本クラスから派生した最初のアクティビティ

mycontext = this

次に、ダイアログを作成するときにgetApplicationContextの代わりにmycontextを使用します。

AlertDialog alertDialog = new AlertDialog.Builder(mycontext).create();
1
rainhut

フラグメントでProgressDialog.show()を呼び出している場合、mContextをActivityにキャストするとうまくいきました。

     ProgressDialog pd = new ProgressDialog((Activity) mContext);
1
Dale Julian

グループのアクティビティに問題がある場合は、これを使用しないでください。 PARENTは、Parent Activity Groupからの静的です。

final AlertDialog.Builder builder = new AlertDialog.Builder(GroupActivityParent.PARENT);

の代わりに

final AlertDialog.Builder builder = new AlertDialog.Builder(getParent());
0
vilvestre

これはよくある問題です。 getApplicationContext()の代わりにthisを使用してください。これで問題が解決するはずです

0
Atul Kumar

ダイアログは常に作成され、アクティビティの一部として表示されます。アプリケーションコンテキストではなく、アクティビティコンテキストを渡す必要があります。

http://developer.Android.com/guide/topics/ui/dialogs.html#ShowingADialog

0
Sam