Ghanshyam Savaliya
Ghanshyam Savaliya

Reputation: 345

How to open an application from a Flutter app?

I am developing a Flutter app, in which I need to show navigation to the user for a place. So, how can I open a map application from my Flutter app like we do using external intent in Android?

Or their is any flutter-plugin for it?

Upvotes: 21

Views: 55898

Answers (6)

Suresh B B
Suresh B B

Reputation: 1420

The url_launcher plugin allows your Flutter application to perform actions like opening a web page in Safari or deep-linking into another application with context.

Adding the url_launcher Plugin

dependencies:
  flutter:
    sdk: flutter

  url_launcher: ^6.0.3


import 'dart:async';

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

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

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

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

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

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

  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';
    }
  }

  Future<void> _launchInWebViewOrVC(String url) async {
    if (await canLaunch(url)) {
      await launch(
        url,
        forceSafariVC: true,
        forceWebView: true,
        headers: <String, String>{'my_header_key': 'my_header_value'},
      );
    } else {
      throw 'Could not launch $url';
    }
  }

  Future<void> _launchInWebViewWithJavaScript(String url) async {
    if (await canLaunch(url)) {
      await launch(
        url,
        forceSafariVC: true,
        forceWebView: true,
        enableJavaScript: true,
      );
    } else {
      throw 'Could not launch $url';
    }
  }

  Future<void> _launchInWebViewWithDomStorage(String url) async {
    if (await canLaunch(url)) {
      await launch(
        url,
        forceSafariVC: true,
        forceWebView: true,
        enableDomStorage: true,
      );
    } else {
      throw 'Could not launch $url';
    }
  }

  Future<void> _launchUniversalLinkIos(String url) async {
    if (await canLaunch(url)) {
      final bool nativeAppLaunchSucceeded = await launch(
        url,
        forceSafariVC: false,
        universalLinksOnly: true,
      );
      if (!nativeAppLaunchSucceeded) {
        await launch(
          url,
          forceSafariVC: true,
        );
      }
    }
  }

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

  Future<void> _makePhoneCall(String url) async {
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      throw 'Could not launch $url';
    }
  }

  @override
  Widget build(BuildContext context) {
    const String toLaunch = 'https:'https://www.cylog.org/headers/';
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView(
        children: <Widget>[
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Padding(
                padding: EdgeInsets.all(16.0),
                child: Text('Launch URL : $toLaunch'),
              ),
              RaisedButton(
                onPressed: () => setState(() {
                  _launched = _launchInBrowser(toLaunch);
                }),
                child: const Text('Launch in browser'),
              ),
              const Padding(padding: EdgeInsets.all(16.0)),
              RaisedButton(
                onPressed: () => setState(() {
                  _launched = _launchInWebViewOrVC(toLaunch);
                }),
                child: const Text('Launch in app'),
              ),
              RaisedButton(
                onPressed: () => setState(() {
                  _launched = _launchInWebViewWithJavaScript(toLaunch);
                }),
                child: const Text('Launch in app(JavaScript ON)'),
              ),
              RaisedButton(
                onPressed: () => setState(() {
                  _launched = _launchInWebViewWithDomStorage(toLaunch);
                }),
                child: const Text('Launch in app(DOM storage ON)'),
              ),
              const Padding(padding: EdgeInsets.all(16.0)),
              RaisedButton(
                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)),
              RaisedButton(
                onPressed: () => setState(() {
                  _launched = _launchInWebViewOrVC(toLaunch);
                  Timer(const Duration(seconds: 5), () {
                    print('Closing WebView after 5 seconds...');
                    closeWebView();
                  });
                }),
                child: const Text('Launch in app + close after 5 seconds'),
              ),
              const Padding(padding: EdgeInsets.all(16.0)),
              FutureBuilder<void>(future: _launched, builder: _launchStatus),
            ],
          ),
        ],
      ),
    );
  }
}

Upvotes: 0

Sagar Mitkari
Sagar Mitkari

Reputation: 11

I think you are looking for a scenario where you want to open device installed app from Flutter?

If so , you can use a package called device_apps.

This FLutter package also shows you icon of app to display and you can open app by package name as well.

Just browse all methods it offers. I am using it for my Flutter FItness app to launch installed music player.

https://pub.dev/packages/device_apps

Upvotes: 1

Shubham Narkhede
Shubham Narkhede

Reputation: 2130

In that case you just need to use url_launcher plugin which opens your app.

yourMap() async {
  const url = "https://www.google.com/maps/search/? 
  api=1&query=LATITUDE,LONGITUDE,17&query_place_id=PLACE_ID";
 if (await canLaunch(url)) {
   await launch(url);
 } else {
   throw 'Could not launch Maps';
  }
}

and then call this yourMap() method on your button onPress.

Upvotes: 0

cosinus
cosinus

Reputation: 2165

For iOS use, no browser involved, directly to apps:

//waze 
canLaunch("waze://") 
launch("waze://?ll=${latitude},${longitude}&navigate=yes"); 
//gmaps 
canLaunch("comgooglemaps://") 
launch("comgooglemaps://?saddr=${latitude},${longitude}&directionsmode=driving")

What you need to do is to add to Info.plist:

<key>LSApplicationQueriesSchemes</key>  
<array>         
  <string>comgooglemaps</string>        
  <string>waze</string>     
</array>

Upvotes: 17

shadowsheep
shadowsheep

Reputation: 15002

I suggest you to use url_launcher dart package.

In this way you can use all url schemas to open (phone, sms, and even maps as in your case).

In order to open Google Maps either in Android and iOS you could use the general Android Maps URI schema as suggested by Hemanth Raj.

_openMap() async {
    const url = 'https://www.google.com/maps/search/?api=1&query=52.32,4.917';
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      throw 'Could not launch $url';
    }
  }

If you want to give a choice on Android you could use the general geo: URI schema.

If you want specifically open iOS Maps API you can use Cupertino Maps URI schema.

If you choose to distinguish between Android and iOS (not using Google Maps Api schema for all platform) you have to do it also in your open map call in a way like this:

_openMap() async {
    // Android
    const url = 'geo:52.32,4.917';
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      // iOS
      const url = 'http://maps.apple.com/?ll=52.32,4.917';
      if (await canLaunch(url)) {
        await launch(url);
      } else {
        throw 'Could not launch $url';
      }
    }
  }

Or you can check the OS at runtime with dart.io library Platform class:

import 'dart:io';

_openMap() async {
    // Android
    var url = 'geo:52.32,4.917';
    if (Platform.isIOS) {
      // iOS
      url = 'http://maps.apple.com/?ll=52.32,4.917';
    }
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      throw 'Could not launch $url';
    }
  }

Now that I finished hosekeeping (the real one... not some code refactoring... ^^') I can finish my answer.

As I tell you at the beginning with url_launcher you can use all URI Schemas in order to call, send sms, send e-mail etc.

Here some code to do that:

_sendMail() async {
    // Android and iOS
    const uri = 'mailto:[email protected]?subject=Greetings&body=Hello%20World';
    if (await canLaunch(uri)) {
      await launch(uri);
    } else {
    throw 'Could not launch $uri';
    }
  }

  _callMe() async {
    // Android
    const uri = 'tel:+1 222 060 888';
    if (await canLaunch(uri)) {
      await launch(uri);
    } else {
      // iOS
      const uri = 'tel:001-22-060-888';
      if (await canLaunch(uri)) {
        await launch(uri);
      } else {
        throw 'Could not launch $uri';
      }
    }
  }

  _textMe() async {
    // Android
    const uri = 'sms:+39 349 060 888';
    if (await canLaunch(uri)) {
      await launch(uri);
    } else {
      // iOS
      const uri = 'sms:0039-222-060-888';
      if (await canLaunch(uri)) {
        await launch(uri);
      } else {
        throw 'Could not launch $uri';
      }
    }
  }

Even if URI schema should be standards (RFC) sometimes the authority and path parts of them could differ between frameworks (Android or iOS).

So here I manage the different OSes with exception but, you could do it better with dart.io library Platform class:

import 'dart:io'

and then in code:

if (Platform.isAndroid) {

} else if (Platform.isIOS) {

}

I suggest you always test them in both environments.

You can check the Android and iOS schema documenation here:

If you wanna something similar to startActivity in Android (but that works only for Android platform) you can use the dart package android_intent.

Upvotes: 78

Hemanth Raj
Hemanth Raj

Reputation: 34769

You can just use the url_launcher plugin to open maps. It launches map if installed or falls back to open the map on a browser.

Example:

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

void main() {
  runApp(new Scaffold(
    body: new Center(
      child: new RaisedButton(
        onPressed: _launchURL,
        child: new Text('Launch Maps'),
      ),
    ),
  ));
}

_launchMaps() async {
  const url = "https://www.google.com/maps/search/?api=1&query=LATITUDE,LONGITUDE,17&query_place_id=PLACE_ID";
  if (await canLaunch(url)) {
    await launch(url);
  } else {
    throw 'Could not launch Maps';
  }
}

Hope that helps!

Upvotes: 2

Related Questions