使用 react-native-webview 和相机
Using react-native-webview and camera
简介:
大家好!我正在开发一个项目,该项目基本上由一个带有集成导航和登录屏幕的 webview 组成,但是这个 webview 在两次执行时需要读取二维码或条形码。在打开 webview 之前使用 android 和 ios 权限,我只能在服务器端访问执行库实现的相机,但是我发现在 ios 上相机在 safari 上崩溃了并且未检测到我的 webview,在 android 它工作正常,但无法显示相机名称。
我的想法:
我想找到一个 QR 和条形码 reader 库与 JAVA 和 Primefaces 8 兼容,支持 webview,部署在服务器端,或者在 webview 执行期间,识别 url 在使用 QR 读取的地方,暂停 webview 并打开一个 react-native 库来扫描 QR 码,之后应用程序将 return 到 webview 刷新页面并传递必要的参数在 url
问题:
所有这一切的问题是我不知道如何在反应原生扫描器库和 webview 之间实现这种切换行为。
我也担心导航,在执行阅读后我无法重新激活扫描仪,而是返回上一页,即扫描仪之前的页面。
另一个问题是我不能丢失的用户会话,用户必须保持登录状态。
我的代码:
此页面在我的登录页面中收到 url 个网络服务:
/* import * as React from 'react'; */
import React, { useState, useEffect, useRef } from 'react';
import { Text, View, StyleSheet, BackHandler, Alert, StatusBar, Platform, Linking } from 'react-native';
import { WebView } from 'react-native-webview';
import { ActivityIndicator } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import {check, PERMISSIONS, request, RESULTS} from 'react-native-permissions';
export default function WebViewUsrLogado(props:any) {
/* ==========================> Variaveis utilizadas <========================= */
const propriedade = props.route.params.url
const webViewRef = useRef<any | null>(null)
const statusBarRef = useRef<any | null>(null)
const [cameraGranted, setCameraGranted] = useState(false);
const [newurl, setNewUrl] = useState<any | null>(null);
const navigation = useNavigation();
const isIOS = Platform.OS === 'ios' ? true : false
; const Spinner = () => (
<View style={styles.activityContainer}>
<ActivityIndicator size="large" color="#f29900" />
</View>
);
const handleCameraPermission = async () => {
const permission = Platform.OS === 'ios' ? PERMISSIONS.IOS.CAMERA : PERMISSIONS.ANDROID.CAMERA
console.log(permission)
const res = await check(permission);
if (res === RESULTS.GRANTED) {
setCameraGranted(true);
} else if (res === RESULTS.DENIED) {
const res2 = await request(permission);
res2 === RESULTS.GRANTED ? setCameraGranted(true) : setCameraGranted(false);
}
};
const handleAcessExternalStoragePermission = async () => {
const permission = Platform.OS === 'ios' ? PERMISSIONS.IOS.PHOTO_LIBRARY : PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE
console.log(permission)
const res = await check(permission);
if (res === RESULTS.GRANTED) {
setCameraGranted(true);
} else if (res === RESULTS.DENIED) {
const res2 = await request(permission);
res2 === RESULTS.GRANTED ? setCameraGranted(true) : setCameraGranted(false);
}
};
const handlePhotoLibraryAddPermission = async () => {
const permission = PERMISSIONS.IOS.PHOTO_LIBRARY_ADD_ONLY
console.log(permission)
const res = await check(permission);
if (res === RESULTS.GRANTED) {
console.log( `Permitido`)
setCameraGranted(true);
} else if (res === RESULTS.DENIED) {
const res2 = await request(permission);
res2 === RESULTS.GRANTED ? setCameraGranted(true) : setCameraGranted(false);
}
};
const handleMicrophonePermission = async () => {
const permission = PERMISSIONS.IOS.MICROPHONE
console.log(permission)
const res = await check(permission);
if (res === RESULTS.GRANTED) {
setCameraGranted(true);
} else if (res === RESULTS.DENIED) {
const res2 = await request(permission);
res2 === RESULTS.GRANTED ? setCameraGranted(true) : setCameraGranted(false);
}
};
/* ==============================> Observaveis <============================= */
//Verificação de permissão
useEffect(() => {
handleCameraPermission();
handleAcessExternalStoragePermission();
if (Platform.OS == `ios`) {
handlePhotoLibraryAddPermission();
handleMicrophonePermission();
}
}, []);
//Botão voltar
useEffect(() => {
const backAction = () => {
const url = webViewRef.current.startUrl;
if (url.includes('/home.xhtml')) {
console.log('Peguei')
alerta();
}
webViewRef.current.goBack();
return true;
};
const backHandler = BackHandler.addEventListener('hardwareBackPress', backAction);
return () => backHandler.remove();
}, []);
/* ===============================> Funcções <=============================== */
const backButtonHandler = () => {
console.log(newurl)
if (webViewRef.current) {
if (newurl.includes('/home.xhtml')) {
alerta()
} else {
webViewRef.current.goBack()
}
}
}
function alerta(){
Alert.alert(
"Deseja Sair?",
"Caso deseja sair sua sessão e atividades serão encerradas.",
[
{
text: "Cancel",
onPress: () => console.log("Cancel Pressed"),
style: "cancel"
},
{ text: "OK", onPress: () => logOut() }
]
);
}
//Verifica se a url é igual a url de login, caso falso chama logout
function voltar(url: any){
setNewUrl(url)
if (url == 'https:/myurl/login.xhtml') {
console.log('iGUAL');
logOut();
} else if (url.includes(`http://fileurl/`)){
console.log(`opa peguei <==================================================`)
Linking.openURL(url);
webViewRef.current.goBack();
} else {
console.log(url)
}
}
//Verifica se existe item na pilha navegação e retira
function logOut(){
let canGoBack = navigation.canGoBack();
if (canGoBack) {
navigation.goBack();
} else{
console.log('tENTOU FAZER AÇÃO MAIS DE UMA VEZ')
}
}
/* ========================> Retorno de Visualização <======================== */
if (cameraGranted) {
return (
<View style={styles.container}>
<StatusBar backgroundColor="#1c4154" />
{
isIOS &&
<Text onPress={backButtonHandler}>Voltar</Text>
}
<WebView
source={{ uri: propriedade }}
ref={webViewRef}
style={styles.view}
originWhitelist={['*']}
allowsInlineMediaPlayback
javaScriptEnabled
scalesPageToFit
mediaPlaybackRequiresUserAction={false}
javaScriptEnabledAndroid
useWebkit
startInLoadingState={true}
renderLoading={Spinner}
onNavigationStateChange={(event)=>{
voltar(event.url)
}}
/>
</View>
);
} else {
return <Text>No access to camera</Text>;
}
}
/* ==============================> Estilização <============================= */
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor:'#1c4154',
paddingTop:20
},
activityContainer: {
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
top: 0,
left: 0,
backgroundColor: '#fff',
height: '100%',
width: '100%'
},
view: {
borderColor: 'red',
}
});
Android 清单
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" />
<uses-permission android:name="android.permission.CAMERA" android:required="false" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.front" android:required="false" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
开发环境:
网站:JAVA 8 和 Primefaces 8
应用程序:
“反应”:“17.0.1”,
“本机反应”:“0.64.2”,
经过大量搜索,我想出了一个解决方法。在服务器端,当我需要读取 url 时,我会生成一个伪造的 url 传递参数。在参数中我使用了两个:mustReadBrcodeOrQR 和 type(Barcode/qr)。在客户端,我使用了 react-native-webview 的 onShouldStartLoadWithRequest 属性,它调用了一个传递 url 的方法,当 url 具有这些参数时,我调用了一个模式,其中我打开代码 reader debarras/qr,阅读后我通过网络服务发送结果并重新加载页面,该页面现在将由网络服务
填写字段
简介:
大家好!我正在开发一个项目,该项目基本上由一个带有集成导航和登录屏幕的 webview 组成,但是这个 webview 在两次执行时需要读取二维码或条形码。在打开 webview 之前使用 android 和 ios 权限,我只能在服务器端访问执行库实现的相机,但是我发现在 ios 上相机在 safari 上崩溃了并且未检测到我的 webview,在 android 它工作正常,但无法显示相机名称。
我的想法:
我想找到一个 QR 和条形码 reader 库与 JAVA 和 Primefaces 8 兼容,支持 webview,部署在服务器端,或者在 webview 执行期间,识别 url 在使用 QR 读取的地方,暂停 webview 并打开一个 react-native 库来扫描 QR 码,之后应用程序将 return 到 webview 刷新页面并传递必要的参数在 url
问题:
所有这一切的问题是我不知道如何在反应原生扫描器库和 webview 之间实现这种切换行为。 我也担心导航,在执行阅读后我无法重新激活扫描仪,而是返回上一页,即扫描仪之前的页面。 另一个问题是我不能丢失的用户会话,用户必须保持登录状态。
我的代码:
此页面在我的登录页面中收到 url 个网络服务:
/* import * as React from 'react'; */
import React, { useState, useEffect, useRef } from 'react';
import { Text, View, StyleSheet, BackHandler, Alert, StatusBar, Platform, Linking } from 'react-native';
import { WebView } from 'react-native-webview';
import { ActivityIndicator } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import {check, PERMISSIONS, request, RESULTS} from 'react-native-permissions';
export default function WebViewUsrLogado(props:any) {
/* ==========================> Variaveis utilizadas <========================= */
const propriedade = props.route.params.url
const webViewRef = useRef<any | null>(null)
const statusBarRef = useRef<any | null>(null)
const [cameraGranted, setCameraGranted] = useState(false);
const [newurl, setNewUrl] = useState<any | null>(null);
const navigation = useNavigation();
const isIOS = Platform.OS === 'ios' ? true : false
; const Spinner = () => (
<View style={styles.activityContainer}>
<ActivityIndicator size="large" color="#f29900" />
</View>
);
const handleCameraPermission = async () => {
const permission = Platform.OS === 'ios' ? PERMISSIONS.IOS.CAMERA : PERMISSIONS.ANDROID.CAMERA
console.log(permission)
const res = await check(permission);
if (res === RESULTS.GRANTED) {
setCameraGranted(true);
} else if (res === RESULTS.DENIED) {
const res2 = await request(permission);
res2 === RESULTS.GRANTED ? setCameraGranted(true) : setCameraGranted(false);
}
};
const handleAcessExternalStoragePermission = async () => {
const permission = Platform.OS === 'ios' ? PERMISSIONS.IOS.PHOTO_LIBRARY : PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE
console.log(permission)
const res = await check(permission);
if (res === RESULTS.GRANTED) {
setCameraGranted(true);
} else if (res === RESULTS.DENIED) {
const res2 = await request(permission);
res2 === RESULTS.GRANTED ? setCameraGranted(true) : setCameraGranted(false);
}
};
const handlePhotoLibraryAddPermission = async () => {
const permission = PERMISSIONS.IOS.PHOTO_LIBRARY_ADD_ONLY
console.log(permission)
const res = await check(permission);
if (res === RESULTS.GRANTED) {
console.log( `Permitido`)
setCameraGranted(true);
} else if (res === RESULTS.DENIED) {
const res2 = await request(permission);
res2 === RESULTS.GRANTED ? setCameraGranted(true) : setCameraGranted(false);
}
};
const handleMicrophonePermission = async () => {
const permission = PERMISSIONS.IOS.MICROPHONE
console.log(permission)
const res = await check(permission);
if (res === RESULTS.GRANTED) {
setCameraGranted(true);
} else if (res === RESULTS.DENIED) {
const res2 = await request(permission);
res2 === RESULTS.GRANTED ? setCameraGranted(true) : setCameraGranted(false);
}
};
/* ==============================> Observaveis <============================= */
//Verificação de permissão
useEffect(() => {
handleCameraPermission();
handleAcessExternalStoragePermission();
if (Platform.OS == `ios`) {
handlePhotoLibraryAddPermission();
handleMicrophonePermission();
}
}, []);
//Botão voltar
useEffect(() => {
const backAction = () => {
const url = webViewRef.current.startUrl;
if (url.includes('/home.xhtml')) {
console.log('Peguei')
alerta();
}
webViewRef.current.goBack();
return true;
};
const backHandler = BackHandler.addEventListener('hardwareBackPress', backAction);
return () => backHandler.remove();
}, []);
/* ===============================> Funcções <=============================== */
const backButtonHandler = () => {
console.log(newurl)
if (webViewRef.current) {
if (newurl.includes('/home.xhtml')) {
alerta()
} else {
webViewRef.current.goBack()
}
}
}
function alerta(){
Alert.alert(
"Deseja Sair?",
"Caso deseja sair sua sessão e atividades serão encerradas.",
[
{
text: "Cancel",
onPress: () => console.log("Cancel Pressed"),
style: "cancel"
},
{ text: "OK", onPress: () => logOut() }
]
);
}
//Verifica se a url é igual a url de login, caso falso chama logout
function voltar(url: any){
setNewUrl(url)
if (url == 'https:/myurl/login.xhtml') {
console.log('iGUAL');
logOut();
} else if (url.includes(`http://fileurl/`)){
console.log(`opa peguei <==================================================`)
Linking.openURL(url);
webViewRef.current.goBack();
} else {
console.log(url)
}
}
//Verifica se existe item na pilha navegação e retira
function logOut(){
let canGoBack = navigation.canGoBack();
if (canGoBack) {
navigation.goBack();
} else{
console.log('tENTOU FAZER AÇÃO MAIS DE UMA VEZ')
}
}
/* ========================> Retorno de Visualização <======================== */
if (cameraGranted) {
return (
<View style={styles.container}>
<StatusBar backgroundColor="#1c4154" />
{
isIOS &&
<Text onPress={backButtonHandler}>Voltar</Text>
}
<WebView
source={{ uri: propriedade }}
ref={webViewRef}
style={styles.view}
originWhitelist={['*']}
allowsInlineMediaPlayback
javaScriptEnabled
scalesPageToFit
mediaPlaybackRequiresUserAction={false}
javaScriptEnabledAndroid
useWebkit
startInLoadingState={true}
renderLoading={Spinner}
onNavigationStateChange={(event)=>{
voltar(event.url)
}}
/>
</View>
);
} else {
return <Text>No access to camera</Text>;
}
}
/* ==============================> Estilização <============================= */
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor:'#1c4154',
paddingTop:20
},
activityContainer: {
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
top: 0,
left: 0,
backgroundColor: '#fff',
height: '100%',
width: '100%'
},
view: {
borderColor: 'red',
}
});
Android 清单
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" />
<uses-permission android:name="android.permission.CAMERA" android:required="false" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.front" android:required="false" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
开发环境:
网站:JAVA 8 和 Primefaces 8
应用程序: “反应”:“17.0.1”, “本机反应”:“0.64.2”,
经过大量搜索,我想出了一个解决方法。在服务器端,当我需要读取 url 时,我会生成一个伪造的 url 传递参数。在参数中我使用了两个:mustReadBrcodeOrQR 和 type(Barcode/qr)。在客户端,我使用了 react-native-webview 的 onShouldStartLoadWithRequest 属性,它调用了一个传递 url 的方法,当 url 具有这些参数时,我调用了一个模式,其中我打开代码 reader debarras/qr,阅读后我通过网络服务发送结果并重新加载页面,该页面现在将由网络服务
填写字段