From d2be63ea0859745a373452c855498bf3d24cebf4 Mon Sep 17 00:00:00 2001 From: MADAO-LUV <3335075714@qq.com> Date: Mon, 12 May 2025 20:00:31 +0800 Subject: [PATCH] Merge branch 'main' of https://github.com/MADAO-LUV/ManGoWalk --- app/proguard-rules.pro | 3 + app/src/main/AndroidManifest.xml | 12 ++ .../com/example/mangowalking/GuideMap.java | 171 +++++++++++++++--- .../example/mangowalking/RouteActivity.java | 17 +- .../mangowalking/utils/AmapTTSController.java | 170 +++++++++++++++++ .../example/mangowalking/utils/IBuilder.java | 6 + .../main/res/layout/activity_guide_map.xml | 11 +- 7 files changed, 355 insertions(+), 35 deletions(-) create mode 100644 app/src/main/java/com/example/mangowalking/utils/AmapTTSController.java create mode 100644 app/src/main/java/com/example/mangowalking/utils/IBuilder.java diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index cf50408..540c3d4 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -20,3 +20,6 @@ # hide the original source file name. #-renamesourcefileattribute SourceFile +-keep class com.amap.api.navi.**{*;} +-keep class com.alibaba.idst.nui.* {*;} +-keep class com.google.**{*;} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 880858e..f4778bb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,6 +24,8 @@ + + @@ -48,6 +50,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/java/com/example/mangowalking/GuideMap.java b/app/src/main/java/com/example/mangowalking/GuideMap.java index a3a22de..0037dc6 100644 --- a/app/src/main/java/com/example/mangowalking/GuideMap.java +++ b/app/src/main/java/com/example/mangowalking/GuideMap.java @@ -1,29 +1,37 @@ package com.example.mangowalking; import android.annotation.SuppressLint; -import android.content.pm.PackageManager; +import android.content.Intent; import android.os.Bundle; import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; -import androidx.core.content.ContextCompat; import com.amap.api.location.AMapLocationClient; import com.amap.api.location.AMapLocationClientOption; import com.amap.api.location.AMapLocationListener; import com.amap.api.maps.AMapException; +import com.amap.api.maps.model.LatLng; +import com.amap.api.maps.model.Poi; 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.AmapNaviPage; +import com.amap.api.navi.AmapNaviParams; +import com.amap.api.navi.AmapNaviType; +import com.amap.api.navi.AmapPageType; import com.amap.api.navi.ParallelRoadListener; import com.amap.api.navi.enums.AMapNaviParallelRoadStatus; import com.amap.api.navi.enums.NaviType; import com.amap.api.navi.enums.TransportType; +import com.amap.api.navi.enums.TravelStrategy; import com.amap.api.navi.model.*; import com.example.mangowalking.utils.TTSController; -import com.google.android.filament.View; import java.util.ArrayList; @@ -32,38 +40,109 @@ import java.util.List; public class GuideMap extends AppCompatActivity implements AMapNaviListener, AMapNaviViewListener, ParallelRoadListener { private static final String TAG = "GuideMap"; private AMapNaviView mNaviView; // 对应DEMO mAMapNaviView; - private AMapNavi mNavi; // mAMapNavi; + private AMapNavi mAMapNavi; // mAMapNavi; protected TTSController mTtsManager; - private NaviLatLng mStartPoint; // 起点 - private NaviLatLng mEndPoint; // 终点 + + //终点坐标 + private double endLat,endLon; //终点坐标 + private List mWayPoints = new ArrayList<>(); // 途经点 - protected final List sList = new ArrayList(); - protected final List eList = new ArrayList(); - protected List mWayPointList = new ArrayList(); //与定位相关 private AMapLocationClient mapLocationClient; private AMapLocationClientOption mLocationOption; - private boolean isAutoStartLocation = false; + + private AmapNaviType currentNaviType = AmapNaviType.WALK; + private NaviLatLng end; + private TextView tvRouteInfo; + private Button btnStartNavi; + private Button btnSwitchMode; @SuppressLint("MissingInflatedId") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); -// mNavi.setIsNaviTravelView(true); - setContentView(R.layout.activity_guide_map); - // 1. 初始化导航组件 - mNaviView = findViewById(R.id.naviView); - mNaviView.onCreate(savedInstanceState); + + // 获取传入的终点经纬度 + Intent intent = getIntent(); + endLat = intent.getDoubleExtra("end_lat", 0); + endLon = intent.getDoubleExtra("end_lon", 0); + Log.d("GuideMap", "收到终点坐标: lat=" + endLat + ", lon=" + endLon); + Log.d("GuideMap", "接收到坐标:" + endLat + "," + endLon); + + if (endLat < 1 || endLon < 1) { + Toast.makeText(this, "终点坐标可能异常", Toast.LENGTH_LONG).show(); + } + end = new NaviLatLng(endLat,endLon); + startNaviToDestination(currentNaviType); +// +// mNaviView = findViewById(R.id.naviView); +// mNaviView.onCreate(savedInstanceState); +// +// mTtsManager = TTSController.getInstance(getApplicationContext()); +// mTtsManager.init(); +// mTtsManager.setTTSType(TTSController.TTSType.SYSTEMTTS); +// try { +// AMapNavi.getInstance(this).calculateWalkRoute(null,end); +// } catch (AMapException e) { +// throw new RuntimeException(e); +// } + try { - mNavi = AMapNavi.getInstance(getApplicationContext()); + AMapNavi.getInstance(this).calculateWalkRoute(end); + mAMapNavi = AMapNavi.getInstance(getApplicationContext()); + mAMapNavi.setUseInnerVoice(true,false); + AMapNavi.setTtsPlaying(true); } catch (AMapException e) { throw new RuntimeException(e); } + mAMapNavi.addAMapNaviListener(mTtsManager); + mAMapNavi.playTTS("主人你好呀", false); + +// mAMapNavi.startNavi(NaviType.EMULATOR); + //以上为新添加的 不知道怎么处理 + + // try { +// mAMapNavi = AMapNavi.getInstance(getApplicationContext()); +// } catch (AMapException e) { +// throw new RuntimeException(e); +// } +// mAMapNavi.addAMapNaviListener(this); +// mAMapNavi.addAMapNaviListener(mTtsManager); +// +// // 🚩 设置为骑/步行视图(重要) +// mAMapNavi.setIsNaviTravelView(true); +// +// // 🚶 步行路线规划(起点为空)——无起点规划 +// NaviLatLng end = new NaviLatLng(endLat, endLon); +// mAMapNavi.calculateWalkRoute(end); // 或 mAMapNavi.calculateRideRoute(end); +// +// // 初始化界面控件 +// tvRouteInfo = findViewById(R.id.tvRouteInfo); +// btnStartNavi = findViewById(R.id.btnStartNavi); +// btnSwitchMode = findViewById(R.id.btnSwitchMode); +// // 切换模式按钮 +// btnSwitchMode.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View view) { +// if (currentNaviType == AmapNaviType.WALK) { +// currentNaviType = AmapNaviType.DRIVER; +// } else { +// currentNaviType = AmapNaviType.WALK; +// } +// updateRouteInfoText(); +// } +// }); +// +// // 开始导航按钮 +// btnStartNavi.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View view) { +// startNaviToDestination(currentNaviType); +// } +// }); - // 2. 设置导航监听器 - mNavi.addAMapNaviListener(this); mNaviView.setAMapNaviViewListener(new AMapNaviViewListener() { @Override public void onNaviSetting() { @@ -122,12 +201,12 @@ public class GuideMap extends AppCompatActivity implements AMapNaviListener, AMa } // 处理导航视图事件... }); - mNaviView.setNaviMode(mNaviView.NORTH_UP_MODE); - initLocation(); + // 3. 添加途经点(可选) // mWayPoints.add(new NaviLatLng(39.993706, 116.400865)); //初始化定位 // initLocation(); +// mNaviView.setNaviMode(mNaviView.NORTH_UP_MODE); } @Override public void onNaviSetting() { @@ -223,6 +302,22 @@ public class GuideMap extends AppCompatActivity implements AMapNaviListener, AMa } + private void updateRouteInfoText() { + String modeText = currentNaviType == AmapNaviType.WALK ? "步行模式" : "公交模式"; + tvRouteInfo.setText("当前导航模式:" + modeText); + } + + private void startNaviToDestination(AmapNaviType naviType) { + Poi end = new Poi("目的地", new LatLng(endLat, endLon), null); + AmapNaviParams params = new AmapNaviParams(null, null, end, naviType, AmapPageType.ROUTE); + params.setUseInnerVoice(true); + AmapNaviPage.getInstance().showRouteActivity(getApplicationContext(), params, null); + } + + + + + @Override protected void onResume() { @@ -238,14 +333,25 @@ public class GuideMap extends AppCompatActivity implements AMapNaviListener, AMa @Override protected void onDestroy() { +// super.onDestroy(); +// mNaviView.onDestroy(); +// //since 1.6.0 不再在naviview destroy的时候自动执行AMapNavi.stopNavi();请自行执行 +// if (mAMapNavi!=null){ +// mAMapNavi.stopNavi(); +// mAMapNavi.destroy(); +// } super.onDestroy(); - mNaviView.onDestroy(); - //since 1.6.0 不再在naviview destroy的时候自动执行AMapNavi.stopNavi();请自行执行 - if (mNavi!=null){ - mNavi.stopNavi(); - mNavi.destroy(); +// if(mTtsManager != null) +// { +// mTtsManager.stopSpeaking(); +// mTtsManager.destroy(); +// } + if(mAMapNavi != null) + { +// mAMapNavi.removeAMapNaviListener(mTtsManager); + mAMapNavi.stopNavi(); } - + mNaviView.onDestroy(); } @@ -257,8 +363,8 @@ public class GuideMap extends AppCompatActivity implements AMapNaviListener, AMa @Override public void onInitNaviSuccess() { //这里无需super 因为我是直接在父类上直接写 - mNavi.setTravelInfo(new AMapTravelInfo(TransportType.Walk)); - mNavi.calculateWalkRoute(new NaviLatLng(39.925846, 116.435765), new NaviLatLng(39.925846, 116.532765)); + mAMapNavi.setTravelInfo(new AMapTravelInfo(TransportType.Walk)); + mAMapNavi.calculateWalkRoute(null, end); } @Override @@ -273,7 +379,7 @@ public class GuideMap extends AppCompatActivity implements AMapNaviListener, AMa @Override public void onLocationChange(AMapNaviLocation aMapNaviLocation) { - + aMapNaviLocation.getCoord(); } @Override @@ -413,7 +519,12 @@ public class GuideMap extends AppCompatActivity implements AMapNaviListener, AMa @Override public void onCalculateRouteSuccess(AMapCalcRouteResult aMapCalcRouteResult) { - mNavi.startNavi(NaviType.GPS); + try { + AMapNavi.getInstance(this).startNavi(NaviType.GPS); + AMapNavi.getInstance(this.getApplicationContext()).setIsNaviTravelView(true); + } catch (AMapException e) { + throw new RuntimeException(e); + } } @Override diff --git a/app/src/main/java/com/example/mangowalking/RouteActivity.java b/app/src/main/java/com/example/mangowalking/RouteActivity.java index b13b679..3ff5615 100644 --- a/app/src/main/java/com/example/mangowalking/RouteActivity.java +++ b/app/src/main/java/com/example/mangowalking/RouteActivity.java @@ -201,7 +201,22 @@ public class RouteActivity extends AppCompatActivity implements //初始化出行方式 initTravelMode(); - binding.buttonmy.setOnClickListener(v->startActivity(new Intent(this,GuideMap.class))); + // 源码 ---> + //binding.buttonmy.setOnClickListener(v->startActivity(new Intent(this,GuideMap.class))); + binding.buttonmy.setOnClickListener(v -> { + // 检查终点坐标是否存在 + if (mEndPoint != null) { + Intent intent = new Intent(this, GuideMap.class); + // 将终点坐标放入Intent + intent.putExtra("end_lat", mEndPoint.getLatitude()); + intent.putExtra("end_lon", mEndPoint.getLongitude()); + Log.d("RouteActivity", "准备跳转 GuideMap,终点:" + mEndPoint.getLatitude() + "," + mEndPoint.getLongitude()); + startActivity(intent); + } else { + Toast.makeText(this, "请先选择目的地", Toast.LENGTH_SHORT).show(); + } + }); + // 新加入的 scanner = bluetoothAdapter.getBluetoothLeScanner(); //不进行权限验证 diff --git a/app/src/main/java/com/example/mangowalking/utils/AmapTTSController.java b/app/src/main/java/com/example/mangowalking/utils/AmapTTSController.java new file mode 100644 index 0000000..08962f4 --- /dev/null +++ b/app/src/main/java/com/example/mangowalking/utils/AmapTTSController.java @@ -0,0 +1,170 @@ +package com.example.mangowalking.utils; + +import static com.iflytek.cloud.SpeechSynthesizer.createSynthesizer; + +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.widget.Toast; + +import com.amap.api.navi.AMapNavi; +import com.iflytek.cloud.ErrorCode; +import com.iflytek.cloud.InitListener; +import com.iflytek.cloud.SpeechConstant; +import com.iflytek.cloud.SpeechError; +import com.iflytek.cloud.SpeechSynthesizer; +import com.iflytek.cloud.SpeechUtility; +import com.iflytek.cloud.SynthesizerListener; + +import java.util.LinkedList; + +/** + * 当前DEMO的播报方式是队列模式。其原理就是依次将需要播报的语音放入链表中,播报过程是从头开始依次往后播报。 + *

