Использование react-native-webview и камеры

#react-native #webview #react-native-android #react-native-ios

Вопрос:

Введение:

Эй, ребята! Я разрабатываю проект, который в основном состоит из веб-представления со встроенной навигацией и экраном входа в систему, однако это веб-представление за два времени выполнения должно считывать qr-код или штрих-код. Используя разрешения android и ios перед открытием webview, я смог получить доступ к камере, выполняющей библиотечные реализации только на стороне сервера, однако я обнаружил, что на ios камера разбилась в safari, и мой веб-просмотр не был обнаружен, на Android он работал нормально, хотя и не мог отображать имена камер.

Что я думал:

Я думал найти библиотеку считывателей QR и штрих-кодов, совместимую с JAVA и Primefaces 8 с поддержкой webview, развертываемую на стороне сервера или во время выполнения webview, определить URL-адрес, по которому будет использоваться считывание QR, приостановить webview и открыть собственную библиотеку react для сканирования QR-кода, после чего приложение вернется в webview, перефразируя страницу, передавая необходимые параметры в URL-адресе.

Проблема:

Проблема со всем этим заключается в том, что я понятия не имею, как реализовать это переключение между библиотеками react native scanner и 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 amp;amp;
          <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 Manifest

     <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»,