153

Once user presses button in my application, I would like to open standard Google Map application and to show particular location. How can I do it? (without using com.google.android.maps.MapView)

LA_
  • 19,823
  • 58
  • 172
  • 308

11 Answers11

259

You should create an Intent object with a geo-URI:

String uri = String.format(Locale.ENGLISH, "geo:%f,%f", latitude, longitude);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
context.startActivity(intent);

If you want to specify an address, you should use another form of geo-URI: geo:0,0?q=address.

reference : https://developer.android.com/guide/components/intents-common.html#Maps

Community
  • 1
  • 1
Michael
  • 53,859
  • 22
  • 133
  • 139
  • 1
    Thanks, @Pixie! What is the format of latitude and longitude? If I pass `lat: 59.915494, lng: 30.409456` it returns wrong position. – LA_ Jun 01 '11 at 19:54
  • The URI must be: `geo:59.915494,30.409456`. You can check it using http://maps.google.com. Just enter `59.915494,30.409456` and you will get the right place. Google says it's on a bridge in Saint Petersburg, Russia. – Michael Jun 02 '11 at 04:38
  • @Pixie, thanks - this is exactly what I did. maps.google.com shows correct location, but when the same URI is used in android app, it shows some different place. – LA_ Jun 02 '11 at 06:59
  • Strange, this must work. Have you tried to get coordinates of the place the app shows? Maybe you should also try to download other map applications and launch them with this URI. – Michael Jun 02 '11 at 07:25
  • 2
    Ok, I've found the issue. `String.format("geo:%f,%f", latitude, longitude)` returned the string with commas: `geo:59,915494,30,409456`. – LA_ Jun 02 '11 at 07:49
  • 1
    @Pixie the call to startActivity should be this.startActivity(intent) (where this is the context) – AsTeR Oct 25 '11 at 17:42
  • @Michael how to show direction from my longitude, latitude to given address – Pratik Butani Jul 04 '13 at 06:57
  • 1
    @PratikButani, I think you can use this solution: http://stackoverflow.com/a/2663565/170842 – Michael Jul 04 '13 at 08:43
  • 24
    THis moves me to the location but it does not put a balloon there. I would love a baloon so the user can click it to get directions etc. – Mike Aug 26 '13 at 22:38
  • 1
    Thanks its working..! but how to show pinpoint in maps application – Prasad Oct 30 '14 at 17:10
  • 7
    Do not mess with String.format() for simple String concatenation. That method is meant for UI text only, that's why decimal point represenation may vary. Just use the "+" operator or StringBuilder: String uri = "geo:" + lastLocation.getLatitude() + "," + lastLocation.getLongitude(). – Agustí Sánchez Apr 30 '15 at 22:26
  • 4
    For directions, a navigation intent is now supported with google.navigation:q=latitude,longitude: Uri gmmIntentUri = Uri.parse("google.navigation:q=" + 12f " +"," + 2f); Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri); mapIntent.setPackage("com.google.android.apps.maps"); startActivity(mapIntent); – David Thompson Mar 09 '17 at 12:14
  • @Michael How to get back the result for startactvityforresult? – Roon13 Jun 21 '17 at 06:50
  • @Roon13 I'm not sure it's possible. Anyway, you'd better ask that as a separate question. – Michael Jun 21 '17 at 08:02
  • is there any way to launch this navigation without using ACTION_VIEW, i want to launch this in my custom layout? – Ashana.Jackol Jun 30 '17 at 03:58
  • If you need it in a custom layout you should use Maps API. – Michael Jun 30 '17 at 06:40
  • @DavidThompson awesome, it also automatically goes into navigation mode! – Makalele Feb 06 '18 at 14:34
  • any method to show a pin in google maps? like every other maps app on the planet – behelit Mar 17 '19 at 21:24
119

You can also simply use http://maps.google.com/maps as your URI

String uri = "http://maps.google.com/maps?saddr=" + sourceLatitude + "," + sourceLongitude + "&daddr=" + destinationLatitude + "," + destinationLongitude;
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
startActivity(intent);

or you can make sure that the Google Maps app only is used, this stops the intent filter (dialog) from appearing, by using

intent.setPackage("com.google.android.apps.maps");

like so:

String uri = "http://maps.google.com/maps?saddr=" + sourceLatitude + "," + sourceLongitude + "&daddr=" + destinationLatitude + "," + destinationLongitude;
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
intent.setPackage("com.google.android.apps.maps");
startActivity(intent);

or you can add labels to the locations by adding a string inside parentheses after each set of coordinates like so:

String uri = "http://maps.google.com/maps?saddr=" + sourceLatitude + "," + sourceLongitude + "(" + "Home Sweet Home" + ")&daddr=" + destinationLatitude + "," + destinationLongitude + " (" + "Where the party is at" + ")";
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
intent.setPackage("com.google.android.apps.maps");
startActivity(intent);

To use the users current location as the starting point (unfortunately I haven't found a way to label the current location) then just drop off the saddr parameter as follows:

String uri = "http://maps.google.com/maps?daddr=" + destinationLatitude + "," + destinationLongitude + " (" + "Where the party is at" + ")";
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
intent.setPackage("com.google.android.apps.maps");
startActivity(intent);

For completeness, if the user doesn't have the maps app installed then it's going to be a good idea to catch the ActivityNotFoundException, as @TonyQ states, then we can start the activity again without the maps app restriction, we can be pretty sure that we will never get to the Toast at the end since an internet browser is a valid application to launch this url scheme too.

        String uri = "http://maps.google.com/maps?daddr=" + 12f + "," + 2f + " (" + "Where the party is at" + ")";
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
        intent.setPackage("com.google.android.apps.maps");
        try
        {
            startActivity(intent);
        }
        catch(ActivityNotFoundException ex)
        {
            try
            {
                Intent unrestrictedIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
                startActivity(unrestrictedIntent);
            }
            catch(ActivityNotFoundException innerEx)
            {
                Toast.makeText(this, "Please install a maps application", Toast.LENGTH_LONG).show();
            }
        }

EDIT:

For directions, a navigation intent is now supported with google.navigation

Uri navigationIntentUri = Uri.parse("google.navigation:q=" + 12f + "," + 2f);
Intent mapIntent = new Intent(Intent.ACTION_VIEW, navigationIntentUri);
mapIntent.setPackage("com.google.android.apps.maps");
startActivity(mapIntent);
David Thompson
  • 2,902
  • 2
  • 18
  • 21
  • java.util.IllegalFormatConversionException: %f can't format java.lang.String arguments exceptions – Amitsharma Jun 08 '15 at 08:01
  • Please post what you have replaced the first line of code with [the line that begins with String uri = string.format ] Seems like you have a string as one of the parameters that should be a float – David Thompson Jun 09 '15 at 08:31
  • Hey when I am passing label to google maps with latitude and longitude , map application converts the label into the addresses. Can you please tell that how to solve this problem? – Rohan Sharma Mar 09 '18 at 18:54
43

Using String format will help but you must be care full with the locale. In germany float will be separates with in comma instead an point.

Using String.format("geo:%f,%f",5.1,2.1); on locale english the result will be "geo:5.1,2.1" but with locale german you will get "geo:5,1,2,1"

You should use the English locale to prevent this behavior.

String uri = String.format(Locale.ENGLISH, "geo:%f,%f", latitude, longitude);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
context.startActivity(intent);

To set an label to the geo point you can extend your geo uri by using:

!!! but be carefull with this the geo-uri is still under develoment https://datatracker.ietf.org/doc/html/draft-mayrhofer-geo-uri-00

String uri = String.format(Locale.ENGLISH, "geo:%f,%f?z=%d&q=%f,%f (%s)", 
                           latitude, longitude, zoom, latitude, longitude, label);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
context.startActivity(intent);
Community
  • 1
  • 1
David Boho
  • 2,646
  • 20
  • 17
  • you can also use "&t=h" versus "&t=m" for calling in satellite or map layer display. – tony gil Mar 20 '13 at 19:55
  • 1
    I'm trying something similar except that I add a query with the coordinates so that I get a balloon. My code looks exactly like your first example. I format the URI with English locale, but when I use it on my device that is set to German locale, Google Maps still replaces dots with commas so that my query doesn't work. When I set the device's locale to English US f.e. it works perfectly fine. What can I do? It seems no matter what Google Maps changes the query string again. – kaolick Sep 05 '13 at 11:07
9

Check this page from google :

http://developer.android.com/guide/appendix/g-app-intents.html

You can use a URI of the form

geo:latitude,longitude

to open Google map viewer and point it to a location.

Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
Snicolas
  • 37,840
  • 15
  • 114
  • 173
8

To go to location WITH PIN on it, use:

String uri = "http://maps.google.com/maps?q=loc:" + destinationLatitude + "," + destinationLongitude;
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
intent.setPackage("com.google.android.apps.maps");
startActivity(intent);

for without pin, use this in uri:

 String uri = "geo:" + destinationLatitude + "," + destinationLongitude;
M. Usman Khan
  • 3,689
  • 1
  • 59
  • 69
7

You can also use the code snippet below, with this manner the existence of google maps is checked before the intent is started.

Uri gmmIntentUri = Uri.parse(String.format(Locale.ENGLISH,"geo:%f,%f", latitude, longitude));
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
mapIntent.setPackage("com.google.android.apps.maps");
if (mapIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(mapIntent);
}

Reference: https://developers.google.com/maps/documentation/android-api/intents

6

Sometimes if there's no any application associated with geo: protocal , you could use try-catch to get the ActivityNotFoundException to handle it.

It happens when you use some emulator like androVM which is not installed google map by default.

TonyQ
  • 657
  • 7
  • 8
1

This is written in Kotlin, it will open the maps app if it's found and place the point and let you start the trip:

  val gmmIntentUri = Uri.parse("http://maps.google.com/maps?daddr=" + adapter.getItemAt(position).latitud + "," + adapter.getItemAt(position).longitud)
        val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
        mapIntent.setPackage("com.google.android.apps.maps")
        if (mapIntent.resolveActivity(requireActivity().packageManager) != null) {
            startActivity(mapIntent)
        }

Replace requireActivity() with your Context.

halfer
  • 19,824
  • 17
  • 99
  • 186
Gastón Saillén
  • 12,319
  • 5
  • 67
  • 77
0

I have a sample app where I prepare the intent and just pass the CITY_NAME in the intent to the maps marker activity which eventually calculates longitude and latitude by Geocoder using CITY_NAME.

Below is the code snippet of starting the maps marker activity and the complete MapsMarkerActivity.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    } else if (id == R.id.action_refresh) {
        Log.d(APP_TAG, "onOptionsItemSelected Refresh selected");
        new MainActivityFragment.FetchWeatherTask().execute(CITY, FORECAS_DAYS);
        return true;
    } else if (id == R.id.action_map) {
        Log.d(APP_TAG, "onOptionsItemSelected Map selected");
        Intent intent = new Intent(this, MapsMarkerActivity.class);
        intent.putExtra("CITY_NAME", CITY);
        startActivity(intent);
        return true;
    }

    return super.onOptionsItemSelected(item);
}

