PermissionHelper.java 11.7 KB
package com.vlion.simple.util;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.provider.Settings;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;

/**
 * Android 6.0 上权限分为<b>正常</b>和<b>危险</b>级别
 * <ul>
 * <li>正常级别权限:开发者仅仅需要在AndroidManifext.xml上声明,那么应用就会被允许拥有该权限,如:android.permission.INTERNET</li>
 * <li>危险级别权限:开发者需要在AndroidManifext.xml上声明,并且在运行时进行申请,而且用户允许了,应用才会被允许拥有该权限,如:android.permission.WRITE_EXTERNAL_STORAGE</li>
 * </ul>
 * 有米的以下权限需要在Android6.0上被允许,有米广告sdk才能正常工作,开发者需要在调用有米的任何代码之前,提前让用户允许权限
 * <ul>
 * <li>必须申请的权限
 * <ul>
 * <li>android.permission.READ_PHONE_STATE</li>
 * <li>android.permission.WRITE_EXTERNAL_STORAGE</li>
 * </ul>
 * </li>
 * <li>可选申请的权限
 * <ul>
 * <li>android.permission.ACCESS_FINE_LOCATION</li>
 * </ul>
 * </li>
 * </ul>
 * Android 6.0+ 权限申请助手
 *
 * @since 2016-01-12
 */
public class PermissionHelper {
	
	private static final String TAG = "PermissionHelper";
	
	/**
	 * 小tips:这里的int数值不能太大,否则不会弹出请求权限提示,测试的时候,改到1000就不会弹出请求了
	 */
	private final static int READ_PHONE_STATE_CODE = 101;
	
	private final static int WRITE_EXTERNAL_STORAGE_CODE = 102;
	
	private final static int REQUEST_OPEN_APPLICATION_SETTINGS_CODE = 12345;
	
	/**
	 * 有米 Android SDK 所需要向用户申请的权限列表
	 */
	private PermissionModel[] mPermissionModels = new PermissionModel[] {
			new PermissionModel("电话", Manifest.permission.READ_PHONE_STATE, "我们需要读取手机信息的权限来标识您的身份", READ_PHONE_STATE_CODE),
			new PermissionModel(
					"存储空间",
					Manifest.permission.WRITE_EXTERNAL_STORAGE,
					"我们需要您允许我们读写你的存储卡,以方便我们临时保存一些数据",
					WRITE_EXTERNAL_STORAGE_CODE
			)
	};
	
	private Activity mActivity;
	
	private OnApplyPermissionListener mOnApplyPermissionListener;
	
	public PermissionHelper(Activity activity) {
		mActivity = activity;
	}
	
	public void setOnApplyPermissionListener(OnApplyPermissionListener onApplyPermissionListener) {
		mOnApplyPermissionListener = onApplyPermissionListener;
	}
	
