今天来看一下Android中的事件分发以及动态权限
Android的权限机制从第一个版本开始就已经存在,但之前的Android权限机制在保护用户安全和隐私等方面起到的作用有限,为此,Android开发团队在6.0系统中引用了运行时权限的功能
共分为 9 组,每组只要有一个权限申请成功了,就默认整组权限都可以使用了
//获取通讯录权限
group:android.permission-group.CONTACTS
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
//获取拨打电话的权限
group:android.permission-group.PHONE
permission:android.permission.READ_CALL_LOG
permission:android.permission.READ_PHONE_STATE
permission:android.permission.CALL_PHONE
permission:android.permission.WRITE_CALL_LOG
permission:android.permission.USE_SIP
permission:android.permission.PROCESS_OUTGOING_CALLS
permission:com.android.voicemail.permission.ADD_VOICEMAIL
//获取日历的权限
group:android.permission-group.CALENDAR
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDAR
group:android.permission-group.CAMERA
permission:android.permission.CAMERA
//获取传感器的权限
group:android.permission-group.SENSORS
permission:android.permission.BODY_SENSORS
group:android.permission-group.LOCATION
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATION
//获取文件读写的权限
group:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
//获取麦克风的权限
group:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIO
//获取短信的权限
group:android.permission-group.SMS
permission:android.permission.READ_SMS
permission:android.permission.RECEIVE_WAP_PUSH
permission:android.permission.RECEIVE_MMS
permission:android.permission.RECEIVE_SMS
permission:android.permission.SEND_SMS
permission:android.permission.READ_CELL_BROADCASTS
只需要在manifest.xml中添加的权限
android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_NOTIFICATION_POLICY
android.permission.ACCESS_WIFI_STATE
android.permission.ACCESS_WIMAX_STATE
android.permission.BLUETOOTH
android.permission.BLUETOOTH_ADMIN
android.permission.BROADCAST_STICKY
android.permission.CHANGE_NETWORK_STATE
android.permission.CHANGE_WIFI_MULTICAST_STATE
android.permission.CHANGE_WIFI_STATE
android.permission.CHANGE_WIMAX_STATE
android.permission.DISABLE_KEYGUARD
android.permission.EXPAND_STATUS_BAR
android.permission.FLASHLIGHT
android.permission.GET_ACCOUNTS
android.permission.GET_PACKAGE_SIZE
android.permission.INTERNET
android.permission.KILL_BACKGROUND_PROCESSES
android.permission.MODIFY_AUDIO_SETTINGS
android.permission.NFC
android.permission.READ_SYNC_SETTINGS
android.permission.READ_SYNC_STATS
android.permission.RECEIVE_BOOT_COMPLETED
android.permission.REORDER_TASKS
android.permission.REQUEST_INSTALL_PACKAGES
android.permission.SET_TIME_ZONE
android.permission.SET_WALLPAPER
android.permission.SET_WALLPAPER_HINTS
android.permission.SUBSCRIBED_FEEDS_READ
android.permission.TRANSMIT_IR
android.permission.USE_FINGERPRINT
android.permission.VIBRATE
android.permission.WAKE_LOCK
android.permission.WRITE_SYNC_SETTINGS
com.android.alarm.permission.SET_ALARM
com.android.launcher.permission.INSTALL_SHORTCUT
com.android.launcher.permission.UNINSTALL_SHORTCUT
第一步需要检测是否授权
//检测是否有写sd卡的权限
int code = ActivityCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE);
if(code == PackageManager.PERMISSION_DENIED){
//未授权
}
如果没有授权则申请授权
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION);
最后处理授权结果:在Activity中重写onRequestPermissionsResult
// 授权结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSION) {
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
// 用户拒绝
// 检测是否有必要跟用户说明为什么要申请这个权限,如果拒绝了会有什么结果
if (ActivityCompat.shouldShowRequestPermissionRationale(WelcomeActivity.this, permissions[0])) {
// 解释一下
AlertDialog.Builder b = new AlertDialog.Builder(WelcomeActivity.this);
b.setTitle(" 警告 ")
.setMessage(" 不授权将影响应用的正常使用 , 是否需要重新授权 ?")
.setPositiveButton(" 是 ", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(WelcomeActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION);
}
}).setNegativeButton(" 否 ", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
b.show();
}
} else {
toMainActivity();
}
}
}
1 、封装了授权检测
2 、授权分进入设置 –> 应用详情 –> 权限这种打开方式 以及 直接使用授权申请方法两种
3 、对结果同一处理为 RESULT_OK 就是成功 否则就是授权失败
/**
* 申请授权的 Activity ( 1 、可以进入设置打开或者关闭权限, 2 、直接使用授权申请方法来申请)
* github PermissionGrant
*/
public class PermissionActivity extends Activity {
private static final int REQUEST_SETTINGS = 1;
private static final int REQUEST_PERMISSION = 2;
private String[] permissions;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent it = getIntent();
if (it == null || !it.hasExtra("permissions")) {
finish();
return;
}
permissions = it.getStringArrayExtra("permissions");
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_permission);
findViewById(R.id.btn_setting).setOnClickListener(btnClick);
findViewById(R.id.btn_grant).setOnClickListener(btnClick);
}
/**
* 启动授权界面
*
* @param context
* @param requestCode
* @param permissions
*/
public static void startPermissionActivity(Activity context, int requestCode, String... permissions) {
Intent it = new Intent(context, PermissionActivity.class);
it.putExtra("permissions", permissions);
context.startActivityForResult(it, requestCode);
}
private View.OnClickListener btnClick = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_setting:
// 进入设置打开权限
Intent it = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
// 配置跳转要查看的应用的包名 packege:com.xykj.filemanager
it.setData(Uri.parse("package:" + getApplication().getPackageName()));
startActivityForResult(it, REQUEST_SETTINGS);
break;
case R.id.btn_grant:
// 使用申请授权方法
ActivityCompat.requestPermissions(PermissionActivity.this, permissions, REQUEST_PERMISSION);
break;
}
}
};
// 授权结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSION) {
int deniedIndex = getFirstDeniedIndex(grantResults);
if (deniedIndex != -1) {
// 用户拒绝
// 检测是否有必要跟用户说明为什么要申请这个权限,如果拒绝了会有什么结果
if(ActivityCompat.shouldShowRequestPermissionRationale(PermissionActivity.this,
permissions[deniedIndex])) {
// 解释一下
AlertDialog.Builder b = new AlertDialog.Builder(PermissionActivity.this);
b.setTitle(" 警告 ")
.setMessage(" 不授权将影响应用的正常使用 , 是否需要重新授权 ?")
.setPositiveButton(" 是 ", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(
PermissionActivity.this,
PermissionActivity.this.permissions,
REQUEST_PERMISSION);
}
}).setNegativeButton(" 否 ", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
b.show();
}
} else {
setResult(RESULT_OK);
finish();
}
}
}
private int getFirstDeniedIndex(int[] grantResults) {
int len = grantResults.length;
for (int i = 0; i < len; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
return i;
}
}
return -1;
}
/**
* 检测是否授权
*
* @param context
* @param permissions
* @return
*/
public static boolean isGrantedPermission(Context context, List permissions) {
if (Build.VERSION.SDK_INT < 23) {
return true;
}
int size = permissions.size();
for (int i = 0; i < size; i++) {
String name = permissions.get(i);
// 一个个的检测授权情况,如果发现了其中某一个未授权,返回 false 表示检测授权失败
int code = ActivityCompat.checkSelfPermission(context, name);
if (code == PackageManager.PERMISSION_DENIED) {
return false;
}
String op = AppOpsManagerCompat.permissionToOp(name);
if (TextUtils.isEmpty(op)) {
continue;
}
code = AppOpsManagerCompat.noteProxyOp(context, op, context.getApplicationContext().getPackageName());
if (code != AppOpsManagerCompat.MODE_ALLOWED) {
return false;
}
}
return true;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_SETTINGS) {
if (isGrantedPermission(PermissionActivity.this, permissions)) {
setResult(RESULT_OK);
} else {
setResult(RESULT_CANCELED);
}
finish();
}
}
}
为了方便该授权Activity的运用,可以将其显示为Dialog
使用:
if (!PermissionActivity.isGrantedPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// 未授权,申请授权
PermissionActivity.startPermissionActivity(this,REQUEST_PERMISSION,Manifest.permission.WRITE_EXTERNAL_STORAGE);
} else {
// 成功
...
}
结果处理
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
// 授权成功
}else{
// 授权失败
}
}
这里我后续会慢慢改进