一,简介
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_CONTACTSgroup: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_VOICEMAILgroup:android.permission-group.CALENDAR
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDARgroup:android.permission-group.CAMERA
permission:android.permission.CAMERAgroup:android.permission-group.SENSORS
permission:android.permission.BODY_SENSORSgroup:android.permission-group.LOCATION
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATIONgroup:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGEgroup:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIOgroup: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 删除快捷方式
以上这些只是普通权限,我们开发的时候,正常使用就行了,需要的权限在清单文件配置即可。
三,demo
1,效果,分两种情况,
第一种:点击允许
第二种:点击拒绝,并再次点击拒绝+不在询问
2,代码:
视图层:
permission.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:layout_marginTop="200dp"android:id="@+id/btn_get2"android:layout_width="match_parent"android:layout_height="50dp"android:onClick="get"android:text="读取手机内存"/></LinearLayout>
权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
testPermission.java
public class testPermission extends Activity {private static final int REQUEST_EXTERNAL_STORAGE = 1;@Overrideprotected 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;elsereturn 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*//当点击了不在询问,但是想要实现某个功能,必须要用到权限,可以提示用户,引导用户去设置@Overridepublic 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() {@Overridepublic 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() {@Overridepublic void onClick(DialogInterface dialog, int which) {//引导用户手动授权,权限请求失败Toast.makeText(testPermission.this,"权限获取失败",Toast.LENGTH_SHORT).show();}}).setOnCancelListener(new DialogInterface.OnCancelListener() {@Overridepublic 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<File> dateList;//File 数据@Overrideprotected 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);elsedir= Environment.getExternalStorageDirectory().getAbsolutePath();//获取title:让其显示文件路劲:如Android>data>com......if(intent.getStringExtra("title")!=null)title.setText(intent.getStringExtra("title"));elsetitle.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() {@Overridepublic 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);}}});}//为上下文菜单添加菜单项@Overridepublic 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一下,@Overridepublic 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);}}
}