public class MapsMarkerActivity extends AppCompatActivity
        implements OnMapReadyCallback {

    private String cityName = "";

    private double longitude;

    private double latitude;

    static final int numberOptions = 10;

    String [] optionArray = new String[numberOptions];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Retrieve the content view that renders the map.
        setContentView(R.layout.activity_map);
        // Get the SupportMapFragment and request notification
        // when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

        // Test whether geocoder is present on platform
        if(Geocoder.isPresent()){
            cityName = getIntent().getStringExtra("CITY_NAME");
            geocodeLocation(cityName);
        } else {
            String noGoGeo = "FAILURE: No Geocoder on this platform.";
            Toast.makeText(this, noGoGeo, Toast.LENGTH_LONG).show();
            return;
        }
    }

    /**
     * Manipulates the map when it's available.
     * The API invokes this callback when the map is ready to be used.
     * This is where we can add markers or lines, add listeners or move the camera. In this case,
     * we just add a marker near Sydney, Australia.
     * If Google Play services is not installed on the device, the user receives a prompt to install
     * Play services inside the SupportMapFragment. The API invokes this method after the user has
     * installed Google Play services and returned to the app.
     */
    @Override
    public void onMapReady(GoogleMap googleMap) {
        // Add a marker in Sydney, Australia,
        // and move the map's camera to the same location.
        LatLng sydney = new LatLng(latitude, longitude);
        // If cityName is not available then use
        // Default Location.
        String markerDisplay = "Default Location";
        if (cityName != null
                && cityName.length() > 0) {
            markerDisplay = "Marker in " + cityName;
        }
        googleMap.addMarker(new MarkerOptions().position(sydney)
                .title(markerDisplay));
        googleMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
    }

    /**
     * Method to geocode location passed as string (e.g., "Pentagon"), which
     * places the corresponding latitude and longitude in the variables lat and lon.
     *
     * @param placeName
     */
    private void geocodeLocation(String placeName){

        // Following adapted from Conder and Darcey, pp.321 ff.
        Geocoder gcoder = new Geocoder(this);

        // Note that the Geocoder uses synchronous network access, so in a serious application
        // it would be best to put it on a background thread to prevent blocking the main UI if network
        // access is slow. Here we are just giving an example of how to use it so, for simplicity, we
        // don't put it on a separate thread.  See the class RouteMapper in this package for an example
        // of making a network access on a background thread. Geocoding is implemented by a backend
        // that is not part of the core Android framework, so we use the static method
        // Geocoder.isPresent() to test for presence of the required backend on the given platform.

        try{
            List<Address> results = null;
            if(Geocoder.isPresent()){
                results = gcoder.getFromLocationName(placeName, numberOptions);
            } else {
                Log.i(MainActivity.APP_TAG, "No Geocoder found");
                return;
            }
            Iterator<Address> locations = results.iterator();
            String raw = "\nRaw String:\n";
            String country;
            int opCount = 0;
            while(locations.hasNext()){
                Address location = locations.next();
                if(opCount == 0 && location != null){
                    latitude = location.getLatitude();
                    longitude = location.getLongitude();
                }
                country = location.getCountryName();
                if(country == null) {
                    country = "";
                } else {
                    country =  ", " + country;
                }
                raw += location+"\n";
                optionArray[opCount] = location.getAddressLine(0)+", "
                        +location.getAddressLine(1)+country+"\n";
                opCount ++;
            }
            // Log the returned data
            Log.d(MainActivity.APP_TAG, raw);
            Log.d(MainActivity.APP_TAG, "\nOptions:\n");
            for(int i=0; i<opCount; i++){
                Log.i(MainActivity.APP_TAG, "("+(i+1)+") "+optionArray[i]);
            }
            Log.d(MainActivity.APP_TAG, "latitude=" + latitude + ";longitude=" + longitude);
        } catch (Exception e){
            Log.d(MainActivity.APP_TAG, "I/O Failure; do you have a network connection?",e);
        }
    }
}

Links expire so i have pasted complete code above but just in case if you would like to see complete code then its available at : https://github.com/gosaliajigar/CSC519/tree/master/CSC519_HW4_89753

JRG
  • 4,037
  • 3
  • 23
  • 34
0

Also, you can use external_app_launcher: https://pub.dev/packages/external_app_launcher

To know if is installed:

await LaunchApp.isAppInstalled(androidPackageName: 'com.google.android.maps.MapView', iosUrlScheme: 'comgooglemaps://');

To open:

await LaunchApp.openApp(
                    androidPackageName: 'com.google.android.maps.MapView',
                    iosUrlScheme: 'comgooglemaps://',
                  );
Ricardo
  • 2,086
  • 25
  • 35
0
Uri gmmIntentUri = Uri.parse("google.streetview:cbll=46.414382,10.013988");


Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);

mapIntent.setPackage("com.google.android.apps.maps");


startActivity(mapIntent);