三三要成为安卓糕手
这些权限敏感度不高,在清单中声明即可
<uses-permission android:name="android.permission.INTERNET"/> //网络访问
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>//允许应用访问网络状态
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>//允许访问wifi
<uses-permission android:name="android.permission.WAKE_LOCK"/>//允许应用防止手机进入休眠状态
<uses-permission android:name="android.permission.VIBRATE"/>//允许应用手机震动
这些权限有一定敏感度,除了在清单中声明,还需要在代码中动态获取
ACCESS_FINE_LOCATION:访问精确的位置(使用 GPS 和网络提供的位置)
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
ACCESS_COARSE_LOCATION:访问粗略的位置(使用网络提供的位置)
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
READ_CONTACTS:读取联系人数据
<uses-permission android:name="android.permission.READ_CONTACTS"/>
WRITE_CONTACTS:写入联系人数据
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
READ_PHONE_STATE:读取电话状态(例如设备 ID、网络状态)
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
CALL_PHONE:直接拨打电话
<uses-permission android:name="android.permission.CALL_PHONE"/>
READ_CALL_LOG:读取通话记录
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
WRITE_CALL_LOG:写入通话记录
<uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
SEND_SMS:发送 SMS 短信
<uses-permission android:name="android.permission.SEND_SMS"/>
READ_SMS:读取 SMS 短信
<uses-permission android:name="android.permission.READ_SMS"/>
READ_EXTERNAL_STORAGE:读取外部存储的数据(在android13设备上,如果只是对媒体文件图片、视频、音频,那么可以只做单独的权限申请)
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
WRITE_EXTERNAL_STORAGE:写入外部存储的数据。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
访问图片文件
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
访问视频文件
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
访问音频文件
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
CAMERA:访问设备的相机。
<uses-permission android:name="android.permission.CAMERA"/>
RECORD_AUDIO:录制音频。
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
这类权限涉及到比较高的系统权限或者是用户隐私,应用内部不能直接获取,所以需要跳转系统设置页:
//SYSTEM_ALERT_WINDOW:允许应用在其他应用的上层显示窗口。用户需要在设置中手动授予这个权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Intentintent=newIntent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
//REQUEST_INSTALL_PACKAGES:允许应用安装其他 APK 文件。用户需要在设置中手动授予这个权限。
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
//WRITE_SETTINGS:允许应用修改系统设置。用户需要在设置中手动授予这个权限。
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
Intentintent=newIntent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
//ACCESS_NOTIFICATION_POLICY:允许应用访问或修改通知策略。用户需要在设置中手动授予这个权限
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>
Intent intent = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
startActivity(intent);
//MANAGE_EXTERNAL_STORAGE:允许应用访问所有外部存储文件。用户需要在设置中手动授予这个权限。
//安卓13(api版本33)开始,安卓引入“分区存储模式”以限制应用对存储文件的访问,当前这个权限几乎相当于自由读写所有文件
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivity(intent);
在清单文件中进行权限声明
public class MyPermissionActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
findViewById(R.id.btn_record).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int selfPermission = checkSelfPermission(Manifest.permission.RECORD_AUDIO);
if(selfPermission != PackageManager.PERMISSION_GRANTED){
requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO},200);
}else {
Toast.makeText(MyPermissionActivity.this, "录音权限已经获取过了", Toast.LENGTH_SHORT).show();
}
}
});
}
/**
* 处理用户返回的权限授权结果
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == 200){
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
Toast.makeText(MyPermissionActivity.this, "获取录音权限成功", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MyPermissionActivity.this, "获取录音权限失败", Toast.LENGTH_SHORT).show();
}
}
}
}
获取权限,需要传参permission;
audio [ˈɔːdiəʊ] 声音的
这是一个常量,这里还有很多权限对应的常量值
PackageManager.PERMISSION_GRANTED
被授权成功的意思,相对应的PackageManager.PERMISSION.DENIED
denied [dɪ’naɪəd] 拒绝 grant 授权
requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO},200);
既然有请求码,自然少不了用户处理完权限申请这件事,安卓接收结果的方法
grantResults放着返回的结果集合,这里内部只是简单的用弹窗处理了一下显示结果
场景:当用户勾选不在询问并且拒绝权限后,代码内部不可以在去获取权限了,此时需要引导用户去设置中自行勾选权限
else{
//用户拒绝权限
//应该展示请求许可的原因吗
boolean b = shouldShowRequestPermissionRationale(Manifest.permission.RECORD_AUDIO);
if(!b){
//勾选了不在询问,一直在上一个else循环中,需要用户手动去设置页面加权限
new AlertDialog.Builder(MyPermissionActivity.this)
.setTitle("需要麦克风权限")
.setMessage("应用需要麦克风权限来录音,请前往设置开启权限")
.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", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
})
.setNegativeButton("取消",null)
.show();
}else{
//用户之前拒绝过权限,但是没有勾选不再询问
Toast.makeText(MyPermissionActivity.this, "获取录音权限失败", Toast.LENGTH_SHORT).show();
}
}
rationale 英 [ˌræʃəˈnɑːl] 理论的说明
译为:是否应该向用户显示请求权限的解释说明? 返回类型为boolean
返回 true
的情况:
返回 false
的情况:
false
,因为还没有过拒绝记录,不需要额外的解释。
false
。再次调用 requestPermissions
方法请求权限,系统会直接弹出权限拒绝的结果,此时就需要单独处理了
参数 permission 就是你要检查的具体权限名称,这里的Manifest.permission.RECORD_AUDIO就是录音权限,之前用过
在复习一下,积极按钮在右侧,消极在左侧;这里可以使用lambda表达式会更简洁;
Settings.ACTION_APPLICATION_DETAILS_SETTINGS
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Intent
对象,并指定其动作(Action)为 Settings.ACTION_APPLICATION_DETAILS_SETTINGS
。这个动作常量的作用是,告诉系统要启动的是应用详情设置页面的相关组件。Uri uri = Uri.fromParts("package", getPackageName(), null);
Uri
是统一资源标识符,用于标识和定位资源。
Uri.fromParts
方法用于构建一个 Uri
对象。这里传入三个参数:
"package"
是 Uri
的 scheme(模式),表示这是与应用包相关的 Uri
。getPackageName()
会获取当前应用的包名,这样就能定位到当前应用的设置详情。null
表示 fragment(片段),这里不需要,所以设为 null
。像极了爱情~~~~~第一次拒绝,第二次拒绝且不再询问
请求权限
======================================================================
因为用户已经勾选过 “不再询问”了,所以往后在点击申请权限按钮后, requestPermissions 不会再弹出系统权限申请对话框,而是一直走这一段代码
流程通了
findViewById(R.id.btn_location).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//获取位置权限
//返回true:一般是因为之前用户拒绝过了这个权限,但是没勾选不在询问
//返回false:有可能是第一次请求权限,或者是用户选择了“不再询问”
boolean b = shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION);
if(b){
new AlertDialog.Builder(MyPermissionActivity.this)
.setTitle("权限请求")
.setMessage("我接下来,需要请求你的定位,因为我要跟踪你")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//再次弹出权限申请
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},100);
}
})
.setNegativeButton("取消",null)
.show();
}else{
//第一次请求权限:无需解释
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},100);
}
}
});
else if(requestCode == 100){
//检查是否获得了权限
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
Toast.makeText(MyPermissionActivity.this,"已获得位置权限",Toast.LENGTH_SHORT).show();
}else{
//用户拒绝权限
boolean b = shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION);
if(!b){
//用户勾选了"不在询问"
//让用户自己去设置页面手动授权
new AlertDialog.Builder(MyPermissionActivity.this)
.setTitle("需要位置权限")
.setMessage("应用需要位置权限,请前往设置开启权限")
.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", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
})
.setNegativeButton("取消",null)
.show();
}else{
Toast.makeText(MyPermissionActivity.this, "已拒绝位置权限", Toast.LENGTH_SHORT).show();
}
}
}
((20250812195602-2syxexr “知识回顾”)):之前在学习页面跳转的时候,学习过用lanch进行页面跳转,和利用ActivityResultLauncher进行数据传输;Contracts中预定义了很多方法,其中就有页面跳转;本篇文章展示一下权限相关的用法
public class ARLauncherActivity extends AppCompatActivity {
private ActivityResultLauncher<String> activityResultLauncher = registerForActivityResult(
new ActivityResultContracts.RequestPermission(),
new ActivityResultCallback<Boolean>() {
@Override
public void onActivityResult(Boolean o) {
if(o){
//获取权限成功
Toast.makeText(ARLauncherActivity.this, "同意授权", Toast.LENGTH_SHORT).show();
}else {
//获取权限失败
boolean b = shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION);
if (b){
//没有点击不在询问
Toast.makeText(ARLauncherActivity.this, "拒绝了权限,没有勾选不在询问", Toast.LENGTH_SHORT).show();
}else {
//勾选了不在询问
Toast.makeText(ARLauncherActivity.this,"拒绝了权限,勾选不在询问",Toast.LENGTH_SHORT).show();
}
}
}
}
);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_arlauncher);
findViewById(R.id.btn_location).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int i = checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION);
//如果没有获取权限
if (i != PackageManager.PERMISSION_GRANTED){
activityResultLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION);
}
}
});
}
}
这里使用的是RequestPermission,第二个参数可以理解成我们注册了一个permission回调函数,用户处理完权限,会触发onActivityResult回调方法
,o作为返回值
之前我们在使用页面跳转的时候给ActivityResultLauncher定义的泛型是Intent;这里我们传参的是Manifest.permission.ACCESS_FINE_lOCATION它的本质是一个字符串,所以这里我们定义的泛型是String
效果展示
//方式一:
activityResultLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION);
//方式二:
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},100);