如何在我的活动中授予屏幕覆盖权限

23

在我的应用程序中,我遇到了Android 6+屏幕覆盖问题。我尝试打开它,但是需要给予屏幕覆盖权限。

我按照此处的说明进行操作,但无法在我的活动中集成。

我还尝试了此处的方法,两种方法都有效,所以我想将它们集成到我的活动中。

这是我的活动:

public class MainActivity extends Activity {

    public static final int R_PERM = 123;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.data);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        if ((CheckPermission(this, Manifest.permission.CAMERA)) &&
                (CheckPermission(this, Manifest.permission.READ_PHONE_STATE)) &&
                (CheckPermission(this, Manifest.permission.NFC))) {
            PermHandling();
        } else {
            RequestPermission(MainActivity.this, Manifest.permission.CAMERA, R_PERM);
            RequestPermission(MainActivity.this, Manifest.permission.READ_PHONE_STATE, R_PERM);
            RequestPermission(MainActivity.this, Manifest.permission.NFC, R_PERM);

            //NewPermHandling();
        }

    }

    private void PermHandling() {
        //My app internal parts....
        //Here my stuff works...
    }

    //private void NewPermHandling(){

    //}

    @Override
    public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults) {

        switch (permsRequestCode) {

            case R_PERM: {
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    PermHandling();
                } else {
                    //Toast.makeText(this, "Please Grant Permissions other wise app will close.!", Toast.LENGTH_SHORT).show();
                }
                return;
            }
        }
    }

    public void RequestPermission(Activity thisActivity, String Permission, int Code) {
        if (ContextCompat.checkSelfPermission(thisActivity,
                Permission)
                != PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
                    Permission)) {
            } else {
                ActivityCompat.requestPermissions(thisActivity,
                        new String[]{Permission},
                        Code);
            }
        }
    }

    public boolean CheckPermission(Context context, String Permission) {
        if (ContextCompat.checkSelfPermission(context,
                Permission) == PackageManager.PERMISSION_GRANTED) {
            return true;
        } else {
            return false;
        }
    }
}

有人可以建议我如何在我的活动中授予屏幕方向权限,以便用户无需担心或手动设置。请帮忙。 我尝试了这个,但我不知道PERM_REQUEST_CODE_DRAW_OVERLAYS是什么。

有人可以帮助我在我的活动中添加它吗?这不是重复的问题,我只是想知道如何添加它。


为什么你需要这个应用的权限? - Yuichi Akiyoshi
它要求屏幕叠加权限,否则应用程序无法正常工作...但是当我尝试打开它时,我的应用程序有一个“NO”的选项....如果您已经了解Android 6+中每个应用程序的屏幕叠加问题,请尝试帮助我,先生... - Don't Be negative
3个回答

28

以下是使用自定义覆盖来禁用拉取通知的示例代码,它在Android版本低于和6+上正常工作。

清单文件中所需的权限:

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

禁用推送通知

private void disablePullNotificationTouch() {
   try {
    Log.v("App", "Disable Pull Notification");

    private HUDView mView = new HUDView(this);
    int statusBarHeight = (int) Math.ceil(25 * getResources().getDisplayMetrics().density);
    Log.v("App", "" + statusBarHeight);

    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
     WindowManager.LayoutParams.MATCH_PARENT,
     statusBarHeight,
     WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
     WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
     WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, //Disables status bar
     PixelFormat.TRANSPARENT); //Transparent

    params.gravity = Gravity.CENTER | Gravity.TOP;
    WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
    wm.addView(mView, params);
   } catch (Exception e) {
    Log.v("App", "Exception: " + e.getMessage());

   }
  }

  // code to post/handler request for permission 
  public final static int REQUEST_CODE = -1010101;

  @RequiresApi(api = Build.VERSION_CODES.M)
  public void checkDrawOverlayPermission() {
   Log.v("App", "Package Name: " + getApplicationContext().getPackageName());

   // check if we already  have permission to draw over other apps
   if (!Settings.canDrawOverlays(context)) {
    Log.v("App", "Requesting Permission" + Settings.canDrawOverlays(context));
    // if not construct intent to request permission
    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
     Uri.parse("package:" + getApplicationContext().getPackageName()));
    / request permission via start activity for result
    startActivityForResult(intent, REQUEST_CODE);
   } else {
    Log.v("App", "We already have permission for it.");
    disablePullNotificationTouch();
   }
  }
  @TargetApi(Build.VERSION_CODES.M)
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   Log.v("App", "OnActivity Result.");
   //check if received result code
   //  is equal our requested code for draw permission
   if (requestCode == REQUEST_CODE) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
     if (Settings.canDrawOverlays(this)) {
      disablePullNotificationTouch();
     }
    }
   }
  }

