Android无法解决permission denied for this window type
Android 中无法解决 Permission Denied for this Window Type
错误的详细解决方案
Permission Denied for this Window Type
是 Android 开发中一个常见的权限问题,通常出现在尝试在应用中使用特定类型的窗口或界面时。以下是对该问题的详细解释、解决方案以及示例代码。
1. 问题描述
在 Android 应用中,Permission Denied for this Window Type
错误通常发生在尝试创建或显示窗口(如 Dialog
、PopupWindow
、WindowManager
的自定义窗口)时,当前应用没有足够的权限来执行这些操作。
错误信息示例
plaintextandroid.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
常见场景
- 使用
WindowManager
添加窗口或视图时。 - 尝试创建系统级窗口(例如悬浮窗)时。
2. 解决方案
2.1 检查和添加必要的权限
不同类型的窗口需要不同的权限。常见的权限包括:
悬浮窗权限
对于需要创建悬浮窗的应用,您需要在
AndroidManifest.xml
文件中添加以下权限:xml<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
从 Android 6.0(API 级别 23)开始,您还需要在运行时请求该权限:
javaif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (!Settings.canDrawOverlays(context)) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + context.getPackageName())); startActivityForResult(intent, REQUEST_CODE); } }
TYPE_APPLICATION_OVERLAY
权限从 Android 8.0(API 级别 26)开始,
SYSTEM_ALERT_WINDOW
权限被分为TYPE_APPLICATION_OVERLAY
。更新后的权限声明如下:xml<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
使用
TYPE_APPLICATION_OVERLAY
:javaWindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, // API 26 及以上使用此类型 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);
2.2 检查窗口类型
在创建窗口时,确保使用了正确的窗口类型。以下是一些常见窗口类型及其用途:
TYPE_APPLICATION
:应用窗口。TYPE_APPLICATION_PANEL
:应用面板窗口。TYPE_SYSTEM_ALERT
:系统级警报窗口(Android 8.0 后被TYPE_APPLICATION_OVERLAY
替代)。TYPE_APPLICATION_OVERLAY
:用于创建悬浮窗(API 26 及以上)。
示例代码:设置悬浮窗
javapublic class MyService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
Intent overlayIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(overlayIntent, REQUEST_CODE);
} else {
showOverlay();
}
} else {
showOverlay();
}
return START_NOT_STICKY;
}
private void showOverlay() {
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, // API 26 及以上使用此类型
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
View overlayView = LayoutInflater.from(this).inflate(R.layout.overlay_layout, null);
windowManager.addView(overlayView, params);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
2.3 确保 Activity 处于运行状态
确保在进行窗口操作时,Activity 是处于运行状态的。如果 Activity 被销毁或不是前台状态,窗口操作可能会失败。
2.4 检查 WindowManager
设置
确保 WindowManager
的 LayoutParams
设置正确,特别是 type
和 flags
:
javaWindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, // 适用于 Android 8.0 及以上
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSLUCENT
);
3. 常见问题与解决方案
3.1 问题:Permission Denied
错误
原因:应用缺少必要的权限或权限请求未被批准。
解决方案:
- 确保
AndroidManifest.xml
中声明了正确的权限。 - 对于 Android 6.0 及以上版本,确保在运行时请求了
SYSTEM_ALERT_WINDOW
权限。
3.2 问题:窗口类型不正确
原因:使用了不适合的窗口类型。
解决方案:
- 对于系统级窗口,使用
TYPE_APPLICATION_OVERLAY
。 - 确保
TYPE_APPLICATION_OVERLAY
是正确的类型。
3.3 问题:Activity 不在前台
原因:尝试在 Activity 不在前台时创建窗口。
解决方案:
- 确保 Activity 处于活动状态,或考虑将窗口创建逻辑移至
Service
中。
4. 完整示例代码
以下是一个示例,展示如何在 Android 中处理 Permission Denied for this Window Type
错误:
javapublic class MyOverlayService extends Service {
private static final int REQUEST_CODE = 1234;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.canDrawOverlays(this)) {
showOverlay();
} else {
Intent overlayIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(overlayIntent, REQUEST_CODE);
}
} else {
showOverlay();
}
return START_NOT_STICKY;
}
private void showOverlay() {
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, // API 26 及以上使用此类型
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT
);
View overlayView = LayoutInflater.from(this).inflate(R.layout.overlay_layout, null);
windowManager.addView(overlayView, params);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
5. 参考资料
总结与关键字
总结
在 Android 开发中处理 Permission Denied for this Window Type
错误主要涉及到检查和请求适当的权限、确保使用正确的窗口类型以及验证 Activity 的状态。解决方案包括在 AndroidManifest.xml
中添加权限声明,动态请求权限,确保 WindowManager
设置正确,以及处理运行时权限问题。示例代码展示了如何处理这些问题,并提供了处理悬浮窗的完整实现。
关键字
Android, Permission Denied for this Window Type
, WindowManager
, SYSTEM_ALERT_WINDOW
, TYPE_APPLICATION_OVERLAY
, 权限问题, `AndroidMan