Android: ProgressDialog.show () аварийно завершает работу с getApplicationContext - PullRequest
108 голосов
/ 13 октября 2009

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

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.

Ответы [ 18 ]

127 голосов
/ 24 мая 2010

Я использую Android версии 2.1 с API уровня 7. Я столкнулся с этой (или похожей) проблемой и решил ее с помощью:

Dialog dialog = new Dialog(this);

вместо этого:

Dialog dialog = new Dialog(getApplicationContext());

Надеюсь, это поможет:)

64 голосов
/ 24 мая 2011

У меня работало изменение

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

до

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

Странно то, что первое можно найти в учебнике Google, и люди получают сообщение об ошибке ..

42 голосов
/ 13 октября 2009

Какую версию 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
}
23 голосов
/ 06 мая 2010

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

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

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 здесь: WindowManager $ BadTokenException

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

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

10 голосов
/ 12 ноября 2010

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

Это выкинуло ошибку

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, поэтому могу ошибаться, но думаю, что для моей конкретной ситуации причина могла быть связана с тем фактом, что приведенный выше фрагмент был определен в классе Abstract Activity; унаследованный и используемый многими Деятельностями, возможно это способствовало тому, что getApplicationContext () не возвращает действительный контекст ?? (Просто предположение).

6 голосов
/ 06 августа 2010

Я создаю вид карты с подробными наложениями. Я создавал свой оверлей оверлейной записи, как это из моей картыActivity:

OCItemizedOverlay currentLocationOverlay = new OCItemizedOverlay(pin,getApplicationContext);

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

Я обнаружил, что если я просто передал «this» вместо «getApplicationContext ()» моему конструктору, проблема исчезнет. Это, кажется, подтверждает заключение иностранца. странно.

4 голосов
/ 09 января 2012

Для действий, отображаемых в TabActivities, используйте getParent ()

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

вместо

final AlertDialog.Builder builder = new AlertDialog.Builder(this);
3 голосов
/ 26 мая 2011

для 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).

3 голосов
/ 11 июля 2011

Попробуйте -

AlertDialog.Builder builder = new AlertDialog.Builder(getParent());
2 голосов
/ 19 сентября 2016

Для использования диалогов внутри действий, сделайте это так:

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

Вот и все ^ _ ^

...