动态权限申请工具包 PermissionUtil (适配Andr
2019-07-20 本文已影响13人
12313凯皇
从Android 6.0
开始,一些常用权限如相机拍照等不仅仅需要在AndroidManifest.xml
中申请就可以了,还需要动态申请权限。但是申请权限后有需要在onRequestPermissionsResult
方法中进行处理,这样就感觉很烦。
于是便尝试着写一个util
工具包来简化操作,于是我找到了这个:RxPermissions,内部好像是通过RxJava2
实现的,8K+
的star
还是足矣说明它的强大的,不过本着学习的态度还是准备自己实现一个,哪怕适配比较差也行啊。
其实PermissionUtil
比较复杂的一点就是onRequestPermissionsResult
回调方法的问题,在度娘那里搜寻了一番后找到了一个比较通用的方法,就是通过一个透明主题的Activity
去实现,同时还可以给出一些友好的提示性Dialog
。废话说了那么多,下面开始正题:
效果图:
)
代码实现:
- 首先是权限申请完之后的
PermissionResultCallBack
回调接口。
public interface PermissionResultCallBack {
/**
* 当全部权限的申请被用户允许之后,该方法会被调用
*/
void onPermissionGranted();
/**
* 被拒绝的权限
*
* @param permissions permissions
*/
void onPermissionDenied(String... permissions);
/**
* 被拒绝且勾选了不再提示,需要去设置界面手动开启的权限
*
* @param permissions permissions
*/
void onRationalShow(String... permissions);
}
- 然后是用于申请权限的
TransparentActivity
public class TransparentActivity extends AppCompatActivity {
public static final String TAG = TransparentActivity.class.getSimpleName();
/**
* 权限申请相关
*/
public static final String EXTRA_PERMISSIONS = "extra_permission"; //权限列表
public static final int REQUEST_CODE = 1000; //请求码
private static PermissionResultCallBack mStaticPermissionResultCallBack;
private String[] permissions;
private AlertDialog mPermissionRequestDialog;
/**
* 请求权限
* 记得在{@code AndroidManifest.xml}中加上相应权限
*/
public static void requestPermission(Activity activity, String[] permissions, PermissionResultCallBack callBack) {
mStaticPermissionResultCallBack = callBack;
Intent intent = new Intent(activity, TransparentActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(TransparentActivity.EXTRA_PERMISSIONS, permissions);
activity.startActivity(intent);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_transparent);
Intent intent = getIntent();
if (intent.hasExtra(EXTRA_PERMISSIONS)) {
//权限申请
requestPermissions(intent);
return;
}
Log.e(TAG, "申请权限需要通过\"EXTRA_PERMISSIONS\"传递权限列表");
finish();
}
@Override
protected void onDestroy() {
if (mPermissionRequestDialog != null && mPermissionRequestDialog.isShowing()) {
mPermissionRequestDialog.dismiss();
}
super.onDestroy();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
Log.d(TAG, "onRequestPermissionsResult: requestCode = " + requestCode +
"\npermission = " + Arrays.toString(permissions) +
"\ngrantResults = " + Arrays.toString(grantResults));
//申请权限
if (requestCode == REQUEST_CODE) {
//是否为android 6.0及以上版本
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
mStaticPermissionResultCallBack.onPermissionGranted();
return;
}
List<String> deniedPermissions = new ArrayList<>();
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
//某个权限未授权
deniedPermissions.add(permissions[i]);
}
}
List<String> shouldShowRationalePermissions = getShouldShowRationPermissions(permissions,grantResults);
if (shouldShowRationalePermissions.size() != 0) {
//设置了不再提示且拒绝了的权限 需要到设置中去手动开启
mStaticPermissionResultCallBack.onRationalShow(shouldShowRationalePermissions.toArray(new String[0]));
finish();
return;
}
if (deniedPermissions.size() != 0) {
//拒绝的权限
mStaticPermissionResultCallBack.onPermissionDenied(deniedPermissions.toArray(new String[0]));
finish();
return;
}
//所有权限都授权了
mStaticPermissionResultCallBack.onPermissionGranted();
}
finish();
}
/**
* 申请权限
*/
private void requestPermissions(Intent intent) {
String[] extraPermissions = intent.getStringArrayExtra(EXTRA_PERMISSIONS);
if (extraPermissions == null) {
Log.e(TAG, "permissions 传参有误");
Toast.makeText(this, "permissions 传参有误", Toast.LENGTH_SHORT).show();
finish();
return;
}
//需要申请的权限(剔除掉已经拥有了的权限)
permissions = getNeedRequestPermissions(extraPermissions);
if (permissions.length == 0) {
Log.d(TAG, "权限都已拥有");
mStaticPermissionResultCallBack.onPermissionGranted();
finish();
return;
}
showDialog();
}
/**
* 申请权限前友好提示的dialog
*/
private void showDialog() {
if (mPermissionRequestDialog == null) {
mPermissionRequestDialog = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Light_Dialog)
.setTitle("权限申请")
.setMessage("系统需要申请" + permissions.length + "项权限")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(permissions, REQUEST_CODE);
} else {
ActivityCompat.requestPermissions(TransparentActivity.this,
permissions, REQUEST_CODE);
}
}
})
.setNegativeButton("拒绝", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
mStaticPermissionResultCallBack.onPermissionDenied(permissions);
finish();
}
}).create();
}
mPermissionRequestDialog.show();
}
/**
* 找出需要申请的权限,去掉已经拥有了的权限
*
* @param permissions permissions
* @return 需要申请的权限
*/
@TargetApi(Build.VERSION_CODES.M)
private String[] getNeedRequestPermissions(String[] permissions) {
List<String> permissionsNeedRequest = new ArrayList<>();
for (String permission : permissions) {
if (checkSelfPermission(permission) !=
PackageManager.PERMISSION_GRANTED) {
permissionsNeedRequest.add(permission);
}
}
return permissionsNeedRequest.toArray(new String[0]);
}
/**
* 需要跳转到设置中手动开启的权限
*/
private List<String> getShouldShowRationPermissions(String[] permissions, int[] grantResults) {
List<String> rationPermissions = new ArrayList<>();
//shouldShowRequestPermissionRationale
//如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true。
// 如果用户在过去拒绝了权限请求,并在权限请求系统对话框中选择了 Don't ask again 选项,
// 此方法将返回 false。
// 如果设备规范禁止应用具有该权限,此方法也会返回 false。
// 注:如果已拥有该权限那么也会返回false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED
&& !shouldShowRequestPermissionRationale(permissions[i])) {
rationPermissions.add(permissions[i]);
}
}
}
return rationPermissions;
}
}
然后是透明主题:
<!--继承Theme.AppCompat.NoActionBar,不显示标题栏,用于PermissionActivity-->
<style name="TransparentTheme" parent="Theme.AppCompat.NoActionBar">
<!--不设置activity进入和退出动画样式-->
<item name="android:windowAnimationStyle">@null</item>
<!--设置窗口的背景为透明,设置透明背景必须要设置此项-->
<item name="android:windowBackground">@android:color/transparent</item>
<!--设置窗口的背景是否为半透明,设置透明背景必须要设置此项-->
<item name="android:windowIsTranslucent">true</item>
<!--设置状态栏的背景为半透明-->
<item name="android:windowTranslucentStatus">true</item>
</style>
别忘了注册Activity
<activity
android:name="com.yu.hu.permissionlibrary.util.TransparentActivity"
android:theme="@style/TransparentTheme" />
- 权限申请
PermissionUtil
public class PermissionUtil {
private static final String TAG = "PermissionUtil";
/**
* 申请相机权限
*/
public static void requestCameraPermission(Activity activity, PermissionResultCallBack callBack) {
requestPermissions(activity, new String[]{Manifest.permission.CAMERA}, callBack);
}
/**
* 申请录制音频权限
*/
public static void requestRecordAudioPermission(Activity activity, PermissionResultCallBack callBack) {
requestPermissions(activity, new String[]{Manifest.permission.RECORD_AUDIO}, callBack);
}
/**
* 适用于app初始化或在主页时申请所需所有权限使用
*/
public static void requestInitPermissions(Activity activity, String[] permissions, PermissionResultCallBack callBack) {
requestPermissions(activity, permissions, callBack);
}
/**
* 请求多个权限
*
* @param activity activity
* @param permissions 权限列表
* @param callBack
*/
private static void requestPermissions(Activity activity, String[] permissions, @NonNull PermissionResultCallBack callBack) {
//使用PermissionRequestActivity请求
Log.d(TAG, "使用PermissionRequestActivity请求权限 "
+ "\n请求权限:" + Arrays.toString(permissions));
TransparentActivity.requestPermission(activity, permissions, callBack);
}
}
- 使用
PermissionUtil.requestInitPermissions(MainActivity.this,
new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.READ_EXTERNAL_STORAGE}
, new PermissionResultCallBack() {
@Override
public void onPermissionGranted() {
Toast.makeText(MainActivity.this, "允许了权限", Toast.LENGTH_SHORT).show();
}
@Override
public void onPermissionDenied(String... permissions) {
Log.d("MainActivity", "拒绝的权限: " + Arrays.toString(permissions));
Toast.makeText(MainActivity.this, "拒绝了权限" + Arrays.toString(permissions), Toast.LENGTH_SHORT).show();
}
@Override
public void onRationalShow(String... permissions) {
Log.d("MainActivity", "需要到系统设置开启的权限: " + Arrays.toString(permissions));
Toast.makeText(MainActivity.this, "需要到系统设置开启的权限: " + Arrays.toString(permissions), Toast.LENGTH_SHORT).show();
}
});