android7.1.1系统,toast的exception:android.view.windowmanager$badtokenexception解决(代码片段)

怀化纱厂球迷 怀化纱厂球迷     2022-12-15     262

关键词:

 7.1.1系统版本,我发现问题很多,比如 有个接口字段用了base64,但是我添加包的时候用的 java.util.base64 结果会崩溃报错,网上搜索后要用 android.util.base64 来解决,

 

 今天发现突然有崩溃,看了下崩溃信息

Fatal Exception: android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@fcd9ef6 is not valid; is your activity running?
       at android.view.ViewRootImpl.setView(ViewRootImpl.java:806)
       at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:369)
       at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:94)
       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:186)
       at android.app.ActivityThread.main(ActivityThread.java:6491)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:914)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:804)

一下解决办法是我网上转过来的,经过自测后,解决了我的问题,我这边记录

这个BadTokenException是由谷歌系统产生的BUG,只有在系统7.x会产生,谷歌团队已经在8.0以上系统修复,但对于开发者来说面对android的7.x系统的用户不得不去解决这个BUG

BadTokenException产生的原因及谷歌的解决方案
在Toast.show()之后,UI线程做了耗时的操作阻塞了Handlermessage的处理。7.X系统对TYPE_TOAST的Window类型做了超时限制,绑定了WindowToken,如果UI在这段时间内没有执行完,Toast.show()内部的handlermessage得不到执行,NotificationManageService那端会把这个Toast取消掉,同时把Toast对于的windowtoken置为无效。等App端真正需要显示Toast时,因为windowtoken已经失效,ViewRootImpl就抛出了上面的异常。

我们看一下谷歌源码是如何解决的,8.0以上系统Toast的handleShow 方法里面的一段代码,mWM.addView(mView, mParams),是被try catch 了,在7.x的系统是没有被catch住的(这里就不贴代码了)
 

看到谷歌的解决方案,所以我们7.x的解决方案其实也是把异常给catch 住。那如何catch住呢?我们看Toast的源码时里面有个mHandler的成员变量,我们想办法把分发消息的dispatchMessage(Message msg) 异常捕获不就可以了吗?这个其实和谷歌的解决方案一样。

 这里我们采用Java的反射机制
 

try 
      sField_TN = Toast.class.getDeclaredField("mTN");
      sField_TN.setAccessible(true);
      sField_TN_Handler = sField_TN.getType().getDeclaredField("mHandler");
      sField_TN_Handler.setAccessible(true);
      Object tn = sField_TN.get(toast);
      //获取原有的Handler
      Handler preHandler = (Handler) sField_TN_Handler.get(tn);
      //设置自定义的Handler
      sField_TN_Handler.set(tn, new SafelyHandlerWarpper(preHandler));
     catch (Exception e) 
    

  这里我们设置自定义的Handler

/****
     * 自定义Handler catch处理异常
     */
    public static class SafelyHandlerWarpper extends Handler 
        private Handler impl;
 
        public SafelyHandlerWarpper(Handler impl) 
            this.impl = impl;
        
 
        @Override
        public void dispatchMessage(Message msg) 
            try 
                super.dispatchMessage(msg);
             catch (Exception e) 
            
        
 
        @Override
        public void handleMessage(Message msg) 
            impl.handleMessage(msg);//需要委托给原Handler执行
        
    
 

我们把dispatchMessage给catch住,handleMessage处理的消息具体实现还是原有的handler处理逻辑,不去影响原有的处理逻辑,我们只是catch住异常防止应用崩溃。

完整实现类如下:

/***
 *
 * 解决部分7.1.1手机崩溃Toast解决方案
 */
public class ZtAppCompatToast 
 
    private static Field sField_TN;
    private static Field sField_TN_Handler;
 
    private Toast mToast;
 
 
    static 
        //安卓7.0的做处理,其它版本系统的不用处理
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1 && Build.VERSION.SDK_INT > Build.VERSION_CODES.M) 
            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) 
            
        
    
 
    public ZtAppCompatToast(Context context) 
        mToast = new Toast(context);
        setHook(mToast);
    
 
    public Toast getToast() 
        return mToast;
    
 
    public static Toast makeText(Context context,
                                 CharSequence text, int duration) 
        Toast toast = Toast.makeText(context, text, duration);
        setHook(toast);
        return toast;
    
 
    public static Toast makeText(Context context,
                                 int textSrc, int duration) 
        Toast toast = Toast.makeText(context, textSrc, duration);
        setHook(toast);
        return toast;
    
 
    private static void setHook(Toast toast) 
        //安卓7.0的做处理,其它版本系统的不用处理
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1 && Build.VERSION.SDK_INT > Build.VERSION_CODES.M) 
            hook(toast);
        
    
 
    /*****
     *
     * @param toast
     */
    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 SafelyHandlerWarpper(preHandler));
         catch (Exception e) 
        
    
 
    /****
     * 自定义Handler catch处理异常
     */
    public static class SafelyHandlerWarpper extends Handler 
        private Handler impl;
 
        public SafelyHandlerWarpper(Handler impl) 
            this.impl = impl;
        
 
        @Override
        public void dispatchMessage(Message msg) 
            try 
                super.dispatchMessage(msg);
             catch (Exception e) 
            
        
 
        @Override
        public void handleMessage(Message msg) 
            impl.handleMessage(msg);//需要委托给原Handler执行
        
    
 

android7.1.1系统,toast的exception:android.view.windowmanager$badtokenexception解决(代码片段)

 7.1.1系统版本,我发现问题很多,比如有个接口字段用了base64,但是我添加包的时候用的java.util.base64结果会崩溃报错,网上搜索后要用android.util.base64来解决,  今天发现突然有崩溃,看了下崩溃信息Fatal... 查看详情