	/**
	 * 这里我们演示如何在Android 6.0+上运行时申请权限
	 */
	public void applyPermissions() {
		try {
			for (final PermissionModel model : mPermissionModels) {
				if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(mActivity, model.permission)) {
					ActivityCompat.requestPermissions(mActivity, new String[] { model.permission }, model.requestCode);
					return;
				}
			}
			if (mOnApplyPermissionListener != null) {
				mOnApplyPermissionListener.onAfterApplyAllPermission();
			}
		} catch (Throwable e) {
			Log.e(TAG, "", e);
		}
	}
	
	/**
	 * 对应Activity的 {@code onRequestPermissionsResult(...)} 方法
	 *
	 * @param requestCode
	 * @param permissions
	 * @param grantResults
	 */
	public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
		switch (requestCode) {
		case READ_PHONE_STATE_CODE:
		case WRITE_EXTERNAL_STORAGE_CODE:
			// 如果用户不允许,我们视情况发起二次请求或者引导用户到应用页面手动打开
			if (PackageManager.PERMISSION_GRANTED != grantResults[0]) {
				
				// 二次请求,表现为:以前请求过这个权限,但是用户拒接了
				// 在二次请求的时候,会有一个“不再提示的”checkbox
				// 因此这里需要给用户解释一下我们为什么需要这个权限,否则用户可能会永久不在激活这个申请
				// 方便用户理解我们为什么需要这个权限
				if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, permissions[0])) {
					AlertDialog.Builder builder = new AlertDialog.Builder(mActivity).setTitle("权限申请")
					                                                                .setMessage(findPermissionExplain
							                                                                (permissions[0])).setPositiveButton(
							                                                                "确定",
							                                                                new DialogInterface.OnClickListener
									                                                                () {
								
								                                                                @Override
								                                                                public void onClick(
										                                                                DialogInterface dialog,
										                                                                int which) {
									                                                                applyPermissions();
								                                                                }
							                                                                }
					                                                                );
					builder.setCancelable(false);
					builder.show();
				}
				// 到这里就表示已经是第3+次请求,而且此时用户已经永久拒绝了,这个时候,我们引导用户到应用权限页面,让用户自己手动打开
				else {
					AlertDialog.Builder builder = new AlertDialog.Builder(mActivity).setTitle("权限申请")
					                                                                .setMessage("请在打开的窗口的权限中开启" +
					                                                                            findPermissionName
							                                                                            (permissions[0]) +
					                                                                            "权限,以正常使用本应用")
					                                                                .setPositiveButton(
							                                                                "去设置",
							                                                                new DialogInterface.OnClickListener
									                                                                () {
								
								                                                                @Override
								                                                                public void onClick(
										                                                                DialogInterface dialog,
										                                                                int which) {
									                                                                openApplicationSettings(
											                                                                REQUEST_OPEN_APPLICATION_SETTINGS_CODE);
								                                                                }
							                                                                }
					                                                                )
					                                                                .setNegativeButton(
							                                                                "取消",
							                                                                new DialogInterface.OnClickListener
									                                                                () {
								                                                                @Override
								                                                                public void onClick(
										                                                                DialogInterface dialog,
										                                                                int which) {
									                                                                mActivity.finish();
								                                                                }
							                                                                }
					                                                                );
					builder.setCancelable(false);
					builder.show();
				}
				return;
			}
			
			// 到这里就表示用户允许了本次请求,我们继续检查是否还有待申请的权限没有申请
			if (isAllRequestedPermissionGranted()) {
				if (mOnApplyPermissionListener != null) {
					mOnApplyPermissionListener.onAfterApplyAllPermission();
				}
			} else {
				applyPermissions();
			}
			break;
		}
	}
	
	/**
	 * 对应Activity的 {@code onActivityResult(...)} 方法
	 *
	 * @param requestCode
	 * @param resultCode
	 * @param data
	 */
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		switch (requestCode) {
		case REQUEST_OPEN_APPLICATION_SETTINGS_CODE:
			if (isAllRequestedPermissionGranted()) {
				if (mOnApplyPermissionListener != null) {
					mOnApplyPermissionListener.onAfterApplyAllPermission();
				}
			} else {
				mActivity.finish();
			}
			break;
		}
	}
	
	/**
	 * 判断是否所有的权限都被授权了
	 *
	 * @return
	 */
	public boolean isAllRequestedPermissionGranted() {
		for (PermissionModel model : mPermissionModels) {
			if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(mActivity, model.permission)) {
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 打开应用设置界面
	 *
	 * @param requestCode 请求码
	 *
	 * @return
	 */
	private boolean openApplicationSettings(int requestCode) {
		try {
			Intent intent =
					new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + mActivity.getPackageName()));
			intent.addCategory(Intent.CATEGORY_DEFAULT);
			
			// Android L 之后Activity的启动模式发生了一些变化
			// 如果用了下面的 Intent.FLAG_ACTIVITY_NEW_TASK ,并且是 startActivityForResult
			// 那么会在打开新的activity的时候就会立即回调 onActivityResult
			// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			mActivity.startActivityForResult(intent, requestCode);
			return true;
		} catch (Throwable e) {
			Log.e(TAG, "", e);
		}
		return false;
	}
	
	/**
	 * 查找申请权限的解释短语
	 *
	 * @param permission 权限
	 *
	 * @return
	 */
	private String findPermissionExplain(String permission) {
		if (mPermissionModels != null) {
			for (PermissionModel model : mPermissionModels) {
				if (model != null && model.permission != null && model.permission.equals(permission)) {
					return model.explain;
				}
			}
		}
		return null;
	}
	
	/**
	 * 查找申请权限的名称
	 *
	 * @param permission 权限
	 *
	 * @return
	 */
	private String findPermissionName(String permission) {
		if (mPermissionModels != null) {
			for (PermissionModel model : mPermissionModels) {
				if (model != null && model.permission != null && model.permission.equals(permission)) {
					return model.name;
				}
			}
		}
		return null;
	}
	
	private static class PermissionModel {
		
		/**
		 * 权限名称
		 */
		public String name;
		
		/**
		 * 请求的权限
		 */
		public String permission;
		
		/**
		 * 解析为什么请求这个权限
		 */
		public String explain;
		
		/**
		 * 请求代码
		 */
		public int requestCode;
		
		public PermissionModel(String name, String permission, String explain, int requestCode) {
			this.name = name;
			this.permission = permission;
			this.explain = explain;
			this.requestCode = requestCode;
		}
	}
	
	/**
	 * 权限申请事件监听
	 */
	public interface OnApplyPermissionListener {
		
		/**
		 * 申请所有权限之后的逻辑
		 */
		void onAfterApplyAllPermission();
	}
	
}