menu 首页 标签 归档 视频 关于
Android-动态申请权限

一言加载中...

前言

在之前一篇关于高德定位错误总结的博客中,遇到在Android版本达到6.0+时对于一些危险权限用户手动授予,没有动态申请就会出现软件不能使用的问题,所以写出这篇博客解决动态申请权限的问题。

Android 6.0+SDK 版本号大于23后)对于普通权限可以在AndroidMinifest.xml文件中可以直接使用,而对于那些危险权限(如:定位权限,通话,发送短信等)需要动态申请权限;

下面是一个通过高德定位的案例

MainActivity中:

    //初始化定位
    private void initLocation(){
    //初始化定位
    mLocationClient = new AMapLocationClient(getApplicationContext());
    //设置定位回调监听
    mLocationClient.setLocationListener(new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation aMapLocation) {
            if (aMapLocation != null) {
                // 0为成功
                if (aMapLocation.getErrorCode() == 0) {
                    Toast.makeText(MainActivity.this, aMapLocation.getProvince()+" "+aMapLocation.getCity()+" "+aMapLocation.getDistrict(), Toast.LENGTH_SHORT).show();
                    StopLocation();
                }else{
                    if(aMapLocation.getErrorCode()==12)
                        Toast.makeText(MainActivity.this, "您没有授予定位所需权限,请到授权管理允许权限!", Toast.LENGTH_SHORT).show();
                    else
                        Toast.makeText(MainActivity.this, "错误代码"+aMapLocation.getErrorCode(), Toast.LENGTH_SHORT).show();
                }
            }
        }
    });
    //初始化定位参数
    mLocationOption = new AMapLocationClientOption();
    //设置定位模式为高精度模式,Battery_Saving为低功耗模式,Device_Sensors是仅设备模式
    mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
    //设置是否返回地址信息(默认返回地址信息)
    mLocationOption.setNeedAddress(true);
    //是否只定位一次
    mLocationOption.setOnceLocation(true);
    //设置是否强制刷新WIFI,默认为强制刷新
    mLocationOption.setWifiScan(true);
    //设置是否允许模拟位置,默认为false,不允许模拟位置
    mLocationOption.setMockEnable(false);
    //设置定位间隔,单位毫秒,默认为2000ms
    mLocationOption.setInterval(2000);
    //给定位客户端对象设置定位参数
    mLocationClient.setLocationOption(mLocationOption);
    //启动定位
    mLocationClient.startLocation();
    }
    //开始定位
    private void startLocation(){
        mLocationClient.startLocation();
    }
    //结束定位
    private void StopLocation(){
        mLocationClient.stopLocation();
    }

CheckPermission.java

public class CheckPermission extends Activity {
    /**
     * 需要进行检测的权限数组
     */
    protected String[] needPermissions = {
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.READ_PHONE_STATE
    };

    private static final int PERMISSON_REQUESTCODE = 0;

    /**
     * 判断是否需要检测,防止不停的弹框
     */
    private boolean isNeedCheck = true;

    @Override
    protected void onResume() {
        super.onResume();
        if (Build.VERSION.SDK_INT >= 23
                && getApplicationInfo().targetSdkVersion >= 23) {
            if (isNeedCheck) {
                checkPermissions(needPermissions);
            }
        }
    }

