当我在我的android应用上频繁执行某些操作时(我的假设,这是由于Toast消息引起的),出现以下错误。我没有确切找到此问题的位置。我可以从某人那里寻求帮助来解决该问题吗?< / p>
--------- beginning of crash
10-04 16:13:49.250 6541-6541/com.test.myapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.test.myapp, PID: 6541
android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@e2815e is not valid; is your activity running?
at android.view.ViewRootImpl.setView(ViewRootImpl.java:679)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:342)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at android.widget.Toast$TN.handleShow(Toast.java:459)
at android.widget.Toast$TN$2.handleMessage(Toast.java:342)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
注意:这种崩溃并不总是会出现。
答案 0 :(得分:4)
在将Context
传递到Toast之前,应始终检查要使用的上下文的有效性。在我的应用程序中,我使用了一种上下文检查器方法:
public static boolean isContextValid(Context context, Fragment fragment) {
if (context instanceof Activity) {
Activity activity = (Activity) context;
if (activity.isFinishing() || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed())) {
return false;
}
}
return context != null && (fragment == null || (fragment.isAdded() && !fragment.isRemoving());
}
您只能传递一个上下文,如果当前上下文是一个片段,也可以传递Fragment
。此方法检查上下文是否为Activity
,在这种情况下,我们检查活动是否已完成/销毁。
如果要在片段生命周期之后显示吐司,还可以传递到当前片段的方法,这样我们就可以判断该片段是否仍然可见并附加到活动中。
BANDUS ANDROID 7.1
在API 25上,这还不够,有时设备仍会因您提供的堆栈跟踪而崩溃。
This repository可能是解决方案,因为它将错误的调用包装在try / catch子句中。当然,这不是最好的做法,但至少可以解决7.1设备的这种令人讨厌的崩溃。
答案 1 :(得分:0)
android.view.WindowManager $ BadTokenException:无法添加窗口-令牌android.os.BinderProxy@e2815e无效;您的活动正在进行吗?
在此行中,它向您提示您在尝试举杯时可能没有进行活动。
如果要在这样的活动中显示吐司,
Toast toast = Toast.makeText(this, R.string.message, Toast.LENGTH_LONG).show();
您应该意识到,您试图通过将第一个参数设置为'this'并以此方式(如果您finish())将其显示在Activity的上下文中;您在此行之前的活动,您将获得该异常。因此,我建议检查是否是这种情况,或者您可以改用Application的上下文:
Toast toast = Toast.makeText(getApplicationContext(), R.string.message, Toast.LENGTH_LONG).show();
希望这会有所帮助!
答案 2 :(得分:0)
这是Toast
在Android 8.0之后正式修复的问题,也可以通过将WindowManagerWrapper.addView(view, params)
与第三方lib PureWriter/ToastCompat挂钩来解决。
由于isFinishing
是异步进度,因此检查活动Toast.show()
无法解决崩溃问题:
Toast.makeText().show()
-> Toast.getService().enqueueToast()
-> Toast.TN.handleShow() // crash here, and unable to be caught from outside
在Android 8.0之后,崩溃被捕获在handleShow
中(请参阅最后几行):
public void handleShow(IBinder windowToken) {
if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
+ " mNextView=" + mNextView);
// If a cancel/hide is pending - no need to show - at this point
// the window token is already invalid and no need to do any work.
if (mHandler.hasMessages(CANCEL) || mHandler.hasMessages(HIDE)) {
return;
}
if (mView != mNextView) {
// remove the old view if necessary
handleHide();
mView = mNextView;
Context context = mView.getContext().getApplicationContext();
String packageName = mView.getContext().getOpPackageName();
if (context == null) {
context = mView.getContext();
}
mWM = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
// We can resolve the Gravity here by using the Locale for getting
// the layout direction
final Configuration config = mView.getContext().getResources().getConfiguration();
final int gravity = Gravity.getAbsoluteGravity(mGravity, config.getLayoutDirection());
mParams.gravity = gravity;
if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
mParams.horizontalWeight = 1.0f;
}
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) {
mParams.verticalWeight = 1.0f;
}
mParams.x = mX;
mParams.y = mY;
mParams.verticalMargin = mVerticalMargin;
mParams.horizontalMargin = mHorizontalMargin;
mParams.packageName = packageName;
mParams.hideTimeoutMilliseconds = mDuration ==
Toast.LENGTH_LONG ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT;
mParams.token = windowToken;
if (mView.getParent() != null) {
if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
mWM.removeView(mView);
}
if (localLOGV) Log.v(TAG, "ADD! " + mView + " in " + this);
// Since the notification manager service cancels the token right
// after it notifies us to cancel the toast there is an inherent
// race and we may attempt to add a window after the token has been
// invalidated. Let us hedge against that.
try {
mWM.addView(mView, mParams);
trySendAccessibilityEvent();
} catch (WindowManager.BadTokenException e) {
/* ignore */
}
}
}
答案 3 :(得分:0)
尝试使用应用程序上下文,而不是活动上下文。
更新: 抱歉,无论您传递给Toast的上下文是Activity还是ApplicationContext或Service,都会发生此异常。而且您无法尝试捕获它。
无法解决它,这是API 25上的一个Android SDK错误。 尝试编写一个新的Toast类。