优化算路

This commit is contained in:
2026-03-30 16:13:22 +08:00
parent 5843ef6e87
commit 8748a60f7f
4 changed files with 573 additions and 132 deletions

View File

@@ -40,6 +40,12 @@
android:name="com.amap.api.navi.AmapRouteActivity" android:name="com.amap.api.navi.AmapRouteActivity"
android:theme="@android:style/Theme.NoTitleBar" android:theme="@android:style/Theme.NoTitleBar"
android:configChanges="orientation|keyboardHidden|screenSize|navigation" /> android:configChanges="orientation|keyboardHidden|screenSize|navigation" />
<!--自定义导航 Activity-->
<activity
android:name="com.lnkj.ln_jq_app.NavigationActivity"
android:theme="@android:style/Theme.NoTitleBar"
android:configChanges="orientation|keyboardHidden|screenSize|navigation"
android:screenOrientation="portrait" />
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true" android:exported="true"

View File

@@ -3,7 +3,6 @@ package com.lnkj.ln_jq_app;
import android.Manifest; import android.Manifest;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Build; import android.os.Build;
import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
@@ -15,7 +14,6 @@ import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import io.flutter.embedding.android.FlutterActivity; import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine; import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
public class MainActivity extends FlutterActivity { public class MainActivity extends FlutterActivity {
@@ -39,39 +37,6 @@ public class MainActivity extends FlutterActivity {
"NativeFirstPage", "NativeFirstPage",
new NativeMapFactory(this) new NativeMapFactory(this)
); );
// 注册方法通道用于地图控制
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler((call, result) -> {
switch (call.method) {
case "requestPermissions":
requestPermissions();
result.success(null);
break;
case "onResume":
if (mapView != null) {
mapView.onResume();
}
result.success(null);
break;
case "onPause":
if (mapView != null) {
mapView.onPause();
}
result.success(null);
break;
case "onDestroy":
if (mapView != null) {
mapView.dispose();
mapView = null;
}
result.success(null);
break;
default:
result.notImplemented();
break;
}
});
} }
/** /**
@@ -133,23 +98,6 @@ public class MainActivity extends FlutterActivity {
this.mapView = mapView; this.mapView = mapView;
} }
@Override
protected void onResume() {
super.onResume();
// 注意高德SDK合规检查通过后再进行定位相关操作
// 这里仅保留地图生命周期调用权限建议在Flutter端或按需触发
if (mapView != null) {
mapView.onResume();
}
}
@Override
protected void onPause() {
super.onPause();
if (mapView != null) {
mapView.onPause();
}
}
@Override @Override
protected void onDestroy() { protected void onDestroy() {
@@ -160,13 +108,6 @@ public class MainActivity extends FlutterActivity {
} }
} }
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
if (mapView != null) {
mapView.onSaveInstanceState(outState);
}
}
@Override @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

View File

@@ -2,6 +2,7 @@ package com.lnkj.ln_jq_app;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Canvas; import android.graphics.Canvas;
@@ -35,6 +36,7 @@ import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ListView; import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
@@ -60,7 +62,6 @@ import com.amap.api.navi.AmapNaviPage;
import com.amap.api.navi.AmapNaviParams; import com.amap.api.navi.AmapNaviParams;
import com.amap.api.navi.AmapNaviType; import com.amap.api.navi.AmapNaviType;
import com.amap.api.navi.AmapPageType; import com.amap.api.navi.AmapPageType;
import com.amap.api.navi.enums.PathPlanningStrategy;
import com.amap.api.navi.model.AMapCarInfo; import com.amap.api.navi.model.AMapCarInfo;
import com.amap.api.navi.model.NaviPoi; import com.amap.api.navi.model.NaviPoi;
import com.amap.api.services.core.AMapException; import com.amap.api.services.core.AMapException;
@@ -150,6 +151,8 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
// 存储货车路线算法接口返回的数据 // 存储货车路线算法接口返回的数据
private TruckRouteData truckRouteData; private TruckRouteData truckRouteData;
//当前定位信息
private AMapLocation mLoc;
public NativeMapView(Context context, int id, Object args) { public NativeMapView(Context context, int id, Object args) {
@@ -171,6 +174,7 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
container.addView(mapView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); container.addView(mapView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
initLoadingView(context);
initData(context); initData(context);
initServices(context); initServices(context);
initOverlays(context); initOverlays(context);
@@ -194,6 +198,7 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
} }
private LinearLayout bottomContainer; private LinearLayout bottomContainer;
private void initOverlays(Context context) { private void initOverlays(Context context) {
// --- 底部主容器 (包含两个互斥显示的面板) --- // --- 底部主容器 (包含两个互斥显示的面板) ---
bottomContainer = new LinearLayout(context); bottomContainer = new LinearLayout(context);
@@ -392,6 +397,7 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
//最后调用监听函数 //最后调用监听函数
addKeyboardListener(); addKeyboardListener();
} }
private void addKeyboardListener() { private void addKeyboardListener() {
container.getViewTreeObserver().addOnGlobalLayoutListener(() -> { container.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
Rect r = new Rect(); Rect r = new Rect();
@@ -412,6 +418,7 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
} }
}); });
} }
private void updateBottomMargin(int bottomPx) { private void updateBottomMargin(int bottomPx) {
if (bottomContainer != null) { if (bottomContainer != null) {
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) bottomContainer.getLayoutParams(); FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) bottomContainer.getLayoutParams();
@@ -422,6 +429,7 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
} }
} }
} }
private LinearLayout createDetailPanel(Context context) { private LinearLayout createDetailPanel(Context context) {
LinearLayout panel = new LinearLayout(context); LinearLayout panel = new LinearLayout(context);
panel.setOrientation(LinearLayout.VERTICAL); panel.setOrientation(LinearLayout.VERTICAL);
@@ -516,12 +524,7 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
return; return;
} }
// 开始规划前隐藏输入框面板 fetchTruckRouteAlgorithm(mLoc);
searchArea.setVisibility(View.GONE);
RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(new LatLonPoint(startPoint.latitude, startPoint.longitude), new LatLonPoint(endPoint.latitude, endPoint.longitude));
RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DRIVING_SINGLE_DEFAULT, null, null, "");
routeSearch.calculateDriveRouteAsyn(query);
} }
@Override @Override
@@ -603,11 +606,10 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
} }
//确定目的地坐标和名称 //确定目的地坐标和名称
// 优先级:用户手动选择 > truckRouteData (接口返回的精准点) > endPoint (地图点击/搜索的点)
LatLng finalDestinationLatLng = null; LatLng finalDestinationLatLng = null;
String finalDestinationName = endName; String finalDestinationName = endName;
// 如果用户手动选择了目的地,直接使用用户选择的地址 // 优先级:用户手动选择 > truckRouteData (接口返回的精准点) > endPoint (地图点击/搜索的点)
if (isUserSelectedDestination && endPoint != null) { if (isUserSelectedDestination && endPoint != null) {
finalDestinationLatLng = endPoint; finalDestinationLatLng = endPoint;
finalDestinationName = endName; finalDestinationName = endName;
@@ -619,8 +621,10 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
//防止 parseDouble 崩溃 //防止 parseDouble 崩溃
if (latStr != null && !latStr.isEmpty() && lngStr != null && !lngStr.isEmpty()) { if (latStr != null && !latStr.isEmpty() && lngStr != null && !lngStr.isEmpty()) {
try { try {
finalDestinationLatLng = new LatLng(Double.parseDouble(latStr), Double.parseDouble(lngStr)); finalDestinationLatLng = new LatLng(Double.parseDouble(latStr),
if (truckRouteData.destinationSite.name != null && !truckRouteData.destinationSite.name.isEmpty()) { Double.parseDouble(lngStr));
if (truckRouteData.destinationSite.name != null &&
!truckRouteData.destinationSite.name.isEmpty()) {
finalDestinationName = truckRouteData.destinationSite.name; finalDestinationName = truckRouteData.destinationSite.name;
} }
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
@@ -640,64 +644,83 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
return; return;
} }
//构造起点和终点 POI //获取途径点
Poi start = new Poi(startName, startPoint, ""); List<NaviPoi> waysPoiIds = new ArrayList<>();
Poi end = new Poi(finalDestinationName, finalDestinationLatLng, ""); if (truckRouteData != null && truckRouteData.pathDto != null && truckRouteData.pathDto.naviList !=
null) {
//配置导航参数 for (NaviPoint np : truckRouteData.pathDto.naviList) {
AmapNaviParams params = new AmapNaviParams(start, null, end, AmapNaviType.DRIVER, AmapPageType.ROUTE); if (np.coordinate != null && !TextUtils.isEmpty(np.coordinate.latitude) &&
!TextUtils.isEmpty(np.coordinate.longitude)) {
try { try {
AMapNavi mAMapNavi = AMapNavi.getInstance(mContext); double lat = Double.parseDouble(np.coordinate.latitude);
double lng = Double.parseDouble(np.coordinate.longitude);
// 设置车辆信息 (只有在数据完整时设置) waysPoiIds.add(new NaviPoi(np.name, new LatLng(lat, lng), np.poiId));
if (truckRouteData != null && truckRouteData.truckDto != null) { } catch (Exception e) {
AMapCarInfo carInfo = new AMapCarInfo(); Log.e(TAG, "途径点坐标解析错误: " + np.name);
carInfo.setCarNumber(plateNumber); // 使用初始化时获取的车牌
carInfo.setCarType(String.valueOf(truckRouteData.truckDto.mcarType));
carInfo.setVehicleAxis(String.valueOf(truckRouteData.truckDto.mvehicleAxis));
carInfo.setVehicleHeight(truckRouteData.truckDto.mvehicleHeight);
carInfo.setVehicleLength(truckRouteData.truckDto.mvehicleLength);
carInfo.setVehicleWidth(truckRouteData.truckDto.mvehicleWidth);
carInfo.setVehicleSize(String.valueOf(truckRouteData.truckDto.mvehicleSize));
carInfo.setVehicleLoad(truckRouteData.truckDto.mvehicleLoad);
carInfo.setVehicleWeight(truckRouteData.truckDto.mvehicleWeight);
carInfo.setRestriction(truckRouteData.truckDto.isRestriction);
carInfo.setVehicleLoadSwitch(truckRouteData.truckDto.mvehicleLoadSwitch);
params.setCarInfo(carInfo);
mAMapNavi.setCarInfo(carInfo);
}
//处理途径点 (如果接口返回了 naviList)
if (truckRouteData != null && truckRouteData.pathDto != null && truckRouteData.pathDto.naviList != null) {
NaviPoi startNaviPoi = new NaviPoi(startName, startPoint, "");
NaviPoi endNaviPoi = new NaviPoi(finalDestinationName, finalDestinationLatLng, "");
List<NaviPoi> waysPoiIds = new ArrayList<>();
for (NaviPoint np : truckRouteData.pathDto.naviList) {
if (np.coordinate != null && !TextUtils.isEmpty(np.coordinate.latitude) && !TextUtils.isEmpty(np.coordinate.longitude)) {
try {
double lat = Double.parseDouble(np.coordinate.latitude);
double lng = Double.parseDouble(np.coordinate.longitude);
waysPoiIds.add(new NaviPoi(np.name, new LatLng(lat, lng), np.poiId));
} catch (Exception e) {
Log.e(TAG, "途径点坐标解析错误: " + np.name);
}
} }
} }
// 如果有途径点,主动触发算路逻辑
if (!waysPoiIds.isEmpty()) {
mAMapNavi.calculateDriveRoute(startNaviPoi, endNaviPoi, waysPoiIds, PathPlanningStrategy.DRIVING_MULTIPLE_ROUTES_DEFAULT);
}
} }
} catch (Exception e) {
Log.e(TAG, "配置导航参数出错: " + e.getMessage());
} }
//车辆信息
AMapCarInfo carInfo = new AMapCarInfo();
carInfo.setCarNumber(plateNumber);
carInfo.setCarType(String.valueOf(truckRouteData.truckDto.mcarType));
carInfo.setVehicleAxis(String.valueOf(truckRouteData.truckDto.mvehicleAxis));
carInfo.setVehicleHeight(truckRouteData.truckDto.mvehicleHeight);
carInfo.setVehicleLength(truckRouteData.truckDto.mvehicleLength);
carInfo.setVehicleWidth(truckRouteData.truckDto.mvehicleWidth);
carInfo.setVehicleSize(String.valueOf(truckRouteData.truckDto.mvehicleSize));
carInfo.setVehicleLoad(truckRouteData.truckDto.mvehicleLoad);
carInfo.setVehicleWeight(truckRouteData.truckDto.mvehicleWeight);
carInfo.setRestriction(truckRouteData.truckDto.isRestriction);
carInfo.setVehicleLoadSwitch(truckRouteData.truckDto.mvehicleLoadSwitch);
//启动高德 // 检查途径点数量,决定使用哪种导航方式
AmapNaviPage.getInstance().showRouteActivity(mActivity, params, null); int wayPointsCount = waysPoiIds.size();
Log.d(TAG, "途经点数量: " + wayPointsCount);
if (wayPointsCount > 3) {
// 途经点超过3个跳转到 NavigationActivity
Intent intent = new Intent(mContext, NavigationActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 设置起点和终点 POI
NaviPoi startNaviPoi = new NaviPoi("", startPoint, "");
NaviPoi endNaviPoi = new NaviPoi("", finalDestinationLatLng, "");
intent.putExtra("startPoi", startNaviPoi);
intent.putExtra("endPoi", endNaviPoi);
// 设置车辆信息
if (truckRouteData != null && truckRouteData.truckDto != null) {
intent.putExtra("carInfo", carInfo);
}
// 设置途径点
if (!waysPoiIds.isEmpty()) {// 必须转换为 ArrayList 才能调用 putParcelableArrayListExtra
ArrayList<NaviPoi> wayPointsArrayList = new ArrayList<>(waysPoiIds);
intent.putParcelableArrayListExtra("wayPoints", wayPointsArrayList);
}
mContext.startActivity(intent);
} else {
Poi start = new Poi(startName, startPoint, "");
Poi end = new Poi(finalDestinationName, finalDestinationLatLng, "");
AmapNaviParams params = new AmapNaviParams(start, null, end, AmapNaviType.DRIVER,
AmapPageType.ROUTE);
try {
AMapNavi mAMapNavi = AMapNavi.getInstance(mContext);
// 设置车辆信息
if (truckRouteData != null && truckRouteData.truckDto != null) {
params.setCarInfo(carInfo);
mAMapNavi.setCarInfo(carInfo);
}
params.setNeedDestroyDriveManagerInstanceWhenNaviExit(true);
AmapNaviPage.getInstance().showRouteActivity(mActivity, params, null);
} catch (Exception e) {
Log.e(TAG, "配置导航参数出错: " + e.getMessage());
}
}
} }
private void initData(Context context) { private void initData(Context context) {
@@ -721,6 +744,9 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
* 获取货车路线算法信息 * 获取货车路线算法信息
*/ */
private void fetchTruckRouteAlgorithm(AMapLocation loc) { private void fetchTruckRouteAlgorithm(AMapLocation loc) {
showLoading();
if (plateNumber == null || plateNumber.isEmpty()) { if (plateNumber == null || plateNumber.isEmpty()) {
return; return;
} }
@@ -742,6 +768,7 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
@Override @Override
public void onFailure(@NonNull Call call, @NonNull IOException e) { public void onFailure(@NonNull Call call, @NonNull IOException e) {
Log.e(TAG, "fetchTruckRouteAlgorithm failed", e); Log.e(TAG, "fetchTruckRouteAlgorithm failed", e);
dismissLoading();
} }
@Override @Override
@@ -756,18 +783,78 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
JSONObject data = res.getJSONObject("data"); JSONObject data = res.getJSONObject("data");
truckRouteData = parseTruckRouteData(data); truckRouteData = parseTruckRouteData(data);
Log.d(TAG, "TruckRouteAlgorithm data loaded"); Log.d(TAG, "TruckRouteAlgorithm data loaded");
dismissLoading();
// 开始规划前隐藏输入框面板
searchArea.setVisibility(View.GONE);
RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(new LatLonPoint(startPoint.latitude, startPoint.longitude), new LatLonPoint(endPoint.latitude, endPoint.longitude));
RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DRIVING_SINGLE_DEFAULT, null, null, "");
routeSearch.calculateDriveRouteAsyn(query);
} else {
dismissLoading();
} }
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "parseTruckRouteAlgorithm error", e); Log.e(TAG, "parseTruckRouteAlgorithm error", e);
} }
} else {
dismissLoading();
} }
} }
}); });
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "fetchTruckRouteAlgorithm error", e); Log.e(TAG, "fetchTruckRouteAlgorithm error", e);
dismissLoading();
} }
} }
private ProgressBar progressBar;
private FrameLayout loadingOverlay;
private void initLoadingView(Context context) {
// 创建遮罩层 (全屏透明,拦截点击)
loadingOverlay = new FrameLayout(context);
loadingOverlay.setLayoutParams(new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
loadingOverlay.setClickable(true); // 拦截点击
loadingOverlay.setFocusable(true);
loadingOverlay.setVisibility(View.GONE); // 默认隐藏
progressBar = new ProgressBar(context, null, android.R.attr.progressBarStyleLarge);
FrameLayout.LayoutParams progressParams = new FrameLayout.LayoutParams(
dp2px(45), dp2px(45));
progressParams.gravity = Gravity.CENTER; // 居中显示
// 把进度条加到遮罩层
loadingOverlay.addView(progressBar, progressParams);
// 最后把整个遮罩层添加到主容器的最顶层
container.addView(loadingOverlay);
}
private void showLoading() {
if (mActivity == null)
return;
mActivity.runOnUiThread(() -> {
if (loadingOverlay != null) {
loadingOverlay.setVisibility(View.VISIBLE);
}
// 如果想在加载时给用户文字提示,可以动态加一个 TextView 在 ProgressBar 下方
});
}
private void dismissLoading() {
if (mActivity == null)
return;
mActivity.runOnUiThread(() -> {
if (loadingOverlay != null) {
loadingOverlay.setVisibility(View.GONE);
}
});
}
private void setupMapUi() { private void setupMapUi() {
aMap.setLocationSource(this); aMap.setLocationSource(this);
aMap.setMyLocationEnabled(true); aMap.setMyLocationEnabled(true);
@@ -829,6 +916,7 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
mlocationClient = new AMapLocationClient(mContext); mlocationClient = new AMapLocationClient(mContext);
AMapLocationClientOption option = new AMapLocationClientOption(); AMapLocationClientOption option = new AMapLocationClientOption();
mlocationClient.setLocationListener(this); mlocationClient.setLocationListener(this);
option.setNeedAddress(true);
option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
mlocationClient.setLocationOption(option); mlocationClient.setLocationOption(option);
mlocationClient.startLocation(); mlocationClient.startLocation();
@@ -840,19 +928,19 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
@Override @Override
public void onLocationChanged(AMapLocation loc) { public void onLocationChanged(AMapLocation loc) {
if (loc != null && loc.getErrorCode() == 0) { mLoc = loc;
currentLatLng = new LatLng(loc.getLatitude(), loc.getLongitude()); if (mLoc != null && mLoc.getErrorCode() == 0) {
currentLatLng = new LatLng(mLoc.getLatitude(), mLoc.getLongitude());
if (mListener != null) if (mListener != null)
mListener.onLocationChanged(loc); mListener.onLocationChanged(mLoc);
if (isFirstLocation) { if (isFirstLocation) {
isFirstLocation = false; isFirstLocation = false;
startPoint = currentLatLng; startPoint = currentLatLng;
aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 14f)); aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 14f));
getAddressByLatlng(currentLatLng); getAddressByLatlng(currentLatLng);
fetchRecommendStation(loc); fetchRecommendStation(mLoc);
fetchNearbyStations(loc); fetchNearbyStations(mLoc);
// 获取货车路线算法信息
fetchTruckRouteAlgorithm(loc);
} }
} }
} }
@@ -1234,7 +1322,6 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
private void switchMode(String mode) { private void switchMode(String mode) {
// 处理模式切换逻辑 // 处理模式切换逻辑
Toast.makeText(mContext, "切换到:" + mode, Toast.LENGTH_SHORT).show();
modeMenu.setVisibility(View.GONE); modeMenu.setVisibility(View.GONE);
} }
@@ -1252,7 +1339,7 @@ public class NativeMapView implements PlatformView, LocationSource, AMapLocation
GradientDrawable gd = new GradientDrawable(); GradientDrawable gd = new GradientDrawable();
gd.setColor(color); gd.setColor(color);
// 顺序左上x2, 右上x2, 右下x2, 左下x2 // 顺序左上x2, 右上x2, 右下x2, 左下x2
gd.setCornerRadii(new float[]{r, r, r, r, 0, 0, 0, 0}); gd.setCornerRadii(new float[]{r, r, r, r, r, r, r, r});
return gd; return gd;
} }

