How to know if user has disabled Picture in Picture feature permission?

3.8k Views Asked by At

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 ?

4

There are 4 best solutions below

1
On BEST ANSWER

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.

5
On

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
}
0
On

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
    }
}
0
On

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