Android 1.6 : "android.view.WindowManager $ BadTokenException : 창을 추가 할 수 없습니다. 토큰 null은 응용 프로그램 용이 아닙니다"


303

대화 상자 창을 열려고하는데 열 때 마다이 예외가 발생합니다.

Uncaught handler: thread main exiting due to uncaught exception
android.view.WindowManager$BadTokenException: 
     Unable to add window -- token null is not for an application
  at android.view.ViewRoot.setView(ViewRoot.java:460)
  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
  at android.app.Dialog.show(Dialog.java:238)
  at android.app.Activity.showDialog(Activity.java:2413)

showDialog디스플레이의 ID 로 호출 하여 만들고 있습니다 . onCreateDialog핸들러는 벌금을 기록하고 나는 문제없이 단계별로 할 수 있지만, 내가 뭔가를 누락 것처럼 보이기 때문에 나는 그것을 첨부했습니다 :

@Override
public Dialog onCreateDialog(int id)
{
    Dialog dialog;
    Context appContext = this.getApplicationContext();
    switch(id)
    {
        case RENAME_DIALOG_ID:
            Log.i("Edit", "Creating rename dialog...");
            dialog = new Dialog(appContext);
            dialog.setContentView(R.layout.rename);
            dialog.setTitle("Rename " + noteName);
            break;
        default:
            dialog = null;
            break;
    }
    return dialog;      
}

이것에서 빠진 것이 있습니까? 에서 대화 상자를 만들 때이 문제가 발생하는 것에 대해 몇 가지 질문에 대해 이야기 onCreate했습니다. 활동이 아직 생성되지 않았기 때문에 발생하지만 메뉴 객체에서 호출 한 appContext것이므로 변수가 디버거에 올바르게 채워진 것처럼 보입니다.

답변:


609

대신 : Context appContext = this.getApplicationContext(); 현재 활동에 대한 포인터를 사용해야합니다 (아마도 this).

오늘도 이것에 물 렸습니다. 성가신 부분은 getApplicationContext()developer.android.com의 축약어입니다.


2
또한 버그로보고되었습니다 (사용자가 질문을 게시 한 시점은 아니지만) : code.google.com/p/android/issues/detail?id=11199
Raymond Martineau

63
누군가에게 도움이되는 경우를 대비하여 myActivity.this를 대화 상자의 컨텍스트로 사용하십시오.
Rab Ross

13
이 질문과 답변은 2 일 만에 3 살이됩니다. 나는 아직도 명성을 얻고있다. 그래서 구글은 여전히 ​​그들의 문서를
고치지


6
이것은 2016 년 4 월이며 여전히이 예외로 인해 대화 상자 시작시 응용 프로그램이 중단됩니다.
Yogesh Seralia

78

활동이 아닌 컨텍스트를 통해 애플리케이션 창 / 대화 상자를 표시 할 수 없습니다. 유효한 활동 참조를 전달하십시오


어떻게? 나는 시도 activity.this하고 activity.getBaseContext()있지만 아무 소용이 있습니다. 어떤 도움?
Darpan

3
알았다. 활동 이름을 직접 전달하십시오. 없이 .this.
Darpan

45

getApplicationContext에 대한 내용입니다.

안드로이드 사이트의 문서가 그것을 사용한다고 말했지만 작동하지 않습니다 ... grrrrr :-P

그냥 해:

dialog = new Dialog(this); 

"this" 는 일반적으로 대화를 시작하는 활동입니다.


43

안드로이드 문서는 getApplicationContext ();

AlertDialog.Builder 또는 AlertDialog 또는 Dialog를 인스턴스화하는 동안 현재 활동을 사용하는 대신 작동하지 않습니다 ...

전의:

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

또는

AlertDialog.Builder builder = new  AlertDialog.Builder((Your Activity).this);

이것은 나를 크게 도와주었습니다. 다른 대화 상자에서 대화 상자를 만들고 "AlertDialog.Builder (this);" 오류가 발생했습니다. 감사!
EHarpham

(ActivityName.this)는 버튼 클릭시 대화 상자를 만들 때 특히 유용합니다
RmK

내 문제는 어댑터 내부의 AlertDialog 안에 ProgressDialog를 작성하고 있다는 것입니다 ... 작동하지 않습니다.
Martin Erlic


13

비슷한 클래스가 있는데 다른 클래스가 있습니다.

public class Something {
  MyActivity myActivity;

  public Something(MyActivity myActivity) {
    this.myActivity=myActivity;
  }

  public void someMethod() {
   .
   .
   AlertDialog.Builder builder = new AlertDialog.Builder(myActivity);
   .
   AlertDialog alert = builder.create();
   alert.show();
  }
}

대부분 잘 작동했지만 때로는 같은 오류로 충돌했습니다. 그런 다음에 나는 MyActivity...

public class MyActivity extends Activity {
  public static Something something;

