Android 1.6: Android android.view.WindowManager $ BadTokenException: Không thể thêm cửa sổ - mã thông báo null không dành cho ứng dụng.


303

Tôi đang cố mở một cửa sổ hộp thoại, nhưng mỗi lần tôi cố mở nó sẽ ném ngoại lệ này:

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)

Tôi đang tạo nó bằng cách gọi showDialogvới id của màn hình. Trình onCreateDialogxử lý ghi nhật ký tốt và tôi có thể bước qua nó mà không gặp vấn đề gì, nhưng tôi đã đính kèm vì có vẻ như tôi đang thiếu một cái gì đó:

@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;      
}

Có cái gì thiếu từ cái này? Một số câu hỏi đã nói về vấn đề này khi tạo hộp thoại onCreate, điều này xảy ra do hoạt động chưa được tạo, nhưng điều này đến từ một cuộc gọi từ một đối tượng menu và appContextbiến có vẻ như được đặt chính xác trong trình gỡ lỗi.

Câu trả lời:


609

Thay vì: Context appContext = this.getApplicationContext(); bạn nên sử dụng một con trỏ tới hoạt động bạn có thể (có thể this).

Hôm nay tôi cũng bị cắn, phần khó chịu getApplicationContext()là nguyên văn từ developer.android.com :(


2
Nó cũng được báo cáo là một lỗi (mặc dù đó không phải là khi người dùng đăng câu hỏi): code.google.com/p/android/issues/detail?id=11199
Raymond Martineau

63
Chỉ trong trường hợp điều này giúp bất cứ ai - sử dụng myActivity.this làm bối cảnh của bạn trong một hộp thoại.
Rab Ross

13
Câu hỏi và câu trả lời này tròn 3 tuổi trong 2 ngày. Tôi vẫn đang nổi tiếng, vì vậy tôi đoán Google vẫn chưa sửa tài liệu của họ ...
Torp

2
Điều này đã được sửa trong ( developer.android.com/guide/topics/ui/dialogs.html )
Martin Marconcini

6
Đây là tháng 4 năm 2016, và vẫn còn trường hợp ngoại lệ này khiến ứng dụng gặp sự cố khi bắt đầu hộp thoại.
Yogesh Seralia

78

Bạn không thể hiển thị cửa sổ / hộp thoại ứng dụng thông qua Ngữ cảnh không phải là Hoạt động. Hãy thử chuyển một tham chiếu hoạt động hợp lệ


làm sao? Tôi đã thử activity.thisactivity.getBaseContext()không có kết quả. Có ai giúp đỡ không?
Darpan

3
Hiểu rồi. Trực tiếp vượt qua tên hoạt động của bạn trong đó. Không có .this.
Darpan

45

Ditto về điều getApplicationContext.

Các tài liệu trên trang web android nói sẽ sử dụng nó, nhưng nó không hoạt động ... grrrrr :-P

Cứ làm đi:

dialog = new Dialog(this); 

"này" thường là Hoạt động của bạn mà từ đó bạn bắt đầu hộp thoại.


43

Các tài liệu Android đề xuất sử dụng getApplicationContext ();

nhưng nó sẽ không hoạt động thay vì sử dụng hoạt động hiện tại của bạn trong khi khởi tạo AlertDialog.Builder hoặc AlertDialog hoặc Dialog ...

Ví dụ:

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

hoặc là

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

Điều này đã giúp tôi ra ngoài một cách ồ ạt. Tôi đã cố gắng tạo một hộp thoại từ trong một hộp thoại khác và chỉ cần có "AlertDialog.Builder (cái này);" đã đưa ra một lỗi. Cảm ơn!
EHarpham

(ActivityName.this) đặc biệt hữu ích khi cố gắng tạo hộp thoại bên trong onClick của một nút
RmK

Vấn đề của tôi là tôi đang xây dựng một ProgressDialog bên trong AlertDialog bên trong Bộ chuyển đổi ... Tôi không thể làm cho nó hoạt động được.
Martin Erlic


13

Tôi đã có một vấn đề tương tự khi tôi có một lớp khác như thế này:

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();
  }
}

Làm việc tốt hầu hết thời gian, nhưng đôi khi nó bị lỗi với cùng một lỗi. Sau đó tôi nhận ra rằng trong MyActivitytôi đã có ...

public class MyActivity extends Activity {
  public static Something something;

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

Bởi vì tôi đang giữ đối tượng như vậy static, một đoạn mã thứ hai vẫn đang giữ phiên bản gốc của đối tượng, và do đó vẫn đề cập đến bản gốc Activity, không tồn tại lâu.

Sai lầm ngớ ngẩn ngu ngốc, đặc biệt là khi tôi thực sự không cần phải giữ đối tượng như staticlúc đầu ...


12

Chỉ cần thay đổi nó thành

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

Thay vì

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

9

Một giải pháp khác là đặt loại cửa sổ thành hộp thoại hệ thống:

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

Điều này cần có sự SYSTEM_ALERT_WINDOWcho phép:

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

Như các tài liệu nói:

Rất ít ứng dụng nên sử dụng quyền này; các cửa sổ này được dành cho tương tác cấp hệ thống với người dùng.

Đây là một giải pháp bạn chỉ nên sử dụng nếu bạn yêu cầu một hộp thoại không gắn liền với một hoạt động.


Đây là cờ không dùng nữa từ API cấp 26. Bởi vì nó cho phép nhà phát triển chơi với cửa sổ hệ thống không tốt từ góc độ người dùng.
CopsOnRoad

4

Đừng dùng getApplicationContext() để khai báo dialouge

Luôn luôn sử dụng thishoặc của bạnactivity.this


2

Đối với các hộp thoại lồng nhau, vấn đề này rất phổ biến, Nó hoạt động khi

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

được sử dụng thay vì

mDialogBuilder = new AlertDialog.Builder(getApplicationContext);

sự thay thế này.


2

Điều này làm việc cho tôi--

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();

Sử dụng

ActivityName.this

0

Bạn cũng có thể làm điều này

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

Điều này làm việc cho tôi !!


0

Như đã nói, bạn cần một Hoạt động làm bối cảnh cho hộp thoại, sử dụng "YourActivity.this" cho bối cảnh tĩnh hoặc kiểm tra ở đây để biết cách sử dụng một động trong chế độ an toàn


0

Cố gắng đặt lại loại dialogcửa sổ thành

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

Đừng quên sử dụng quyền 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);
//                          }
        });
    }

Văn bản ở đây: -
sử dụng điều này để có được activitybối cảnh choprogressdialog

 progressdialog = new ProgressDialog(Splash.this);

hoặc là progressdialog = new ProgressDialog(this);

sử dụng này để có được bối cảnh ứng dụng cho BroadcastListener không progressdialog.

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

0

Cách tốt nhất và an toàn nhất để hiển thị 'ProgressDialog' trong AsyncTask, tránh sự cố rò rỉ bộ nhớ là sử dụng 'Handler' với Looper.main ().

    private ProgressDialog tProgressDialog;

sau đó trong 'onCreate'

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

Bây giờ bạn đã thực hiện với phần thiết lập. Bây giờ hãy gọi 'showProTHER ()' và 'hideProTHER ()' trong AsyncTask.

    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);
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.