如何从 Flutter 应用程序打开应用程序?

How to open an application from a Flutter app?

我正在开发一个 Flutter 应用程序,我需要在其中向用户显示某个地点的导航。那么,我如何才能像在 Android 中使用外部意图一样从我的 Flutter 应用程序打开地图应用程序?

或者他们有什么 flutter-plugin 吗?

您可以只使用url_launcher插件打开地图。如果已安装,它会启动地图,或者回退到在浏览器上打开地图。

示例:

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

希望对您有所帮助!

我建议你使用 url_launcher dart 包。

通过这种方式,您可以使用所有 url 模式打开(phonesms,甚至 maps,如您的情况)。

要在 Android 和 iOS 中打开 Google 地图,您可以按照 Hemanth Raj 的建议使用 general Android Maps URI schema

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

如果您想在 Android 上做出选择,您可以使用一般的 geo: URI schema

如果你想专门打开 iOS 地图 API 你可以使用 Cupertino Maps URI schema.

如果您选择区分 Android 和 iOS(不对所有平台使用 Google 地图 Api 模式),您也必须在您的开放地图调用方式如下:

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

或者您可以在运行时使用 dart.io library Platform class:

检查 OS
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';
    }
  }

现在我完成了管理(真正的管理...不是一些代码重构...^^')我可以完成我的回答了。

正如我在开头告诉您的 url_launcher 您可以使用所有 URI 模式来打电话、发送短信、发送 e-mail 等

这里有一些代码可以做到这一点:

_sendMail() async {
    // Android and iOS
    const uri = 'mailto:test@example.org?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';
      }
    }
  }

即使 URI 模式应该是标准 (RFC),有时它们的 authoritypath 部分可能因框架而异(Android 或 iOS).

所以在这里我管理不同的 OSes 但你可以用 dart.io library Platform class:

做得更好
import 'dart:io'

然后在代码中:

if (Platform.isAndroid) {

} else if (Platform.isIOS) {

}

我建议您始终在两种环境中测试它们。

您可以在此处查看 Android 和 iOS 架构文档:

如果你想要类似于 Android 中的 startActivity 的东西(但只适用于 Android 平台)你可以使用 dart 包 android_intent.

供iOS使用,不涉及浏览器,直接到应用程序:

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

你需要做的是添加到Info.plist:

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

在这种情况下,您只需要使用 url_launcher 插件即可打开您的应用程序。

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

然后在您的按钮 onPress 上调用这个 yourMap() 方法。

我想您正在寻找一种场景,您想要从 Flutter 打开设备安装的应用程序?

如果是这样,您可以使用名为 device_apps 的包。

这个 FLutter 包还会显示要显示的应用程序图标,您也可以通过包名打开应用程序。

只需浏览它提供的所有方法即可。我在我的 Flutter FItness 应用程序中使用它来启动已安装的音乐播放器。

https://pub.dev/packages/device_apps

url_launcher 插件允许您的 Flutter 应用程序执行操作,例如在 Safari 中打开网页或使用上下文深度链接到另一个应用程序。

添加 url_launcher 插件

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),
            ],
          ),
        ],
      ),
    );
  }
}