ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Android 权限申请案例以及注意事项

2021-02-25 18:59:26  阅读:269  来源: 互联网

标签:READ 程序 用户 应用程序 注意事项 允许 Android 权限


权限的目的是为了保护Android用户的隐私。Android应用程序必须请求允许访问敏感用户数据(如联系人和 SMS),以及某些系统特征(如摄像头和 Internet)。根据该特征,系统可以自动授予许可,或者提示用户批准请求。

在Android 6.0以前的设备上,系统将不会提醒用户正在获取的权限。一旦安装应用,就意味着该应用所需的所有权限均已获得。 在不经用户同意的情况下,一些应用在后台可以自由地收集用户隐私信息而不被用户察觉。

为了解决这个问题,从Android 6.0版本开始,在安装应用时,该应用无法取得任何权限。在使用应用的过程中,若某个功能需要获取某个权限,系统会弹出一个对话框,由用户决定是否将该权限赋予应用。只有得到了用户的许可,该功能才可以被使用。

需要注意的是,赋予权限的对话框并不会自动弹出,而需要由开发者手动调用。若程序调用的某个方法需要用户赋予相应权限,而此时该权限并未被赋予时,那么程序就会抛出异常并崩溃。除此之外,用户还可以在任何时候,通过设置中的应用管理撤销赋予过的权限。

  1. 权限分类

在Android 6.0(M)之后,对权限进行了分类,大致有这三种:

普通权限:
涵盖应用需要访问其沙盒外部数据或资源,但对用户隐私或其他应用操作风险很小的区域。这些权限在应用安装时授予,运行时不再询问用户。例如: 网络访问、WIFI状态、音量设置等。

危险权限:
涵盖应用需要涉及用户隐私信息的数据或资源,或者可能对用户存储的数据或其他应用的操作产生影响的区域。例如: 读取通讯录、读写存储器数据、获取用户位置等。如果应用声明需要这些危险权限,则必须在运行时明确告诉用户,让用户手动授予。

特殊权限:
SYSTEM_ALERT_WINDOW 和 WRITE_SETTINGS 这两个权限比较特殊,不能通过代码申请方式获取,必须得用户打开软件设置页手动打开,才能授权。
  1. 权限列表

