美文网首页
Android7.1.1(API25) Toast异常

Android7.1.1(API25) Toast异常

作者: 主音King | 来源:发表于2020-08-17 09:15 被阅读0次

    在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没有捕获异常:


    image.png

    在api25之后进行了try catch


    image.png

    相关文章

      网友评论

          本文标题:Android7.1.1(API25) Toast异常

          本文链接:https://www.haomeiwen.com/subject/lwhydktx.html