本文共 11497 字,大约阅读时间需要 38 分钟。
android应用默认是不使用任何的权限的,当我们使用某些功能的时候,会要求用户添加某些权限,方可使用。例如请求网络和写入文件等等。当我们使用某些权限的时候,只需要在Manifest使用添加权限,例如:
我们为程序添加了读取联系人权限,当用户请求查看联系人时,程序会弹出请求权限的对话框进行询问是否对App进行授权(Android6.0以上并且targetSdkVersion为23会弹出提示框,后面会进行讲解)。
对于安全权限来说,这样的权限使用不会对用户造成用户隐私的泄露,系统会自动在安装时授予该应用程序的权限。例如用户设置时区的权限就是安全的权限。
安全权限列表: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_IGNORE_BATTERY_OPTIMIZATIONS 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
对于危险权限来说,会涉及到用户的隐私信息和数据的存储,例如读取联系人权限和对用户文件读写权限。
像危险权限,采用动态申请的方式。用户在使用的时候应该先检查用户是否已经对改权限进行授权,之后方可使用,如何操作后文会详细讲解。 注意:不管是安全权限和普通权限都应该在AndroidManifest文件中进行注册。在Android权限中,任何权限都属于权限组,当用户是运行的设备是Android6.0(API23),并且应用的targetSdkVersion 是 23 或更高版本,则当用户请求危险权限时系统会发生以下行为:
任何权限都可属于一个权限组,包括正常权限和应用定义的权限。但权限组仅当权限危险时才影响用户体验。可以忽略正常权限的权限组。
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
当处于这种情况下,用户安装App时,用户可以不授权任何权限即可安装。但是如果不是这种情况(如Android为6.0一下,或者targetSdkVersion为23以下),用户在安装应用的时候必须全部同意所有的权限,才可以安装。
用户运行程序时,当用户的接下来要执行一个危险的权限,例如:像程序中写入一个文件,这时我们必须要检查用户是否已经拥有了这个权限,如果用户没有开启这个权限并且还执行了相应的操作,程序会出现报错或者警告提示。
所以我们应该采取如下方案:
a、检查用户是否具有某个权限可以调用checkSelfPermission()方法
这里介绍两个常量
/**
* Permission check result: this is returned by {@link #checkPermission} * if the permission has been granted to the given package. */ 权限已经授权 public static final int PERMISSION_GRANTED = 0;/** * Permission check result: this is returned by {@link #checkPermission} * if the permission has not been granted to the given package. */ 权限没有授权public static final int PERMISSION_DENIED = -1;
例:
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { System.out.println("用户没有权限了"); } else { System.out.println("已经有权限了"); }
当已经授权了,我们执行相应的操作即可,例如查看联系人、读写文件等操作。
b、当用户没有授权,我们应该发出请求授权的请求,去让用户手动授权
//第一次请求用户去授权
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_CONTACTS}, 2);注意,上图是第一次请求授权,这个弹框是系统的弹框,用户不能去更改
c、当用户每次调用requestPermissions时,都会回调onRequestPermissionsResult方法。
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {}
第一个参数:requestCode即为requestPermissions请求的第三个参数,我们可以在这里判断是在哪进行请求的
第二个参数:permissions[]从名字就可以看出来这个是用户请求权限时回调的数组,里面存放的是你请求的所有权限。 第三个参数:int[] grantResults第三个参数与第二个参数相对应,分别为第二个参数所对应的是否用户授权的值,授权为0,没有授权为1。例如(请求了单个权限):
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_CONTACTS}, 2);
在onRequestPermissionsResult方法中:
requestCode=2; permissions=android.permission.READ_CONTACTS grantResults=-1(点击拒绝)例如(请求了多个权限):
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_CONTACTS
,Manifest.permission.WRITE_EXTERNAL_STORAGE}, 2);在onRequestPermissionsResult方法中:
requestCode=2; permissions=android.permission.READ_CONTACTS,android.permission.WRITE_EXTERNAL_STORAGE grantResults=-1(点击拒绝),0(点击了允许)@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { int flag = -1; switch (requestCode) { case 2: //单个权限 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ // 用户同意权限 } else { // 用户不同意权限 } //多个权限 if (grantResults.length > 0) { for (int i = 0; i < grantResults.length; i++) { if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { flag = 0; } else { flag=-1; break; } } } if (flag==0){ // 用户同意权限 }else { // 用户不同意权限 } } } }
d、shouldShowRequestPermissionRationale,该方法返回一个boolean类型的值这个方法有一个特点,当用户第一次对某一个权限点击拒绝的时候,该方法返回true,当第二次用户再次点击拒绝的时候并且勾选了[不在提示]对话框。该方法返回的是false;
上图为第二次申请权限,因为系统已经检测到你已经拒绝过一次权限,所以第二次会弹出不在提示选框
当我们第二次请求权限的时候,我们可以在onRequestPermissionsResult方法中,观察是否为false,并且提醒用户,该权限的重要性,如果无法开启这个权限会严重影响app的使用。
完整代码逻辑,这里讲述的是一个页面中,同时申请了两个权限,缺一不可的情况下,用户可以根据自己的需求进行增加和删除。
package com.example.mac.studypermission1;import android.Manifest;import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.content.pm.PackageManager;import android.net.Uri;import android.provider.Settings;import android.support.v4.app.ActivityCompat;import android.support.v4.content.ContextCompat;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.Toast;public class MainActivity extends AppCompatActivity { private Button bt; private Button bt1; private String[] permissions = new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_EXTERNAL_STORAGE}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt = (Button) findViewById(R.id.bt); bt1 = (Button) findViewById(R.id.bt1); //第二次授权 bt1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 2); } }); //第一次授权 bt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { boolean allPermissions = false; for (int i = 0; i < permissions.length; i++) { if (ContextCompat.checkSelfPermission(MainActivity.this, permissions[i]) == PackageManager.PERMISSION_GRANTED) { allPermissions = true; } else { allPermissions = false; break; } } if (allPermissions == false) { //应该请求授权 ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_CONTACTS , Manifest.permission.WRITE_EXTERNAL_STORAGE}, 2); } else { System.out.println("以授权"); } } }); } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { int flag = -1; switch (requestCode) { case 2: { if (grantResults.length > 0) { for (int i = 0; i < grantResults.length; i++) { if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { flag = 0; } else { flag = -1; break; } } } if (flag == 0) { System.out.println("以授权"); } else { // 用户不同意权限,第二次shouldShowRequestPermissionRationale为false boolean isJump = false; for (int i = 0; i < permissions.length; i++) { //第二次还是拒绝权限,这时shouldShowRequestPermissionRationale为false,应该提醒用户,此权限的重要性 if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, permissions[i]) == false) { isJump = true; } else { isJump = false; break; } } if (isJump) { AlertDialog.Builder builder = new AlertDialog.Builder( MainActivity.this); builder.setTitle("提示"); builder.setMessage("这是一个很重要的权限!"); builder.setIcon(R.mipmap.ic_launcher); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "确定被点击", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivityForResult(intent, 10); dialog.dismiss(); } }); builder.setCancelable(false); builder.show(); } } } } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { boolean allPermissions = false; for (int i = 0; i < permissions.length; i++) { //这里从App的设置中心返回时,应该二次检察权限 if (ContextCompat.checkSelfPermission(MainActivity.this, permissions[i]) == PackageManager.PERMISSION_GRANTED) { allPermissions = true; } else { allPermissions = false; break; } } if (allPermissions == false) { //应该请求授权 ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_CONTACTS , Manifest.permission.WRITE_EXTERNAL_STORAGE}, 2); } else { System.out.println("以授权"); } super.onActivityResult(requestCode, resultCode, data); }}
则系统会在用户安装应用时要求用户授予权限。如果将新权限添加到更新的应用版本,系统会在用户更新应用时要求授予该权限。用户一旦安装应用,他们撤销权限的唯一方式是卸载应用。
微信公众号:
QQ群:365473065