Android动态运行时权限

        android 6.0(API 级别 23)开始,android引入了运行时权限,应用安装时不向其授予权限,应用运行时向其授予权限。如果在运行时该功能没有动态地申请相应的权限,就会抛出SecurityException异常。

        android的运行时权限的申请过程主要有两步:
        1、在需要申请权限的地方检查该权限是否被授权,如果已经授权就直接执行,如果未授权就动态申请权限。
        2、重写Activity或Fragment的onRequestPermissionsResult方法,根据grantResults数组判断权限是否被授权,如果授权就直接执行,如果未授权就要进行相应的提示,如果用户勾选了“don't ask again”,还要引导用户去“Settings”界面打开权限,这时还要重写onActivityResult判断权限是否被授权。

权限的分类

        android中所有的预定义权限(不包括厂商自定义的)都可以在Manifest.permission这个静态类中找到定义,android把权限分为四类:普通权限、签名权限、危险权限和特殊权限,每一种类型的权限都分配一个对应的Protection Level,分别为:normal、signature、dangerous和appop。

1、普通权限
普通权限,Protection Level为normal,不需要动态申请,只需要在AndroidManifest.xml中静态地声明,系统在应用安装时就会自动的授予该应用相应的权限。

2、签名权限
这类权限我们用得比较少,它只对拥有相同签名的应用开放,Protection Level为signature,不需要动态申请,例如应用A在AndroidManifest.xml中自定义了一个permission且在权限标签中加入android:protectionLevel=”signature”,表示应用A声明了一个签名权限,那么应用B想要访问应用A受该权限保护的数据时,必须要在AndroidManifest.xml中声明该权限,同时要用与应用A相同的签名打包,这样系统在应用B安装时才会自动地授予应用B该权限,应用B在获得授权后就可以访问该权限控制的数据,其他应用即使知道这个权限,也在AndroidManifest.xml中声明了该权限,但由于应用签名不同,安装时系统不会授予它该权限,这样其他应用就无法访问受该权限保护的数据。
还有一些签名权限不会供第三方应用程序使用,只会供系统预装应用使用,这种签名权限的Protection Level为signature和privileged。

3、危险权限
危险权限也叫运行时权限,Protection Level为dangerous,
所有的危险权限都有对应的权限组,当我们动态的申请某个危险权限时,都是按权限组申请的,当用户一旦同意授权该危险权限,那么该权限所对应的权限组中的其他在AndroidManifest.xml中注册的权限也会同时被授权,android预定义的11个权限组包含的危险权限如下:

Permission Group Dangerous Permissions
CALENDAR (日历) READ_CALENDAR
WRITE_CALENDAR
CALL_LOG (通话记录,Added in android 29) READ_CALL_LOG
WRITE_CALL_LOG
PROCESS_OUTGOING_CALLS
CAMERA (相机) CAMERA
CONTACTS (通讯录) READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS
LOCATION (位置信息) ACCESS_COARSE_LOCATION
ACCESS_FINE_LOCATION
ACCESS_BACKGROUND_LOCATION (Added in android 10)
MICROPHONE (麦克风) RECORD_AUDIO
PHONE (电话) READ_PHONE_NUMBERS  READ_PHONE_STATE  CALL_PHONE  ANSWER_PHONE_CALLS  ADD_VOICEMAIL  USE_SIP  ACCEPT_HANDOVER (Added in android 9)
SENSORS (身体传感器) BODY_SENSORS
SMS (短信) BODY_SENSORS
STORAGE (存储空间) READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE
ACCESS_MEDIA_LOCATION (Added in android 10)
ACTIVITY_RECOGNITION (身体活动,Added in android 10)     ACTIVITY_RECOGNITION (Added in android 10)
访问媒体文件  READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, READ_MEDIA_AUDIO (Added in android 13)
通知权限 POST_NOTIFICATIONS (Added in android 13)

4.特殊权限

特殊权限用于保护一些特定的应用程序操作,Protection Level为appop,使用前也需要在AndroidManifest.xml中静态地声明,也需要动态的申请,特殊权限的申请需要跳转到指定的设置界面,点击同意,截止到android 11,常用的5个特殊权限为:

