前言
在很久以前,即 Android 6.0 (API 23) 得时候。
应用的权限只要你在AndroidManifest.xml文件中注册权限,安装时则会全部授予,需要的时候 自动唤起授权弹窗询问用户。
但后来,在 Android 6.0 或更高版本对权限进行了分类,对某些涉及到用户隐私的高危权限,不单单要在AndroidManifest.xml文件中注册权限,还要根据用户的需要动态授予(即手动唤起授权弹窗询问用户)。
另外 用户同意过的危险权限还可以在设置中进行修改,比如再次手动授权和取消授权。
正常权限
涵盖应用需要访问其沙盒外部数据或资源,但对用户隐私或其他应用操作风险很小的区域。这些权限在应用安装时授予,运行时不再询问用户。例如: 网络访问、WIFI状态、音量设置等。
危险权限
涵盖应用需要涉及用户隐私信息的数据或资源,或者可能对用户存储的数据或其他应用的操作产生影响的区域。例如: 读取通讯录、读写存储器数据、获取用户位置、摄像头、录音等。如果应用声明需要这些危险权限,则必须在运行时明确告诉用户,让用户手动授予。
具体权限列表可以去看看官网权限介绍
动态申请权限
首先需要 在AndroidManifest.xml
清单中,列出所需权限
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- 权限start-->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 权限start-->
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.BlutoothList"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
单个权限
页面布局activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="409dp"
android:layout_height="100dp"
android:orientation="vertical"
android:gravity="center"
tools:ignore="MissingConstraints">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取相机权限" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取录音权限" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
页面逻辑MainActivity.java
package com.example.blutoothlist;
import android.Manifest;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
public class MainActivity extends AppCompatActivity {
private final int PERMISSIONS_CODE_CAMERA = 0;
private final int PERMISSIONS_CODE_RECORD_AUDIO = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//监听按钮点击
Button btn1 = findViewById(R.id.button1);
Button btn2 = findViewById(R.id.button2);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 动态获取权限
ActivityCompat.requestPermissions(MainActivity3.this, new String[]{Manifest.permission.CAMERA}, PERMISSIONS_CODE_CAMERA);
}
});
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 动态获取权限
ActivityCompat.requestPermissions(MainActivity3.this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSIONS_CODE_RECORD_AUDIO);
}
});
}
/**
* @param requestCode 权限申请组id 自定义的
* @param permissions 申请权限组内容 是个数组
* @param grantResults 存储着权限授权结果 也是个数组
* @deprecated grantResults和permissions一一对应, 被拒绝则为-1,被同意则为0
*/
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case PERMISSIONS_CODE_CAMERA:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "获得相机权限成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "您拒绝了相机权限", Toast.LENGTH_SHORT).show();
}
break;
case PERMISSIONS_CODE_RECORD_AUDIO:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "获得录音权限成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "您拒绝了录音权限", Toast.LENGTH_SHORT).show();
}
break;
}
}
}
效果
权限组
页面布局activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="409dp"
android:layout_height="100dp"
android:orientation="vertical"
android:gravity="center"
tools:ignore="MissingConstraints">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取相机和录音权限" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
页面逻辑MainActivity.java
package com.example.blutoothlist;
import android.Manifest;
import android.app.AlertDialog;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import java.util.HashMap;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
private final int PermissionsCode_CameraAndAudio = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//监听按钮点击
Button btn = findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 动态获取权限
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}, PermissionsCode_CameraAndAudio);
}
});
}
/**
* @param requestCode 权限申请组id 自定义的
* @param permissions 申请权限组内容 是个数组
* @param grantResults 存储着权限授权结果 也是个数组
* @deprecated grantResults和permissions一一对应, 被拒绝则为-1,被同意则为0
*/
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case PermissionsCode_CameraAndAudio:
Map map = new HashMap();
for (int i = 0; i < permissions.length; i++) {
String permission = permissions[i]; // 权限名
int permissionResult = grantResults[i]; // 权限结果
map.put(permission, permissionResult == PackageManager.PERMISSION_GRANTED ? true : false);
}
new AlertDialog.Builder(this)
//标题
.setTitle("权限组获得权限情况")
//内容
.setMessage(map.toString())
//图标
.setIcon(R.mipmap.ic_launcher)
.setPositiveButton("确认", null)
.create()
.show();
break;
}
}
}
效果