您修改后的代码

public class MainActivity extends Activity {

 public static final int REQUEST_PERMISSION = 123;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.data);
  setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
   Log.v("App", "Build Version Greater than or equal to M: " + Build.VERSION_CODES.M);
   checkDrawOverlayPermission();
  } else {
   Log.v("App", "OS Version Less than M");
   //No need for Permission as less then M OS.
  }


  if ((CheckPermission(this, Manifest.permission.CAMERA)) &&
   (CheckPermission(this, Manifest.permission.READ_PHONE_STATE)) &&
   (CheckPermission(this, Manifest.permission.NFC))) {
   PermHandling();
  } else {
   RequestPermission(MainActivity.this, Manifest.permission.CAMERA, REQUEST_PERMISSION);
   RequestPermission(MainActivity.this, Manifest.permission.READ_PHONE_STATE, REQUEST_PERMISSION);
   RequestPermission(MainActivity.this, Manifest.permission.NFC, REQUEST_PERMISSION);

   //NewPermHandling();
  }

 }

 private void PermHandling() {
  //My app internal parts....
  //Here my stuff works...
 }

 //private void NewPermHandling(){

 //}

 @Override
 public void onRequestPermissionsResult(int permissionRequestCode, String[] permissions, int[] grantResults) {
  if (permissionRequestCode != REQUEST_PERMISSION) {
   return;
  }

  if (grantResults.length && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
   PermHandling();
  } else {
   // Ask the user to grant the permission
  }
 }

 public void RequestPermission(Activity thisActivity, String Permission, int Code) {
  if (ContextCompat.checkSelfPermission(thisActivity,
    Permission) !=
   PackageManager.PERMISSION_GRANTED) {
   if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
     Permission)) {} else {
    ActivityCompat.requestPermissions(thisActivity,
     new String[] {
      Permission
     },
     Code);
   }
  }
 }

 public final static int REQUEST_CODE = -1010101;

 @RequiresApi(api = Build.VERSION_CODES.M)
 public void checkDrawOverlayPermission() {
  Log.v("App", "Package Name: " + getApplicationContext().getPackageName());

  // Check if we already  have permission to draw over other apps
  if (!Settings.canDrawOverlays(context)) {
   Log.v("App", "Requesting Permission" + Settings.canDrawOverlays(context));
   // if not construct intent to request permission
   Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
    Uri.parse("package:" + getApplicationContext().getPackageName()));
   // request permission via start activity for result 
   startActivityForResult(intent, REQUEST_CODE); //It will call onActivityResult Function After you press Yes/No and go Back after giving permission
  } else {
   Log.v("App", "We already have permission for it.");
   // disablePullNotificationTouch();
   // Do your stuff, we got permission captain
  }
 }

 @TargetApi(Build.VERSION_CODES.M)
 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  Log.v("App", "OnActivity Result.");
  //check if received result code
  //  is equal our requested code for draw permission
  if (requestCode == REQUEST_CODE) {
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (Settings.canDrawOverlays(this)) {
     // Permission Granted by Overlay
     // Do your Stuff
    }
   }
  }
 }

 public boolean CheckPermission(Context context, String Permission) {
  if (ContextCompat.checkSelfPermission(context,
    Permission) == PackageManager.PERMISSION_GRANTED) {
   return true;
  } else {
   return false;
  }
 }
}

如果您从Activity调用startActivityForResult而不是从服务中调用,则会调用onActivityResult。有关详细信息,请阅读此处


谢谢@Ahmad Shahwiz先生,您能否在我的代码中更新您的答案?实际上我无法将两者结合起来,我会向您提供赏金。 - Don't Be negative
已更新。如果需要帮助,请告诉我。 - Ahmad Shahwaiz
非常感谢,它解决了我80%的问题。我会用这种方式进行重命名...请为我的问题点赞,我在悬赏中失去了一些。 - Don't Be negative
3
根据开发者文档,没有名为android.permission.ACTION_MANAGE_OVERLAY_PERMISSION的权限 - 相反,它明确说明这是一个调用设置操作。我是否漏掉了什么?在我的大约14k个应用程序样本中,只有4个应用程序请求此“权限”。还有更多使用android.permission.SYSTEM_ALERT_WINDOW的应用程序。 - Izzy