1.SYSTEM_ALERT_WINDOW:允许应用在其他应用的顶部绘制悬浮窗,当你创建的悬浮窗是TYPE_APPLICATION_OVERLAY类型时需要申请这个权限;


2.WRITE_SETTINGS:允许应用修改系统设置,当你需要修改系统参数Settings.System时需要申请该权限,例如修改系统屏幕亮度等;


3.REQUEST_INSTALL_PACKAGES: 允许应用安装未知来源应用,android 8.0以后当你在应用中安装第三方应用时需要申请这个权限,否则不会跳转到安装界面;


4.PACKAGE_USAGE_STATS:允许应用收集其他应用的使用信息,当你使用UsageStatsManager相关Api获取其他应用的信息时需要申请这个权限;


5.MANAGE_EXTERNAL_STORAGE(Added in android 11):允许应用访问作用域存储(scoped storage)中的外部存储,android 11以后强制新安装的应用使用作用域存储,但是对于文件管理器这一类的应用它们需要管理整个SD卡上的文件,所以针对这些特殊应用可以申请这个权限来获得对整个SD卡的读写权限,当应用授予这个权限后,它就可以访问文件的真实路径,注意这个权限是很危险的,声明这个权限上架应用时可能需要进行审核.

除了特殊权限,LOCATION权限组中的位置权限也有点特殊,需要注意一下,位置信息的获取不仅依赖位置权限的动态申请还依赖系统定位开关,如果你没有打开定位开关就申请了位置权限,那么就算用户同意授权位置权限,应用通过Location相关Api也无法获取到位置信息,所以申请位置权限前,最好先通过LocationManager#isProviderEnabled方法判断是否打开定位开关后再进行位置权限的申请,如果没有打开定位开关需要先跳转到设置界面打开定位开关:


    LocationManager locationManager = (LocationManager) getContext()
                    .getSystemService(Context.LOCATION_SERVICE);
            if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
               //请求权限
            } else {
                    //跳转到开启定位的地方
        Toast.makeText(this, "检测到未开启定位服务,请开启", Toast.LENGTH_SHORT).show();
        Intent intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        startActivityForResult(intent, REQUEST_CODE_LOCATION_PROVIDER);
            }
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package android;

public final class Manifest {
    public Manifest() {
        throw new RuntimeException("Stub!");
    }

    public static final class permission_group {
        public static final String ACTIVITY_RECOGNITION = "android.permission-group.ACTIVITY_RECOGNITION";
        public static final String CALENDAR = "android.permission-group.CALENDAR";
        public static final String CALL_LOG = "android.permission-group.CALL_LOG";
        public static final String CAMERA = "android.permission-group.CAMERA";
        public static final String CONTACTS = "android.permission-group.CONTACTS";
        public static final String LOCATION = "android.permission-group.LOCATION";
        public static final String MICROPHONE = "android.permission-group.MICROPHONE";
        public static final String NEARBY_DEVICES = "android.permission-group.NEARBY_DEVICES";
        public static final String PHONE = "android.permission-group.PHONE";
        public static final String SENSORS = "android.permission-group.SENSORS";
        public static final String SMS = "android.permission-group.SMS";
        public static final String STORAGE = "android.permission-group.STORAGE";

        public permission_group() {
            throw new RuntimeException("Stub!");
        }
    }

