权限申请模板代码

Android5.0后加入了权限动态申请,而且过运营商测试也有这个要求。但是真正在所需权限的地方写申请权限代码的话工作量是很大的(也有app真的能做到这种要求,例如微信,入口处什么权限都不需要的,只有具体需要才申请,用户体验真是做到极致了),所以app一般会在入口处申请全部的权限,例如新闻客户端就可这么搞,反正就一个入口。但是如果Activity非常多,入口也很多,那么要写大量的申请权限代码。Contacts和Dialer中为了解决这个问题专门写了几个类在ContactsCommon中。

RequestPermissionsActivityBase

packages/apps/ContactsCommon/src/com/android/contacts/common/activity/RequestPermissionsActivityBase.java

    private Intent mPreviousActivityIntent;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPreviousActivityIntent = (Intent) getIntent().getExtras().get(PREVIOUS_ACTIVITY_INTENT);

        // Only start a requestPermissions() flow when first starting this activity the first time.
        // The process is likely to be restarted during the permission flow (necessary to enable
        // permissions) so this is important to track.
        if (savedInstanceState == null) {
            requestPermissions();
        }
    }
创建的时候保存上一个Acitivity(也就是要申请权限的Activity),然后申请权限

    private void requestPermissions() {
         ...
            final ArrayList<String> unsatisfiedPermissions = new ArrayList<>();
            for (String permission : getDesiredPermissions()) {
                if (checkSelfPermission(permission)
                        != PackageManager.PERMISSION_GRANTED) {
                    unsatisfiedPermissions.add(permission);
                }
            }
            requestPermissions(
                    unsatisfiedPermissions.toArray(new String[unsatisfiedPermissions.size()]),
                    PERMISSIONS_REQUEST_ALL_PERMISSIONS);
          ...
    }
首先获取要申请的权限,然后申请。其中getDesiredPermissions是个抽象函数,要在子类中实现。

    public void onRequestPermissionsResult(int requestCode, String permissions[],
            int[] grantResults) {
        if (permissions != null && permissions.length > 0
                && isAllGranted(permissions, grantResults)) {
            mPreviousActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
            startActivity(mPreviousActivityIntent);
            finish();
            overridePendingTransition(0, 0);
        ...
    }
获取到权限后,关闭当前activity然后跳转回原来的Activity。

该类中还有个protected静态方法供子类调用

  protected static boolean startPermissionActivity(Activity activity,
            String[] requiredPermissions, Class<?> newActivityClass) {
        ...
        if (!RequestPermissionsActivity.hasPermissions(activity, requiredPermissions)) {
            final Intent intent = new Intent(activity,  newActivityClass);
            intent.putExtra(PREVIOUS_ACTIVITY_INTENT, activity.getIntent()); //简化了需要用到该类的代码,例如调用方根本无需知道(PREVIOUS_ACTIVITY_INTENT是啥
            activity.startActivity(intent);
            activity.finish();
            return true;
        }
        ...
        return false;
    }

RequestPermissionsActivity

packages/apps/ContactsCommon/src/com/android/contacts/common/activity/RequestPermissionsActivity.java

@Override
    protected String[] getDesiredPermissions() {
        return new String[]{
                permission.ACCESS_FINE_LOCATION, // Location Group
                permission.READ_CONTACTS, // Contacts group
                permission.READ_CALL_LOG, // Permission group phone
                permission.READ_CALENDAR, // Calendar group
                permission.READ_SMS, // SMS group
        };
    }
实现了基类的抽象方法,因为这个是给Contacts用的,所以已经初始化为Contacts需要的权限。

 public static boolean startPermissionActivity(Activity activity) {
        return startPermissionActivity(activity, REQUIRED_PERMISSIONS,
                RequestPermissionsActivity.class);
    }
startPermissionActivity调用基类的静态方法完成申请权限的任务,可以看出startPermissionActivity就是给Contacts中其它Activity使用的,使用只需要一句

    RequestPermissionsActivity.startPermissionActivity(this);

虽然这个是给Contacts使用的,但是稍加修改就能作为一个申请权限的模板代码使用,不用每个类写一遍申请权限代码。

PermissionsUtil

packages/apps/ContactsCommon/src/com/android/contacts/common/util/PermissionsUtil.java

public static boolean hasPermission(Context context, String permission) {
        return context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
        }

    public static boolean hasAppOp(Context context, String appOp) {
        final AppOpsManager appOpsManager =
                (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        final int mode = appOpsManager.checkOpNoThrow(appOp, Process.myUid(),
                context.getPackageName());
        return mode == AppOpsManager.MODE_ALLOWED;
    }
PermissionsUtil是个工具类,最常用的就是上面两个了。

该类中的意外发现是LocalBroadcastManager,详细见点击打开链接,它只会在进程内广播,不会影响别的进程(也就不受别的进程的影响),代码中发送消息的又一个工具。

其它

其实app使用系统签名就不会弹出权限申请框而自动有权限了。Android.mk中

LOCAL_CERTIFICATE := platform



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值