当前位置:   article > 正文

Android 11 (API 级别 30)AppOpsManager.OnOpNotedCallback监听隐私运行时权限调用

appopsmanager.onopnotedcallback

一、简介

监听隐私运行时权限调用: 此流程在搭载 Android 11(API 级别 30)及更高版本的设备上可用,可让您更好地识别可能出现的意外数据访问。您的应用可以注册 AppOpsManager.OnOpNotedCallback 实例,该实例可在每次发生以下任一事件时执行相应操作:

  1. 应用的代码访问私密数据。为了帮助您确定应用的哪个逻辑部分调用了事件,您可以按归因标记审核数据访问。
  2. 依赖库或 SDK 中的代码访问私密数据。

数据访问审核是在发生数据请求的线程上调用的。这意味着,如果应用中的第三方 SDK 或库调用访问私密数据的 API,您的 OnOpNotedCallback 可以调用数据访问审核检查有关该调用的信息。通常,此回调对象可以通过查看应用的当前状态(例如当前线程的堆栈轨迹)以判断调用是来自您的应用还是来自 SDK。

二、使用

1. 监听单个activity

如需使用 AppOpsManager.OnOpNotedCallback 实例执行数据访问审核,请在您打算审核数据访问的组件中实现回调逻辑,例如在某个 Activity 的 onCreate() 方法中。

2. 全局监听

创建自定义子类 Application,并在子类的 onCreate() 方法中定义 AppOpsManager.OnOpNotedCallback。

执行注册监听

