Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does resuming an activity in android cause BadTokenException?

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.

like image 527
esilver Avatar asked May 02 '11 06:05

esilver


1 Answers

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.

like image 78
Tapemaster Avatar answered Sep 18 '22 14:09

Tapemaster