Flutter Plugin For Launching A URL

url_launcher

 AndroidiOSLinuxmacOSWebWindows
SupportSDK 16+11.0+Any10.11+AnyWindows 10+

Usage

To use this plugin, add url_launcher as a dependency in your pubspec.yaml file.

Example

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

final Uri _url = Uri.parse('https://flutter.dev');

void main() => runApp(
      const MaterialApp(
        home: Material(
          child: Center(
            child: ElevatedButton(
              onPressed: _launchUrl,
              child: Text('Show Flutter homepage'),
            ),
          ),
        ),
      ),
    );

Future<void> _launchUrl() async {
  if (!await launchUrl(_url)) {
    throw Exception('Could not launch $_url');
  }
}

See the example app for more complex examples.

Configuration

iOS

Add any URL schemes passed to canLaunchUrl as LSApplicationQueriesSchemes entries in your Info.plist file, otherwise it will return false.

Example:

<key>LSApplicationQueriesSchemes</key><array>  <string>sms</string>  <string>tel</string></array>

See -[UIApplication canOpenURL:] for more details.

Android

Add any URL schemes passed to canLaunchUrl as <queries> entries in your AndroidManifest.xml, otherwise it will return false in most cases starting on Android 11 (API 30) or higher. A <queries> element must be added to your manifest as a child of the root element.

Example:

