diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 4fe9fa8..7f7a0b7 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -2,6 +2,9 @@ + + + diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..356aa17 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..c8397c9 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ef7fb58 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# ManGoWalk +用于存放我自己的app项目 diff --git a/app/build.gradle b/app/build.gradle index 356b2e9..0283bc8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,5 +1,6 @@ plugins { alias(libs.plugins.androidApplication) + alias(libs.plugins.jetbrainsKotlinAndroid) } android { @@ -18,6 +19,9 @@ android { //设置支持的SO库架构(开发者可以根据需要,选择一个或多个平台的so) abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86","x86_64" } + vectorDrawables { + useSupportLibrary true + } } sourceSets { @@ -41,6 +45,18 @@ android { buildFeatures { viewBinding true + compose true + } + kotlinOptions { + jvmTarget = '1.8' + } + composeOptions { + kotlinCompilerExtensionVersion '1.5.1' + } + packaging { + resources { + excludes += '/META-INF/{AL2.0,LGPL2.1}' + } } } @@ -66,11 +82,24 @@ dependencies { implementation libs.material implementation libs.activity implementation libs.constraintlayout + implementation libs.filament.android + implementation libs.lifecycle.runtime.ktx + implementation libs.activity.compose + implementation platform(libs.compose.bom) + implementation libs.ui + implementation libs.ui.graphics + implementation libs.ui.tooling.preview + implementation libs.material3 // implementtation 'cn.shanyaliux.serialport:serialport:4.2.0' // implementation 'com.amap.api:3dmap-location-search:latest.integration' // implementation 'com.amap.api:3dmap:latest.integration' -// implementation 'com.amap.api:location:6.4.9' +// implementation 'com.amap.api:location:6.4.9 + testImplementation libs.junit androidTestImplementation libs.ext.junit androidTestImplementation libs.espresso.core + androidTestImplementation platform(libs.compose.bom) + androidTestImplementation libs.ui.test.junit4 + debugImplementation libs.ui.tooling + debugImplementation libs.ui.test.manifest } \ No newline at end of file diff --git a/app/libs/AMap3DMap_10.1.201_AMapNavi_10.1.201_AMapSearch_9.7.4_AMapLocation_6.4.9_20250326.jar b/app/libs/AMap3DMap_10.1.201_AMapNavi_10.1.201_AMapSearch_9.7.4_AMapLocation_6.4.9_20250326.jar new file mode 100644 index 0000000..692af7d Binary files /dev/null and b/app/libs/AMap3DMap_10.1.201_AMapNavi_10.1.201_AMapSearch_9.7.4_AMapLocation_6.4.9_20250326.jar differ diff --git a/app/libs/AMap3DMap_10.1.201_AMapSearch_9.7.4_AMapLocation_6.4.9_20250317.jar b/app/libs/AMap3DMap_10.1.201_AMapSearch_9.7.4_AMapLocation_6.4.9_20250317.jar deleted file mode 100644 index 123b4eb..0000000 Binary files a/app/libs/AMap3DMap_10.1.201_AMapSearch_9.7.4_AMapLocation_6.4.9_20250317.jar and /dev/null differ diff --git a/app/libs/Msc.jar b/app/libs/Msc.jar new file mode 100644 index 0000000..a9f0c61 Binary files /dev/null and b/app/libs/Msc.jar differ diff --git a/app/libs/arm64-v8a/libAMapSDK_NAVI_v10_1_200.so b/app/libs/arm64-v8a/libAMapSDK_NAVI_v10_1_200.so new file mode 100644 index 0000000..2432a9c Binary files /dev/null and b/app/libs/arm64-v8a/libAMapSDK_NAVI_v10_1_200.so differ diff --git a/app/libs/arm64-v8a/libneonui_shared.so b/app/libs/arm64-v8a/libneonui_shared.so new file mode 100644 index 0000000..3098523 Binary files /dev/null and b/app/libs/arm64-v8a/libneonui_shared.so differ diff --git a/app/libs/arm64-v8a/libneonuijni_public.so b/app/libs/arm64-v8a/libneonuijni_public.so new file mode 100644 index 0000000..62d6a4b Binary files /dev/null and b/app/libs/arm64-v8a/libneonuijni_public.so differ diff --git a/app/libs/armeabi-v7a/libAMapSDK_NAVI_v10_1_200.so b/app/libs/armeabi-v7a/libAMapSDK_NAVI_v10_1_200.so new file mode 100644 index 0000000..a7a2dcd Binary files /dev/null and b/app/libs/armeabi-v7a/libAMapSDK_NAVI_v10_1_200.so differ diff --git a/app/libs/armeabi-v7a/libneonui_shared.so b/app/libs/armeabi-v7a/libneonui_shared.so new file mode 100644 index 0000000..f48bb4f Binary files /dev/null and b/app/libs/armeabi-v7a/libneonui_shared.so differ diff --git a/app/libs/armeabi-v7a/libneonuijni_public.so b/app/libs/armeabi-v7a/libneonuijni_public.so new file mode 100644 index 0000000..b3b0045 Binary files /dev/null and b/app/libs/armeabi-v7a/libneonuijni_public.so differ diff --git a/app/libs/build.properties b/app/libs/build.properties index b3b8338..a1f7b14 100644 --- a/app/libs/build.properties +++ b/app/libs/build.properties @@ -1,10 +1,9 @@ iid=11600 -sid=3528001 -bid=1350002 -version=13.08.0.10009081 -time=2025-03-17 18:00:51 +sid=3535967 +bid=1359895 +version=13.08.0.10009084 +time=2025-03-26 09:54:38 FEATURE_LOCATION=1 -FEATURE_ROUTE_OVERLAY=1 -FEATURE_MVT=1 -FEATURE_3DTiles=1 -FEATURE_GLTF=1 +FEATURE_MVT=0 +FEATURE_3DTiles=0 +FEATURE_GLTF=0 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ed80cb6..880858e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,16 +12,15 @@ + + - - - + - - + @@ -40,6 +39,9 @@ android:supportsRtl="true" android:theme="@style/Theme.ManGoWalking" tools:targetApi="31"> + @@ -49,7 +51,8 @@ + android:hardwareAccelerated="true" + android:launchMode="singleTop"> diff --git a/app/src/main/java/com/example/mangowalking/GuideMap.java b/app/src/main/java/com/example/mangowalking/GuideMap.java new file mode 100644 index 0000000..a3a22de --- /dev/null +++ b/app/src/main/java/com/example/mangowalking/GuideMap.java @@ -0,0 +1,438 @@ +package com.example.mangowalking; + +import android.annotation.SuppressLint; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.util.Log; +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.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.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.model.*; +import com.example.mangowalking.utils.TTSController; +import com.google.android.filament.View; + + +import java.util.ArrayList; +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; + + protected TTSController mTtsManager; + private NaviLatLng mStartPoint; // 起点 + private NaviLatLng mEndPoint; // 终点 + 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; + + @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); + try { + mNavi = AMapNavi.getInstance(getApplicationContext()); + } catch (AMapException e) { + throw new RuntimeException(e); + } + + // 2. 设置导航监听器 + mNavi.addAMapNaviListener(this); + mNaviView.setAMapNaviViewListener(new AMapNaviViewListener() { + @Override + public void onNaviSetting() { + + } + + @Override + public void onNaviCancel() { + + } + + @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() { + Log.d("wlx","导航页面加载成功"); + Log.d("wlx","请不要使用AMapNaviView.getMap().setOnMapLoadedListener();会overwrite导航SDK内部画线逻辑"); + } + + @Override + public void onMapTypeChanged(int i) { + + } + + @Override + public void onNaviViewShowMode(int i) { + + } + // 处理导航视图事件... + }); + mNaviView.setNaviMode(mNaviView.NORTH_UP_MODE); + initLocation(); + // 3. 添加途经点(可选) +// mWayPoints.add(new NaviLatLng(39.993706, 116.400865)); + //初始化定位 +// initLocation(); + } + @Override + public void onNaviSetting() { + + } + + @Override + public void onNaviCancel() { + + } + + @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) { + + } + + @Override + public void notifyParallelRoad(AMapNaviParallelRoadStatus aMapNaviParallelRoadStatus) { + if (aMapNaviParallelRoadStatus.getmElevatedRoadStatusFlag() == 1) { + Toast.makeText(this, "当前在高架上", Toast.LENGTH_SHORT).show(); + Log.d("wlx", "当前在高架上"); + } else if (aMapNaviParallelRoadStatus.getmElevatedRoadStatusFlag() == 2) { + Toast.makeText(this, "当前在高架下", Toast.LENGTH_SHORT).show(); + Log.d("wlx", "当前在高架下"); + } + + if (aMapNaviParallelRoadStatus.getmParallelRoadStatusFlag() == 1) { + Toast.makeText(this, "当前在主路", Toast.LENGTH_SHORT).show(); + Log.d("wlx", "当前在主路"); + } else if (aMapNaviParallelRoadStatus.getmParallelRoadStatusFlag() == 2) { + Toast.makeText(this, "当前在辅路", Toast.LENGTH_SHORT).show(); + Log.d("wlx", "当前在辅路"); + } + } + + public enum NaviMode {WALK,BUS}; + private NaviMode currentNaviMode = NaviMode.WALK; + + + + // 初始化定位配置 + private void initLocation() { + try { + mapLocationClient = new AMapLocationClient(getApplicationContext()); + mLocationOption = new AMapLocationClientOption(); + mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); + mLocationOption.setInterval(2000); + mapLocationClient.setLocationListener((AMapLocationListener) this); + mapLocationClient.setLocationOption(mLocationOption); + } catch (Exception e) { + throw new RuntimeException(e); + } + + } + + + @Override + protected void onResume() { + super.onResume(); + mNaviView.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + mNaviView.onPause(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mNaviView.onDestroy(); + //since 1.6.0 不再在naviview destroy的时候自动执行AMapNavi.stopNavi();请自行执行 + if (mNavi!=null){ + mNavi.stopNavi(); + mNavi.destroy(); + } + + } + + + @Override + public void onInitNaviFailure() { + Toast.makeText(this, "init navi Failed", Toast.LENGTH_SHORT).show(); + } + + @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)); + } + + @Override + public void onStartNavi(int 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() { + + } + + @Override + public void onCalculateRouteFailure(int i) { + + } + + @Override + public void onReCalculateRouteForYaw() { + + } + + @Override + public void onReCalculateRouteForTrafficJam() { + + } + + @Override + public void onArrivedWayPoint(int i) { + + } + + @Override + public void onGpsOpenStatus(boolean b) { + + } + + @Override + public void onNaviInfoUpdate(NaviInfo naviInfo) { + + } + + @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) { + + } + + @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) { + mNavi.startNavi(NaviType.GPS); + } + + @Override + public void onCalculateRouteFailure(AMapCalcRouteResult aMapCalcRouteResult) { + //路线计算失败 + Log.e("dm", "--------------------------------------------"); + Log.i("dm", "路线计算失败:错误码=" + aMapCalcRouteResult.getErrorCode() + ",Error Message= " + aMapCalcRouteResult.getErrorDescription()); + Log.i("dm", "错误码详细链接见:http://lbs.amap.com/api/android-navi-sdk/guide/tools/errorcode/"); + Log.e("dm", "--------------------------------------------"); + Toast.makeText(this, "errorInfo:" + aMapCalcRouteResult.getErrorDetail() + ", Message:" + aMapCalcRouteResult.getErrorDescription(), Toast.LENGTH_LONG).show(); + } + + @Override + public void onNaviRouteNotify(AMapNaviRouteNotifyData aMapNaviRouteNotifyData) { + + } + + @Override + public void onGpsSignalWeak(boolean b) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mangowalking/RouteActivity.java b/app/src/main/java/com/example/mangowalking/RouteActivity.java index e9e2652..b13b679 100644 --- a/app/src/main/java/com/example/mangowalking/RouteActivity.java +++ b/app/src/main/java/com/example/mangowalking/RouteActivity.java @@ -1,5 +1,6 @@ package com.example.mangowalking; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static com.example.mangowalking.utils.MapUtil.convertToLatLng; import static com.example.mangowalking.utils.MapUtil.convertToLatLonPoint; @@ -31,6 +32,7 @@ import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.ArrayAdapter; +import android.widget.Button; import android.widget.RelativeLayout; import android.widget.Spinner; import android.widget.TextView; @@ -41,6 +43,7 @@ import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; @@ -56,6 +59,7 @@ import com.amap.api.maps.model.BitmapDescriptorFactory; import com.amap.api.maps.model.LatLng; import com.amap.api.maps.model.MarkerOptions; import com.amap.api.maps.model.MyLocationStyle; +import com.amap.api.navi.AMapNavi; import com.amap.api.services.busline.BusLineItem; import com.amap.api.services.core.AMapException; import com.amap.api.services.core.LatLonPoint; @@ -151,6 +155,7 @@ public class RouteActivity extends AppCompatActivity implements private BluetoothGattCharacteristic writeCharacteristic; + private ArrayList poiListForGuideMap = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { @@ -163,6 +168,7 @@ public class RouteActivity extends AppCompatActivity implements v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); + //添加蓝牙开启 蓝牙部分是成功开启了 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Toast.makeText(RouteActivity.this, "没有蓝牙", Toast.LENGTH_SHORT).show(); @@ -182,6 +188,8 @@ public class RouteActivity extends AppCompatActivity implements @SuppressLint("MissingPermission") Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); //创建一个蓝牙启动的意图 launcher.launch(enableBtIntent);//使用launcer启动这个意图就可以了。 + + //此处可行 //初始化定位 initLocation(); @@ -193,6 +201,7 @@ public class RouteActivity extends AppCompatActivity implements //初始化出行方式 initTravelMode(); + binding.buttonmy.setOnClickListener(v->startActivity(new Intent(this,GuideMap.class))); // 新加入的 scanner = bluetoothAdapter.getBluetoothLeScanner(); //不进行权限验证 @@ -213,13 +222,31 @@ public class RouteActivity extends AppCompatActivity implements ScanFilter sn = new ScanFilter.Builder().setDeviceName("蓝牙设备的名称").setServiceUuid(ParcelUuid.fromString("0000FFE0-0000-1000-8000-00805F9B34FB")).build(); List scanFilters = new ArrayList<>(); scanFilters.add(sn); - if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) { + if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_SCAN) != PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions return; } scanner.startScan(scanFilters, new ScanSettings.Builder().build(), callback); bluetoothGatt = device.connectGatt(this, false, gattCallback); + +// Button btn_1 = findViewById(R.id.btn_ble); +// +// // 重写一个内部类 +// btn_1.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View v) { +// Log.d("RouteActivity", "点击了跳转按钮"); +//// ArrayList poiList = new ArrayList<>(); +// //这只是一个意图 +// Intent intent = new Intent(RouteActivity.this,GuideMap.class); +//// intent.putParcelableArrayListExtra("poi_list",poiList); +// startActivity(intent); +// } +// }); +// RouteActivity.java 中修改点击事件 + + } BluetoothGattCallback gattCallback = new BluetoothGattCallback() { @@ -228,7 +255,7 @@ public class RouteActivity extends AppCompatActivity implements public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { super.onConnectionStateChange(gatt, status, newState); if (newState == BluetoothProfile.STATE_CONNECTED) { - if (ActivityCompat.checkSelfPermission(RouteActivity.this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + if (ActivityCompat.checkSelfPermission(RouteActivity.this, android.Manifest.permission.BLUETOOTH_CONNECT) != PERMISSION_GRANTED) { return; } gatt.discoverServices(); @@ -300,7 +327,7 @@ public class RouteActivity extends AppCompatActivity implements // 假设写特征的 UUID 就是 READ_UUID(或者你需要再定义一个 WRITE_UUID) writeCharacteristic = service.getCharacteristic(UUID.fromString(READ_UUID)); // 如果该特征需要先 enableNotification,也可在这里设置: - if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PERMISSION_GRANTED) { return; } gatt.setCharacteristicNotification(writeCharacteristic, true); @@ -327,7 +354,7 @@ public class RouteActivity extends AppCompatActivity implements writeCharacteristic.setValue(data); // 3) 发写命令,异步执行 - if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PERMISSION_GRANTED) { return; } boolean success = bluetoothGatt.writeCharacteristic(writeCharacteristic); @@ -400,7 +427,10 @@ public class RouteActivity extends AppCompatActivity implements mLocationClient.setLocationListener(this); mLocationOption = new AMapLocationClientOption(); mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); - mLocationOption.setOnceLocationLatest(true); + // 设置定位间隔 2000ms更新一次 + mLocationOption.setInterval(2000); + // + mLocationOption.setOnceLocationLatest(false); mLocationOption.setNeedAddress(true); mLocationOption.setHttpTimeOut(20000); mLocationOption.setLocationCacheEnable(false); @@ -408,6 +438,8 @@ public class RouteActivity extends AppCompatActivity implements } } + + /** * 初始化地图 * @@ -571,7 +603,7 @@ public class RouteActivity extends AppCompatActivity implements binding.mapView.onDestroy(); if (bluetoothGatt != null) { - if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PERMISSION_GRANTED) { return; } bluetoothGatt.close(); @@ -673,6 +705,8 @@ public class RouteActivity extends AppCompatActivity implements } } } + poiListForGuideMap.clear(); + poiListForGuideMap.addAll(allPoiPoints); // // 🧪 测试打印 // for (LatLng p : poiList) { @@ -753,6 +787,8 @@ public class RouteActivity extends AppCompatActivity implements Log.d("POI_POINT", p.latitude + "," + p.longitude); } sendPoiList(poiList); + poiListForGuideMap.clear(); + poiListForGuideMap.addAll(poiList); } diff --git a/app/src/main/java/com/example/mangowalking/ui/theme/Color.kt b/app/src/main/java/com/example/mangowalking/ui/theme/Color.kt new file mode 100644 index 0000000..4a8d89c --- /dev/null +++ b/app/src/main/java/com/example/mangowalking/ui/theme/Color.kt @@ -0,0 +1,11 @@ +package com.example.mangowalking.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) \ No newline at end of file diff --git a/app/src/main/java/com/example/mangowalking/ui/theme/Theme.kt b/app/src/main/java/com/example/mangowalking/ui/theme/Theme.kt new file mode 100644 index 0000000..d70b298 --- /dev/null +++ b/app/src/main/java/com/example/mangowalking/ui/theme/Theme.kt @@ -0,0 +1,70 @@ +package com.example.mangowalking.ui.theme + +import android.app.Activity +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalView +import androidx.core.view.WindowCompat + +private val DarkColorScheme = darkColorScheme( + primary = Purple80, + secondary = PurpleGrey80, + tertiary = Pink80 +) + +private val LightColorScheme = lightColorScheme( + primary = Purple40, + secondary = PurpleGrey40, + tertiary = Pink40 + + /* Other default colors to override + background = Color(0xFFFFFBFE), + surface = Color(0xFFFFFBFE), + onPrimary = Color.White, + onSecondary = Color.White, + onTertiary = Color.White, + onBackground = Color(0xFF1C1B1F), + onSurface = Color(0xFF1C1B1F), + */ +) + +@Composable +fun ManGoWalkingTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable () -> Unit +) { + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + window.statusBarColor = colorScheme.primary.toArgb() + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme + } + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mangowalking/ui/theme/Type.kt b/app/src/main/java/com/example/mangowalking/ui/theme/Type.kt new file mode 100644 index 0000000..f533d99 --- /dev/null +++ b/app/src/main/java/com/example/mangowalking/ui/theme/Type.kt @@ -0,0 +1,34 @@ +package com.example.mangowalking.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val Typography = Typography( + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ) + /* Other default text styles to override + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) + */ +) \ No newline at end of file diff --git a/app/src/main/java/com/example/mangowalking/utils/ICallBack.java b/app/src/main/java/com/example/mangowalking/utils/ICallBack.java new file mode 100644 index 0000000..aad9379 --- /dev/null +++ b/app/src/main/java/com/example/mangowalking/utils/ICallBack.java @@ -0,0 +1,5 @@ +package com.example.mangowalking.utils; + +public interface ICallBack { + void onCompleted(int code); +} diff --git a/app/src/main/java/com/example/mangowalking/utils/IFlyTTS.java b/app/src/main/java/com/example/mangowalking/utils/IFlyTTS.java new file mode 100644 index 0000000..5575226 --- /dev/null +++ b/app/src/main/java/com/example/mangowalking/utils/IFlyTTS.java @@ -0,0 +1,170 @@ +package com.example.mangowalking.utils; + +import static com.iflytek.cloud.SpeechSynthesizer.createSynthesizer; + +import android.content.Context; +import android.media.AudioManager; +import android.os.Bundle; + +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; + +public class IFlyTTS implements TTS, SynthesizerListener, AudioManager.OnAudioFocusChangeListener { + private static IFlyTTS iflyTTS = null; + Context mContext = null; + private boolean isPlaying = false; + private AudioManager mAm = null; + ICallBack callBack = null; + + + + /** + * 请务必替换为您自己申请的ID。 + */ + private final String appId = "1342cc62"; //这个是我自己的ID + + public static IFlyTTS getInstance(Context context) { + if (iflyTTS == null) { + iflyTTS = new IFlyTTS(context); + } + return iflyTTS; + } + + private IFlyTTS(Context context) { + mContext = context; + SpeechUtility.createUtility(mContext, SpeechConstant.APPID + "=" + + appId); + createSynthesizer(); + mAm = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + } + + private void createSynthesizer() { + mTts = SpeechSynthesizer.createSynthesizer(mContext, + new InitListener() { + @Override + public void onInit(int errorcode) { + if (ErrorCode.SUCCESS == errorcode) { + //初始化成功 + } + } + }); + } + + private SpeechSynthesizer mTts; + @Override + public void onAudioFocusChange(int focusChange) { + + } + + @Override + public void init() { + if (mTts!=null){ + //设置发音人 + 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"); + //设置与其他音频软件冲突的时候是否暂停其他音频 + mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "false"); + //女生仅vixy支持多音字播报 + mTts.setParameter(SpeechConstant.VOICE_NAME, "vixy"); + } + } + + @Override + public void playText(String playText) { + //多音字处理举例 + if (playText != null && playText.contains("京藏")) { + playText = playText.replace("京藏", "京藏[=zang4]"); + } + if (playText != null && playText.length() > 0) { + int result = mAm.requestAudioFocus(this, + AudioManager.STREAM_MUSIC, + AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK); + if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { + int code = mTts.startSpeaking(playText, this); + isPlaying = true; + } + } + } + + @Override + public void stopSpeak() { + if(mTts != null){ + mTts.stopSpeaking(); + } + isPlaying = false; + } + + @Override + public void destroy() { + stopSpeak(); + if(mTts != null){ + mTts.destroy(); + } + iflyTTS = null; + } + + @Override + public boolean isPlaying() { + return isPlaying; + } + + + + @Override + public void onSpeakBegin() { + isPlaying = true; + } + + @Override + public void onBufferProgress(int i, int i1, int i2, String s) { + + } + + @Override + public void onSpeakPaused() { + isPlaying = false; + } + + @Override + public void onSpeakResumed() { + + } + + @Override + public void onSpeakProgress(int i, int i1, int i2) { + + } + + @Override + public void onCompleted(SpeechError arg0) { + isPlaying = false; + if (mAm != null) { + mAm.abandonAudioFocus(this); + } + if (callBack != null) { + if (arg0 == null) { + callBack.onCompleted(0); + } + } + } + + @Override + public void onEvent(int i, int i1, int i2, Bundle bundle) { + + } + + @Override + public void setCallback(ICallBack callback) { + callBack = callback; + } +} diff --git a/app/src/main/java/com/example/mangowalking/utils/SystemTTS.java b/app/src/main/java/com/example/mangowalking/utils/SystemTTS.java new file mode 100644 index 0000000..b9c77d3 --- /dev/null +++ b/app/src/main/java/com/example/mangowalking/utils/SystemTTS.java @@ -0,0 +1,119 @@ +package com.example.mangowalking.utils; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.speech.tts.TextToSpeech; +import android.speech.tts.UtteranceProgressListener; + +import java.util.Locale; + +@SuppressLint("NewApi") +public class SystemTTS extends UtteranceProgressListener implements TTS, TextToSpeech.OnUtteranceCompletedListener { + + private Context mContext; + private static SystemTTS singleton; + private TextToSpeech textToSpeech; // 系统语音播报类 + private boolean isSuccess = true; + + ICallBack callBack = null; + + public static SystemTTS getInstance(Context context) { + if (singleton == null) { + synchronized (SystemTTS.class) { + if (singleton == null) { + singleton = new SystemTTS(context); + } + } + } + return singleton; + } + + private SystemTTS(Context context) { + this.mContext = context.getApplicationContext(); + textToSpeech = new TextToSpeech(mContext, new TextToSpeech.OnInitListener() { + @Override + public void onInit(int i) { + //系统语音初始化成功 + if (i == TextToSpeech.SUCCESS) { + int result = textToSpeech.setLanguage(Locale.CHINA); + textToSpeech.setPitch(1.0f);// 设置音调,值越大声音越尖(女生),值越小则变成男声,1.0是常规 + textToSpeech.setSpeechRate(1.0f); + textToSpeech.setOnUtteranceProgressListener(SystemTTS.this); + textToSpeech.setOnUtteranceCompletedListener(SystemTTS.this); + if (result == TextToSpeech.LANG_MISSING_DATA + || result == TextToSpeech.LANG_NOT_SUPPORTED) { + //系统不支持中文播报 + isSuccess = false; + } + } + + } + }); + } + + @Override + public void onUtteranceCompleted(String utteranceId) { + + } + + @Override + public void onStart(String utteranceId) { + + } + + @Override + public void onDone(String utteranceId) { + + } + + @Override + public void onError(String utteranceId) { + + } + + @Override + public void init() { + + } + + @Override + public void playText(String playText) { + if(!isSuccess){ + return; + } + if(textToSpeech != null) + { + textToSpeech.speak(playText, + TextToSpeech.QUEUE_ADD,null,null); + } + } + + @Override + public void stopSpeak() { + if(textToSpeech != null) + { + textToSpeech.stop(); + } + } + + @Override + public void destroy() { + stopSpeak(); + if(textToSpeech != null) + { + textToSpeech.shutdown(); + } + singleton = null; + } + + @Override + public boolean isPlaying() { + return textToSpeech.isSpeaking(); + } + + + @Override + public void setCallback(ICallBack callback) { + callBack = callback; + } +} diff --git a/app/src/main/java/com/example/mangowalking/utils/TTS.java b/app/src/main/java/com/example/mangowalking/utils/TTS.java new file mode 100644 index 0000000..ca6c7ec --- /dev/null +++ b/app/src/main/java/com/example/mangowalking/utils/TTS.java @@ -0,0 +1,10 @@ +package com.example.mangowalking.utils; + +public interface TTS { + public void init(); + public void playText(String playText); + public void stopSpeak(); + public void destroy(); + public boolean isPlaying(); + public void setCallback(ICallBack callback); +} diff --git a/app/src/main/java/com/example/mangowalking/utils/TTSController.java b/app/src/main/java/com/example/mangowalking/utils/TTSController.java new file mode 100644 index 0000000..6228eaf --- /dev/null +++ b/app/src/main/java/com/example/mangowalking/utils/TTSController.java @@ -0,0 +1,321 @@ +package com.example.mangowalking.utils; + + +import android.content.Context; +import android.os.Message; +import android.os.Handler; + +import com.amap.api.navi.AMapNaviListener; +import com.amap.api.navi.model.AMapCalcRouteResult; +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 java.util.LinkedList; +import java.util.logging.LogRecord; + +public class TTSController implements AMapNaviListener,ICallBack{ + + @Override + public void onCompleted(int code) { + if (handler != null) { + handler.obtainMessage(1).sendToTarget(); + } + } + public static enum TTSType { + /** + * 讯飞语音 + */ + IFLYTTS, + /** + * 系统语音 + */ + SYSTEMTTS; + } + + public static TTSController ttsManager; + private Context mContext; + private TTS tts = null; + private SystemTTS systemTTS; + private IFlyTTS iflyTTS = null; + 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: + if (tts != null && wordList.size() > 0) { + tts.playText(wordList.removeFirst()); + } + break; + case CHECK_TTS_PLAY: + if (!tts.isPlaying()) { + handler.obtainMessage(1).sendToTarget(); + } + break; + default: + } + + } + }; + + public void setTTSType(TTSType type) { + if (type == TTSType.SYSTEMTTS) { + tts = systemTTS; + } else { + tts = iflyTTS; + } + tts.setCallback(this); + } + + private TTSController(Context context) { + mContext = context.getApplicationContext(); + systemTTS = SystemTTS.getInstance(mContext); + iflyTTS = IFlyTTS.getInstance(mContext); + tts = iflyTTS; + } + + public void init() { + if (systemTTS != null) { + systemTTS.init(); + } + if (iflyTTS != null) { + iflyTTS.init(); + } + tts.setCallback(this); + } + + public static TTSController getInstance(Context context) { + if (ttsManager == null) { + ttsManager = new TTSController(context); + } + return ttsManager; + } + + public void stopSpeaking() { + if (systemTTS != null) { + systemTTS.stopSpeak(); + } + if (iflyTTS != null) { + iflyTTS.stopSpeak(); + } + wordList.clear(); + } + + public void destroy() { + if (systemTTS != null) { + systemTTS.destroy(); + } + if (iflyTTS != null) { + iflyTTS.destroy(); + } + ttsManager = null; + } + + /**************************************************************************** + * 以下都是导航相关接口 + ****************************************************************************/ + + @Override + public void onInitNaviFailure() { + + } + + @Override + public void onInitNaviSuccess() { + + } + + @Override + public void onStartNavi(int 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() { + + } + + @Override + public void onCalculateRouteFailure(int i) { + + } + + @Override + public void onReCalculateRouteForYaw() { + if (wordList != null) { + wordList.addLast("路线重新规划"); + } + } + + @Override + public void onReCalculateRouteForTrafficJam() { + if (wordList != null) { + wordList.addLast("前方路线拥堵,路线重新规划"); + } + } + + @Override + public void onArrivedWayPoint(int i) { + + } + + @Override + public void onGpsOpenStatus(boolean b) { + + } + + @Override + public void onNaviInfoUpdate(NaviInfo naviInfo) { + + } + + @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) { + + } + + @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) { + if(wordList != null) + { + wordList.addLast("主人你好棒呀"); + } + } + + @Override + public void onCalculateRouteFailure(AMapCalcRouteResult aMapCalcRouteResult) { + if (wordList != null) { + wordList.addLast("路线规划失败"); + } + } + + @Override + public void onNaviRouteNotify(AMapNaviRouteNotifyData aMapNaviRouteNotifyData) { + + } + + @Override + public void onGpsSignalWeak(boolean b) { + + } + + +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_back.jpg b/app/src/main/res/drawable/ic_back.jpg new file mode 100644 index 0000000..9e981a4 Binary files /dev/null and b/app/src/main/res/drawable/ic_back.jpg differ diff --git a/app/src/main/res/drawable/ic_move.png b/app/src/main/res/drawable/ic_move.png new file mode 100644 index 0000000..b1e74f3 Binary files /dev/null and b/app/src/main/res/drawable/ic_move.png differ diff --git a/app/src/main/res/drawable/ic_setting.jpg b/app/src/main/res/drawable/ic_setting.jpg new file mode 100644 index 0000000..7c86a19 Binary files /dev/null and b/app/src/main/res/drawable/ic_setting.jpg differ diff --git a/app/src/main/res/layout/activity_guide_map.xml b/app/src/main/res/layout/activity_guide_map.xml new file mode 100644 index 0000000..92e6a91 --- /dev/null +++ b/app/src/main/res/layout/activity_guide_map.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + +