这里是对所以权限进行整体判断,单一判断的逻辑复杂,而且AlertDialog容易错乱(主要还是本人学艺不精~)
点击“始终允许”则打开权限不在提示;
点击“禁止”未选择“禁止不在询问”则循环请求循环(简单粗暴点吧);
点击“禁止”选择“禁止不在询问”则提示用户去应用手动打开权限。

以下是主类和权限基础类,算是简单进行封装吧
MainActivity.java

public class MainActivity extends PermissionBaseActivity {
    private String[] mPermissions = new String[]{
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.CAMERA,
            Manifest.permission.ACCESS_COARSE_LOCATION};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        setPermissions(mPermissions, new InterfacePermission() {
            @Override
            public void onAllow() {
                Toast.makeText(MainActivity.this, "权限已全部允许,可进行初始化操作", Toast.LENGTH_SHORT).show();
            }
        });
    }

}

PermissionBaseActivity.java

public class PermissionBaseActivity extends Activity {

    private AlertDialog mPermissionDialog;
    private String[] mPermissions;
    private InterfacePermission mInterPer;


    public void setPermissions(String[] mPermissions, InterfacePermission mInterPer) {
        this.mPermissions = mPermissions;
        this.mInterPer = mInterPer;
        init_permission();

    }


    public void init_permission() {
        List<String> mPermissionList = new ArrayList<>();
        mPermissionList.clear();
        for (int i = 0; i < mPermissions.length; i++) {
            if (ContextCompat.checkSelfPermission(this, mPermissions[i]) != PackageManager.PERMISSION_GRANTED) {
                mPermissionList.add(mPermissions[i]);
            }
        }

        if (mPermissionList.isEmpty()) {// 全部允许
            //可进行初始化操作,接口回调
            mInterPer.onAllow();
        } else {//存在未允许的权限
            String[] permissionsArr = mPermissionList.toArray(new String[mPermissionList.size()]);
            ActivityCompat.requestPermissions(this, permissionsArr, 101);
        }

    }


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 101:
                for (int i = 0; i < grantResults.length; i++) {
                    if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                        //判断是否勾选"禁止后不再询问"
                        boolean showRequestPermission = ActivityCompat
                                .shouldShowRequestPermissionRationale(this, permissions[i]);
                        if (showRequestPermission) {//未勾选,循环请求权限
                            init_permission();
                            return;
                        } else { //已勾选,跳转到应用设置,手动打开权限
                            showPermissionDialog();
                        }
                    }
                }
                break;
            default:
                break;
        }

    }


    public void showPermissionDialog() {
        if (mPermissionDialog == null) {
            mPermissionDialog = new AlertDialog.Builder(this)
                    .setTitle("使用xxx须打开相应权限")
                    .setMessage("请在“应用设置”的“权限”中,允许相应权限")
                    .setPositiveButton("转自“设置”", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            mPermissionDialog.cancel();
                            Uri packageURI = Uri.parse("package:" + getPackageName());
                            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
                            startActivityForResult(intent, 100);//打开应用设置


                        }
                    }).create();
            mPermissionDialog.setCanceledOnTouchOutside(false);
        }
        mPermissionDialog.show();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 100) {
            //从设置返回到应用时,再次判断
            init_permission();
        }
    }

    public interface InterfacePermission {
        void onAllow();
    }
}

**知识点:**先理解,不必深入!
继承时,对于方法覆盖时,new的谁,this,就指向谁,多态性决定;
如果是成员变量,this在哪个类就指向哪个类的成员变量,成员变量没有多态性;
A类中this表示该A类对象,注意在匿名内部类,要使用外部类则需要强调 A.this
A extends AppCompatActivity/Activity,最终extends Context,所以A既是Activity也是Context

父类中调用工具类的时传入的this,父类中构造方法的this,或父类中普通方法onCreate中的this,都是指子类对象;
因为Java 中创建子类对象不会创建父类对象!继承时,方法覆盖new的谁,this就指向谁.
创建对象指的是在堆区开辟空间
编译器在运行子类构造器之前,必须先执行父类构造器;且调用父类构造器的语句必须在子类构造器的第一行。
构造方法的作用是为堆区中的对象的属性初始化,创建对象由new关键字去做.