转自:http://blog.csdn.net/yvan_z/article/details/54138477
以下是Android中的危险权限分为9组24种
下面我们来看如何动态获取权限!!!
先看最简单的,动态获取一个权限
比如现在要动态获取一个打电话的权限。。
首先需要在AndroidManifest.xml文件中写上这个权限
然后在Java代码进行动态获取
请求授权的代码
/**
* 请求授权
*/
private void requestPermission(){
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){ //表示未授权时
//进行授权
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CALL_PHONE},1);
}else{
//调用打电话的方法
makeCall();
}
}
请求之后,我们需要重写onRequestPermissionsResult这个方法
/**
* 权限申请返回结果
* @param requestCode 请求码
* @param permissions 权限数组
* @param grantResults 申请结果数组,里面都是int类型的数
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ //同意权限申请
makeCall();
}else { //拒绝权限申请
Toast.makeText(this,"权限被拒绝了",Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
}
/**
* 打电话方法
*/
private void makeCall(){
try {
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel://123456789"));
startActivity(intent);
}catch (SecurityException e){
e.printStackTrace();
}
}
上面只是对一个权限进行授权,如果我们需要对多个权限进行授权呢?难道还是这样一个一个写吗?答案是否定的,我们看一下授权申请的方法
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CALL_PHONE},1);
我们注意到权限的参数是一个String类型的数组,这就说明我们可以直接把所有要授权的权限放在一个数组中,这样就可以对多个权限进行授权了
以打电话和SD卡权限为例
/**
* 当有多个权限需要申请的时候
* 这里以打电话和SD卡读写权限为例
*/
private void requestPermissions(){
List permissionList = new ArrayList<>();
if (ContextCompat.checkSelfPermission(this,Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){
permissionList.add(Manifest.permission.CALL_PHONE);
}
if (ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (!permissionList.isEmpty()){ //申请的集合不为空时,表示有需要申请的权限
ActivityCompat.requestPermissio8ns(this,permissionList.toArray(new String[permissionList.size()]),1);
}else { //所有的权限都已经授权过了
}
}
同样需要写onRequestPermissionsResult()方法,这里和单个权限申请的写法有一点区别
/**
* 权限申请返回结果
* @param requestCode 请求码
* @param permissions 权限数组
* @param grantResults 申请结果数组,里面都是int类型的数
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 1:
if (grantResults.length > 0){ //安全写法,如果小于0,肯定会出错了
for (int i = 0; i < grantResults.length; i++) {
int grantResult = grantResults[i];
if (grantResult == PackageManager.PERMISSION_DENIED){ //这个是权限拒绝
String s = permissions[i];
Toast.makeText(this,s+"权限被拒绝了",Toast.LENGTH_SHORT).show();
}else{ //授权成功了
//do Something
}
}
}
break;
default:
break;
}
}
上面两种是单个和多个的权限申请,可是这还有一个问题,就是我们只能在当前类中使用。这个时候,我们需要想到一个封装,然后让所有的类都可以使用。
如何去封装呢? 我们在开发一个项目的时候,都会打一个框架,这里面可定会有各种各样的基类,这个时候我们就可以把权限的申请放在BaseActivity中,然后各个子Activity去继承BaseActivity。
然后通过接口回调的方式把授权结果传给子Activity。
下面来看代码:
首先是定义的接口
/**
* Created by 11213 on 2017/1/4.
* 权限回调接口
*/
public interface PermissionListener {
//授权成功
void onGranted();
//授权部分
void onGranted(List grantedPermission);
//拒绝授权
void onDenied(List deniedPermission);
}
BaseActivity的代码
public class BaseActivity1 extends AppCompatActivity {
private PermissionListener mlistener;
/**
* 权限申请
* @param permissions 待申请的权限集合
* @param listener 申请结果监听事件
*/
protected void requestRunTimePermission(String[] permissions,PermissionListener listener){
this.mlistener = listener;
//用于存放为授权的权限
List permissionList = new ArrayList<>();
//遍历传递过来的权限集合
for (String permission : permissions) {
//判断是否已经授权
if (ContextCompat.checkSelfPermission(this,permission) != PackageManager.PERMISSION_GRANTED){
//未授权,则加入待授权的权限集合中
permissionList.add(permission);
}
}
//判断集合
if (!permissionList.isEmpty()){ //如果集合不为空,则需要去授权
ActivityCompat.requestPermissions(this,permissionList.toArray(new String[permissionList.size()]),1);
}else{ //为空,则已经全部授权
listener.onGranted();
}
}
/**
* 权限申请结果
* @param requestCode 请求码
* @param permissions 所有的权限集合
* @param grantResults 授权结果集合
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 1:
if (grantResults.length > 0){
//被用户拒绝的权限集合
List deniedPermissions = new ArrayList<>();
//用户通过的权限集合
List grantedPermissions = new ArrayList<>();
for (int i = 0; i < grantResults.length; i++) {
//获取授权结果,这是一个int类型的值
int grantResult = grantResults[i];
if (grantResult != PackageManager.PERMISSION_GRANTED){ //用户拒绝授权的权限
String permission = permissions[i];
deniedPermissions.add(permission);
}else{ //用户同意的权限
String permission = permissions[i];
grantedPermissions.add(permission);
}
}
if (deniedPermissions.isEmpty()){ //用户拒绝权限为空
mlistener.onGranted();
}else { //不为空
//回调授权成功的接口
mlistener.onDenied(deniedPermissions);
//回调授权失败的接口
mlistener.onGranted(grantedPermissions);
}
}
break;
default:
break;
}
}
}
子Activity中进行调用
private void requestPermission(){
requestRunTimePermission(new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.WRITE_EXTERNAL_STORAGE}
, new PermissionListener() {
@Override
public void onGranted() { //所有权限授权成功
}
@Override
public void onGranted(List grantedPermission) { //授权失败权限集合
}
@Override
public void onDenied(List deniedPermission) { //授权成功权限集合
}
});
}
上面的代码注释很详细,就不再解释了
上面的封装,只能用在Activity中,如果要用在非Activity中(在v4包下的Fragment也可以进行授权),比如工具类中使用时,上面的就不适用了,因为我们看到,申请权限的方法必须传递一个Activity对象,为Activity又不可以new。这个时候,我们要想到,Activity管理栈。
代码如下:
接口还是上面的接口。。。
Activity管理栈
/**
* Created by 11213 on 2017/1/5.
* Activity管理类
*/
public class ActivityCollector {
private static List activityList = new ArrayList<>();
/** 添加一个Activity到集合中*/
public static void addActivity(Activity activity){
activityList.add(activity);
}
/** 从集合中删除一个Activity*/
public static void removeActivity(Activity activity){
activityList.remove(activity);
}
/**获取Activity栈中的栈顶的Activity
* 需要注意的是,栈是先进后出,所以最上面的Activity是集合中的最后一个*/
public static Activity getTopActivity(){
if (activityList.isEmpty()){ //Activity栈为空
return null;
}else { //不为空时
return activityList.get(activityList.size() - 1);
}
}
}
BaseActivity的代码
public class BaseActivity extends AppCompatActivity {
private static PermissionListener mlistener;
/**
* 创建Activity时加到管理栈中
* @param savedInstanceState
*/
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityCollector.addActivity(this);
}
/**
* 销毁时从Activity管理栈中移除
*/
@Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.removeActivity(this);
}
/**
* 权限申请
* @param permissions 待申请的权限集合
* @param listener 申请结果监听事件
*/
protected static void requestRunTimePermission(String[] permissions,PermissionListener listener){
mlistener = listener;
Activity topActivity = ActivityCollector.getTopActivity();
if (topActivity == null){
return;
}
//用于存放为授权的权限
List permissionList = new ArrayList<>();
//遍历传递过来的权限集合
for (String permission : permissions) {
//判断是否已经授权
if (ContextCompat.checkSelfPermission(topActivity,permission) != PackageManager.PERMISSION_GRANTED){
//未授权,则加入待授权的权限集合中
permissionList.add(permission);
}
}
//判断集合
if (!permissionList.isEmpty()){ //如果集合不为空,则需要去授权
ActivityCompat.requestPermissions(topActivity,permissionList.toArray(new String[permissionList.size()]),1);
}else{ //为空,则已经全部授权
listener.onGranted();
}
}
/**
* 权限申请结果
* @param requestCode 请求码
* @param permissions 所有的权限集合
* @param grantResults 授权结果集合
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 1:
if (grantResults.length > 0){
//被用户拒绝的权限集合
List deniedPermissions = new ArrayList<>();
//用户通过的权限集合
List grantedPermissions = new ArrayList<>();
for (int i = 0; i < grantResults.length; i++) {
//获取授权结果,这是一个int类型的值
int grantResult = grantResults[i];
if (grantResult != PackageManager.PERMISSION_GRANTED){ //用户拒绝授权的权限
String permission = permissions[i];
deniedPermissions.add(permission);
}else{ //用户同意的权限
String permission = permissions[i];
grantedPermissions.add(permission);
}
}
if (deniedPermissions.isEmpty()){ //用户拒绝权限为空
mlistener.onGranted();
}else { //不为空
//回调授权成功的接口
mlistener.onDenied(deniedPermissions);
//回调授权失败的接口
mlistener.onGranted(grantedPermissions);
}
}
break;
default:
break;
}
}
}
调用方法
public class Util {
private void requestPermission(){
BaseActivity.requestRunTimePermission(new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.WRITE_EXTERNAL_STORAGE}
, new PermissionListener() {
@Override
public void onGranted() {
}
@Override
public void onGranted(List grantedPermission) {
}
@Override
public void onDenied(List deniedPermission) {
}
});
}
}
后边的这些代码的注释写的很详细,大家都可以看明白。这些可以直接封装到自己的项目中,另外还有一些其他的封装思路,比如郭神说的使用一个透明的Activity。当然我们也可以使用第三方库。