Flutter url_launcher 无法启动 webview 短谷歌表单链接

Posted

技术标签:

【中文标题】Flutter url_launcher 无法启动 webview 短谷歌表单链接【英文标题】:Flutter url_launcher unable launch webview short google form link 【发布时间】:2021-01-26 08:44:21 【问题描述】:

我正在使用 Flutter 开发一个带有 url_launcher 5.7.2 包 https://pub.dev/packages/url_launcher 的应用程序,当用户点击某个按钮时,该应用程序仅针对谷歌表单启动 webivew。

但是我发现如果使用谷歌表单的缩短 URL 会遇到 ERR_UNKNOWN_URL_SCHEME 错误,使用原始 url 是有效的。

我正在使用这个示例 https://pub.dev/packages/url_launcher/example 并将网址替换为 https://forms.gle/mEwVA8jXmwJEFn5X6 然后点击Launch in app(JavaScript ON)

按钮
await launch(url,forceSafariVC: true,
        forceWebView: true,
        enablejavascript: true,);

如果使用原始长 URL https://docs.google.com/forms/d/e/1FAIpQLSfzXnHMRe890CJj5rSxN-jonjrvZ8HvRBSFcdyJD5IDhOr-IQ/viewform?usp=sf_link 有效。

我已经将 android:usesCleartextTraffic="true" 添加到我的 AndroidManifest.xml 但仍然无法使用短网址

【问题讨论】:

【参考方案1】:

我建议您使用“flutter_webview_plugin”包而不是“url_launcher”。 这个问题是由重定向引起的,浏览器无法理解 android 中“intent”的开头。

import 'dart:async';

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

void main() 
  runApp(MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      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> 
  @override
  void initState() 
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: _buildBody(),
      floatingActionButton: FloatingActionButton(
        onPressed: () 
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) =>
                  WebViewPage(url: 'https://forms.gle/mEwVA8jXmwJEFn5X6'),
            ),
          );
        ,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  

  Widget _buildBody() 
    return Container();
  


class WebViewPage extends StatefulWidget 
  final String url;
  WebViewPage(Key key, this.url) : super(key: key);

  @override
  _WebViewPageState createState() => _WebViewPageState();


class _WebViewPageState extends State<WebViewPage> 
  final flutterWebviewPlugin = FlutterWebviewPlugin();

  @override
  void initState() 
    super.initState();
  

  @override
  void dispose() 
    flutterWebviewPlugin.dispose();
    super.dispose();
  

  @override
  Widget build(BuildContext context) 
    return Material(
      type: MaterialType.transparency,
      child: WebviewScaffold(
        appBar: AppBar(
          title: Text('WebView Page'),
        ),
        url: widget.url,
        userAgent: 'Fake',
        clearCookies: false,
        clearCache: false,
        hidden: true,
        appCacheEnabled: true,
        supportMultipleWindows: true,
      ),
    );
  



【讨论】:

嗨,launch() 可以工作,但我需要在 webview 中使用这个 await launch(url,forceSafariVC: true, forceWebView: true, enableJavaScript: true,); 我按照你说的改变了启动方式。但它再次运行良好。 也许只有 iPhone 可以工作?我在 Android 中测试但仍然无法正常工作, @B.Cos 你用flutter_webview_plugin怎么样?我用“flutter_webview_plugin”更改了代码。 如何将 URL 传递给 WebviewScaffold() 而不是硬编码 URL?示例读取文本字段 URL 值并传递给 WebviewScaffold()【参考方案2】:

试试,这两个都对我有用。尝试卸载然后运行应用程序

代码片段:

class URLLauncher extends StatelessWidget 
  Future<void> _launchInBrowser(String url) async 
    if (await canLaunch(url)) 
      await launch(
        url,
        forceSafariVC: false,
        forceWebView: false,
        headers: <String, String>'my_header_key': 'my_header_value',
      );
     else 
      throw 'Could not launch $url';
    
  
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(),
      body: RaisedButton(onPressed: () 
        // _launchInBrowser("https://docs.google.com/forms/d/e/1FAIpQLSfzXnHMRe890CJj5rSxN-jonjrvZ8HvRBSFcdyJD5IDhOr-IQ/viewform?usp=sf_link ");
        _launchInBrowser("https://forms.gle/mEwVA8jXmwJEFn5X6");
      ),
    );
  

【讨论】:

嗨,我需要 forceWebView: true 因为我需要在应用程序 webview 中使用来隐藏显示 URL 以避免用户看到 url 你在哪里尝试真机或模拟器? 在Android真机上,Android 9【参考方案3】:

当使用 url 启动器时,我们必须按照我在下面提到的步骤进行操作:-

适用于安卓

从 API 30 开始,Android 需要在您的 AndroidManifest.xml 中配置包可见性,否则 canLaunch 将返回 false

    <queries>
        <!-- If your app opens https URLs -->
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <data android:scheme="https" />
        </intent>
        <!-- If your app makes calls -->
        <intent>
            <action android:name="android.intent.action.DIAL" />
            <data android:scheme="tel" />
        </intent>
        <!-- If your sends SMS messages -->
        <intent>
            <action android:name="android.intent.action.SENDTO" />
            <data android:scheme="smsto" />
        </intent>
        <!-- If your app sends emails -->
        <intent>
            <action android:name="android.intent.action.SEND" />
            <data android:mimeType="*/*" />
        </intent>
    </queries>

适用于 iOS

将传递给 canLaunch 的任何 URL 方案添加为 Info.plist 文件中的 LSApplicationQueriesSchemes 条目。

<key>LSApplicationQueriesSchemes</key>
<array>
  <string>https</string>
  <string>http</string>
</array>

【讨论】:

以上是关于Flutter url_launcher 无法启动 webview 短谷歌表单链接的主要内容,如果未能解决你的问题,请参考以下文章

Flutter/Firebase/url_launcher/ 如何从应用程序发送短信?

有啥方法可以播放视频或使用 Flutter for web 启动视频?

带有多个电话号码的 Flutter url_launcher

Url_Launcher 在 iOS 上打开任何地图应用程序

Flutter如何跳转外部地图app导航

如何在 Flutter 中启动 URL?