Android:使用 TYPE_APPLICATION_OVERLAY window 类型 2038 的权限被拒绝
Android: permission denied for window type 2038 using TYPE_APPLICATION_OVERLAY
我试图创建一个高于其他应用程序的视图:
WindowManager.LayoutParams paramsDirectorView = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
我查看了其他回复,发现 "drawing over applications" 的以下内容:
- 清单中有 android.permission.SYSTEM_ALERT_WINDOW
- 我正在做 Settings.canDrawOverlays(this) 检查
返回 true.
- 我已经完成了这里的所有内容permission denied for window type
我仍然收到“-- window 类型 2038 的权限被拒绝”错误。到目前为止,我正在使用 TYPE_PHONE 并且它可以工作,但它已被弃用并说要使用 TYPE_APPLICATION_OVERLAY。有人可以跟进吗,因为 TYPE_PHONE 答案不是真正的解决方案,而是 Android O.
中弃用的 "patch work" 解决方案
我 运行 Android 7.1.2
android.view.WindowManager$BadTokenException: Unable to add window
android.view.ViewRootImpl$W@1f47e89 -- permission denied for window
type 2038 at
android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3344)
at android.app.ActivityThread.-wrap21(ActivityThread.java) at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1583)
at android.os.Handler.dispatchMessage(Handler.java:102) at
android.os.Looper.loop(Looper.java:154) at
android.app.ActivityThread.main(ActivityThread.java:6121) at
java.lang.reflect.Method.invoke(Native Method) at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) Caused
by: android.view.WindowManager$BadTokenException: Unable to add window
android.view.ViewRootImpl$W@1f47e89 -- permission denied for window
type 2038 at android.view.ViewRootImpl.setView(ViewRootImpl.java:703)
at
android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:342)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at
HeadService.TwoViewManager.(TwoViewManager.java:99)
at
HeadService.UIHeadService.onStartCommand(UIHeadService.java:65)
at
android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3327)
at android.app.ActivityThread.-wrap21(ActivityThread.java) at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1583)
at android.os.Handler.dispatchMessage(Handler.java:102) at
android.os.Looper.loop(Looper.java:154) at
android.app.ActivityThread.main(ActivityThread.java:6121) at
java.lang.reflect.Method.invoke(Native Method) at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
尝试将 WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
更改为 WindowManager.LayoutParams.TYPE_PHONE
?
您是否通过调用以下意图请求运行时权限?
private void requestOverlayPermission() {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
return;
}
Intent myIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
myIntent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(myIntent, APP_PERMISSIONS);
}
然后在 onActivityResult() 中检查 Settings.canDrawOverlays(this) 是否为真,否则通过调用上述方法再次请求权限。
Source
SYSTEM_ALERT_WINDOW
字符串 SYSTEM_ALERT_WINDOW
允许应用创建 windows 使用类型 TYPE_APPLICATION_OVERLAY,显示在所有其他应用之上。很少有应用程序应该使用此权限;这些 windows 用于与用户进行系统级交互。
注意:如果应用面向 API 级别 23 或更高级别,则应用用户必须通过权限管理屏幕明确向应用授予此权限。该应用通过发送带有操作 ACTION_MANAGE_OVERLAY_PERMISSION 的意图请求用户的批准。应用程序可以通过调用 Settings.canDrawOverlays().
来检查它是否有这个权限
我遇到了完全相同的问题。我想你应该区分目标(奥利奥之前和之后)
int LAYOUT_FLAG;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LAYOUT_FLAG,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
我在服务中遇到了完全相同的问题 class(在 Marshmallow 之前和之后)。
if (Build.VERSION.SDK_INT >= 23) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 1234);
}
} else {
startService(new Intent(SplashActivity.this,
CheckServicesForApps.class));
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1234) {
startService(new Intent(SplashActivity.this,
CheckServicesForApps.class));
}
}
public class CheckServicesForApps extends Service {
private Context context = null;
@Override
public void onCreate() {
super.onCreate();
ImageView imageView = new ImageView(context);
imageView.setVisibility(View.GONE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
try {
windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
//here is all the science of params
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager. LayoutParams.TYPE_SYSTEM_ERROR,
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
PixelFormat.TRANSLUCENT
);
windowManager.addView(imageView, params);
hand=new Handler();
} catch (Exception e) {
hand=new Handler();
e.printStackTrace();
}
}else{
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.CENTER;
params.x = ((getApplicationContext().getResources().getDisplayMetrics().widthPixels) / 2);
params.y = ((getApplicationContext().getResources().getDisplayMetrics().heightPixels) / 2);
windowManager.addView(imageView, params);
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
/* We want this service to continue running until it is explicitly
* stopped, so return sticky.
*/
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
if (imageView != null) {
try {
windowManager.removeView(imageView);
} catch (Exception e) {
e.printStackTrace();
}
}
/**** added to fix the bug of view not attached to window manager ****/
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
}else {
layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
}
我试图创建一个高于其他应用程序的视图:
WindowManager.LayoutParams paramsDirectorView = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
我查看了其他回复,发现 "drawing over applications" 的以下内容:
- 清单中有 android.permission.SYSTEM_ALERT_WINDOW
- 我正在做 Settings.canDrawOverlays(this) 检查 返回 true.
- 我已经完成了这里的所有内容permission denied for window type
我仍然收到“-- window 类型 2038 的权限被拒绝”错误。到目前为止,我正在使用 TYPE_PHONE 并且它可以工作,但它已被弃用并说要使用 TYPE_APPLICATION_OVERLAY。有人可以跟进吗,因为 TYPE_PHONE 答案不是真正的解决方案,而是 Android O.
中弃用的 "patch work" 解决方案我 运行 Android 7.1.2
android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@1f47e89 -- permission denied for window type 2038 at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3344) at android.app.ActivityThread.-wrap21(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1583) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6121) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) Caused by: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@1f47e89 -- permission denied for window type 2038 at android.view.ViewRootImpl.setView(ViewRootImpl.java:703) at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:342) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93) at HeadService.TwoViewManager.(TwoViewManager.java:99) at HeadService.UIHeadService.onStartCommand(UIHeadService.java:65) at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3327) at android.app.ActivityThread.-wrap21(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1583) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6121) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
尝试将 WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
更改为 WindowManager.LayoutParams.TYPE_PHONE
?
您是否通过调用以下意图请求运行时权限?
private void requestOverlayPermission() {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
return;
}
Intent myIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
myIntent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(myIntent, APP_PERMISSIONS);
}
然后在 onActivityResult() 中检查 Settings.canDrawOverlays(this) 是否为真,否则通过调用上述方法再次请求权限。
Source SYSTEM_ALERT_WINDOW 字符串 SYSTEM_ALERT_WINDOW 允许应用创建 windows 使用类型 TYPE_APPLICATION_OVERLAY,显示在所有其他应用之上。很少有应用程序应该使用此权限;这些 windows 用于与用户进行系统级交互。
注意:如果应用面向 API 级别 23 或更高级别,则应用用户必须通过权限管理屏幕明确向应用授予此权限。该应用通过发送带有操作 ACTION_MANAGE_OVERLAY_PERMISSION 的意图请求用户的批准。应用程序可以通过调用 Settings.canDrawOverlays().
来检查它是否有这个权限我遇到了完全相同的问题。我想你应该区分目标(奥利奥之前和之后)
int LAYOUT_FLAG;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LAYOUT_FLAG,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
我在服务中遇到了完全相同的问题 class(在 Marshmallow 之前和之后)。
if (Build.VERSION.SDK_INT >= 23) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 1234);
}
} else {
startService(new Intent(SplashActivity.this,
CheckServicesForApps.class));
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1234) {
startService(new Intent(SplashActivity.this,
CheckServicesForApps.class));
}
}
public class CheckServicesForApps extends Service {
private Context context = null;
@Override
public void onCreate() {
super.onCreate();
ImageView imageView = new ImageView(context);
imageView.setVisibility(View.GONE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
try {
windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
//here is all the science of params
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager. LayoutParams.TYPE_SYSTEM_ERROR,
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
PixelFormat.TRANSLUCENT
);
windowManager.addView(imageView, params);
hand=new Handler();
} catch (Exception e) {
hand=new Handler();
e.printStackTrace();
}
}else{
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.CENTER;
params.x = ((getApplicationContext().getResources().getDisplayMetrics().widthPixels) / 2);
params.y = ((getApplicationContext().getResources().getDisplayMetrics().heightPixels) / 2);
windowManager.addView(imageView, params);
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
/* We want this service to continue running until it is explicitly
* stopped, so return sticky.
*/
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
if (imageView != null) {
try {
windowManager.removeView(imageView);
} catch (Exception e) {
e.printStackTrace();
}
}
/**** added to fix the bug of view not attached to window manager ****/
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
}else {
layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
}