从 React native App 中的 WebView 打开动态 link

Opening a dynamic link from a WebView inside React native App

我需要在网站上使用用户 selection 打开一个应用程序屏幕,当用户 select 一个项目时,它应该在移动应用程序中打开相关页面。 但是网站应该在同一个应用程序中的 webview 中加载。 这里我使用 Firebase 动态 links 来管理这个导航。

我可以在模拟器中从 chrome 浏览器打开网站,并根据需要打开导航到准确页面的应用程序。 但是当我从应用程序中的 webview 单击相同的组件时,它会抛出以下错误并且应用程序不会打开 firebase 动态 link 应该打开的页面,就像 chrome 的第一种情况一样浏览器。

Can't open url: intent://example.page.link/getapp#Intent;package=com.google.android.gms;action=com.google.firebase.dynamiclinks.VIEW_DYNAMIC_LINK;scheme=https;S.browser_fallback_url=https://play.google.com/store/apps/details%3Fid%3Dcom.ubercab;end;

我的实现如下,

WebApp

App.js

function App() {  

  return (

    <div>
      <Button variant="primary">
        Open this in your App
      </Button>
      <Banner url={"https://testingapp.page.link/getapp"}/>
    <Banner url={"https://testingapp.page.link/getapp"}/>
    <Banner url={"https://testingapp.page.link/getapp"}/>
    <Banner url={"https://testingapp.page.link/getapp"}/>
    </div>

  );
}

Banner.js

const Banner=(props)=>{
    const classes = useStyles();
    const [expanded, setExpanded] = React.useState(false);

    const styles = {
        cardAction: {
            display: 'block',
            textAlign: 'initial',
            height: '100%'
        }
    }



  return (
      <div onClick={() => window.open(props.url, "_blank")}>
          <Card className={classes.root}>
              <CardMedia
                  className={classes.media}
                  image= {banner}
                  title="Offer"
              />
          </Card>
      </div>

  );
        };

export default Banner;

移动端:

App.jsx

import React, { useEffect } from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import dynamicLinks from '@react-native-firebase/dynamic-links';
import { WebView } from 'react-native-webview';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
function DetailsScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Details Screen</Text>
    </View>
  );
}

function HomeScreen({ navigation }) {
  async function buildLink() {
    console.log('building link');
    const link = await dynamicLinks().buildLink({
      link: 'https://invertase.io',
      // domainUriPrefix is created in your firebase console
      domainUriPrefix: 'https://testingapp.page.link',
      // optional set up which updates firebase analytics campaign
      // "banner". This also needs setting up before hand
      analytics: {
        campaign: 'banner',
      },
    });

    return link;
  }


  const handleDynamicLink = link => {
    // Handle dynamic link inside your own application
    console.log('Received URfffL:' + link.url);
    if (link.url === 'https://example.com/packageview') {
      console.log('hit package view');
      navigation.push('packageview');
    }
  };

  useEffect(() => {
    const unsubscribe = dynamicLinks().onLink(handleDynamicLink);
    // When the is component unmounted, remove the listener

    dynamicLinks()
      .getInitialLink()
      .then(link => {
        console.log('Received URL:' + link.url);
        if (link.url === 'https://example.com/packageview') {
          console.log('hit package view');
          navigation.push('packageview');
        }
      });


    return () => unsubscribe();


  }, []);
  return (   
      <WebView source={{ uri: 'http://10.0.2.2:3000/' }}/>   
  );
}


export default function App() {



  const Stack = createStackNavigator();

    return (
      <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="packageview" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
    );

}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

有没有人有这方面的经验?关于这里出了什么问题?

有一个解决方案,但更像是一种变通方法,因此 webview 似乎阻止了带有 "intent://" 头部的请求,作为解决方案 "intent://" 可以添加到 WebView 的白名单中。检查下面的代码,

 <WebView      
      originWhitelist={['intent://']}
      source={{ uri: 'http://10.0.2.2:3000/' }}/>   

但用户体验可能不会那么好,因为这使得 URL 从网络浏览器打开,网络浏览器将导航到应用程序内的页面。