6.0以上 授权方式改变
在API23以下的系统采取的权限机制是安装APP时全部一次性询问,而在API23及以上版本修改了权限机制,用户可直接在运行时管理应用权限,对于不需要的用到的权限可以拒绝授权。
官方文档:https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html
权限分类
Google把所有权限分为正常权限和危险权限
- 正常权限基本不会涉及到用户隐私,不需要用户授权
- 危险权限会涉及到用户隐私,需要用户授权才能使用的
正常权限
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
GET_PACKAGE_SIZE
INSTALL_SHORTCUT
INTERNET
KILL_BACKGROUND_PROCESSES
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_INSTALL_PACKAGES
SET_ALARM
SET_TIME_ZONE
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
UNINSTALL_SHORTCUT
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
危险权限
CALENDAR
READ_CALENDAR
WRITE_CALENDAR
CAMERA
CAMERA
CONTACTS
READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS
LOCATION
ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
MICROPHONE
RECORD_AUDIO
PHONE
READ_PHONE_STATE
CALL_PHONE
READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
SENSORS
BODY_SENSORS
SMS
SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
STORAGE
READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE
关于危险权限分组–因为6.0以上版本每次请求授权,并不是一个个权限的询问的,而是一组一组权限询问的,当你允许了这一组权限,组内的所有权限都会被允许,这样更加方便
权限询问封装方法
- Github上的一个开源框架–RxPermission
- 自己封装,写点简单的代码即可实现
具体怎么封装
- 创建BaseActivity, 继承AppCompatActivity
package com.example.pokawing.root60;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;
public class BaseActivity extends AppCompatActivity {
private static PermissionListener mListener;
//获取当前活动
private static Activity topActivity = ActivityController.getTopActivity();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//活动启动时,添加活动到activity管理类中
ActivityController.addActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
//活动销毁时,从活动管理中移走该活动
ActivityController.removeActivity(this);
}
public static void requestRuntimePermission(String[] permissions,PermissionListener listener){
if (topActivity == null) {
return;
}
mListener = listener;
List<String> permissionList = new ArrayList<>();
for (String permission : permissions){
//如果请求的权限被拒绝了,就把该权限添加到list中
if (ContextCompat.checkSelfPermission(topActivity,permission) != PackageManager.PERMISSION_GRANTED) {
permissionList.add(permission);
}
}
if (!permissionList.isEmpty()){
//有权限被拒绝,就会请求获取权限
ActivityCompat.requestPermissions(topActivity,permissionList.toArray(new String[permissionList.size()]),1);
} else {
doSomething();
//所有权限都获得了
mListener.onGrant();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 1:
if (grantResults.length > 0) {
List<String> deniedPermissions = new ArrayList<>();
for (int i = 0;i < grantResults.length;i++) {
int grantResult = grantResults[i];
String permission = permissions[i];
if (grantResult != PackageManager.PERMISSION_GRANTED) {
deniedPermissions.add(permission);
//把所有被拒绝的权限都放进一个list里面
}
}
if (deniedPermissions.isEmpty()) {
//如果全部都被授权了,就调用监听器onGrant方法
mListener.onGrant();
} else {
//如果有被拒绝授权的权限,就调用监听器传入被拒绝的权限的名字的列表
mListener.onDenied(deniedPermissions);
}
}
break;
default:
break;
}
}
public static void doSomething(){
//自己制定的任意方法
}
}
- 创建监听器,接口类
package com.example.pokawing.root60;
import java.util.List;
public interface PermissionListener {
void onGrant();
//要知道是哪个权限被拒绝了
void onDenied(List<String> deniedPermission);
}
- 创建活动管理类
package com.example.pokawing.root60;
import android.app.Activity;
import java.util.ArrayList;
import java.util.List;
/**
* activity管理类
*/
public class ActivityController {
private static List<Activity> list;
private static Activity topActivity = null;
public ActivityController(){
list = new ArrayList<>();
}
public static void addActivity(Activity activity){
list.add(activity);
}
public static Activity getActivity(int position){
return list.get(position);
}
public static void removeActivity(Activity activity){
list.remove(activity);
}
public static Activity getTopActivity(){
if (list.isEmpty()){
return topActivity;
} else {
topActivity = list.get(list.size() - 1);
return topActivity;
}
}
}
- 创建Utils类,重写监听器里的方法,用Toast方便反馈授权情况
package com.example.pokawing.root60;
import android.app.Activity;
import android.widget.Toast;
import java.util.List;
/**
* 如果在不继承activity的类中使用该封装方法,创建这个Utils类
*/
public class Utils {
private Activity activity;
public Utils(Activity activity) {
this.activity = activity;
}
public void requestPermission(String[] permissions) {
BaseActivity.requestRuntimePermission(permissions,new PermissionListener() {
@Override
public void onGrant() {
Toast.makeText(activity, "所有权限都同意了", Toast.LENGTH_SHORT).show();
}
@Override
public void onDenied(List<String> deniedPermission) {
for (String permission : deniedPermission) {
Toast.makeText(activity,"被拒绝权限:"+permission,Toast.LENGTH_SHORT).show();
}
}
});
}
}
- 在MainActicity中直接使用,继承BaseActivity,我就只在layout中写了一个button,点击button开始进行请求授权
package com.example.pokawing.root60;
import android.Manifest;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
public class MainActivity extends BaseActivity implements View.OnClickListener{
private Button bt;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt= (Button) findViewById(R.id.button);
bt.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Utils permissionUtils = new Utils(this);
//从这里的string数组中传入要申请的权限
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE
,Manifest.permission.CAMERA,Manifest.permission.CALL_PHONE};
permissionUtils.requestPermission(permissions);
}
}