勤能补拙,熟能生巧,宁静致远

记录工作中的点滴积累,总结成长的步伐里程。

博客园 首页 新随笔 联系 订阅 管理

android6.0系统允许用户管理应用权限,可以关闭/打开权限。

所以需要在APP中增加权限判断,以免用户关闭相应权限后,APP运行异常。

以MMS为例,在系统设置——应用——MMS——权限——>关闭短信权限

 这个界面的处理代码在 android\packages\apps\PackageInstaller 中。

通过调试 PackageInstaller,可以知道短信权限对应是 permissionGroup:  android.permission-group.SMS

其中包含的具体permission:

  android.permission.READ_SMS,

  android.permission.RECEIVE_WAP_PUSH,

  android.permission.RECEIVE_MMS,

  android.permission.RECEIVE_SMS,

  android.permission.SEND_SMS,

  android.permission.READ_CELL_BROADCASTS

 

关闭短信权限后,MMS无法读取,收发信息。操作MMS还会出现报错现象。所以需要在MMS启动时增加权限判断。

查看PackageInstaller中关闭权限的处理

AppOpsManager mAppOps = context.getSystemService(AppOpsManager.class);
......
//
Disable the app op. mAppOps.setUidMode(permission.getAppOp(), uid, AppOpsManager.MODE_IGNORED); //将权限对应的操作标记为 AppOpsManager.MODE_IGNORED,使权限被限制

AppOpsManager 是专门管理 APP操作权限的, 所以用AppOpsManager来判断权限是否被允许。

AppOpsManager中定义了系统权限对应的int码,和string字符。可以直接拿来用

android\frameworks\base\core\java\android\app\AppOpsManager.java

/** @hide No operation specified. */
    public static final int OP_NONE = -1;
    /** @hide Access to coarse location information. */
    public static final int OP_COARSE_LOCATION = 0;
    /** @hide Access to fine location information. */
    public static final int OP_FINE_LOCATION = 1;
    /** @hide Causing GPS to run. */
    public static final int OP_GPS = 2;
    /** @hide */
    public static final int OP_VIBRATE = 3;
    /** @hide */
    public static final int OP_READ_CONTACTS = 4;
    /** @hide */
    public static final int OP_WRITE_CONTACTS = 5;
    /** @hide */
    public static final int OP_READ_CALL_LOG = 6;
    /** @hide */
    public static final int OP_WRITE_CALL_LOG = 7;
    /** @hide */
    public static final int OP_READ_CALENDAR = 8;
    /** @hide */
    public static final int OP_WRITE_CALENDAR = 9;
    /** @hide */
    public static final int OP_WIFI_SCAN = 10;
    /** @hide */
    public static final int OP_POST_NOTIFICATION = 11;
    /** @hide */
    public static final int OP_NEIGHBORING_CELLS = 12;
    /** @hide */
    public static final int OP_CALL_PHONE = 13;
    /** @hide */
    public static final int OP_READ_SMS = 14;
    /** @hide */
    public static final int OP_WRITE_SMS = 15;
    /** @hide */
    public static final int OP_RECEIVE_SMS = 16;
    /** @hide */
    public static final int OP_RECEIVE_EMERGECY_SMS = 17;
    /** @hide */
    public static final int OP_RECEIVE_MMS = 18;
    /** @hide */
    public static final int OP_RECEIVE_WAP_PUSH = 19;
    /** @hide */
    public static final int OP_SEND_SMS = 20;
    /** @hide */
    public static final int OP_READ_ICC_SMS = 21;
    /** @hide */
    public static final int OP_WRITE_ICC_SMS = 22;
    /** @hide */
    public static final int OP_WRITE_SETTINGS = 23;
    /** @hide */
    public static final int OP_SYSTEM_ALERT_WINDOW = 24;
    /** @hide */
    public static final int OP_ACCESS_NOTIFICATIONS = 25;
    /** @hide */
    public static final int OP_CAMERA = 26;
    /** @hide */
    public static final int OP_RECORD_AUDIO = 27;
    /** @hide */
    public static final int OP_PLAY_AUDIO = 28;
    /** @hide */
    public static final int OP_READ_CLIPBOARD = 29;
    /** @hide */
    public static final int OP_WRITE_CLIPBOARD = 30;
    /** @hide */
    public static final int OP_TAKE_MEDIA_BUTTONS = 31;
    /** @hide */
    public static final int OP_TAKE_AUDIO_FOCUS = 32;
    /** @hide */
    public static final int OP_AUDIO_MASTER_VOLUME = 33;
    /** @hide */
    public static final int OP_AUDIO_VOICE_VOLUME = 34;
    /** @hide */
    public static final int OP_AUDIO_RING_VOLUME = 35;
    /** @hide */
    public static final int OP_AUDIO_MEDIA_VOLUME = 36;
    /** @hide */
    public static final int OP_AUDIO_ALARM_VOLUME = 37;
    /** @hide */
    public static final int OP_AUDIO_NOTIFICATION_VOLUME = 38;
    /** @hide */
    public static final int OP_AUDIO_BLUETOOTH_VOLUME = 39;
    /** @hide */
    public static final int OP_WAKE_LOCK = 40;
    /** @hide Continually monitoring location data. */
    public static final int OP_MONITOR_LOCATION = 41;
    /** @hide Continually monitoring location data with a relatively high power request. */
    public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42;
    /** @hide Retrieve current usage stats via {@link UsageStatsManager}. */
    public static final int OP_GET_USAGE_STATS = 43;
    /** @hide */
    public static final int OP_MUTE_MICROPHONE = 44;
    /** @hide */
    public static final int OP_TOAST_WINDOW = 45;
    /** @hide Capture the device's display contents and/or audio */
    public static final int OP_PROJECT_MEDIA = 46;
    /** @hide Activate a VPN connection without user intervention. */
    public static final int OP_ACTIVATE_VPN = 47;
    /** @hide Access the WallpaperManagerAPI to write wallpapers. */
    public static final int OP_WRITE_WALLPAPER = 48;
    /** @hide Received the assist structure from an app. */
    public static final int OP_ASSIST_STRUCTURE = 49;
    /** @hide Received a screenshot from assist. */
    public static final int OP_ASSIST_SCREENSHOT = 50;
    /** @hide Read the phone state. */
    public static final int OP_READ_PHONE_STATE = 51;
    /** @hide Add voicemail messages to the voicemail content provider. */
    public static final int OP_ADD_VOICEMAIL = 52;
    /** @hide Access APIs for SIP calling over VOIP or WiFi. */
    public static final int OP_USE_SIP = 53;
    /** @hide Intercept outgoing calls. */
    public static final int OP_PROCESS_OUTGOING_CALLS = 54;
    /** @hide User the fingerprint API. */
    public static final int OP_USE_FINGERPRINT = 55;
    /** @hide Access to body sensors such as heart rate, etc. */
    public static final int OP_BODY_SENSORS = 56;
    /** @hide Read previously received cell broadcast messages. */
    public static final int OP_READ_CELL_BROADCASTS = 57;
    /** @hide Inject mock location into the system. */
    public static final int OP_MOCK_LOCATION = 58;
    /** @hide Read external storage. */
    public static final int OP_READ_EXTERNAL_STORAGE = 59;
    /** @hide Write external storage. */
    public static final int OP_WRITE_EXTERNAL_STORAGE = 60;
    /** @hide Turned on the screen. */
    public static final int OP_TURN_SCREEN_ON = 61;
    /** @hide Get device accounts. */
    public static final int OP_GET_ACCOUNTS = 62;
    /** @hide */
    public static final int _NUM_OP = 63;
