Android利用Fragment实现权限授权管理

实现背景:

最近写项目有多处需要动态的申请权限,Android原生的权限申请方式虽然足够简单但是却并不是很方便。
比如首先要通过checkSelfPermission去判断是否已经有权限,已经有权限则进行相应的业务处理,如果没有权限则通过requestPermissions申请权限,并且在onRequestPermissionsResult回调方法中再次进行判断,如果有权限再次调用业务代码。
也就是业务代码需要进行两次调用,所以想要把权限申请的部分进行封装,并且不需要在onRequestPermissionsResult回调任何代码。

基本原理

首先调用requestPermissions只有通过回调才能知道用户是不是对权限进行了授权,这点无法改变。但是我们可以通过一个维护一个临时的Fragment添加到Activity中,然后再调用此FragmentrequestPermissions方法去申请权限,这样用户进行操作后就会回调Fragment中的onRequestPermissionsResult(因为Fragment的生命周期与宿主Activity相同)。然后再Fragment中通过回调方法进行授权的结果判断。

具体实现

我把具体实现的代码放在了文末供大家参考。实现匆忙,仅为原理验证,所以尚有不足还望见谅。

使用方法

参考文末的代码,新建一个类,然后把代码复制到自己这个类中。

申请权限的方法

FastPermissions fastpermissions = new FastPermissions(this);

fastPermissions.need(Manifest.permission.READ_EXTERNAL_STORAGE)
	.subscribe(new FastPermissions.Subscribe() {
			@Override
			public void onResult(int requestCode, boolean allGranted, String[] permissions) {
				if (allGranted){
					//权限允许后进行的操作
				}else{
					//权限拒绝后进行的操作
					Toast.makeText(getActivity(), "权限被拒绝", Toast.LENGTH_SHORT).show();
				}
			}
	}).request(1);

使用解释

简化一下其实就是这样

//实例化方法
FastPermissions fastpermissions = new FastPermissions(this);
fastpermission.need(/*这里设置需要的权限*/).subscribe(/* 设置回调 */).request(/*请求码*/);

@需要设置的权限 这里可以为单个权限也可以为权限字符串数组
@回调的方法

new FastPermissions.Subscribe() {
	 @Override
     public void onResult(int requestCode, boolean allGranted, String[] permissions) {
           if (allGranted){
                 //权限允许
            }
            else
            {
                //权限被拒绝
			}
     }
}

@请求码 多次调用请求的时候务必设置不同的请求码

使用注意

  • 因为其原理是维护了一个临时的Fragment,所以从节省资源的角度考虑,一个Activity最多对FastPermission实例化一次
  • 实例化的时候传入的Activity必须继承自AppCompatActivity,不能继承Activity

完整代码

package cn.dingd.darkchat;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.HashMap;

public class FastPermissions {
    private final String TAG = FastPermissions.class.getSimpleName();
    private Activity activity;

    private PermissionFragment permissionFragment;


    /**
     * 订阅回调接口
     */
    public interface Subscribe {
        void onResult(int requestCode, boolean allGranted, String[] permissions);
    }

    /**
     * 内部回调使用,用户不应该调用或者实现此接口
     */
    public interface Callback {
        void onRequestPermissionsCallback(final int requestCode, String[] permissions, int[] grantResults);
    }

    static public class PermissionFragment extends Fragment {

        private HashMap<Integer, Callback> callbacks = new HashMap<>();
        private ArrayList<Runnable> runnables = new ArrayList<>();


        public void registerCallback(int requestCode, Callback callback) {
            callbacks.put(requestCode, callback);
        }

        @Override
        public void onAttach(@NonNull Context context) {
            super.onAttach(context);
            Log.d("PermissionFragment", "延迟执行");
            while (!runnables.isEmpty())
                runnables.remove(0).run();
        }

        public void postRequestPermissions(final String[] permissions, final int requestCode) {
            if (isAdded()) {
                requestPermissions(permissions, requestCode);
            } else {
                runnables.add(new Runnable() {
                    @Override
                    public void run() {
                        requestPermissions(permissions, requestCode);
                    }
                });
            }
        }

