Android: ProgressDialog.show () аварийно завершает работу с getApplicationContext


Я не могу понять, почему это происходит. Этот код:

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.access00(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 метод.

18 105

18 ответов:

какую версию API вы используете? Если я прав в том, что проблема, то это было исправлено в Android 1.6 (API версии 4).

Это похоже на ссылку на объект, который getApplicationContext() возвращает просто указывает на null. Я думаю, что у вас возникла проблема, похожая на ту, которую я имел в том, что некоторые из кода в onCreate() выполняется до того, как окно фактически будет построено. Это будет хак, но попробуйте запустить новый поток через несколько сотен миллисекунд (IIRC: 300-400 казалось бы, работает для меня, но вам нужно будет поработать), который открывает ваш ProgressDialog и начинает все, что вам нужно (например. сеть ИО). Что-то вроде этого:

@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, и люди получают ошибку на этом..

Я не думаю, что это вопрос времени вокруг нулевого контекста приложения

попробуйте расширить приложение в вашем приложении (или просто использовать его, если у вас уже есть)

public class MyApp extends Application

сделать экземпляр доступным как частный синглтон. Это never null

private static MyApp appInstance;

сделать статический помощник в MyApp (который будет использовать синглтон)

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

бум!!

кроме того, проверьте ответ инженера android здесь: WindowManager$BadTokenException

одна из причин этой ошибки может быть попытка отобразить приложения окно / диалог через контекст, который не является действием.

Теперь, я согласен, это не имеет смысла, что метод принимает контекст param, а не активность..

прочитав приведенные выше ответы, я обнаружил, что для моей ситуации следующее исправило проблему.

это вызвало ошибку

myButton.setOnClickListener(new OnClickListener(){
    public void onClick(View v) {
        MyDialogue dialog = new MyDialogue(getApplicationContext());
        dialog.show();              
    }
});

основываясь на предыдущих ответах, которые предполагали, что контекст был неправильным, я изменил getApplicationContext (), чтобы получить контекст из представления, переданного в метод buttons onClick.

myButton.setOnClickListener(new OnClickListener(){
    public void onClick(View v) {
        MyDialogue dialog = new MyDialogue(v.getContext());
        dialog.show();              
    }
});

Я не полностью понимаю работу Java, поэтому я могу ошибаться, но я предполагаю, что для моего конкретного ситуация причина могла быть связана с тем, что приведенный выше фрагмент был определен в абстрактном классе Activity; наследуется и используется многими действиями, возможно, это способствовало тому, что getApplicationContext() не возвращает допустимый контекст?? (Просто догадка).

Я создаю вид карты с детализированными накладками. Я создавал свой itemizedoverlay вот так из моей mapActivity:

OCItemizedOverlay currentLocationOverlay = new OCItemizedOverlay(pin,getApplicationContext);

Я обнаружил, что получу "android.вид.WindowManager$BadTokenException: невозможно добавить window -- token null не для приложения" исключение, когда был вызван метод onTap моего itemizedoverlay (когда местоположение нажато на mapview).

Я обнаружил, что если я просто передал 'this' вместо 'getApplicationContext ()' моему конструктор, проблема ушла. Это подтверждает вывод alienjazzcat это. странный.

для действий, показанных в TabActivities использовать 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 к Activity сработало для меня.

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

я реализовал Диалог оповещения для исключения броска на текущий вид activitty.Всякий раз, когда я давал Вот так

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

учитывая же исключение окна.Я пишу код для оповещения из onCreate (). так просто я использовал context = this; после setContentView() заявление onCreate() метод.Принято контекстной переменной как глобальной, как 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 я нашел этот запрос.Прочитав все ответы на этот пост, я попробовал этот способ, чтобы он работал .Я думал, что это простое решение для преодоления исключения.

спасибо, Rajendar

Если у вас есть проблема на groupActivity не используйте это. PARENT-это статический объект из родительской группы 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() Это должно решить вашу проблему