    public static final class permission {
        public static final String ACCEPT_HANDOVER = "android.permission.ACCEPT_HANDOVER";
        public static final String ACCESS_BACKGROUND_LOCATION = "android.permission.ACCESS_BACKGROUND_LOCATION";
        public static final String ACCESS_BLOBS_ACROSS_USERS = "android.permission.ACCESS_BLOBS_ACROSS_USERS";
        public static final String ACCESS_CHECKIN_PROPERTIES = "android.permission.ACCESS_CHECKIN_PROPERTIES";
        public static final String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
        public static final String ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION";
        public static final String ACCESS_LOCATION_EXTRA_COMMANDS = "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS";
        public static final String ACCESS_MEDIA_LOCATION = "android.permission.ACCESS_MEDIA_LOCATION";
        public static final String ACCESS_NETWORK_STATE = "android.permission.ACCESS_NETWORK_STATE";
        public static final String ACCESS_NOTIFICATION_POLICY = "android.permission.ACCESS_NOTIFICATION_POLICY";
        public static final String ACCESS_WIFI_STATE = "android.permission.ACCESS_WIFI_STATE";
        public static final String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER";
        public static final String ACTIVITY_RECOGNITION = "android.permission.ACTIVITY_RECOGNITION";
        public static final String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL";
        public static final String ANSWER_PHONE_CALLS = "android.permission.ANSWER_PHONE_CALLS";
        public static final String BATTERY_STATS = "android.permission.BATTERY_STATS";
        public static final String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
        public static final String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
        public static final String BIND_AUTOFILL_SERVICE = "android.permission.BIND_AUTOFILL_SERVICE";
        public static final String BIND_CALL_REDIRECTION_SERVICE = "android.permission.BIND_CALL_REDIRECTION_SERVICE";
        public static final String BIND_CARRIER_MESSAGING_CLIENT_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_CLIENT_SERVICE";
        /** @deprecated */
        @Deprecated
        public static final String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE";
        public static final String BIND_CARRIER_SERVICES = "android.permission.BIND_CARRIER_SERVICES";
        /** @deprecated */
        @Deprecated
        public static final String BIND_CHOOSER_TARGET_SERVICE = "android.permission.BIND_CHOOSER_TARGET_SERVICE";
        public static final String BIND_COMPANION_DEVICE_SERVICE = "android.permission.BIND_COMPANION_DEVICE_SERVICE";
        public static final String BIND_CONDITION_PROVIDER_SERVICE = "android.permission.BIND_CONDITION_PROVIDER_SERVICE";
        public static final String BIND_CONTROLS = "android.permission.BIND_CONTROLS";
        public static final String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
        public static final String BIND_DREAM_SERVICE = "android.permission.BIND_DREAM_SERVICE";
        public static final String BIND_INCALL_SERVICE = "android.permission.BIND_INCALL_SERVICE";
        public static final String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
        public static final String BIND_MIDI_DEVICE_SERVICE = "android.permission.BIND_MIDI_DEVICE_SERVICE";
        public static final String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
        public static final String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
        public static final String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
        public static final String BIND_QUICK_ACCESS_WALLET_SERVICE = "android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE";
        public static final String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
        public static final String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
        public static final String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
        public static final String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
        public static final String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
        public static final String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
        public static final String BIND_VISUAL_VOICEMAIL_SERVICE = "android.permission.BIND_VISUAL_VOICEMAIL_SERVICE";
        public static final String BIND_VOICE_INTERACTION = "android.permission.BIND_VOICE_INTERACTION";
        public static final String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
        public static final String BIND_VR_LISTENER_SERVICE = "android.permission.BIND_VR_LISTENER_SERVICE";
        public static final String BIND_WALLPAPER = "android.permission.BIND_WALLPAPER";
        public static final String BLUETOOTH = "android.permission.BLUETOOTH";
        public static final String BLUETOOTH_ADMIN = "android.permission.BLUETOOTH_ADMIN";
        public static final String BLUETOOTH_ADVERTISE = "android.permission.BLUETOOTH_ADVERTISE";
        public static final String BLUETOOTH_CONNECT = "android.permission.BLUETOOTH_CONNECT";
        public static final String BLUETOOTH_PRIVILEGED = "android.permission.BLUETOOTH_PRIVILEGED";
        public static final String BLUETOOTH_SCAN = "android.permission.BLUETOOTH_SCAN";
        public static final String BODY_SENSORS = "android.permission.BODY_SENSORS";
        public static final String BROADCAST_PACKAGE_REMOVED = "android.permission.BROADCAST_PACKAGE_REMOVED";
        public static final String BROADCAST_SMS = "android.permission.BROADCAST_SMS";
        public static final String BROADCAST_STICKY = "android.permission.BROADCAST_STICKY";
        public static final String BROADCAST_WAP_PUSH = "android.permission.BROADCAST_WAP_PUSH";
        public static final String CALL_COMPANION_APP = "android.permission.CALL_COMPANION_APP";
        public static final String CALL_PHONE = "android.permission.CALL_PHONE";
        public static final String CALL_PRIVILEGED = "android.permission.CALL_PRIVILEGED";
        public static final String CAMERA = "android.permission.CAMERA";
        public static final String CAPTURE_AUDIO_OUTPUT = "android.permission.CAPTURE_AUDIO_OUTPUT";
        public static final String CHANGE_COMPONENT_ENABLED_STATE = "android.permission.CHANGE_COMPONENT_ENABLED_STATE";
        public static final String CHANGE_CONFIGURATION = "android.permission.CHANGE_CONFIGURATION";
        public static final String CHANGE_NETWORK_STATE = "android.permission.CHANGE_NETWORK_STATE";
        public static final String CHANGE_WIFI_MULTICAST_STATE = "android.permission.CHANGE_WIFI_MULTICAST_STATE";
        public static final String CHANGE_WIFI_STATE = "android.permission.CHANGE_WIFI_STATE";
        public static final String CLEAR_APP_CACHE = "android.permission.CLEAR_APP_CACHE";
        public static final String CONTROL_LOCATION_UPDATES = "android.permission.CONTROL_LOCATION_UPDATES";
        public static final String DELETE_CACHE_FILES = "android.permission.DELETE_CACHE_FILES";
        public static final String DELETE_PACKAGES = "android.permission.DELETE_PACKAGES";
        public static final String DIAGNOSTIC = "android.permission.DIAGNOSTIC";
        public static final String DISABLE_KEYGUARD = "android.permission.DISABLE_KEYGUARD";
        public static final String DUMP = "android.permission.DUMP";
        public static final String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR";
        public static final String FACTORY_TEST = "android.permission.FACTORY_TEST";
        public static final String FOREGROUND_SERVICE = "android.permission.FOREGROUND_SERVICE";
        public static final String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
        public static final String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
        public static final String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
        /** @deprecated */
        @Deprecated
        public static final String GET_TASKS = "android.permission.GET_TASKS";
        public static final String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH";
        public static final String HIDE_OVERLAY_WINDOWS = "android.permission.HIDE_OVERLAY_WINDOWS";
        public static final String HIGH_SAMPLING_RATE_SENSORS = "android.permission.HIGH_SAMPLING_RATE_SENSORS";
        public static final String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER";
        public static final String INSTALL_PACKAGES = "android.permission.INSTALL_PACKAGES";
        public static final String INSTALL_SHORTCUT = "com.android.launcher.permission.INSTALL_SHORTCUT";
        public static final String INSTANT_APP_FOREGROUND_SERVICE = "android.permission.INSTANT_APP_FOREGROUND_SERVICE";
        public static final String INTERACT_ACROSS_PROFILES = "android.permission.INTERACT_ACROSS_PROFILES";
        public static final String INTERNET = "android.permission.INTERNET";
        public static final String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
        public static final String LOADER_USAGE_STATS = "android.permission.LOADER_USAGE_STATS";
        public static final String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
        public static final String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS";
        public static final String MANAGE_EXTERNAL_STORAGE = "android.permission.MANAGE_EXTERNAL_STORAGE";
        public static final String MANAGE_MEDIA = "android.permission.MANAGE_MEDIA";
        public static final String MANAGE_ONGOING_CALLS = "android.permission.MANAGE_ONGOING_CALLS";
        public static final String MANAGE_OWN_CALLS = "android.permission.MANAGE_OWN_CALLS";
        public static final String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
        public static final String MEDIA_CONTENT_CONTROL = "android.permission.MEDIA_CONTENT_CONTROL";
        public static final String MODIFY_AUDIO_SETTINGS = "android.permission.MODIFY_AUDIO_SETTINGS";
        public static final String MODIFY_PHONE_STATE = "android.permission.MODIFY_PHONE_STATE";
        public static final String MOUNT_FORMAT_FILESYSTEMS = "android.permission.MOUNT_FORMAT_FILESYSTEMS";
        public static final String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS";
        public static final String NFC = "android.permission.NFC";
        public static final String NFC_PREFERRED_PAYMENT_INFO = "android.permission.NFC_PREFERRED_PAYMENT_INFO";
        public static final String NFC_TRANSACTION_EVENT = "android.permission.NFC_TRANSACTION_EVENT";
        public static final String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS";
        /** @deprecated */
        @Deprecated
        public static final String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY";
        /** @deprecated */
        @Deprecated
        public static final String PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS";
        public static final String QUERY_ALL_PACKAGES = "android.permission.QUERY_ALL_PACKAGES";
        public static final String READ_CALENDAR = "android.permission.READ_CALENDAR";
        public static final String READ_CALL_LOG = "android.permission.READ_CALL_LOG";
        public static final String READ_CONTACTS = "android.permission.READ_CONTACTS";
        public static final String READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE";
        /** @deprecated */
        @Deprecated
        public static final String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE";
        public static final String READ_LOGS = "android.permission.READ_LOGS";
        public static final String READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS";
        public static final String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
        public static final String READ_PRECISE_PHONE_STATE = "android.permission.READ_PRECISE_PHONE_STATE";
        public static final String READ_SMS = "android.permission.READ_SMS";
        public static final String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
        public static final String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
        public static final String READ_VOICEMAIL = "com.android.voicemail.permission.READ_VOICEMAIL";
        public static final String REBOOT = "android.permission.REBOOT";
        public static final String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED";
        public static final String RECEIVE_MMS = "android.permission.RECEIVE_MMS";
        public static final String RECEIVE_SMS = "android.permission.RECEIVE_SMS";
        public static final String RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH";
        public static final String RECORD_AUDIO = "android.permission.RECORD_AUDIO";
        public static final String REORDER_TASKS = "android.permission.REORDER_TASKS";
        public static final String REQUEST_COMPANION_PROFILE_WATCH = "android.permission.REQUEST_COMPANION_PROFILE_WATCH";
        public static final String REQUEST_COMPANION_RUN_IN_BACKGROUND = "android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND";
        public static final String REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND = "android.permission.REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND";
        public static final String REQUEST_COMPANION_USE_DATA_IN_BACKGROUND = "android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND";
        public static final String REQUEST_DELETE_PACKAGES = "android.permission.REQUEST_DELETE_PACKAGES";
        public static final String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
        public static final String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
        public static final String REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE = "android.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE";
        public static final String REQUEST_PASSWORD_COMPLEXITY = "android.permission.REQUEST_PASSWORD_COMPLEXITY";
        /** @deprecated */
        @Deprecated
        public static final String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
        public static final String SCHEDULE_EXACT_ALARM = "android.permission.SCHEDULE_EXACT_ALARM";
        public static final String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
        public static final String SEND_SMS = "android.permission.SEND_SMS";
        public static final String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
        public static final String SET_ALWAYS_FINISH = "android.permission.SET_ALWAYS_FINISH";
        public static final String SET_ANIMATION_SCALE = "android.permission.SET_ANIMATION_SCALE";
        public static final String SET_DEBUG_APP = "android.permission.SET_DEBUG_APP";
        /** @deprecated */
        @Deprecated
        public static final String SET_PREFERRED_APPLICATIONS = "android.permission.SET_PREFERRED_APPLICATIONS";
        public static final String SET_PROCESS_LIMIT = "android.permission.SET_PROCESS_LIMIT";
        public static final String SET_TIME = "android.permission.SET_TIME";
        public static final String SET_TIME_ZONE = "android.permission.SET_TIME_ZONE";
        public static final String SET_WALLPAPER = "android.permission.SET_WALLPAPER";
        public static final String SET_WALLPAPER_HINTS = "android.permission.SET_WALLPAPER_HINTS";
        public static final String SIGNAL_PERSISTENT_PROCESSES = "android.permission.SIGNAL_PERSISTENT_PROCESSES";
        /** @deprecated */
        @Deprecated
        public static final String SMS_FINANCIAL_TRANSACTIONS = "android.permission.SMS_FINANCIAL_TRANSACTIONS";
        public static final String START_FOREGROUND_SERVICES_FROM_BACKGROUND = "android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND";
        public static final String START_VIEW_PERMISSION_USAGE = "android.permission.START_VIEW_PERMISSION_USAGE";
        public static final String STATUS_BAR = "android.permission.STATUS_BAR";
        public static final String SYSTEM_ALERT_WINDOW = "android.permission.SYSTEM_ALERT_WINDOW";
        public static final String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
        public static final String UNINSTALL_SHORTCUT = "com.android.launcher.permission.UNINSTALL_SHORTCUT";
        public static final String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
        public static final String UPDATE_PACKAGES_WITHOUT_USER_ACTION = "android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION";
        public static final String USE_BIOMETRIC = "android.permission.USE_BIOMETRIC";
        /** @deprecated */
        @Deprecated
        public static final String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
        public static final String USE_FULL_SCREEN_INTENT = "android.permission.USE_FULL_SCREEN_INTENT";
        public static final String USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = "android.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER";
        public static final String USE_SIP = "android.permission.USE_SIP";
        public static final String UWB_RANGING = "android.permission.UWB_RANGING";
        public static final String VIBRATE = "android.permission.VIBRATE";
        public static final String WAKE_LOCK = "android.permission.WAKE_LOCK";
        public static final String WRITE_APN_SETTINGS = "android.permission.WRITE_APN_SETTINGS";
        public static final String WRITE_CALENDAR = "android.permission.WRITE_CALENDAR";
        public static final String WRITE_CALL_LOG = "android.permission.WRITE_CALL_LOG";
        public static final String WRITE_CONTACTS = "android.permission.WRITE_CONTACTS";
        public static final String WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE";
        public static final String WRITE_GSERVICES = "android.permission.WRITE_GSERVICES";
        public static final String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS";
        public static final String WRITE_SETTINGS = "android.permission.WRITE_SETTINGS";
        public static final String WRITE_SYNC_SETTINGS = "android.permission.WRITE_SYNC_SETTINGS";
        public static final String WRITE_VOICEMAIL = "com.android.voicemail.permission.WRITE_VOICEMAIL";