加粗权限为基础权限,应用程序中会经常使用到。
权限 描述
ACCESS_CHECKIN_PROPERTIES 允许读取或写入登记check-in数据库属性表的权限
ACCESS_COARSE_LOCATION 允许通过无线网络或移动基站的方式获取用户的经纬度信息
ACCESS_FINE_LOCATION 允许通过GPS接收卫星的定位信息
ACCESS_LOCATION_EXTRA_COMMANDS 允许程序访问额外的定位提供者指令
ACCESS_NETWORK_STATE 允许获取网络信息状态
ACCESS_NOTIFICATION_POLICY 允许访问通知策略的应用程序的标记许可
ACCESS_WIFI_STATE 允许获取当前WiFi接入的状态以及WLAN热点的信息
ACCOUNT_MANAGER 允许程序通过账户验证方式访问账户管理ACCOUNT_MANAGER相关信息
AUTHENTICATE_ACCOUNTS 允许一个应用程序添加语音邮件系统
ANSWER_PHONE_CALLS 允许接听来电
BATTERY_STATS 允许获取电池电量统计信息
BIND_ACCESSIBILITY_SERVICE 请求accessibilityservice服务,以确保只有系统可以绑定到它
BIND_APPWIDGET 允许应用程序告诉AppWidget服务应用程序可以访问AppWidget的数据
BIND_DEVICE_ADMIN 请求系统管理员接收者receiver,只有系统才能使用
BIND_INPUT_METHOD 请求InputMethodService服务,只有系统才能使用
BIND_NFC_SERVICE 由HostApduService或OffHostApduService,必须确保只有系统绑定到它
BIND_NOTIFICATION_LISTENER_SERVICE 必须要求由NotificationListenerService,以确保只有系统可以绑定到它
BIND_PRINT_SERVICE 必须要求由PrintService,以确保只有系统可以绑定到它
BIND_REMOTEVIEWS 必须通过RemoteViewsService,服务来请求,只有系统才能用
BIND_TEXT_SERVICE 必须要求TextService,以确保只有系统可以绑定到它
BIND_VPN_SERVICE 必须要求VpnService,以确保只有系统可以绑定到它
BIND_WALLPAPER 必须要求WallpaperService,以确保只有系统可以绑定到它
BLUETOOTH 允许应用程序连接到蓝牙设备配对
BLUETOOTH_ADMIN 允许应用程序发现和蓝牙设备
BLUETOOTH_PRIVILEGED 允许应用程序对蓝牙设备,不需要用户交互
BODY_SENSORS 允许应用程序访问用户使用的传感器来测量
BROADCAST_PACKAGE_REMOVED 允许应用程序广播通知应用程序包被移除后
BROADCAST_SMS 允许程序当收到短信时触发一个广播
BROADCAST_STICKY 允许程序收到广播后快速收到下一个广播
BROADCAST_WAP_PUSH 允许应用程序播放一个WAP推收到通知
CALL_PHONE 允许程序从非系统拨号器里拨打电话
CALL_PRIVILEGED 允许程序拨打电话,替换系统的拨号器界面
CAMERA 允许程序访问摄像头进行拍照
CAPTURE_AUDIO_OUTPUT 允许应用程序捕获音频输出
CAPTURE_SECURE_VIDEO_OUTPUT 允许应用程序获取安全的视频输出
CAPTURE_VIDEO_OUTPUT 允许一个应用程序来捕获视频输出
CHANGE_COMPONENT_ENABLED_STATE 允许一个应用程序改变组件是否启用状态
CHANGE_CONFIGURATION 允许应用程序修改当前配置
CHANGE_NETWORK_STATE 允许应用程序改变网络连接状态
CHANGE_WIFI_MULTICAST_STATE 允许应用程序进入无线多播模式
CHANGE_WIFI_STATE 允许应用程序改变wifi连接状态
CLEAR_APP_CACHE 允许应用程序清除所有已安装的 应用程序缓存
CLEAR_APP_USER_DATA 允许应用程序清除用户数据
CONTROL_LOCATION_UPDATES 允许程序获得移动网络定位信息改变
DELETE_CACHE_FILES 允许应用程序删除缓存文件
DELETE_PACKAGES 允许应用程序删除应用
DEVICE_POWER 允许低级访问电源管理
DIAGNOSTIC 允许应用程序RW诊断资源
DISABLE_KEYGUARD 允许应用程序禁用键盘锁
DUMP 允许程序获取系统dump信息从系统服务
EXPAND_STATUS_BAR 允许应用程序展开或折叠状态栏
FACTORY_TEST 允许程序运行工厂测试模式
FLASHLIGHT 允许访问的闪光灯
FORCE_BACK 允许应用程序强制操作任何事情
GET_ACCOUNTS 允许访问的帐户的Gmail列表服务
GET_PACKAGE_SIZE 允许一个程序获取任何package占用空间容量
GET_TASKS 允许应用程序获取当前的信息 或最近运行的任务
GET_TOP_ACTIVITY_INFO 允许应用程序获取私人信息
GLOBAL_SEARCH 允许程序允许全局搜索
HARDWARE_TEST 允许访问硬件辅助设备
INJECT_EVENTS 允许访问本程序的底层事件,获取按键、轨迹球的事件流
INSTALL_LOCATION_PROVIDER 允许程序安装定位提供
INSTALL_PACKAGES 允许程序安装应用
INSTALL_SHORTCUT 允许应用程序快捷方式
INTERNAL_SYSTEM_WINDOW 允许程序打开内部窗口,不对第三方应用程序开放此权限
INTERNET 允许程序访问网络连接,可能产生GPRS流量
KILL_BACKGROUND_PROCESSES 允许一个应用程序调用killBackgroundProcesses()方法结束后台进程
LOCATION_HARDWARE 允许一个应用程序中使用定位功能的硬件,不使用第三方应用
MANAGE_ACCOUNTS 允许程序管理AccountManager中的账户列表
MANAGE_APP_TOKENS 管理创建、摧毁、Z轴顺序,仅用于系统
MANAGE_DOCUMENTS 允许程序管理文件的访问
MASTER_CLEAR 允许程序执行软格式化,删除系统配置信息
MEDIA_CONTENT_CONTROL 允许一个应用程序知道什么是播放和控制其内容 ,不能被第三方应用使用
MODIFY_AUDIO_SETTINGS 允许程序修改声音设置信息
MODIFY_PHONE_STATE 允许程序修改电话状态
MOUNT_FORMAT_FILESYSTEMS 允许程序格式化可移动文件系统
MOUNT_UNMOUNT_FILESYSTEMS 允许程序挂载、反挂载外部文件系统
NFC 允许程序执行NFC近距离通讯操作
PERSISTENT_ACTIVITY 允许程序创建一个永久的Activity,该功能标记为将来将被移除
PROCESS_OUTGOING_CALLS 允许程序监视,修改或放弃播出电话
READ_CALENDAR 允许应用程序读取用户的日程信息
READ_CALL_LOG 允许应用程序读取用户的通话记录
READ_CONTACTS 允许应用程序读取用户的联系人信息
READ_EXTERNAL_STORAGE 允许应用程序读取设备外部存储空间的文件
READ_FRAME_BUFFER 允许程序读取帧缓存用于屏幕截图
READ_HISTORY_BOOKMARKS 允许应用程序读取浏览器收藏夹和历史记录
READ_INPUT_STATE 读取当前键的输入状态,仅用于系统
READ_LOGS 允许应用程序读取系统底层日志
READ_PHONE_STATE 允许程序访问电话状态
READ_PROFILE 允许应用程序读取用户的个人资料信息
READ_SMS 允许应用程序读取短信内容
READ_SYNC_SETTINGS 允许应用程序读取同步设置,读取Google在线同步设置
READ_SYNC_STATS 允许程序读取同步状态,获得Google在线同步状态
READ_USER_DICTIONARY 允许应用程序读取用户字典
REBOOT 允许能够重新启动设备
RECEIVE_BOOT_COMPLETED 允许程序开机自动运行
RECEIVE_MMS 允许程序接收彩信
RECEIVE_SMS 允许程序接收短信
RECEIVE_WAP_PUSH 允许程序接收WAP PUSH信息
RECORD_AUDIO 允许程序录制声音通过手机或耳机的麦克
REORDER_TASKS 允许程序重新排序系统Z轴运行中的任务
RESTART_PACKAGES 允许程序结束任务通过restartPackage(String)方法,该方式将在外来放弃
SEND_RESPOND_VIA_MESSAGE 允许用户在来电的时候用你的应用进行即时的短信息回复
SEND_SMS 允许程序发送短信
SET_ACTIVITY_WATCHER 设置Activity观察器一般用于monkey测试
SET_ALARM 允许程序设置闹铃提醒
SET_ALWAYS_FINISH 允许程序设置程序在后台是否总是退出
SET_ANIMATION_SCALE 允许程序设置全局动画缩放
SET_DEBUG_APP 允许程序设置调试程序,一般用于开发
SET_ORIENTATION 设置屏幕方向为横屏或标准方式显示,不用于普通应用
SET_POINTER_SPEED 系统权限,不能被第三方应用获取
SET_PREFERRED_APPLICATIONS 允许程序设置应用的参数
SET_PROCESS_LIMIT 允许程序设置最大的进程数量的限制
SET_TIME 允许程序设置系统时间
SET_TIME_ZONE 允许程序设置系统时区
SET_WALLPAPER 允许程序设置桌面壁纸
SET_WALLPAPER_HINTS 允许程序设置壁纸建议
SIGNAL_PERSISTENT_PROCESSES 允许程序发送一个永久的进程信号
STATUS_BAR 允许程序打开、关闭、禁用状态栏
SUBSCRIBED_FEEDS_READ 允许应用程序访问已订阅的数据库
SUBSCRIBED_FEEDS_WRITE 允许应用程序写入或修改订阅内容的数据库
SYSTEM_ALERT_WINDOW 允许程序显示系统窗口
TRANSMIT_IR 允许使用设备的红外发射器,如果可用
UNINSTALL_SHORTCUT 删除快捷方式
UPDATE_DEVICE_STATS 允许程序更新设备状态
USE_CREDENTIALS 允许应用程序请求验证AccountManager
USE_SIP 允许程序使用SIP视频服务
VIBRATE 允许程序振动
WAKE_LOCK 允许程序在手机屏幕关闭后后台进程仍然运行
WRITE_APN_SETTINGS 允许程序写入网络GPRS接入点设置
WRITE_CALENDAR 允许程序写入日程,但不可读取
WRITE_CALL_LOG 允许程序写入联系人数据,但不可读取
WRITE_CONTACTS 允许程序写入联系人,但不可读取
WRITE_EXTERNAL_STORAGE 允许程序写入外部存储
WRITE_GSERVICES 允许应用程序修改谷歌地图服务
WRITE_HISTORY_BOOKMARKS 允许应用程序写入浏览器历史记录或收藏夹,但不可读取
WRITE_PROFILE 允许应用程序编写用户的个人人资料信息,但不可读取
WRITE_SECURE_SETTINGS 允许应用程序读取或写入安全系统设置
WRITE_SETTINGS 允许应用程序读取或写入系统设置
WRITE_SMS 允许应用程序编写短信
WRITE_SYNC_SETTINGS 允许应用程序编写Google在线同步设置
WRITE_USER_DICTIONARY 允许应用程序编写用户字典

