如何从我的应用程序中打开标准的 Google Map 应用程序?
Posted
技术标签:
【中文标题】如何从我的应用程序中打开标准的 Google Map 应用程序?【英文标题】:How to open standard Google Map application from my application? 【发布时间】:2011-09-06 13:02:06 【问题描述】:一旦用户在我的应用程序中按下按钮,我想打开标准的谷歌地图应用程序并显示特定的位置。我该怎么做? (不使用com.google.android.maps.MapView
)
【问题讨论】:
【参考方案1】:您应该使用地理 URI 创建一个 Intent
对象:
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
【讨论】:
谢谢,@Pixie!纬度和经度的格式是什么?如果我通过lat: 59.915494, lng: 30.409456
它会返回错误的位置。
好的,我找到了问题。 String.format("geo:%f,%f", latitude, longitude)
用逗号返回字符串:geo:59,915494,30,409456
。
这会将我移动到该位置,但它不会在那里放置气球。我想要一个气球,这样用户就可以点击它来获取路线等。
不要将 String.format() 用于简单的字符串连接。该方法仅适用于 UI 文本,这就是小数点表示可能会有所不同的原因。只需使用 "+" 运算符或 StringBuilder: String uri = "geo:" + lastLocation.getLatitude() + "," + lastLocation.getLongitude()。
对于路线,导航意图现在支持 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);【参考方案2】:
您也可以简单地使用 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,因为 Internet 浏览器也是启动此 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);
【讨论】:
java.util.IllegalFormatConversionException: %f 无法格式化 java.lang.String 参数异常 请发布您已将第一行代码替换为 [以 String uri = string.format 开头的行] 似乎您有一个字符串作为应该是浮点数的参数之一 嘿,当我将标签传递给带有纬度和经度的谷歌地图时,地图应用程序会将标签转换为地址。你能告诉我如何解决这个问题吗?【参考方案3】:使用字符串格式会有所帮助,但您必须注意语言环境。在德国,浮点数将用逗号分隔,而不是一个点。
在语言环境中使用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:
!!! 但要小心,geo-uri 仍在开发中 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);
【讨论】:
您也可以使用“&t=h”与“&t=m”来调用卫星或地图图层显示。 我正在尝试类似的方法,只是我添加了一个带有坐标的查询,以便得到一个气球。我的代码看起来与您的第一个示例完全相同。我使用英语语言环境格式化 URI,但是当我在设置为德语语言环境的设备上使用它时,Google 地图仍然用逗号替换点,因此我的查询不起作用。当我将设备的语言环境设置为 English US f.e.它工作得很好。我能做些什么?似乎无论谷歌地图再次更改查询字符串。【参考方案4】:从谷歌检查这个页面:
http://developer.android.com/guide/appendix/g-app-intents.html
您可以使用格式为 URI
geo:latitude,longitude
打开 Google 地图查看器并将其指向某个位置。
【讨论】:
【参考方案5】:您也可以使用下面的代码 sn-p,以这种方式在启动意图之前检查谷歌地图的存在。
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
【讨论】:
【参考方案6】:有时如果没有任何与 geo: protocal 相关的应用程序, 你可以使用 try-catch 来获取 ActivityNotFoundException 来处理它。
当你使用像androVM这样默认没有安装谷歌地图的模拟器时会发生这种情况。
【讨论】:
【参考方案7】:要前往带有 PIN 码的位置,请使用:
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);
如果没有 pin,请在 uri 中使用:
String uri = "geo:" + destinationLatitude + "," + destinationLongitude;
【讨论】:
【参考方案8】:这是用 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
。
【讨论】:
【参考方案9】:我有一个示例应用程序,我在其中准备意图并将意图中的 CITY_NAME 传递给地图标记活动,该活动最终通过地理编码器使用 CITY_NAME 计算经度和纬度。
下面是启动地图标记活动的代码sn-p和完整的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
【讨论】:
【参考方案10】:另外,您可以使用 external_app_launcher:https://pub.dev/packages/external_app_launcher
要知道是否安装:
await LaunchApp.isAppInstalled(androidPackageName: 'com.google.android.maps.MapView', iosUrlScheme: 'comgooglemaps://');
打开:
await LaunchApp.openApp(
androidPackageName: 'com.google.android.maps.MapView',
iosUrlScheme: 'comgooglemaps://',
);
【讨论】:
【参考方案11】: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);
【讨论】:
纯代码答案是低质量的答案。 “低质量”,是的,但不(必然)值得删除。不过,解释会大大改善帖子。以上是关于如何从我的应用程序中打开标准的 Google Map 应用程序?的主要内容,如果未能解决你的问题,请参考以下文章
从我自己的 Android 应用程序单击我的 Google 地图活动中的标记时打开浏览器 url
如何从我的 Google Developers Console 中识别 Google Cloud Storage URI?