Andrid6.0权限机制介绍及处理

来源:互联网 发布:全球网络电视 编辑:程序博客网 时间:2024/06/09 14:08

在Android M添加的权限机制中,Google将权限分为两类:

  • Normal Permissions(普通权限):不涉及用户隐私,不需要用户进行授权,比如访问网络等
android.permission.ACCESS_LOCATION_EXTRA_COMMANDSandroid.permission.ACCESS_NETWORK_STATEandroid.permission.ACCESS_NOTIFICATION_POLICYandroid.permission.ACCESS_WIFI_STATEandroid.permission.ACCESS_WIMAX_STATEandroid.permission.BLUETOOTHandroid.permission.BLUETOOTH_ADMINandroid.permission.BROADCAST_STICKYandroid.permission.CHANGE_NETWORK_STATEandroid.permission.CHANGE_WIFI_MULTICAST_STATEandroid.permission.CHANGE_WIFI_STATEandroid.permission.CHANGE_WIMAX_STATEandroid.permission.DISABLE_KEYGUARDandroid.permission.EXPAND_STATUS_BARandroid.permission.FLASHLIGHTandroid.permission.GET_ACCOUNTSandroid.permission.GET_PACKAGE_SIZEandroid.permission.INTERNETandroid.permission.KILL_BACKGROUND_PROCESSESandroid.permission.MODIFY_AUDIO_SETTINGSandroid.permission.NFCandroid.permission.READ_SYNC_SETTINGSandroid.permission.READ_SYNC_STATSandroid.permission.RECEIVE_BOOT_COMPLETEDandroid.permission.REORDER_TASKSandroid.permission.REQUEST_INSTALL_PACKAGESandroid.permission.SET_TIME_ZONEandroid.permission.SET_WALLPAPERandroid.permission.SET_WALLPAPER_HINTSandroid.permission.SUBSCRIBED_FEEDS_READandroid.permission.TRANSMIT_IRandroid.permission.USE_FINGERPRINTandroid.permission.VIBRATEandroid.permission.WAKE_LOCKandroid.permission.WRITE_SYNC_SETTINGScom.android.alarm.permission.SET_ALARMcom.android.launcher.permission.INSTALL_SHORTCUTcom.android.launcher.permission.UNINSTALL_SHORTCUT
  • Dangerous Permission(危险权限):涉及到用户隐私,需要用户进行授权,比如相机访问、读取SD卡等
group:android.permission-group.CONTACTS  permission:android.permission.WRITE_CONTACTS  permission:android.permission.GET_ACCOUNTS      permission:android.permission.READ_CONTACTSgroup: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_VOICEMAILgroup:android.permission-group.CALENDAR  permission:android.permission.READ_CALENDAR  permission:android.permission.WRITE_CALENDARgroup:android.permission-group.CAMERA  permission:android.permission.CAMERAgroup:android.permission-group.SENSORS  permission:android.permission.BODY_SENSORSgroup:android.permission-group.LOCATION  permission:android.permission.ACCESS_FINE_LOCATION  permission:android.permission.ACCESS_COARSE_LOCATIONgroup:android.permission-group.STORAGE  permission:android.permission.READ_EXTERNAL_STORAGE  permission:android.permission.WRITE_EXTERNAL_STORAGEgroup:android.permission-group.MICROPHONE  permission:android.permission.RECORD_AUDIOgroup: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

运行时权限只适合APP运行在Android 6.x以上的机器,对于危险权限Google官方也对其进行了分组,只要一组中的某一权限被授权,同组的权限也同样会被授权。

操作步骤

新的权限机制操作步骤如下

  • 在Androidmanifest.xml文件声明相关权限

  • 通过ContextCompat.checkSelfPermission方法检查某项权限被授予情况

  • 通过ActivityCompat.shouldShowRequestPermissionRationale方法检查权限是否被永久拒绝需要向用户说明

  • 通过Activity.requestPermissions申请授权

  • 处理Activity.onRequestPermissionsResult权限回调

Google给出的Demo实现方式

