2009-10-13 2 views
101

Я не могу понять, почему это происходит. Этот код: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.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.

+0

Если вы используете 'Fragment', http://stackoverflow.com/questions/24825114/show-progressdialog-in-fragment-class – Yeo

ответ

41

Какую версию 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 
} 
+6

Я используя 1.6. Я почти уверен, что любые действия пользовательского интерфейса должны выполняться в потоке пользовательского интерфейса, поэтому вызов ProgressDialog.show() в отдельном потоке может быть большой проблемой. Все еще думайте, что это странно. – Felix

+3

В примере, который я вам дал, вы не выполняете операции пользовательского интерфейса в другом потоке, а другой поток просто обращается к потоку пользовательского интерфейса, говоря ему, чтобы открыть диалог. –

+0

Это определенно странно, и это полный взлом, но это сработало для меня. Мне нужно протестировать ошибку, с которой я столкнулся в 1.6, чтобы проверить, могу ли я STOP использовать это. –

23

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

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

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

BOOM !!

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

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

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

128

Я использую Android версию 2.1 с API Level 7.Я сталкивался с этим (или аналогичными) проблемами и решить с помощью этого:

Dialog dialog = new Dialog(this); 

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

Dialog dialog = new Dialog(getApplicationContext()); 

Надеется, что это помогает :)

+4

У меня была аналогичная проблема, но я использовал ActivityGroup. Единственный способ решить эту ошибку - использовать вместо этого getParent(). – brack

+0

Исправлено это для меня даже в 1.5 –

+16

Как это отвечает на его вопрос? Он спрашивает, ПОЧЕМУ, что второй не работает, в то время как первый делает. – Burkhard

0

Я реализовал оповещение Dialog для исключения бросания на текущий вид деятельности. В то время как я так дал

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

Учитывая то же окно, кроме ion.I писать код для оповещения из OnCreate(). Так просто я использовал context = this; после setContentView() заявления в onCreate() method.Taken переменной контекста как глобальные, как 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); 
....... 

Он отлично работает для me.Actually я искал эту ошибку на StackOverflow я нашел этот query.After читает все ответы этого поста, я попробовал этот путь, так что работает .I хотя t это простое решение для преодоления исключения.

Спасибо, Rajendar

1

Что я сделал, чтобы обойти это было создать базовый класс для всех моих мероприятий, где я хранить глобальные данные. В первом занятии, я сохранил контекст переменной в моем базовом классе так:

Базовый класс

public static Context myucontext; 

Первая активность происходит от базового класса

mycontext = this 

Затем я использую mycontext вместо getApplicationContext при создании диалогов.

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

Позор, что это решение не получает больше голосов. Из всех возможных решений, представленных здесь, это единственное, что сработало для меня в AsyncTask – ckn

6

Я создаю карту с подробными накладками. Я создаю мой itemizedoverlay, как это от моего mapActivity:

OCItemizedOverlay currentLocationOverlay = new OCItemizedOverlay(pin,getApplicationContext); 

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

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

+1

. Спасибо, это именно то, что было моей проблемой. – Kon

9

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

Это скинул ошибку

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() не возвращает действительный контекст? (Просто догадка).

+1

это сработало для меня таким образом – noloman

+0

Лучшие решения, вероятно, работают для большинства случаев, но ваш метод v.getContext(), кажется, решает самые упрямые случаи, подобные моим. Мои эмпирические знания java приводят меня к мысли, что контекст, исходящий из метода onCreated, не совсем то же самое, что и контекст, исходящий из представления метода onClick. Голосовать! – Josh

+0

Вот так! –

64

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

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

в

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

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

+2

+1 чувак ... решил мою проблему отлично =) – Gerep

+1

+1 от меня тоже .. отличное решение – j2me

+2

+1 хорошее решение спасибо –

3

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

Try -

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

Нужно, когда текущая активность находится внутри группы деятельности – htafoya

4

Для деятельности показано в TabActivities использовать GetParent()

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

вместо

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

Это поможет мне. Большое спасибо! – Gabrielle

0

, если у вас есть проблемы на groupActivity не использовать этот , PARENT является статичным из родительской группы ActivityGroup.

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

вместо

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

была аналогичная проблема с (совместимость) Фрагменты, в которых с помощью 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 уже указывает на что-то. Но в некоторых случаях, например, с некоторыми архитектурами фрагментов, это не вариант.

2

(для будущих ссылок)

Я думаю, это потому, что есть различия в контексте приложений и активность контекста, как описано здесь: http://www.doubleencore.com/2013/06/context/

Это означает, что мы не можем показать диалог с помощью контекста приложения. Вот и все.

1

Если вы вызываете ProgressDialog.show() в фрагменте, то для меня работает mContext для Activity.

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

Для использования диалоговых окон в деятельности, сделать это таким образом:

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

Это он^_^

Смежные вопросы