Android 6.0新特性之Runtime Permission
来源:互联网 发布:苹果系统mac系统下载 编辑:程序博客网 时间:2024/05/16 12:01
Runtime Permissions
在Android 6.0中谷歌摒弃了之前的install time permissions model
取而代之的是runtime permissions model
。先来说说install time permissions model
,这个大家不陌生,就是当Android App安装的时候会向用户展示一坨权限,如果此时用户选择安装,则表示用户同意将这些权限赋予App,如果用户不同意那么这个App就会取消安装。runtime permissions model
就牛逼了,在App安装的时候同样会向用户展示所需要的权限,并且在用户选择安装App的时候并不表示用户将这些权限赋予了App,而是需要App在运行阶段主动去申请这些权限。这样做的好处显而易见,App对权限的申请对于用户来说变得更加透明,而且用户对App权限的控制也更加灵活。
权限的分类
Android将系统权限分成了四个保护等级normal
,dangerous
,signature
,signatureOrSystem
,其中最常见的是normal permission
和dangerous permission
两类。
normal permission涵盖的一系列权限的共同点是:App需要访问App运行沙盒以外的数据或资源,但是这些资源对用户的隐私或其他App的危险性较小,下面列举一下这些权限:
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
FLASHLIGHT
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
以上这些就是Android 6.0中所有的normal permissions
了。
dangerous permissions
dangerous permissions 涵盖的一系列权限的共同点是:这些权限会读写用户的隐私信息,也可能会读写用户存储的数据或影响其他App的正常运行。下面例举出这些权限:
WRITE_CALENDAR
CAMERACAMERACONTACTSREAD_CONTACTSWRITE_CONTACTS
GET_ACCOUNTS
LOCATIONACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION
MICROPHONERECORD_AUDIOPHONEREAD_PHONE_STATECALL_PHONE,READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
SENSORSBODY_SENSORSSMSSEND_SMSRECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
STORAGEREAD_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE
以上这些权限就是Android6.0中所有的dangerous permissions
。
dangerous permissions
,normal permissions
还是会在App安装期间被默认赋予。实战
1、请求3个 dangerous permission,一定要在AndroidManifest.xml上配置,不然只在运行时请求会授权失败
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
2、java code,封装好的一些方法
//---------------------- permission request final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 163; private void startAppWrapper() { List<String> permissionsNeeded = new ArrayList<String>(); final List<String> permissionsList = new ArrayList<String>(); //只需要在这添加需要的dangerous permissions if (!addPermission(permissionsList, Manifest.permission.WRITE_EXTERNAL_STORAGE)) permissionsNeeded.add("Storage"); if (!addPermission(permissionsList, Manifest.permission.READ_PHONE_STATE)) permissionsNeeded.add("Read Phone State"); if (!addPermission(permissionsList, Manifest.permission.GET_ACCOUNTS)) permissionsNeeded.add("Account Info"); if (permissionsList.size() > 0) { if (permissionsNeeded.size() > 0) { // Need Rationale String message = "You need to grant access to " + permissionsNeeded.get(0); for (int i = 1; i < permissionsNeeded.size(); i++) message = message + ", " + permissionsNeeded.get(i); showMessageOKCancel(message, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCompat.requestPermissions(Logo.this, permissionsList.toArray(new String[permissionsList.size()]), REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); } }); return; } ActivityCompat.requestPermissions(Logo.this, permissionsList.toArray(new String[permissionsList.size()]), REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); return; } newStartApp(); } private boolean addPermission(List<String> permissionsList, String permission) { if (ContextCompat.checkSelfPermission(Logo.this, permission) != PackageManager.PERMISSION_GRANTED) { permissionsList.add(permission); // Check for Rationale Option if (!ActivityCompat.shouldShowRequestPermissionRationale(Logo.this, permission)) return false; } return true; } private void showMessage(String message, DialogInterface.OnClickListener okListener, boolean isCancel) { AlertDialog.Builder builder = new AlertDialog.Builder(Logo.this); if (isCancel) { builder.setNegativeButton("Cancel", null); } builder.setMessage(message) .setPositiveButton("OK", okListener) .create() .show(); } private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) { showMessage(message, okListener, true); } private void showMessageOK(String message, DialogInterface.OnClickListener okListener) { showMessage(message, okListener, false); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: { for (int i = 0; i < grantResults.length; i++) { Log.e("--- asd", "--- asd: permission:"+permissions[i]+", result:"+ grantResults[i]); } boolean isAllAllow = true; String notGranted = ""; for (int i = 0; i < permissions.length; i++) { if (grantResults[i] == PackageManager.PERMISSION_DENIED) { isAllAllow = false; notGranted = permissions[i]; break; } } if (isAllAllow) { newStartApp(); } else { // Permission Denied showMessageOK("Grant the permissions for the game please.\n" + notGranted, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }); } } break; default: break; } }
(ps: newStartApp() 方法是跳转到游戏的Acitivity的方法,先在请求玩所有游戏中需要用到的权限,全部授权成功后在跳转到游戏的Activity)
//---------------------- permission request final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 163; private void startAppWrapper() { List<String> permissionsNeeded = new ArrayList<String>(); final List<String> permissionsList = new ArrayList<String>(); //只需要在这添加需要的dangerous permissions if (!addPermission(permissionsList, Manifest.permission.WRITE_EXTERNAL_STORAGE)) permissionsNeeded.add("Storage"); if (!addPermission(permissionsList, Manifest.permission.READ_PHONE_STATE)) permissionsNeeded.add("Read Phone State"); if (!addPermission(permissionsList, Manifest.permission.GET_ACCOUNTS)) permissionsNeeded.add("Account Info"); if (permissionsList.size() > 0) { if (permissionsNeeded.size() > 0) { // Need Rationale String message = "You need to grant access to " + permissionsNeeded.get(0); for (int i = 1; i < permissionsNeeded.size(); i++) message = message + ", " + permissionsNeeded.get(i); showMessageOKCancel(message, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCompat.requestPermissions(Logo.this, permissionsList.toArray(new String[permissionsList.size()]), REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); } }); return; } ActivityCompat.requestPermissions(Logo.this, permissionsList.toArray(new String[permissionsList.size()]), REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); return; } newStartApp(); } private boolean addPermission(List<String> permissionsList, String permission) { if (ContextCompat.checkSelfPermission(Logo.this, permission) != PackageManager.PERMISSION_GRANTED) { permissionsList.add(permission); // Check for Rationale Option if (!ActivityCompat.shouldShowRequestPermissionRationale(Logo.this, permission)) return false; } return true; } private void showMessage(String message, DialogInterface.OnClickListener okListener, boolean isCancel) { AlertDialog.Builder builder = new AlertDialog.Builder(Logo.this); if (isCancel) { builder.setNegativeButton("Cancel", null); } builder.setMessage(message) .setPositiveButton("OK", okListener) .create() .show(); } private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) { showMessage(message, okListener, true); } private void showMessageOK(String message, DialogInterface.OnClickListener okListener) { showMessage(message, okListener, false); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: { for (int i = 0; i < grantResults.length; i++) { Log.e("--- asd", "--- asd: permission:"+permissions[i]+", result:"+ grantResults[i]); } boolean isAllAllow = true; String notGranted = ""; for (int i = 0; i < permissions.length; i++) { if (grantResults[i] == PackageManager.PERMISSION_DENIED) { isAllAllow = false; notGranted = permissions[i]; break; } } if (isAllAllow) { newStartApp(); } else { // Permission Denied showMessageOK("Grant the permissions for the game please.\n" + notGranted, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }); } } break; default: break; } }
//进入app的第一个Activity的OnCreate方法 @Override public void onCreate(Bundle savedInstanceState) { Cocos2dxHelper.setContext(this); super.onCreate(savedInstanceState); setContentView(R.layout.q2_logo); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { newStartApp(); //如果api小与23,不需要运行请求权限 return; } startAppWrapper(); }
运行
- Android 6.0新特性之Runtime Permission
- Android 6.0 新特性之 RunTime Permissions
- 浅谈Android 6.0之Runtime Permission
- Android 6.0 Runtime Permission 机制
- Android 6.0RunTime Permission完美解决方案
- Android 6.0RunTime Permission完美解决方案
- Android M Runtime Permission
- Android Runtime Permission
- Android runtime permission
- Android 6.0新特性之Doze模式
- Android 6.0新特性之 权限管理
- Android 6.0新特性之Doze模式
- Android 6.0新特性之Doze模式
- Android M Runtime Permission 介绍
- Android M Runtime Permission 介绍
- Android M Runtime Permission 介绍
- Android之4.0新特性
- Android新特性之二
- C++学习重点分析
- Android之远程服务器存储
- 在 C# 异步方法中使用 out/ref 参数机制
- 【郑轻】[1900]985的“树”难题
- HDU 1722 Cake
- Android 6.0新特性之Runtime Permission
- ZeroMQ(ZMQ)函数接口英汉直译
- Android——ListView与适配器
- java常用IO流集合用法模板
- 数据结构实验之串三:KMP应用
- 杭电-1875 畅通工程再续(Kruscal)
- poj 2485 Highways ( prim )
- C++ Primer读书笔记:6.3~6.7
- assests文件下读取csv文件和图片