6
您已经查看的第二篇文章清楚地展示了如何检查SYSTEM_ALERT_WINDOW权限。但为了简化和解释,如developer.android.com上所述:允许应用程序使用TYPE_SYSTEM_ALERT类型创建窗口,显示在所有其他应用程序之上。很少有应用程序需要使用此权限;这些窗口旨在与用户进行系统级交互。请注意:如果应用程序的目标API级别为23或更高,则必须通过权限管理屏幕明确授予应用程序用户此权限。应用程序通过发送带有ACTION_MANAGE_OVERLAY_PERMISSION操作的意图来请求用户的批准。应用程序可以通过调用Settings.canDrawOverlays()来检查是否具有此授权。正如您查看的SO 文章中提到的那样,以下是简化的步骤:
  1. First check whether current device SDK version is greater than or equal to Android M (23) by following if condition

    if (android.os.Build.VERSION.SDK_INT >= 23) {
    }
    
  2. Then using Settings.canDrawOverlays() as mentioned in the developer.android.com check whether your application already have permission or not, we will check for do not have permission

    if (android.os.Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(this)) {
    }
    
  3. Then as mentioned in developer.android.com and as implemented in the SO post trigger an intent with ACTION_MANAGE_OVERLAY_PERMISSION.

    if (android.os.Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(this)) {   //Android M Or Over
       Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
       startActivityForResult(intent, <YOUR REQUEST CODE>);
       return;
    }
    
  4. Handle the result in onActivityResult() method defined in Activity, and again check using Settings.canDrawOverlays() if still not then finish() the activity after showing appropriate alert to user.

在完成其他权限流程后,您可以实现整个流程。

谢谢@Rajen Raiyarela,但是我在PERM_REQUEST_CODE_DRAW_OVERLAYS处遇到了错误,我不知道接下来该怎么办,然后我需要检查代码是否有效,然后我需要将此权限与我的权限一起授予...您能否使用我的代码更新您的答案,这样如果它有效,我会给予奖励。 - Don't Be negative
PERM_REQUEST_CODE_DRAW_OVERLAYS 就是用于在 OnActivityResult 方法中识别接收结果的 REQUEST_CODE。我已经修改并放置了占位符 <YOUR REQUEST CODE>,代替 PERM_REQUEST_CODE_DRAW_OVERLAYS。关于实现,您可以从 PermHandling() 方法中调用此流程。 - Rajen Raiyarela
抱歉,我在那里遇到了错误。如果可能的话,您能否在我的代码中更新您的答案?这里我被卡住了:1. PERM_REQUEST_CODE_DRAW_OVERLAYS 和 2. 将其集成到我的代码中... - Don't Be negative

2
这是解决方案,我在整个网络上搜寻了一遍,却没有找到任何有用的信息。答案是:当你请求新权限时,绝不要做其他事情,比如显示toast或者......。在我的情况下,我重新启动了应用程序并请求下一个权限,我使用this code来重新启动应用程序。

祝你好运。

@不要消极,你可以尝试一下,如果不行,请再联系我。

wm = (WindowManager) content.getSystemService(Service.WINDOW_SERVICE);

     orientationChanger = new LinearLayout(content);
     orientationChanger.setClickable(false);
     orientationChanger.setFocusable(false);
     orientationChanger.setFocusableInTouchMode(false);
     orientationChanger.setLongClickable(false);

    orientationLayout = new WindowManager.LayoutParams(
        LayoutParams.WRAP_CONTENT,  LayoutParams.WRAP_CONTENT,
        windowType,  WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
        PixelFormat.RGBA_8888);

     wm.addView(orientationChanger, orientationLayout);
    orientationChanger.setVisibility(View.GONE);

    orientationLayout.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
    wm.updateViewLayout(orientationChanger, orientationLayout);
    orientationChanger.setVisibility(View.VISIBLE);

谢谢@Jamil Hasnine Tamim先生,但在重新启动之前,我需要添加一个覆盖权限。我已经尝试过了,但可能是我走了不同的路线。您能否在我的代码中更新您的答案?我会向您支付悬赏... - Don't Be negative
不要消极,您可以尝试我的更新部分,如果不起作用,请再联系我... - Jamil Hasnine Tamim
谢谢 @Jamil Hasnine Tamim 先生,但我已经在我的应用程序中添加了 SetRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); - Don't Be negative

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接