Android 基于Fragment的權(quán)限封裝
原理
業(yè)內(nèi)普遍比較認(rèn)可使用另外一種小技巧來進(jìn)行實(shí)現(xiàn)。是什么小技巧呢?回想一下,之前所有申請(qǐng)運(yùn)行時(shí)權(quán)限的操作都是在 Activity 中進(jìn)行的,事實(shí)上,Android 在 Fragment 中也提供了一份相同的 API,使得我們?cè)?Fragment 中也能申請(qǐng)運(yùn)行時(shí)權(quán)限。文章來源:http://www.zghlxwxcb.cn/news/detail-817815.html
但不同的是,F(xiàn)ragment 并不像 Activity 那樣必須有界面,我們完全可以向 Activity 中添加一個(gè)隱藏的 Fragment,然后在這個(gè)隱藏的 Fragment 中對(duì)運(yùn)行時(shí)權(quán)限的 API 進(jìn)行封裝。這是一種非常輕量級(jí)的做法,不用擔(dān)心隱藏 Fragment 會(huì)對(duì) Activity 的性能造成什么影響。文章來源地址http://www.zghlxwxcb.cn/news/detail-817815.html
代碼
PermissionUtils.java
/**
* 權(quán)限工具類
*/
public class PermissionUtils {
public static final int REQUEST_SETTING_CODE = 0X123456;
/**
* 權(quán)限是否授予
*/
public static boolean isGranted(@NonNull Context context, @NonNull String permission) {
return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
}
/**
* 權(quán)限是否全部授予
*/
public static boolean isGrantedPermissions(@NonNull Context context, @NonNull ArrayList<String> permissionList) {
for (String permission : permissionList) {
if (!isGranted(context, permission)) {
return false;
}
}
return true;
}
/**
* 權(quán)限是否拒絕且不再詢問
*/
public static boolean isDeniedNever(@NonNull Activity activity, @NonNull String permission) {
return !ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
}
/**
* 權(quán)限是否包含拒絕且不再詢問
*/
public static boolean isDeniedNeverPermissions(@NonNull Activity activity, @NonNull ArrayList<String> permissions) {
for (String permission : permissions) {
if (isDeniedNever(activity, permission)) {
return true;
}
}
return false;
}
/**
* 獲取未授權(quán)權(quán)限
*/
public static ArrayList<String> getDeniedPermissions(@NonNull Context context, @NonNull ArrayList<String> permissionList) {
ArrayList<String> deniedPermissionList = new ArrayList<>();
for (String permission : permissionList) {
if (!isGranted(context, permission)) {
deniedPermissionList.add(permission);
}
}
return deniedPermissionList;
}
/**
* 獲取包名Uri
*/
static Uri getPackageNameUri(@NonNull Context context) {
return Uri.parse("package:" + context.getPackageName());
}
/**
* 跳轉(zhuǎn)設(shè)置界面
*/
public static void gotoSetting(@NonNull Activity activity) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(getPackageNameUri(activity));
activity.startActivityForResult(intent, REQUEST_SETTING_CODE);
}
public static void gotoSetting(@NonNull Fragment fragment) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(getPackageNameUri(fragment.getContext()));
fragment.startActivityForResult(intent, REQUEST_SETTING_CODE);
}
/**
* 鎖定屏幕方向
*/
public static void lockScreenOrientation(@NonNull Activity activity) {
try {
// 獲取實(shí)際屏幕方向
int screenOrientation = activity.getResources().getConfiguration().orientation;
switch (screenOrientation) {
case Configuration.ORIENTATION_LANDSCAPE:
activity.setRequestedOrientation(PermissionUtils.isActivityReverse(activity) ?
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE :
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case Configuration.ORIENTATION_PORTRAIT:
activity.setRequestedOrientation(PermissionUtils.isActivityReverse(activity) ?
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT :
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
default:
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Activity是否反方向旋轉(zhuǎn)
*/
public static boolean isActivityReverse(@NonNull Activity activity) {
int activityRotation;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
activityRotation = activity.getDisplay().getRotation();
} else {
activityRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
}
switch (activityRotation) {
case Surface.ROTATION_180:
case Surface.ROTATION_270:
return true;
case Surface.ROTATION_0:
case Surface.ROTATION_90:
default:
return false;
}
}
}
PermissionsFragment.java
/**
* 權(quán)限請(qǐng)求Fragment
*/
public class PermissionsFragment extends Fragment {
public static final String REQUEST_CODE = "requestCode"; //請(qǐng)求碼
public static final String PARAM_PERMISSIONS = "permissionList";
/**
* 權(quán)限結(jié)果回調(diào)
*/
@Nullable
private OnPermissionCallback mOnPermissionCallback;
/**
* 設(shè)置結(jié)果回調(diào)
*/
@Nullable
private OnSettingsCallback mOnSettingsCallback;
/**
* 獲取當(dāng)前請(qǐng)求的屏幕方向
*/
private int mScreenOrientation;
private PermissionHelper mHelper;
private ArrayList<String> allPermissionList;
private int mRequestCode;
private static final ArrayList<Integer> requestCodeList = new ArrayList<>();
public static void launch(@NonNull FragmentActivity activity, @NonNull ArrayList<String> permissionList, @NonNull PermissionHelper helper,
@NonNull OnPermissionCallback onPermissionCallback, @Nullable OnSettingsCallback onSettingsCallback) {
PermissionsFragment fragment = new PermissionsFragment();
Bundle bundle = new Bundle();
int requestCode = generateCode();
bundle.putInt(REQUEST_CODE, requestCode);
bundle.putStringArrayList(PARAM_PERMISSIONS, permissionList);
fragment.setArguments(bundle);
fragment.setRetainInstance(true);
fragment.setCallback(onPermissionCallback, onSettingsCallback);
fragment.setHelper(helper);
fragment.attachActivity(activity);
}
private void setHelper(PermissionHelper helper) {
mHelper = helper;
}
/**
* 隨機(jī)生成requestCode
*/
private static int generateCode() {
int requestCode = new Random().nextInt(65536);
while (requestCodeList.contains(requestCode)) {
requestCode = new Random().nextInt(65536);
}
requestCodeList.add(requestCode);
return requestCode;
}
/**
* 綁定Activity
*/
private void attachActivity(@NonNull FragmentActivity activity) {
activity.getSupportFragmentManager().beginTransaction().add(this, this.toString()).commitAllowingStateLoss();
}
/**
* 解綁Activity
*/
private void detachActivity(@NonNull FragmentActivity activity) {
activity.getSupportFragmentManager().beginTransaction().remove(this).commitAllowingStateLoss();
}
/**
* 設(shè)置權(quán)限監(jiān)聽回調(diào)監(jiān)聽
*/
public void setCallback(@NonNull OnPermissionCallback onPermissionCallback, @Nullable OnSettingsCallback onSettingsCallback) {
mOnPermissionCallback = onPermissionCallback;
mOnSettingsCallback = onSettingsCallback;
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
FragmentActivity activity = getActivity();
if (activity == null) {
return;
}
Bundle bundle = getArguments();
if (bundle != null) {
ArrayList<String> permissionList = bundle.getStringArrayList(PARAM_PERMISSIONS);
if (permissionList == null || permissionList.isEmpty()) {
return;
}
mRequestCode = bundle.getInt(REQUEST_CODE);
allPermissionList = permissionList;
}
// 獲取請(qǐng)求的屏幕方向
mScreenOrientation = activity.getRequestedOrientation();
// 如果未指定屏幕方向,就鎖定當(dāng)前屏幕方向
if (mScreenOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
PermissionUtils.lockScreenOrientation(activity);
}
}
@Override
public void onDetach() {
super.onDetach();
FragmentActivity activity = getActivity();
if (activity == null) {
return;
}
// 如果當(dāng)前屏幕方向是未指定,同時(shí)當(dāng)前請(qǐng)求的屏幕方向是橫屏或豎屏?xí)r,則屏幕方向切換為未指定方向模式
if (mScreenOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED &&
activity.getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
}
@Override
public void onResume() {
super.onResume();
requestPermissions(allPermissionList.toArray(new String[allPermissionList.size() - 1]), mRequestCode);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NotNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (permissions.length == 0 || grantResults.length == 0) {
return;
}
if (requestCode == mRequestCode) {
FragmentActivity activity = getActivity();
if (activity == null) {
return;
}
ArrayList<String> grantedList = new ArrayList<>(); //已授予權(quán)限
ArrayList<String> deniedList = new ArrayList<>(); //已拒絕權(quán)限
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
deniedList.add(permissions[i]);
} else {
grantedList.add(permissions[i]);
}
}
requestCodeList.remove((Integer) mRequestCode);
OnPermissionCallback onPermissionCallback = mOnPermissionCallback;
mOnPermissionCallback = null;
OnSettingsCallback onSettingsCallback = mOnSettingsCallback;
mOnSettingsCallback = null;
PermissionHelper helper = mHelper;
mHelper = null;
detachActivity(activity);
boolean allGranted = grantedList.size() == permissions.length;
if (allGranted) {
onPermissionCallback.onGranted(true, grantedList);
return;
}
boolean deniedNever = PermissionUtils.isDeniedNeverPermissions(activity, deniedList);
onPermissionCallback.onDenied(deniedNever, deniedList);
if (grantedList.size() > 0) {
onPermissionCallback.onGranted(false, grantedList);
}
if (deniedNever) {
helper.showPermissionSettingDialog(activity, deniedList, onSettingsCallback);
} else if (deniedList.size() > 0) {
helper.showPermissionInfoDialog(activity, deniedList, onPermissionCallback, onSettingsCallback);
}
}
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onDestroy() {
super.onDestroy();
mOnPermissionCallback = null;
}
}
/**
* 權(quán)限結(jié)果回調(diào)
*/
public interface OnPermissionCallback {
/**
* 權(quán)限授予時(shí)回調(diào)
*
* @param allGranted 是否全部被授予
* @param permissions 已授予權(quán)限
*/
void onGranted(boolean allGranted, @NonNull ArrayList<String> permissions);
/**
* 權(quán)限拒絕時(shí)回調(diào)
*
* @param deniedNever 是否拒絕且不再詢問
* @param permissions 被拒絕權(quán)限
*/
void onDenied(boolean deniedNever, @NonNull ArrayList<String> permissions);
}
public interface OnSettingsCallback {
void onResult();
}
PermissionHelper.java
/**
* 權(quán)限請(qǐng)求類
*/
public class PermissionHelper {
@Nullable
private final FragmentActivity mActivity;
@NonNull
private final ArrayList<String> mPermissions = new ArrayList<>();
private PermissionHelper(FragmentActivity activity) {
mActivity = activity;
}
/**
* 設(shè)置請(qǐng)求對(duì)象
*/
public static PermissionHelper with(FragmentActivity activity) {
return new PermissionHelper(activity);
}
public static PermissionHelper with(Fragment fragment) {
FragmentActivity activity = fragment.getActivity();
return new PermissionHelper(activity);
}
public PermissionHelper permissions(@NonNull ArrayList<String> permissionList) {
mPermissions.addAll(permissionList);
return this;
}
/**
* 請(qǐng)求權(quán)限
*/
public void request(@NonNull OnPermissionCallback onPermissionCallback) {
request(onPermissionCallback, null);
}
public void request(@NonNull OnPermissionCallback onPermissionCallback, @Nullable OnSettingsCallback onSettingsCallback) {
if (mActivity == null || mActivity.isFinishing() || mActivity.isDestroyed()) {
return;
}
showPermissionInfoDialog(mActivity, mPermissions, onPermissionCallback, onSettingsCallback);
}
/**
* 權(quán)限說明彈窗
*/
public void showPermissionInfoDialog(@NonNull FragmentActivity activity, @NonNull ArrayList<String> allPermissions, @NonNull OnPermissionCallback onPermissionCallback) {
showPermissionInfoDialog(activity, allPermissions, onPermissionCallback, null);
}
public void showPermissionInfoDialog(FragmentActivity activity, @NonNull ArrayList<String> allPermissions, @NonNull OnPermissionCallback onPermissionCallback, @Nullable OnSettingsCallback onSettingsCallback) {
if (activity == null || activity.isFinishing() || activity.isDestroyed()) {
return;
}
ArrayList<String> permissionList = PermissionUtils.getDeniedPermissions(activity, allPermissions);
String title = "權(quán)限說明";
String message = "使用此功能需要先授予:" + listToString(getPermissionNames(permissionList));
new AlertDialog.Builder(activity)
.setTitle(title)
.setMessage(message)
.setCancelable(false)
.setPositiveButton("授予", (dialog, which) -> {
dialog.dismiss();
PermissionsFragment.launch(activity, permissionList, this, onPermissionCallback, onSettingsCallback);
})
.setNegativeButton("取消", (dialog, which) -> {
})
.show();
}
/**
* 獲取權(quán)限名
*/
public static ArrayList<String> getPermissionNames(ArrayList<String> permissions) {
ArrayList<String> permissionNames = new ArrayList<>();
for (String permission : permissions) {
switch (permission) {
case Manifest.permission.CAMERA:
permissionNames.add("相機(jī)權(quán)限");
break;
case Manifest.permission.ACCESS_FINE_LOCATION:
permissionNames.add("定位權(quán)限");
break;
case Manifest.permission.CALL_PHONE:
permissionNames.add("撥號(hào)權(quán)限");
break;
default:
break;
}
}
return permissionNames;
}
/**
* ArrayList轉(zhuǎn)String
*/
public static String listToString(ArrayList<String> permissionNames) {
StringBuilder builder = new StringBuilder();
for (int i = 0, size = permissionNames.size(); i < size; i++) {
if (i == size - 1) {
builder.append(permissionNames.get(i));
} else {
builder.append(permissionNames.get(i)).append("、");
}
}
return builder.toString();
}
/**
* 權(quán)限提醒彈窗
*/
public void showPermissionSettingDialog(FragmentActivity activity, ArrayList<String> permissionList, @Nullable OnSettingsCallback onSettingsCallback) {
if (activity == null || activity.isFinishing() || activity.isDestroyed()) {
return;
}
String title = "權(quán)限提醒";
String message = "獲取權(quán)限失敗,請(qǐng)手動(dòng)授予:" + listToString(getPermissionNames(permissionList));
new AlertDialog.Builder(activity)
.setTitle(title)
.setMessage(message)
.setPositiveButton("前往授權(quán)", (dialog, which) -> {
dialog.dismiss();
SettingsFragment.launch(activity, onSettingsCallback);
})
.show();
}
}
SettingsFragment.java
/**
* 跳轉(zhuǎn)設(shè)置頁(yè)Fragment
*/
public class SettingsFragment extends Fragment {
@Nullable
private OnSettingsCallback mCallBack;
public static void launch(@NonNull FragmentActivity activity, @Nullable OnSettingsCallback callback) {
SettingsFragment fragment = new SettingsFragment();
fragment.setRetainInstance(true);
if (callback != null)
fragment.setCallback(callback);
fragment.attachActivity(activity);
}
/**
* 設(shè)置回調(diào)
*/
public void setCallback(@NonNull OnSettingsCallback callback) {
mCallBack = callback;
}
/**
* 綁定Activity
*/
private void attachActivity(@NonNull FragmentActivity activity) {
activity.getSupportFragmentManager().beginTransaction().add(this, this.toString()).commitAllowingStateLoss();
}
/**
* 解綁Activity
*/
private void detachActivity(@NonNull FragmentActivity activity) {
activity.getSupportFragmentManager().beginTransaction().remove(this).commitAllowingStateLoss();
}
@Override
public void onResume() {
super.onResume();
PermissionUtils.gotoSetting(this);
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable @org.jetbrains.annotations.Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PermissionUtils.REQUEST_SETTING_CODE) {
OnSettingsCallback callback = mCallBack;
mCallBack = null;
if (callback != null) {
callback.onResult();
}
}
FragmentActivity activity = getActivity();
if (activity == null) {
return;
}
detachActivity(activity);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onDestroy() {
super.onDestroy();
mCallBack = null;
}
}
Activity中使用
{
ArrayList<String> permissionList = new ArrayList<>();
permissionList.add(Manifest.permission.CAMERA);
permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
permissionList.add(Manifest.permission.CALL_PHONE);
if (PermissionUtils.isGrantedPermissions(mContext, permissionList)) {
Toast.makeText(mContext, "權(quán)限都通過了", Toast.LENGTH_SHORT).show();
} else {
PermissionHelper.with(this)
.permissions(permissionList)
.request(new OnPermissionCallback() {
@Override
public void onGranted(boolean allGranted, @NonNull ArrayList<String> permissions) {
if (allGranted) {
Toast.makeText(mContext, "權(quán)限全部通過", Toast.LENGTH_SHORT).show();
}
Log.e("TAG", "onGranted: " + allGranted + " - " + permissions);
}
@Override
public void onDenied(boolean deniedNever, @NonNull ArrayList<String> permissions) {
if (deniedNever) {
Toast.makeText(mContext, "權(quán)限拒絕且不再詢問", Toast.LENGTH_SHORT).show();
}
Log.e("TAG", "onDenied: " + deniedNever + " - " + permissions);
}
}, new OnSettingsCallback() {
@Override
public void onResult() {
Log.e("TAG", "onResult");
}
});
}
}
Fragment中使用
ArrayList<String> permissionList = new ArrayList<>();
permissionList.add(Manifest.permission.CAMERA);
permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
permissionList.add(Manifest.permission.CALL_PHONE);
if (PermissionUtils.isGrantedPermissions(mContext, permissionList)) {
Toast.makeText(mContext, "權(quán)限都通過了", Toast.LENGTH_SHORT).show();
} else {
PermissionHelper.with(this)
.permissions(permissionList)
.request(new OnPermissionCallback() {
@Override
public void onGranted(boolean allGranted, @NonNull ArrayList<String> permissions) {
if (allGranted) {
Toast.makeText(mContext, "權(quán)限全部通過", Toast.LENGTH_SHORT).show();
}
Log.e("TAG", "onGranted: " + allGranted + " - " + permissions);
}
@Override
public void onDenied(boolean deniedNever, @NonNull ArrayList<String> permissions) {
if (deniedNever) {
Toast.makeText(mContext, "權(quán)限拒絕且不再詢問", Toast.LENGTH_SHORT).show();
}
Log.e("TAG", "onDenied: " + deniedNever + " - " + permissions);
}
}, new OnSettingsCallback() {
@Override
public void onResult() {
Log.e("TAG", "onResult");
}
});
}
源碼
到了這里,關(guān)于Android 基于Fragment的權(quán)限封裝的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!