为什么在android中恢复活动会导致异常?

为什么在android中恢复活动会导致异常?,android,android-activity,window-managers,Android,Android Activity,Window Managers,各位,有人能解释一下这个堆栈吗?请注意,上面没有我的代码。如果你在谷歌上搜索这些异常,每个遇到这个问题的人都试图在活动终止后创建对话框,这里的情况似乎不是这样。这只是一份简单的活动简历。我经常看到该领域的客户报告此异常情况,如果可能,我希望予以纠正 android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@405177d8 is not valid; is

各位,有人能解释一下这个堆栈吗?请注意,上面没有我的代码。如果你在谷歌上搜索这些异常,每个遇到这个问题的人都试图在活动终止后创建对话框,这里的情况似乎不是这样。这只是一份简单的活动简历。我经常看到该领域的客户报告此异常情况,如果可能,我希望予以纠正

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:

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类中,我有以下代码:

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();
    }
}
因此,该活动尚未完成,因此应仍然有效


此外,行号似乎与您在google源代码中看到的不匹配。在2.3.3源代码中签出。第2268行位于私有方法CreateTumbnailBitmap中。崩溃客户端上传的构建版本是10,这表示SDK_INT是10,因此是2.3.3

有许多关于同一异常的报告。所有这些都指向使用错误的
上下文的某个视图

请参阅下面的示例,并尝试找出在您的活动中哪些地方正在做类似的事情:

检查
ViewRoot.java
code中的
setView(…)
方法。它可能会帮助您了解:

特别是以下几行:

case WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN:
  throw new WindowManagerImpl.BadTokenException(
    "Unable to add window -- token " + attrs.token
    + " is not valid; is your activity running?");

当Application.onCreate()中运行一个耗时的操作时,我可以不断地重现这个问题。 在这种情况下,如果我从启动程序中按下应用程序图标,然后快速按下home按钮并运行其他应用程序,我最终会崩溃

我的应用程序中导致此崩溃的更改是AndroidManifest.xml的活动声明中的
android:noHistory=“true”


看起来Android对待具有backbackback历史记录的活动和没有窗口标记的活动是不同的。

我也有同样的问题,同样的错误,没有堆栈跟踪

我一直在使用很多单例类,这些类包含一个指向活动上下文的变量。在重写代码以消除对上下文的此类引用之后,问题似乎消失了


因此,即使对话框没有问题,您也可能会发现在代码的其他位置以错误的方式引用了上下文。

这个崩溃困扰了我很长一段时间,但最终我解决了它。 只需在活动类中添加以下代码

private boolean mDestroyed = false;

public final boolean isActivityDestroyed() {
    return mDestroyed;
}

@Override
protected void onPostResume() {
    super.onPostResume();
    if(isFinishing()){
        finish();
    }
}

@Override
public boolean isFinishing() {
    return super.isFinishing() || isActivityDestroyed();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    mDestroyed = true;
}

这对我来说很有效,但我不知道这次坠机的根本原因。阅读AOSP中的ActivityThread.java和ViewRootImpl.java之后,您将清楚地看到。

发布引发异常的活动的一些代码。这是我看到的唯一堆栈,因此在本例中,我不知道是哪个活动导致了异常。我通过添加一个unhandledexceptionhandler来获得上面的堆栈,该处理程序将堆栈跟踪远程上载到我的服务器。因此,在处理程序上发布一些代码,以及如何添加它…K,用处理程序如何工作的代码更新了原始问题。您解决了这个问题吗?我有完全相同的问题,我没有找到解决办法。该设备是HTC One S和安卓4.0.3。感谢您提供的信息。不幸的是,这些似乎都与同一个bug有关:调用getApplicationContext()并将其作为上下文传递给Dialog.show。这似乎不是我的问题。此外,我的应用程序代码都不在堆栈上这一事实令人困惑;我希望在堆栈上看到我的代码。是的,堆栈中的缺陷是阻止我们得出结论的原因。我正在查看异常之前堆栈中的最后一行:
位于android.view.ViewRoot.setView(ViewRoot.java:527)
,它提示我使用onDraw()或onStart()方法尝试膨胀视图。对,因此ViewRoot()的第497行实际上返回了WindowManagerImpl.ADD\u BAD\u SUBWINDOW\u TOKEN或WindowManagerImpl.ADD\u BAD\u APP\u TOKEN。我刚刚检查了一下,我的onStart方法所做的就是调用FlurryAgent.onStartSession(这里是Constants.FlurryClientId)。我没有现成的方法。当然有可能是flurry在扔东西;然而,我刚刚做了一个测试,在我的onStart方法中执行了一个DivideByZero异常,它确实出现在堆栈上。因此,我不认为flurry在这种情况下抛出了一个异常;具体来说,当我在后台放置一个视图,然后单击应用程序图标将其还原时,我在堆栈上看不到HandlerLaunchActivity。看看这个线程:我想知道之前是否有一些不相关的异常触发了“重新启动”,但它本身失败了?关键字是
android.app.ActivityThread.handleResumeActivity
。不是关于任何视图或对话框。这是活动本身无法附加到窗口的原因。因此,这个答案与问题无关。“在Application.onCreate中运行耗时的操作”您不应该在主线程上执行耗时的操作。我知道,这有助于始终如一地重现问题并理解根本原因。即使我没有耗时的操作,也存在竞争条件,我们的一小部分用户仍然有可能崩溃。有一个中文博客解释了为什么会发生这种情况。如果应用程序和活动的onCreate花费了大量时间,则使用android:noHistory=“true”
的活动将完成。这些解决方案减少了onCreate或仅仅删除
android:noHistory=“true”
所需的时间,正如在其他答案中所说的,我猜您在某处引用了上下文。
private boolean mDestroyed = false;

public final boolean isActivityDestroyed() {
    return mDestroyed;
}

@Override
protected void onPostResume() {
    super.onPostResume();
    if(isFinishing()){
        finish();
    }
}

@Override
public boolean isFinishing() {
    return super.isFinishing() || isActivityDestroyed();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    mDestroyed = true;
}