        @Override
        public void onRequestPermissionsResult(int requestCode, @NotNull final String[] permissions, @NotNull final int[] grantResults) {
            if (callbacks.containsKey(requestCode)) {
                Callback callback = callbacks.get(requestCode);
                if (callback != null)
                    callback.onRequestPermissionsCallback(requestCode, permissions, grantResults);
            }
        }
    }

    /**
     * 快捷的进行权限申请,通过添加一个临时的Fragment来进行生命周期管理,因此
     * 一个Activity请只初始化一个FastPermissions实例
     *
     * @param appCompatActivity 所在的activity,必须继承自AppCompatActivity
     */

    public FastPermissions(AppCompatActivity appCompatActivity) {
        if (appCompatActivity == null)
            throw new IllegalArgumentException("Activity must not be null!");
        permissionFragment = new PermissionFragment();
        activity = appCompatActivity;
        FragmentManager fragmentManager = appCompatActivity.getSupportFragmentManager();
        fragmentTransaction(fragmentManager);

    }

    public FastPermissions(Fragment fragment) {
        activity = fragment.getActivity();
        if (activity == null)
            throw new IllegalArgumentException("Activity must not be null!");
        permissionFragment = new PermissionFragment();
        FragmentManager fragmentManager = fragment.getChildFragmentManager();
        fragmentTransaction(fragmentManager);
    }

    private void fragmentTransaction(FragmentManager fragmentManager) {
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(permissionFragment, PermissionFragment.class.getSimpleName());
        fragmentTransaction.commit();
        if (permissionFragment.isAdded()) {
            Log.d(TAG, "已经被添加到Activity");
        } else {
            Log.d(TAG, "尚未添加到Activity");
        }
    }

    /**
     * 设置所需要申请的权限
     *
     * @param permission 需要申请的权限
     * @return 返回一个RequestPermissionsResult实例用于进行后续操作
     */
    public RequestPermissionsResult need(String permission) {
        return need(new String[]{permission});
    }

    /**
     * 设置所需要申请的权限
     *
     * @param permissions 需要申请的权限数组
     * @return 返回一个RequestPermissionsResult实例用于进行后续操作
     */
    public RequestPermissionsResult need(String[] permissions) {
        return new RequestPermissionsResult(activity, permissions, permissionFragment);
    }

    static class RequestPermissionsResult implements Callback {
        private Activity activity;
        private String[] permissions;
        private PermissionFragment permissionFragment;
        private Subscribe subscribe;
        private boolean showDialog = true;

        RequestPermissionsResult(Activity activity, String[] permissions, PermissionFragment permissionFragment) {
            this.activity = activity;
            this.permissions = permissions;
            this.permissionFragment = permissionFragment;
        }

        /**
         * 设置当权限被拒绝的时候是否弹窗提示用户
         *
         * @param showDialog 为true则弹窗反之不弹窗 默认为true
         * @return 返回RequestPermissionsResult
         */
        public RequestPermissionsResult showDialog(boolean showDialog) {
            this.showDialog = showDialog;
            return this;
        }

        private boolean requestPermissions(String[] permissions, int requestCode) {
            for (String permission : permissions) {
                if (ActivityCompat.checkSelfPermission(activity, permission)
                        == PackageManager.PERMISSION_DENIED) {
                    //注册回调
                    permissionFragment.registerCallback(requestCode, this);
                    permissionFragment.postRequestPermissions(permissions, requestCode);
                    return false;
                }
            }
            return true;
        }

        /**
         * 开始请求权限
         *
         * @param requestCode 请求号
         */
        public void request(int requestCode) {

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (!requestPermissions(permissions, requestCode)) {
                    return;
                }
            }
            //通知权限监听回调
            publish(requestCode, true, permissions);
        }

        private void publish(int requestCode, boolean allGranted, String[] permissions) {
            if (subscribe != null)
                subscribe.onResult(requestCode, allGranted, permissions);
        }

