RN权限设置

48 阅读5分钟
/*
 * @Description: '公共基础库'
 * @Last Modified time: 2022-08-17 17:14:52
 * @ToDo: ''
 */

import { Linking, Platform, PermissionsAndroid } from 'react-native'
import {
	PERMISSIONS,
	RESULTS,
	check,
	checkMultiple,
	checkNotifications,
	request,
	requestMultiple,
	requestNotifications,
} from 'react-native-permissions'
import OpenNative from './OpenNative'
import { setItem } from './storage'
import MMKVKey from '@/constants/MMKVKey'

/**
 * 检测是否有地址权限
 * @returns
 */
function checkHasLocationMultiple() {
	return new Promise((resolve, reject) => {
		let select = Platform.select({
			android: [PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION, PERMISSIONS.ANDROID.ACCESS_COARSE_LOCATION],
			ios: [PERMISSIONS.IOS.LOCATION_ALWAYS, PERMISSIONS.IOS.LOCATION_WHEN_IN_USE],
		})
		console.log('select', select)

		checkMultiple(select)
			.then((statuses) => {
				let has =
					statuses[PERMISSIONS.ANDROID.ACCESS_COARSE_LOCATION] == RESULTS.GRANTED ||
					statuses[PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION] == RESULTS.GRANTED
				if (Platform.OS === 'ios') {
					has =
						statuses[PERMISSIONS.IOS.LOCATION_ALWAYS] == RESULTS.GRANTED ||
						statuses[PERMISSIONS.IOS.LOCATION_WHEN_IN_USE] == RESULTS.GRANTED
				}
				const key = statuses[select[0]]
				if (has) {
					//有权限
					resolve(true)
				} else {
					reject(false)
				}
				console.log('地址权限--checkMultiple', key, has, RESULTS.BLOCKED)
			})
			.catch((err) => {
				console.log('地址权限--checkMultiple-err', err)
				reject(err)
			})
	})
}

/**
 * 请求地址权限
 * @returns
 */
const onRequestLocationMultiple = async () => {
	const hasLocation = await OpenNative.checkLocationService()
	console.log('2323---3e', hasLocation)
	if (hasLocation) {
		return new Promise((resolve, reject) => {
			let select = Platform.select({
				android: [PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION, PERMISSIONS.ANDROID.ACCESS_COARSE_LOCATION],
				ios: [PERMISSIONS.IOS.LOCATION_ALWAYS, PERMISSIONS.IOS.LOCATION_WHEN_IN_USE],
			})
			//有权限
			console.log('select', select)

			requestMultiple(select)
				.then((statuses) => {
					console.log('statuses', statuses)
					let has =
						statuses[PERMISSIONS.ANDROID.ACCESS_COARSE_LOCATION] == RESULTS.GRANTED ||
						statuses[PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION] == RESULTS.GRANTED
					if (Platform.OS === 'ios') {
						has =
							statuses[PERMISSIONS.IOS.LOCATION_ALWAYS] == RESULTS.GRANTED ||
							statuses[PERMISSIONS.IOS.LOCATION_WHEN_IN_USE] == RESULTS.GRANTED
					}
					const key = statuses[select[0]]
					console.log('has', has)
					if (has) {
						resolve(true)
					} else {
						// if (showDefaultAlert) {
						if (key != RESULTS.BLOCKED) {
							//首次 或者 杀掉app关闭弹框 ,此时调用会弹出一个系统弹窗
							console.log('地址权限--首次请求', key, has, RESULTS.BLOCKED)
							// denied  不准许
							// granted  仅本次使用时  和 使用应用时
							// blocked
						} else {
							NormalModal.Confirm({
								title: '地址权限授权提示',
								content: `您还没有开启地址权限,无法使用地址功能,请前往设置开启地址权限。`,
								cancelText: '暂不开启',
								confirmText: '去设置',
								autoCloseModal: true,
								confirmFn: () => {
									Linking.openSettings()
								},
							})
							console.log('地址权限--拒绝后再去设置请求', key, has, RESULTS.BLOCKED)
						}
						// }
						reject({ has: false, key })
					}
					console.log('地址权限--requestMultiple', has, statuses)
				})
				.catch((err) => {
					console.log('地址权限--requestMultiple-err', err)
					reject(err)
				})
		})
	} else {
		return Promise.reject(false)
	}
}

/**
 * 是否有通知权限判断
 */
const onCheckNotifications = () => {
	return new Promise((resolve, reject) => {
		checkNotifications()
			.then((statuses) => {
				if (
					JSON.stringify(statuses).indexOf(RESULTS.DENIED) === -1 &&
					JSON.stringify(statuses).indexOf(RESULTS.BLOCKED) === -1
				) {
					console.log('通知权限--已经开启', statuses)
					resolve(true)
				} else {
					console.log('通知权限--未开启', statuses)
					reject(false)
				}
			})
			.catch((err) => {
				console.log('通知权限--检查失败', err)
				reject(err)
			})
	})
}

/**
 * 打开通知权限设置
 */
async function onRequestNotification(confirmFn?: () => void, cancelFn?: () => void) {
	return requestNotifications(['alert']).then((statuses) => {
		if (statuses.status != RESULTS.BLOCKED) {
			//首次 或者 杀掉app关闭弹框 ,此时调用会弹出一个系统弹窗
			console.log('通知权限--首次请求', statuses.status)
			return true
		} else {
			//被永久拒绝一次后,调用此方法去手机设置通知
			console.log('通知权限--拒绝后再去设置', statuses.status)
			NormalModal.Confirm({
				title: '通知授权提示',
				content: `您还没有开启通知权限,无法接到消息通知,请前往设置开启通知权限。`,
				cancelText: '取消',
				confirmText: '去设置',
				autoCloseModal: true,
				cancelFn: () => {
					setItem(MMKVKey?.notification_check_time, '1')
					cancelFn && cancelFn()
				},
				confirmFn: () => {
					setItem(MMKVKey?.notification_check_time, '1')
					confirmFn && confirmFn()
					OpenNative.openNotificationSettings()
				},
			})
			return false
		}
	})
}

/**
 *  检测是否有相册权限
 * @param showDefaultAlert
 * @returns
 */
function onCheckPhotoMultiple() {
	//打开相册
	return new Promise((resolve, reject) => {
		let select = Platform.select({
			android: [
				PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,
				PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,
				PERMISSIONS.ANDROID.READ_MEDIA_IMAGES,
			],
			ios: [PERMISSIONS.IOS.PHOTO_LIBRARY],
		})
		//有权限
		checkMultiple(select)
			.then((statuses) => {
				let has =
					statuses[PERMISSIONS.ANDROID.READ_MEDIA_IMAGES] == RESULTS.GRANTED ||
					statuses[PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE] == RESULTS.GRANTED
				if (Platform.OS === 'ios') {
					has = statuses[PERMISSIONS.IOS.PHOTO_LIBRARY] == RESULTS.GRANTED
				}
				const key = statuses[select[0]]
				if (!has) {
					reject(false)
				} else {
					resolve(true)
				}
				console.log('相册权限--checkMultiple', key)
			})
			.catch((err) => {
				console.log('相册权限--checkMultiple error', err)
				reject(err)
			})
	})
}

/**
 * 请求相册权限--(说明:检测是否有权限和说明一体,有权限走then,无权限会弹窗)
 * @param showDefaultAlert
 * @returns Promise<any>
 */
function onRequestPhotoMultiple(): Promise<any> {
	//打开相册
	return new Promise((resolve, reject) => {
		let select = Platform.select({
			android: [
				PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,
				PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,
				PERMISSIONS.ANDROID.READ_MEDIA_IMAGES,
			],
			ios: [PERMISSIONS.IOS.PHOTO_LIBRARY],
		})
		//有权限
		requestMultiple(select)
			.then((statuses) => {
				let has =
					statuses[PERMISSIONS.ANDROID.READ_MEDIA_IMAGES] == RESULTS.GRANTED ||
					statuses[PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE] == RESULTS.GRANTED
				if (Platform.OS === 'ios') {
					has =
						statuses[PERMISSIONS.IOS.PHOTO_LIBRARY] == RESULTS.GRANTED ||
						statuses[PERMISSIONS.IOS.PHOTO_LIBRARY] == RESULTS.LIMITED
				}
				const key = statuses[select[0]]
				if (!has) {
					if (key != RESULTS.BLOCKED) {
						//首次 或者 杀掉app关闭弹框 ,此时调用会弹出一个系统弹窗
						console.log('相册权限--首次请求', key, has, RESULTS.BLOCKED)
						// denied  不准许
						// granted  仅本次使用时  和 使用应用时
						// blocked
					} else {
						let isLoveAndroid = Platform.OS === 'android' && Platform.Version <= 29
						NormalModal.Confirm({
							title: '相册权限授权提示',
							content: `您还没有开启相册权限,无法使用相册功能,请前往设置开启相册权限。${
								isLoveAndroid ? '(注:当您在权限设置下没有看到相册权限时,请开启存储权限)' : ''
							}`,
							cancelText: '取消',
							confirmText: '去设置',
							autoCloseModal: true,
							confirmFn: () => {
								Linking.openSettings()
							},
						})
						console.log('相册权限--拒绝后再去设置请求', key, has, RESULTS.BLOCKED)
					}
					reject({ has: false, key })
				} else {
					resolve(true)
				}
			})
			.catch((err) => {
				reject(err)
				console.log('相册权限--error', err)
			})
	})
}

