android 6.0之前的设备,只需要这两条权限
- <uses-permission android:name="android.permission.BLUETOOTH" />
- <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
6.0及后续版本:使用蓝牙扫描,来需要添加如下的权限,且该权限还需要在使用时动态申请:
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
3) 动态申请权限
//判断是否有权限if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//请求权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION);
//判断是否需要 向用户解释,为什么要申请该权限
if(ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_CONTACTS)) {
Toast.makeText(this, "shouldShowRequestPermissionRationale", Toast.LENGTH_SHORT).show();
}
}
/权限申请结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[]
grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
引申问题:
在SDK23以前,我们开发的时候要是想要申请权限,直接在AndroidManifest中配置一下就好了,但到了在SDK23+开发的话,我们要是还是这样,当涉及到一些危险权限(Dangerous Permissions)时,程序就又可能会出现崩溃了,这时候需要我们在操作发生之前让用户进行权限授予才能进行下一步的操作。
如果你的app TargetSDK设置在了23以下那么在6.0+系统中运行是不会崩溃的,当然你也可以TargetSDK一直设置在23以下,这样的话你就不需要考虑动态授权的问题了。
下面这张图来自官方文档,给我们展示了哪些权限需要在运行是进行授权。
危险权限
Permission Group | Permissions |
---|---|
android.permission-group.CALENDAR |
|
android.permission-group.CAMERA |
|
android.permission-group.CONTACTS |
|
android.permission-group.LOCATION |
|
android.permission-group.MICROPHONE |
|
android.permission-group.PHONE |
|
android.permission-group.SENSORS |
|
android.permission-group.SMS |
|
android.permission-group.STORAGE |
|
这张图中提及的权限不仅需要在AndroidManifest中进行配置,在SDK23以上开发的时候还需要在运行时让用户进行授权。
使用方法
- 将targetSdkVersion设置为>= 23,这样的话,在项目的开发种涉及到权限问题时则必须按照Android官方的要求,动态的申请权限。
当然,如果你不想这么做的话,就将将targetSdkVersion设置为设置为 22或22以下 就好了
- 在AndroidManifest.xml中申请你需要的权限,包括普通权限和需要申请的特殊权限。
- 接下来就是来申请权限了
- 1.检查是否由此权限:checkSelfPermission(),如果已经开启,则直接进行需要的操作。
- 2.如果没有开启,则要判断是否需要向用户解释为何申请权限的原因:shouldShowRequestPermissionRationale。
- 3.如果需要(返回true),则弹出对话框提示用户申请权限原因,用户确认后申请权限:requestPermissions(),如果不需要(即返回false),则直接申请权限:requestPermissions()。
例子
这里来演示下模拟调用系统相机时需要申请的权限
public class MainActivity extends AppCompatActivity {
private Button button;
private TextView textView;
private final int CAMERA_REQUESTCODE = 0X11;//与回调有关
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
intEvent();
}
private void initView() {
button = (Button) findViewById(R.id.button);
textView = (TextView) findViewById(R.id.textView);
}
private void intEvent() {
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
takePhoto();
}
});
}
private void takePhoto() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
/**
* 第一次请求权限时,用户如果拒绝,下一次请求调用shouldShowRequestPermissionRationale()方法返回true
* 向用户解释为什么需要这个权限
*/
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
new AlertDialog.Builder(this)
.setMessage("申请相机权限")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//申请相机权限
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.CAMERA}, CAMERA_REQUESTCODE);
}
}).show();
} else {
//申请相机权限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},
CAMERA_REQUESTCODE);
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == CAMERA_REQUESTCODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
textView.setText("相机权限已经申请");
} else {
/**
* 用户勾选了不在询问
* 提示用户手动打开权限
*/
if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
Toast.makeText(this, "相机权限已经禁止", Toast.LENGTH_LONG).show();
}
}
}
}
}
当然,别忘了在AndroidManifest中配置相机权限
<uses-permission android:name="android.permission.CAMERA" />
相关API介绍
- REQUESTCODE :用来进行回调处理,因为申请权限是有回调结果的。
- ContextCompat.checkSelfPermission :主要用于检测某个权限是否已经被授予,方法参数为(context,需要检测的权限),方法返回值为PackageManager.PERMISSION_DENIED或者PackageManager.PERMISSION_GRANTED,当返回PackageManager.PERMISSION_DENIED时需要调用API进行权限申请。
- ActivityCompat.requestPermissions :用于权限的申请,方法参数为(context,需要申请的权限数组,自定义的请求码),系统会弹出一个申请权限的对话框。
- shouldShowRequestPermissionRationale :Android原生系统中,如果第二次弹出权限申请的对话框,会出现“以后不再弹出”的提示框,如果用户勾选了,你再申请权限,则shouldShowRequestPermissionRationale返回true,意思是说要给用户一个 解释,告诉用户为什么要这个权限。但是在实际开发中我们需要注意国内一些厂商定制的系统,比如在申请权限时,如果用户选择了拒绝,则不会再弹出对话框,所以我就在回调里面进行处理,如果用户拒绝了这个权限,则打开本应用信息界面,由用户自己手动开启这个权限。