14

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.

esilver
  • 25,374
  • 21
  • 112
  • 159

4 Answers4

7

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.

Tapemaster
  • 487
  • 5
  • 9
  • 1
    "time-consuming operation running in Application.onCreate" You should never have time consuming operation on the main-thread. – Jared Burrows Jul 21 '15 at 13:06
  • I know, that just helps to reproduce the issue consistently and understand the root cause. Even if I don't have time-consuming operation, there is a race condition, and a crash is still possible for small fraction of our users. – Tapemaster Jul 21 '15 at 13:14
  • 1
    There is a Chinese blog that explains why this occurs http://blog.desmondyao.com/android-bad-window-token/ . The activity with ```android:noHistory="true"``` will be finished if the Application and activity's onCreate cost much time. The solutions is reducing time consuming in onCreate or just remove ```android:noHistory="true"``` – Carlos Parker Oct 31 '17 at 02:11
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?");
Community
  • 1
  • 1
Aleadam
  • 39,361
  • 9
  • 84
  • 108
  • 1
    Thanks for the info. Unfortunately these all seem to be related to the same bug: calling getApplicationContext() and passing that as context to a Dialog.show. That does not appear to be my issue. Moreover, the fact that none of my application code is on the stack is confusing; I would expect to see my code on the stack. – esilver May 03 '11 at 20:29
  • Yes, that lack in the stack is what prevents us to reach a conclusion. I'm looking at the last line in the stack before the exception: `at android.view.ViewRoot.setView(ViewRoot.java:527)` which hints me to an onDraw() or onStart() method trying to inflate the View. – Aleadam May 03 '11 at 20:36
  • Right, so effectively line 497 of ViewRoot (http://bit.ly/itqRiP) is returning WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN or WindowManagerImpl.ADD_BAD_APP_TOKEN. I just checked and all my onStart methods do is call FlurryAgent.onStartSession(this, Constants.FlurryClientId). I have no onDraw methods. It is certainly possible that flurry is throwing; however, I just did a test where I did a DivideByZero exception in my onStart method and it does it fact appear on the stack. Thus, I don't think it is flurry throwing an exception in this case. – esilver May 03 '11 at 21:05
  • One curious thing: I am unsuccessful in my attempts to repro that exact same stack; specifically I don't see handleRelaunchActivity on the stack when I put a view in the background and then restore it by clicking on the application icon. Looking at this thread: http://stackoverflow.com/questions/4466529/uncaught-exception-relaunching-the-calling-activity I wonder if there may in fact be some unrelated exception earlier that is triggering a "relaunch" which itself fails? – esilver May 03 '11 at 21:17
  • But wouldn't you see the stack of that "unrelated exception" first? Perhaps the activity gets killed? – Aleadam May 03 '11 at 21:26
  • 2
    The keyword is `android.app.ActivityThread.handleResumeActivity`. Not about any view or dialog. It's the activity itself can't attach to the window. So this answer is not related to the question. – Kimi Chiu Dec 25 '16 at 02:12
0

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.

anti_gone
  • 773
  • 7
  • 17
-1

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.

Matrixxun
  • 1
  • 1