[Android]动态权限管理

    Android 6.0之后有些权限需要动态申请,这里先记录一下哪些权限是需要动态申请的,方便以后查看
 

Android 6.0之后需要动态申请的权限
Permission Group Permission
android.permission-group.CALENDER

android.permission.READ_CALENDAR

android.permission.WRITE_CALENDAR

android.permission-group.CAMERA android.permission.CAMERA
android.permission-group.CONTACTS

android.permission.WRITE_CONTACTS

android.permission.GET_ACCOUNTS

android.permission.READ_CONTACTS

android.permission-group.SENSORS android.permission.BODY_SENSORS
android.permission-group.LOCATION

android.permission.ACCESS_FINE_LOCATION

android.permission.ACCESS_COARSE_LOCATION

android.permission-group.STORAGE

android.permission.READ_EXTERNAL_STORAGE

android.permission.WRITE_EXTERNAL_STORAGE

android.permission-group.MICROPHONE android.permission.RECORD_AUDIO
android.permission-group.SMS

android.permission.READ_SMS

android.permission.RECEIVE_WAP_PUSH

android.permission.RECEIVE_MMS

android.permission.RECEIVE_SMS

android.permission.SEND_SMS

android.permission.SEND_SMS

android.permission-group.PHONE

android.permission.READ_CALL_LOG

android.permission.READ_PHONE_STATE

android.permission.CALL_PHONE

android.permission.WRITE_CALL_LOG

android.permission.USE_SIP

android.permission.PROCESS_OUTGOING_CALLS

com.android.voicemail.permission.ADD_VOICEMAIL

先记录到这里

        这两天写通讯录相关的东西看了看Android这部分相关的源码,然后看到了一个有意思的东西:PermissionsUtils,Android源码每个应用都会写这么一个工具类,这里类里包含此应用需要的相关权限。我把我写的通讯录的相关的代码贴到这里做个示例:

PermissionUtil类:

import android.Manifest.permission;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Process;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager;

public class PermissionUtil {

    public static final String PHONE = permission.CALL_PHONE;
    public static final String CONTACTS = permission.READ_CONTACTS;
    public static final String LOCATION = permission.ACCESS_FINE_LOCATION;

    public static boolean hasPhonePermissions(Context context) {
        return hasPermission(context, PHONE);
    }

    public static boolean hasContactsPermissions(Context context) {
        return hasPermission(context, CONTACTS);
    }

    public static boolean hasLocationPermissions(Context context) {
        return hasPermission(context, LOCATION);
    }

    public static boolean hasPermission(Context context, String permission) {
        return ContextCompat.checkSelfPermission(context, 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;
    }
}

RequestPermissionBaseActivity类(需要在build.gradle里加入   implementation 'com.github.dfqin:grantor:2.1.0'):


import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Trace;
import android.support.v4.app.ActivityCompat;

import com.github.dfqin.grantor.PermissionsUtil;

import java.util.ArrayList;
import java.util.Arrays;

public abstract class RequestPermissionBaseActivity extends Activity implements ActivityCompat.OnRequestPermissionsResultCallback {

    public static final String PREVIOUS_ACTIVITY_INTENT = "previous_intent";

    /**
     * Whether the permissions activity was already started.
     */
    protected static final String EXTRA_STARTED_PERMISSIONS_ACTIVITY =
            "started_permissions_activity";

    protected static final String EXTRA_IS_CALLER_SELF = "is_caller_self";

    private static final int PERMISSIONS_REQUEST_ALL_PERMISSIONS = 1;

    /**
     * @return list of permissions that are needed in order for {@link #PREVIOUS_ACTIVITY_INTENT}
     * to operate. You only need to return a single permission per permission group you care about.
     */
    protected abstract String[] getPermissions();

    protected Intent mPreviousActivityIntent;

    /**
     * If true then start the target activity "for result" after permissions are granted.
     */
    protected boolean mIsCallerSelf;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPreviousActivityIntent = (Intent) getIntent().getExtras().get(PREVIOUS_ACTIVITY_INTENT);
        mIsCallerSelf = getIntent().getBooleanExtra(EXTRA_IS_CALLER_SELF, false);

