RN 打开外部链接

40 阅读2分钟
import projectConfig from '@/config/projectConfig'
import { Linking } from 'react-native'
import DeviceInfo from 'react-native-device-info'
import navigationUtils from './navigationUtils'
import { RouteName } from '@/types'
import CommonUtils from './CommonUtils'

enum MessageEnum {
	closeWebView = 'closeWebView', // 关闭Webview
	getLatLng = 'getLatLng', // 获取当前经纬度
	logout = 'logout',
	getAppParams = 'getAppParams', // 获取app参数
	share = 'share',
	goRegister = 'goRegister',
	login = 'login',
	reportEvent = 'reportEvent',
	onScan = 'onScan',
	goPage = 'goPage', // 跳转app页面
}

let _webviewRef: any = {}

function setWebViewRef(webviewRef: any) {
	_webviewRef = webviewRef
}

function onMessage(params: any, callback: any, h5Params: any) {
	const { service, data } = params
	const response = { callbackName: 'appResponse', data: { ...h5Params } }

	switch (service) {
		case MessageEnum?.closeWebView:
			return navigationUtils.pop()
		case MessageEnum?.goPage:
			// 数据传参案列  data={pageName:'Login',params:{id:12,phone:2323}}
			const routeName = data?.pageName
			const params = data?.params
			if (Object.values(RouteName).includes(routeName as RouteName)) {
				navigationUtils.push(routeName, CommonUtils.isObjNotNull(params) ? params : {})
			}
			return null
		case MessageEnum?.getAppParams:
			return callback(service, encodeURIComponent(JSON.stringify(response)))
		case MessageEnum?.logout:
			return null
		case MessageEnum?.getLatLng:
			return null
		case MessageEnum?.share:
			return null
		case MessageEnum?.goRegister:
			return null
		case MessageEnum?.login:
			return null
		case MessageEnum?.reportEvent:
			return null
		case MessageEnum?.onScan:
			return null
		default:
			return null
	}
}

// 注:这里用NavigationUtils.navigate有时候会很奇怪取不到NavigationUtils里面的navigation方法,回退时页面直接挂了,保险点还是把navigation传进的
function webSkipEvent(url: string) {
	let type = ''
	//正式
	const strings = url.split(projectConfig.schemeUrl)
	if (strings && strings.length > 1) {
		type = strings[1]
	}
	if (type === 'exitH5') {
		//退出h5
		navigationUtils.pop()
	} else {
		// 匹配路由做跳转    type类似这种形式  jingyunxiao://Home?params='{phone:123,password:123}'
		const typeArr = type.split('?') || []
		type = typeArr[0]
		let params = typeArr[1] && typeArr[1].replace('params=', '') && JSON.parse(typeArr[1])
		if (Object.values(RouteName).includes(type as RouteName)) {
			navigationUtils.push(type, CommonUtils.isObjNotNull(params) ? params : {})
		}
	}
}

function openUrl(url: string) {
	try {
		Linking.openURL(url).catch((err) => {
			Toast.info('要打开的App不存在')
			console.log('webview---openURl err', err)
		})
	} catch (e) {
		Toast.info('要打开的App不存在')
		console.log('webview---openURl err-catch', e)
	}
	// Linking.canOpenURL(url)
	//     .then((supported) => {
	//         if (supported) {
	//             Linking.openURL(url);
	//         } else {
	//             Toast.info(I18n.t('common_openApp_notExist'))
	//         }
	//     })
	//     .catch((error) => {
	//         Toast.info(I18n.t('common_openApp_notExist'))
	//     })
}

function initUrl(url: string) {
	if (url?.indexOf('time=') !== -1) {
		return url
	} else if (url?.indexOf('?') === -1) {
		return url + '?time=' + new Date().getTime()
	} else {
		return url + '&time=' + new Date().getTime()
	}
}

// 深度链接解析支付url参数(返回时调用)--支付后返回app时,截取v后的连接,做打开h5动作(定向支持返回后跳转到哪个页面)
const getPayParamFromUrlByKey = (url: string) => {
	// 解码URL
	try {
		const queryString = url.split('?v=')[1]
		return decodeURIComponent(queryString)
	} catch (e) {
		console.log('webview--getPayParamFromUrlByKey失败', e)
	}
	return ''
}

function deviceInfoString() {
	return JSON.stringify({
		deviceId: DeviceInfo.getDeviceId(),
		versionCode: DeviceInfo.getBuildNumber(),
		versionName: DeviceInfo.getApplicationName(),
		SystemVersion: DeviceInfo.getSystemVersion(),
		DeviceBrand: DeviceInfo.getBrand(),
	})
}

export default {
	onMessage,
	webSkipEvent,
	openUrl,
	initUrl,
	getPayParamFromUrlByKey,
	deviceInfoString,
}