首先,先介绍下背景环境,第一,是Android7.0,其次,要屏蔽home键,先上下出问题的代码
private void testWindow() {
AlertDialog d = new AlertDialog.Builder(this)
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
.setTitle("i am a test").create();
d.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
d.setOnKeyListener(new DialogInterface.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_HOME) {
Log.i(TAG, "onKey: key home press");
return true;
return false;
d.show();
代码很简单,出问题的罪魁祸首就是这货了
d.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
设置这货就是为了能够捕获到home键,当然,调用这句话前提是申请了权限。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= 23) {
if (Settings.canDrawOverlays(this)) {
testWindow();
} else {
Uri uri = Uri.parse("package:" + MainActivity.this.getPackageName());
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, uri);
startActivityForResult(intent, 100);
在onActivityResult处理
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 100) {
if (Build.VERSION.SDK_INT >= 23 && Settings.canDrawOverlays(this)) {
testWindow();
} else {
ToastUtil.showToast("permission denied.");
当然,AndroidManifest里添加权限(没添加权限,在前面申请出来的框框中,就不能授权了)
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
网上查了好久,明明已经授权了啊,为毛还抛出这个错误,今天就根据代码来排查下。
先根据异常定位下代码。(后面的就不大需要了,这些就够了)
Caused by: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@6518342 -- permission denied for window type 2009
at android.view.ViewRootImpl.setView(ViewRootImpl.java:702)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:342)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at android.app.Dialog.show(Dialog.java:316)
at com.felix.windowndemo.MainActivity.testWindow(MainActivity.java:96)
首先是因为调用了show而引起的,show中会添加view到Windows,报错的底层定位到ViewRootImpl,直接点开查看相关代码
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {