window 类型 2038 的权限被拒绝
Permission denied for window type 2038
我正在修复一个不是我开发的android应用程序,几天前客户要求我将targetSdkVersion设置为26(之前是14),之后我发现该应用程序在某些情况下会崩溃,例如在显示 ProgressDialog 时崩溃。这是有问题的代码部分:
mProgressDialog.setTitle(getString(R.string.downloading_data));
mProgressDialog.setMessage(mAlertMsg);
Drawable icon = getActivity().getDrawable(android.R.drawable.ic_dialog_info);
icon.setColorFilter(Color.parseColor("#00cbac"), PorterDuff.Mode.SRC_ATOP);
mProgressDialog.setIcon(icon);
mProgressDialog.setIndeterminate(true);
mProgressDialog.setCancelable(false);
mProgressDialog.setButton(getString(R.string.cancel), loadingButtonListener);
mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
mProgressDialog.show();
执行最后一行时,应用程序崩溃并出现此错误 Logcat:
android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@b784d3a -- permission denied for window type 2003
当应用 运行 在具有 Android 8 和 9 的设备中时,会出现此问题。
我寻找类似问题的解决方案,发现使用WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
而不是TYPE_SYSTEM_ALERT
会更好,然后我修改了我在post中编写的代码的倒数第二行但它没有改变任何东西,应用程序同样崩溃并且在日志中出现此错误:
android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@b784d3a -- permission denied for window type 2038
在清单中我有权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
我还从设备设置中启用了该应用程序的所有权限。
我该如何解决这个问题?
如您所见,Android Oreo 及更高版本严格限制您可以使用的覆盖类型。 Oreo 引入了新的 TYPE_APPLICATION_OVERLAY
常量供应用程序使用,同时弃用和禁止使用旧常量。
但是,TYPE_APPLICATION_OVERLAY
在 Nougat 及以下版本中不存在,因此尝试在那里使用它会导致 SecurityException。
替换
mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
有
mProgressDialog.getWindow().setType(
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
else
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
至于为什么它仍然在 Oreo 和更高版本的 TYPE_APPLICATION_OVERLAY
上崩溃,SYSTEM_ALERT_WINDOW
权限不是正常的运行时权限,并且没有显示在 "Permissions" 部分下在应用程序信息中。它面向用户的名称是 "Draw over other apps"(通常),它位于一般应用信息页面或设置>>应用>>特殊访问下。
您不能像使用运行时权限那样以编程方式授予它,在运行时权限中您有一个简单的对话框来授予它。相反,您需要检查权限是否被授予,如果没有,启动设置页面以允许用户授予权限:How to programmatically grant the "draw over other apps" permission in android?
但是,我真的不明白为什么一个简单的进度对话框需要是一个成熟的覆盖。事实上,ProgressDialog 已被完全弃用。您应该考虑迁移到简单的 ProgressBar,或者,如果您想保留 ProgressDialog,请删除 setType()
行。
我正在修复一个不是我开发的android应用程序,几天前客户要求我将targetSdkVersion设置为26(之前是14),之后我发现该应用程序在某些情况下会崩溃,例如在显示 ProgressDialog 时崩溃。这是有问题的代码部分:
mProgressDialog.setTitle(getString(R.string.downloading_data));
mProgressDialog.setMessage(mAlertMsg);
Drawable icon = getActivity().getDrawable(android.R.drawable.ic_dialog_info);
icon.setColorFilter(Color.parseColor("#00cbac"), PorterDuff.Mode.SRC_ATOP);
mProgressDialog.setIcon(icon);
mProgressDialog.setIndeterminate(true);
mProgressDialog.setCancelable(false);
mProgressDialog.setButton(getString(R.string.cancel), loadingButtonListener);
mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
mProgressDialog.show();
执行最后一行时,应用程序崩溃并出现此错误 Logcat:
android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@b784d3a -- permission denied for window type 2003
当应用 运行 在具有 Android 8 和 9 的设备中时,会出现此问题。
我寻找类似问题的解决方案,发现使用WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
而不是TYPE_SYSTEM_ALERT
会更好,然后我修改了我在post中编写的代码的倒数第二行但它没有改变任何东西,应用程序同样崩溃并且在日志中出现此错误:
android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@b784d3a -- permission denied for window type 2038
在清单中我有权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
我还从设备设置中启用了该应用程序的所有权限。 我该如何解决这个问题?
Android Oreo 及更高版本严格限制您可以使用的覆盖类型。 Oreo 引入了新的 TYPE_APPLICATION_OVERLAY
常量供应用程序使用,同时弃用和禁止使用旧常量。
但是,TYPE_APPLICATION_OVERLAY
在 Nougat 及以下版本中不存在,因此尝试在那里使用它会导致 SecurityException。
替换
mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
有
mProgressDialog.getWindow().setType(
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
else
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
至于为什么它仍然在 Oreo 和更高版本的 TYPE_APPLICATION_OVERLAY
上崩溃,SYSTEM_ALERT_WINDOW
权限不是正常的运行时权限,并且没有显示在 "Permissions" 部分下在应用程序信息中。它面向用户的名称是 "Draw over other apps"(通常),它位于一般应用信息页面或设置>>应用>>特殊访问下。
您不能像使用运行时权限那样以编程方式授予它,在运行时权限中您有一个简单的对话框来授予它。相反,您需要检查权限是否被授予,如果没有,启动设置页面以允许用户授予权限:How to programmatically grant the "draw over other apps" permission in android?
但是,我真的不明白为什么一个简单的进度对话框需要是一个成熟的覆盖。事实上,ProgressDialog 已被完全弃用。您应该考虑迁移到简单的 ProgressBar,或者,如果您想保留 ProgressDialog,请删除 setType()
行。