Android 权限适配 从此第三方系统新增的权限无法判断状态的问题得到解决! 如MIUI自启动, 后台弹出界面权限等

如图:
Android 权限适配 从此第三方系统新增的权限无法判断状态的问题得到解决! 如MIUI自启动, 后台弹出界面权限等_第1张图片

我们在做适配的时候有没有遇到一类需求, 比如 判断某个权限, 而这个权限是某手机自己创造的 不属于原生api, 怎么判断? 如 第三方ROM中的 [开机自启动] [后台省电] [后台打开界面] 等

现在, 有办法解决了!

很简单, 原理是通过反射AppOpsManager取得支持的变量, 理论上 华为小米 魅族这些新增的权限都会在这个类里面增加常量值, 我们只需要反射遍历这些常量值即可:
以[后台弹出界面] 权限为例:
我们在app里加入这个函数, 运行app 后观察log日志 观察哪些权限的变量名和[后台弹出界面] 的意思比较和相似, 进行定位

 /**
     * 通过这个获取所有的OPS Field, 理论上第三方系统厂商都是修改这个来实现新增权限的, 这个可以解决比如miui的自启动和后台弹出界面等
     */
    fun getAllOPSField(context: Context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            val manager = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
            val f = manager.javaClass.declaredFields
         
            for (field in f) {
                if (field.type == Int::class.java && Modifier.isStatic(field.modifiers)) {
                    field.isAccessible = true
                    println("${field.name} = ${field.get(null)}")
                }
            }
            
        }
    }

然后通过一下代码判断该权限