        public permission() {
            throw new RuntimeException("Stub!");
        }
    }
}

动态权限申请设计 

权限申请相关变更

1.android 8.0以后并且应用的targetSdkVersion >= 28时,应用申请某个危险权限授权,用户同意后,系统不再把该危险权限对应的权限组中的其他在AndroidManifest.xml中注册的权限一并授予给应用,系统只会授予应用明确请求的权限。一旦用户应用同意授权某个危险权限,则后续对该危险权限的权限组中的其他权限请求都会被自动批准,而不会提示用户。例如某个应用在AndroidManifest.xml中注册READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限,应用申请READ_EXTERNAL_STORAGE权限并且用户同意,在android 8.0之前,系统在用户同意后还会一并授予WRITE_EXTERNAL_STORAGE权限,因为它和READ_EXTERNAL_STORAGE权限是同一个权限组并且也在AndroidManifest.xml中注册。但在android 8.0之后并且应用的targetSdkVersion >= 28,系统在用户同意后只会授予READ_EXTERNAL_STORAGE权限,但是如果后来应用又申请WRITE_EXTERNAL_STORAGE权限,系统会立即授予该权限,而不会提示用户,换句话说,如果只申请了外部存储空间读取权限,在低版本下(android < 8.0)对外部存储空间使用写入操作是没有问题的,但是在高版本(android >= 8.0 && targetSdkVersion >= 28)下是会出现问题的,解决方案是将两个读和写的权限一起申请。

