BadTokenException: Unable to add window -- token android.os.BinderProxy

2023-05-16

由于遇到的是BadTokenException这个异常,所以搜资料总结了一下:


这个异常总共有一下几种出现方式:

  • 1.Unable to add window --token null is not valid; is your activity running

  • **2.Unable to add window --token null is not for an application **

  • 3.Unable to add window -- token android.os.BinderProxy@XXX is not valid;
    is your activity running

  • **4.Unable to add window -- token android.app.LocalActivityManager
    $LocalActivityRecord @xxx is not valid; is your activity running
    **

处理方式分别是

情形1.android.view.WindowManager$BadTokenException: Unable to add window --token null is not valid; is your activity running?异常处理。

$BadTokenException: Unable to add window -- 
token null is not valid; is your activity running 

E/AndroidRuntime(1412): at android.view.ViewRootImpl.setView(ViewRootImpl.java:538) 
......

该异常多见于Popup Window组件的使用中抛出。

原因:错误在PopupWindow.showAtLocation(findViewById(R.id.main), Gravity.BOTTOM,0,0); popwindow必须依附于某一个view,而在oncreate中view还没有加载完毕,必须要等activity的生命周期函数全部执行完毕,你需要依附的view加载好后才可以执行popwindow。

解决办法:showAtLocation()函数可以这样改:

//修正后代码
findviewById(R.id.mView).post(new Runnable() {
                        @Override
                        public void run() {
                                popwindow.showAtLocation(mView, Gravity.CENTER, 0, 0);

                        }
                });

总结: PopupWindow必须在某个事件中显示或者是开启一个新线程去调用,不能直接在onCreate方法中显示一个Popupwindow,否则永远会有以上的错误。

参考
http://stackoverflow.com/questions/4187673/problems-creating-a-popup-window-in-android-activity

 

情形2.android.view.WindowManager$BadTokenException: Unable to add window --token null is not for an application ?异常处理

$BadTokenException: Unable to add window -- 
token null is not for an application 

E/AndroidRuntime(1412): at android.view.ViewRootImpl.setView(ViewRootImpl.java:538) 
......

该异常多见于AlertDialog组件的使用中抛出。

//抛异常代码
new AlertDialog.Builder(getApplicationContext())  //不能用getApplicationContext()
            .setIcon(android.R.drawable.ic_dialog_alert)  
            .setTitle("Warnning")  
            .setPositiveButton("Yes", positiveListener)
            .setNegativeButton(  "No", negativeListener)
            .create().show(); 

原因:导致报这个错是在于new AlertDialog.Builder(mcontext),虽然这里的参数是AlertDialog.Builder(Context context),但我们不能使用getApplicationContext()获得的Context,而必须使用Activity,因为只有一个Activity才能添加一个窗体。

解决方法:将new AlertDialog.Builder(Context context)中的参数用Activity.this(Activity是你的Activity的名称)或者getActivity()来填充就可以正确的创建一个Dialog了。

//修正后代码
new AlertDialog.Builder(this)  //this可以替换为MainActivity.this或getActivity()
            .setIcon(android.R.drawable.ic_dialog_alert)  
            .setTitle("Warnning")  
            .setPositiveButton("Yes", positiveListener)
            .setNegativeButton(  "No", negativeListener)
            .create().show(); 

参考
http://stackoverflow.com/questions/20779377/android-custom-dialog-gives-an-error

情形3.android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@XXX is not valid; is your activity running?异常处理。

android.view.WindowManager$BadTokenException: Unable to add window -- 
token android.os.BinderProxy@4250d6d8 is not valid; is your activity running?
    at android.view.ViewRootImpl.setView(ViewRootImpl.java:698)
   
    ......
    at dalvik.system.NativeStart.main(Native Method)

原因:从错误信息我们也可以明白其原因,此问题根本原因就是由于将要弹出的dialog所要依附的View已经不存在导致的。当界面销毁后再弹出来;或者界面跳转时我们的view发生改变,dialog依附的context发生变化或者界面未运行了。

解决方法:界面已经销毁引起的错误就只能判断界面是否存在然后再弹出了。

//修正后代码
if(!isFinishing()) {
     alert.show();
 }

参考
http://stackoverflow.com/questions/25554279/unable-to-add-window-token-android-os-binderproxy4250d6d8-is-not-valid-is-your

https://github.com/VKCOM/vk-android-sdk/issues/21