//--------------------------------上面的int 类型标记了@hide,需要在源码下才能调用编译通过。对于普通APP,可以用下面的string 类型-----------------------------//
/** Access to coarse location information. */ public static final String OPSTR_COARSE_LOCATION = "android:coarse_location"; /** Access to fine location information. */ public static final String OPSTR_FINE_LOCATION = "android:fine_location"; /** Continually monitoring location data. */ public static final String OPSTR_MONITOR_LOCATION = "android:monitor_location"; /** Continually monitoring location data with a relatively high power request. */ public static final String OPSTR_MONITOR_HIGH_POWER_LOCATION = "android:monitor_location_high_power"; /** Access to {@link android.app.usage.UsageStatsManager}. */ public static final String OPSTR_GET_USAGE_STATS = "android:get_usage_stats"; /** Activate a VPN connection without user intervention. @hide */ @SystemApi public static final String OPSTR_ACTIVATE_VPN = "android:activate_vpn"; /** Allows an application to read the user's contacts data. */ public static final String OPSTR_READ_CONTACTS = "android:read_contacts"; /** Allows an application to write to the user's contacts data. */ public static final String OPSTR_WRITE_CONTACTS = "android:write_contacts"; /** Allows an application to read the user's call log. */ public static final String OPSTR_READ_CALL_LOG = "android:read_call_log"; /** Allows an application to write to the user's call log. */ public static final String OPSTR_WRITE_CALL_LOG = "android:write_call_log"; /** Allows an application to read the user's calendar data. */ public static final String OPSTR_READ_CALENDAR = "android:read_calendar"; /** Allows an application to write to the user's calendar data. */ public static final String OPSTR_WRITE_CALENDAR = "android:write_calendar"; /** Allows an application to initiate a phone call. */ public static final String OPSTR_CALL_PHONE = "android:call_phone"; /** Allows an application to read SMS messages. */ public static final String OPSTR_READ_SMS = "android:read_sms"; /** Allows an application to receive SMS messages. */ public static final String OPSTR_RECEIVE_SMS = "android:receive_sms"; /** Allows an application to receive MMS messages. */ public static final String OPSTR_RECEIVE_MMS = "android:receive_mms"; /** Allows an application to receive WAP push messages. */ public static final String OPSTR_RECEIVE_WAP_PUSH = "android:receive_wap_push"; /** Allows an application to send SMS messages. */ public static final String OPSTR_SEND_SMS = "android:send_sms"; /** Required to be able to access the camera device. */ public static final String OPSTR_CAMERA = "android:camera"; /** Required to be able to access the microphone device. */ public static final String OPSTR_RECORD_AUDIO = "android:record_audio"; /** Required to access phone state related information. */ public static final String OPSTR_READ_PHONE_STATE = "android:read_phone_state"; /** Required to access phone state related information. */ public static final String OPSTR_ADD_VOICEMAIL = "android:add_voicemail"; /** Access APIs for SIP calling over VOIP or WiFi */ public static final String OPSTR_USE_SIP = "android:use_sip"; /** Use the fingerprint API. */ public static final String OPSTR_USE_FINGERPRINT = "android:use_fingerprint"; /** Access to body sensors such as heart rate, etc. */ public static final String OPSTR_BODY_SENSORS = "android:body_sensors"; /** Read previously received cell broadcast messages. */ public static final String OPSTR_READ_CELL_BROADCASTS = "android:read_cell_broadcasts"; /** Inject mock location into the system. */ public static final String OPSTR_MOCK_LOCATION = "android:mock_location"; /** Read external storage. */ public static final String OPSTR_READ_EXTERNAL_STORAGE = "android:read_external_storage"; /** Write external storage. */ public static final String OPSTR_WRITE_EXTERNAL_STORAGE = "android:write_external_storage"; /** Required to draw on top of other apps. */ public static final String OPSTR_SYSTEM_ALERT_WINDOW = "android:system_alert_window"; /** Required to write/modify/update system settingss. */ public static final String OPSTR_WRITE_SETTINGS = "android:write_settings"; /** @hide Get device accounts. */ public static final String OPSTR_GET_ACCOUNTS = "android:get_accounts";

