Android 1.6: "Android.View.WindowManager $ badtokenxception: غير قادر على إضافة نافذة - الرمز المميز ليس للتطبيق"
-
26-09-2019 - |
سؤال
أحاول فتح نافذة مربع حوار ، لكن في كل مرة أحاول فتحها ، يلقي هذا الاستثناء:
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);
}