Android 6.0 为了保护用户隐私,将一些权限的申请放在了应用运行的时候去申请, 比如以往的开发中,开发人员只需要将需要的权限在清单文件中配置即可,安装后用户可以在设置中的应用信息中看到:XX应用以获取****权限。用户点击可以选择给应用相应的权限。此前的应用权限用户可以选择允许、提醒和拒绝。在安装的时候用户是已经知道应用需要的权限的。但是这样存在一个问题,就是用户在安装的时候,应用需要的权限十分的多(有些开发者为了省事,会请求一些不必要的权限或者请求全部的权限),这个时候用户在安装应用的时候也许并没有发现某些侵犯自己隐私的权限请求,安装之后才发现自己的隐私数据被窃取。其实Android6.0 动态权限一方面是为了广大用户考虑,另一方面其实是Google为了避免一些不必要的官司。下面就说一下Android6.0对权限的分割:
下面是对权限的总结:(此处内容摘抄自:http://blog.csdn.net/u011200604/article/details/52874599)
首先是大家感兴趣的危险权限
这类权限需要在需要的时候,需要我们动态申请,比如:当我们需要打开相机拍摄照片的时候需要我们通过代码的方式在需要的地方去申请权限。Android6.0中权限问题中我们需要注意的是:
1:由于权限API的问题,我们的Actiivty最好是AppCompatActivity类型的,也就是说在你的BaseActivity需要继承AppCompatActivity
2:权限是分组的,同一组的权限申请其中一个,同组的权限就全部都申请了
特殊权限 组:
CALENDAR 日历
CAMERA 相机
CONTACTS 联系人
LOCATION 定位
MICROPHONE 麦克相关,比如录音
PHONE 手机状态
SENSORS 传感器
SMS 短信
STORAGE 存储权限
具体的权限分组情况如下表:
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
普通权限的总结:
ACCESS_LOCATION_EXTRA_COMMANDS 定位权限
ACCESS_NETWORK_STATE 网络状态权限
ACCESS_NOTIFICATION_POLICY 通知 APP通知显示在状态栏
ACCESS_WIFI_STATE WiFi状态权限
BLUETOOTH 使用蓝牙权限
BLUETOOTH_ADMIN 控制蓝牙开关
BROADCAST_STICKY 粘性广播
CHANGE_NETWORK_STATE 改变网络状态
CHANGE_WIFI_MULTICAST_STATE 改变WiFi多播状态,应该是控制手机热点(猜测)
CHANGE_WIFI_STATE 控制WiFi开关,改变WiFi状态
DISABLE_KEYGUARD 改变键盘为不可用
EXPAND_STATUS_BAR 扩展bar的状态
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 删除快捷方式
以上这些只是普通权限,我们开发的时候,正常使用就行了,需要的权限在清单文件配置即可。
第一种:点击允许
第二种:点击拒绝,并再次点击拒绝+不在询问
视图层:
permission.xml
权限:
testPermission.java
public class testPermission extends Activity {
private static final int REQUEST_EXTERNAL_STORAGE = 1;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.permission);
}
public void get(View v){
String[] permissions;
//读取内存权限
permissions = new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE
};
if (checkPermission(Manifest.permission.READ_EXTERNAL_STORAGE)) {
//如果已经获得权限
String dir= Environment.getExternalStorageDirectory().getAbsolutePath();
Intent intent=new Intent(testPermission.this,FileManager.class);
intent.putExtra("dir",dir);
intent.putExtra("title","文件管理");
startActivity(intent);
}else{
//否则去获取权限
getPermission(Manifest.permission.READ_EXTERNAL_STORAGE,permissions);
}
}
//检查某个权限是否已经获得
private boolean checkPermission(String permission){
//检查权限(NEED_PERMISSION)是否被授权 PackageManager.PERMISSION_GRANTED表示同意授权
if (ActivityCompat.checkSelfPermission(this, permission)
== PackageManager.PERMISSION_GRANTED)
return true;
else
return false;
}
//获取权限
private void getPermission(String permission,String [] permissions) {
//申请权限
ActivityCompat.requestPermissions(
this,
permissions,
REQUEST_EXTERNAL_STORAGE);
//用户已经拒绝过一次,再次弹出权限申请对话框需要给用户一个解释
if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission))
Toast.makeText(this, "请开通相关权限,否则无法正常使用本应用!", Toast.LENGTH_SHORT).show();
}
/**
* 一个或多个权限请求结果回调
*
* @param requestCode
* @param permissions
* @param grantResults
*//当点击了不在询问,但是想要实现某个功能,必须要用到权限,可以提示用户,引导用户去设置
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
boolean hasAllGranted = true;
for (int i = 0; i < grantResults.length; ++i) {
if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
hasAllGranted = false;
//在用户已经拒绝授权的情况下,如果shouldShowRequestPermissionRationale返回false则
// 可以推断出用户选择了“不在提示”选项,在这种情况下需要引导用户至设置页手动授权
if (!ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i])) {
//解释原因,并且引导用户至设置页手动授权
new AlertDialog.Builder(this)
.setMessage("\r\n" +
"获取相关权限失败:xxxxxx,将导致部分功能无法正常使用,需要到设置页面手动授权")
.setPositiveButton("去授权", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//引导用户至设置页手动授权
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getApplicationContext().getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//引导用户手动授权,权限请求失败
Toast.makeText(testPermission.this,"权限获取失败",Toast.LENGTH_SHORT).show();
}
}).setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
//引导用户手动授权,权限请求失败
}
}).show();
} else {
//权限请求失败,但未选中“不再提示”选项
}
break;
}
}
if (hasAllGranted) {
}
}
}
FileManager.java//当权限获取成功时,跳到此activity;
public class FileManager extends Activity {
ListView listView;
TextView title;
String dir;
//用存放路劲
FileAdapter adapter;
//适配器
List dateList;
//File 数据
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.file_manager);
findVById();
init();
//初始化
}
private void findVById() {
listView=(ListView)findViewById(R.id.file_listview);
title=(TextView)findViewById(R.id.file_title);
}
//初始化
private void init() {
Intent intent=getIntent();
//获取Intent的,接收activity传来的值,
dir= intent.getStringExtra("dir");
//如果为null,dir的值为 :Environment.getExternalStorageDirectory().getAbsolutePath();
//这个路劲就是一般打开手机文件管理文件目录的路劲
if (dir!=null)
;
else
dir= Environment.getExternalStorageDirectory().getAbsolutePath();
//获取title:让其显示文件路劲:如Android>data>com......
if(intent.getStringExtra("title")!=null)
title.setText(intent.getStringExtra("title"));
else
title.setText("文件管理");
//为listView注册上下文菜单,当长按某一个文件出现菜单:
this.registerForContextMenu(listView);
dateList=new ArrayList<>();
adapter=new FileAdapter(this,getDate());
listView.setAdapter(adapter);
//listView 点击事件,当点击的文件为目录时,
// 把dir的值赋值为:dir+点击的目录,再次跳到此页,既可以达到循环,不要再去新建一个activity在现实:
// intent.putExtra("dir",dir+"/"+dateList.get(i).getName());
//intent.putExtra("title",title.getText()+">"+dateList.get(i).getName());
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> adapterView, View view, int i, long l) {
if(dateList.get(i).isDirectory())
{
Intent intent=new Intent(FileManager.this,FileManager.class);
intent.putExtra("dir",dir+"/"+dateList.get(i).getName());
intent.putExtra("title",title.getText()+">"+dateList.get(i).getName());
startActivity(intent);
}
}
});
}
//为上下文菜单添加菜单项
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.setHeaderTitle("文件操作");
menu.setHeaderIcon(R.drawable.ic_brightness_high_black_24dp);
menu.add(1,1,1,"复制");
menu.add(1,2,1,"粘贴");
menu.add(1,3,1,"剪切");
menu.add(1,4,1,"重命名");
}
//选中菜单项点击事件,这里就Toast一下,
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()){
case 1:
Toast.makeText(FileManager.this,"已复制",Toast.LENGTH_SHORT).show();
break;
case 2:
Toast.makeText(FileManager.this,"已粘贴",Toast.LENGTH_SHORT).show();
break;
case 3:
Toast.makeText(FileManager.this,"剪切",Toast.LENGTH_SHORT).show();
break;
case 4:
Toast.makeText(FileManager.this,"重命名",Toast.LENGTH_SHORT).show();
break;
}
return super.onContextItemSelected(item);
}
//获取dir下所有的文件
public List< File> getDate() {
File file=new File(dir);
if(file.exists())
{
File[] file1=file.listFiles();
for (File filename :
file1) {
dateList.add(filename);
}
}
return dateList;
}
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
public void myPermission() {
int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
// 没有权限就提示用户
ActivityCompat.requestPermissions(
this,
PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE
);
}
}
}