这样更改对吗?package com.example.bus;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.activity.OnBackPressedCallback;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.MapView;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.LatLngBounds;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.PolylineOptions;
import com.amap.api.services.core.AMapException;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.route.BusPath;
import com.amap.api.services.route.BusRouteResult;
import com.amap.api.services.route.BusStep;
import com.amap.api.services.route.RouteSearch;
import com.amap.api.maps.AMapUtils;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
// ... 前面的 import 和类声明保持不变 ...
public class RoutePlanActivity extends AppCompatActivity implements AMapLocationListener {
public static final String EXTRA_SOURCE = "extra_source";
public static final int SOURCE_FROM_HOME_SEARCH = 1001;
public static final int SOURCE_FROM_MAP_DIRECT = 1002;
// 定义三个策略对应的 Tab 索引
private static final int INDEX_FASTEST = 0; // BUS_DEFAULT
private static final int INDEX_TRANSFER = 1; // BUS_LEASE_CHANGE
private static final int INDEX_WALK = 2; // BUS_LEASE_WALK
// 存储三种策略的路径:按固定索引存储
private final BusPath[] routePaths = new BusPath[3]; // [0]:最快, [1]:最少换乘, [2]:最少步行
private int resultCount = 0;
private boolean isSearching = false;
private int sourceType = -1;
private MapView mapView;
private AMap aMap;
private RecyclerView recyclerSteps;
private TextView tvRouteInfo;
private AMapLocationClient locationClient;
private LatLonPoint currentLocation;
private LatLonPoint targetPoint;
private boolean hasStartedSearch = false;
private OnBackPressedCallback onBackPressedCallback;
private TextView tabFastest, tabTransfer, tabWalk;
public static class VirtualWalkStep {
public final LatLonPoint from;
public final LatLonPoint to;
public final String description;
public VirtualWalkStep(LatLonPoint from, LatLonPoint to, String desc) {
this.from = from;
this.to = to;
this.description = desc;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_route_plan);
sourceType = getIntent().getIntExtra(EXTRA_SOURCE, -1);
double startLat = getIntent().getDoubleExtra("start_lat", 0);
double startLng = getIntent().getDoubleExtra("start_lng", 0);
double targetLat = getIntent().getDoubleExtra("target_lat", 0);
double targetLng = getIntent().getDoubleExtra("target_lng", 0);
Log.d("RoutePlan", "📥 收到参数:");
Log.d("RoutePlan", " sourceType = " + sourceType);
Log.d("RoutePlan", " start = " + startLat + "," + startLng);
Log.d("RoutePlan", " target = " + targetLat + "," + targetLng);
if (targetLat == 0 || targetLng == 0) {
Toast.makeText(this, "目标位置无效", Toast.LENGTH_SHORT).show();
finish();
return;
}
targetPoint = new LatLonPoint(targetLat, targetLng);
mapView = findViewById(R.id.map_view);
recyclerSteps = findViewById(R.id.recycler_steps);
tvRouteInfo = findViewById(R.id.tv_route_info);
mapView.onCreate(savedInstanceState);
if (aMap == null) {
aMap = mapView.getMap();
}
initLocation();
if (sourceType == SOURCE_FROM_MAP_DIRECT) {
startRouteSearch();
}
onBackPressedCallback = new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
if (sourceType == SOURCE_FROM_MAP_DIRECT) {
Intent intent = new Intent(RoutePlanActivity.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("open_tab", "map");
startActivity(intent);
finish();
} else {
setEnabled(false);
getOnBackPressedDispatcher().onBackPressed();
setEnabled(true);
}
}
};
getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback);
tabFastest = findViewById(R.id.tab_fastest);
tabTransfer = findViewById(R.id.tab_transfer);
tabWalk = findViewById(R.id.tab_walk);
View.OnClickListener tabListener = v -> {
if (v == tabFastest && routePaths[INDEX_FASTEST] != null) {
displayRoute(INDEX_FASTEST);
} else if (v == tabTransfer && routePaths[INDEX_TRANSFER] != null) {
displayRoute(INDEX_TRANSFER);
} else if (v == tabWalk && routePaths[INDEX_WALK] != null) {
displayRoute(INDEX_WALK);
}
};
tabFastest.setOnClickListener(tabListener);
tabTransfer.setOnClickListener(tabListener);
tabWalk.setOnClickListener(tabListener);
}
private void initLocation() {
try {
locationClient = new AMapLocationClient(this);
AMapLocationClientOption option = new AMapLocationClientOption();
option.setOnceLocation(true);
option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
option.setMockEnable(false);
locationClient.setLocationOption(option);
locationClient.setLocationListener(this);
locationClient.startLocation();
tvRouteInfo.setText("正在获取您的位置...");
} catch (Exception e) {
Log.e("RoutePlan", "定位初始化失败", e);
tvRouteInfo.setText("定位服务启动失败");
finish();
}
}
private void startRouteSearch() {
if (isSearching || hasStartedSearch) return;
hasStartedSearch = true;
LatLonPoint start = null;
if (sourceType == SOURCE_FROM_HOME_SEARCH) {
if (currentLocation == null) {
Log.e("RoutePlan", "📍 定位未完成,无法发起 HOME_SEARCH");
tvRouteInfo.setText("无法获取您的位置,请稍后重试");
finish();
return;
}
start = currentLocation;
Log.d("RoutePlan", "🏠 使用定位位置作为起点: " + start.getLatitude() + "," + start.getLongitude());
} else if (sourceType == SOURCE_FROM_MAP_DIRECT) {
double startLat = getIntent().getDoubleExtra("start_lat", 0);
double startLng = getIntent().getDoubleExtra("start_lng", 0);
if (Math.abs(startLat) < 1e-6 || Math.abs(startLng) < 1e-6) {
Log.e("RoutePlan", "❌ MapDirect: 起点坐标无效 (" + startLat + ", " + startLng + ")");
tvRouteInfo.setText("起点坐标错误");
finish();
return;
}
start = new LatLonPoint(startLat, startLng);
Log.d("RoutePlan", "🗺️ 使用地图中心作为起点: " + start.getLatitude() + "," + start.getLongitude());
} else {
tvRouteInfo.setText("未知操作来源");
Log.e("RoutePlan", "❌ 未知来源: " + sourceType);
finish();
return;
}
RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(start, targetPoint);
isSearching = true;
tvRouteInfo.setText("正在规划路线...");
sendRequestWithIndex(fromAndTo, RouteSearch.BUS_DEFAULT, INDEX_FASTEST);
sendRequestWithIndex(fromAndTo, RouteSearch.BUS_LEASE_CHANGE, INDEX_TRANSFER);
sendRequestWithIndex(fromAndTo, RouteSearch.BUS_LEASE_WALK, INDEX_WALK);
}
private void sendRequestWithIndex(RouteSearch.FromAndTo fromAndTo, int mode, int index) {
RouteSearch search;
try {
search = new RouteSearch(this);
} catch (AMapException e) {
Log.e("RoutePlan", "创建 RouteSearch 失败 [mode=" + mode + "]", e);
resultCount++;
checkAllResultsAndDisplay();
return;
}
search.setRouteSearchListener(new RouteSearch.OnRouteSearchListener() {
@Override
public void onBusRouteSearched(BusRouteResult result, int rCode) {
isSearching = false;
if (rCode == 1000 && result != null && !result.getPaths().isEmpty()) {
synchronized (routePaths) {
routePaths[index] = result.getPaths().get(0);
}
} else {
Log.w("RoutePlan", "公交路线查询失败 [mode=" + mode + "], rCode=" + rCode);
}
resultCount++;
checkAllResultsAndDisplay();
}
@Override
public void onDriveRouteSearched(com.amap.api.services.route.DriveRouteResult r, int c) {}
@Override
public void onWalkRouteSearched(com.amap.api.services.route.WalkRouteResult r, int c) {}
@Override
public void onRideRouteSearched(com.amap.api.services.route.RideRouteResult r, int c) {}
});
RouteSearch.BusRouteQuery query = new RouteSearch.BusRouteQuery(fromAndTo, mode, "全国", 0);
search.calculateBusRouteAsyn(query);
}
private void addStartMarker(LatLonPoint startPoint) {
if (startPoint == null || aMap == null) return;
aMap.addMarker(new MarkerOptions()
.position(new LatLng(startPoint.getLatitude(), startPoint.getLongitude()))
.title("出发点"));
}
@Override
public void onLocationChanged(AMapLocation loc) {
if (loc != null && loc.getErrorCode() == 0) {
currentLocation = new LatLonPoint(loc.getLatitude(), loc.getLongitude());
Log.d("RoutePlan", "✅ 定位成功: " + loc.getLatitude() + "," + loc.getLongitude());
if (sourceType == SOURCE_FROM_HOME_SEARCH && !hasStartedSearch) {
startRouteSearch();
}
} else {
Log.e("RoutePlan", "❌ 定位失败: " + (loc != null ? loc.getErrorInfo() : "null"));
tvRouteInfo.setText("定位失败,请检查权限");
Toast.makeText(this, "无法获取位置", Toast.LENGTH_LONG).show();
finish();
}
}
// ✅ 【核心修改】展示指定索引的路线(新增换乘步行)
private void displayRoute(int index) {
if (index < 0 || index >= 3 || routePaths[index] == null) return;
BusPath bestPath = routePaths[index];
List<BusStep> originalSteps = bestPath.getSteps();
List<Object> enhancedSteps = new ArrayList<>();
LatLonPoint start = null;
if (sourceType == SOURCE_FROM_HOME_SEARCH && currentLocation != null) {
start = currentLocation;
} else if (sourceType == SOURCE_FROM_MAP_DIRECT) {
double slat = getIntent().getDoubleExtra("start_lat", 0);
double slng = getIntent().getDoubleExtra("start_lng", 0);
if (Math.abs(slat) > 1e-6 && Math.abs(slng) > 1e-6) {
start = new LatLonPoint(slat, slng);
}
}
// 首段步行
if (start != null && !originalSteps.isEmpty()) {
LatLonPoint firstStation = getEntrancePoint(originalSteps.get(0));
if (firstStation != null && !start.equals(firstStation)) {
String name = originalSteps.get(0).getBusLine() != null ?
originalSteps.get(0).getBusLine().getDepartureBusStation().getBusStationName() : "站点";
enhancedSteps.add(new VirtualWalkStep(start, firstStation,
"从当前位置步行至【" + name + "】"));
}
}
// 主体步骤 + 插入换乘步行
for (int i = 0; i < originalSteps.size(); i++) {
BusStep cur = originalSteps.get(i);
enhancedSteps.add(cur);
if (i < originalSteps.size() - 1) {
BusStep next = originalSteps.get(i + 1);
LatLonPoint exit = getExitPoint(cur);
LatLonPoint entrance = getEntrancePoint(next);
if (exit != null && entrance != null && !exit.equals(entrance)) {
String name = next.getBusLine() != null ?
next.getBusLine().getDepartureBusStation().getBusStationName() :
(next.getRailway() != null ? "地铁站" : "站点");
enhancedSteps.add(new VirtualWalkStep(exit, entrance,
"换乘步行至【" + name + "】"));
}
}
}
// 尾段步行
if (!originalSteps.isEmpty()) {
LatLonPoint lastStation = getExitPoint(originalSteps.get(originalSteps.size() - 1));
if (lastStation != null && !lastStation.equals(targetPoint)) {
String exitName = "";
BusStep last = originalSteps.get(originalSteps.size() - 1);
if (last.getExit() != null && last.getExit().getName() != null) {
exitName = last.getExit().getName();
}
String name = last.getBusLine() != null ?
last.getBusLine().getArrivalBusStation().getBusStationName() : "站点";
String desc = "从【" + name + "】下车后步行至目的地" + (exitName.isEmpty() ? "" : " (" + exitName + ")");
enhancedSteps.add(new VirtualWalkStep(lastStation, targetPoint, desc));
}
}
drawRouteOnMapEnhanced(enhancedSteps);
StepAdapter adapter = new StepAdapter(enhancedSteps);
recyclerSteps.setLayoutManager(new LinearLayoutManager(this));
recyclerSteps.setAdapter(adapter);
calculateAndShowRouteInfo(enhancedSteps, bestPath);
if (start != null) {
addStartMarker(start);
}
updateTabSelection(index);
}
// ✅ 新增:获取当前步骤的下车/出口点
private LatLonPoint getExitPoint(BusStep step) {
if (step.getBusLine() != null && step.getBusLine().getArrivalBusStation() != null)
return step.getBusLine().getArrivalBusStation().getLatLonPoint();
if (step.getExit() != null) return step.getExit().getLatLonPoint();
if (step.getRailway() != null) return step.getRailway().getArrivalstop().getLatLonPoint();
return null;
}
// ✅ 新增:获取下一段的上车/入口点
private LatLonPoint getEntrancePoint(BusStep step) {
if (step.getBusLine() != null && step.getBusLine().getDepartureBusStation() != null)
return step.getBusLine().getDepartureBusStation().getLatLonPoint();
if (step.getEntrance() != null) return step.getEntrance().getLatLonPoint();
if (step.getRailway() != null) return step.getRailway().getDeparturestop().getLatLonPoint();
return null;
}
private void updateTabSelection(int selectedIndex) {
TextView[] tabs = {tabFastest, tabTransfer, tabWalk};
int[] colors = {0xFFB2EBF2, 0xFFFFFFFF};
for (int i = 0; i < 3; i++) {
tabs[i].setBackgroundColor(i == selectedIndex ? colors[0] : colors[1]);
}
}
private void drawRouteOnMapEnhanced(List<Object> steps) {
aMap.clear();
List<LatLng> allPoints = new ArrayList<>();
for (Object stepObj : steps) {
if (stepObj instanceof BusStep) {
BusStep step = (BusStep) stepObj;
if (step.getBusLine() != null && step.getBusLine().getPolyline() != null) {
for (LatLonPoint point : step.getBusLine().getPolyline()) {
allPoints.add(new LatLng(point.getLatitude(), point.getLongitude()));
}
} else if (step.getWalk() != null && step.getWalk().getPolyline() != null) {
for (LatLonPoint point : step.getWalk().getPolyline()) {
allPoints.add(new LatLng(point.getLatitude(), point.getLongitude()));
}
} else {
if (step.getEntrance() != null) {
LatLonPoint p = step.getEntrance().getLatLonPoint();
allPoints.add(new LatLng(p.getLatitude(), p.getLongitude()));
}
if (step.getExit() != null) {
LatLonPoint p = step.getExit().getLatLonPoint();
allPoints.add(new LatLng(p.getLatitude(), p.getLongitude()));
}
}
} else if (stepObj instanceof VirtualWalkStep) {
VirtualWalkStep vStep = (VirtualWalkStep) stepObj;
allPoints.add(new LatLng(vStep.from.getLatitude(), vStep.from.getLongitude()));
allPoints.add(new LatLng(vStep.to.getLatitude(), vStep.to.getLongitude()));
}
}
if (!allPoints.isEmpty()) {
PolylineOptions options = new PolylineOptions()
.addAll(allPoints)
.color(0xFF4A90E2)
.width(12f);
aMap.addPolyline(options);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
for (LatLng point : allPoints) {
builder.include(point);
}
aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 100));
} else {
tvRouteInfo.setText("路线数据为空");
}
}
// ✅ 计算并显示完整信息(时间、票价、步行距离、换乘次数)
private void calculateAndShowRouteInfo(List<Object> steps, BusPath originalPath) {
long totalDuration = 0;
double totalWalkDistance = 0;
int busRideCount = 0;
for (Object obj : steps) {
if (obj instanceof BusStep) {
BusStep step = (BusStep) obj;
if (step.getBusLine() != null && step.getBusLine().getDuration() > 0) {
totalDuration += step.getBusLine().getDuration();
busRideCount++;
} else if (step.getWalk() != null) {
totalDuration += step.getWalk().getDuration();
totalWalkDistance += step.getWalk().getDistance();
} else if (step.getRailway() != null) {
totalDuration += Long.parseLong(step.getRailway().getTime());
busRideCount++;
}
} else if (obj instanceof VirtualWalkStep) {
VirtualWalkStep v = (VirtualWalkStep) obj;
double dist = AMapUtils.calculateLineDistance(
new LatLng(v.from.getLatitude(), v.from.getLongitude()),
new LatLng(v.to.getLatitude(), v.to.getLongitude())
);
totalWalkDistance += dist;
totalDuration += (dist / 80) * 60; // 步行速度约 80m/min
}
}
int transferNum = Math.max(0, busRideCount - 1);
double cost = originalPath.getCost();
String info = String.format(
"⏱️ %d分钟 | 💰 ¥%.2f | 🚶 %d米 | 🚌 %d次换乘",
(int)(totalDuration / 60),
cost,
(int)totalWalkDistance,
transferNum
);
tvRouteInfo.setText(info);
tvRouteInfo.setVisibility(View.VISIBLE); // 确保可见
}
// ✅ 【关键修复】不再隐藏 tvRouteInfo
private void checkAllResultsAndDisplay() {
if (resultCount >= 3) {
runOnUiThread(() -> {
for (int i = 0; i < 3; i++) {
if (routePaths[i] != null) {
displayRoute(i);
return;
}
}
tvRouteInfo.setText("未找到可用路线");
Toast.makeText(RoutePlanActivity.this, "抱歉,未找到可用的公交路线", Toast.LENGTH_LONG).show();
});
}
}
@Override
public boolean onSupportNavigateUp() {
getOnBackPressedDispatcher().onBackPressed();
return true;
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
if (locationClient != null) {
locationClient.onDestroy();
}
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
}