如何在Android Studio中利用Google Maps实现往返路线显示功能
Android Studio集成Google Maps路线规划器实现步骤
一、前期准备
- 在Google Cloud Console中启用Maps SDK for Android和Directions API,生成并获取专属API密钥。
- 在项目的
AndroidManifest.xml中添加必要配置:- 声明权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - 添加API密钥的meta-data:
<meta-data android:name="com.google.android.geo.API_KEY" android:value="你的API密钥"/>
- 声明权限:
二、搭建布局
在Activity的布局文件(如activity_main.xml)中添加输入框、按钮和地图组件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <EditText android:id="@+id/et_start" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="输入起点"/> <EditText android:id="@+id/et_end" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="输入终点" android:layout_marginTop="8dp"/> <Button android:id="@+id/btn_show_route" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="显示轨迹" android:layout_marginTop="16dp"/> <fragment android:id="@+id/map_fragment" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:layout_marginTop="16dp"/> </LinearLayout>
三、核心代码实现
1. 初始化地图
在Activity中获取地图实例,实现OnMapReadyCallback:
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback { private GoogleMap mMap; private EditText etStart, etEnd; private Button btnShowRoute; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); etStart = findViewById(R.id.et_start); etEnd = findViewById(R.id.et_end); btnShowRoute = findViewById(R.id.btn_show_route); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map_fragment); mapFragment.getMapAsync(this); } @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; // 启用我的位置图层(需处理运行时权限) if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 100); return; } mMap.setMyLocationEnabled(true); } }
2. 地址转坐标(Geocoder)
添加方法将输入的地址转换为LatLng坐标:
private LatLng getLatLngFromAddress(String address) { Geocoder geocoder = new Geocoder(this, Locale.getDefault()); List<Address> addresses = null; try { addresses = geocoder.getFromLocationName(address, 1); if (addresses != null && !addresses.isEmpty()) { Address location = addresses.get(0); return new LatLng(location.getLatitude(), location.getLongitude()); } } catch (IOException e) { e.printStackTrace(); } return null; }
3. 请求并绘制路线
绑定按钮点击事件,调用Directions API获取路线数据并绘制:
btnShowRoute.setOnClickListener(v -> { String startAddr = etStart.getText().toString().trim(); String endAddr = etEnd.getText().toString().trim(); if (TextUtils.isEmpty(startAddr) || TextUtils.isEmpty(endAddr)) { Toast.makeText(this, "请输入起点和终点", Toast.LENGTH_SHORT).show(); return; } LatLng startLatLng = getLatLngFromAddress(startAddr); LatLng endLatLng = getLatLngFromAddress(endAddr); if (startLatLng == null || endLatLng == null) { Toast.makeText(this, "地址解析失败,请检查输入", Toast.LENGTH_SHORT).show(); return; } // 构建Directions API请求URL String url = "https://maps.googleapis.com/maps/api/directions/json?" + "origin=" + startLatLng.latitude + "," + startLatLng.longitude + "&destination=" + endLatLng.latitude + "," + endLatLng.longitude + "&mode=driving" + // 可选:driving/walking/bicycling/transit "&key=你的API密钥"; // 发起网络请求(示例用AsyncTask,推荐用Retrofit等现代框架) new FetchRouteTask(startLatLng, endLatLng).execute(url); }); // 异步任务处理路线请求 private class FetchRouteTask extends AsyncTask<String, Void, String> { private final LatLng start; private final LatLng end; public FetchRouteTask(LatLng start, LatLng end) { this.start = start; this.end = end; } @Override protected String doInBackground(String... urls) { String response = ""; try { URL url = new URL(urls[0]); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); InputStream in = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); String line; while ((line = reader.readLine()) != null) { response += line; } reader.close(); conn.disconnect(); } catch (IOException e) { e.printStackTrace(); } return response; } @Override protected void onPostExecute(String response) { super.onPostExecute(response); parseRouteResponse(response, start, end); } } // 解析路线响应并绘制Polyline private void parseRouteResponse(String response, LatLng start, LatLng end) { try { JSONObject jsonObject = new JSONObject(response); JSONArray routes = jsonObject.getJSONArray("routes"); if (routes.length() == 0) { Toast.makeText(this, "未找到可行路线", Toast.LENGTH_SHORT).show(); return; } JSONObject route = routes.getJSONObject(0); JSONObject overviewPolyline = route.getJSONObject("overview_polyline"); String encodedPolyline = overviewPolyline.getString("points"); // 解码Polyline点 List<LatLng> points = PolyUtil.decode(encodedPolyline); // 绘制路线 mMap.addPolyline(new PolylineOptions() .addAll(points) .width(10) .color(Color.BLUE)); // 移动相机到路线区域 LatLngBounds bounds = new LatLngBounds.Builder() .include(start) .include(end) .build(); mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100)); } catch (JSONException e) { e.printStackTrace(); Toast.makeText(this, "路线解析失败", Toast.LENGTH_SHORT).show(); } }
四、注意事项
- 为API密钥设置包名+SHA-1的应用限制,避免密钥被滥用。
- 建议使用Retrofit替代已废弃的AsyncTask处理网络请求。
- Android 6.0及以上系统需动态申请位置权限。
- Geocoder在部分设备/区域可能失效,可考虑备用地址解析方案。
内容的提问来源于stack exchange,提问作者Donny
相关产品推荐
相关产品推荐

