Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Open an Alert asking to choose App to open map with

I have a view controller with map kit integrated. I need to shoot an alert before opening that map, asking to choose from all similar applications of maps to open it with. For instance, if google maps app is installed in my iPhone, there should be an option for it, along with the default mapkit view. Is there a possibility to achieve this functionality which scans every similar app from iphone and returns the result as options to open map with.

like image 786
Sam Avatar asked Jul 07 '16 16:07

Sam


People also ask

How do I get Google Maps to open automatically?

Open the Gmail app and tap the menu icon in the top left corner of the screen. Scroll down to the bottom of the menu and tap Settings. On the Settings screen, tap the Default apps option. Under the Navigate from your location and the Navigate between location sections, tap to select Google Maps.


3 Answers

Swift 5+ solution based on previous answers, this one shows a selector between Apple Maps, Google Maps, Waze and City Mapper. It also allows for some optional location title (for those apps that support it) and presents the alert only if there are more than 1 option (it opens automatically if only 1, or does nothing if none).

func openMaps(latitude: Double, longitude: Double, title: String?) {
    let application = UIApplication.shared
    let coordinate = "\(latitude),\(longitude)"
    let encodedTitle = title?.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
    let handlers = [
        ("Apple Maps", "http://maps.apple.com/?q=\(encodedTitle)&ll=\(coordinate)"),
        ("Google Maps", "comgooglemaps://?q=\(coordinate)"),
        ("Waze", "waze://?ll=\(coordinate)"),
        ("Citymapper", "citymapper://directions?endcoord=\(coordinate)&endname=\(encodedTitle)")
    ]
        .compactMap { (name, address) in URL(string: address).map { (name, $0) } }
        .filter { (_, url) in application.canOpenURL(url) }

    guard handlers.count > 1 else {
        if let (_, url) = handlers.first {
            application.open(url, options: [:])
        }
        return
    }
    let alert = UIAlertController(title: R.string.localizable.select_map_app(), message: nil, preferredStyle: .actionSheet)
    handlers.forEach { (name, url) in
        alert.addAction(UIAlertAction(title: name, style: .default) { _ in
            application.open(url, options: [:])
        })
    }
    alert.addAction(UIAlertAction(title: R.string.localizable.cancel(), style: .cancel, handler: nil))
    contextProvider.currentViewController.present(alert, animated: true, completion: nil)
}

Note this solution uses R.swift for string localization but you can replace those with NSLocalizedString normally, and it uses a contextProvider.currentViewController to get the presented UIViewController, but you can replace it with self if you are calling this in a view controller already.

As usual, you need to also add the following to your app Info.plist:

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>citymapper</string>
    <string>comgooglemaps</string>
    <string>waze</string>
</array>
like image 149
Angel G. Olloqui Avatar answered Oct 19 '22 05:10

Angel G. Olloqui


Swift 5+

Base on @Emptyless answer.

to

import MapKit

func openMapButtonAction() {
        let latitude = 45.5088
        let longitude = -73.554

        let appleURL = "http://maps.apple.com/?daddr=\(latitude),\(longitude)"
        let googleURL = "comgooglemaps://?daddr=\(latitude),\(longitude)&directionsmode=driving"
        let wazeURL = "waze://?ll=\(latitude),\(longitude)&navigate=false"

        let googleItem = ("Google Map", URL(string:googleURL)!)
        let wazeItem = ("Waze", URL(string:wazeURL)!)
        var installedNavigationApps = [("Apple Maps", URL(string:appleURL)!)]

        if UIApplication.shared.canOpenURL(googleItem.1) {
            installedNavigationApps.append(googleItem)
        }

        if UIApplication.shared.canOpenURL(wazeItem.1) {
            installedNavigationApps.append(wazeItem)
        }

        let alert = UIAlertController(title: "Selection", message: "Select Navigation App", preferredStyle: .actionSheet)
        for app in installedNavigationApps {
            let button = UIAlertAction(title: app.0, style: .default, handler: { _ in
                UIApplication.shared.open(app.1, options: [:], completionHandler: nil)
            })
            alert.addAction(button)
        }
        let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
        alert.addAction(cancel)
        present(alert, animated: true)
    }

Also put these in your info.plist:

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

Cheers!

like image 27
Ahmadreza Avatar answered Oct 19 '22 05:10

Ahmadreza


You can create an array of checks to map the installed apps using sumesh's answer [1]:

var installedNavigationApps : [String] = ["Apple Maps"] // Apple Maps is always installed

and with every navigation app you can think of:

if (UIApplication.sharedApplication().canOpenURL(url: NSURL)) {
        self.installedNavigationApps.append(url)
} else {
        // do nothing
}

Common navigation apps are:

  • Google Maps - NSURL(string:"comgooglemaps://")
  • Waze - NSURL(string:"waze://")
  • Navigon - NSURL(string:"navigon://")
  • TomTom - NSURL(string:"tomtomhome://")

A lot more can be found at: http://wiki.akosma.com/IPhone_URL_Schemes

After you created your list of installed navigation apps you can present an UIAlertController:

let alert = UIAlertController(title: "Selection", message: "Select Navigation App", preferredStyle: .ActionSheet)
for app in self.installNavigationApps {
    let button = UIAlertAction(title: app, style: .Default, handler: nil)
    alert.addAction(button)
}
self.presentViewController(alert, animated: true, completion: nil)

Of course you need to add the behavior of a button click in the handler with the specified urlscheme. For example if Google Maps is clicked use something like this:

UIApplication.sharedApplication().openURL(NSURL(string:
            "comgooglemaps://?saddr=&daddr=\(place.latitude),\(place.longitude)&directionsmode=driving")!) // Also from sumesh's answer

With only Apple Maps and Google Maps installed this will yield something like this:

enter image description here

like image 36
Emptyless Avatar answered Oct 19 '22 03:10

Emptyless