2

我尝试将 qr_code_scanner 的 QR 码扫描器与 Webview 组件webview_flutter结合使用

在 iOS 上一切正常,但在 Android 设备上它不起作用,QR 扫描仪不显示,我得到重复的控制台打印。

D/mali_winsys(30667): EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, EGLBoolean) returns 0x3000 

我已经在两台 Android 设备(Android 10、v29 和 Android 7、v24)上进行了尝试,结果相同。

以下是重现该问题的最小应用程序。它需要以下依赖项:

qr_code_scanner: ^0.3.5
webview_flutter: ^2.0.2 

下面的代码显示了一个顶部有一个按钮的全屏 web 视图。按下按钮,QR 扫描仪将/应该显示...

import 'package:flutter/material.dart';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
import 'package:webview_flutter/webview_flutter.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _showQr = false;

  @override
  void initState() {
    super.initState();
    // Enable hybrid composition.
    if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
  }

  void closeQr() {
    setState(() {
      _showQr = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Stack(
          children: [
            WebView(
              initialUrl: 'https://flutter.dev',
            ),
            Center(
              child: TextButton(
                onPressed: () {
                  setState(() {
                    _showQr = !_showQr;
                  });
                },
                child: Text('Show QR Scanner'),
                style: TextButton.styleFrom(
                  primary: Colors.white,
                  backgroundColor: Colors.teal,
                  onSurface: Colors.grey,
                ),
              ),
            ),
          ],
        ),
        Center(
          child: (_showQr) ? QRWidget(onClose: closeQr) : null,
        ),
      ],
    );
  }
}

class QRWidget extends StatefulWidget {
  const QRWidget({
    Key key,
    this.onClose,
  }) : super(key: key);

  final Function onClose;

  @override
  State<StatefulWidget> createState() => _QRWidgetState();
}

class _QRWidgetState extends State<QRWidget> {
  Barcode result;
  QRViewController controller;
  final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');

  // In order to get hot reload to work we need to pause the camera if the platform
  // is android, or resume the camera if the platform is iOS.
  @override
  void reassemble() {
    super.reassemble();
    if (Platform.isAndroid) {
      controller.pauseCamera();
    }
    controller.resumeCamera();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: <Widget>[
          _buildQrView(context),
          Container(
            alignment: Alignment.bottomCenter,
            padding: EdgeInsets.only(bottom: 60.0),
            child: Row(
              children: <Widget>[
                Expanded(
                  child: RawMaterialButton(
                    onPressed: () {
                      setState(() {
                        widget.onClose();
                      });
                    },
                    elevation: 2.0,
                    fillColor: Colors.white,
                    child: Icon(
                      Icons.close_sharp,
                      color: Color(0xff459d44),
                      size: 40.0,
                    ),
                    padding: EdgeInsets.all(8.0),
                    shape: CircleBorder(),
                  ),
                ),
              ],
            ),
          )
        ],
      ),
    );
  }

  Widget _buildQrView(BuildContext context) {
    // For this example we check how width or tall the device is and change the scanArea and overlay accordingly.
    var scanArea = (MediaQuery.of(context).size.width < 400 ||
            MediaQuery.of(context).size.height < 400)
        ? 150.0
        : 300.0;
    // To ensure the Scanner view is properly sizes after rotation
    // we need to listen for Flutter SizeChanged notification and update controller
    return QRView(
      key: qrKey,
      onQRViewCreated: _onQRViewCreated,
      overlay: QrScannerOverlayShape(
          borderColor: Color(0xff459d44),
          borderRadius: 10,
          borderLength: 30,
          borderWidth: 10,
          cutOutSize: scanArea),
    );
  }

  void _onQRViewCreated(QRViewController controller) {
    setState(() {
      this.controller = controller;
    });
    controller.scannedDataStream.listen((scanData) {
      setState(() {
        result = scanData;
      });
    });
  }

  @override
  void dispose() {
    controller?.dispose();
    super.dispose();
  }
}

为什么不能在安卓上运行?

4

1 回答 1

0

您是否在 AndroidManifest.xml 中添加了权限

<uses-permission android:name="android.permission.CAMERA" />

如果它的 webview,你为什么不使用flutter_inappwebview。它很好用,并且具有您以后可能需要的许多附加功能。它仍然需要 androidmanifest 的许可。如果您决定选择flutter_inappwebview,以下是示例。

class _HomePageState extends State<HomePage> {
  InAppWebViewController webView;
  String url = "";

  @override
  void initState(){
    checkPermissions();
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

    checkPermissions() async{
    await [
      Permission.camera,
      Permission.storage,
    ].request();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: SafeArea(
        child: Container(
          child: Column(children: <Widget>[
            Expanded(
              child: Container(
                child: InAppWebView(
                  initialUrl: 'https://flutter.dev',
                  initialHeaders: {},
                  initialOptions: InAppWebViewGroupOptions(
                    crossPlatform: InAppWebViewOptions(
                        debuggingEnabled: true,
                    )
                  ),
                  onWebViewCreated: (InAppWebViewController controller) {
                    webView = controller;
                  },
                  onLoadStart: (InAppWebViewController controller, String url) {
                    setState(() {
                      this.url = url;
                    });
                  },
                  onLoadStop: (InAppWebViewController controller, String url) async {
                    setState(() {
                      this.url = url;
                    });
                  },
                  /// this is the important one to pass the permission
                  androidOnPermissionRequest: (InAppWebViewController controller, String origin, List<String> resources) async {
                    return PermissionRequestResponse(resources: resources, action: PermissionRequestResponseAction.GRANT);
                  },
                ),
              ),
            ),
          ])
        ),
      ),
    );
  }
}

不要忘记在你的 pubspec.yaml中添加这个permission_handler

于 2021-03-22T12:38:52.223 回答