Android权限 - 动态权限申请步骤


1.清单配置需要的权限:在AndroidManifest.xml中申请需要的权限
如:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.snazzyapp">

    <uses-permission android:name="android.permission.INTERNET"/>
    <!-- other permissions go here -->

    <application ...>
        ...
    </application>
</manifest>

2.检查是否拥有申请的权限

if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR)
        != PackageManager.PERMISSION_GRANTED) {
    // Permission is not granted
}

在Android 10上,如果不进行checkSelfPermission而直接申请权限,可能出现permissions revoked而导致进程被kill:
04-15 14:01:56.574   992  4007 I ActivityManager: Killing 18761:com.android.messaging/u0a89 (adj 100): permissions revoked
具体现象为:在应用使用过程中,需要用到某些运行时权限,然后应用进行申请。但是在权限框弹出前,应用闪退或是黑屏接着显示权限申请框。
同样的应用在Android 9上没有这个问题;在Android 10上才存在这个问题。

关于checkSelfPermission,在Context中定义的抽象方法,在ContextImpl中实现(具体的关联下次再总结). 
(Activity extends ContextThemeWrapper extends ContextWrapper extends Context)

3.没有权限,去申请权限

// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
        Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {

    // Permission is not granted
    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
            Manifest.permission.READ_CONTACTS)) {
        // Show an explanation to the user *asynchronously* -- don't block
        // this thread waiting for the user's response! After the user
        // sees the explanation, try again to request the permission.
    } else {
        // No explanation needed; request the permission
        ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
} else {
    // Permission has already been granted
}

关于requestPermissions,在Activity中实现,具体如下:

public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
    if (requestCode < 0) {
        throw new IllegalArgumentException("requestCode should be >= 0");
    }
    if (mHasCurrentPermissionsRequest) {
        Log.w(TAG, "Can request 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]);  //具体的Activity中实现
        return;
    }
    Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
    startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
    mHasCurrentPermissionsRequest = true;
}

关于buildRequestPermissionsIntent,在PackageManager中实现:

public Intent buildRequestPermissionsIntent(@NonNull String[] permissions) {
    if (ArrayUtils.isEmpty(permissions)) {
       throw new IllegalArgumentException("permission cannot be null or empty");
    }
    // ACTION_REQUEST_PERMISSIONS:
    // public static final String ACTION_REQUEST_PERMISSIONS = 
    // "android.content.pm.action.REQUEST_PERMISSIONS";
    // PackageInstaller中的GrantPermissionsActivity匹配这个Action
    // 所以会打开PackageInstaller的GrantPermissionsActivity进行权限申请
    // 也就是我们最常看见的权限申请界面了
    Intent intent = new Intent(ACTION_REQUEST_PERMISSIONS);
    intent.putExtra(EXTRA_REQUEST_PERMISSIONS_NAMES, permissions);
    intent.setPackage(getPermissionControllerPackageName());
    return intent;
}

4.覆写onRequestPermissionsResult方法,根据requestCode,permissions,grantResults判断我们是否申请成功

@Override
public void onRequestPermissionsResult(int requestCode,
        String[] permissions, int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission was granted, yay! Do the
                // contacts-related task you need to do.
            } else {
                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request.
    }
}

5.拒绝的时候利用shouldShowRequestPermissionRationale判断是否勾选'不再询问'
shouldShowRequestPermissionRationale在Activity中有定义,具体实现在PackageManagerService中。

6.如果勾选'不再询问',下次再申请此权限时默认返回拒绝。
需自定义dialog,让用户去设置里面开启权限。

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值