23

In My application I am getting Screen Overlay Issue in android 6+ I tried to Turn on But for that I need to Give a Permission for Screen Overlay

I followed this I am unable to Integrate in my activity

I also Tried this seems both are working so I want to Integrate them in my activity

This is my activity :

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;
        }
    }
}

Can any one suggest me how to give Screen orientation permission in my activity So that User No need to give it or worry about it Please help Here I tried but I don't know about PERM_REQUEST_CODE_DRAW_OVERLAYS

Any one Please Help me on my activity this is not duplicate or something else I am asking How to add it in my activity

Community
  • 1
  • 1
Don't Be negative
  • 1,215
  • 3
  • 19
  • 46
  • Why do you need this permission for the app? – Yuichi Akiyoshi Nov 15 '16 at 02:26
  • Its asking Screen Overlay Permission without that App is not working ... but When I try to Turn On it has Option "NO" to my app.... If you already Know about Screen Overlay issue in android 6+ for every app then Try to Help me sir.... – Don't Be negative Nov 15 '16 at 05:10

3 Answers3

28

Here is a sample code to disable pull notifications by using custom overlay. It works fine on Android versions below and 6+.

Permissions Required in Manifest:

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

Disabling the pull notifications

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();
     }
    }
   }
  }

Your code after modifications

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;
  }
 }
}

startActivityForResult will call onActivityResult if you call this from an activity and not from service. Read more about it here

Yehonatan
  • 3,168
  • 7
  • 31
  • 39
Ahmad Shahwaiz
  • 1,432
  • 1
  • 17
  • 35
  • Thanks @Ahmad Shahwiz sir Can you Update Your Answer in my Code Actually I am Unable to Combine Both I will Present Bounty to You – Don't Be negative Nov 15 '16 at 03:52
  • Updated it. Let me know in-case you need help. – Ahmad Shahwaiz Nov 15 '16 at 06:36
  • Thanks A lot It solved 80 % of my Problem.. I will Do renaming In this way... Please Up-vote my questions I have Lost some In bounty... – Don't Be negative Nov 15 '16 at 06:48
  • 2
    According to the [developer documentation](https://developer.android.com/reference/android/Manifest.permission), there is no permission named `android.permission.ACTION_MANAGE_OVERLAY_PERMISSION` – instead it clearly say it's an settings action to call. Or do I miss something here? In my sample of ~14k apps, only 4 apps ask for this "permission". There are plenty more using `android.permission.SYSTEM_ALERT_WINDOW`. – Izzy Jun 29 '18 at 12:39
6

The second post you have checked clearly shows the way of checking for SYSTEM_ALERT_WINDOW permission. But to simply and explain,

As mentioned on developer.android.com

Allows an app to create windows using the type TYPE_SYSTEM_ALERT, shown on top of all other apps. Very few apps should use this permission; these windows are intended for system-level interaction with the user.

Note: If the app targets API level 23 or higher, the app user must explicitly grant this permission to the app through a permission management screen. The app requests the user's approval by sending an intent with action ACTION_MANAGE_OVERLAY_PERMISSION. The app can check whether it has this authorization by calling Settings.canDrawOverlays().

and as mentioned in the SO post you checked,

Here are simplified steps:-

  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.

This whole flow you can implement after other permission flow is completed.

andrei_zaitcev
  • 1,358
  • 16
  • 23
Rajen Raiyarela
  • 5,526
  • 4
  • 21
  • 41
  • thanks @Rajen Raiyarela But Here I am getting error At `PERM_REQUEST_CODE_DRAW_OVERLAYS` I dont know After that I can Check that code is working or not and then I need to Give this permission along with my permission... Can you update your Answer with my Code So If its working I will Give Bounty – Don't Be negative Nov 08 '16 at 07:42
  • PERM_REQUEST_CODE_DRAW_OVERLAYS is nothing but the REQUEST_CODE to identify the received result in OnActivityResult method. I have modified and put the place holder instead of PERM_REQUEST_CODE_DRAW_OVERLAYS. Regarding implementation you can call this flow from your PermHandling() method. – Rajen Raiyarela Nov 08 '16 at 08:05
  • Sorry Can I am getting error over there .. If possible can you update ur answer in my code.... Here I am struck with 1. PERM_REQUEST_CODE_DRAW_OVERLAYS and 2. Integrate this in my Code... – Don't Be negative Nov 08 '16 at 08:17
2

This is the solution ,i search all the web. And can't find anything useful . answer is : when you ask for new permission don't ever ever do something else like showing toast or.... in my case i restart my app and ask for the next permission i use this code for restart the app ,

good luck.

@Don't Be negative You can try this , if not work please knock me again:

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);
Community
  • 1
  • 1
Jamil Hasnine Tamim
  • 4,389
  • 27
  • 43
  • Thanks @Jamil Hasnine Tamim sir But Before Restart I need to add a Overlay Permission I already Tried this But May Be I am going in different Way Can you Update your answer in my Code I will Make a bounty to you... – Don't Be negative Nov 15 '16 at 03:54
  • @Don't Be negative You can try my update portion than if its not working than again knock me please... – Jamil Hasnine Tamim Nov 15 '16 at 06:10
  • Thanks @Jamil Hasnine Tamim Sir But already I have Given In my app as `SetRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);` – Don't Be negative Nov 15 '16 at 06:21