aws-amplify / aws-amplify/amplify-ui

FaceLivenessDetector keeps loading without move to oval-shaped screen

Open
#6,154 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature-request Flutter Liveness
Dominant language
TypeScript
Stars
1.1k
Forks
347
Avg merge
18h 29m
Merged PRs (30d)
9

Description

Before creating a new issue, please confirm:
On which framework/platform are you having an issue?

Flutter

Which UI component?

Liveness

How is your app built?

React App

What browsers are you seeing the problem on?

Safari

Which region are you seeing the problem in?

ap-northeast-1

Please describe your bug.

I have tried to run the FaceLivenessDetector on the web browser sucessfully without any problems. But when I try to open the web app from one of the following Flutter webview plugins (WebViewFlutter, InAppWebView, InAppBrowser from InAppWebView), the app always keeps loading after I get the sessionId from my custom backend. It should go the the oval-shaped page to verify my face. But if I use the url_launcher package to directly open Safari browser, it works like the web browser. The issue just happens when I try to show the app in a mobile webview.

What's the expected behaviour?

Mobile webview should work as same as web browser on desktop

Help us reproduce the bug!

Create a new flutter project and add the WebViewFlutter package from pub.dev
Paste the code below to run the webview

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

class FaceLivenessWebViewFlutter extends StatefulWidget {
  const FaceLivenessWebViewFlutter({super.key});

  @override
  State<FaceLivenessWebViewFlutter> createState() =>
      _FaceLivenessWebViewFlutterState();
}

class _FaceLivenessWebViewFlutterState
    extends State<FaceLivenessWebViewFlutter> {
  late WebViewController _webViewController;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    _webViewController = WebViewController()
      ..loadRequest(Uri.parse('[Place an url points to the react app, can be a ngrok url]'))
      ..setJavaScriptMode(JavaScriptMode.unrestricted);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Face Liveness'),
        actions: [],
      ),
      body: Column(
        children: [
          Expanded(
            child: WebViewWidget(
              controller: _webViewController,
            ),
          ),
        ],
      ),
    );
  }
}
Code Snippet
import React, {useEffect, useState} from "react";
import {Button, Heading, Loader, View} from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
import {FaceLivenessDetector} from '@aws-amplify/ui-react-liveness';

interface FaceLivenessProps {
    faceLivenessAnalysis: (data: any) => void;
}

const FaceLiveness: React.FC<FaceLivenessProps> = ({faceLivenessAnalysis}) => {
    const [loading, setLoading] = useState(true);
    const [sessionId, setSessionId] = useState<string | null>(null);

    const endpoint = process.env.REACT_APP_ENV_API_URL || '';

    const fetchCreateLiveness = async () => {
        try {
            const response = await fetch(`${endpoint}/create_session`);
            const data = await response.json();
            console.log(JSON.stringify(data));
            setSessionId(data.sessionId);
            setLoading(false);
        } catch (error) {
            console.error("Failed to create liveness session", error);
        }
    };

    useEffect(() => {
        fetchCreateLiveness();
    }, [endpoint]);

    const handleAnalysisComplete = async () => {
        try {
            const response = await fetch(`${endpoint}/check?sessionId=${sessionId}`, {
                method: 'GET',
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                }
            });
            const data = await response.json();
            faceLivenessAnalysis(data.body);
        } catch (error) {
            console.error("Failed to get liveness session result", error);
        }
    };

    const handleRetry = () => {
        setLoading(true);
        fetchCreateLiveness();
    };

    return (
        <>
            {loading ? (
                <Loader/>
            ) : (
                <FaceLivenessDetector
                    sessionId={sessionId || ''}
                    region={process.env.REACT_APP_REGION || ''}
                    disableStartScreen={true}
                    onAnalysisComplete={handleAnalysisComplete}
                    components={{
                        PhotosensitiveWarning: () => null,
                        ErrorView: ({}) => (
                            <View className="container">
                                <Heading level={6} className="heading">Chưa nhận diện được khuôn mặt</Heading>
                                <div style={{marginBottom: '20px'}}></div>
                                <Button className="button" onClick={handleRetry}>Thử lại</Button>
                            </View>
                        )
                    }}
                    onError={(error) => {
                        console.error(error);
                    }}
                />
            )}
        </>
    );
}

export default FaceLiveness;
Console log output

Nothing shows up

Additional information and screenshots

IMG_0E1D321B72CC-1
The app is stuck here, it should go to the oval-shaped page

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the React FaceLiveness component and its FaceLivenessDetector entry point, then reproduce the behavior with WebViewController in a minimal Flutter project using Safari. Confirm the component moves from the loading state to the oval-shaped verification screen inside a mobile webview, and use the reported reproduction code and screenshot as the baseline.

Written by the indexing model from the issue text.

Assessment

Tech stack
flutter, react, typescript
Domain
frontend, mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.