Android 1.6: "Android.View.WindowManager $ badtokenxception: غير قادر على إضافة نافذة - الرمز المميز ليس للتطبيق"

StackOverflow https://stackoverflow.com/questions/2634991

سؤال

أحاول فتح نافذة مربع حوار ، لكن في كل مرة أحاول فتحها ، يلقي هذا الاستثناء:

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 مع معرف العرض. ال 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 يبدو المتغير وكأنه ملء بشكل صحيح في مصحح الأخطاء.

هل كانت مفيدة؟

المحلول

بدلاً من :Context appContext = this.getApplicationContext();يجب أن تستخدم مؤشرًا للنشاط الذي أنت فيه (ربما this).

لقد تعرضت للعض من هذا اليوم أيضًا ، الجزء المزعج هو getApplicationContext() هو حرفي من المطور .android.com :(

نصائح أخرى

لا يمكنك عرض نافذة/مربع حوار تطبيق من خلال سياق ليس نشاطًا. حاول تمرير مرجع نشاط صالح

كما سبق على شيء getApplicationContext.

تقول المستندات الموجودة على موقع Android لاستخدامها ، لكنها لا تعمل ... Grrrrr: p

فقط افعل:

dialog = new Dialog(this); 

"هذه" عادة ما يكون نشاطك الذي تبدأ منه الحوار.

تقترح مستندات Android استخدام getApplicationContext () ؛

لكنه لن يعمل بدلاً من ذلك ، استخدم نشاطك الحالي أثناء إنشاء إنشاء alertdialog.builder أو Alertdialog أو مربع الحوار ...

السابق:

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

أو

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

بدلاً من getApplicationContext(), ، فقط استخدم ActivityName.this

لقد واجهت مشكلة مماثلة حيث كان لدي فئة أخرى شيء من هذا القبيل:

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 في المقام الأول...

فقط قم بتغييره إلى

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

بدلاً من

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

حل آخر هو تعيين نوع النافذة على مربع حوار النظام:

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

هذا يتطلب SYSTEM_ALERT_WINDOW إذن:

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

كما تقول المستندات:

عدد قليل جدا من التطبيقات يجب أن تستخدم هذا الإذن ؛ هذه النوافذ مخصصة للتفاعل على مستوى النظام مع المستخدم.

هذا هو الحل الذي يجب عليك استخدامه فقط إذا كنت بحاجة إلى مربع حوار غير مرتبط بنشاط ما.

لا تستخدم getApplicationContext() على إعلان dialouge

دائما يستخدم this أو الخاص بك activity.this

هذا عمل بالنسبة لي-

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

بالنسبة لحوارات الحوارات المتداخلة ، فإن هذه المشكلة شائعة جدًا ، فهي تعمل عندما

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

يستخدم بدلا من

mDialogBuilder = new AlertDialog.Builder(getApplicationContext);

هذا البديل.

يمكنك أيضا القيام بذلك

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

هذا عمل بالنسبة لي !!

كما قيل ، تحتاج إلى نشاط كسياق للحوار ، استخدم "هذا النشاط. هذا" لسياق أو شيك ثابت هنا لكيفية استخدام واحدة ديناميكية في وضع آمن

حاول إعادة التعيين dialog نوع النافذة إلى

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

لا تنس استخدام الإذن android.permission.SYSTEM_ALERT_WINDOW

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

النص هنا:-
استخدم هذا للحصول على activity سياق progressdialog

 progressdialog = new ProgressDialog(Splash.this);

أو progressdialog = new ProgressDialog(this);

استخدم هذا للحصول على سياق التطبيق ل BroadcastListenerليس ل progressdialog.

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

أفضل وأكثر الطرق أمانًا لإظهار "ProgressDialog" في Asynctask ، تجنب مشكلة تسرب الذاكرة هو استخدام "معالج" مع looper.main ().

    private ProgressDialog tProgressDialog;

ثم في "oncreate"

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

الآن لقد انتهيت مع جزء الإعداد. الآن اتصل بـ "showprogress ()" و "HideProgress ()" في 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);
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top