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

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_COMMANDS
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_NOTIFICATION_POLICY
android.permission.ACCESS_WIFI_STATE
android.permission.ACCESS_WIMAX_STATE
android.permission.BLUETOOTH
android.permission.BLUETOOTH_ADMIN
android.permission.BROADCAST_STICKY
android.permission.CHANGE_NETWORK_STATE
android.permission.CHANGE_WIFI_MULTICAST_STATE
android.permission.CHANGE_WIFI_STATE
android.permission.CHANGE_WIMAX_STATE
android.permission.DISABLE_KEYGUARD
android.permission.EXPAND_STATUS_BAR
android.permission.FLASHLIGHT
android.permission.GET_ACCOUNTS
android.permission.GET_PACKAGE_SIZE
android.permission.INTERNET
android.permission.KILL_BACKGROUND_PROCESSES
android.permission.MODIFY_AUDIO_SETTINGS
android.permission.NFC
android.permission.READ_SYNC_SETTINGS
android.permission.READ_SYNC_STATS
android.permission.RECEIVE_BOOT_COMPLETED
android.permission.REORDER_TASKS
android.permission.REQUEST_INSTALL_PACKAGES
android.permission.SET_TIME_ZONE
android.permission.SET_WALLPAPER
android.permission.SET_WALLPAPER_HINTS
android.permission.SUBSCRIBED_FEEDS_READ
android.permission.TRANSMIT_IR
android.permission.USE_FINGERPRINT
android.permission.VIBRATE
android.permission.WAKE_LOCK
android.permission.WRITE_SYNC_SETTINGS
com.android.alarm.permission.SET_ALARM
com.android.launcher.permission.INSTALL_SHORTCUT
com.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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值