普通权限
1)系统自动授权,只需要在清单文件中添加权限即可。
ACCESS_LOCATION_EXTRA_COMMANDS
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
BLUETOOTH
BLUETOOTH_ADMIN
BROADCAST_STICKY
CHANGE_NETWORK_STATE
CHANGE_WIFI_MULTICAST_STATE
CHANGE_WIFI_STATE
DISABLE_KEYGUARD
EXPAND_STATUS_BAR
GET_PACKAGE_SIZE
INSTALL_SHORTCUT
INTERNET
KILL_BACKGROUND_PROCESSES
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_INSTALL_PACKAGES
SET_ALARM
SET_TIME_ZONE
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
UNINSTALL_SHORTCUT
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
2)申请权限
... ...
危险权限
1)需要动态申请,同一组的任何一个权限被授权了,其他权限也自动被授权。
CALENDAR(日历)
  READ_CALENDAR
  WRITE_CALENDAR
CAMERA(相机)
  CAMERA
CONTACTS(联系人)
  READ_CONTACTS
  WRITE_CONTACTS
  GET_ACCOUNTS
LOCATION(位置)
  ACCESS_FINE_LOCATION
  ACCESS_COARSE_LOCATION
MICROPHONE(麦克风)
  RECORD_AUDIO
PHONE(手机)
  READ_PHONE_STATE
  READ_PHONE_NUMBERS
  CALL_PHONE
  READ_CALL_LOG
  WRITE_CALL_LOG
  ADD_VOICEMAIL
  USE_SIP
  PROCESS_OUTGOING_CALLS
  PROCESS_OUTGOING_CALLS
