Как только пользователь нажимает кнопку в моем приложении, я хотел бы открыть стандартное приложение Google Map и показать конкретное местоположение. Как я могу это сделать? (без использования com.google.android.maps.MapView
)
145
Как только пользователь нажимает кнопку в моем приложении, я хотел бы открыть стандартное приложение Google Map и показать конкретное местоположение. Как я могу это сделать? (без использования com.google.android.maps.MapView
)
Вы должны создать Intent
объект с гео-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);
Если вы хотите , чтобы указать адрес, вы должны использовать другую форму гео-URI: geo:0,0?q=address
.
ссылка: https://developer.android.com/guide/components/intents-common.html#Maps
lat: 59.915494, lng: 30.409456
он вернет неправильную позицию.String.format("geo:%f,%f", latitude, longitude)
вернула строку с запятымиgeo:59,915494,30,409456
.Вы также можете просто использовать http://maps.google.com/maps в качестве 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);
или вы можете убедиться, что используется только приложение Google Maps, это останавливает отображение фильтра намерения (диалогового окна), используя
intent.setPackage("com.google.android.apps.maps");
вот так:
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);
или вы можете добавить метки к местоположениям, добавив строку в круглых скобках после каждого набора координат, например:
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);
Чтобы использовать текущее местоположение пользователя в качестве отправной точки (к сожалению, я не нашел способа пометить текущее местоположение), просто удалите
saddr
параметр следующим образом: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);
Для полноты, если у пользователя не установлено приложение карт, было бы неплохо поймать ActivityNotFoundException, как утверждает @TonyQ, тогда мы можем снова запустить действие без ограничения приложения карт, мы можем быть уверены что мы никогда не дойдем до Toast в конце, поскольку интернет-браузер является допустимым приложением для запуска этой схемы URL.
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(); } }
РЕДАКТИРОВАТЬ:
Для маршрутов теперь поддерживается цель навигации с помощью 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);
источник
Использование строкового формата поможет, но вы должны быть внимательны к языку. В Германии float будет разделяться запятой вместо точки.
Используя
String.format("geo:%f,%f",5.1,2.1);
английский язык, результат будет,"geo:5.1,2.1"
но с немецким языком вы получите"geo:5,1,2,1"
Вы должны использовать английский язык, чтобы предотвратить такое поведение.
String uri = String.format(Locale.ENGLISH, "geo:%f,%f", latitude, longitude); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri)); context.startActivity(intent);
Чтобы установить метку для географической точки, вы можете расширить свой географический идентификатор, используя:
!!! но будьте осторожны с этим, гео-uri все еще находится в разработке http://tools.ietf.org/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);
источник
Проверьте эту страницу в Google:
http://developer.android.com/guide/appendix/g-app-intents.html
Вы можете использовать URI в форме
geo:latitude,longitude
, чтобы открыть программу просмотра карт Google и указать ее местоположение.
источник
Вы также можете использовать приведенный ниже фрагмент кода, таким образом, наличие карт Google проверяется перед запуском намерения.
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); }
Ссылка: https://developers.google.com/maps/documentation/android-api/intents
источник
Иногда, если нет никакого приложения, связанного с geo: protocal, вы можете использовать try-catch, чтобы получить ActivityNotFoundException для его обработки.
Это происходит, когда вы используете какой-то эмулятор, например androVM, который по умолчанию не установлен на карту Google.
источник
Чтобы перейти к месту с ПИН-кодом, используйте:
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);
для без булавки используйте это в uri:
String uri = "geo:" + destinationLatitude + "," + destinationLongitude;
источник
Это написано на Kotlin, оно откроет приложение карт, если оно будет найдено, разместит точку и позволит вам начать поездку:
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) }
Замените
requireActivity()
на свойContext
.источник
У меня есть образец приложения, в котором я готовлю намерение и просто передаю CITY_NAME в намерении активности маркера карт, который в конечном итоге вычисляет долготу и широту с помощью геокодера с использованием CITY_NAME.
Ниже приведен фрагмент кода для запуска активности маркера карт и полной 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); } } }
Срок действия ссылок истекает, поэтому я вставил полный код выше, но на всякий случай, если вы хотите увидеть полный код, он доступен по адресу: https://github.com/gosaliajigar/CSC519/tree/master/CSC519_HW4_89753
источник