当前位置: 首页 > 工具软件 > data_location > 使用案例 >

Android 10/Android Q定位服务授权失败,ACCESS_BACKGROUND_LOCATION

欧阳高昂
2023-12-01

今天遇到一个问题,华为部分机型定位失败,出现

Manifest.permission.ACCESS_BACKGROUND_LOCATION

此权限为定位服务权限,根据权限管理,加入以下代码

public String[] checkMMPerms() {
        String[] perms;
        if (Build.VERSION.SDK_INT >= 23) {

            perms = new String[(Build.VERSION.SDK_INT >= 29) ? 4 : 3];
            perms[0] = Manifest.permission.WRITE_EXTERNAL_STORAGE;
            perms[1] = Manifest.permission.RECORD_AUDIO;
            perms[2] = Manifest.permission.ACCESS_FINE_LOCATION;
            if (Build.VERSION.SDK_INT >= 29) {
                perms[3] = Manifest.permission.ACCESS_BACKGROUND_LOCATION;

            }

            return perms;
        }else {
            perms = new String[1];
            perms[0] = Manifest.permission.WRITE_EXTERNAL_STORAGE;
            return perms;
        }
    }
permissionsUtil=  PermissionsUtil
                    .with(this)
                    .requestCode(requestCode)
                    .isDebug(true)//开启log
                    .permissions(checkMMPerms())
                    .request();

PermissionsUtil为自定义的权限管理类。

之后问题来了,定位服务已经授权,依旧提示授权失败。

最后发现弹出权限的时候选择【仅适用期间允许】,定位服务勾选后是无效的,只能选择【始终允许】才可以。

以下为全部代码:

public class PermissionsUtil {

    private PermissionsUtil() {
    }

    /**
     * 危险权限,targetSdkVersion >=23必须动态申请
     */
    public static final class Permission {
        private static final List<String> sCalendars = new ArrayList<>(2);
        private static final List<String> sCameras = new ArrayList<>(1);
        private static final List<String> sContactes = new ArrayList<>(3);
        private static final List<String> sLocations = new ArrayList<>(2);
        private static final List<String> sMicrophones = new ArrayList<>(1);
        private static final List<String> sPhones = new ArrayList<>(7);
        private static final List<String> sSensorses = new ArrayList<>(1);
        private static final List<String> sSmses = new ArrayList<>(5);
        private static final List<String> sStorages = new ArrayList<>(2);

        static {
            //Calendar
            sCalendars.add(Calendar.READ_CALENDAR);
            sCalendars.add(Calendar.WRITE_CALENDAR);
            //Camera
            sCameras.add(Camera.CAMERA);
            //Contacts
            sContactes.add(Contacts.WRITE_CONTACTS);
            sContactes.add(Contacts.READ_CONTACTS);
            sContactes.add(Contacts.GET_ACCOUNTS);
            //Location
            sLocations.add(Location.ACCESS_FINE_LOCATION);
            sLocations.add(Location.ACCESS_COARSE_LOCATION);
            //Microphone
            sMicrophones.add(Microphone.RECORD_AUDIO);
            //Phone
            sPhones.add(Phone.READ_PHONE_STATE);
            sPhones.add(Phone.CALL_PHONE);
            sPhones.add(Phone.READ_CALL_LOG);
            sPhones.add(Phone.WRITE_CALL_LOG);
            sPhones.add(Phone.ADD_VOICEMAIL);
            sPhones.add(Phone.USE_SIP);
            sPhones.add(Phone.PROCESS_OUTGOING_CALLS);
            //Sensors
            sSensorses.add(Sensors.BODY_SENSORS);
            //Sms
            sSmses.add(Sms.SEND_SMS);
            sSmses.add(Sms.RECEIVE_SMS);
            sSmses.add(Sms.READ_SMS);
            sSmses.add(Sms.RECEIVE_WAP_PUSH);
            sSmses.add(Sms.RECEIVE_MMS);
            //Storage
            sStorages.add(Storage.READ_EXTERNAL_STORAGE);
            sStorages.add(Storage.WRITE_EXTERNAL_STORAGE);
            sStorages.add(Storage.MANAGE_EXTERNAL_STORAGE);
            //手机本机码
            sStorages.add(PhoneNumber.READ_PHONE_NUMBERS);
        }

