Android 6.0及更高版本Android Runtime Permission(一)

来源:互联网 发布:软件自动升级原理 编辑:程序博客网 时间:2024/06/07 15:14

Android 6.0(Marshmallow) API Level: 23
Android 7.0(Nougat) API Level: 24
虽然Android一直处于持续更新中,但是Android 6.0版本中的一些更新有可能会影响到所有的应用,例如新的Runtime Permission.
自从Android应用程序在安装的时候会将所有的权限进行设置以来,Android的权限系统一直都是最大的一个安全问题。因为一旦程序安装完成,应用就能够访问所有已经被授予的权限而且不通过用户的再次确认。
在Android 6.0 Marshmallow中,整个权限系统被重新设计,所有的应用程序将不会在安装的时候授予任何权限,取而代之的是,应用程序在每次使用相应权限的时候需要询问用户进行授权。
这里写图片描述
注意:在这里,权限请求对话框并不会自动的显示,而是需要开发者进行人为的调用。在开发人员尝试调用一些需要用户尚未授予权限的函数的情况下,函数会突然抛出一个异常,这将导致应用程序崩溃。这里写图片描述
除此之外,用户可以在任何时候通过程序设置收回权限。
这里写图片描述
因此,作为一个开发这,程序的逻辑已经开始改变,你不能只是调用一个函数来做这样的工作,但你必须检查每一个功能的权限,否则你的应用程序将只是简单地崩溃!因此,我门必须对Android6.0及更高版本的SDK做适配。
对于那些已经安装的程序,在操作系统升级到6.0及以上时,将会发生什么呢?
如果应用程序的targetSdkVersion被设置成小于23(即Android6.0),它会假设应用程序并没有针对6.0进行测试,因此,将会转向旧的处理方式:用户不得不接受每一个权限在安装的时候都被授予。因此,以前版本的应用程序依然能正常的工作。
但是,需要注意的是:随用Android6.0将会对用户进行警告,但是,用户依然能在任何时候收回任何应用程序使用的权限。
这里写图片描述
如果这种老版本的应用程序被收回了权限,那么所在的函数没有任何异常将被抛出。相反,它只是简单地什么都不做。对于返回值的函数,它将返回零或0取决于情况。因此,程序一半并不会直接崩溃。但是如果程序没有获取到相应的返回值,程序依然会崩溃。
警告:如果在Android Studio中做开发的话,targetSdkVersion将自动设置为最新版本,23或者更高。如果你还没有准备好让你的应用程序完全支持运行时的允许,我建议你设置targetSdkVersion 22以下。
自动授权:
这里有一些权限是自动在安装的时候被授予的,并且永远不会被收回,如下:

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

使你的程序支持新的Runtime Permission
1.首先进行编译版本的设置:设置compileSdkVersion和targetSdkVersion为23

android {    compileSdkVersion 24    buildToolsVersion "23.0.3"    defaultConfig {        applicationId "XXXX"        minSdkVersion 17        targetSdkVersion 24        versionCode 1        versionName "1.0"    }    buildTypes {        ......    }}

2.在这个例子中将会使用到以下方法,对联系人应用程序进行添加新的人员。

    private void insertDummyContact() {        // Two operations are needed to insert a new contact        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();        // 实现这些代码要求WRITE_CONTRACTS权限        // First, set up a new raw contact.        ContentProviderOperation.Builder op = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null);        operations.add(op.build());        // Next, set the name for the contact.        op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)                .withValue(ContactsContract.Data.MIMETYPE,                        ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)                .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,                        "__DUMMY CONTACT from runtime permissions sample");        operations.add(op.build());        //  Apply the operations        ContentResolver resolver = getContentResolver();        try {            resolver.applyBatch(ContactsContract.AUTHORITY, operations);        } catch (RemoteException e) {            Log.d(TAG, "Could not add a new contact: " + e.getMessage());        } catch (OperationApplicationException e) {            Log.d(TAG, "Could not add a new contact: " + e.getMessage());        }    }

上面的代码请求WRITE_CONTACT权限,如果没有权限进行调用时,程序将会直接崩溃。
3.在AndroidManifest.xml中添加相应的权限声明

<uses-permission android:name="android.permission.WRITE_CONTACTS"/>

4.在这一步,我门必须创建一个函数去检查权限是否被授予
权限被分组成为Permission Group,如下表所示:
这里写图片描述
(原文:If any permission in a Permission Group is granted. Another permission in the same group will be automatically granted as well. In this case, once WRITE_CONTACTS is granted, application will also grant READ_CONTACTS and GET_ACCOUNTS.)(翻译原文:如果获得Permission Group的权限,则分组中所有权限都会获取到。
WRITE_CONTACTS权限被授予以后,应用将会获得READ_CONTACTS和GET_ACCOUNTS的权限。)
5.使用Activity的checkSelfPermission和requestPermissions方法来进行权限的检查以及权限的请求,这些方法都是在API Level 23中添加的,即Android M(6.0)版本以上。

    private void insertDummyContactWrapper() {        // 1。判断是否已经拥有AndroidManifest.xml中声明的权限        int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.WRITE_CONTACTS);        if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {            // 如果没有权限,则通过requestPermissions来调用权限请求对话框            requestPermissions(new String[] {Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_ASK_PERMISSIONS);            return;        }        // 2。如果有的话则直接执行insertDummyContact        insertDummyContact();    }

这里写图片描述
6.无论用户选择拒绝或者允许,Activity的onRequestPermissionsResult方法都会被调用。

    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        switch (requestCode) {            case REQUEST_CODE_ASK_PERMISSIONS:                // 通过这个requestCode来判断是那个函数请求的权限                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {                    // 权限被允许时                    insertDummyContact();                }                break;            default:                super.onRequestPermissionsResult(requestCode, permissions, grantResults);        }    }

这就是Android6.0及更高版本的Runtime Permission权限的申请和使用的过程。

这篇文章是在我遇到Android6.0权限申请时遇到问题时搜到的文章,文章写的很棒,由于是英文的。。。。。
然后就自己翻译了一下,如有不对,大家勿喷,请去看原版,
原版地址如下:
https://inthecheesefactory.com/blog/things-you-need-to-know-about-android-m-permission-developer-edition/en

1 0