小米、Vivo、Oppo后台弹出界面权限检测

小米、Vivo、Oppo后台弹出界面权限检测

记录一个开发中遇到App退到后台startActivity无法跳转问题

背景

公司App需求,从App切到第三方App时,需要在最顶层展示一个“返回”按钮,点击后一键切换回自己App~
然后用WindowManager撸了一个悬浮框,点击悬浮框时startActivity,华为手机一切正常。

测了一台小米手机才发现,startActivity调用了不生效并不会跳转~但我确信不是代码问题,肯定是雷布斯又做了什么定制

问题原因

度娘了一下才知道,原来小米、vivo等厂商为了不让后台应用乱弹广告,增加了一项“后台弹出界面”的权限,默认是禁止的,小米手机可见:小米关于默认关闭“后台弹出页面”权限的通知

不得不说出发点是好的,但并没有提供代码申请此权限,甚至连授权权限的页面都各不一样,设置里找半天才能找到这个块设置

由于我们小团队小项目,也没资格找厂商谈判默认打开,所以只能通过提示引导用户去手动打开~

但又不能一股脑的就喊用户去设置,有些手机是不需要这个权限的,至少得判断当前是否有这个权限,没权限的时候再喊用户去设置,这就合理多了,然后又开始了一轮度娘~

检测方法

直接上代码

小米:
    private fun isXiaomiBgStartPermissionAllowed(context: Context): Boolean {
        val ops = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
        try {
            val op = 10021
            val method: Method = ops.javaClass.getMethod("checkOpNoThrow", Int::class.javaPrimitiveType, Int::class.javaPrimitiveType, String::class.java)
            val result = method.invoke(ops, op, android.os.Process.myUid(), context.packageName) as Int
            return result == AppOpsManager.MODE_ALLOWED
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return false
    }
Vivo:
    private fun isVivoBgStartPermissionAllowed(context: Context): Boolean {
        return getVivoBgStartPermissionStatus(context) == 0
    }

    /**
     * 判断Vivo后台弹出界面状态, 1无权限,0有权限
     * @param context context
     */
    private fun getVivoBgStartPermissionStatus(context: Context): Int {
        val uri: Uri = Uri.parse("content://com.vivo.permissionmanager.provider.permission/start_bg_activity")
        val selection = "pkgname = ?"
        val selectionArgs = arrayOf(context.packageName)
        var state = 1
        try {
            context.contentResolver.query(uri, null, selection, selectionArgs, null)?.use {
                if (it.moveToFirst()) {
                    state = it.getInt(it.getColumnIndex("currentstate"))
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return state
    }
判断当前手机厂商:
    fun isXiaoMi(): Boolean {
        return checkManufacturer("xiaomi")
    }

    fun isOppo(): Boolean {
        return checkManufacturer("oppo")
    }

    fun isVivo(): Boolean {
        return checkManufacturer("vivo")
    }

    private fun checkManufacturer(manufacturer: String): Boolean {
        return manufacturer.equals(Build.MANUFACTURER, true)
    }
完整代码:
object RomUtils {
    private val TAG = RomUtils::class.java.simpleName

    fun isXiaoMi(): Boolean {
        return checkManufacturer("xiaomi")
    }

    fun isOppo(): Boolean {
        return checkManufacturer("oppo")
    }

    fun isVivo(): Boolean {
        return checkManufacturer("vivo")
    }

    private fun checkManufacturer(manufacturer: String): Boolean {
        return manufacturer.equals(Build.MANUFACTURER, true)
    }

    fun isBackgroundStartAllowed(context: Context): Boolean {
        if (isXiaoMi()) {
            return isXiaomiBgStartPermissionAllowed(context)
        }

        if (isVivo()) {
            return isVivoBgStartPermissionAllowed(context)
        }

        if (isOppo() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            return Settings.canDrawOverlays(context)
        }
        return true
    }


    private fun isXiaomiBgStartPermissionAllowed(context: Context): Boolean {
        val ops = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
        try {
            val op = 10021
            val method: Method = ops.javaClass.getMethod("checkOpNoThrow", Int::class.javaPrimitiveType, Int::class.javaPrimitiveType, String::class.java)
            val result = method.invoke(ops, op, android.os.Process.myUid(), context.packageName) as Int
            return result == AppOpsManager.MODE_ALLOWED
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return false
    }

    private fun isVivoBgStartPermissionAllowed(context: Context): Boolean {
        return getVivoBgStartPermissionStatus(context) == 0
    }

    /**
     * 判断Vivo后台弹出界面状态, 1无权限,0有权限
     * @param context context
     */
    private fun getVivoBgStartPermissionStatus(context: Context): Int {
        val uri: Uri = Uri.parse("content://com.vivo.permissionmanager.provider.permission/start_bg_activity")
        val selection = "pkgname = ?"
        val selectionArgs = arrayOf(context.packageName)
        var state = 1
        try {
            context.contentResolver.query(uri, null, selection, selectionArgs, null)?.use {
                if (it.moveToFirst()) {
                    state = it.getInt(it.getColumnIndex("currentstate"))
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return state
    }
}
  • 9
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值