        /**
         * 设置订阅回调
         *
         * @param subscribe 权限被允许或者拒绝的时候会回调此实例
         *                  实例必须实现Subscribe方法
         * @return 返回RequestPermissionsResult实例
         */
        public RequestPermissionsResult subscribe(Subscribe subscribe) {
            this.subscribe = subscribe;
            return this;
        }

        /**
         * 提供权限的回调接口 此方法为内部接口 用户不应该调用此方法
         *
         * @param requestCode  请求号
         * @param permissions  权限
         * @param grantResults 授权结果
         */
        @Override
        public void onRequestPermissionsCallback(final int requestCode, final String[] permissions, final int[] grantResults) {
            //保证运行在主线程
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    onRequestPermissionsResult(requestCode, permissions, grantResults);
                }
            });
        }

        private void onRequestPermissionsResult(final int requestCode, @NotNull final String[] permissions, @NotNull final int[] grantResults) {
            int i = 0;
            for (int grant : grantResults) {
                String permission = permissions[i];
                if (grant == PackageManager.PERMISSION_DENIED) {
                    if (showDialog) {
                        showDialogTips(permission, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                publish(requestCode, false, permissions);
                            }
                        });
                    } else {
                        publish(requestCode, false, permissions);
                    }
                    return;
                }
            }
            publish(requestCode, true, permissions);
        }

        private void showDialogTips(String permission, DialogInterface.OnClickListener onDenied) {
            PackageManager packageManager = activity.getPackageManager();
            String permissionName;
            try {
                PermissionInfo permissionInfo = packageManager.getPermissionInfo(permission, 0);
                assert permissionInfo.group != null;
                PermissionGroupInfo permissionGroupInfo =
                        packageManager.getPermissionGroupInfo(permissionInfo.group, 0);
                permissionName = (String) permissionGroupInfo.loadLabel(packageManager);
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
                permissionName = "";
            }
            AlertDialog alertDialog = new AlertDialog.Builder(activity).setTitle("权限被禁用").setMessage(
                    String.format("您拒绝了相关权限,无法正常使用本功能。请前往 设置->应用管理->%s->权限管理中启用 %s 权限",
                            activity.getString(R.string.app_name),
                            permissionName
                    )).setCancelable(false).
                    setNegativeButton("返回", onDenied).
                    setPositiveButton("去设置", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            Intent manageAppIntent = new Intent();
                            manageAppIntent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                            //第二个参数为包名
                            Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
                            manageAppIntent.setData(uri);
                            activity.startActivity(manageAppIntent);
                        }
                    }).create();
            alertDialog.show();

        }


    }


}


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Android实现分屏,可以使用 Fragment实现。具体实现步骤如下: 1. 在 AndroidManifest.xml 文件中声明支持分屏功能: ```xml <activity android:name=".MainActivity" android:resizeableActivity="true" android:supportsPictureInPicture="true"> <meta-data android:name="android.max_aspect" android:value="2.1" /> </activity> ``` 2. 在布局文件中创建两个 Fragment: ```xml <fragment android:id="@+id/fragment1" android:name="com.example.fragmentdemo.Fragment1" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> <fragment android:id="@+id/fragment2" android:name="com.example.fragmentdemo.Fragment2" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> ``` 3. 在 MainActivity 中实现分屏功能: ```java public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (isInMultiWindowMode()) { Fragment1 fragment1 = new Fragment1(); Fragment2 fragment2 = new Fragment2(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.add(R.id.fragment1, fragment1); transaction.add(R.id.fragment2, fragment2); transaction.commit(); } } } ``` 在 isInMultiWindowMode() 方法中判断是否处于分屏模式,如果是,则创建两个 Fragment 并添加到布局中。 4. 运行程序并进入分屏模式,即可看到两个 Fragment 并排显示在屏幕上。 注意:对于 Android 7.0 及以上版本,需要在 AndroidManifest.xml 文件中声明 android:resizeableActivity="true" 和 android:supportsPictureInPicture="true" 来支持分屏功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值