سؤال

لا يمكنني أن أفهم لماذا يحدث هذا. هذا الرمز:

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 طريقة.

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

المحلول

ما هو إصدار API الذي تستخدمه؟ إذا كنت على صواب بشأن المشكلة ، فقد تم إصلاح ذلك في Android 1.6 (API الإصدار 4).

يبدو أن مرجع الكائن getApplicationContext() يعود فقط النقاط إلى فارغة. أعتقد أنك تواجه مشكلة مشابهة لملكية التي واجهتها في أن بعض الكود في onCreate() يتم تشغيله قبل أن يتم بناء النافذة بالفعل. سيكون هذا اختراقًا ، ولكن حاول إطلاق خيط جديد في بضع مئات من المللي ثانية (IIRC: 300-400 يبدو أنه يعمل من أجلي ، لكنك ستحتاج إلى العبث) الذي يفتح ProgressDialog ويبدأ أي شيء آخر تحتاجه ( على سبيل المثال. الشبكة 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
}

نصائح أخرى

أنا أستخدم Android الإصدار 2.1 مع مستوى API 7. واجهت هذه المشكلة (أو ما شابه) وحلها باستخدام هذا:

Dialog dialog = new Dialog(this);

بدلا من هذا:

Dialog dialog = new Dialog(getApplicationContext());

أتمنى أن يساعدك هذا :)

بالنسبة لي عملت التغيير

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

ل

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

الشيء الغريب هو أنه يمكن العثور على أول واحد في برنامج Google Tutorial وأن الناس يخطئون في هذا ..

لا أعتقد أن هذه مشكلة توقيت حول سياق تطبيق فارغ

حاول تمديد التطبيق داخل التطبيق الخاص بك (أو استخدمه فقط إذا كان لديك بالفعل)

public class MyApp extends Application

اجعل الحالة متاحة كفرد خاص. هذا هو أبدا لاغ

private static MyApp appInstance;

اصنع مساعدًا ثابتًا في MyApp (والذي سيستخدم المفرد)

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

فقاعة!!

أيضًا ، تحقق من إجابة Android Engineer هنا: WindowManager $ badtokenexception

قد يحاول أحد أسباب هذا الخطأ عرض نافذة/مربع حوار تطبيق من خلال سياق ليس نشاطًا.

الآن ، أوافق ، ليس من المنطقي أن هذه الطريقة تأخذ سياقًا ، بدلاً من النشاط ..

بعد قراءة الإجابات أعلاه ، وجدت أنه بالنسبة لموقفي ، حددت المشكلة التالية.

هذا ألقى الخطأ

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 ، لذا فقد أكون مخطئًا ، لكنني أعتقد أنه بالنسبة لموقفي المحدد ، كان من الممكن أن يكون السبب مرتبطًا بحقيقة أن المقتطف أعلاه قد تم تعريفه في فئة نشاط تجريدية ؛ ورثت واستخدامها من قبل العديد من الأنشطة ، ربما ساهمت في حقيقة أن getApplicationContext () لا يعيد سياق صالح؟ (مجرد تخمين).

أقوم بإنشاء عرض خريطة مع تراكبات مفصلة. كنت أقوم بإنشاء excedoverlay مثل هذا من النشاط الخاص بي:

OCItemizedOverlay currentLocationOverlay = new OCItemizedOverlay(pin,getApplicationContext);

لقد وجدت أنني سأحصل على "Android.view.windowmanager $ badtokenxception: غير قادر على إضافة نافذة - الرمز المميز NULL ليس للتطبيق" استثناء عندما تم تشغيل طريقة ONTAP الخاصة بي (عندما يتم استغلال الموقع على MAPVIEW).

لقد وجدت أنه إذا مررت ببساطة ، "هذا" بدلاً من "getApplicationContext ()" إلى مُنشئتي ، فإن المشكلة قد ذهبت بعيدًا. يبدو أن هذا يدعم استنتاج Alienjazzcat. عجيب.

بالنسبة للأنشطة الموضحة في الجدولة استخدام getParent ()

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

بدلاً من

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

لنظام 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) طريقة.

محاولة -

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

كان لديه مشكلة مماثلة مع شظايا (التوافق) التي باستخدام أ 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 يشير بالفعل إلى شيء ما. ولكن في بعض الحالات ، كما هو الحال مع بعض بنيات الأجزاء ، فهو ليس خيارًا.

(للمراجع المستقبلية)

أعتقد أن هناك اختلافات في سياق التطبيق وسياق النشاط ، كما هو موضح هنا: http://www.doubleencore.com/2013/06/context/

مما يعني أنه لا يمكننا عرض مربع الحوار باستخدام سياق التطبيق. هذا هو.

لاستخدام الحوار داخل الأنشطة ، افعل ذلك بهذه الطريقة:

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

هذا كل شيء ^_ ^

ما فعلته للالتفاف على هذا هو إنشاء فصل أساسي لجميع أنشطتي حيث أقوم بتخزين البيانات العالمية. في النشاط الأول ، قمت بحفظ السياق في متغير في فئتي الأساسية مثل:

فئة قاعدة

public static Context myucontext; 

النشاط الأول المستمد من الفئة الأساسية

mycontext = this

ثم أستخدم myContext بدلاً من getApplicationContext عند إنشاء مربعات حوار.

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

إذا كنت تدعو ProgressDialog.show () في جزء ، فاستلقيت McOntext على النشاط عملت بالنسبة لي.

     ProgressDialog pd = new ProgressDialog((Activity) mContext);

لقد قمت بتطبيق مربع حوار ALERT للاستثناء من الرمي على عرض Activitty الحالي. عندما أعطيت مثل هذا

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

بالنظر إلى نفس النافذة استثناء. أكتب رمزًا للتنبيه من OnCreate (). context = this; بعد setContentView() بيان في onCreate() method.taken context ariable مثل Global Like Context context;

رمز عينة هو

static Context context;

 public void onCreate(Bundle savedInstanceState)  { 
        super.onCreate(savedInstanceState); 


        setContentView(R.layout.network); 
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        context = this;
.......

عينة طريقة التنبيه

private void alertException(String execMsg){
        Log.i(TAG,"in alertException()..."+context);
        Log.e(TAG,"Exception :"+execMsg);
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
.......

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

شكرا ، راجندر

إذا كان لديك مشكلة في النشاط الجماعي ، فلا تستخدم هذا. الوالد ثابت من مجموعة ActivityGroup.

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

بدلاً من

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

يتم دائمًا إنشاء مربع حوار وعرضه كجزء من النشاط. تحتاج إلى تمرير في سياق النشاط بدلاً من سياق التطبيق.

http://developer.android.com/guide/topics/ui/Dialogs.html#showingadialog

هذه مشكلة شائعة. يستخدم this بدلاً من getApplicationContext()هذا يجب ان يحل مشكلتك

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top