/** * Check that all given permissions have been granted by verifying that each entry in the * given array is of the value {@link PackageManager#PERMISSION_GRANTED}. * * @see Activity#onRequestPermissionsResult(int, String[], int[]) */public static boolean verifyPermissions(int[] grantResults) {    // At least one result must be checked.    if(grantResults.length < 1){        return false;    }    // Verify that each required permission has been granted, otherwise return false.    for (int result : grantResults) {        if (result != PackageManager.PERMISSION_GRANTED) {            return false;        }    }    return true;}public void showContacts(View v) {    Log.i(TAG, "Show contacts button pressed. Checking permissions.");    // 验证所有联系人权限是否已经获得    if (ActivityCompat.checkSelfPermission(this,             Manifest.permission.READ_CONTACTS)            != PackageManager.PERMISSION_GRANTED            || ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_CONTACTS)            != PackageManager.PERMISSION_GRANTED) {        // 通讯录权限未获得        Log.i(TAG, "Contact permissions has NOT been granted. Requesting permissions.");        requestContactsPermissions();    } else {        // 通讯录权限已获得,显示通讯录Fragment        Log.i(TAG,                "Contact permissions have already been granted. Displaying contact details.");        showContactDetails();    }}/** * 请求通讯录权限 * 如果权限已经被拒绝了,那么会弹出一个弹框提醒用户去授予权限,否则会直接请求 */private void requestContactsPermissions() {    // BEGIN_INCLUDE(contacts_permission_request)    if (ActivityCompat.shouldShowRequestPermissionRationale(this,            Manifest.permission.READ_CONTACTS)            || ActivityCompat.shouldShowRequestPermissionRationale(this,            Manifest.permission.WRITE_CONTACTS)) {        // 如果没有授予许可,请向用户提供额外的理由来让用户理解请求此权限的原因        // 例如,如果以前已经拒绝了权限请求        Log.i(TAG,"Displaying contacts permission rationale to provide additional context.");        // 显示一个带有说明和按钮的SnackBar来触发请求。        Snackbar.make(mLayout, R.string.permission_contacts_rationale,        Snackbar.LENGTH_INDEFINITE)                .setAction(R.string.ok, new View.OnClickListener() {                    @Override                    public void onClick(View view) {                        ActivityCompat.requestPermissions(MainActivity.this, PERMISSIONS_CONTACT,                        REQUEST_CONTACTS);                    }                })                .show();    } else {        // 通讯录权限尚未授予,直接请求        ActivityCompat.requestPermissions(this, PERMISSIONS_CONTACT,        REQUEST_CONTACTS);    }    // END_INCLUDE(contacts_permission_request)}//权限处理结果的回调@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull      String[] permissions,@NonNull int[] grantResults) {    if (requestCode == REQUEST_CONTACTS) {        Log.i(TAG, "Received response for contact permissions request.");        // 对请求的所有联系人权限再核实一遍        if (PermissionUtil.verifyPermissions(grantResults)) {            // 所有权限都已经获得,显示联系人页面            Snackbar.make(mLayout, R.string.permision_available_contacts,                    Snackbar.LENGTH_SHORT)                    .show();        } else {            Log.i(TAG, "Contacts permissions were NOT granted.");            Snackbar.make(mLayout, R.string.permissions_not_granted,                    Snackbar.LENGTH_SHORT)                    .show();        }    } else {        super.onRequestPermissionsResult(requestCode, permissions,grantResults);    }}

关键的几个方法

1.检查是否拥有指定权限

android.support.v4.content.ContextCompat.java

/*** Determine whether <em>you</em> have been granted a particular permission.** @param permission The name of the permission being checked.** @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if you have the* permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED} if not.** @see android.content.pm.PackageManager#checkPermission(String, String)*/public static int checkSelfPermission(@NonNull Context context, @NonNull String permission) {    if (permission == null) {        throw new IllegalArgumentException("permission is null");    }    return context.checkPermission(permission, android.os.Process.myPid(), Process.myUid());}

2.判断是否彻底拒绝而了某项权限而需要对用户进行说明

android.support.v4.app.ActivityCompat.java

/** * Gets whether you should show UI with rationale for requesting a permission. * You should do this only if you do not have the permission and the context in * which the permission is requested does not clearly communicate to the user * what would be the benefit from granting this permission. * <p> * For example, if you write a camera app, requesting the camera permission * would be expected by the user and no rationale for why it is requested is * needed. If however, the app needs location for tagging photos then a non-tech * savvy user may wonder how location is related to taking photos. In this case * you may choose to show UI with rationale of requesting this permission. * </p> * * @param activity The target activity. * @param permission A permission your app wants to request. * @return Whether you can show permission rationale UI. * * @see #checkSelfPermission(android.content.Context, String) * @see #requestPermissions(android.app.Activity, String[], int) */public static boolean shouldShowRequestPermissionRationale(@NonNull Activity activity,        @NonNull String permission) {    if (Build.VERSION.SDK_INT >= 23) {        return ActivityCompatApi23.shouldShowRequestPermissionRationale(activity, permission);    }    return false;}

3.发出权限请求

android.app.Activity

/** * Requests permissions to be granted to this application. These permissions * must be requested in your manifest, they should not be granted to your app, * and they should have protection level {@link android.content.pm.PermissionInfo * #PROTECTION_DANGEROUS dangerous}, regardless whether they are declared by * the platform or a third-party app. * <p> * Normal permissions {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL} * are granted at install time if requested in the manifest. Signature permissions * {@link android.content.pm.PermissionInfo#PROTECTION_SIGNATURE} are granted at * install time if requested in the manifest and the signature of your app matches * the signature of the app declaring the permissions. * </p> * <p> * If your app does not have the requested permissions the user will be presented * with UI for accepting them. After the user has accepted or rejected the * requested permissions you will receive a callback on {@link * #onRequestPermissionsResult(int, String[], int[])} reporting whether the * permissions were granted or not. * </p> * <p> * Note that requesting a permission does not guarantee it will be granted and * your app should be able to run without having this permission. * </p> * <p> * This method may start an activity allowing the user to choose which permissions * to grant and which to reject. Hence, you should be prepared that your activity * may be paused and resumed. Further, granting some permissions may require * a restart of you application. In such a case, the system will recreate the * activity stack before delivering the result to {@link * #onRequestPermissionsResult(int, String[], int[])}. * </p> * <p> * When checking whether you have a permission you should use {@link * #checkSelfPermission(String)}. * </p> * <p> * Calling this API for permissions already granted to your app would show UI * to the user to decide whether the app can still hold these permissions. This * can be useful if the way your app uses data guarded by the permissions * changes significantly. * </p> * <p> * You cannot request a permission if your activity sets {@link * android.R.styleable#AndroidManifestActivity_noHistory noHistory} to * <code>true</code> because in this case the activity would not receive * result callbacks including {@link #onRequestPermissionsResult(int, String[], int[])}. * </p> * <p> * The <a href="http://developer.android.com/samples/RuntimePermissions/index.html"> * RuntimePermissions</a> sample app demonstrates how to use this method to * request permissions at run time. * </p> * * @param permissions The requested permissions. Must me non-null and not empty. * @param requestCode Application specific request code to match with a result *    reported to {@link #onRequestPermissionsResult(int, String[], int[])}. *    Should be >= 0. * * @see #onRequestPermissionsResult(int, String[], int[]) * @see #checkSelfPermission(String) * @see #shouldShowRequestPermissionRationale(String) */public final void requestPermissions(@NonNull String[] permissions, int requestCode) {    if (mHasCurrentPermissionsRequest) {        Log.w(TAG, "Can reqeust only one set of permissions at a time");        // Dispatch the callback with empty arrays which means a cancellation.        onRequestPermissionsResult(requestCode, new String[0], new int[0]);        return;    }    Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);    startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);    mHasCurrentPermissionsRequest = true;}

4.在Activity中接受用户处理结果回调

android.app.Activity

/** * Callback for the result from requesting permissions. This method * is invoked for every call on {@link #requestPermissions(String[], int)}. * <p> * <strong>Note:</strong> It is possible that the permissions request interaction * with the user is interrupted. In this case you will receive empty permissions * and results arrays which should be treated as a cancellation. * </p> * * @param requestCode The request code passed in {@link #requestPermissions(String[], int)}. * @param permissions The requested permissions. Never null. * @param grantResults The grant results for the corresponding permissions *     which is either {@link android.content.pm.PackageManager#PERMISSION_GRANTED} *     or {@link android.content.pm.PackageManager#PERMISSION_DENIED}. Never null. * * @see #requestPermissions(String[], int) */public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,        @NonNull int[] grantResults) {    /* callback - no nothing */}

为了便于使用可以在此基础上进行封装,可以参考下面这篇文章中的封装方式
http://www.jianshu.com/p/4a60b064a0ab

0 0
原创粉丝点击