【问题标题】:Android System overlay windowAndroid 系统覆盖窗口
【发布时间】:2015-12-15 15:12:06
【问题描述】:

我正在尝试创建一个系统覆盖。但我不断收到“权限被拒绝”。我使用的是 SDK 版本 23。

我的清单文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test" >

<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".activity.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

我用来创建叠加层的代码:

    //mView = new HUDView(this);
    mButton = new Button(this);
    mButton.setText("Overlay button");
    mButton.setOnTouchListener(this);

    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
            WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
            PixelFormat.TRANSLUCENT);
    params.gravity = Gravity.RIGHT | Gravity.TOP;
    params.setTitle("Load Average");
    WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
    wm.addView(mButton, params);

【问题讨论】:

标签: java android android-permissions


【解决方案1】:

首先,没有名为SYSTEM_OVERLAY_WINDOW 的权限。是SYSTEM_ALERT_WINDOW

其次,如果您的targetSdkVersion 为 23 或更高,并且您在 Android 6.0+ 设备上运行,您的应用一开始不会获得此权限。调用Settings.canDrawOverlays()查看你是否有权限,如果没有权限使用ACTION_MANAGE_OVERLAY_PERMISSION引导用户进入设置。

【讨论】:

  • 我将权限更改为 SYSTEM_ALERT_WINDOW 但这并没有解决问题。所以我正在尝试实施你的第二个建议。但是我如何使用 ACTION_MANAGE_OVERLAY_PERMISSION 引导用户进入设置?
  • @VeryEvilBetty:这是Intent 操作。 startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)) 应该会打开一个活动,用户可以选择允许您的应用在屏幕上绘制。
  • 是否至少有一种方法可以仅为我的应用启用覆盖,而不要求用户在所有其他应用中搜索我的应用?理想情况下,一个小的弹出窗口,就像权限一样,将是最好的。有什么办法吗?
  • @Meymann:我不知道,抱歉。即使有,they might ban you from the Play Store for using it 如果他们不认为这是合理的。
  • @Meymann 只需添加 settingsIntent.setData(Uri.parse("package:" + getPackageName()));根据意图,这将在该设置列表中打开您应用的详细页面
【解决方案2】:

在 AndroidManifest(版本

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>


public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE= 5469;
//Random value

    public void testPermission() {
        if (!Settings.canDrawOverlays(this)) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
        }
    }

结果:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
        if (Settings.canDrawOverlays(this)) {
            // You have permission
        }
    }
}

【讨论】:

  • 在官方网站上说我们可以对 API v23 做同样的事情,你在 23 上试过这个代码吗? developer.android.com/reference/android/provider/…
  • 是的,你可以。只是清单中的权限是针对版本
  • 我检查了运行时权限列表,SYSTEM_ALERT_WINDOW 不在列表中。我想唯一能指导用户如何授予权限的解决方案!
  • @Anthone 我试过你的代码,Settings.canDrawOverlays(this)onActivityResult 方法中返回false。稍后调用它时,返回true。似乎更改是异步完成的。有没有办法在用户更改此设置时收到通知?
  • 注意:在 Android 8.0 和 8.1 的某些设备上,Settings.canDrawOverlays(this) 可能会在用户刚刚启用权限并返回您的应用时始终返回 false。此方法可能需要 5-7 秒才能返回实际值 true。检查这个关于如何绕过这个已知错误的答案:stackoverflow.com/questions/46173460/…
【解决方案3】:

您还可以将用户引导至特定应用的重叠页面。文档states

输入:可选地,Intent 的数据 URI 可以指定应用程序包名称以直接调用特定于包名称的管理 GUI。例如“package:com.my.app”。

比如:

intent.setData(Uri.fromParts("package", getPackageName(), null));

【讨论】:

    【解决方案4】:

    作为替代解决方案,您可以尝试使用 WindowManager.LayoutParams.TYPE_TOAST 而不是 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT。 这不需要任何许可。 我用它来显示图像,也许按钮可以工作

    【讨论】:

      【解决方案5】:

      供android 8以下及以上用户使用

      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
         LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
      } else {
          LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
      }
      

      【讨论】:

        【解决方案6】:

        我在library 中处理了每个 android 版本的所有覆盖权限。请在此处查看gist

        【讨论】:

          【解决方案7】:

          为了显示在其他应用程序上,需要在清单中添加权限

          <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
          

          检查你的应用是否有权限

          Settings.canDrawOverlays(context)
          

          检查权限checkOverlayPermission

          private const val CODE_DRAW_OVER_OTHER_APP_PERMISSION = 2084
          
          private fun checkOverlayPermission(){
              if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
                  //If the draw over permission is not available open the settings screen
                  //to grant the permission.
                  val intent = Intent(
                      Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                      Uri.parse("package:$packageName")
                  )
                  startActivityForResult(
                      intent,
                      CODE_DRAW_OVER_OTHER_APP_PERMISSION
                  )
              }
          }
          

          在 onActivityResult 中,您可以检查是否授予权限

          override fun onActivityResult(
              requestCode: Int,
              resultCode: Int,
              data: Intent?
          ) {
              if (requestCode == CODE_DRAW_OVER_OTHER_APP_PERMISSION) {
                  if (Settings.canDrawOverlays(this)) {
                      // Permission Granted
                  } else {
                      // Permission not Granted
                      // If you want then call again checkOverlayPermission until permission granted
                  }
              } 
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-11-09
            • 1970-01-01
            • 1970-01-01
            • 2015-04-30
            • 1970-01-01
            • 2013-01-19
            • 2022-01-06
            • 1970-01-01
            相关资源
            最近更新 更多