Android动态权限(懒人自用)

Android动态权限

动态权限基本每个项目都用得到,懒得每次都写整理一下自己用,尽量少点copy(╯0╰)
不想漫天飞舞的引入别人的依赖,简单的事情尽量不要搞复杂,除非真的有必要。

动态预览

Alt

使用权限情景:

  1. App初始化时申请所有权限
  2. 部分涉及权限操作的地方,要检查权限是否可用

代码部分

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值