检查权限方法

public int checkOp(String op, int uid, String packageName) {
        return checkOp(strOpToOp(op), uid, packageName); //strOpToOp(op)将string码转为int码,相当于调用checkOp(int op, int uid, String packageName)
                                  //checkOp(int op, int uid, String packageName)是@hide的,所以只有源码环境下才能直接调用,编译。
}


下面是我写的MMS中检查权限的方法。

public static void mmsPermissionCheck(Context context){
        final String smsPermissionGroupName = "android.permission-group.SMS";
        final Handler handler = new Handler();
        final Context mContext = context;
        final Runnable showPermissonCheck = new Runnable() {
            public void run() {
                    new AlertDialog.Builder(mContext)
                            .setMessage(mContext.getString(R.string.check_mms_permission))
                            .setPositiveButton(android.R.string.ok, new OnClickListener() {
                                public void onClick(DialogInterface dialog, int which) {
                                    ((Activity)mContext).finish();
                                }
                            })
                            .setCancelable(false)
                            .create().show();
            }
        };
        PackageManager pm = context.getPackageManager();
        AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); //AppOpsManager 用来判断权限

        try {
            PackageInfo pkgInfo = pm.getPackageInfo(context.getPackageName(),PackageManager.GET_PERMISSIONS);
            for(PermissionGroupInfo permissionGroupInfo : pm.getAllPermissionGroups(0) ){
                Log.i("antoon", permissionGroupInfo.name);
            }
            /**
             * permissionGroup: android.permission-group.SMS
             * permission: android.permission.READ_SMS, android.permission.RECEIVE_WAP_PUSH,
             *             android.permission.RECEIVE_MMS, android.permission.RECEIVE_SMS,
             *             android.permission.SEND_SMS, android.permission.READ_CELL_BROADCASTS
             * if permission denied,  appOpsManager.checkOp(...) will return >=1
             */
            int resultCount = 0;
            for(PermissionInfo permissionInfo : pm.queryPermissionsByGroup(smsPermissionGroupName,0) ){
                Log.i("antoon", permissionInfo.name);
                int appOp = AppOpsManager.permissionToOpCode(permissionInfo.name);
                int result = appOpsManager.checkOp(appOp, pkgInfo.applicationInfo.uid, pkgInfo.packageName);
                Log.e("antoon", "result = " + result);
                resultCount += result;
            }
            if(resultCount > 1){
                handler.post(showPermissonCheck);
            }

        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

    }

 

 

 

 

posted on 2016-03-23 11:23  ^-^antoon^-^  阅读(5426)  评论(1编辑  收藏  举报