我一直在努力找出这种例外的原因,但是我从来没有能够重现自己,但我的一些客户正在体验它。它只发生在Android 6.0.1上,并且由于SDK本身发生崩溃,因此很难弄清楚它是如何发生的。
有关此问题的其他解决方案没有帮助,例如:
window manager bad token exception
"android.view.WindowManager$BadTokenException: Unable to add window" on buider.show()
我正在使用DialogFragments和AlertDialogs,我想这可能是核心问题,但它只是没有加起来,因为它只会影响Marshmallow用户。
Fatal Exception: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
at android.view.ViewRootImpl.setView(ViewRootImpl.java:849)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:337)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
at android.widget.PopupWindow.invokePopup(PopupWindow.java:1329)
at android.widget.PopupWindow.showAtLocation(PopupWindow.java:1077)
at android.widget.PopupWindow.showAtLocation(PopupWindow.java:1035)
at com.android.internal.widget.FloatingToolbar$FloatingToolbarPopup.show(FloatingToolbar.java:561)
at com.android.internal.widget.FloatingToolbar.show(FloatingToolbar.java:212)
at com.android.internal.view.FloatingActionMode$FloatingToolbarVisibilityHelper.updateToolbarVisibility(FloatingActionMode.java:411)
at com.android.internal.view.FloatingActionMode$1.run(FloatingActionMode.java:65)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7224)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
答案 0 :(得分:22)
因此,在获得三星设备(S6)并能够重现此问题之后,我想出了下面描述的解决方案。
错误本身源自Marshmallow中添加的浮动工具栏和操作模式。在棉花糖设备上选择文字时会出现类似的情况:
如果用户随后导航到另一个活动(例如后退键)而未关闭浮动工具栏,则应用程序会在三星设备上崩溃。它基本上是尝试将浮动工具栏再次添加到即将进行的活动中。
有关浮动工具栏的更多信息:https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-text-selection
因此解决方案是管理操作模式生命周期并确保在任何新活动开始之前完成。我有一个基础活动类,我的所有活动都是从这里继承的,因此在那里添加解决方案是最有意义的。
public class BaseActivity extends AppCompatActivity {
private ActionMode mActionMode;
/**
* Store action mode if it is started
* @param mode
*/
@Override
public void onActionModeStarted(ActionMode mode) {
super.onActionModeStarted(mode);
mActionMode = mode;
}
/**
* When activity is paused, make sure action mode is ended properly.
* This check would feel better to have in onDestroy(), but that seems to be
* too late down the life cycle and the crash keeps on occurring. The drawback
* of this solution is that the action mode is finished when app is minimized etc.
*/
@Override
protected void onPause() {
super.onPause();
endActionMode();
}
/**
* Makes sure action mode is ended
*/
private void endActionMode() {
if (mActionMode != null) {
mActionMode.finish(); /** immediately calls {@link #onActionModeFinished(ActionMode)} */
}
}
/**
* Clear action mode every time it finishes.
* @param mode
*/
@Override
public void onActionModeFinished(ActionMode mode) {
super.onActionModeFinished(mode);
mActionMode = null;
}
}