You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 22:25:30