2.android 9.0增加了CALL_LOG(通话记录)权限组,并把READ_CALL_LOG、WRITE_CALL_LOG]、PROCESS_OUTGOING_CALLS权限从PHONE(电话)权限组移动到了CALL_LOG权限组,CALL_LOG权限组使得用户能够更好地控制需要访问电话通话记录敏感信息的应用程序,例如读取通话记录和识别电话号码。

3.android 10引入了很多隐私变更,新增了ACTIVITY_RECOGNITION(身体活动)权限和权限组,允许应用检测用户的步数或分类用户的身体活动如步行、骑自行车等;同时android 10引入了作用域存储,当应用启用作用域存储时,WRITE_EXTERNAL_STORAGE权限会失效,应用对WRITE_EXTERNAL_STORAGE权限的申请不会对应用的存储访问权限产生任何影响,并且WRITE_EXTERNAL_STORAGE会在未来被废弃,因为作用域存储的目的就是不让应用随意的修改应用沙盒外的外部存储;同时新增了ACCESS_BACKGROUND_LOCATION权限,归属于LOCATION权限组,用于后台运行的应用访问用户定位时申请,与ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION这些前台定位权限区分开,当你的应用targetSdkVersion >= 29并且运行在android 10以上时,应用在后台访问定位时需要动态的申请后台定位权限,当你把后台定位权限和前台定位权限一起申请时,弹窗授权框会有2个允许选项:始终允许和仅在应用使用过程中允许,点击始终允许表示同时授权后台定位权限和前台定位权限,点击仅在应用使用过程中允许表示仅授权前台定位权限,然后下次再次申请时只会单独申请后台定位权限,并且也会有2个允许选项,并且要点击始终允许才会让后台定位权限申请通过,当你的应用targetSdkVersion < 29运行在android 10以上时,应用在申请前台定位权限时系统会把后台定位权限一并授予给应用;android 10还新增了ACCESS_MEDIA_LOCATION权限,归属于STORAGE (存储空间) 权限组,android 10以后,因为隐私问题,默认不再提供图片的地理位置信息,要获取该信息需要向用户申请ACCESS_MEDIA_LOCATION权限,并使用MediaStore.setRequireOriginal()接口更新文件Uri。

