使用 Android 的 registerForActivityResult
API 简化权限请求
在 Android 开发中,请求权限是一个常见的操作。从 Android 13 开始,Google 推出了新的 registerForActivityResult
API,它让权限请求变得更简单。本文将展示如何用这个新 API 替换旧的 onRequestPermissionsResult
方法,并提供一个简单易懂的示例。
为什么要替换?
旧的 onRequestPermissionsResult
方法需要全局回调,用 requestCode
区分不同的权限请求,这使得代码复杂且难以维护。新的 registerForActivityResult
API 让每个权限请求都有自己的回调,代码更清晰、更简洁。
示例代码
1. 权限请求工具类
我们先定义一个工具类 PermissionRequestHelper
,封装权限请求的逻辑。
package net.moao.bluetoothuploader.utils;
import android.app.Activity;
import android.os.Build;
import androidx.annotation.RequiresApi;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import java.util.HashMap;
import java.util.Map;
public class PermissionRequestHelper {
private static final Map<String, String> PERMISSION_NAME_MAP = new HashMap<String, String>() {{
put("android.permission.ACCESS_FINE_LOCATION", "位置");
put("android.permission.BLUETOOTH_SCAN", "蓝牙扫描");
put("android.permission.BLUETOOTH_ADVERTISE", "蓝牙广告");
put("android.permission.BLUETOOTH_CONNECT", "蓝牙连接");
}};
/**
* 获取权限的显示名称
*
* @param permission 权限的英文名称
* @return 权限的显示名称
*/
public static String getPermissionDisplayName(String permission) {
return PERMISSION_NAME_MAP.getOrDefault(permission, permission);
}
/**
* 请求权限
*
* @param activity 当前的 Activity
* @param permissions 请求的权限列表
* @param callback 权限请求结果的回调
*/
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
public static void requestPermissions(Activity activity, String[] permissions, PermissionRequestCallback callback) {
// 注册权限请求
ActivityResultLauncher<String[]> launcher = activity.registerForActivityResult(
new ActivityResultContracts.RequestMultiplePermissions(),
result -> {
// 构建权限请求结果的字符串
StringBuilder resultBuilder = new StringBuilder();
for (String permission : permissions) {
String permissionName = getPermissionDisplayName(permission);
boolean isGranted = result.getOrDefault(permission, false);
String status = isGranted ? "已开启" : "未开启";
resultBuilder.append(permissionName).append(": ").append(status).append("\n");
}
// 调用回调方法
callback.onPermissionsResult(resultBuilder.toString());
}
);
// 发起权限请求
launcher.launch(permissions);
}
/**
* 权限请求结果的回调接口
*/
public interface PermissionRequestCallback {
/**
* 权限请求结果的回调方法
*
* @param result 权限请求的结果
*/
void onPermissionsResult(String result);
}
}
2. 在 Activity 中使用工具类
接下来,我们展示如何在 Activity
中使用 PermissionRequestHelper
类来请求权限。
package net.moao.bluetoothuploader;
import android.os.Bundle;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import net.moao.bluetoothuploader.utils.PermissionRequestHelper;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 定义需要请求的权限
String[] requiredPermissions = {
"android.permission.POST_NOTIFICATIONS",
"android.permission.ACCESS_FINE_LOCATION",
"android.permission.BLUETOOTH_SCAN",
"android.permission.BLUETOOTH_CONNECT",
"android.permission.BLUETOOTH_ADVERTISE"
};
// 请求权限
PermissionRequestHelper.requestPermissions(this, requiredPermissions, new PermissionRequestHelper.PermissionRequestCallback() {
@Override
public void onPermissionsResult(String result) {
// 处理权限请求的结果
Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
}
});
}
}
代码解释
1. 权限名称映射
private static final Map<String, String> PERMISSION_NAME_MAP = new HashMap<String, String>() {{
put("android.permission.ACCESS_FINE_LOCATION", "位置");
put("android.permission.BLUETOOTH_SCAN", "蓝牙扫描");
put("android.permission.BLUETOOTH_ADVERTISE", "蓝牙广告");
put("android.permission.BLUETOOTH_CONNECT", "蓝牙连接");
}};
PERMISSION_NAME_MAP
:一个静态的HashMap
,把权限的英文名称映射为中文名称。这样在用户界面中展示权限名称时更友好。
2. 获取权限的显示名称
public static String getPermissionDisplayName(String permission) {
return PERMISSION_NAME_MAP.getOrDefault(permission, permission);
}
getPermissionDisplayName
:根据权限的英文名称获取对应的中文名称。如果权限名称不在映射表中,就返回原始的英文名称。
3. 请求权限
public static void requestPermissions(Activity activity, String[] permissions, PermissionRequestCallback callback) {
// 注册权限请求
ActivityResultLauncher<String[]> launcher = activity.registerForActivityResult(
new ActivityResultContracts.RequestMultiplePermissions(),
result -> {
// 构建权限请求结果的字符串
StringBuilder resultBuilder = new StringBuilder();
for (String permission : permissions) {
String permissionName = getPermissionDisplayName(permission);
boolean isGranted = result.getOrDefault(permission, false);
String status = isGranted ? "已开启" : "未开启";
resultBuilder.append(permissionName).append(": ").append(status).append("\n");
}
// 调用回调方法
callback.onPermissionsResult(resultBuilder.toString());
}
);
// 发起权限请求
launcher.launch(permissions);
}
requestPermissions
:这个方法用于请求权限。activity
:当前的Activity
实例。permissions
:需要请求的权限列表。callback
:权限请求结果的回调接口。ActivityResultLauncher
:使用registerForActivityResult
方法注册权限请求。ActivityResultContracts.RequestMultiplePermissions
:指定请求多个权限。result
:权限请求的结果,是一个Map<String, Boolean>
,键是权限名称,值是布尔值,表示权限是否被授予。resultBuilder
:构建权限请求结果的字符串,用于在回调中展示。callback.onPermissionsResult
:调用回调方法,把权限请求的结果传递给调用者。
4. 权限请求结果的回调接口
public interface PermissionRequestCallback {
void onPermissionsResult(String result);
}
PermissionRequestCallback
:一个回调接口,用于处理权限请求的结果。onPermissionsResult
:权限请求结果的回调方法,参数result
是权限请求结果的字符串。
使用新 API 的好处
- 代码更简洁:使用
registerForActivityResult
API,代码更简洁,易于维护。 - 避免全局回调:不再需要使用全局的
onRequestPermissionsResult
方法,避免了通过requestCode
区分不同权限请求的复杂性。 - 更直观:每个权限请求都有自己的回调,逻辑更清晰。
评论 (0)