SENSORS(传感器)
  BODY_SENSORS
SMS(短信)
  SEND_SMS
  RECEIVE_SMS
  READ_SMS
  RECEIVE_WAP_PUSH
  RECEIVE_MMS
STORAGE(存储卡)
  READ_EXTERNAL_STORAGE
  WRITE_EXTERNAL_STORAGE
2)申请权限

Android 6.0之前:


//电话
//拍照
//sd卡

Android 6.0之后:
Android 6.0动态权限申请

Android 6.0 (API 23) 之前应用的权限在安装时全部授予,运行时应用不再需要询问用户。在 Android 6.0 或更高版本对权限进行了分类,对某些涉及到用户隐私的权限可在运行时根据用户的需要动态授予。这样就不需要在安装时被强迫同意某些权限。

应用的targetSDKVersion < 23时,权限检查仍是早期的形式(仅在安装时赋予权限,使用时将不被提醒);
应用的targetSDKVersion ≥ 23时,则将使用新的运行时权限规则。

新的权限机制更好的保护了用户的隐私,Google将权限分为三类:

Normal Permissions,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动、访问网络等;
Dangerous Permission,一般是涉及到用户隐私的,需要用户进行授权,比如读取sdcard、访问通讯录等;
Special Permissions,SYSTEM_ALERT_WINDOW 和 WRITE_SETTINGS 这两个权限比较特殊,不能通过代码申请方式获取,必须得用户打开软件设置页手动打开,才能授权。
  1. 权限组
    权限组 权限
    CALENDA READ_CALENDAR
    WRITE_CALENDAR
    CAMERA CAMERA
    CONTACTS READ_CONTACTS
    WRITE_CONTACTS
    GET_ACCOUNTS
    LOCATION ACCESS_FINE_LOCATION
    ACCESS_COARSE_LOCATION
    MICROPHONE RECORD_AUDIO
    PHONE READ_PHONE_STATE
    READ_PHONE_NUMBERS
    CALL_PHONE
    ANSWER_PHONE_CALLS (must request at runtime)
    READ_CALL_LOG
    WRITE_CALL_LOG
    ADD_VOICEMAIL
    USE_SIP
    PROCESS_OUTGOING_CALLS
    ANSWER_PHONE_CALLS
    SENSORS BODY_SENSORS
    SMS SEND_SMS
    RECEIVE_SMS
    READ_SMS
    RECEIVE_WAP_PUSH
    RECEIVE_MMS
    STORAGE READ_EXTERNAL_STORAGE
    WRITE_EXTERNAL_STORAGE
  2. 权限申请