View File

@@ -0,0 +1,407 @@
package com.lnkj.ln_jq_app;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.Toast;
import com.amap.api.maps.AMapException;
import com.amap.api.navi.AMapNavi;
import com.amap.api.navi.AMapNaviListener;
import com.amap.api.navi.AMapNaviView;
import com.amap.api.navi.AMapNaviViewListener;
import com.amap.api.navi.AMapNaviViewOptions;
import com.amap.api.navi.enums.NaviType;
import com.amap.api.navi.enums.PathPlanningStrategy;
import com.amap.api.navi.model.AMapCalcRouteResult;
import com.amap.api.navi.model.AMapCarInfo;
import com.amap.api.navi.model.AMapLaneInfo;
import com.amap.api.navi.model.AMapModelCross;
import com.amap.api.navi.model.AMapNaviCameraInfo;
import com.amap.api.navi.model.AMapNaviCross;
import com.amap.api.navi.model.AMapNaviLocation;
import com.amap.api.navi.model.AMapNaviRouteNotifyData;
import com.amap.api.navi.model.AMapNaviTrafficFacilityInfo;
import com.amap.api.navi.model.AMapServiceAreaInfo;
import com.amap.api.navi.model.AimLessModeCongestionInfo;
import com.amap.api.navi.model.AimLessModeStat;
import com.amap.api.navi.model.NaviInfo;
import com.amap.api.navi.model.NaviPoi;
import java.util.List;
import androidx.activity.ComponentActivity;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
/**
* 导航
*/
public class NavigationActivity extends ComponentActivity implements AMapNaviListener {
private static final String TAG = "NavigationActivity";
private AMapNavi mAMapNavi;
private AMapNaviView naviView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 创建导航视图
naviView = new AMapNaviView(this);
naviView.onCreate(savedInstanceState);
naviView.setAMapNaviViewListener(new AMapNaviViewListener() {
@Override
public void onNaviSetting() {
}
@Override
public void onNaviCancel() {
finish();
}
@Override
public boolean onNaviBackClick() {
return false;
}
@Override
public void onNaviMapMode(int i) {
}
@Override
public void onNaviTurnClick() {
}
@Override
public void onNextRoadClick() {
}
@Override
public void onScanViewButtonClick() {
}
@Override
public void onLockMap(boolean b) {
}
@Override
public void onNaviViewLoaded() {
}
@Override
public void onMapTypeChanged(int i) {
}
@Override
public void onNaviViewShowMode(int i) {
}
});
AMapNaviViewOptions aMapNaviViewOptions = new AMapNaviViewOptions();
Bitmap carBitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.car);
aMapNaviViewOptions.setCarBitmap(carBitmap);
aMapNaviViewOptions.setSettingMenuEnabled(false);
naviView.setViewOptions(aMapNaviViewOptions);
// 创建 AMapNavi 实例
try {
mAMapNavi = AMapNavi.getInstance(this);
mAMapNavi.addAMapNaviListener(this);
} catch (AMapException e) {
Log.e(TAG, "初始化导航失败", e);
Toast.makeText(this, "初始化导航失败", Toast.LENGTH_SHORT).show();
finish();
return;
}
// 添加到容器
FrameLayout container = new FrameLayout(this);
container.addView(naviView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
setContentView(container);
// 获取 Intent 中的参数
processIntent(getIntent());
// 处理返回键
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
finish();
}
});
Log.d(TAG, "NavigationActivity created");
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
processIntent(intent);
}
/**
* 处理 Intent 参数并启动导航
*/
@SuppressWarnings("unchecked")
private void processIntent(Intent intent) {
if (intent == null) {
Log.w(TAG, "Intent is null");
return;
}
try {
// 获取起点、终点和途经点
NaviPoi startNaviPoi = (NaviPoi) intent.getParcelableExtra("startPoi");
NaviPoi endNaviPoi = (NaviPoi) intent.getParcelableExtra("endPoi");
List<NaviPoi> wayPoints = intent.getParcelableArrayListExtra("wayPoints");
if (wayPoints != null) {
Log.d("Navi", "获取到途径点数量: " + wayPoints.size());
}
if (startNaviPoi == null || endNaviPoi == null) {
Log.e(TAG, "Missing start or end point");
return;
}
// 设置车辆信息
AMapCarInfo carInfo = (AMapCarInfo) intent.getParcelableExtra("carInfo");
if (carInfo != null) {
mAMapNavi.setCarInfo(carInfo);
}
// 计算并启动导航
mAMapNavi.calculateDriveRoute(startNaviPoi, endNaviPoi, wayPoints, PathPlanningStrategy.DRIVING_MULTIPLE_ROUTES_DEFAULT);
Log.d(TAG, "Navigation started from: " + startNaviPoi.getName() + " - " + endNaviPoi.getName());
} catch (Exception e) {
Log.e(TAG, "Process intent error", e);
Toast.makeText(this, "导航启动失败", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onResume() {
super.onResume();
if (naviView != null) {
naviView.onResume();
}
}
@Override
protected void onPause() {
super.onPause();
if (naviView != null) {
naviView.onPause();
}
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
if (naviView != null) {
naviView.onSaveInstanceState(outState);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// 停止导航
if (mAMapNavi != null) {
mAMapNavi.stopNavi();
mAMapNavi.removeAMapNaviListener(this);
}
if (naviView != null) {
naviView.onDestroy();
}
Log.d(TAG, "NavigationActivity destroyed");
}
private int dp2px(float dp) {
float density = getResources().getDisplayMetrics().density;
return (int) (dp * density + 0.5f);
}
// ============ AMapNaviListener 回调实现 ============
@Override
public void onInitNaviFailure() {
Log.e(TAG, "onInitNaviFailure");
}
@Override
public void onInitNaviSuccess() {
Log.d(TAG, "onInitNaviSuccess");
}
@Override
public void onStartNavi(int i) {
Log.d(TAG, "onStartNavi: " + i);
}
@Override
public void onTrafficStatusUpdate() {
}
@Override
public void onLocationChange(AMapNaviLocation aMapNaviLocation) {
}
@Override
public void onGetNavigationText(int i, String s) {
}
@Override
public void onGetNavigationText(String s) {
}
@Override
public void onEndEmulatorNavi() {
}
@Override
public void onArriveDestination() {
Log.d(TAG, "onArriveDestination");
}
@Override
public void onCalculateRouteFailure(int i) {
Log.e(TAG, "onCalculateRouteFailure: " + i);
Toast.makeText(this, "路径计算失败: " + i, Toast.LENGTH_SHORT).show();
}
@Override
public void updateCameraInfo(AMapNaviCameraInfo[] aMapNaviCameraInfos) {
}
@Override
public void updateIntervalCameraInfo(AMapNaviCameraInfo aMapNaviCameraInfo, AMapNaviCameraInfo aMapNaviCameraInfo1, int i) {
}
@Override
public void onServiceAreaUpdate(AMapServiceAreaInfo[] aMapServiceAreaInfos) {
}
@Override
public void showCross(AMapNaviCross aMapNaviCross) {
}
@Override
public void hideCross() {
}
@Override
public void showModeCross(AMapModelCross aMapModelCross) {
}
@Override
public void hideModeCross() {
}
@Override
public void showLaneInfo(AMapLaneInfo[] aMapLaneInfos, byte[] bytes, byte[] bytes1) {
}
@Override
public void showLaneInfo(AMapLaneInfo aMapLaneInfo) {
}
@Override
public void hideLaneInfo() {
}
@Override
public void onCalculateRouteSuccess(int[] ints) {
Log.d(TAG, "onCalculateRouteSuccess");
if (mAMapNavi != null) {
mAMapNavi.startNavi(NaviType.GPS);
}
}
@Override
public void notifyParallelRoad(int i) {
}
@Override
public void OnUpdateTrafficFacility(AMapNaviTrafficFacilityInfo[] aMapNaviTrafficFacilityInfos) {
}
@Override
public void OnUpdateTrafficFacility(AMapNaviTrafficFacilityInfo aMapNaviTrafficFacilityInfo) {
}
@Override
public void updateAimlessModeStatistics(AimLessModeStat aimLessModeStat) {
}
@Override
public void updateAimlessModeCongestionInfo(AimLessModeCongestionInfo aimLessModeCongestionInfo) {
}
@Override
public void onPlayRing(int i) {
}
@Override
public void onCalculateRouteSuccess(AMapCalcRouteResult aMapCalcRouteResult) {
Log.d(TAG, "onCalculateRouteSuccess (result)");
if (mAMapNavi != null) {
mAMapNavi.startNavi(NaviType.GPS);
}
}
@Override
public void onCalculateRouteFailure(AMapCalcRouteResult aMapCalcRouteResult) {
Log.e(TAG, "onCalculateRouteFailure: " + aMapCalcRouteResult.getErrorCode());
Toast.makeText(this, "路径计算失败", Toast.LENGTH_SHORT).show();
}
@Override
public void onNaviRouteNotify(AMapNaviRouteNotifyData aMapNaviRouteNotifyData) {
}
@Override
public void onGpsSignalWeak(boolean b) {
}
@Override
public void onReCalculateRouteForYaw() {
Log.d(TAG, "onReCalculateRouteForYaw");
}
@Override
public void onReCalculateRouteForTrafficJam() {
}
@Override
public void onArrivedWayPoint(int i) {
}
@Override
public void onGpsOpenStatus(boolean b) {
}
@Override
public void onNaviInfoUpdate(NaviInfo naviInfo) {
}
}