    /**
     * @param permissions
     * @since 2.5.0
     */
    private void checkPermissions(String... permissions) {
        try {
            if (Build.VERSION.SDK_INT >= 23
                    && getApplicationInfo().targetSdkVersion >= 23) {
                List<String> needRequestPermissonList = findDeniedPermissions(permissions);
                if (null != needRequestPermissonList
                        && needRequestPermissonList.size() > 0) &#123;
                    String[] array = needRequestPermissonList.toArray(new String[needRequestPermissonList.size()]);
                    Method method = getClass().getMethod("requestPermissions", new Class[]&#123;String[].class,int.class&#125;);

                    method.invoke(this, array, PERMISSON_REQUESTCODE);
                &#125;
            &#125;
        &#125; catch (Throwable e) &#123;
        &#125;
    &#125;

    /**
     * 获取权限集中需要申请权限的列表
     *
     * @param permissions
     * @return
     * @since 2.5.0
     */
    private List<String> findDeniedPermissions(String[] permissions) &#123;
        List<String> needRequestPermissonList = new ArrayList<String>();
        if (Build.VERSION.SDK_INT >= 23
                && getApplicationInfo().targetSdkVersion >= 23) &#123;
            try &#123;
                for (String perm : permissions) &#123;
                    Method checkSelfMethod = getClass().getMethod("checkSelfPermission", String.class);
                    Method shouldShowRequestPermissionRationaleMethod = getClass().getMethod("shouldShowRequestPermissionRationale",
                            String.class);
                    if ((Integer) checkSelfMethod.invoke(this, perm) != PackageManager.PERMISSION_GRANTED
                            || (Boolean) shouldShowRequestPermissionRationaleMethod.invoke(this, perm)) &#123;
                        needRequestPermissonList.add(perm);
                    &#125;
                &#125;
            &#125; catch (Throwable e) &#123;

            &#125;
        &#125;
        return needRequestPermissonList;
    &#125;

    /**
     * 检测是否所有的权限都已经授权
     *
     * @param grantResults
     * @return
     * @since 2.5.0
     */
    private boolean verifyPermissions(int[] grantResults) &#123;
        for (int result : grantResults) &#123;
            if (result != PackageManager.PERMISSION_GRANTED) &#123;
                return false;
            &#125;
        &#125;
        return true;
    &#125;

    @TargetApi(23)
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] paramArrayOfInt) &#123;
        if (requestCode == PERMISSON_REQUESTCODE) &#123;
            if (!verifyPermissions(paramArrayOfInt)) &#123;
                showMissingPermissionDialog();
                isNeedCheck = false;
            &#125;
        &#125;
    &#125;
    /**
     * 显示提示信息
     */
    private void showMissingPermissionDialog() &#123;
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("需要您授予下面权限:");
        builder.setMessage("当前应用缺少必要权限。\\n\\n请点击\\\"设置\\\"-\\\"权限\\\"-打开所需权限。");
        // 拒绝, 退出应用
        builder.setNegativeButton("拒绝", new DialogInterface.OnClickListener() &#123;
            @Override
            public void onClick(DialogInterface dialogInterface, int i) &#123;
                finish();
            &#125;
        &#125;);
        builder.setPositiveButton("确定",
                new DialogInterface.OnClickListener() &#123;
                    @Override
                    public void onClick(DialogInterface dialog, int which) &#123;
                        startAppSettings();
                    &#125;
                &#125;);

        builder.setCancelable(false);

        builder.show();
    &#125;
    /**
     * 启动应用的设置
     */
    private void startAppSettings() &#123;
        Intent intent = new Intent(
                Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.parse("package:" + getPackageName()));
        startActivity(intent);
    &#125;
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) &#123;
        if (keyCode == KeyEvent.KEYCODE_BACK) &#123;
            this.finish();
            return true;
        &#125;
        return super.onKeyDown(keyCode, event);
    &#125;

AndroidMinifest.xml

<!-- 需要运行时注册的权限 -->
    <!-- 用于进行网络定位 -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <!-- 用于访问GPS定位 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <!-- 用于提高GPS定位速度 -->
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
    <!-- 写入扩展存储,向扩展卡写入数据,用于写入缓存定位数据 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!-- 读取缓存数据 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <!-- 用于读取手机当前的状态 -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <!-- 更改设置 -->
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />

    <!-- 3.2.0版本增加 -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <!-- 3.2.0版本增加 -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
写博客不易,请我喝杯咖啡?

评论

arrow_upward