1)声明权限
在 AndroidManifest.xml 中声明所需权限:


//电话
//拍照
//sd卡

2)检查权限
方法:
// 检查权限
ContextCompat.checkSelfPermission(Context context, String permission)

返回值PackageManager常量有两种情况:PackageManager.PERMISSION_GRANTED(有权限)、PackageManager.PERMISSION_DENIED(无权限)

示例:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int permission = ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.CALL_PHONE);
if (permission == PackageManager.PERMISSION_GRANTED) {
//表示有权限
} else {
//表示无权限
}
}

当应用需要用到危险权限时,在执行权限相关代码前,使用该方法判断是否拥有指定的权限。有权限,则继续执行设计需要权限的代码;无权限,则向用户请求授予权限。

3)解释权限
方法:
// 解释权限
ActivityCompat.shouldShowRequestPermissionRationale(Activity activity, String permission)

示例:
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)) {
//拒绝权限
} else {
//申请对应的权限
}

判断是否有必要向用户解释为什么要这项权限。如果应用第一次请求过此权限,但是被用户拒绝了,则之后调用该方法将返回 true,此时就有必要向用户详细说明需要此权限的原因。如果用户勾选了权限请求对话框的 “不再询问”,则此方法返回 false。如果设备规范禁止应用拥有该权限,此方法也返回 false。

4)请求权限
方法:
// 请求权限
ActivityCompat.requestPermissions(Activity activity, String[] permissions, int requestCode)

示例:
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, 100);

当检测到应用没有指定的权限时,调用此方法向用户请求权限。调用此方法将弹出权限请求对话框询问用户 “允许” 或 “拒绝” 指定的权限。

5)处理结果
方法:
//处理权限请求结果
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
// …
}

示例:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 100) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//授权
} else {
//拒绝
}
}
}

requestCode请求权限时传入的请求码,用于区别是哪一次请求的;
permissions所请求的所有权限的数组;
grantResults权限授予结果,和 permissions 数组参数中的权限一一对应,元素值为两种情况:
授予: PackageManager.PERMISSION_GRANTED,拒绝:PackageManager.PERMISSION_DENIED
3. 代码案例
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CODE = 100;
private Button btn_record;
private String[] permit = new String[] {
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CALL_PHONE
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_record = (Button) findViewById(R.id.btn_record);
btn_record.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
List mPermissionList = new ArrayList<>();
for(String permission : permit) {
if(ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {//权限判断
permissionLists.add(permission);
}
}
if(!permissionLists.isEmpty()) {
ActivityCompat.requestPermissions(this, permissionLists.toArray(new String[permissionLists.size()]), REQUEST_CODE);
} else { //表示全都授权了
callPhone();
}
} else {
callPhone();
}
}
});
}

@Override
public void onRequestPermissionsResult(int requestCode,  String[] permissions,  int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_CODE) {
        if(grantResults.length > 0) {
            //存放没授权的权限
            List<String> deniedPermissions = new ArrayList<>();
            for(int i = 0; i < grantResults.length; i++) {
                int grantResult = grantResults[i];
                String permission = permissions[i];
                if(grantResult != PackageManager.PERMISSION_GRANTED) {
                    deniedPermissions.add(permission);
                }
            }
            if(deniedPermissions.isEmpty()) {
                //都授权了
                callPhone();
            } else { //没有授权                 
                Toast.makeText(MainActivity.this, "被拒绝的权限:" + deniedPermissions.toString(), Toast.LENGTH_SHORT).show();
            }
        }
    }
}

public void callPhone() {
    Intent intent = new Intent(Intent.ACTION_CALL);
    Uri data = Uri.parse("tel:" + "10086");
    intent.setData(data);
    startActivity(intent);
}

}

特殊权限

有一些权限与普通权限和危险权限都不同。SYSTEM_ALERT_WINDOW 和 WRITE_SETTINGS 特别敏感,因此大多数应用不应该使用它们。如果某应用需要其中一种权限,必须在清单中声明该权限,并且发送请求用户授权的 intent。系统将向用户显示详细管理屏幕,以响应该 intent。

呈上官方文档 传送门

标签:READ,程序,用户,应用程序,注意事项,允许,Android,权限
来源: https://blog.csdn.net/qq_43317486/article/details/114099307

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有