情形4.android.view.WindowManager$BadTokenException: Unable to add window -- token android.app.LocalActivityManager$LocalActivityRecord @xxx is not valid; is your activity running? 异常处理

android.view.WindowManager$BadTokenException: Unable to add window -- 
token android.app.LocalActivityManager$LocalActivityRecord@43e5b158
is not valid; is your activity running?  
//异常代码
TipDialog dialog = new TipDialog(XXX.this) ;

原因:因为new对话框的时候,参数context 指定成了this,即指向当前子Activity的context。但子Activity是动态创建的,不能保证一直存在。其父Activity的context是稳定存在的,所以有下面的解决办法。

解决方法:将context替换为getParent()即可。 注意:要创建dialog对象,上下文环境必须是activity,同时若ActivityGroup中嵌套ActivityGroup,嵌套多少就该使用多少个getParent()。

//修正后代码,只有最多一个parent的情形
TipDialog dialog = new TipDialog(getParent()) ; 
//修正后代码,适用于一个或多个parent的情形
Activity activity = TestActivity.this;  
while (activity.getParent() != null) {  
    activity = activity.getParent();  
 }  
              
TipDialog dialog = new TipDialog(activity) ;                   

参考
http://stackoverflow.com/questions/9914195/webview-in-activity-group-crashing-on-dialogs

注:为什么要使用getParent我们可以从ActivityGroup的内部机制来理解:

TabActivity的父类是ActivityGroup,而ActivityGroup的父类是Activity。因此从Ams的角度来看,ActivityGroup与普通的Activity没有什么区别,其生命周期包括标准的start,stop,resume,destroy等,而且系统中只允许同时允许一个ActivityGroup.但ActivityGroup内部有一个重要成员变量,其类型为LocalActivityManager,该类的最大特点在于它可以访问应用进程的主类,即ActivityThread类。Ams要启动某个Activity或者赞同某个Activity都是通过ActivityThread类执行的,而LocalActivityManager类就意味着可以通过它来装载不同的Activity,并控制Activity的不同的状态。注意,这里是装载,而不是启动,这点很重要。所谓的启动,一般是指会创建一个进程(如果所在的应用经常还不存在)运行该Activity,而装载仅仅是指把该Activity作为一个普通类进行加载,并创建一个该类的对象而已,而该类的任何函数都没有被运行。装载Activity对象的过程对AmS来讲是完全不可见的,那些嵌入的Activity仅仅贡献了自己所包含的Window窗口而已。而子Activity的不同状态是通过moveToState来处理的。

所以子Activity不是像普通的Activity一样,它只是提供Window而已,所以在创建Dialog时就应该使用getParent获取ActivityGroup真正的Activity,才可以加Dialog加入Activity中。

以上摘自https://www.jianshu.com/p/4c5fafe08fa7

我遇到的情况属于第三种,但是并没有解决我的问题,于是我又找到了这篇

 

android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@41791b20 is not valid; is your activity running?
at android.view.ViewRootImpl.setView(ViewRootImpl.java:546)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:302)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:216)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:141)
at android.view.Window$LocalWindowManager.addView(Window.java:537)
at android.app.Dialog.show(Dialog.java:278)
at android.app.AlertDialog$Builder.show(AlertDialog.java:991)
at android.widget.TextView.onTouchEvent(TextView.java:8430)
at android.view.View.dispatchTouchEvent(View.java:5553)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2027)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2027)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1762)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1953)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1397)
at android.app.Activity.dispatchTouchEvent(Activity.java:2431)
at dalvik.system.NativeStart.main(Native Method)

1,错误分析:

从错误信息我们也可以明白其原因,此问题根本原因就是由于将要弹出的dialog所要依附的View已经不存在导致的。

2,什么地方可能照成此问题:当界面销毁后再弹出来;或者界面跳转时我们的view发生改变,dialog依附的context发生变化或者界面未运行了。

此外,很多时候我们需要通过一个非组件类来调用一个view类的方法来弹出dialog或Toast,这样就需要再提供一个静态context来创建这个dialog或者Toast

例如我们在一个view中通过一个静态类来弹出一个对话框:

AlertDialog.Builder builder = new AlertDialog.Builder(mContextNew);

当然并不是所有静态context都是可以用来创建dialog的,例如***App().getApplication().getApplicationContext()这个context就不行,因为它并不代表哪一个Activity或者View。。这样就无法add这个dialog。

此view用于绑定显示数据,我们在其构造方法中初始化一个静态变量mContextNew为此view的mContext。这样我们就可以通过一个静态类来弹出对话框了,只需传入这个静态的context(mContextNew)就可以了。。

