1. 程式人生 > >開發app在android6.0執行直接退出解決(二)

開發app在android6.0執行直接退出解決(二)

許可權的適配主要就是兩步,一是請求許可權,二是系統應答,主要在這兩個地方進行封裝。主要使用第三方庫PermissionsDispatcher

(1)專案build.gradle 中新增
classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.8’
(2)app的 build.gradle 中新增
apply plugin:’android-apt’
apt ‘com.github.hotchemi:permissionsdispatcher-processor:2.1.3’

1.定義PermissionHandler用於許可權回撥,許可權通過、許可權拒絕、許可權不再詢問三種情況

public abstract class PermissionHandle{

        //許可權通過
        public abstract void onGranted();

        //許可權拒絕
        public abstract void onDenied();

        //許可權不在詢問
        public boolean onNeverAsk(){
            return false;
        }
    }

2、請求許可權

private PermissionHandle mHandle;

    /**
     * 請求許可權
     * @param permissions 許可權列表
     * @param handle 回撥
     */
    protected void requestPermission(String[] permissions,PermissionHandle handle){
        if (PermissionUtil.hasSelfPermissions(this,permissions)){
            handle.onGranted();
        }else
{ mHandle=handle; ActivityCompat.requestPermissions(this,permissions,001); } }

注:PermissionUtil是PermissionsDispatcher中使用的工具類

public final class PermissionUtil {

    private static SimpleArrayMap<String,Integer> MIN_SDK_PERMISSIONS;

    static {
        MIN_SDK_PERMISSIONS=new SimpleArrayMap<>(8);
        MIN_SDK_PERMISSIONS.put("com.android.voicemail.permission.ADD_VOICEMAIL",14);
        MIN_SDK_PERMISSIONS.put("android.permission.BODY_SENSORS",20);
        MIN_SDK_PERMISSIONS.put("android.permission.READ_CALL_LOG",16);
        MIN_SDK_PERMISSIONS.put("android.permission.READ_EXTERNAL_STORAGE",16);
        MIN_SDK_PERMISSIONS.put("android.permission.USE_SIP",9);
        MIN_SDK_PERMISSIONS.put("android.permission.WRITE_CALL_LOG",16);
        MIN_SDK_PERMISSIONS.put("android.permission.SYSTEM_ALERT_WINDOW", 23);
        MIN_SDK_PERMISSIONS.put("android.permission.WRITE_SETTINGS", 23);
    }

    private static volatile int targetSdkVersion=-1;

    public PermissionUtil() {
    }

    //檢查所有的許可權是否被授權
    public static boolean verifyPermissions(int... grantResults){
        if (grantResults.length==0){
            return false;
        }
        for (int result : grantResults) {
            if (result!= PackageManager.PERMISSION_GRANTED){
                return false;
            }
        }
        return true;
    }

    //如果活動或片段可以訪問所有給定的許可權,則返回true
    public static boolean hasSelfPermissions(Context context,String... permissions){
        for (String permission : permissions) {
            if (permissionExists(permission)&&hasSelfPermissions(context,permission)){
                return false;
            }
        }
        return true;
    }

    //如果在這個SDK版本存在的許可權,則返回true
    private static boolean permissionExists(String permission) {
        Integer minVersion = MIN_SDK_PERMISSIONS.get(permission);
        return minVersion == null || Build.VERSION.SDK_INT >= minVersion;
    }

    //確定上下文訪問給定的許可權。
    private static boolean hasSelfPermission(Context context, String permission) {
        try {
            return PermissionChecker.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
        } catch (RuntimeException t) {
            return false;
        }
    }

    //檢查需要給予的許可權,顯示理由
    public static boolean shouldShowRequestPermissionRationale(Activity activity, String... permissions) {
        for (String permission : permissions) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
                return true;
            }
        }
        return false;
    }

    //獲取sdk 版本
    @TargetApi(Build.VERSION_CODES.DONUT)
    public static int getTargetSdkVersion(Context context) {
        try {
            if (targetSdkVersion != -1) {
                return targetSdkVersion;
            }
            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            targetSdkVersion = packageInfo.applicationInfo.targetSdkVersion;
        } catch (PackageManager.NameNotFoundException ignored) {
        }
        return targetSdkVersion;
    }
}

3.許可權結果處理

 /**
     * 許可權請求結果
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (mHandle==null){
            return;
        }

        if (PermissionUtil.shouldShowRequestPermissionRationale(this,permissions)){
            if (!mHandle.onNeverAsk()){
                Toast.makeText(this, "許可權已被拒絕,請在設定-應用-許可權中開啟", Toast.LENGTH_SHORT).show();
            }
        }else{
            mHandle.onDenied();
        }
    }

4、呼叫

public class PermissionActivity extends XPermissionActivity implements View.OnClickListener {
    private Context mContext;

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

        mContext=PermissionActivity.this;

        findViewById(R.id.btn_camera).setOnClickListener(this);
        findViewById(R.id.btn_call).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_camera:
                requestPermission(new String[]{Manifest.permission.CAMERA}, new PermissionHandle() {
                    @Override
                    public void onGranted() {
                        Intent intent = new Intent(); //呼叫照相機
                        intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
                        startActivity(intent);
                    }

                    @Override
                    public void onDenied() {
                        Toast.makeText(PermissionActivity.this, "拒絕", Toast.LENGTH_SHORT).show();
                    }
                });
                break;

            case R.id.btn_call:
                requestPermission(new String[]{Manifest.permission.CALL_PHONE}, new PermissionHandle() {
                    @Override
                    public void onGranted() {
                        /*Intent i=new Intent(Intent.ACTION_CALL,Uri.parse("tel:10086"));
                        startActivity(i);*/
                        Uri uri = Uri.parse("tel:10086");
                        Intent intent = new Intent(Intent.ACTION_DIAL, uri);
                        startActivity(intent);
                    }

                    @Override
                    public void onDenied() {
                        Toast.makeText(PermissionActivity.this, "拒絕", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public boolean onNeverAsk() {
                        new AlertDialog.Builder(mContext)
                                .setTitle("許可權申請")
                                .setMessage("在設定-應用-許可權中開始電話許可權,以保證功能的正常使用")
                                .setPositiveButton("去開啟",new DialogInterface.OnClickListener(){
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        Intent i=new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                        Uri uri=Uri.fromParts("package",getPackageName(),null);
                                        i.setData(uri);
                                        startActivity(i);

                                        dialog.dismiss();
                                    }
                                })
                        .setNegativeButton("取消",null)
                        .setCancelable(false)
                        .show();

                        return true;

                    }
                });
                break;
        }
    }
}