android7.1.1系统,toast的exception:android.view.windowmanager$badtokenexception解决(代码片段)

 7.1.1系统版本,我发现问题很多,比如有个接口字段用了base64,但是我添加包的时候用的java.util.base64结果会崩溃报错,网上搜索后要用android.util.base64来解决, 今天发现突然有崩溃,看了下崩溃信息 Fatal... 查看详情

android7.1.1系统设置默认值大全

1,是否有默认值在寻找一个开关的默认值时,首先要明白一点,该开关是否存在默认值,以及该开关状态是否有状态保存(一般状态存储在settings的db中)。判断条件:在reboot(重启)之后开关... 查看详情

android7.1.1之实现3dtouch(代码片段)

...或禁用更新返回栈问题Shortcut概念Shortcut是Android-25(Android7.1)新增的一项类似iOS的3DTouch功能的快捷 查看详情

textandroid的应用开发之android7.1.1出现吐司崩溃问题的解决方案(代码片段)

查看详情

还必须保留哪些android 7.0 sdk组件才能支持android 7.1.1

】还必须保留哪些android7.0sdk组件才能支持android7.1.1【英文标题】:Whichandroid7.0sdkcomponentsmuststillbekepttosupportandroid7.1.1【发布时间】:2017-07-2911:51:28【问题描述】:我尝试下载适用于android7.1.1的新系统映像组件时磁盘空间不足。我... 查看详情

使用系统toast的问题

...4.Android8.0之后的tokennullisnotvalid问题(实测部分机型问题);5.Android7.1之后,不允许同时展示两个TYPE_TOAST弹窗(实测部分机型问题);那么解决方案是:相信不少同学旧项目中封装的ToastUtil都是直接使用的ApplicationContext作为上下文,然后在... 查看详情

toastcustom自定义显示风格的toast

...本文为博主原创文章,未经博主允许不得转载。前言基于系统Toast的自定义显示风格的Toast。效果图代码分析ToastCustom类基于系统Toast,不是继承Toast,只是通过toast.setView(view)方法引用自定义的显示风格布局文件,达到自定义显示... 查看详情

android的toast怎么自定义显示时间长度?

...息提示框之所以在显示一定时间后会自动关闭,是因为在系统中有一个Toast队列。系统会依次从队列中取(出队列)一个Toast,并显示它。在显示一段时间后,再关闭,然后再显示下一个Toast信息提示框。直到Toast队列中所有Toast都显... 查看详情

启动 Airflow 网络服务器失败并出现 sqlalchemy.exc.NoInspectionAvailable:没有可用的检查系统

...失败并出现sqlalchemy.exc.NoInspectionAvailable:没有可用的检查系统【英文标题】:StartingAirflowwebserverfailswithsqlalchemy.exc.NoInspectionAvailable:Noinspectionsystemisavailable【发布时间】:2020-07-2022:13:46【问题描述】:安装正确。db正确启动并尝试... 查看详情

toast的window创建过程以及源码分析

...indow创建过程以及源码分析Toast是基于Window来实现的,系统中继承了handler做定时处理内部实现IPC过程,第一类访问NotificationManagerService(NMS)通过回调TN接口,实现Toast的显示隐藏Toast属于Window,它内部的视图由两种方... 查看详情

android中的toast源码分析和自定义toast(代码片段)

我的主页Demo下载地址一、系统自带Toast的源码分析1.Toast的调用显示学过Android的人都知道,弹出一个系统API吐司只需要一行代码,调用的是Toast对象的makeText()方法,方法里给一个上下文,显示的文字,和显示的... 查看详情

macossierra10.12.4编译android7.1.1源码必须跳的坑(代码片段)

简介下载Android7.1.1源码花费了两天,编译整个源码同样花费了2天,期间遇到无数个坑。现在编译源码,一旦中间遇到错误,则要重新开始。本文记录编译过程遇到的问题及解决方案,如有编译源码需求的可以... 查看详情

部分手机toast不显示的解决办法

...这个工厂进行Toast显示的时候会在自行维护的Toast队列与系统Toast之间选择 查看详情

Swift 追加到数组给了我 EXC_BAD_INSTRUCTION EXC_l386_INVOP 在 32 位系统上

】Swift追加到数组给了我EXC_BAD_INSTRUCTIONEXC_l386_INVOP在32位系统上【英文标题】:SwiftappendtoarraygivesmeEXC_BAD_INSTRUCTIONEXC_l386_INVOPon32-bitsystems【发布时间】:2014-11-2600:04:33【问题描述】:所以我试图解析一个字符串并用每个转换为字符... 查看详情

toast的window创建过程以及源码分析

...indow创建过程以及源码分析Toast是基于Window来实现的,系统中继承了handler做定时处理内部实现IPC过程,第一类访问NotificationManagerService(NMS)通过回调TN接口,实现Toast的显示隐藏Toast属于Window,它内部的视图由两种方... 查看详情

wpf在win10系统上弹出toast和notification

老规矩,先看效果右下角的notification:操作中心的notification:整体效果:前提条件1.需要在开始菜单里添加快捷方式。2.在注册表里注册你实现了INotificationActivationCallBack接口的com组件。3.一个APP_ID,添加到快捷方式里,ActionCenter会... 查看详情

android系统之路(初识mtk)------android11.0给系统相机添加闪光灯低电toast提醒(代码片段)

...操作但没有实际去打开闪光灯,因为底层添加了判断,当系统电量小于等于15%时,是不会去执行打开闪光灯等相关灯光操作的修改后的效果:无论是打开闪光灯常亮、闪光灯自动、手电筒只要当前系统电量小于等于15%时,都会让... 查看详情