LaurenceZanotti / smart-games

Site de jogos eletrônicos para uma loja fictícia. Feito com Django, SQLite e React.
0 stars 0 forks source link

(BUG) QR Code mobile não suporta API MediaDevices #4

Open LaurenceZanotti opened 1 year ago

LaurenceZanotti commented 1 year ago

Bug:

Câmera funciona no Desktop mas não no Android. Teste feito em projeto a parte como POC (proof of concept) antes de implementar em qualquer commit deste repositório.

Objetivo:

Implementar QR Code para mobile apenas

Provável solução (análise inicial):

EDIT: A solução foi encontrada e será postada no fim desse post

Implementar polyfill para API web MediaDevices.

De acordo com os documentos do react-qr-reader, uma de suas dependências (@zxing-js/library) usa WebRTC para câmera, que consequentemente usa a API web MediaDevices, que é nova e não é suportada por muitos browsers.

Do README do zxing-js/library:

"The browser layer is using the MediaDevices web API which is not supported by older browsers. You can use external polyfills like WebRTC adapter to increase browser compatibility." / A camada do navegador está usando API web MediaDevices que não é suportada por navegadores antigos. Você pode usar polyfills externos como WebRTC adapter para aumentar a compatibilidade entre navegadores.

Ambiente: Chrome v106 Android 12

Detalhamento do problema:

Saída do DevTools remoto no celular via USB

[ReactQrReader]: MediaDevices API has no support for your browser. You can fix this by running "npm i webrtc-adapter"

Soluções:

LaurenceZanotti commented 1 year ago

Como o Chrome do celular está na última versão (106) e a versão do Android é uma das versões mais recentes (12), é pouco provável que esse problema seja de compatibilidade de browser. Um polyfill não resolveria o problema.

De acordo com as fontes abaixo, o motivo aparente é

Devido a implementações do navegador a câmera só pode ser acessado por https ou localhost. /"Due to browser implementations the camera can only be accessed over https or localhost."

De acordo com a resposta do Vikash no post do StackOverflow, uma solução temporária é acessar chrome://flags/#unsafely-treat-insecure-origin-as-secure e adicionar o ip do app frontend para tratar o http como https (burlar/tratar origin insegura como segura). Após fazer isso no celular usando DevTools remoto, o leitor de QR Code funcionou no celular usando a câmera frontal.

Soluções:

  1. (Temporária) Burlar https com chrome://flags/#unsafely-treat-insecure-origin-as-secure apenas para testar o aplicativo final
  2. (Definitiva) Rodar o app em https

EDIT: Como dito, o navegador só acessa a câmera se o app estiver rodando com https ou em localhost. O problema aconteceu no ambiente de desenvolvimento porquê o app frontend estava rodando no Desktop (exposto para a rede local em http) e sendo acessado pelo celular na rede local, ou seja, nem http nem origin era http://localhost:porta, mas sim http://ip_da_lan:porta. Como a origin não estava sobre https ou não era localhost, a API MediaDevices fica indisponível, e consequentemente o WebRTC, e o acesso a câmera fica indisponível pelo leitor QR

Óbvio que é importante não esquecer de remover o IP e desabilitar flag de "tratar origins inseguras como seguras" após os testes.

LaurenceZanotti commented 1 year ago

A teoria acima foi provada. Ao acessar o frontend pelo Desktop usando origin diferente (http://ip_da_lan:porta), o DevTools do Desktop deu a mesma saída de erro no console que no DevTools mobile:

utils.ts:6 [ReactQrReader]: MediaDevices API has no support for your browser. You can fix this by running "npm i webrtc-adapter"