Android动态权限(懒人自用)
16lz
2021-01-23
Android动态权限获取(懒人自用)
- Android动态权限
- 动态预览
- 使用权限情景:
- 代码部分
- 使用
- 问题
- 源码
Android动态权限
动态权限基本每个项目都用得到,懒得每次都写整理一下自己用,尽量少点copy(╯0╰)
不想漫天飞舞的引入别人的依赖,简单的事情尽量不要搞复杂,除非真的有必要。
动态预览
使用权限情景:
- App初始化时申请所有权限 ;
- 部分涉及权限操作的地方,要检查权限是否可用 ;
代码部分
1.工具类(PermissionManager.java)
package com.huan.squirrel.appermission.util;import android.Manifest;import android.annotation.TargetApi;import android.app.Activity;import android.app.AlertDialog;import android.app.ProgressDialog;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.content.pm.PackageManager;import android.net.Uri;import android.os.Build;import android.os.Handler;import android.provider.Settings;import android.support.annotation.RequiresApi;import android.support.v4.app.ActivityCompat;import android.support.v4.content.ContextCompat;import android.widget.Toast;import com.huan.squirrel.appermission.R;import static android.provider.Settings.ACTION_MANAGE_OVERLAY_PERMISSION;/** * 系统权限管理 * Created by huan on 2017/11/14. */public class PermissionManager { private static int REQUEST_PERMISS_CODE = 3248; //请求悬浮 public static int SYSTEM_ALERT_WINDOW_CODE = 11004; private Activity context; private static PermissionManager instance; AlertDialog.Builder builder; AlertDialog dialog; public static PermissionManager getInstance(Activity context) { if (instance == null) { instance = new PermissionManager(context); } return instance; } public PermissionManager(Activity context) { this.context = context; } //普通权限 private static String[] PERMISSIONS_ALL = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}; //需要的特殊权限,需要进入设置页面才能授权的 private static String[] PERMISSIONS_SPE = {Manifest.permission.SYSTEM_ALERT_WINDOW, Manifest.permission.INSTALL_PACKAGES}; //初始化app所需的权限 public void initPermission() { if (builder != null && dialog != null) { dialog.dismiss(); } if (getPermissionStatus2(context, PERMISSIONS_SPE)) {//初始化特殊权限 if (!getPermissionStatus(context, PERMISSIONS_ALL)) {//初始化普通权限 chekPermission(context, PERMISSIONS_ALL, new PermissionManager.OnCheckPermissionListener() { @Override public void onPassed() { //必须授权所有权限才能使用则,否则嵌套循环 initPermission(); } @Override public void onNoPassed() { //必须授权所有权限才能使用则,否则嵌套循环 initPermission(); } }); } } } //特殊权限弹窗后进入设置页面处理 public void showPermissionSettingDialog(final Context context, String permission) { switch (permission) { case Manifest.permission.INSTALL_PACKAGES: //弹框提示用户手动打开 showAlert(context, "安装权限", "需要打开允许来自此来源,请去设置中开启此权限", new DialogInterface.OnClickListener() { @RequiresApi(api = Build.VERSION_CODES.O) @Override public void onClick(DialogInterface dialog, int which) { //此方法需要API>=26才能使用 startInstallPermissionSettingActivity((Activity) context); } }); break; case Manifest.permission.SYSTEM_ALERT_WINDOW: //弹框提示用户手动打开 showAlert(context, "悬浮窗权限", "需要打开在其他应用中显示", new DialogInterface.OnClickListener() { @RequiresApi(api = Build.VERSION_CODES.O) @Override public void onClick(DialogInterface dialog, int which) { //此方法需要API>=26才能使用 getOverlayPermission((Activity) context); } }); break; } } //跳转到设置-请求悬浮窗权限 @TargetApi(Build.VERSION_CODES.M) public void getOverlayPermission(Activity context) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); intent.setData(Uri.parse("package:" + context.getPackageName())); //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivityForResult(intent, SYSTEM_ALERT_WINDOW_CODE); } // 跳转到设置-允许安装未知来源-页面 @TargetApi(Build.VERSION_CODES.O) public static void startInstallPermissionSettingActivity(final Activity context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Uri packageURI = Uri.parse("package:" + context.getPackageName()); //注意这个是8.0新API Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI); //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } } //检查安装app权限是否可用 public static boolean getPermissionStatusByName(Context context, String permissionName) { //兼容8.0 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { switch (permissionName) { case Manifest.permission.INSTALL_PACKAGES: return context.getPackageManager().canRequestPackageInstalls(); case Manifest.permission.SYSTEM_ALERT_WINDOW: return Settings.canDrawOverlays(context); } } return true; } //获取普通权限是否可用 @TargetApi(Build.VERSION_CODES.M) public static boolean getPermissionStatus(Context context, String permissionName) { // 版本判断。当手机系统大于 23 时,才有必要去判断权限是否获取 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { int i = ContextCompat.checkSelfPermission(context, permissionName); // 权限是否已经 授权 GRANTED---授权 DINIED---拒绝 return (i == PackageManager.PERMISSION_GRANTED); } return true; } //特殊权限 public boolean getPermissionStatus2(Context context, String[] permissions) { // 版本判断。当手机系统大于 23 时,才有必要去判断权限是否获取 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // 检查该权限是否已经获取 for (String str : permissions) { if (!getPermissionStatusByName(context, str)) { showPermissionSettingDialog(context, str); return false; } } } return true; } //普通权限 public static boolean getPermissionStatus(Context context, String[] permissions) { // 版本判断。当手机系统大于 23 时,才有必要去判断权限是否获取 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // 检查该权限是否已经获取 for (String str : permissions) { if (!getPermissionStatus(context, str)) { return false; } } } return true; } public static void chekPermission(Context context, String[] permissions, OnCheckPermissionListener listener) { // 版本判断。当手机系统大于 23 时,才有必要去判断权限是否获取 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // 检查该权限是否已经获取 boolean useful = getPermissionStatus(context, permissions); if (!useful) { // 如果没有授予该权限,就去提示用户请求 showDialogTipUserRequestPermission(context, permissions); } else { listener.onPassed(); } } else { listener.onPassed(); } } // 提示用户该请求权限的弹出框 private static void showDialogTipUserRequestPermission(final Context context, final String[] permission) { new AlertDialog.Builder(context) .setTitle("权限不可用") .setMessage("请开启权限后,再继续操作") .setPositiveButton("立即开启", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startRequestPermission(context, permission); } }) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(context, "请开启权限后再操作", Toast.LENGTH_LONG).show(); instance.initPermission(); } }).setCancelable(false).show(); } // 开始提交请求权限 private static void startRequestPermission(final Context context, String[] permissions) { ActivityCompat.requestPermissions((Activity) context, permissions, REQUEST_PERMISS_CODE); } //部分权限需要延时后生效 public void showProcess() { Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { //重新检查所有权限是否可用 initPermission(); } }, 1000); } /** * 监听器,监听权限是否通过 */ public interface OnCheckPermissionListener { void onPassed();//通过 void onNoPassed();//不通过 } /** * alert 消息提示框显示 * * @param context 上下文 * @param title 标题 * @param message 消息 * @param listener 监听器 */ public void showAlert(Context context, String title, String message, DialogInterface.OnClickListener listener) { builder = new AlertDialog.Builder(context); builder.setTitle(title); builder.setMessage(message); builder.setPositiveButton("确定", listener); builder.setCancelable(false); builder.setIcon(R.mipmap.ic_launcher); dialog = builder.create(); dialog.show(); }}
2.使用部分(MainActivity.java)
package com.huan.squirrel.appermission;import android.Manifest;import android.content.Context;import android.content.Intent;import android.support.annotation.NonNull;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;import com.huan.squirrel.appermission.util.PermissionManager;import static com.huan.squirrel.appermission.util.PermissionManager.SYSTEM_ALERT_WINDOW_CODE;public class MainActivity extends AppCompatActivity { private Context context; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /********************* 需要权限的功能要再次检查权限是否可用 start ******************************************/ context = this; final Button btn_permission = findViewById(R.id.btn_permission); final String[] PERMISSIONS_ALL = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}; btn_permission.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { PermissionManager.chekPermission(context, PERMISSIONS_ALL, new PermissionManager.OnCheckPermissionListener() { @Override public void onPassed() { Toast.makeText(context,"权限已经全部开启",Toast.LENGTH_LONG).show(); } @Override public void onNoPassed() { Toast.makeText(context,"部分权限未开启",Toast.LENGTH_LONG).show(); } }); } }); /************************* 需要权限的功能要再次检查权限是否可用 end **************************************/ } /************************ app第一次打开页面设置app运行必要的权限 start ***************************************/ @Override protected void onResume() { super.onResume(); PermissionManager.getInstance(this).initPermission(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(SYSTEM_ALERT_WINDOW_CODE==requestCode){ PermissionManager.getInstance(this).showProcess(); }else{ PermissionManager.getInstance(this).initPermission(); } } //处理权限申请回调(写在Activity中) @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { PermissionManager.getInstance(this).initPermission(); } /********************** app第一次打开页面设置app运行必要的权限 start ***************************************/}
使用
1.activity中声明全部的权限
复制三个方法 onResume, onActivityResult, onRequestPermissionsResult
2.某些需要权限才能操作的时候需要检查
使用 PermissionManager.chekPermission()方法处理
问题
1.有些地方还存在问题没有好的解决。如 获取悬浮窗权限的时候,跳转到设置页面手动开启权限后,返回MainActivity并通过Settings.canDrawOverlays方法没有及时返回true,要延迟一会儿。
2.没有对onActivityResult方法做过多的判断,全都在resume方法中重新检查并初始化权限(容易让人诟病)。
3.特殊权限需要的时候自己添加处理。
源码
https://github.com/squirrelhuan/APPermission
更多相关文章
- android Matrix处理图片原理及方法整理
- Android的安全与权限(1)
- android studio打开旧项目遇到build.gradle相关的问题解决方法
- Android的读写文件权限
- 将retrofit2和rxjava的初始化配置到application
- android判断模拟器的三种方法