        public static final class Calendar {
            public static final String READ_CALENDAR = Manifest.permission.READ_CALENDAR;
            public static final String WRITE_CALENDAR = Manifest.permission.WRITE_CALENDAR;
            private static final String MSG = "日历";
        }

        public static final class Camera {
            public static final String CAMERA = Manifest.permission.CAMERA;
            private static final String MSG = "相机";
        }

        public static final class Contacts {
            public static final String READ_CONTACTS = Manifest.permission.READ_CONTACTS;
            public static final String WRITE_CONTACTS = Manifest.permission.WRITE_CONTACTS;
            public static final String GET_ACCOUNTS = Manifest.permission.GET_ACCOUNTS;
            private static final String MSG = "联系人";
        }

        public static final class Location {
            public static final String ACCESS_FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
            public static final String ACCESS_COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
            private static final String MSG = "定位";
        }

        public static final class Microphone {
            public static final String RECORD_AUDIO = Manifest.permission.RECORD_AUDIO;
            private static final String MSG = "麦克风";
        }

        public static final class Phone {
            public static final String READ_PHONE_STATE = Manifest.permission.READ_PHONE_STATE;
            public static final String CALL_PHONE = Manifest.permission.CALL_PHONE;
            public static final String READ_CALL_LOG = Manifest.permission.READ_CALL_LOG;
            public static final String WRITE_CALL_LOG = Manifest.permission.WRITE_CALL_LOG;
            public static final String ADD_VOICEMAIL = Manifest.permission.ADD_VOICEMAIL;
            public static final String USE_SIP = Manifest.permission.USE_SIP;
            public static final String PROCESS_OUTGOING_CALLS = Manifest.permission.PROCESS_OUTGOING_CALLS;
            private static final String MSG = "电话";
        }

        public static final class Sensors {
            public static final String BODY_SENSORS = Manifest.permission.BODY_SENSORS;
            private static final String MSG = "传感器";
        }


        public static final class Sms {
            public static final String SEND_SMS = Manifest.permission.SEND_SMS;
            public static final String RECEIVE_SMS = Manifest.permission.RECEIVE_SMS;
            public static final String READ_SMS = Manifest.permission.READ_SMS;
            public static final String RECEIVE_WAP_PUSH = Manifest.permission.RECEIVE_WAP_PUSH;
            public static final String RECEIVE_MMS = Manifest.permission.RECEIVE_MMS;
            private static final String MSG = "短信";
        }

        public static final class Storage {
            public static final String READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE;
            public static final String WRITE_EXTERNAL_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
            public static final String MANAGE_EXTERNAL_STORAGE = Manifest.permission.MANAGE_EXTERNAL_STORAGE;
            private static final String MSG = "存储";
        }
        public static final class PhoneNumber {
            public static final String READ_PHONE_NUMBERS = Manifest.permission.READ_PHONE_NUMBERS;
            private static final String MSG = "手机标识码";
        }
    }