/*** 查看相机权限 */
const checkCameraPermission = async () => {
	let select = Platform.select({
		ios: PERMISSIONS.IOS.CAMERA,
		android: PERMISSIONS.ANDROID.CAMERA,
	})
	try {
		const permissionStatus = await check(select)
		console.log('相机权限--', permissionStatus)
		if (permissionStatus === RESULTS.GRANTED) {
			return true
		}
		return false
	} catch (error) {
		console.error('相机权限-error:', error)
		return false
	}
}

const requestCameraPermission = async () => {
	let select = Platform.select({
		ios: PERMISSIONS.IOS.CAMERA,
		android: PERMISSIONS.ANDROID.CAMERA,
	})
	const requestResult = await request(select)
	console.log('相机权限--', requestResult)
	if (requestResult === RESULTS.GRANTED) {
		return true
	} else {
		// 提示用户前往设置开启权限
		NormalModal.Confirm({
			title: '相机权限授权提示',
			content: `您还没有开启相机权限,无法使用该功能,请前往设置开启相机权限`,
			cancelText: '取消',
			confirmText: '去设置',
			autoCloseModal: true,
			confirmFn: () => {
				Linking.openSettings().catch(() => console.warn('无法打开设置页面'))
			},
		})
		return false
	}
}
/*** 检查是否有访问相机权限 */
const checkAndRequestCameraPermission = async () => {
	try {
		const hasPermission = await checkCameraPermission()
		if (hasPermission) {
			return true
		}
		const requestPermission = await requestCameraPermission()
		if (requestPermission) {
			return true
		}
		console.log('相机权限--checkAndRequestCameraPermission')
		return false
	} catch (error) {
		console.log(`error`, error)
		return false
	}
}

/** 检查文档权限 */
const checkDocumentPermission = async () => {
	try {
		const granted = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE)
		return granted
	} catch (error) {
		console.log(error, 'error11111')
		return false
	}
}

/** 请求文档权限 */
const requestDocumentPermission = async () => {
	try {
		const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE, {
			title: '存储访问权限',
			message: '应用需要访问文件管理器以选择文件。',
			buttonNeutral: '稍后再说',
			buttonNegative: '拒绝',
			buttonPositive: '允许',
		})
		return granted === PermissionsAndroid.RESULTS.GRANTED
	} catch (error) {
		console.log(error, 'errrrr')
		return false
	}
}
/** 打开文件管理 */
const openFileManage = async () => {
	if (Platform.OS === 'android' && Platform.Version < 29) {
		const hasPermission = await checkDocumentPermission()
		if (!hasPermission) {
			NormalModal.Confirm({
				title: '文档权限授权提示',
				content: `您还没有开启文档权限,无法使用该功能,请前往设置开启该权限。`,
				cancelText: '取消',
				confirmText: '去设置',
				autoCloseModal: true,
				confirmFn: () => {
					Linking.openSettings().catch(() => console.warn('无法打开设置页面'))
				},
			})
			return false
		}
		return true
	}
	// ios 及其 更高版本不校验权限
	return true
}

const requestStorePermission = async () => {
	/*** ios 判断是否有读取相册权限 */
	if (Platform.OS === 'ios') {
		return await onRequestPhotoMultiple()
	} else if (Platform.OS === 'android' && Platform.Version > 29) {
		return true
	} else {
		let select = [PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE, PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE]
		return checkMultiple(select)
			.then((statuses) => {
				let has =
					statuses[PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE] == RESULTS.GRANTED ||
					statuses[PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE] == RESULTS.GRANTED
				const key = statuses[select[0]]
				console.log('存储权限--checkMultiple', key, has, RESULTS.BLOCKED)
				if (has) {
					//有权限
					return true
				} else {
					if (key != RESULTS.GRANTED) {
						NormalModal.Confirm({
							title: '存储权限授权提示',
							content: `您还没有开启存储权限,无法使用相关功能,请前往设置开启该权限。`,
							cancelText: '取消',
							confirmText: '去设置',
							autoCloseModal: true,
							confirmFn: () => {
								Linking.openSettings()
							},
						})
					}
					console.log('相册权限--拒绝后再去设置请求', key, has, RESULTS.BLOCKED)
					return false
				}
			})
			.catch((err) => {
				console.log('地址权限--checkMultiple-err', err)
				return false
			})
	}
}

export default {
	checkHasLocationMultiple,
	onRequestLocationMultiple,
	onCheckPhotoMultiple,
	onRequestPhotoMultiple,
	onCheckNotifications,
	onRequestNotification,
	checkCameraPermission,
	requestCameraPermission,
	checkAndRequestCameraPermission,
	openFileManage,
	requestStorePermission,
}