但是这个静态的context如果只在构造方法中初始化的话是会存在问题的,因为如果另起了一个界面其绑定数据的view也是用的这个view那么这个静态context就会被重新修改。。

因此当这个新的界面finish后返回到上次的界面,这个静态的context是刚才已经finish的view的context。因此如果仍然传入这个静态变量通过一个静态类来弹出对话框就会出现上述找不到window的错误了。

解决办法:

对于tab页出现的错误可以用其父类的context来弹出dialog;  对于界面已经销毁引起的错误就只能判断界面是否存在然后再弹出了;

对于利用静态context来弹出的dialog可以通过规避的方式来解决,比如避免出现静态context被修改。。但是这样就可能限制了我们程序的功能。。

因此我们可以通过在bind数据时时时更新这个静态context就可以解决此问题了,这样就可以保证这个静态的context在任何view中都是当前的界面的view的context。就不会出现找不到其父类window了。

以上摘自https://www.cnblogs.com/awkflf11/p/5293267.html

这个说明更加清晰一些,是说给AlertDialog.Builder builder = new AlertDialog.Builder(mContextNew);传入的静态context已经发生了变化,但是要弹出的Dialog还是用的老的context,所以我们要更新这个context才行,所以我查了我的代码,确定是这个错误。贴一下我的代码

public void showProgressDialog(Context context) {

        if(progressDialog == null) {
            progressDialog = new ProgressDialog(context);
            progressDialog.setMessage("正在加载中...");
            progressDialog.setCancelable(false);
        }
        progressDialog.show();

    }


    public void hideProgressDialog(){
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
            progressDialog=null;    
        }

    }

在网络请求之前调用showProgressDialog(Context context),网络请求之后调用hideProgressDialog().以上两个方法都是在MainActivity的Tab中的fragment中调用的,当我点击返回键返回到桌面,再回到MainActivity中的这个Fragment中时,调用showProagressDialog(Context context),由于我判断了当progressDialog== null时才会创建ProgressDialog所以此时progressDialog已经创建过了是存在这个对象的,所以不会重新创建,但是我们此时用的context是上次销毁的Mainactivity对象,而不是此时新创建的MainActivity,所以就会报错。解决办法就是在progressDialog.dismiss();方法后面添加progressDialog=null,下次ProgressDialog会重新创建,而且使用总是最新的Mainactivity对象。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