override fun onCreate(savedInstanceState: Bundle?) {
    val onOpNotedCallback = object : AppOpsManager.OnOpNotedCallback() {

        // 保存和记录信息。可能从不同线程调用,因此同步。可以进一步优化到只处理可变列表MutableList 的部分。
        /**
         *  @param operation 操作
         *  @param stackTrace 堆栈跟踪
         */
        @Synchronized
        private fun saveAndLog(operation: String, stackTrace: String) {
            // 将 操作和堆栈信息,存到opsNotedForThisApp
            opsNotedForThisApp.add(Pair(operation, stackTrace))

            // Log
            Log.d(TAG, "saveAndLog" + operation)
            Log.d(TAG, "saveAndLog stackTrace:" + stackTrace)


            // 输出到屏幕outputTextView
            val operationsOnly = opsNotedForThisApp.map { "- ${it.first}" }
            runOnUiThread {
                binding.outputTextView.text =
                    operationsOnly.joinToString("\n", "Check Log for stacktrace.\n", "\n")
            }
        }

        /**
         * onNoted—通过同步调用访问受保护数据时调用。例如,如果应用程序请求用户的最后一个已知位置,并且该函数立即返回值synchronous,则会触发onNoted。
         */
        override fun onNoted(operation: SyncNotedAppOp) {
            // 获取 操作operation.op    和 归因
            val operationDescription =
                prettyOperationDescription("onNoted()", operation.op, operation.attributionTag)
            // 获取当前线程的堆栈信息
            val prettyStackTrace = prettyStackTrack(Thread.currentThread().stackTrace)

            saveAndLog(operationDescription, prettyStackTrace)
        }

        /**
         * onAsyncNoted—通过异步回调访问受保护数据时调用。例如,如果某个应用程序订阅的位置发生了更改,
         * 则在调用具有新位置的回调时将触发onAsyncNoted。地理围栏是另一个例子。
         *
         * 重要提示:由于您正在等待GPS信号更新,因此单击按钮后可能需要一两分钟才能显示。
         */
        override fun onAsyncNoted(asyncOp: AsyncNotedAppOp) {
            val operationDescription =
                prettyOperationDescription("onAsyncNoted()", asyncOp.op, asyncOp.attributionTag)

            // 对于AsyncNotedAppOp,使用“message”字段而不是检索当前线程的堆栈跟踪来标识调用更有效。
            val message = asyncOp.message

            saveAndLog(operationDescription, message)
        }

        /**
         *  onSelfNoted—当开发人员调用{@link android.app.apppsmanager#noteOp}
         *  手动触发受保护的数据访问时调用。这是系统未触发的唯一回调。
         *     当应用程序感觉自己正在访问受保护的数据并想要对其进行审核时,这是一种自责的方式
         *
         *  这是一个相当罕见的用例,所以在大多数情况下,您不需要这样做。
         */
        override fun onSelfNoted(operation: SyncNotedAppOp) {
            val operationDescription =
                prettyOperationDescription("onSelfNoted()", operation.op, operation.attributionTag)

            val prettyStackTrace = prettyStackTrack(Thread.currentThread().stackTrace)

            saveAndLog(operationDescription, prettyStackTrace)
        }
    }

    val appOpsManager =
            getSystemService(AppOpsManager::class.java) as AppOpsManager
    appOpsManager.setOnOpNotedCallback(mainExecutor, appOpsCallback)
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76

三、按归因【Attribution】标记审核数据访问

如果您在某个 Activity 中访问数据(例如请求位置信息或访问用户的联系人列表),请在该 Activity 的 onCreate() 方法中调用 createAttributionContext(),并传入您希望与应用的一部分相关联的归因标记。

以下代码段展示了如何为应用的“照片位置信息分享”部分创建归因标记:

class SharePhotoLocationActivity : AppCompatActivity() {
    lateinit var attributionContext: Context

    override fun onCreate(savedInstanceState: Bundle?) {
        attributionContext = createAttributionContext("sharePhotos")
    }

    fun getLocation() {
        val locationManager = attributionContext.getSystemService(
                LocationManager::class.java) as LocationManager
        // Use "locationManager" to access device location information.
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在 回调中拿到归因tag,知道调用原因

val appOpsCallback = object : AppOpsManager.OnOpNotedCallback() {
    // attributionTag  归因tag
    private fun logPrivateDataAccess(
            opCode: String, attributionTag: String, trace: String) {
        Log.i(MY_APP_TAG, "Private data accessed. " +
                    "Operation: $opCode\n " +
                    "Attribution Tag:$attributionTag\nStack Trace:\n$trace")
    }

    override fun onNoted(syncNotedAppOp: SyncNotedAppOp) {
        logPrivateDataAccess(syncNotedAppOp.op,
                syncNotedAppOp.attributionTag,
                Throwable().stackTrace.toString())
    }

    override fun onSelfNoted(syncNotedAppOp: SyncNotedAppOp) {
        logPrivateDataAccess(syncNotedAppOp.op,
                syncNotedAppOp.attributionTag,
                Throwable().stackTrace.toString())
    }

    override fun onAsyncNoted(asyncNotedAppOp: AsyncNotedAppOp) {
        logPrivateDataAccess(asyncNotedAppOp.op,
                asyncNotedAppOp.attributionTag,
                asyncNotedAppOp.message)
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

四、权限列表

运行时权限:

group:android.permission-group.CONTACTS
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
 
group:android.permission-group.PHONE
permission:android.permission.READ_CALL_LOG
permission:android.permission.READ_PHONE_STATE
permission:android.permission.CALL_PHONE
permission:android.permission.WRITE_CALL_LOG
permission:android.permission.USE_SIP
permission:android.permission.PROCESS_OUTGOING_CALLS
permission:com.android.voicemail.permission.ADD_VOICEMAIL
 
group:android.permission-group.CALENDAR
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDAR
 
group:android.permission-group.CAMERA
permission:android.permission.CAMERA
 
group:android.permission-group.SENSORS
permission:android.permission.BODY_SENSORS
 
group:android.permission-group.LOCATION
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATION
 
group:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
 
group:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIO
 
group:android.permission-group.SMS
permission:android.permission.READ_SMS
permission:android.permission.RECEIVE_WAP_PUSH
permission:android.permission.RECEIVE_MMS
permission:android.permission.RECEIVE_SMS
permission:android.permission.SEND_SMS
permission:android.permission.READ_CELL_BROADCASTS
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

普通权限

 
ACCESS_LOCATION_EXTRA_COMMANDS 定位权限
 
ACCESS_NETWORK_STATE 网络状态权限
 
ACCESS_NOTIFICATION_POLICY 通知 APP通知显示在状态栏
 
ACCESS_WIFI_STATE WiFi状态权限
 
BLUETOOTH 使用蓝牙权限
 
BLUETOOTH_ADMIN 控制蓝牙开关
 
BROADCAST_STICKY 粘性广播
 
CHANGE_NETWORK_STATE 改变网络状态
 
CHANGE_WIFI_MULTICAST_STATE 改变WiFi多播状态,应该是控制手机热点(猜测)
 
CHANGE_WIFI_STATE 控制WiFi开关,改变WiFi状态
 
DISABLE_KEYGUARD 改变键盘为不可用
 
EXPAND_STATUS_BAR 扩展bar的状态
 
GET_PACKAGE_SIZE 获取应用安装包大小
 
INTERNET 网络权限
 
KILL_BACKGROUND_PROCESSES 杀死后台进程
 
MODIFY_AUDIO_SETTINGS 改变音频输出设置
 
NFC 支付
 
READ_SYNC_SETTINGS 获取手机设置信息
 
READ_SYNC_STATS 数据统计
 
RECEIVE_BOOT_COMPLETED 监听启动广播
 
REORDER_TASKS 创建新栈
 
REQUEST_INSTALL_PACKAGES 安装应用程序
 
SET_TIME_ZONE 允许应用程序设置系统时间区域
 
SET_WALLPAPER 设置壁纸
 
SET_WALLPAPER_HINTS 设置壁纸上的提示信息,个性化语言
 
TRANSMIT_IR 红外发射
 
USE_FINGERPRINT 指纹识别
 
VIBRATE 震动
 
WAKE_LOCK 锁屏
 
WRITE_SYNC_SETTINGS 改变设置
 
SET_ALARM 设置警告提示
 
INSTALL_SHORTCUT 创建快捷方式
 
UNINSTALL_SHORTCUT 删除快捷方式



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

官方demo

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/261412
推荐阅读
相关标签
  

闽ICP备14008679号