为了在Android 6.0及以上版本上获得一些敏感权限,如读取设备存储器、拍照、录音等,需要使用运行时权限。本文将介绍如何完美封装运行时权限,使其在应用中更加方便快捷。
1. 权限获取流程
首先,我们需要确定权限获取的流程:
- 先判断权限是否已经被授予:
- 如果有授予了,直接执行后续操作。
- 如果没有授予,执行下一步。
- 弹出权限请求框,请求用户授权。
- 用户授权或拒绝后,系统回调我们预定义的处理函数,然后我们在该函数中处理相关逻辑。
现在,我们开始具体实现这个流程。
2. 权限申请流程封装
我们创建一个PermissionUtil
类来封装该过程。
public class PermissionUtil {
/**
* 判断是否已经授权该权限
* @param context 应用上下文
* @param permission 权限字符串
* @return true 已经授权,false 未授权
*/
public static boolean hasPermission(Context context, String permission) {
return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
}
/**
* 请求权限
* @param activity 当前Activity实例
* @param permission 权限字符串
* @param requestCode 请求码
*/
public static void requestPermission(Activity activity, String permission, int requestCode) {
ActivityCompat.requestPermissions(activity, new String[]{permission}, requestCode);
}
/**
* 判断是否需要向用户解释此权限作用
* @param activity 当前Activity实例
* @param permission 权限字符串
* @return true 需要解释,false 不需要解释
*/
public static boolean shouldShowRequestPermissionRationale(Activity activity, String permission) {
return ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
}
}
这个类封装了三个静态方法,分别用于判断权限是否已经被授予、请求权限和判断是否需要向用户解释权限。
这样实现的目的是使我们的代码能够更加清晰和易于维护。
3. 处理权限请求和结果
在Activity
或Fragment
的代码中,我们需要处理权限请求和结果。我们创建一个新的类PermissionActivity
,用于处理权限请求。
public class PermissionActivity extends AppCompatActivity {
private static final String EXTRA_PERMISSION_LIST = "extra_permission_list";
private static final int PERMISSION_REQUEST_CODE = 1;
private String[] mPermissionList;
/**
* 启动 PermissionActivity 的静态方法
* @param context 应用上下文
* @param permissionList 权限列表
* @param callback 处理权限结果的回调
*/
public static void launch(Context context, String[] permissionList, PermissionCallback callback) {
Intent intent = new Intent(context, PermissionActivity.class);
intent.putExtra(EXTRA_PERMISSION_LIST, permissionList);
PermissionCallbackHolder.getInstance().setPermissionCallback(callback);
context.startActivity(intent);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPermissionList = getIntent().getStringArrayExtra(EXTRA_PERMISSION_LIST);
if (mPermissionList == null || mPermissionList.length == 0) {
// 权限列表为空
finish();
return;
}
requestPermissions();
}
/**
* 请求权限
*/
private void requestPermissions() {
ActivityCompat.requestPermissions(this, mPermissionList, PERMISSION_REQUEST_CODE);
}
/**
* 处理权限结果
* @param requestCode 请求码
* @param permissions 权限列表
* @param grantResults 请求结果列表
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionCallback callback = PermissionCallbackHolder.getInstance().getPermissionCallback();
if (requestCode == PERMISSION_REQUEST_CODE) {
List<String> granted = new ArrayList<>();
List<String> denied = new ArrayList<>();
for (int i = 0; i < grantResults.length; i++) {
String permission = permissions[i];
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
granted.add(permission);
} else {
denied.add(permission);
}
}
if (denied.isEmpty()) {
// 全部权限都已授权
callback.onPermissionGranted();
} else {
// 有权限被拒绝
callback.onPermissionDenied(denied, shouldShowPermissionRationale());
}
}
finish();
}
/**
* 判断是否需要向用户解释权限作用
* @return true 需要解释,false 不需要解释
*/
private boolean shouldShowPermissionRationale() {
for (String permission : mPermissionList) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
return true;
}
}
return false;
}
}
在PermissionActivity
中,我们启动权限请求框、处理请求结果,并在回调中处理相关逻辑.
这个类未涉及到UI操作,只是进行了数据操作,可以便捷地被其他Activity
或Fragment
调用。
4. 处理权限结果回调
最后,我们需要处理权限结果回调。为了将回调处理与要求权限的Activity
或Fragment
解耦,我们将回调处理统一调用。
public class PermissionCallbackHolder {
private static final PermissionCallbackHolder INSTANCE = new PermissionCallbackHolder();
private PermissionCallbackHolder() {}
@Nullable
private PermissionCallback mPermissionCallback;
public static PermissionCallbackHolder getInstance() {
return INSTANCE;
}
@Nullable
public PermissionCallback getPermissionCallback() {
return mPermissionCallback;
}
public void setPermissionCallback(@Nullable PermissionCallback permissionCallback) {
mPermissionCallback = permissionCallback;
}
}
PermissionCallbackHolder
类创建一个全局静态实例,负责保存处理权限结果的回调PermissionCallback
。
public interface PermissionCallback {
void onPermissionGranted();
void onPermissionDenied(List<String> denied, boolean alwaysDenied);
}
在PermissionCallback
中定义了两个函数:onPermissionGranted()
和onPermissionDenied(denied, alwaysDenied)
。前者会在所有权限被授予时调用,后者会在有权限被拒绝时调用。如果alwaysDenied
参数为true
,表示用户总是拒绝了该权限,并勾选了“不再询问”选项。
5. 在Activity或Fragment中调用PermissionUtil
现在我们已经完成了所有需要的组件,可以开始在Activity
或Fragment
中调用权限请求。
public class MainActivity extends AppCompatActivity implements PermissionCallback {
private static final String PERMISSION_RECORD_AUDIO = Manifest.permission.RECORD_AUDIO;
private static final String PERMISSION_CAMERA = Manifest.permission.CAMERA;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
// 检查录音权限
String[] permissions = {PERMISSION_RECORD_AUDIO};
if (PermissionUtil.hasPermission(this, PERMISSION_RECORD_AUDIO)) {
onPermissionGranted();
} else {
if (!PermissionUtil.shouldShowRequestPermissionRationale(this, PERMISSION_RECORD_AUDIO)) {
Toast.makeText(this, R.string.permission_no_granted, Toast.LENGTH_SHORT).show();
}
PermissionUtil.requestPermission(this, PERMISSION_RECORD_AUDIO, PERMISSION_RECORD_AUDIO.hashCode());
}
// 检查相机权限
permissions[0] = PERMISSION_CAMERA;
if (PermissionUtil.hasPermission(this, PERMISSION_CAMERA)) {
onPermissionGranted();
} else {
if (!PermissionUtil.shouldShowRequestPermissionRationale(this, PERMISSION_CAMERA)) {
Toast.makeText(this, R.string.permission_no_granted, Toast.LENGTH_SHORT).show();
}
PermissionUtil.requestPermission(this, PERMISSION_CAMERA, PERMISSION_CAMERA.hashCode());
}
}
@Override
public void onPermissionGranted() {
// 权限请求成功操作
Toast.makeText(this, R.string.permission_granted, Toast.LENGTH_SHORT).show();
}
@Override
public void onPermissionDenied(List<String> denied, boolean alwaysDenied) {
// 权限请求失败操作
if (alwaysDenied && !denied.isEmpty()) {
String message = getString(R.string.permission_denied_always_message, TextUtils.join(", ", denied));
new AlertDialog.Builder(this)
.setTitle(R.string.permission_denied_always_title)
.setMessage(message)
.setPositiveButton(R.string.permission_setting, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
PermissionUtil.showAppSettings(MainActivity.this);
}
})
.setNegativeButton(R.string.permission_not_now, null)
.create().show();
} else {
Toast.makeText(this, R.string.permission_denied, Toast.LENGTH_SHORT).show();
}
}
}
在onResume()
方法中,我们检查申请RECORD_AUDIO
和CAMERA
权限。如果已经授予权限,则调用onPermissionGranted()
方法,否则调用requestPermission()
方法请求权限。当权限请求完成后,onRequestPermissionsResult
方法会被调用。这个方法中判断所有权限是否授权,并根据情况调用onPermissionGranted()
或onPermissionDenied()
方法。
这样,我们就完成了一整个完美封装流程,并在实际开发中得到了应用。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:android6.0运行时权限完美封装方法 - Python技术站