    public static final int SETTINGS_REQ_CODE = 99;
    private static final String TAG = "PermissionsUtil";
    private static final String KEY_DENIED_PERMISSIONS = "deniedPermissions";
    private static final String KEY_REQUEST_CODE = "requestCode";
    private static final int MSG_UI_HANDLER_DEAL_DENIED_PERMISSION = 100;
    private static boolean sDebug = true;
    private Object mObject;
    private String[] mPermissions;
    private int mRequestCode;
    private String mRationaleTitle;
    private String mPositiveText = "确定";
    private String mNegativeText = "取消";
    private Handler mUiHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_UI_HANDLER_DEAL_DENIED_PERMISSION:
                    Bundle data = msg.getData();
                    int requestCode = data.getInt(KEY_REQUEST_CODE);
                    String[] permissions = data.getStringArray(KEY_DENIED_PERMISSIONS);
                    Object object = msg.obj;
                    showAlertDialog(object, requestCode, permissions);
                    break;
            }
        }
    };


    private PermissionsUtil(@NonNull Object object) {
        if (isObjectIllegality(object))
            throw new IllegalArgumentException("Activity or Fragment must implements IPermissionsCallback");
        mObject = object;
    }
    public static PermissionsUtil with(@NonNull Application application) {
        return new PermissionsUtil(application);
    }

    public static PermissionsUtil with(@NonNull Activity activity) {
        return new PermissionsUtil(activity);
    }

    public static PermissionsUtil with(@NonNull Fragment fragment) {
        return new PermissionsUtil(fragment);
    }

    public static PermissionsUtil with(@NonNull android.app.Fragment fragment) {
        return new PermissionsUtil(fragment);
    }

    public PermissionsUtil permissions(@NonNull String... permissions) {
        if (hasEmpty(permissions))
            throw new IllegalArgumentException("permissions can't contain null");
        mPermissions = permissions;
        return this;
    }

    public PermissionsUtil requestCode(int requestCode) {
        mRequestCode = requestCode;
        return this;
    }

    public PermissionsUtil rationaleTitle(String title) {
        mRationaleTitle = title;
        return this;
    }

    public PermissionsUtil positiveText(String positiveText) {
        mPositiveText = positiveText;
        return this;
    }

    public PermissionsUtil negativeText(String negativeText) {
        mNegativeText = negativeText;
        return this;
    }

    public PermissionsUtil isDebug(boolean isDebug) {
        sDebug = isDebug;
        return this;
    }

    public PermissionsUtil request() {
        request(mObject, mRequestCode, mPermissions);
        return this;
    }

    public void request(Object object, int requestCode, String... permissions) {
        if (needRequest() && notGrantedAllPermissions(getActivity(object), permissions)) {
            List<String> unGrantedPermissionsList = createUnGrantedPermissionsList(object, permissions);
            PLog.e("TAG权限request---" + "requestCode : " + requestCode + "---unGrantedPermissionsList : " + unGrantedPermissionsList);
            if (unGrantedPermissionsList.size() > 0) {
                requestPermissions(object, requestCode, listToStringArray(unGrantedPermissionsList));
                unGrantedPermissionsList.clear();
            } else {
                invokePermissionsGranted(object, requestCode, permissions);
            }
            unGrantedPermissionsList = null;
        } else {
            PLog.e("TAG权限request---" + "requestCode : " + requestCode + "---permissionsGranted : " + stringArrayToList(permissions));
            invokePermissionsGranted(object, requestCode, permissions);
        }
    }

    private List<String> createUnGrantedPermissionsList(Object object, String... permissions) {
        List<String> unGrantedPermissionsList = new ArrayList<>();
        for (String permission : permissions) {
            if (notGrantedPermission(getActivity(object), permission)) {
                unGrantedPermissionsList.add(permission);
            }
        }
        return unGrantedPermissionsList;
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    private void requestPermissions(Object object, int requestCode, String... permissions) {
        PLog.d("requestPermissions---" + "requestCode : " + requestCode + "---requestPermissions : " + stringArrayToList(permissions));
        if (object instanceof Activity) {
            ActivityCompat.requestPermissions((Activity) object, permissions, requestCode);
        } else if (object instanceof Fragment) {
            ((Fragment) object).requestPermissions(permissions, requestCode);
        } else if (object instanceof android.app.Fragment) {
            ((android.app.Fragment) object).requestPermissions(permissions, requestCode);
        }
    }

    /**
     * @param object
     * @param requestCode
     * @param deniedPermissions denied permissions
     * @return
     */
    private void showAlertDialog(final Object object, final int requestCode, final String... deniedPermissions) {
        PLog.d("showAlertDialog --- " + "requestCode : " + requestCode + "--- deniedPermissions : " + stringArrayToList(deniedPermissions));
        new AlertDialog(getActivity(mObject)).builder().setTitle(getString(R.string.title_tip))
                .setMsg(createRationaleMsg(getActivity(object), deniedPermissions))
                .setPositiveButton(getString(R.string.ok), new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        goSetting(object);
                    }
                }).setNegativeButton(getString(R.string.personal_cancle), new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                invokePermissionsDenied(object, requestCode, deniedPermissions);
            }
        }).show();
    }
    @NonNull
    private final String getString(@StringRes int resId) {
        return getActivity(mObject).getResources().getString(resId);
    }
    private boolean needRequest() {
        return Build.VERSION.SDK_INT >= 23;
    }

    private Activity getActivity(Object object) {
        Activity activity = null;
        if (object instanceof Activity) {
            activity = (Activity) object;
        } else if (object instanceof Fragment) {
            activity = ((Fragment) object).getActivity();
        } else if (object instanceof android.app.Fragment) {
            activity = ((android.app.Fragment) object).getActivity();
        }
        return activity;
    }

    public boolean grantedPermission(Activity activity, String permission) {
        return ContextCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED;
    }

    public boolean notGrantedPermission(Activity activity, String permission) {
        return !grantedPermission(activity, permission);
    }

    public boolean grantedAllPermissions(Activity activity, String... permissions) {
        for (String permission : permissions) {
            if (notGrantedPermission(activity, permission)) {
                return false;
            }
        }
        return true;
    }

    public boolean notGrantedAllPermissions(Activity activity, String... permissions) {
        return !grantedAllPermissions(activity, permissions);
    }

    private void dealDeniedPermissions(Object object, int requestCode, String... deniedPermissions) {
        Log.e("TAG_定位权限","requestCode : " + requestCode +
                "--- deniedPermissions : " + stringArrayToList(deniedPermissions));
        Message message = mUiHandler.obtainMessage();
        Bundle bundle = new Bundle();
        bundle.putStringArray(KEY_DENIED_PERMISSIONS, deniedPermissions);
        bundle.putInt(KEY_REQUEST_CODE, requestCode);
        message.setData(bundle);
        message.obj = object;
        message.what = MSG_UI_HANDLER_DEAL_DENIED_PERMISSION;
        mUiHandler.sendMessage(message);
    }

    private boolean isObjectLegal(Object object) {
        return (object instanceof IPermissionsCallback);
    }

    private boolean isObjectIllegality(Object object) {
        return !isObjectLegal(object);
    }

    private boolean hasEmpty(String... strings) {
        boolean hasEmpty = false;
        if (strings != null && strings.length > 0) {
            for (String s : strings) {
                if (TextUtils.isEmpty(s)) {
                    hasEmpty = true;
                    break;
                }
            }
        } else {
            hasEmpty = true;
        }
        return hasEmpty;
    }

    private String[] listToStringArray(List<String> stringList) {
        return stringList.toArray(new String[stringList.size()]);
    }

    private List<String> stringArrayToList(String[] strings) {
        return Arrays.asList(strings);
    }

    private String getAppName(Context context) {
        String appName = "";
        PackageManager packageManager = context.getPackageManager();
        try {
            ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);
            appName = (String) packageManager.getApplicationLabel(applicationInfo);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return appName;
    }

    private String createRationaleMsg(Context context, String... permissions) {
        String permissionsMsg = createPermissionsMsg(permissions);
        Log.e("TAG_定位权限","permissionsMsg : " + permissionsMsg);
//        permissionsMsg = permissionsMsg.substring(0, permissionsMsg.length() - 1);
        return getAppName(context) + "需要" + permissionsMsg + "权限,是否去设置";
    }

    private String createPermissionsMsg(String... permissions) {
        StringBuilder builder = new StringBuilder();
        boolean grantedCalendar = false;
        boolean grantedCamera = false;
        boolean grantedContacts = false;
        boolean grantedLocation = false;
        boolean grantedMicrophone = false;
        boolean grantedPhone = false;
        boolean grantedSensors = false;
        boolean grantedSms = false;
        boolean grantedStorage = false;
        for (String permission : permissions) {
            if (!grantedCalendar && Permission.sCalendars.contains(permission)) {
                builder.append(Permission.Calendar.MSG);
                builder.append("、");
                grantedCalendar = true;
            }
            if (!grantedCamera && Permission.sCameras.contains(permission)) {
                builder.append(Permission.Camera.MSG);
                builder.append("、");
                grantedCamera = true;
            }
            if (!grantedContacts && Permission.sContactes.contains(permission)) {
                builder.append(Permission.Contacts.MSG);
                builder.append("、");
                grantedContacts = true;
            }
            if (!grantedLocation && Permission.sLocations.contains(permission)) {
                builder.append(Permission.Location.MSG);
                builder.append("、");
                grantedLocation = true;
            }
            if (!grantedMicrophone && Permission.sMicrophones.contains(permission)) {
                builder.append(Permission.Microphone.MSG);
                builder.append("、");
                grantedMicrophone = true;
            }
            if (!grantedPhone && Permission.sPhones.contains(permission)) {
                builder.append(Permission.Phone.MSG);
                builder.append("、");
                grantedPhone = true;
            }
            if (!grantedSensors && Permission.sSensorses.contains(permission)) {
                builder.append(Permission.Sensors.MSG);
                builder.append("、");
                grantedSensors = true;
            }
            if (!grantedSms && Permission.sSmses.contains(permission)) {
                builder.append(Permission.Sms.MSG);
                builder.append("、");
                grantedSms = true;
            }
            if (!grantedStorage && Permission.sStorages.contains(permission)) {
                builder.append(Permission.Storage.MSG);
                builder.append("、");
                grantedStorage = true;
            }

        }
        return builder.toString();
    }

    private IPermissionsCallback getPermissionsCallback(Object object) {
        return (IPermissionsCallback) object;
    }

    private void invokePermissionsGranted(Object object, int requestCode, String... permissions) {
        getPermissionsCallback(object).onPermissionsGranted(requestCode, permissions);
    }

    private void invokePermissionsDenied(Object object, int requestCode, String... permissions) {
        getPermissionsCallback(object).onPermissionsDenied(requestCode, permissions);
    }

    public interface IPermissionsCallback {
        //确认
        void onPermissionsGranted(int requestCode, String... permission);
        //拒绝
        void onPermissionsDenied(int requestCode, String... permission);
    }

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == mRequestCode) {
            List<String> deniedPermissions = new ArrayList<>();
            for (int i = 0; i < grantResults.length; i++) {
                if (grantResults[i] != PackageManager.PERMISSION_GRANTED)
                    deniedPermissions.add(permissions[i]);
            }
            PLog.d("TAG权限onRequestPermissionsResult--- " + "requestCode : " + requestCode + "--- deniedPermissions : " + deniedPermissions);
            if (deniedPermissions.size() > 0) {
                dealDeniedPermissions(mObject, requestCode, listToStringArray(deniedPermissions));
            } else {
                invokePermissionsGranted(mObject, requestCode, permissions);
            }
        }
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == SETTINGS_REQ_CODE) {
            List<String> unPermissionsList = createUnGrantedPermissionsList(mObject, mPermissions);

            if (unPermissionsList.size() > 0) {
                Log.e("TAG_权限","unPermissionsList="+unPermissionsList.toString()
                        +";resultCode="+resultCode);
//                if (unPermissionsList.size()==1
//                        && unPermissionsList.contains("android.permission.ACCESS_BACKGROUND_LOCATION")){
                    invokePermissionsGranted(mObject, mRequestCode, mPermissions);
//                }else {
//                    invokePermissionsDenied(mObject, mRequestCode, listToStringArray(unPermissionsList));
//                }
            } else {
                invokePermissionsGranted(mObject, mRequestCode, mPermissions);
            }
        }
    }

    private void goSetting(Object object) {
        PLog.d("goSetting");
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", getActivity(object).getPackageName(), null);
        intent.setData(uri);
        if (object instanceof Activity) {
            ((Activity) object).startActivityForResult(intent, SETTINGS_REQ_CODE);
        } else if (object instanceof Fragment) {
            ((Fragment) object).startActivityForResult(intent, SETTINGS_REQ_CODE);
        } else if (object instanceof android.app.Fragment) {
            ((android.app.Fragment) object).startActivityForResult(intent, SETTINGS_REQ_CODE);
        }
    }

    static final class PLog {
        private static void d(String msg) {
            if (sDebug)
                Log.d(TAG, msg);
        }

        private static void e(String msg) {
            if (sDebug)
                Log.e(TAG, msg);
        }
    }
}

基类重写onRequestPermissionsResult即可

@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        //需要调用onRequestPermissionsResult
        permissionsUtil.onRequestPermissionsResult(requestCode, permissions, grantResults);
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

如果需要刷新权限判断,比如刷新相机权限,需要重写onActivityResult方法

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case CAMERA_REQUESTCODE:
            //监听跳转到权限设置界面后再回到应用
            permissionsUtil.onActivityResult(requestCode, resultCode, data);

            break;
        default:
            super.onActivityResult(requestCode, resultCode, data);
            break;
    }
}
 类似资料: