关闭

Android 6.0 权限问题解决方法

标签: androidandroid6.0 权限
1756人阅读 评论(0) 收藏 举报
分类:

最近在浏览 Andorid bus  时无意间看到Andorid 6.0 权限问题   现在6.0 慢慢普及 相信过不了多久 大家都会做6.0的适配 但是 6.0对权限尤其是用户隐私方面做了严格的限制   如果还是和以前一样 直接在配置文件中添加之后  就以为 万事大吉  这就错了    于是为了给更多忙的没时间的朋友传播解决方法   就无耻的把前辈的成果借取过来  (主要是自己懒不想在网上论坛帖子里面找了 )  方便自己以后遇到可以顺利解决   


http://www.apkbus.com/blog-705730-60306.html


以上链接是原文章  


概述

安卓平台权限一直有被流氓应用随便利用诟病, android M的发布彻底解决了这一问题,取而代之的是,app不得不在运行时一个一个询问用户授予权限。

Android 6.0(api23)系统中,做了一些限制, 开发者在使用到每条权限时必须自己调用相关代码请求.

如果没有获得某项权限,直接使用相关功能,则会导致自己程序crash. 见log

可见6.0以后的系统开发者必须对权限适配,否则软件随时都可能奔溃,那么问题来了~

已经发出去的版本或是targetSdkVersion小与23的apk怎么办? 废话,当然会崩了!!!

只要在满足在Android M上直接使用为授权的功能,程序必须Crash. targetSdkVersion<23的应用在安装时系统会默认全部授权应用在manifest中申请的权限, 不要应用这样你的应用就完事大全了.用户可以在以下页面或是其他应用关闭相关权限,然后...你的应用就没有然后了~ 关闭权限页

Android M 权限分类

安卓系统把权限分为了三类:

  • Normal Permissions

  • Dangerous Permissions

  • Special Permissions

Normal Permissions-一般权限

一般权限都是一些系统认为比较权限的权限,流氓应用就是拥有这些权限也干不出多大坏事,Normal 权限会在应用安装是直接授权, 官网解释:权限如下:

ACCESS_LOCATION_EXTRA_COMMANDS
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
BLUETOOTH
BLUETOOTH_ADMIN
BROADCAST_STICKY
CHANGE_NETWORK_STATE
CHANGE_WIFI_MULTICAST_STATE
CHANGE_WIFI_STATE
DISABLE_KEYGUARD
EXPAND_STATUS_BAR
FLASHLIGHT
GET_PACKAGE_SIZE
INTERNET
KILL_BACKGROUND_PROCESSES
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_INSTALL_PACKAGES
SET_TIME_ZONE
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
SET_ALARM
INSTALL_SHORTCUT
UNINSTALL_SHORTCUT

Dangerous Permissions-危险权限

这些权限都是一些敏感性权限,一些广告平台或是流氓应用会用这些权限干一些坏坏的事情,因此系统将这类权限分了几个类别, 应用每次都要检测下是否有权限,没有的化必须弹出对话框申请,只要一个组别中的一个权限得到了授权,整个组的权限都会的到授权.

这部分权限也是我们重点在M系统上关注和适配的部分. 官网权威说明, 具体相关权限见图:

Dangerous Permission

Special Permissions- 特殊权限

SYSTEM_ALERT_WINDOW and WRITE_SETTINGS, 这两个权限比较特殊,不能通过代码申请方式获取,必须得用户打开软件设置页手动打开,才能授权.

There are a couple of permissions that don't behave like normal and dangerous permissions. SYSTEM_ALERT_WINDOW and WRITE_SETTINGS are particularly sensitive, so most apps should not use them. If an app needs one of these permissions, it must declare the permission in the manifest, and send an intent requesting the user's authorization. The system responds to the intent by showing a detailed management screen to the user.

特殊权限官网推荐用法

实战Android m权限申请用法

我们对相关申请方法封装成了工具类,方便m系统适配随时调用.

相关配置

compileSdkVersion and targetSdkVersion 设置为 23开始

调用相关权限

private void testAlertPermission() {
    WindowManager mWindowManager = (WindowManager) getSystemService(
            Context.WINDOW_SERVICE);
    WindowManager.LayoutParams params = new WindowManager.LayoutParams();
    params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
    mWindowManager.addView(new TextView(this), params);
}

权限申请相关代码

// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
               Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {

   // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
           Manifest.permission.READ_CONTACTS)) {

    // Show an expanation to the user *asynchronously* -- don't block
    // this thread waiting for the user's response! After the user
    // sees the explanation, try again to request the permission.

     } else {

    // No explanation needed, we can request the permission.

    ActivityCompat.requestPermissions(thisActivity,
            new String[]{Manifest.permission.READ_CONTACTS},
            MY_PERMISSIONS_REQUEST_READ_CONTACTS);

    // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
    // app-defined int constant. The callback method gets the
    // result of the request.
      }
}

requestPermissions方法调用时会弹出以下对话框.当用户点击拒绝并且勾选了不再弹出后这个对话框将不会再弹出,会直接拒绝掉该权限: requestPermissions

shouldShowRequestPermissionRationale方法说明

用户拒绝,或是不在弹出,这个方法会返回false. 返回说明

Activity和Fragment的申请方法不一样,所以我们对方法做了包装如下:

@TargetApi(Build.VERSION_CODES.M)
public static boolean checkPermission(Object cxt, String permission, int requestCode) {
    if (!checkSelfPermissionWrapper(cxt, permission)) {
        if (!shouldShowRequestPermissionRationaleWrapper(cxt, permission)) {
            requestPermissionsWrapper(cxt, new String[]{permission}, requestCode);
        } else {
            Log.d(TAG, "should show rational");
        }
        return false;
    }
    return true;
}

private static void requestPermissionsWrapper(Object cxt, String[] permission, int requestCode) {
    if (cxt instanceof Activity) {
        Activity activity = (Activity) cxt;
        ActivityCompat.requestPermissions(activity, permission, requestCode);
    } else if (cxt instanceof Fragment) {
        Fragment fragment = (Fragment) cxt;
        fragment.requestPermissions(permission, requestCode);
    } else {
        throw new RuntimeException("cxt is net a activity or fragment");
    }
}

权限可以一次申请多个

如图一次可以申请多个权限,但是用户还是一个一个授权.我们对该请求也做了封装: multi multi

@TargetApi(23)
private static boolean checkSelfPermissionWrapper(Object cxt, String permission) {
    if (cxt instanceof Activity) {
        Activity activity = (Activity) cxt;
        return ActivityCompat.checkSelfPermission(activity,
                permission) == PackageManager.PERMISSION_GRANTED;
    } else if (cxt instanceof Fragment) {
        Fragment fragment = (Fragment) cxt;
        return fragment.getActivity().checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
    } else {
        throw new RuntimeException("cxt is net a activity or fragment");
    }
}

private static String[] checkSelfPermissionArray(Object cxt, String[] permission) {
    ArrayList<String> permiList = new ArrayList<>();
    for (String p : permission) {
        if (!checkSelfPermissionWrapper(cxt, p)) {
            permiList.add(p);
        }
    }

    return permiList.toArray(new String[permiList.size()]);
}

权限返回处理

在activity或fragment 中重写onRequestPermissionsResult,用户处理相关权限后会回调该方法,当活取到相关应用后可以继续原来的逻辑.

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode) {
        case PermissionUtils.PERMISSION_REQUEST_CODE:
            if (PermissionUtils.verifyPermissions(grantResults)) {
                // Permission Granted
                // do you action
            } else {
                // Permission Denied
                Toast.makeText(this, "WRITE_CONTACTS Denied", Toast.LENGTH_SHORT)
                        .show();
            }
            break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

public static boolean verifyPermissions(int[] grantResults) {
    // At least one result must be checked.
    if (grantResults.length < 1) {
        return false;
    }

    // Verify that each required permission has been granted, otherwise return false.
    for (int result : grantResults) {
        if (result != PackageManager.PERMISSION_GRANTED) {
            return false;
        }
    }
    return true;
}

特殊权限的申请

以前特殊权限说明地方已经支出,该类权限需求intent到具体的设置页面,让用户手动打开,才能授权. 同样重写onActivityResult方法,返回该页面时做回调处理.

sp

系统弹出权限,相关代码实例:

/**
 * 检测系统弹出权限
 * @param cxt
 * @param req
 * @return
 */
@TargetApi(23)
public static boolean checkSettingAlertPermission(Object cxt, int req) {
    if (cxt instanceof Activity) {
        Activity activity = (Activity) cxt;
        if (!Settings.canDrawOverlays(activity.getBaseContext())) {
            Log.i(TAG, "Setting not permission");

            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + activity.getPackageName()));
            activity.startActivityForResult(intent, req);
            return false;
        }
    } else if (cxt instanceof Fragment) {
        Fragment fragment = (Fragment) cxt;
        if (!Settings.canDrawOverlays(fragment.getActivity())) {
            Log.i(TAG, "Setting not permission");

            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + fragment.getActivity().getPackageName()));
            fragment.startActivityForResult(intent, req);
            return false;
        }
    } else {
        throw new RuntimeException("cxt is net a activity or fragment");
    }

    return true;
}

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == PermissionUtils.PERMISSION_SETTING_REQ_CODE) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (Settings.canDrawOverlays(this)) {
                    // do something
                } else {
                    Toast.makeText(this, "not has setting permission", Toast.LENGTH_LONG).show();
                    finish();
                }
            }
        }
    }


