如何在Flutter中通过QR Code扫描判断APP安装状态并实现跳转
实现基于Flutter的QR Code扫描跳转方案
一、已安装APP时:内置扫描器+内置浏览器实现
1. 依赖选择
使用qr_code_scanner实现QR码扫描,webview_flutter实现内置浏览器,二者都是Flutter生态中稳定常用的包。
2. 核心实现步骤
- 集成QR扫描组件,监听扫描结果并解析URL
- 用WebView加载解析后的URL,替代系统浏览器跳转
3. 示例代码
首先在pubspec.yaml中添加依赖:
dependencies: flutter: sdk: flutter qr_code_scanner: ^1.0.1 webview_flutter: ^4.4.0
然后实现扫描页面与WebView页面:
import 'package:flutter/material.dart'; import 'package:qr_code_scanner/qr_code_scanner.dart'; import 'package:webview_flutter/webview_flutter.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'QR Scanner Demo', theme: ThemeData(primarySwatch: Colors.blue), home: const QRScannerPage(), ); } } class QRScannerPage extends StatefulWidget { const QRScannerPage({super.key}); @override State<QRScannerPage> createState() => _QRScannerPageState(); } class _QRScannerPageState extends State<QRScannerPage> { final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); QRViewController? controller; bool _isScanned = false; @override void reassemble() { super.reassemble(); controller?.pauseCamera(); controller?.resumeCamera(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('内置QR扫描器')), body: _isScanned ? const SizedBox.shrink() : QRView( key: qrKey, onQRViewCreated: _onQRViewCreated, ), ); } void _onQRViewCreated(QRViewController controller) { this.controller = controller; controller.scannedDataStream.listen((scanData) { if (!_isScanned) { _isScanned = true; controller.pauseCamera(); final url = scanData.code; if (url != null && Uri.tryParse(url) != null) { Navigator.push( context, MaterialPageRoute(builder: (context) => WebViewPage(url: url)), ).then((_) { _isScanned = false; controller.resumeCamera(); }); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('扫描到的内容不是有效URL')), ); _isScanned = false; controller.resumeCamera(); } } }); } @override void dispose() { controller?.dispose(); super.dispose(); } } class WebViewPage extends StatefulWidget { final String url; const WebViewPage({super.key, required this.url}); @override State<WebViewPage> createState() => _WebViewPageState(); } class _WebViewPageState extends State<WebViewPage> { late WebViewController webViewController; @override void initState() { super.initState(); webViewController = WebViewController() ..loadRequest(Uri.parse(widget.url)); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('内置浏览器')), body: WebViewWidget(controller: webViewController), ); } }
二、未安装APP时:QR码引导下载方案
1. 核心思路
生成包含**深度链接(Deeplink)**的QR码,用户用系统工具扫描后:
- 若APP已安装,系统唤起APP并传递目标URL参数
- 若未安装,跳转到预设的引导页面(如官网,放置Play/App Store下载按钮)
2. 配置Deeplink
Android配置
在android/app/src/main/AndroidManifest.xml的<activity>标签内添加:
<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="yourapp" android:host="scanner" /> </intent-filter>
iOS配置
在ios/Runner/Info.plist中添加:
<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>yourapp</string> </array> <key>CFBundleURLName</key> <string>scanner</string> </dict> </array>
3. QR码内容格式
使用类似以下格式的链接:
yourapp://scanner?url=https://example.com
同时需在服务器端配置跳转逻辑:访问该链接时优先尝试唤起APP,失败则跳转至下载引导页面。
4. Flutter中处理Deeplink
使用uni_links包监听Deeplink,唤起APP后直接打开目标URL:
先添加依赖:
uni_links: ^0.5.1
修改MyApp为StatefulWidget并添加监听逻辑:
import 'package:flutter/material.dart'; import 'package:uni_links/uni_links.dart'; class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { Uri? _initialUri; @override void initState() { super.initState(); _initUniLinks(); } Future<void> _initUniLinks() async { try { final initialUri = await getInitialUri(); if (initialUri != null) _handleUri(initialUri); uriLinkStream.listen(_handleUri, onError: (err) {}); } catch (e) {} } void _handleUri(Uri uri) { final targetUrl = uri.queryParameters['url']; if (targetUrl != null && Uri.tryParse(targetUrl) != null) { Navigator.push( context, MaterialPageRoute(builder: (context) => WebViewPage(url: targetUrl)), ); } } @override Widget build(BuildContext context) { return MaterialApp( title: 'QR Scanner Demo', theme: ThemeData(primarySwatch: Colors.blue), home: const QRScannerPage(), ); } }
三、注意事项
- Android测试Deeplink可使用命令:
adb shell am start -W -a android.intent.action.VIEW -d "yourapp://scanner?url=https://example.com" com.your.package.name - iOS可通过Xcode Scheme测试或在Safari中输入链接
- 内置WebView需配置网络权限:Android在Manifest中添加
<uses-permission android:name="android.permission.INTERNET" />,iOS若访问HTTP链接需在Info.plist中配置NSAppTransportSecurity
内容的提问来源于stack exchange,提问作者user2297679
相关产品推荐
相关产品推荐

