// permissionUtils.js /** * 统一权限检测工具 * 支持平台:APP(Android/iOS)、微信小程序、H5 */ export default { /** * 检查权限状态 * @param {String} permission 权限类型 * @param {String} description 权限描述(仅APP端需要) * @returns {Promise} * - granted: 是否已授权 * - firstRequest: 是否第一次请求 * - canRequest: 是否可以请求(用户未永久拒绝) */ async checkPermission(permission, description = '') { // #ifdef APP-PLUS return await this._checkAppPermission(permission, description); // #endif // #ifdef MP-WEIXIN return await this._checkMpPermission(permission); // #endif // #ifdef H5 // H5默认返回已授权,实际权限由浏览器控制 return { granted: true, firstRequest: false, canRequest: false }; // #endif }, /** * APP端权限检查 */ async _checkAppPermission(permission, description) { // Android和iOS通用权限映射 const permissionMap = { 'camera': { android: 'android.permission.CAMERA', ios: 'camera' }, 'location': { android: 'android.permission.ACCESS_FINE_LOCATION', ios: 'location' }, 'phone': { android: 'android.permission.CALL_PHONE', ios: 'phone' }, 'photo_library': { android: [ 'android.permission.READ_EXTERNAL_STORAGE', 'android.permission.WRITE_EXTERNAL_STORAGE' ], ios: 'photo_library', } // 添加其他需要的权限... }; const platformPerm = permissionMap[permission]; if (!platformPerm) { console.error('不支持的权限类型:', permission); return { granted: false, firstRequest: false, canRequest: false }; } // #ifdef APP-PLUS if (plus.os.name === 'Android') { return this._checkAndroidPermission(platformPerm.android); }else { return this._checkIosPermission(platformPerm.ios, description); } // #endif return { granted: false, firstRequest: false, canRequest: false }; }, /** * Android权限检查 */ async _checkAndroidPermission(permission) { return new Promise((resolve) => { plus.android.requestPermissions( Array.isArray(permission) ? permission : [permission], (e) => { console.log(`perm_${permission}`,e) // 第一次请求标记 const firstRequest = !plus.storage.getItem(`perm_${permission}`); if (firstRequest) { plus.storage.setItem(`perm_${permission}`, '1'); } if(e.deniedPresent.length !== 0) { plus.storage.setItem(`perm_${permission}_no`, '2'); } if(e.granted.length !== 0) { plus.storage.removeItem(`perm_${permission}_no`, '2'); } resolve({ granted: e.granted.length !== 0, firstRequest, canRequest: true // Android可以重复请求 }); }, (e) => { resolve({ granted: false, firstRequest: false, canRequest: true }); } ); }); }, /** * iOS权限检查 */ async _checkIosPermission(permission, description) { try { let status; switch (permission) { case 'camera': status = plus.ios.invoke('AVCaptureDevice', 'authorizationStatusForMediaType:', 'vide'); break; case 'location': const locationManager = plus.ios.newObject('CLLocationManager'); status = plus.ios.invoke(locationManager, 'authorizationStatus'); plus.ios.deleteObject(locationManager); break; // 其他权限处理... default: return { granted: false, firstRequest: false, canRequest: false }; } // iOS授权状态 // 0: 未决定(第一次) // 1: 受限 // 2: 已拒绝 // 3: 已授权 return { granted: status === 3, firstRequest: status === 0, canRequest: status !== 2 // 不是永久拒绝 }; } catch (e) { console.error('iOS权限检查错误:', e); return { granted: false, firstRequest: false, canRequest: false }; } }, /** * 小程序权限检查 */ async _checkMpPermission(permission) { // 小程序scope映射 const scopeMap = { 'camera': 'scope.camera', 'location': 'scope.userLocation', 'record': 'scope.record', // 其他小程序权限... }; const scope = scopeMap[permission]; if (!scope) { return { granted: false, firstRequest: false, canRequest: false }; } return new Promise((resolve) => { uni.getSetting({ success(res) { const authSetting = res.authSetting; resolve({ granted: authSetting[scope] === true, firstRequest: authSetting[scope] === undefined, canRequest: authSetting[scope] !== false // 不是拒绝状态 }); }, fail() { resolve({ granted: false, firstRequest: false, canRequest: false }); } }); }); }, /** * 请求权限 */ async requestPermission(permission, description = '') { const { granted, firstRequest, canRequest } = await this.checkPermission(permission, description); if (granted) return true; if (!canRequest) return false; // #ifdef APP-PLUS return this._requestAppPermission(permission, description); // #endif // #ifdef MP-WEIXIN return this._requestMpPermission(permission); // #endif // #ifdef H5 return false; // H5无法主动请求权限 // #endif }, /** * APP端请求权限 */ async _requestAppPermission(permission, description) { // #ifdef APP-PLUS && ANDROID return new Promise((resolve) => { plus.android.requestPermissions( [permission], (e) => resolve(e.denied.length === 0), () => resolve(false) ); }); // #endif // #ifdef APP-PLUS && IOS return new Promise((resolve) => { switch (permission) { case 'camera': plus.ios.invoke('AVCaptureDevice', 'requestAccessForMediaType:completionHandler:', 'vide', (granted) => { resolve(granted); }); break; case 'location': const locationManager = plus.ios.newObject('CLLocationManager'); plus.ios.invoke(locationManager, 'requestWhenInUseAuthorization'); // iOS定位权限需要监听变化 setTimeout(() => { const status = plus.ios.invoke(locationManager, 'authorizationStatus'); plus.ios.deleteObject(locationManager); resolve(status === 3 || status === 4); }, 300); break; default: resolve(false); } }); // #endif return false; }, /** * 小程序请求权限 */ async _requestMpPermission(permission) { const scopeMap = { 'camera': 'scope.camera', 'location': 'scope.userLocation', 'record': 'scope.record', }; const scope = scopeMap[permission]; if (!scope) return false; return new Promise((resolve) => { uni.authorize({ scope, success: () => resolve(true), fail: () => resolve(false) }); }); }, /** * 打开系统设置页 */ openSystemSettings() { // #ifdef APP-PLUS if (plus.os.name === 'Android') { 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); } else { const UIApplication = plus.ios.import('UIApplication'); const NSURL = plus.ios.import('NSURL'); const url = NSURL.URLWithString('app-settings:'); const application = UIApplication.sharedApplication(); if (plus.ios.invoke(application, 'canOpenURL:', url)) { plus.ios.invoke(application, 'openURL:', url); } plus.ios.deleteObject(url); plus.ios.deleteObject(application); } // #endif // #ifdef MP-WEIXIN uni.openSetting(); // #endif // #ifdef H5 console.log('H5无法打开系统设置'); // #endif } };