+ * 导航SDK原则上是不提供语音播报模块的,如果您觉得此种播报方式不能满足你的需求,请自行优化或改进。 + */ +public class AmapTTSController { + private final String appId = "1342cc62"; + public static AmapTTSController ttsManager; + private Context mContext; + private SpeechSynthesizer mTts; + private boolean isPlaying = false; + private LinkedList wordList = new LinkedList(); + private final int TTS_PLAY = 1; + private final int CHECK_TTS_PLAY = 2; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + switch (msg.what) { + case TTS_PLAY: + synchronized (mTts) { + if (!isPlaying && mTts != null && wordList.size() > 0) { + isPlaying = true; + String playtts = wordList.removeFirst(); + if (mTts == null) { + createSynthesizer(); + } + mTts.startSpeaking(playtts, new SynthesizerListener() { + @Override + public void onCompleted(SpeechError arg0) { + AMapNavi.setTtsPlaying(isPlaying = false); + handler.obtainMessage(1).sendToTarget(); + } + + @Override + public void onEvent(int arg0, int arg1, int arg2, Bundle arg3) { + } + + @Override + public void onBufferProgress(int arg0, int arg1, int arg2, String arg3) { + // 合成进度 + isPlaying = true; + } + + @Override + public void onSpeakBegin() { + //开始播放 + AMapNavi.setTtsPlaying(isPlaying = true); + } + + @Override + public void onSpeakPaused() { + } + + @Override + public void onSpeakProgress(int arg0, int arg1, int arg2) { + //播放进度 + isPlaying = true; + } + + @Override + public void onSpeakResumed() { + //继续播放 + isPlaying = true; + } + }); + } + } + break; + case CHECK_TTS_PLAY: + if (!isPlaying) { + handler.obtainMessage(1).sendToTarget(); + } + break; + default: + } + + } + }; + private AmapTTSController(Context context) { + mContext = context.getApplicationContext(); + SpeechUtility.createUtility(mContext, SpeechConstant.APPID + "=" + appId); + if (mTts == null) { + createSynthesizer(); + } + } + + private void createSynthesizer() { + mTts = SpeechSynthesizer.createSynthesizer(mContext, + new InitListener() { + @Override + public void onInit(int errorcode) { + if (ErrorCode.SUCCESS == errorcode) { + } else { + Toast.makeText(mContext, "语音合成初始化失败!", Toast.LENGTH_SHORT); + } + } + }); + } + + public void init() { + //设置发音人 + mTts.setParameter(SpeechConstant.VOICE_NAME, "xiaoyan"); + //设置语速,值范围:[0, 100],默认值:50 + mTts.setParameter(SpeechConstant.SPEED, "55"); + //设置音量 + mTts.setParameter(SpeechConstant.VOLUME, "tts_volume"); + //设置语调 + mTts.setParameter(SpeechConstant.PITCH, "tts_pitch"); + } + + public static AmapTTSController getInstance(Context context) { + if (ttsManager == null) { + ttsManager = new AmapTTSController(context); + } + return ttsManager; + } + + public void stopSpeaking() { + if (wordList != null) { + wordList.clear(); + } + if (mTts != null) { + mTts.stopSpeaking(); + } + isPlaying = false; + } + + public void destroy() { + if (wordList != null) { + wordList.clear(); + } + if (mTts != null) { + mTts.destroy(); + } + } + + public void onGetNavigationText(String arg1) { + if (wordList != null){ + wordList.addLast(arg1); + } + handler.obtainMessage(CHECK_TTS_PLAY).sendToTarget(); + } +}; + + + + diff --git a/app/src/main/java/com/example/mangowalking/utils/IBuilder.java b/app/src/main/java/com/example/mangowalking/utils/IBuilder.java new file mode 100644 index 0000000..b4e75e2 --- /dev/null +++ b/app/src/main/java/com/example/mangowalking/utils/IBuilder.java @@ -0,0 +1,6 @@ +package com.example.mangowalking.utils; + +public interface IBuilder { + + T build(); +} diff --git a/app/src/main/res/layout/activity_guide_map.xml b/app/src/main/res/layout/activity_guide_map.xml index 92e6a91..3680281 100644 --- a/app/src/main/res/layout/activity_guide_map.xml +++ b/app/src/main/res/layout/activity_guide_map.xml @@ -11,12 +11,14 @@ android:layout_width="match_parent" android:layout_height="match_parent" /> + + android:padding="8dp" + android:layout_gravity="top"> + android:gravity="center" /> + android:textAllCaps="false" />