123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- /**
- * 权限管理工具类
- * 用于iOS和Android的权限检查、请求和本地缓存
- */
- // 判断是否为iOS系统
- let isIos = false;
- // #ifdef APP-PLUS
- isIos = (plus.os.name == "iOS");
- // #endif
- /**
- * 权限类型枚举
- * @enum {string}
- */
- export const PermissionType = {
- // 相机权限
- CAMERA: 'camera',
- // 相册权限
- PHOTO_LIBRARY: 'photoLibrary',
- // 相册写入权限
- PHOTO_LIBRARY_ADD_ONLY: 'photoLibraryAddOnly',
- // 麦克风权限
- MICROPHONE: 'microphone',
- // 位置权限
- LOCATION: 'location',
- // 位置权限(始终允许)
- LOCATION_ALWAYS: 'locationAlways',
- // 位置权限(使用期间)
- LOCATION_WHEN_IN_USE: 'locationWhenInUse',
- // 位置权限(精确位置)
- LOCATION_PRECISE: 'locationPrecise',
- // 位置权限(粗略位置)
- LOCATION_APPROXIMATE: 'locationApproximate',
- // 通知权限
- NOTIFICATION: 'notification',
- // 通讯录权限
- CONTACTS: 'contacts',
- // 日历权限
- CALENDAR: 'calendar',
- // 备忘录权限
- MEMO: 'memo',
- // 蓝牙权限
- BLUETOOTH: 'bluetooth',
- // 蓝牙外设权限
- BLUETOOTH_PERIPHERAL: 'bluetoothPeripheral',
- // 蓝牙中心设备权限
- BLUETOOTH_CENTRAL: 'bluetoothCentral',
- // 健康数据权限
- HEALTH: 'health',
- // 运动与健身权限
- MOTION: 'motion',
- // 生物识别权限(指纹/面容)
- BIOMETRICS: 'biometrics',
- // 网络权限
- NETWORK: 'network',
- // 后台运行权限
- BACKGROUND_FETCH: 'backgroundFetch',
- // 后台处理权限
- BACKGROUND_PROCESSING: 'backgroundProcessing',
- // 后台音频播放权限
- BACKGROUND_AUDIO: 'backgroundAudio',
- // 后台位置更新权限
- BACKGROUND_LOCATION: 'backgroundLocation',
- // 后台网络权限
- BACKGROUND_NETWORK: 'backgroundNetwork',
- // 后台蓝牙权限
- BACKGROUND_BLUETOOTH: 'backgroundBluetooth',
- // 后台通知权限
- BACKGROUND_NOTIFICATION: 'backgroundNotification',
- // 后台传感器权限
- BACKGROUND_SENSOR: 'backgroundSensor',
- // 后台任务权限
- BACKGROUND_TASK: 'backgroundTask',
- // 后台下载权限
- BACKGROUND_DOWNLOAD: 'backgroundDownload',
- // 后台上传权限
- BACKGROUND_UPLOAD: 'backgroundUpload',
- // 后台同步权限
- BACKGROUND_SYNC: 'backgroundSync',
- // 后台定位权限
- BACKGROUND_LOCATION_ALWAYS: 'backgroundLocationAlways',
- // 后台定位权限(使用期间)
- BACKGROUND_LOCATION_WHEN_IN_USE: 'backgroundLocationWhenInUse',
- // 后台定位权限(精确位置)
- BACKGROUND_LOCATION_PRECISE: 'backgroundLocationPrecise',
- // 后台定位权限(粗略位置)
- BACKGROUND_LOCATION_APPROXIMATE: 'backgroundLocationApproximate'
- };
- // 默认权限说明配置
- const DefaultPermissionConfig = {
- [PermissionType.LOCATION]: {
- title: '定位权限说明',
- describe: '便于您使用该功能在位置展示时显示距搜索位置的距离,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.ACCESS_FINE_LOCATION',
- permissionName: '位置'
- },
- [PermissionType.LOCATION_ALWAYS]: {
- title: '后台定位权限说明',
- describe: '便于您在应用后台运行时获取位置信息,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.ACCESS_BACKGROUND_LOCATION',
- permissionName: '后台定位'
- },
- [PermissionType.LOCATION_WHEN_IN_USE]: {
- title: '使用期间定位权限说明',
- describe: '便于您在应用使用期间获取位置信息,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.ACCESS_COARSE_LOCATION',
- permissionName: '使用期间定位'
- },
- [PermissionType.PHOTO_LIBRARY]: {
- title: '相册权限说明',
- describe: '便于您使用该功能上传您的照片/图片/及用户修改头像,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.READ_EXTERNAL_STORAGE',
- permissionName: '相册'
- },
- [PermissionType.PHOTO_LIBRARY_ADD_ONLY]: {
- title: '相册写入权限说明',
- describe: '便于您保存图片到相册,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.WRITE_EXTERNAL_STORAGE',
- permissionName: '相册写入'
- },
- [PermissionType.CAMERA]: {
- title: '拍摄权限说明',
- describe: '便于您使用该功能拍摄照片修改头像、意见反馈上传图片等信息,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.CAMERA',
- permissionName: '相机'
- },
- [PermissionType.MICROPHONE]: {
- title: '麦克风权限说明',
- describe: '便于您使用该功能录制音频,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.RECORD_AUDIO',
- permissionName: '麦克风'
- },
- [PermissionType.NOTIFICATION]: {
- title: '通知权限说明',
- describe: '便于您接收重要消息通知,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.POST_NOTIFICATIONS',
- permissionName: '通知'
- },
- [PermissionType.CONTACTS]: {
- title: '通讯录权限说明',
- describe: '便于您使用该功能访问通讯录,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.READ_CONTACTS',
- permissionName: '通讯录'
- },
- [PermissionType.CALENDAR]: {
- title: '日历权限说明',
- describe: '便于您使用该功能访问日历,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.READ_CALENDAR',
- permissionName: '日历'
- },
- [PermissionType.MEMO]: {
- title: '备忘录权限说明',
- describe: '便于您使用该功能访问备忘录,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.READ_CALENDAR',
- permissionName: '备忘录'
- },
- [PermissionType.BLUETOOTH]: {
- title: '蓝牙权限说明',
- describe: '便于您使用蓝牙功能,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.BLUETOOTH',
- permissionName: '蓝牙'
- },
- [PermissionType.BLUETOOTH_PERIPHERAL]: {
- title: '蓝牙外设权限说明',
- describe: '便于您使用蓝牙外设功能,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.BLUETOOTH_ADMIN',
- permissionName: '蓝牙外设'
- },
- [PermissionType.BLUETOOTH_CENTRAL]: {
- title: '蓝牙中心设备权限说明',
- describe: '便于您使用蓝牙中心设备功能,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.BLUETOOTH_SCAN',
- permissionName: '蓝牙中心设备'
- },
- [PermissionType.HEALTH]: {
- title: '健康数据权限说明',
- describe: '便于您使用健康数据相关功能,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.ACTIVITY_RECOGNITION',
- permissionName: '健康数据'
- },
- [PermissionType.MOTION]: {
- title: '运动与健身权限说明',
- describe: '便于您使用运动与健身相关功能,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.ACTIVITY_RECOGNITION',
- permissionName: '运动与健身'
- },
- [PermissionType.BIOMETRICS]: {
- title: '生物识别权限说明',
- describe: '便于您使用指纹/面容识别功能,请您确认授权,否则无法使用该功能',
- androidPermission: 'android.permission.USE_BIOMETRICS',
- permissionName: '生物识别'
- }
- };
- /**
- * 获取权限配置
- * @param {string} permissionType 权限类型
- * @param {Object} customConfig 自定义配置
- * @returns {Object} 权限配置
- */
- function getPermissionConfig(permissionType, customConfig = {}) {
- const defaultConfig = DefaultPermissionConfig[permissionType] || {
- title: '权限说明',
- describe: '便于您使用该功能,请您确认授权,否则无法使用该功能',
- androidPermission: '',
- permissionName: '未知权限'
- };
- return {
- ...defaultConfig,
- ...customConfig
- };
- }
- // iOS权限相关的常量和工具函数
- const IOS_PERMISSION_HANDLERS = {
- // 定位权限
- location: {
- check: () => {
- const cllocationManger = plus.ios.import("CLLocationManager");
- const status = cllocationManger.authorizationStatus();
- const result = (status != 2) ? 1 : 0;
- plus.ios.deleteObject(cllocationManger);
- return result;
- },
- request: () => {
- return new Promise((resolve) => {
- const cllocationManger = plus.ios.import("CLLocationManager");
- const manager = new cllocationManger();
- manager.requestWhenInUseAuthorization();
- plus.ios.deleteObject(manager);
- plus.ios.deleteObject(cllocationManger);
- setTimeout(() => resolve(IOS_PERMISSION_HANDLERS.location.check() === 1), 1000);
- });
- }
- },
- // 相机权限
- camera: {
- check: () => {
- const AVCaptureDevice = plus.ios.import("AVCaptureDevice");
- const authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide');
- const result = authStatus === 3 ? 1 : 0;
- plus.ios.deleteObject(AVCaptureDevice);
- return result;
- },
- request: () => {
- return new Promise((resolve) => {
- const AVCaptureDevice = plus.ios.import("AVCaptureDevice");
- AVCaptureDevice.requestAccessForMediaTypeCompletionHandler('vide', (granted) => {
- plus.ios.deleteObject(AVCaptureDevice);
- resolve(granted);
- });
- });
- }
- },
- // 相册权限
- photoLibrary: {
- check: () => {
- const PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");
- const authStatus = PHPhotoLibrary.authorizationStatus();
- const result = authStatus === 3 ? 1 : 0;
- plus.ios.deleteObject(PHPhotoLibrary);
- return result;
- },
- request: () => {
- return new Promise((resolve) => {
- const PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");
- PHPhotoLibrary.requestAuthorization((status) => {
- plus.ios.deleteObject(PHPhotoLibrary);
- resolve(status === 3);
- });
- });
- }
- },
- // 麦克风权限
- microphone: {
- check: () => {
- const avaudiosession = plus.ios.import("AVAudioSession");
- const avaudio = avaudiosession.sharedInstance();
- const permissionStatus = avaudio.recordPermission();
- const result = (permissionStatus !== 1684369017 && permissionStatus !== 1970168948) ? 1 : 0;
- plus.ios.deleteObject(avaudiosession);
- return result;
- },
- request: () => {
- return new Promise((resolve) => {
- const avaudiosession = plus.ios.import("AVAudioSession");
- const avaudio = avaudiosession.sharedInstance();
- avaudio.requestRecordPermission((granted) => {
- plus.ios.deleteObject(avaudiosession);
- resolve(granted);
- });
- });
- }
- },
- // 其他iOS权限处理器...
- };
- // Android权限处理
- const ANDROID_PERMISSION_HANDLERS = {
- request: (permissionID) => {
- return new Promise((resolve) => {
- plus.android.requestPermissions(
- [permissionID],
- (resultObj) => {
- let result = 0;
- if (resultObj.granted.length > 0) {
- result = 1;
- } else if (resultObj.deniedAlways.length > 0) {
- result = -1;
- }
- resolve(result);
- },
- (error) => {
- console.error('Request permission error:', error);
- resolve(0);
- }
- );
- });
- }
- };
- // 权限配置映射
- const PERMISSION_CONFIG = {
- [PermissionType.CAMERA]: {
- title: '相机权限申请',
- describe: '需要使用相机权限来拍摄照片',
- androidPermission: 'android.permission.CAMERA',
- iosHandler: 'camera'
- },
- [PermissionType.PHOTO_LIBRARY]: {
- title: '相册权限申请',
- describe: '需要访问相册权限来选择照片',
- androidPermission: 'android.permission.READ_EXTERNAL_STORAGE',
- iosHandler: 'photoLibrary'
- },
- // ... 其他权限配置
- };
- // 统一的权限处理类
- class PermissionManager {
- static async check(permissionType) {
- const config = PERMISSION_CONFIG[permissionType];
- if (!config) return false;
- if (isIos) {
- const handler = IOS_PERMISSION_HANDLERS[config.iosHandler];
- return handler ? handler.check() === 1 : false;
- } else {
- const MainActivity = plus.android.runtimeMainActivity();
- const permission = config.androidPermission;
- return MainActivity.checkSelfPermission(permission) === 0;
- }
- }
- /**
- * 请求权限
- * @param {string} permissionType 权限类型
- * @param {Object} options 配置选项
- * @returns {Promise<boolean>} 是否获得权限
- */
- static async request(permissionType, options = {}) {
- // 在 H5 环境下直接返回 true
- // #ifdef H5
- return true;
- // #endif
- const config = getPermissionConfig(permissionType, options);
- if (!config) return false;
- // 先检查权限
- const hasPermission = await this.check(permissionType);
- if (hasPermission) return true;
- // 显示权限申请对话框
- const dialogResult = await showPermissionDialog(config);
- if (!dialogResult) return false;
- // #ifdef APP-PLUS
- if (isIos) {
- // iOS权限请求逻辑
- return true;
- } else {
- // Android权限请求
- const result = await ANDROID_PERMISSION_HANDLERS.request(config.androidPermission);
-
- // 如果权限被永久拒绝,引导用户去设置页面
- if (result === -1) {
- return new Promise((resolve) => {
- uni.showModal({
- title: '权限申请',
- content: `${config.permissionName}权限被永久拒绝,请到设置中手动开启`,
- confirmText: '去设置',
- cancelText: '取消',
- success: function(res) {
- if (res.confirm) {
- // 跳转到应用权限设置页面
- if (plus.os.name.toLowerCase() === 'android') {
- const main = plus.android.runtimeMainActivity();
- const Intent = plus.android.importClass('android.content.Intent');
- const Settings = plus.android.importClass('android.provider.Settings');
- const Uri = plus.android.importClass('android.net.Uri');
- const intent = new Intent();
- intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
- const uri = Uri.fromParts('package', main.getPackageName(), null);
- intent.setData(uri);
- main.startActivity(intent);
- }
- }
- resolve(false);
- }
- });
- });
- }
-
- return result === 1;
- }
- // #endif
- return false;
- }
- static openSettings() {
- if (isIos) {
- const UIApplication = plus.ios.import("UIApplication");
- const application = UIApplication.sharedApplication();
- const settingsUrl = plus.ios.newObject("NSURL").URLWithString("app-settings:");
- application.openURL(settingsUrl);
- plus.ios.deleteObject(settingsUrl);
- plus.ios.deleteObject(application);
- } else {
- const Intent = plus.android.importClass("android.content.Intent");
- const Settings = plus.android.importClass("android.provider.Settings");
- const Uri = plus.android.importClass("android.net.Uri");
- const MainActivity = plus.android.runtimeMainActivity();
-
- const intent = new Intent();
- intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
- const uri = Uri.fromParts("package", MainActivity.getPackageName(), null);
- intent.setData(uri);
- MainActivity.startActivity(intent);
- }
- }
- }
- // 显示权限说明弹窗
- const showPermissionDialog = (options) => {
- return new Promise((resolve) => {
- uni.showModal({
- title: options.title || '权限申请',
- content: options.content || options.describe,
- cancelText: '暂不授权',
- confirmText: '去授权',
- success: (res) => {
- resolve(res.confirm);
- }
- });
- });
- };
- /**
- * 清除权限缓存
- * @param {string} permissionType 权限类型,不传则清除所有权限缓存
- */
- function clearPermissionCache(permissionType) {
- if (permissionType) {
- uni.removeStorageSync(`permission_${permissionType}`);
- } else {
- // 清除所有权限缓存
- Object.values(PermissionType).forEach(type => {
- uni.removeStorageSync(`permission_${type}`);
- });
- }
- }
- // 导出模块
- export default {
- PermissionType,
- check: PermissionManager.check.bind(PermissionManager),
- request: PermissionManager.request.bind(PermissionManager),
- openSettings: PermissionManager.openSettings.bind(PermissionManager),
- showPermissionDialog,
- clearPermissionCache,
- getPermissionConfig
- };
|