一、dialog.show()引起的android.view.WindowManager$BadTokenException错误
错误日志
?
1
2
3
4
5
6
7
android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy
@427b7270
is not valid; is your activity running?
at android.view.ViewRootImpl.setView(ViewRootImpl.java:
653
)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:
326
)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:
224
)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:
149
)
at android.view.Window$LocalWindowManager.addView(Window.java:
558
)
at android.app.Dialog.show(Dialog.java:
316
)
错误原因 错误原因是Dialog在show的时候必须要有一个activity作为窗口载体,上面的日志的意思是承载Dialog的activity已经被销毁了,不存在了 解决办法 1、在show之前加判断activity是否被销毁了 if(!isFinishing()){ dialog.show(); } 2、直接try catch(不推荐) 错误日志 android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application 错误原因 先说说上下文的使用 对话框它是我们的Activity的一部分,对话框它挂载在我们的Activity上; getApplicationContext()这个方法得到的是Context Activity.this 得到Context的一个子类 也就是说 Activity.this 相当于是getApplicationContext()的子类 父类有的子类一定有 - 没有 token 子类有的父类不一定有 --有 token this 还有Activity.this和我们的getApplicationContext(); 大多数情况推荐:Activity.this 解决办法 上下文大多数情况推荐:Activity.this 二、dialog.dismiss()引起的java.lang.IllegalArgumentException错误 错误日志
?
1
2
3
4
5
6
java.lang.IllegalArgumentException: View not attached to window manager
at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:
383
)
at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:
285
)
at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:
104
)
at android.app.Dialog.dismissDialog(Dialog.java:
332
)
at android.app.Dialog.dismiss(Dialog.java:
315
)
错误原因 这个错误测试是测不出来的,我是加了第三方的错误统计才得以发现的,原因是由于某种原因导致Activity被杀死后又重新创建 常发生这类Exception的情形都是,有一个费时的线程操作,需要在显示一个ProgressDialog,在任务开始的时候显示一个对话框,然后当任务完成了再Dismiss对话框,如果在此期间如果Activity因为某种原因被杀掉且又重新启动了,那么当Dismiss的时候WindowManager检查发现Dialog所属的Activity已经不存在了,所以会报IllegalArgumentException: View not attached to window manager. 解决办法 从网上找了好些解决方案都不是太理想,然后就尝试着自己解决, 我是这么解决的,反正加上之后这个错误就没有再出现过,如有不对还请赐教。 重写Activity的onDestroy,将dialog置为空。
?
1
2
3
4
5
@Override
public
void
onDestroy() {
super
.onDestroy();
dialog=
null
;
}
三、读取通讯录时,用户选择拒绝,未能获取权限导致的java.lang.SecurityException: Permission Denial错误 错误日志
?
1
2
3
4
5
6
7
java.lang.SecurityException: Permission Denial: reading com.android.providers.contacts.ContactsProvider2 uri content:
//com.android.contacts/data/phones from pid=27697, uid=10194 requires android.permission.READ_CONTACTS, or grantUriPermission()
at android.os.Parcel.readException(Parcel.java:
1465
)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:
185
)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:
137
)
at android.content.ContentProviderProxy.query(ContentProviderNative.java:
413
)
at android.content.ContentResolver.query(ContentResolver.java:
470
)
at android.content.ContentResolver.query(ContentResolver.java:
413
)
错误原因 读取通讯录时,用户选择拒绝,未能获取权限 解决办法 直接try catch 如果捕获到异常,提示用户未授于权限。 四、拨打电话时,手机没有相关应用程序导致的android.content.ActivityNotFoundException错误,用浏览器 打开网页链接时,若没有安装浏览器,也会产生类似的错误,解决办法一样 错误日志
?
1
2
3
4
5
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.DIAL dat=tel:xxxxxxxxxxxx }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:
1632
)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:
1424
)
at android.app.Activity.startActivityForResult(Activity.java:
3438
)
at android.app.Activity.startActivityForResult(Activity.java:
3399
)
错误原因 因为手机没有安装可以拨打电话的应用程序 解决办法 直接try catch 如果捕获到异常,提示用户没有相关的应用程序处理此操作 五、在子线程,更新UI 错误日志
?
1
2
3
4
5
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:
5281
)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:
943
)
at android.view.View.requestLayout(View.java:
15614
)
at android.view.View.requestLayout(View.java:
15614
)
错误原因 在子线程显示一个Toast,更新UI只能在主线程中进行 解决办法 1、使用Looper
?
1
2
3
Looper.prepare();
Toast.makeText(aActivity.
this
,
"test"
,Toast.LENGTH_SHORT).show();
Looper.loop();
2、使用Handler 在类中定义
?
1
2
3
4
5
6
7
8
9
10
11
private
final
Handler msgHandler =
new
Handler(){
public
void
handleMessage(Message msg) {
switch
(msg.arg1) {
case
R.string.msg_not_network:
Toast.makeText(getApplicationContext(), getResources().getString(R.string.msg_not_network), Toast.LENGTH_SHORT).show();
break
;
default
:
break
;
}
}
};
在子线程中,发送消息
?
1
2
3
Message msg = msgHandler.obtainMessage();
msg.arg1 = R.string.msg_not_network;
msgHandler.sendMessage(msg);