```

See the Android documentation for examples of other queries.

Supported URL schemes

The provided URL is passed directly to the host platform for handling. The supported URL schemes therefore depend on the platform and installed apps.

Commonly used schemes include:

SchemeExampleAction
https:<URL>https://flutter.devOpen <URL> in the default browser
mailto:<email address>?subject=<subject>&body=<body>mailto:smith@example.org?subject=News&body=New%20pluginCreate email to <email address> in the default email app
tel:<phone number>tel:+1-555-010-999Make a phone call to <phone number> using the default phone app
sms:<phone number>sms:5550101234Send an SMS message to <phone number> using the default messaging app
file:<path>file:/homeOpen file or folder using default app association, supported on desktop platforms

More details can be found here for iOS and Android

URL schemes are only supported if there are apps installed on the device that can support them. For example, iOS simulators don't have a default email or phone apps installed, so can't open tel: or mailto: links.

Checking supported schemes

If you need to know at runtime whether a scheme is guaranteed to work before using it (for instance, to adjust your UI based on what is available), you can check with canLaunchUrl.

However, canLaunchUrl can return false even if launchUrl would work in some circumstances (in web applications, on mobile without the necessary configuration as described above, etc.), so in cases where you can provide fallback behavior it is better to use launchUrl directly and handle failure. For example, a UI button that would have sent feedback email using a mailto URL might instead open a web-based feedback form using an https URL on failure, rather than disabling the button if canLaunchUrl returns false for mailto.

Encoding URLs

URLs must be properly encoded, especially when including spaces or other special characters. In general this is handled automatically by the Uri class.

However, for any scheme other than http or https, you should use the query parameter and the encodeQueryParameters function shown below rather than Uri's queryParameters constructor argument for any query parameters, due to a bug in the way Uri encodes query parameters. Using queryParameters will result in spaces being converted to + in many cases.

String? encodeQueryParameters(Map<String, String> params) {
  return params.entries
      .map((MapEntry<String, String> e) =>
          '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}')
      .join('&');
}
// ···
  final Uri emailLaunchUri = Uri(
    scheme: 'mailto',
    path: 'smith@example.com',
    query: encodeQueryParameters(<String, String>{
      'subject': 'Example Subject & Symbols are allowed!',
    }),
  );

  launchUrl(emailLaunchUri);

Encoding for sms is slightly different:

final Uri smsLaunchUri = Uri(
  scheme: 'sms',
  path: '0118 999 881 999 119 7253',
  queryParameters: <String, String>{
    'body': Uri.encodeComponent('Example Subject & Symbols are allowed!'),
  },
);

URLs not handled by Uri

In rare cases, you may need to launch a URL that the host system considers valid, but cannot be expressed by Uri. For those cases, alternate APIs using strings are available by importing url_launcher_string.dart.

Using these APIs in any other cases is strongly discouraged, as providing invalid URL strings was a very common source of errors with this plugin's original APIs.

File scheme handling

file: scheme can be used on desktop platforms: Windows, macOS, and Linux.

We recommend checking first whether the directory or file exists before calling launchUrl.

Example:

final String filePath = testFile.absolute.path;
final Uri uri = Uri.file(filePath);

if (!File(uri.toFilePath()).existsSync()) {
  throw Exception('$uri does not exist!');
}
if (!await launchUrl(uri)) {
  throw Exception('Could not launch $uri');
}

macOS file access configuration

If you need to access files outside of your application's sandbox, you will need to have the necessary entitlements.

Browser vs in-app Handling

On some platforms, web URLs can be launched either in an in-app web view, or in the default browser. The default behavior depends on the platform (see launchUrl for details), but a specific mode can be used on supported platforms by passing a LaunchMode.

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add url_launcher

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  url_launcher: ^6.1.11

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:url_launcher/url_launcher.dart';

example/lib/main.dart

// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// ignore_for_file: public_member_api_docs

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:url_launcher/link.dart';
import 'package:url_launcher/url_launcher.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'URL Launcher',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'URL Launcher'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _hasCallSupport = false;
  Future<void>? _launched;
  String _phone = '';

  @override
  void initState() {
    super.initState();
    // Check for phone call support.
    canLaunchUrl(Uri(scheme: 'tel', path: '123')).then((bool result) {
      setState(() {
        _hasCallSupport = result;
      });
    });
  }

  Future<void> _launchInBrowser(Uri url) async {
    if (!await launchUrl(
      url,
      mode: LaunchMode.externalApplication,
    )) {
      throw Exception('Could not launch $url');
    }
  }

  Future<void> _launchInWebViewOrVC(Uri url) async {
    if (!await launchUrl(
      url,
      mode: LaunchMode.inAppWebView,
      webViewConfiguration: const WebViewConfiguration(
          headers: <String, String>{'my_header_key': 'my_header_value'}),
    )) {
      throw Exception('Could not launch $url');
    }
  }

  Future<void> _launchInWebViewWithoutJavaScript(Uri url) async {
    if (!await launchUrl(
      url,
      mode: LaunchMode.inAppWebView,
      webViewConfiguration: const WebViewConfiguration(enableJavaScript: false),
    )) {
      throw Exception('Could not launch $url');
    }
  }

  Future<void> _launchInWebViewWithoutDomStorage(Uri url) async {
    if (!await launchUrl(
      url,
      mode: LaunchMode.inAppWebView,
      webViewConfiguration: const WebViewConfiguration(enableDomStorage: false),
    )) {
      throw Exception('Could not launch $url');
    }
  }

  Future<void> _launchUniversalLinkIos(Uri url) async {
    final bool nativeAppLaunchSucceeded = await launchUrl(
      url,
      mode: LaunchMode.externalNonBrowserApplication,
    );
    if (!nativeAppLaunchSucceeded) {
      await launchUrl(
        url,
        mode: LaunchMode.inAppWebView,
      );
    }
  }

  Widget _launchStatus(BuildContext context, AsyncSnapshot<void> snapshot) {
    if (snapshot.hasError) {
      return Text('Error: ${snapshot.error}');
    } else {
      return const Text('');
    }
  }

  Future<void> _makePhoneCall(String phoneNumber) async {
    final Uri launchUri = Uri(
      scheme: 'tel',
      path: phoneNumber,
    );
    await launchUrl(launchUri);
  }

  @override
  Widget build(BuildContext context) {
    // onPressed calls using this URL are not gated on a 'canLaunch' check
    // because the assumption is that every device can launch a web URL.
    final Uri toLaunch =
        Uri(scheme: 'https', host: 'www.cylog.org', path: 'headers/');
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView(
        children: <Widget>[
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: TextField(
                    onChanged: (String text) => _phone = text,
                    decoration: const InputDecoration(
                        hintText: 'Input the phone number to launch')),
              ),
              ElevatedButton(
                onPressed: _hasCallSupport
                    ? () => setState(() {
                          _launched = _makePhoneCall(_phone);
                        })
                    : null,
                child: _hasCallSupport
                    ? const Text('Make phone call')
                    : const Text('Calling not supported'),
              ),
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: Text(toLaunch.toString()),
              ),
              ElevatedButton(
                onPressed: () => setState(() {
                  _launched = _launchInBrowser(toLaunch);
                }),
                child: const Text('Launch in browser'),
              ),
              const Padding(padding: EdgeInsets.all(16.0)),
              ElevatedButton(
                onPressed: () => setState(() {
                  _launched = _launchInWebViewOrVC(toLaunch);
                }),
                child: const Text('Launch in app'),
              ),
              ElevatedButton(
                onPressed: () => setState(() {
                  _launched = _launchInWebViewWithoutJavaScript(toLaunch);
                }),
                child: const Text('Launch in app (JavaScript OFF)'),
              ),
              ElevatedButton(
                onPressed: () => setState(() {
                  _launched = _launchInWebViewWithoutDomStorage(toLaunch);
                }),
                child: const Text('Launch in app (DOM storage OFF)'),
              ),
              const Padding(padding: EdgeInsets.all(16.0)),
              ElevatedButton(
                onPressed: () => setState(() {
                  _launched = _launchUniversalLinkIos(toLaunch);
                }),
                child: const Text(
                    'Launch a universal link in a native app, fallback to Safari.(Youtube)'),
              ),
              const Padding(padding: EdgeInsets.all(16.0)),
              ElevatedButton(
                onPressed: () => setState(() {
                  _launched = _launchInWebViewOrVC(toLaunch);
                  Timer(const Duration(seconds: 5), () {
                    closeInAppWebView();
                  });
                }),
                child: const Text('Launch in app + close after 5 seconds'),
              ),
              const Padding(padding: EdgeInsets.all(16.0)),
              Link(
                uri: Uri.parse(
                    'https://pub.dev/documentation/url_launcher/latest/link/link-library.html'),
                target: LinkTarget.blank,
                builder: (BuildContext ctx, FollowLink? openLink) {
                  return TextButton.icon(
                    onPressed: openLink,
                    label: const Text('Link Widget documentation'),
                    icon: const Icon(Icons.read_more),
                  );
                },
              ),
              const Padding(padding: EdgeInsets.all(16.0)),
              FutureBuilder<void>(future: _launched, builder: _launchStatus),
            ],
          ),
        ],
      ),
    );
  }
}

Download details:

Author: flutter.dev

Source: https://github.com/flutter/packages/tree/main/packages/url_launcher/url_launcher

#flutter #android #ios #launch #api #web-development #web 

Flutter Plugin For Launching A URL
2.80 GEEK