Why does resuming an activity in android cause BadTokenException?

做~自己de王妃 提交于 2019-12-04 10:21:16

问题


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)

Update:

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

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.

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.


回答1:


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.

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

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




回答2:


There are numerous reports of the same exception. All point to some view that is using a wrong Context.

See examples below and try to find where in your Activity are doing something similar:

http://groups.google.com/group/android-developers/browse_thread/thread/7a648edddccf6f7d

http://www.anddev.org/view-layout-resource-problems-f27/how-to-fix-this-windowmanager-badtokenexception-t16555.html

Android: ProgressDialog.show() crashes with getApplicationContext

Android 1.6: "android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application"

Check at the setView(...) method in the ViewRoot.java code. It may help you figure out: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/view/ViewRoot.java#ViewRoot.setView%28android.view.View%2Candroid.view.WindowManager.LayoutParams%2Candroid.view.View%29

Specially, the lines:

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



回答3:


I had the same issue, same error without stack trace.

I had been using lots of singleton classes that held a variable pointing to an activity context. After rewriting my code to eliminate such references to context the problem seems to have disappeared.

So even if there's not problem with a dialog, you might find that you are referencing context in a wrong way some other place in your code.




回答4:


This Crash has troubled me for a long time, But finally I have fixed it. just add the following code in your Activity class

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

It works well for me, but I don't know the root cause about this crash. After read the ActivityThread.java and ViewRootImpl.java in AOSP, you will be clearly.



来源:https://stackoverflow.com/questions/5854290/why-does-resuming-an-activity-in-android-cause-badtokenexception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!