@RequiresApi(Build.VERSION_CODES.KITKAT)
        fun checkOp(context: Context, op: Int): Boolean {
            val version = Build.VERSION.SDK_INT
            if (version >= 19) {
                val manager = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
                try {
                    val managerClass = manager.javaClass
                    val method = managerClass.getDeclaredMethod(
                        "checkOp",
                        Int::class.java,
                        Int::class.java,
                        String::class.java
                    ).apply {
                        isAccessible = true
                    }
                    val isAllowNum =
                        method.invoke(manager, op, Binder.getCallingUid(), context.packageName) as Int

                    return AppOpsManager.MODE_ALLOWED == isAllowNum
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
            return false
        }

最后给出我自己通过以上方法记录到的变量值 (以MIUI11为例)

 		const val MIUI_OP_END = 10028
        const val MIUI_OP_START = 10000
        const val MODE_ALLOWED = 0
        const val MODE_ASK = 5
        const val MODE_DEFAULT = 3
        const val MODE_ERRORED = 2
        const val MODE_FOREGROUND = 4
        const val MODE_IGNORED = 1
        const val MODE_UNKNOWN = -1
        const val OP_ACCEPT_HANDOVER = 74
        const val OP_ACCESS_NOTIFICATIONS = 25
        const val OP_ACCESS_XIAOMI_ACCOUNT = 10015
        const val OP_ACTIVATE_VPN = 47
        const val OP_ADD_VOICEMAIL = 52
        const val OP_ANSWER_PHONE_CALLS = 69
        const val OP_ASSIST_SCREENSHOT = 50
        const val OP_ASSIST_STRUCTURE = 49
        const val OP_AUDIO_ACCESSIBILITY_VOLUME = 64
        const val OP_AUDIO_ALARM_VOLUME = 37
        const val OP_AUDIO_BLUETOOTH_VOLUME = 39
        const val OP_AUDIO_MASTER_VOLUME = 33
        const val OP_AUDIO_MEDIA_VOLUME = 36
        const val OP_AUDIO_NOTIFICATION_VOLUME = 38
        const val OP_AUDIO_RING_VOLUME = 35
        const val OP_AUDIO_VOICE_VOLUME = 34
        const val OP_AUTO_START = 10008 //是否允许自启动权限
        const val OP_BACKGROUND_LOCATION = 10027  //后台定位权限
        const val OP_BACKGROUND_START_ACTIVITY = 10021 //后台弹出界面
        const val OP_BIND_ACCESSIBILITY_SERVICE = 73
        const val OP_BLUETOOTH_CHANGE = 10002
        const val OP_BLUETOOTH_SCAN = 77
        const val OP_BODY_SENSORS = 56
        const val OP_BOOT_COMPLETED = 10007
        const val OP_CALL_PHONE = 13
        const val OP_CAMERA = 26
        const val OP_CHANGE_WIFI_STATE = 71
        const val OP_COARSE_LOCATION = 0
        const val OP_DATA_CONNECT_CHANGE = 10003
        const val OP_DELETE_CALL_LOG = 10013
        const val OP_DELETE_CONTACTS = 10012
        const val OP_DELETE_MMS = 10011
        const val OP_DELETE_SMS = 10010
        const val OP_EXACT_ALARM = 10014
        const val OP_FINE_LOCATION = 1
        const val OP_GET_ACCOUNTS = 62
        const val OP_GET_ANONYMOUS_ID = 10024
        const val OP_GET_INSTALLED_APPS = 10022
        const val OP_GET_TASKS = 10019
        const val OP_GET_UDEVICE_ID = 10025
        const val OP_GET_USAGE_STATS = 43
        const val OP_GPS = 2
        const val OP_INSTALL_SHORTCUT = 10017 //安装快捷方式
        const val OP_INSTANT_APP_START_FOREGROUND = 68
        const val OP_MANAGE_IPSEC_TUNNELS = 75
        const val OP_MOCK_LOCATION = 58
        const val OP_MONITOR_HIGH_POWER_LOCATION = 42
        const val OP_MONITOR_LOCATION = 41
        const val OP_MUTE_MICROPHONE = 44
        const val OP_NEIGHBORING_CELLS = 12
        const val OP_NFC = 10016
        const val OP_NFC_CHANGE = 10009
        const val OP_NONE = -1
        const val OP_PICTURE_IN_PICTURE = 67
        const val OP_PLAY_AUDIO = 28
        const val OP_POST_NOTIFICATION = 11
        const val OP_PROCESS_OUTGOING_CALLS = 54
        const val OP_PROJECT_MEDIA = 46
        const val OP_READ_CALENDAR = 8
        const val OP_READ_CALL_LOG = 6
        const val OP_READ_CELL_BROADCASTS = 57
        const val OP_READ_CLIPBOARD = 29
        const val OP_READ_CONTACTS = 4
        const val OP_READ_EXTERNAL_STORAGE = 59
        const val OP_READ_ICC_SMS = 21
        const val OP_READ_MMS = 10005
        const val OP_READ_NOTIFICATION_SMS = 10018
        const val OP_READ_PHONE_NUMBERS = 65
        const val OP_READ_PHONE_STATE = 51
        const val OP_READ_SMS = 14
        const val OP_RECEIVE_EMERGECY_SMS = 17
        const val OP_RECEIVE_MMS = 18
        const val OP_RECEIVE_SMS = 16
        const val OP_RECEIVE_WAP_PUSH = 19
        const val OP_RECORD_AUDIO = 27
        const val OP_REQUEST_DELETE_PACKAGES = 72
        const val OP_REQUEST_INSTALL_PACKAGES = 66
        const val OP_RUN_ANY_IN_BACKGROUND = 70
        const val OP_RUN_IN_BACKGROUND = 63
        const val OP_SEND_MMS = 10004
        const val OP_SEND_SMS = 20
        const val OP_SERVICE_FOREGROUND = 10023
        const val OP_SHOW_DEAMON_NOTIFICATION = 10026
        const val OP_SHOW_WHEN_LOCKED = 10020
        const val OP_START_FOREGROUND = 76
        const val OP_SYSTEM_ALERT_WINDOW = 24
        const val OP_TAKE_AUDIO_FOCUS = 32
        const val OP_TAKE_MEDIA_BUTTONS = 31
        const val OP_TOAST_WINDOW = 45
        const val OP_TURN_SCREEN_ON = 61
        const val OP_USE_FINGERPRINT = 55
        const val OP_USE_SIP = 53
        const val OP_VIBRATE = 3
        const val OP_WAKE_LOCK = 40
        const val OP_WIFI_CHANGE = 10001
        const val OP_WIFI_SCAN = 10
        const val OP_WRITE_CALENDAR = 9
        const val OP_WRITE_CALL_LOG = 7
        const val OP_WRITE_CLIPBOARD = 30
        const val OP_WRITE_CONTACTS = 5
        const val OP_WRITE_EXTERNAL_STORAGE = 60
        const val OP_WRITE_ICC_SMS = 22
        const val OP_WRITE_MMS = 10006
        const val OP_WRITE_SETTINGS = 23
        const val OP_WRITE_SMS = 15
        const val OP_WRITE_WALLPAPER = 48

是不是很眼熟?..OP_AUTO_START (自启动), .OP_BACKGROUND_START_ACTIVITY (后台弹出界面)

#那判断完成了怎么跳转?
看我另一篇文章 Intent跳转到[自启动]页面全网最全适配机型解决方案(持续更新)

欢迎加入技术交流群: 418263790

你可能感兴趣的:(Android适配问题)