android应用中增加权限判断

时间:2023-03-08 21:52:05
android应用中增加权限判断

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

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

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

android应用中增加权限判断 这个界面的处理代码在 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();
} }