  public void someMethod() {
    if (something==null) {
      something=new Something(this);
    }
  }
}

객체를로 유지했기 때문에 static코드의 두 번째 실행은 여전히 ​​원래 버전의 객체를 유지하고 있었으므로 여전히 원본을 참조했습니다.Activity 더 이상 존재하지 않는 있었습니다.

어리석은 어리석은 실수, 특히 내가 static처음부터 물건을 들고있을 필요가 없었기 때문에 ...


12

그냥 바꿔

AlertDialog.Builder alert_Categoryitem = 
    new AlertDialog.Builder(YourActivity.this);

대신에

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

9

다른 해결책은 창 유형을 시스템 대화 상자로 설정하는 것입니다.

dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

여기에는 SYSTEM_ALERT_WINDOW권한 이 필요합니다 .

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

문서에서 말한 것처럼 :

이 권한을 사용해야하는 응용 프로그램은 거의 없습니다. 이 창은 시스템 수준의 사용자와의 상호 작용을위한 것입니다.

이것은 활동에 첨부되지 않은 대화 상자가 필요한 경우에만 사용해야하는 솔루션입니다.


이제 API 레벨 26에서 플래그가 더 이상 사용되지 않습니다. 개발자 관점에서 사용자 관점으로는 좋지 않은 시스템 창을 사용할 수 있기 때문입니다.
CopsOnRoad

4

전화 getApplicationContext()걸기 선언에 사용하지 마십시오

항상 this또는activity.this


2

중첩 대화 상자 에서이 문제는 매우 일반적입니다.

AlertDialog.Builder mDialogBuilder = new AlertDialog.Builder(MyActivity.this);

대신에 사용

mDialogBuilder = new AlertDialog.Builder(getApplicationContext);

이 대안.


2

이것은 나를 위해 일했다.

new AlertDialog.Builder(MainActivity.this)
        .setMessage(Html.fromHtml("<b><i><u>Spread Knowledge Unto The Last</u></i></b>"))
        .setCancelable(false)
        .setPositiveButton("Dismiss",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                    }
                }).show();

사용하다

ActivityName.this

0

당신은 또한 이것을 할 수 있습니다

public class Example extends Activity {
    final Context context = this;
    final Dialog dialog = new Dialog(context);
}

이것은 나를 위해 일했다!!


0

말했듯이 대화 상자의 컨텍스트로 활동이 필요합니다. 정적 컨텍스트에 "YourActivity.this"를 사용하거나 안전 모드에서 동적 컨텍스트 를 사용하는 방법은 여기 를 확인 하십시오.


0

dialog창의 유형을 다음 으로 재설정하십시오.

WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

권한을 사용하는 것을 잊지 마십시오 android.permission.SYSTEM_ALERT_WINDOW


0
public class Splash extends Activity {

    Location location;
    LocationManager locationManager;
    LocationListener locationlistener;
    ImageView image_view;
    ublic static ProgressDialog progressdialog;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splash);
        progressdialog = new ProgressDialog(Splash.this);
           image_view.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                        locationManager.requestLocationUpdates("gps", 100000, 1, locationlistener);
                        Toast.makeText(getApplicationContext(), "Getting Location plz wait...", Toast.LENGTH_SHORT).show();

                            progressdialog.setMessage("getting Location");
                            progressdialog.show();
                            Intent intent = new Intent(Splash.this,Show_LatLng.class);
//                          }
        });
    }

여기에 텍스트 :- 컨텍스트를
얻는 데 사용 하십시오.activityprogressdialog

 progressdialog = new ProgressDialog(Splash.this);

또는 progressdialog = new ProgressDialog(this);

BroadcastListener not에 대한 애플리케이션 컨텍스트를 가져 오기 위해 이것을 사용하십시오 progressdialog.

progressdialog = new ProgressDialog(getApplicationContext());
progressdialog = new ProgressDialog(getBaseContext());

0

메모리 누수 문제를 피하면서 AsyncTask에서 'ProgressDialog'를 표시하는 가장 안전하고 안전한 방법은 Looper.main ()과 함께 'Handler'를 사용하는 것입니다.

    private ProgressDialog tProgressDialog;

그런 다음 'onCreate'에서

    tProgressDialog = new ProgressDialog(this);
    tProgressDialog.setMessage(getString(R.string.loading));
    tProgressDialog.setIndeterminate(true);

이제 설정 부분을 완료했습니다. 이제 AsyncTask에서 'showProgress ()'및 'hideProgress ()'를 호출하십시오.

    private void showProgress(){
        new Handler(Looper.getMainLooper()){
            @Override
            public void handleMessage(Message msg) {
                tProgressDialog.show();
            }
        }.sendEmptyMessage(1);
    }

    private void hideProgress(){
        new Handler(Looper.getMainLooper()){
            @Override
            public void handleMessage(Message msg) {
                tProgressDialog.dismiss();
            }
        }.sendEmptyMessage(1);
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.