        // 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();
        }
    }

    /**
     * If any permissions the Contacts app needs are missing, open an Activity
     * to prompt the user for these permissions. Moreover, finish the current activity.
     * <p>
     * This is designed to be called inside {@link android.app.Activity#onCreate}
     */
    protected static boolean startPermissionActivity(Activity activity,
                                                     String[] requiredPermissions, Class<?> newActivityClass) {
        return startPermissionActivity(activity, requiredPermissions, /* isCallerSelf */ false,
                newActivityClass);
    }

    protected static boolean startPermissionActivity(Activity activity,
                                                     String[] requiredPermissions, boolean isCallerSelf, Class<?> newActivityClass) {
        if (!hasPermissions(activity, requiredPermissions)) {
            final Intent intent = new Intent(activity, newActivityClass);
            activity.getIntent().putExtra(EXTRA_STARTED_PERMISSIONS_ACTIVITY, true);
            intent.putExtra(PREVIOUS_ACTIVITY_INTENT, activity.getIntent());
            intent.putExtra(EXTRA_IS_CALLER_SELF, isCallerSelf);
            activity.startActivity(intent);
            activity.finish();
            return true;
        }

        // Account type initialization must be delayed until the Contacts permission group
        // has been granted (since GET_ACCOUNTS) falls under that groups.  Previously it
        // was initialized in ContactApplication which would cause problems as
        // AccountManager.getAccounts would return an empty array. See b/22690336
//        AccountTypeManager.getInstance(activity);

        return false;
    }

    protected boolean isAllGranted(String permissions[], int[] grantResult) {
        for (int i = 0; i < permissions.length; i++) {
            if (grantResult[i] != PackageManager.PERMISSION_GRANTED
                    && isPermissionRequired(permissions[i])) {
                return false;
            }
        }
        return true;
    }

    private boolean isPermissionRequired(String p) {
        return Arrays.asList(getPermissions()).contains(p);
    }

    private void requestPermissions() {
        Trace.beginSection("requestPermissions");
        try {
            // Construct a list of missing permissions
            final ArrayList<String> unsatisfiedPermissions = new ArrayList<>();
            for (String permission : getPermissions()) {
                if (!PermissionsUtil.hasPermission(this, permission)) {
                    unsatisfiedPermissions.add(permission);
                }
            }
            if (unsatisfiedPermissions.size() == 0) {
                throw new RuntimeException("Request permission activity was called even"
                        + " though all permissions are satisfied.");
            }
            ActivityCompat.requestPermissions(
                    this,
                    unsatisfiedPermissions.toArray(new String[unsatisfiedPermissions.size()]),
                    PERMISSIONS_REQUEST_ALL_PERMISSIONS);
        } finally {
            Trace.endSection();
        }
    }

    protected static boolean hasPermissions(Context context, String[] permissions) {
        Trace.beginSection("hasPermission");
        try {
            for (String permission : permissions) {
                if (!PermissionsUtil.hasPermission(context, permission)) {
                    return false;
                }
            }
            return true;
        } finally {
            Trace.endSection();
        }
    }
}

RequestPermissionsActivity类:

/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import android.Manifest.permission;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.v4.content.LocalBroadcastManager;
import android.widget.Toast;

import com.soundai.contacts.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Activity that requests permissions needed for activities exported from Contacts.
 */
public class RequestPermissionsActivity extends RequestPermissionBaseActivity {

    public static final String BROADCAST_PERMISSIONS_GRANTED = "broadcastPermissionsGranted";

    private static String[] sRequiredPermissions;

    @Override
    protected String[] getPermissions() {
        return getPermissions(getPackageManager());
    }

    /**
     * Method to check if the required permissions are given.
     */
    public static boolean hasRequiredPermissions(Context context) {
        return hasPermissions(context, getPermissions(context.getPackageManager()));
    }

    public static boolean startPermissionActivityIfNeeded(Activity activity) {
        return startPermissionActivity(activity,
                getPermissions(activity.getPackageManager()),
                RequestPermissionsActivity.class);
    }

    private static String[] getPermissions(PackageManager packageManager) {
        if (sRequiredPermissions == null) {
            final List<String> permissions = new ArrayList<>();
            // Contacts相关权限,如果各位想在自己的应用里使用,这里要改成自己申请的权限
//            permissions.add(permission.GET_ACCOUNTS);
            permissions.add(permission.READ_CONTACTS);
            permissions.add(permission.WRITE_CONTACTS);

            // 检查手机是否有相关功能模块,如果有该模块才申请相关权限
            // Phone group
            // These are only used in a few places such as QuickContactActivity and
            // ImportExportDialogFragment.  We work around missing this permission when
            // telephony is not available on the device (i.e. on tablets).
            if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
                permissions.add(permission.CALL_PHONE);
//                permissions.add(permission.READ_CALL_LOG);
//                permissions.add(permission.READ_PHONE_STATE);
            }
            sRequiredPermissions = permissions.toArray(new String[0]);
        }
        return sRequiredPermissions;
    }

    @Override
    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);
            if (mIsCallerSelf) {
                startActivityForResult(mPreviousActivityIntent, 0);
            } else {
                startActivity(mPreviousActivityIntent);
            }
            finish();
            overridePendingTransition(0, 0);

            LocalBroadcastManager.getInstance(this).sendBroadcast(
                    new Intent(BROADCAST_PERMISSIONS_GRANTED));
        } else {
            Toast.makeText(this, R.string.missing_required_permission, Toast.LENGTH_SHORT).show();
            finish();
        }
    }
}

在Activity中的使用就很简单了,只需要在需要的Activity中    setContentView()前加入这段话:

RequestPermissionsActivity.startPermissionActivityIfNeeded(this);

就可以了。这里的RequestPermissionBaseActivity和RequestPermissionsActivity是从Android源码里拷贝出来的,稍微做了修改,另外引入了第三方的包,用起来感觉还是蛮顺手的。

发布了61 篇原创文章 · 获赞 2 · 访问量 8727

猜你喜欢

转载自blog.csdn.net/woaily1346/article/details/84544148