import permisionUtil from "./permission.js" import { popup } from './native_popup.js' const prefix = 'permision_' const { uniPlatform, platform, osAndroidAPILevel, ...rest } = uni.getSystemInfoSync() let targetSdkVersion = 28 const getTargetSdkVersion = () => { const main = plus.android.runtimeMainActivity(); const pm = plus.android.invoke(main, 'getPackageManager'); const pkg = plus.android.invoke(main, 'getPackageName'); const appInfo = plus.android.invoke(pm, 'getApplicationInfo', pkg, 0); const targetSdk = plus.android.getAttribute(appInfo, 'targetSdkVersion'); return targetSdk } if (uniPlatform == 'app' && platform == 'android') { targetSdkVersion = getTargetSdkVersion() } const getAlbumPermission = async (type = "all") => { if (osAndroidAPILevel < 23) return 1 if (osAndroidAPILevel >= 33 && targetSdkVersion >= 33) { if (osAndroidAPILevel >= 34) { const limited = await permisionUtil.requestAndroidPermission('android.permission.READ_MEDIA_VISUAL_USER_SELECTED') if (type == 'image') return limited > 0 ? limited : await permisionUtil.requestAndroidPermission('android.permission.READ_MEDIA_IMAGES') if (type == 'video') return limited > 0 ? limited : await permisionUtil.requestAndroidPermission('android.permission.READ_MEDIA_VIDEO') const s1 = await permisionUtil.requestAndroidPermission('android.permission.READ_MEDIA_IMAGES') const s2 = await permisionUtil.requestAndroidPermission('android.permission.READ_MEDIA_VIDEO') return limited > 0 ? limited : (s2 == 1 && s2 == 1) } if (type == 'image') return await permisionUtil.requestAndroidPermission('android.permission.READ_MEDIA_IMAGES') if (type == 'video') return await permisionUtil.requestAndroidPermission('android.permission.READ_MEDIA_VIDEO') const s1 = await permisionUtil.requestAndroidPermission('android.permission.READ_MEDIA_IMAGES') const s2 = await permisionUtil.requestAndroidPermission('android.permission.READ_MEDIA_VIDEO') return s2 == 1 && s2 == 1 } return await permisionUtil.requestAndroidPermission('android.permission.READ_EXTERNAL_STORAGE') } const permisionMap = { album: async function() { try { const status = await getAlbumPermission() return Promise.resolve(status) } catch (e) { return Promise.resolve(0) } }, camera: async function() { try { const status = await permisionUtil.requestAndroidPermission('android.permission.CAMERA') return Promise.resolve(status) } catch (e) { return Promise.resolve(0) } }, chooseImage: async function() { try { const status1 = await permisionUtil.requestAndroidPermission('android.permission.CAMERA') const status2 = await getAlbumPermission('image') if (status1 == 1 || status2 == 1) { return Promise.resolve(1) } else { return Promise.resolve(-1) } } catch (e) { return Promise.resolve(0) } }, chooseVideo: async function() { try { const status1 = await permisionUtil.requestAndroidPermission('android.permission.CAMERA') const status2 = await getAlbumPermission('video') if (status1 == 1 || status2 == 1) { return Promise.resolve(1) } else { return Promise.resolve(-1) } } catch (e) { return Promise.resolve(0) } }, chooseMedia: async function() { try { const status1 = await permisionUtil.requestAndroidPermission('android.permission.CAMERA') const status2 = await getAlbumPermission() if (status1 == 1 || status2 == 1) { return Promise.resolve(1) } else { return Promise.resolve(-1) } } catch (e) { return Promise.resolve(0) } }, saveImageToPhotosAlbum: async function() { try { const status = await permisionUtil.requestAndroidPermission('android.permission.WRITE_EXTERNAL_STORAGE') return Promise.resolve(status) } catch (e) { return Promise.resolve(0) } }, saveVideoToPhotosAlbum: async function() { try { const status = await permisionUtil.requestAndroidPermission('android.permission.WRITE_EXTERNAL_STORAGE') return Promise.resolve(status) } catch (e) { return Promise.resolve(0) } }, getLocation: async function() { try { const status = await permisionUtil.requestAndroidPermission('android.permission.ACCESS_FINE_LOCATION') return Promise.resolve(status) } catch (e) { return Promise.resolve(0) } }, startLocationUpdate: async function() { try { const status = await permisionUtil.requestAndroidPermission('android.permission.ACCESS_FINE_LOCATION') return Promise.resolve(status) } catch (e) { return Promise.resolve(0) } }, makePhoneCall: async function() { try { const status = await permisionUtil.requestAndroidPermission('android.permission.CALL_PHONE') return Promise.resolve(status) } catch (e) { return Promise.resolve(0) } }, getRecorderManager: async function() { try { const status = await permisionUtil.requestAndroidPermission('android.permission.RECORD_AUDIO') return Promise.resolve(status) } catch (e) { return Promise.resolve(0) } }, startBluetoothDevicesDiscovery: async function() { try { const status1 = await permisionUtil.requestAndroidPermission('android.permission.ACCESS_FINE_LOCATION') const status2 = await permisionUtil.requestAndroidPermission('android.permission.BLUETOOTH_SCAN') const status3 = await permisionUtil.requestAndroidPermission('android.permission.BLUETOOTH_CONNECT') if (status1 == 1 && status2 == 1 && status3 == 1) { return Promise.resolve(1) } else { return Promise.resolve(-1) } } catch (e) { return Promise.resolve(0) } }, scanCode: async function() { try { const status1 = await permisionUtil.requestAndroidPermission('android.permission.CAMERA') const status2 = await getAlbumPermission('image') if (status1 == 1 || status2 == 1) { return Promise.resolve(1) } else { return Promise.resolve(-1) } } catch (e) { return Promise.resolve(0) } }, chooseFile: async function() { try { const status = await getAlbumPermission() return Promise.resolve(status) } catch (e) { return Promise.resolve(0) } }, } const resultHandler = function(args, err) { args.fail && args.fail(err) args.complete && args.complete(err) } let getRecorderManagerFlag = false const _getRecorderManager = uni.getRecorderManager const gotoAppPermissionSetting = function() { uni.showModal({ title: '提示', content: '当前功能需要开启相应权限,是否前往开启?', cancelText: '否', confirmText: '是', success: (res) => { if (res.confirm) { permisionUtil.gotoAppPermissionSetting() } } }) } /** * @func addPermisionInterceptor * @desc 添加权限申请说明拦截 * @param {String} permisionName 要拦截的 uniApi 名称 * @param {String} content 申请权限说明信息 * @param {Boolean} once 只询问一次, 用户不同意申请或拒绝权限将无法使用 uniApi, 如果要继续使用 Api 先用 removePermisionInterceptor 函数移除拦截再调用 Api * @return 无 * @Author Xingfei Xu * @Email 1824159241@qq.com */ export const addPermisionInterceptor = function(permisionName, content, once) { if (uniPlatform != 'app' || platform != 'android') return const getRecorderManagerAdapter = function() { const recorder = _getRecorderManager() const _start = recorder.start.bind(recorder) recorder.start = async function(options) { const perm = uni.getStorageSync(prefix + permisionName) if (perm == 1) { _start(options) return } if (once && typeof perm == 'number') { console.error(`用户不同意申请或已拒绝权限`) return } try { popup.show({ content }) let status = 0 if (permisionMap[permisionName]) { status = await permisionMap[permisionName]() } else { status = 1 console.error(`addPermisionInterceptor fail, ${permisionName}-未配置获取权限方法`) } uni.setStorageSync(prefix + permisionName, status) if (status === 1) { _start(options) } if (status === 0) { console.error(`申请麦克风权限失败`) } if (status === -1) { console.error(`用户已拒绝麦克风权限`) gotoAppPermissionSetting() } } catch (err) { console.error(err) } finally { popup.close() } } return recorder } if (permisionName == 'getRecorderManager') { if (getRecorderManagerFlag) return uni.getRecorderManager = getRecorderManagerAdapter getRecorderManagerFlag = true return } uni.addInterceptor(permisionName, { invoke(args) { if (args.sourceType && Array.isArray(args.sourceType) && args.sourceType.length == 1) permisionName = args.sourceType[0] return new Promise(async (resolve, reject) => { const perm = uni.getStorageSync(prefix + permisionName) if (perm == 1) { resolve(args) return } if (once && typeof perm == 'number') { reject(args) resultHandler(args, { errMsg: '用户不同意申请或已拒绝权限' }) return } try { let status = 0 status = await new Promise(async (resolve) => { let parmas = { content, onConfirm: async () => { if (permisionMap[permisionName]) { const permissionRes = await permisionMap[permisionName]() resolve(permissionRes) } else { resolve(1) console.error(`addPermisionInterceptor fail, ${permisionName}-未配置获取权限方法`) } }, onCancel: () => { resolve(0) } } popup.show(parmas) }) uni.setStorageSync(prefix + permisionName, status) if (status === 1) { resolve(args) } if (status === 0) { reject(args) resultHandler(args, { errMsg: '申请权限失败' }) } if (status === -1) { reject(args) resultHandler(args, { errMsg: '用户已拒绝该权限' }) gotoAppPermissionSetting() } } catch (err) { reject(args) resultHandler(args, err) } finally { popup.close() } }); }, // success: (res) => { // console.log(res); // }, fail(err) { console.log('interceptor-fail', err) const errMsg = String(err?.errMsg) if (errMsg.includes('fail No Permission') || (errMsg.includes('fail') && errMsg.includes('权限'))) { uni.setStorageSync(prefix + permisionName, 0) gotoAppPermissionSetting() } } }) } /** * @func removePermisionInterceptor * @desc 移除权限申请说明拦截 * @param {String} permisionName 要移除拦截的 uniApi 名称 * @return 无 * @Author Xingfei Xu * @Email 1824159241@qq.com */ export const removePermisionInterceptor = function(permisionName) { if (permisionName == 'getRecorderManager') { getRecorderManagerFlag = false uni.getRecorderManager = _getRecorderManager } uni.removeInterceptor(permisionName) uni.removeStorageSync(prefix + permisionName) } /** * @Func requestAndroidPermission * @Desc 请求安卓权限 * @param {String} permissionName 安卓权限名称, 例: android.permission.CAMERA * @param {Object} explainContent 安卓权限申请说明信息, 例: { title: '相机权限申请说明', content: '应用需要访问您的相机,以便拍摄照片或扫描二维码。'} * @param {String} isCache 是否缓存权限状态(如果缓存的权限状态为 1 时不会显示权限说明信息) * @return {Promise} 权限申请结果(1:已获得权限, 0:拒绝本次申请, -1:永久拒绝申请) * @Author 已被K修改 */ export const requestAndroidPermission = async (permissionName, explainContent, isCache) => { try { const status = isCache ? uni.getStorageSync(prefix + permissionName) : 0 if (uniPlatform != 'app' || platform != 'android' || status === 1) return 1 const res = await new Promise(async (resolve) => { if (explainContent) { explainContent.onConfirm = async () => { const permissionRes = await permisionUtil.requestAndroidPermission(permissionName) resolve(permissionRes) } explainContent.onCancel = () => { resolve(0) } popup.show(explainContent) } else { const permissionRes = await permisionUtil.requestAndroidPermission(permissionName) resolve(permissionRes) } }) if (isCache) uni.setStorageSync(prefix + permissionName, res) return res } catch (error) { return Promise.reject(error) } finally { popup.close() } } /** * @Func clearAndroidPermissionCache * @Desc 清除安卓权限状态缓存 * @param {String} permissionName 安卓权限名称, 例: android.permission.CAMERA * @return * @Author Xingfei Xu * @Email 1824159241@qq.com */ export const clearAndroidPermissionCache = async (permissionName) => { uni.removeStorageSync(prefix + permissionName) }