6

enter image description here

and here is another example:

enter image description here

from the screenshot above we see user is able to disable picture in picture mode. you can find it in the "special app access" screen on the emulator api 27 . How can i detect if user has disabled this feature ?

i tried checking the following but it does not work:

packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)

compiler states that AppOpsManager cannot be found. any ideas ?

j2emanue
  • 60,549
  • 65
  • 286
  • 456

4 Answers4

10

just like AlexTa said. but i wanted to actually write the code to save someone some time:

private fun hasPermission(): Boolean {
    val appOps = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
    } else {
        return false
    }
    return appOps.checkOpNoThrow(AppOpsManager.OPSTR_PICTURE_IN_PICTURE, android.os.Process.myUid(), packageName) == AppOpsManager.MODE_ALLOWED
}
j2emanue
  • 60,549
  • 65
  • 286
  • 456
  • If we check this for Chrome, the UID and package name should be of Chrome's, right ? – Jim_Ktr Feb 13 '20 at 09:03
  • why dont you test it out by toggling the setting. im not too sure about that. – j2emanue Feb 13 '20 at 10:53
  • I have done that and when i use my apps UID I always get MODE_ALLOWED. When I use Chrome's UID I gen an SecurityException exception uid [My app's UID] does not have android.permission.UPDATE_APP_OPS_STATS. – Jim_Ktr Feb 13 '20 at 11:01
  • if you want to sent user to enable the permission use: startActivityForResult(Intent("android.settings.PICTURE_IN_PICTURE_SETTINGS", Uri.parse("package:$packageName")), 0) – Ultimo_m Jan 09 '23 at 13:19
  • KitKat, what do you mean? `OPSTR_PICTURE_IN_PICTURE` is available from OREO... So it's not even available for Nougat and have here KitKat... – user924 Jun 25 '23 at 21:09
6

Try AppOpsManager.checkOp (String op, int uid, String packageName), where op is OPSTR_PICTURE_IN_PICTURE operation. That method should return MODE_ALLOWED constant if supports Picture in Picture operation.

For more info, check this link.

AlexTa
  • 5,133
  • 3
  • 29
  • 46
  • I see that the solution is checked, did it work for you? Are you getting the status of pic in pic of chrome? – Jim_Ktr Feb 13 '20 at 09:01
5

I might be late but here's the answer

private fun hasPermission(): Boolean {
    val appOps = getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager?
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            appOps?.unsafeCheckOpNoThrow(AppOpsManager.OPSTR_PICTURE_IN_PICTURE, android.os.Process.myUid(), packageName) == AppOpsManager.MODE_ALLOWED
        } else {
            appOps?.checkOpNoThrow(AppOpsManager.OPSTR_PICTURE_IN_PICTURE, android.os.Process.myUid(), packageName) == AppOpsManager.MODE_ALLOWED
        }
    } else {
        false
    }
}
Crazy
  • 576
  • 6
  • 5
0

Permission is available from Android 26+ (Oreo).

On the Android 24+ it's allowed for all apps by default.

It's not available on Android 23 and lower as it's mentioned in some other answers.

So the correct logic would be:

private fun hasPipPermission(context: Context): Boolean {
    val appOps = context.getSystemService(Context.APP_OPS_SERVICE) as? AppOpsManager?
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val mode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            appOps?.unsafeCheckOpNoThrow(
                AppOpsManager.OPSTR_PICTURE_IN_PICTURE,
                android.os.Process.myUid(),
                context.packageName
            )
        } else {
            @Suppress("DEPRECATION")
            appOps?.checkOpNoThrow(
                AppOpsManager.OPSTR_PICTURE_IN_PICTURE,
                android.os.Process.myUid(),
                context.packageName
            )
        }
        mode == AppOpsManager.MODE_ALLOWED
    } else {
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
    }
}
user924
  • 8,146
  • 7
  • 57
  • 139