1
0
查看评论

cordova 插件 开发添加 android 权限

cordova 插件 开发添加 android 权限
  • gufeilong
  • gufeilong
  • 2016-11-28 22:28
  • 3807

cordova学习三:config.xml文件配置

HelloWorld A sample Apache Cordova application that responds to the deviceready event. Apache Cordo...
  • jyy_12
  • jyy_12
  • 2015-06-22 14:44
  • 14529

android6.0以上权限申请工具类

Android6.0以上,有部分权限是需要申请的。共9组,只要一个权限申请成功默认这一组的权限也申请成功,看下图: 注意:如果需要测试就在xml中将targetsdkversion>=23即可 Android权限大全表查看 权限申请工具类如下: package com.examp...
  • qq_17387361
  • qq_17387361
  • 2016-10-19 09:46
  • 3123

Cordova-Android 插件开发

Android 插件开发 原文地址:https://cordova.apache.org/docs/en/latest/guide/platforms/android/plugin.html Android Plugins 本节提供了如何实现Android平台上的本机插件代码的详细信息。阅...
  • u014359108
  • u014359108
  • 2016-03-04 15:14
  • 4439

Android基于cordova3.3的插件开发

最近工作的项目,需要用到cordova进行插件开发,具体Cordova的作用,就不再赘述,大家可以自行的去百度就OK了,直接开始。具体的流程,我将已一个小的Demo进行推进讲解。也是刚刚接触,太理论的基础东西我也说不好,还是先跑起来一个Demo,才有继续学下去的动力~大家多多指教~   ...
  • xq328220454
  • xq328220454
  • 2014-07-11 10:36
  • 24775

基于Cordova的android项目入门

本文记录在ecplise里建立一个基于Cordova的android项目的基本步骤。 准备工作: 1、cordova-3.0.0.jar 2、cordova.js 3、发开android的eclipse的环境。Android SDK、ADT Plugin 开始建立项目 1、打开Eclip...
  • findsafety
  • findsafety
  • 2015-11-17 09:41
  • 4919

Android 6.0动态获取权限开源项目

Android 6.0 相比之前的Android版本有一个很大的不同点,就是动态获取权限,即不仅在Manifest文件里设置各种权限,在使用一些危险权限时候还得动态的弹出个对话框让客户去选择授予这个权限。     基本内容和代码就不重复了,大家可以参考这一篇: http:...
  • bit_kaki
  • bit_kaki
  • 2016-11-16 17:11
  • 1854

Cordova实现文件创建和读写操作(支持Android和IOS等)

Cordova实现文件操作,本篇文章讲述的是在IOS和Android上实现以下两种需求: 1,创建文件夹和文件,从数据库获取数据并写入到文件; 2,获取指定目录文件夹下文件,并读取文件数据; 先上效果图: 创建文件夹和文件,从数据库获取数据并写入到文件 获取指定目录...
  • fxp850899969
  • fxp850899969
  • 2018-01-27 21:36
  • 3378

cordova ---- 获取手机设备信息 IMEI

我们的项目是ionic。。。 此功能是利用Phonegap的Device 提供有: device.model     :返回设备的模型或产品的名称 device.cordova  :返回cordova的版本 device.uuid &...
  • liayn523
  • liayn523
  • 2017-03-31 18:08
  • 3102

Cordova各个插件使用介绍系列(六)—$cordovaDevice获取设备的相关信息

详情请看:Cordova各个插件使用介绍系列(六)—$cordovaDevice获取设备的相关信息 在项目中需要获取到当前设备,例如手机的ID,联网状态,等,然后这个Cordova里有这个插件可以用,就是$cordovaDevice,下面我来介绍一下怎么来使用它: 一、添加命令: cordov...
  • xiaojun_zxj
  • xiaojun_zxj
  • 2016-03-25 11:14
  • 4974
    个人资料
    • 访问:16731次
    • 积分:286
    • 等级:
    • 排名:千里之外
    • 原创:10篇
    • 转载:3篇
    • 译文:0篇
    • 评论:23条
    最新评论