BadTokenException: Unable to add window -- token android.os.BinderProxy 的相关文章

  • 将 vim 的强大功能融入 WM:模态窗口管理? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我是 Vim 的忠实粉丝 并且在很大程度上坚持极其高效的模式编辑风格 在使用 Vim 一些经验之后 我决定使用其他分享其高效 快速键盘使用理念的软件
  • 在 PowerShell 窗口中运行应用程序

    我正在尝试放弃命令提示符 因为它是一个死胡同 转向 PowerShell ISE 我还没有弄清楚如何在 PowerShell ISE 窗口中运行命令行应用程序 每次我使用 开始进程 时 都会出现 然后消失 命令提示符窗口 我看到有些人建议
  • Activity 已泄漏窗口

    在我的启动屏幕中 我做了它 以便它检测 wifi 或 3g 是否启用 如果不是 则会出现一个对话框屏幕提示用户退出并打开其中一个 如果它打开 则代码将继续 我的 logcat 中不断收到有关我的活动有泄漏窗口的错误 我不知道如何解决这个问题
  • C# 将程序添加到Windows启动(Windows 7)

    我试图通过将程序执行路径添加到注册表编辑器来将我的程序添加到 Windows 启动程序中 这是代码 RegistryKey registryKey Registry CurrentUser OpenSubKey SOFTWARE Micro
  • 如何更改 Sublime Text 中输出面板的位置?

    我希望输出显示在代码的右侧 而不是下面 我可以将视图更改为两列 但无法更改输出面板的位置 例如 是否可以将输出面板的位置更改为代码的右侧 而不是代码的下方 有一种解决方案已经存在多年 但似乎并未得到广泛使用 这是包buildview 它将构
  • 如何在 Pygame 中获取显示器的分辨率?

    我只是想知道我是否可以在 Pygame 中获取显示器的分辨率 然后使用这些尺寸创建一个窗口 以便启动程序检测显示器分辨率 然后自动将窗口适合全屏屏幕 我目前正在使用pygame display set mode AN INTEGER AN
  • 当页面比屏幕大时如何将div定位在屏幕中间

    您好 我正在使用类似于以下内容的方法来将 div 放置在屏幕中间
  • ANTLR4:隐式或显式标记定义

    在 ANTLR4 中使用显式标记定义有哪些优点和缺点 我发现单括号中的文本比创建单独的标记并使用它代替文本更具描述性且更易于使用 E g grammar SimpleTest top library module library libra
  • createwindow(...)之后,如何给窗口赋予颜色?

    我创建了一个窗口 其句柄是handle parent 然后我创建了一个子窗口 如下所示 hwnd child CreateWindow child class name T WS CHILDWINDOW 0 0 0 0 hwnd paren
  • 推送通知设备令牌?

    如何从我的 iPhone 设备获取设备令牌 此方法将在调试模式下在控制台中打印 deviceToken 如果您想查看设备令牌 也可以在 UIAlert 中看到 void application UIApplication applicati
  • 新发布的“使用Google Play服务进行身份验证”,通过GoogleAuthUtil.getToken获取令牌的问题

    Update 刚才我使用我也用于 Google App Engine 的 Google 帐户注册了 Google API 现在错误已更改为com google android gms auth GoogleAuthException Unk
  • 如何使调整 WPF 窗口大小时不那么“滞后”?

    我对 WPF 世界比较陌生 我立即注意到的一件事是 当您调整窗口大小时 窗口内容的绘制是多么滞后 例如 如果窗口边缘有滚动条 则这些滚动条在缩小时将部分隐藏 并且在放大时它们与窗口边框之间有空间 即使在 Visual Studio 中创建的
  • JavaScript 丢失带有私有/公共属性的“this”对象引用

    我在运行以下页面时出现以下错误 this testpublic 不是一个函数 test function var testprivate function this testpublic this testpublic function c
  • 为什么从 App.xaml 设置样式 TargetType="Window" 不起作用?

    我正在 VS2013 中创建一个简单的 WPF 项目 我想将属性应用到我的主窗口 我将它们设置在我的App xaml像这样的文件
  • C++/SFML 显示故障,通过鼠标单击更改精灵成员

    我正在学习 C SFML 作为练习 我正在制作一个小程序 在窗口中显示 64x64 像素方形棕色精灵的 10x10 网格 该程序允许您使用键盘选择绿色 黄色 蓝色 灰色 棕色方形精灵 并用该选定的精灵替换所述网格上的任何图块 游戏循环如下
  • 无法打开目标 = 空白的 Electron webview 链接

    我正在使用 Electron 我有一个显示外部网站的 webview 但我无法成功显示通常由该网站上的链接打开且目标 blank 的附加窗口 a href mentions html target blank Mentions l gale
  • Tkinter - 窗口焦点丢失事件

    是否有事件触发tkinter窗口失去可以绑定到的焦点tkinter窗口使用 bind method 您正在寻找的活动是
  • .NET WPF 窗口淡入和淡出动画

    下面是窗口淡入和淡出动画的代码片段 Create the fade in storyboard fadeInStoryboard new Storyboard fadeInStoryboard Completed new EventHand
  • java中如何制作弹出窗口

    我目前正在开发一个java应用程序 我想显示一个包含文本区域和按钮的新窗口 你有什么想法 同样的答案 J选项面板 http docs oracle com javase 7 docs api javax swing JOptionPane
  • 关闭主窗口时 WPF 应用程序不会关闭

    我习惯了在 Visual Studio 中进行 WinForms 编程 但我想尝试一下 WPF 我向我的项目添加了另一个窗口 名为 Window01 主窗口称为MainWindow 之前public MainWindow 构造函数我声明Wi

