111

我似乎无法理解为什么会这样。这段代码:

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方法中调用它。

4

18 回答 18

129

我正在使用具有 API 级别 7 的 Android 版本 2.1。我遇到了这个(或类似的)问题并通过以下方式解决:

Dialog dialog = new Dialog(this);

而不是这个:

Dialog dialog = new Dialog(getApplicationContext());

希望这可以帮助 :)

于 2010-05-24T19:23:10.747 回答
64

对我来说工作改变

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

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

奇怪的是,第一个可以在谷歌教程中找到,人们对此会出错..

于 2011-05-24T13:17:31.043 回答
42

您使用的是哪个 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
}
于 2009-10-13T19:56:11.487 回答
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!
}

繁荣!!

另外,请在此处查看 android 工程师的答案: WindowManager$BadTokenException

此错误的一个原因可能是尝试通过不是 Activity 的 Context 显示应用程序窗口/对话框。

现在,我同意,该方法采用 Context 参数而不是 Activity 是没有意义的。

于 2010-05-05T22:32:05.970 回答
10

阅读上述答案后,我发现对于我的情况,以下解决了该问题。

这引发了错误

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() 不返回有效上下文的事实?(只是猜测)。

于 2010-11-12T12:30:21.850 回答
6

我正在创建一个带有逐项叠加的地图视图。我正在从我的 mapActivity 创建我的 itemizedoverlay:

OCItemizedOverlay currentLocationOverlay = new OCItemizedOverlay(pin,getApplicationContext);

我发现当我的 itemizedoverlay 的 onTap 方法被触发时(当在地图视图上点击位置时),我会得到“android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application”异常。

我发现如果我只是将 'this' 而不是 'getApplicationContext()' 传递给我的构造函数,问题就消失了。这似乎支持了alienjazzcat 的结论。奇怪的。

于 2010-08-06T19:32:32.710 回答
4

对于 TabActivities 中显示的活动,请使用getParent()

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

代替

final AlertDialog.Builder builder = new AlertDialog.Builder(this);
于 2012-01-09T11:53:44.283 回答
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)方法之外创建的。

于 2011-05-26T10:07:46.787 回答
3

尝试 -

AlertDialog.Builder builder = new AlertDialog.Builder(getParent());
于 2011-07-11T13:06:12.567 回答
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 以使其有更多时间来获取上下文。仍然不能保证这会起作用,它只是减少了崩溃的可能性。如果它仍然不起作用,您将不得不求助于计时器黑客(这可能会导致其他计时问题,例如稍后关闭对话框)。

当然,如果你可以使用thisor ActivityName.this,它会更稳定,因为它this已经指向了一些东西。但在某些情况下,例如某些 Fragment 架构,这不是一种选择。

于 2013-02-14T03:50:27.160 回答
2

(供将来参考)

我认为这是因为应用程序上下文和活动上下文存在差异,如下所述:http: //www.doubleencore.com/2013/06/context/

这意味着我们不能使用应用程序上下文显示对话框。就是这样。

于 2014-03-02T15:12:15.210 回答
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;
}

就是这样^_^

于 2016-09-19T13:31:28.887 回答
1

为了解决这个问题,我为我存储全局数据的所有活动创建了一个基类。在第一个活动中,我将上下文保存在基类的变量中,如下所示:

基类

public static Context myucontext; 

从基类派生的第一个活动

mycontext = this

然后我在创建对话框时使用 mycontext 而不是 getApplicationContext。

AlertDialog alertDialog = new AlertDialog.Builder(mycontext).create();
于 2010-08-01T08:15:26.223 回答
1

如果您在片段中调用 ProgressDialog.show(),则将 mContext 转换为 Activity 对我有用。

     ProgressDialog pd = new ProgressDialog((Activity) mContext);
于 2016-07-20T01:34:03.377 回答
1

这是一个常见的问题。使用this而不是getApplicationContext() 应该可以解决您的问题

于 2018-06-25T06:18:25.080 回答
0

我已经实现了警报对话框,以便将异常抛出到当前的活动视图中。每当我这样给出

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

给定相同的窗口异常。我为 onCreate() 之外的警报编写代码。如此简单,我在方法中使用context = this;aftersetContentView()语句。将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 上搜索了这个错误,我发现了这个查询。在阅读了这篇文章的所有回复后,我尝试了这种方式,所以它有效。我认为这是克服异常的简单解决方案。

谢谢,拉金达尔

于 2010-06-22T06:12:40.483 回答
0

如果您对 groupActivity 有问题,请不要使用它。PARENT 是来自 Parent ActivityGroup 的静态变量。

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

代替

final AlertDialog.Builder builder = new AlertDialog.Builder(getParent());
于 2012-02-03T11:50:39.103 回答
0

对话框总是作为 Activity 的一部分创建和显示。您需要传入 Activity 上下文而不是 Application 上下文。

http://developer.android.com/guide/topics/ui/dialogs.html#ShowingADialog

于 2012-10-03T19:04:37.817 回答