为什么在android中恢复活动会导致BadTokenException? [英] Why does resuming an activity in android cause BadTokenException?

查看:86
本文介绍了为什么在android中恢复活动会导致BadTokenException?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

伙计-谁能解释这个堆栈?请注意,我的代码无处可寻.如果您针对上述任何一种情况使用Google进行搜索,那么遇到此问题的每个人都将在活动终止后尝试创建对话框,但情况似乎并非如此.这只是一个简单的活动简历.我看到该领域的客户经常报告此异常,并希望在可能的情况下更正此异常.

Folks - Can anyone explain this stack? Note that my code is nowhere on it. If you Google for any of these exceptions, everyone who has experiencing this issue was trying to create dialogs after an activity was terminated, which doesn't seem to be the case here. It's just a simple activity resume. I am seeing this exception reported from clients in the field quite frequently and would like to correct it if possible.

android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@405177d8 is not valid; is your activity running?
at android.view.ViewRoot.setView(ViewRoot.java:527)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
at android.view.Window$LocalWindowManager.addView(Window.java:424)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2268)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1721)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:2955)
at android.app.ActivityThread.access$1600(ActivityThread.java:124)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:972)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3806)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)

更新:

这是我能够远程检索此堆栈的方法.首先,在活动的onCreate顶部添加一个uncaughtExceptionHandler:

Here is how I am able to retrieve this stack remotely. First, I add an uncaughtExceptionHandler at the top of my activity's onCreate:

try {
  File crashLogDirectory = new File(Environment.getExternalStorageDirectory().getCanonicalPath() + Constants.CrashLogDirectory);
  crashLogDirectory.mkdirs();

  Thread.setDefaultUncaughtExceptionHandler(new RemoteUploadExceptionHandler(this, crashLogDirectory.getCanonicalPath()));
} catch (Exception e) {
  if (MyActivity.WARN) Log.e(MyActivity.TAG, "Exception setting up exception handler! " + e.toString());
}

在我的RemoteUploadExceptionHandler类中,我有以下代码:

In my RemoteUploadExceptionHandler class, I have the following code:

public void uncaughtException(Thread t, Throwable e) {        
  String timestamp = Calendar.getInstance().getTime().toGMTString();
  String filename = timestamp + ".stacktrace";
  final Writer result = new StringWriter();
  final PrintWriter printWriter = new PrintWriter(result);
  e.printStackTrace(printWriter);
  String stacktrace = result.toString();
  printWriter.close();
  sendToServer(stacktrace, filename);
  defaultUEH.uncaughtException(t, e);
}


private void sendToServer(String stacktrace, String filename) {
    DefaultHttpClient httpClient = new DefaultHttpClient();
    HttpPost httpPost = new HttpPost(Constants.RemoteUploadUrl);
    List<NameValuePair> nvps = new ArrayList<NameValuePair>();
    nvps.add(new BasicNameValuePair("filename", filename));
    nvps.add(new BasicNameValuePair("stacktrace", stacktrace));
    nvps.add(new BasicNameValuePair("platform_version", platformVersion));
    nvps.add(new BasicNameValuePair("device_id", deviceId));

    nvps.add(new BasicNameValuePair("build_device", Build.DEVICE));
    nvps.add(new BasicNameValuePair("build_brand", Build.BRAND));
    nvps.add(new BasicNameValuePair("build_product", Build.PRODUCT));
    nvps.add(new BasicNameValuePair("build_manufacturer", Build.MANUFACTURER));
    nvps.add(new BasicNameValuePair("build_model", Build.MODEL));
    nvps.add(new BasicNameValuePair("build_version", String.format("%d",Build.VERSION.SDK_INT)));

    try {
        httpPost.setEntity(
                new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
        httpClient.execute(httpPost);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

这是每小时向我发送很多堆栈的代码,就像上面显示的那样.

This is the code that is sending me many stacks per hour like the one I have shown above.

此外,如果您通过

Moreover, if you look at the ActivityThread code through google code search you can see this check prior to the call to addView:

if (r.window == null && !a.mFinished && willBeVisible) {

因此,该活动尚未完成,因此它应该仍然有效.

Thus, the activity has not finished and as such it should be still valid.

此外,行号似乎与您在google源代码中看到的不匹配.结帐

Additionally, the line numbers don't seem to match with what you can see in the google source code. Checkout the ActivityThread.java file in the 2.3.3 source. Line 2268 is in the private method createThumbnailBitmap. The Build Version uploaded by the crashing client is 10, which indicates SDK_INT is 10 and so it is 2.3.3.

推荐答案

当Application.onCreate()中运行耗时的操作时,我可以不断重现此问题. 在这种情况下,如果我按下启动器中的应用程序图标,但随后快速按下主页按钮并运行其他应用程序,则最终将导致此崩溃.

I could constantly reproduce this issue when there is a time-consuming operation running in Application.onCreate(). In this case if I press app icon from the launcher, but then quickly press home button and run other apps, I will eventually get this crash.

在AndroidManifest.xml的Activity声明中,android:noHistory="true"是我的应用程序中可能导致崩溃的更改.

The change in my app that makes this crash possible is android:noHistory="true" in Activity declaration of AndroidManifest.xml.

类似Android的活动具有后退历史记录,并且出于窗口令牌目的而没有区别.

Looks like Android treats activities with backstack history and without differently for window token purposes.

这篇关于为什么在android中恢复活动会导致BadTokenException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