4.android 11也引入了很多隐私变更,android 11强制新安装的应用(targetSdkVersion >= 30)启用作用域存储,新增MANAGE_EXTERNAL_STORAGE用于代替WRITE_EXTERNAL_STORAGE权限,提供给手机管家、文件管理器这类需要管理整个SD卡上的文件的应用申请;android 11中当用户开启“安装未知来源应用”权限后返回应用,应用会被杀死重启,该行为与强制分区存储有关;从android 11后,如果应用对某个权限连续点击多次拒绝,那么下一次请求该权限时系统会直接拒绝连授权弹窗都不会弹出,该行为等同于android 11之前勾选了don‘t ask again;android 11后还新增了一次性权限(One-time permissions)和权限自动重置功能(Permissions auto-reset),这些变更只要你正确的进行运行时权限请求就不需要做额外适配;同时android 11后当targetSdkVersion < 30的应用把后台定位权限和前台定位权限一起申请时,弹窗授权框的允许选项中不再会显示始终允许选项,只有本次允许和仅在应用使用过程中允许,也就说点击允许时只会授予你前台定位权限不再默认授予你后台定位权限,而android 11后targetSdkVersion >= 30的应用的ACCESS_BACKGROUND_LOCATION权限需要独立申请,不能与前台权限一起申请,如果与前台权限一起申请,系统会直接拒绝连授权弹窗都不会弹出,系统推荐增量请求权限,这样对用户更友好,同时用户必须先同意前台权限后才能进入后台定位权限的申请。
可以看到从android 10引入ACCESS_BACKGROUND_LOCATION权限以来,后台定位权限的申请一直都非常特殊,它在android 10可以和前台定位权限一起申请,而在android 11又不可以一起申请还有先后申请顺序,针对这种特殊情况,申请后台定位权限时要做到:

1、先请求前台定位权限,再请求后台定位权限;
2、单独请求后台定位权限,不要与其他权限一同请求.

5.Android 13增加了通知权限,开发者需要在AndroidManifest.xml中声明POST_NOTIFICATIONS权限,还需要在使用通知栏推送功能时在代码中申请运行时权限:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="xxx.xxx.xxx.xxx">
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
</manifest>
requestPermissions(new String[]{“android.permission.POST_NOTIFICATIONS”})

6.Android13对本地数据访问权限也做了进一步细化。Android13将READ_EXTERNAL_STORAGE和 WRITE_EXTERNAL_STORAGE权限细分为:READ_MEDIA_IMAGES、 READ_MEDIA_VIDEO和 READ_MEDIA_AUDIO。单独请求READ_MEDIA_IMAGES、单独请求 READ_MEDIA_VIDEO和同时请求READ_MEDIA_IMAGES& READ_MEDIA_VIDEO,系统均将只显示一个授权弹窗。 
另外,如果App(targetSdk == 33)已经申请了读的权限,那App同时也就有了写的权限,无需再额外声明 WRITE_EXTERNAL_STORAGE权限。

猜你喜欢

转载自blog.csdn.net/zhangying1994/article/details/128550327