随机推荐

  • Ubuntu ver.22.04.2 root用户登录

    ps xff1a 因为站内的多种方法需要的文件 xff0c 我的白板机没有 xff0c 于是提供下自己的解决思路 补充 xff1a 一种可能的方法 xff1a 打开终端 xff0c 键入sudo i 回车 xff0c 并输入当前账户的密码
  • go语言中time包基础内容

    目录 一 介绍简单的几个时间UTC CST CDT 二 获取时间的函数 三 时间的加 减 等 四 判断两时间发生前后 五 周期性定时器 time Tick 时间间隔 六 时间也有格式化 七 时间字符串格式的解析 八 时区 xff08 tim
  • 一,HTML&CSS

    一个网页是由三部分组成 xff0c 分别是 xff1a 结构 xff1a 对应的是 HTML 语言表现 xff1a 对应的是 CSS 语言行为 xff1a 对应的是 JavaScript 语言 1 HTML 1 xff09 文件结构 xff
  • centos7学习笔记:开启虚拟机黑屏

    问题 xff1a centos7开机进入到登录界面黑屏 xff0c 无法登陆到图形化界面 因为我自己之前出现过一次这种情况 xff0c 上一次删除了 xff0c 但又出现这种问题了 xff0c 所以打算记录下来 xff0c 最后其实是做了个
  • windows修改cmd终端样式

    一下为我的终端样式 xff08 有点丑 xff09 修改这个其实很简单 首先 win 43 r 输入 regedit 在上面搜索 计算机 HKEY LOCAL MACHINE SOFTWARE Microsoft Command Proce
  • SpringCloud ---启动顺序

    1 启动Eureka服务模块 2 启动Eureka客户端被调用者模块 3 最后启动Eureka调用者模块
  • Zabbix6.0LTS安装流程

    安装环境选择 xff1a eSXI6 7 43 CentOS8 43 Zabbix6 0LTS 43 MySQL 43 Apache zabbix官方网站 xff1a 下载Zabbix 1 打开命令行控制台 xff08 ctrl 43 al
  • Java中Arrays类中的数组操作方法详解

    前言 我们讲到了一维数组和二维数组以及开发工具eclipse的配置 java util Arrays 类能方便地操作数组 xff0c 它提供的所有方法都是静态的 具有以下功能 xff1a 替换元素以及填充元素 xff1a 通过 fill 方
  • 【一行命令】查看Linux系统查看端口长连接数量

    netstat an grep 8080 wc l
  • JAVA中集合类概述

    目录 前言 一 集合类概述 二 Collection 1 List实现 2 set实现 三 Map 总结 前言 这篇文章是根据张席主编的 JAVA语言程序设计教程 提炼出来的一些JAVA中集合的知识 xff0c 还会加上我在编程过程中的遇到
  • 归并排序算法

    目录 何为归并排序 排序步骤 合并过程 全过程 归并排序实现代码 xff08 C语言描述 xff09 复杂度分析 归并排序的优缺点 何为归并排序 归并排序 merge sort 是建立在归并操作上的一种有效 xff0c 稳定的排序算法 xf
  • 生产者消费者设计模式

    生产者和消费者模式 是一个经典的多线程设计模式 xff0c 生产者和消费者在同一时间段内共用同一个存储空间 xff0c 生产者往存储空间中添加产品 xff0c 消费者从存储空间中取走产品 xff0c 当存储空间为空时 xff0c 消费者阻塞
  • MySQL/MariaDB 字段约束

    主键约束 primary key 唯一且不为空 主键约束 xff1a 如果为一个列添加了主键约束 xff0c 那么这个列就是主键 xff0c 主键的特点是唯一且不能为空 通常情况下 xff0c 每张表都会有主键 添加主键约束 xff0c 例
  • MySQL/MariaDB 时间函数

    获取年月日时分秒 SELECT NOW 年月日及当前时间 SELECT CURDATE 年月日 SELECT CURRENT DATE 年月日 SELECT CURTIME 时分秒 SELECT CURRENT TIME 时分秒 年份 YE
  • MySQL/MariaDB 查询语句

    基础表 emp 去重查询 DISTINCT 查询职位 SELECT job from emp 显示所有职位 SELECT DISTINCT job FROM emp 查看表中包含的所有job类型 xff0c 重复的只显示一个 输出结果 限制
  • Spring框架通过工厂实现对象实例化过程

  • Eclipse常用设置

    1 界面风格 2 代码字体字号 3 工作空间编码
  • SpringBoot整合HikariCP连接池

    整合 HikariCP 连接池 创建依赖 配置连接池 打开 application properties 配置文件 xff0c 添加如下内容 spring datasource url 61 jdbc mysql dbgoods serve
  • SpringBoot框架整合MyBatis

    添加 MyBatis 启动依赖 参考官网mybatis org spring 找到Spring Boot菜单选项 基于菜单项找到MyBatis启动依赖 xff0c 一定要设置版本 xff0c Spring Boot 中没有设置 MyBati
  • BadTokenException: Unable to add window -- token android.os.BinderProxy

    由于遇到的是BadTokenException这个异常 xff0c 所以搜资料总结了一下 xff1a 这个异常总共有一下几种出现方式 xff1a 1 Unable to add window token null is not valid