在Android7.1.1(API25)上同时展示两个windowmanager.LayoutParams.type = type_toast,会抛出错误:
android.view.WindowManager$BadTokenException
Unable to add window -- token android.os.BinderProxy@451a42a is not valid; is your activity running?
测试代码:
WindowManager mw = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
TextView tv = new TextView(this);
tv.setLayoutParams(new WindowManager.LayoutParams(-2,-2));
tv.setText("windowmanager 添加悬浮窗");
WindowManager.LayoutParams params =new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_TOAST;
mw.addView(tv,params);
Toast toast = new Toast(this);
toast.makeText(this,"API25 type_toast",Toast.LENGTH_LONG).show();
可以通过反射解决:
/**
* 7.1.1(api25)Toast BadTokenException问题;之后版本Google捕获异常,就不会crash了。
* Android,利用反射捕获异常解决版本中遇到的问题。
*/
public class SafeToast {
private static final String TAG = "SafeToast";
private static Field sField_TN;
private static Field sField_TN_Handler;
private static Toast mToast;
static {
try {
sField_TN = Toast.class.getDeclaredField("mTN");
sField_TN.setAccessible(true);
sField_TN_Handler = sField_TN.getType().getDeclaredField("mHandler");
sField_TN_Handler.setAccessible(true);
} catch (Exception e) {
Log.d(TAG, "static initializer: "+e);
}
}
private SafeToast() {
}
public static void show(Context context, CharSequence message, int duration) {
if (mToast == null) {
mToast = Toast.makeText(context.getApplicationContext(), message, duration);
hook(mToast);
} else {
mToast.setDuration(duration);
mToast.setText(message);
}
mToast.show();
}
public static void show(Context context, @StringRes int resId, int duration) {
if (mToast == null) {
mToast = Toast.makeText(context.getApplicationContext(), resId, duration);
hook(mToast);
} else {
mToast.setDuration(duration);
mToast.setText(context.getString(resId));
}
mToast.show();
}
private static void hook(Toast toast) {
try {
Object tn = sField_TN.get(toast);
Handler preHandler = (Handler) sField_TN_Handler.get(tn);
sField_TN_Handler.set(tn, new SafeHandler(preHandler));
} catch (Exception e) {
Log.d(TAG, "hook: "+e);
}
}
private static class SafeHandler extends Handler {
private Handler impl;
public SafeHandler(Handler impl) {
this.impl = impl;
}
@Override
public void dispatchMessage(Message msg) {
try {
super.dispatchMessage(msg);
} catch (Exception e) {
Log.d(TAG, "hook: "+e);
}
}
@Override
public void handleMessage(Message msg) {
impl.handleMessage(msg);//需要委托给原Handler执行
}
}
}
通过判断所用的手机sdk的api进行处理。
在api25之后,Google对toast进行了try catch处理。
在api25的时候Google没有捕获异常:

在api25之后进行了try catch

网友评论