diff --git a/app/src/main/java/com/navinfo/outdoor/activity/AutoTakePictureActivity.java b/app/src/main/java/com/navinfo/outdoor/activity/AutoTakePictureActivity.java index 342ba3a..a4d7167 100644 --- a/app/src/main/java/com/navinfo/outdoor/activity/AutoTakePictureActivity.java +++ b/app/src/main/java/com/navinfo/outdoor/activity/AutoTakePictureActivity.java @@ -71,6 +71,7 @@ import com.navinfo.outdoor.util.Geohash; import com.navinfo.outdoor.util.GeometryTools; import com.navinfo.outdoor.util.Gps; import com.navinfo.outdoor.util.MyTecentLocationSource; +import com.navinfo.outdoor.util.NaviUtils; import com.navinfo.outdoor.util.PreserveUtils; import com.navinfo.outdoor.util.SystemTTS; import com.navinfo.outdoor.util.TencentMarkerUtils; @@ -87,6 +88,12 @@ import com.otaliastudios.cameraview.size.AspectRatio; import com.otaliastudios.cameraview.size.SizeSelector; import com.otaliastudios.cameraview.size.SizeSelectors; import com.tencent.map.geolocation.TencentLocation; +import com.tencent.map.navi.TencentNaviManager; +import com.tencent.map.navi.TencentRouteSearchCallback; +import com.tencent.map.navi.car.TencentCarNaviManager; +import com.tencent.map.navi.data.CalcRouteResult; +import com.tencent.map.navi.data.NaviPoi; +import com.tencent.map.navi.data.RouteData; import com.tencent.tencentmap.mapsdk.maps.CameraUpdate; import com.tencent.tencentmap.mapsdk.maps.CameraUpdateFactory; import com.tencent.tencentmap.mapsdk.maps.TencentMap; @@ -103,6 +110,7 @@ import com.tencent.tencentmap.mapsdk.maps.model.MyLocationStyle; import com.tencent.tencentmap.mapsdk.maps.model.Polyline; import com.tencent.tencentmap.mapsdk.maps.model.PolylineOptions; import com.tencent.tencentmap.mapsdk.maps.model.TencentMapGestureListener; +import com.umeng.commonsdk.debug.UMLogCommon; import com.umeng.commonsdk.internal.crash.UMCrashManager; import com.umeng.umcrash.UMCrash; import org.locationtech.jts.algorithm.Angle; @@ -137,6 +145,7 @@ import java.util.Objects; import java.util.Optional; import java.util.Timer; import java.util.TimerTask; +import java.util.function.Predicate; import java.util.stream.Collectors; import io.reactivex.BackpressureStrategy; @@ -203,6 +212,7 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic private ImageView imgViewSettingHook; // 调起隐藏设置的按钮 private TencentLocation oldCurrentLocation = null; private MediaPlayer mediaPlayer; + private ImageView imgNaviDistance; // 自动规划到距离最近的数据开关 @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -252,6 +262,7 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic ivPicVideoImage = findViewById(R.id.iv_pic_video); btnClearMatch = findViewById(R.id.clear_all_match_data); btnStopPicture = findViewById(R.id.btn_stop_picture); + imgNaviDistance = findViewById(R.id.img_navi_distance); //获取地图 tencentMap = tvMapView.getMap(); @@ -410,6 +421,13 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic lastClickTime = System.currentTimeMillis(); } }); + + imgNaviDistance.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + imgNaviDistance.setSelected(!imgNaviDistance.isSelected()); + } + }); } private long lastClickTime = 0; private int settingHookClickCount = 1; @@ -774,6 +792,8 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic // 语音提示用户 mediaPlayer.start(); systemTTS.playText("拍摄完成"); + // 此时自动规划距离最近的任务路径 + } } @@ -808,6 +828,102 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic } } + /** + * 导航到最近的POIEntity + * */ + @RequiresApi(api = Build.VERSION_CODES.N) + private void navi2NearestPoiEntity() { + if (removables == null || removables.isEmpty()) { + SystemTTS.getInstance(this).playText("附近当前没有可匹配的任务"); + return; + } + Geometry currentGeometry = GeometryTools.createGeometry(new double[]{Constant.currentLocation.getLongitude(), Constant.currentLocation.getLatitude()}); + Removable minRemoveable = removables.stream().filter(new Predicate() { + @Override + public boolean test(Removable removable) { + if (removable instanceof Marker) { + return true; + } + return false; + } + }).min((removable, t1) -> { + Marker marker1 = (Marker) removable; + Marker marker2 = (Marker) t1; + // 判断距离用户当前位置的距离 + JobSearchBean.BodyBean.ListBean bean1 = (JobSearchBean.BodyBean.ListBean) marker1.getTag(); + JobSearchBean.BodyBean.ListBean bean2 = (JobSearchBean.BodyBean.ListBean) marker2.getTag(); + // 转换geo + Geometry geometry1 = GeometryTools.createGeometry(Geohash.getInstance().decode(bean1.getGeo())); + Geometry geometry2 = GeometryTools.createGeometry(Geohash.getInstance().decode(bean2.getGeo())); + if (currentGeometry.distance(geometry1) arrayList) { + NaviUtils.getInstance().addRoutes(arrayList, tencentMap); + NaviUtils.getInstance().zoomToRoute(arrayList.get(0), tencentMap); + if (tencentNaviManager!=null) { + if (Constant.currentNaviType == Constant.NAV_TYPE.CAR) { + ((TencentCarNaviManager)tencentNaviManager).startNavi(0); + } else if (Constant.currentNaviType == Constant.NAV_TYPE.RIDE) { + + } else { + + } + } + } + + @Override + public void onCalcRouteSuccess(CalcRouteResult calcRouteResult) { + + } + + @Override + public void onCalcRouteFailure(CalcRouteResult calcRouteResult) { + + } + }; + /** * 初始化领取任务的管理栈 * */ diff --git a/app/src/main/java/com/navinfo/outdoor/api/Constant.java b/app/src/main/java/com/navinfo/outdoor/api/Constant.java index 95aa557..b950c14 100644 --- a/app/src/main/java/com/navinfo/outdoor/api/Constant.java +++ b/app/src/main/java/com/navinfo/outdoor/api/Constant.java @@ -274,4 +274,5 @@ public class Constant { } public static NAV_TYPE currentNaviType; // 当前的导航方式 + public static boolean NAV_NEAREST_POI = false; } diff --git a/app/src/main/java/com/navinfo/outdoor/fragment/GatherGetFragment.java b/app/src/main/java/com/navinfo/outdoor/fragment/GatherGetFragment.java index af8f52e..5c75fa0 100644 --- a/app/src/main/java/com/navinfo/outdoor/fragment/GatherGetFragment.java +++ b/app/src/main/java/com/navinfo/outdoor/fragment/GatherGetFragment.java @@ -204,45 +204,18 @@ public class GatherGetFragment extends BaseFragment implements View.OnClickListe public void selectNaviType(Constant.NAV_TYPE nav_type) { // 显示导航类型选择的对话框 Constant.currentNaviType = nav_type; - startNav(); + NaviUtils.getInstance().startNav(getActivity(), new LatLng(Constant.currentLocation.getLatitude(), Constant.currentLocation.getLongitude()), new LatLng(Double.parseDouble(poiEntity.getY()), Double.parseDouble(poiEntity.getX()))); } }); } else { // 已选择导航方式 - startNav(); + NaviUtils.getInstance().startNav(getActivity(), new LatLng(Constant.currentLocation.getLatitude(), Constant.currentLocation.getLongitude()), new LatLng(Double.parseDouble(poiEntity.getY()), Double.parseDouble(poiEntity.getX()))); } } }); } } - /** - * 开始路径规划 - * */ - private void startNav() { - if (Constant.currentLocation == null) { - ToastUtils.Message(getActivity(), "无法获取当前位置,请检查是否授权应用获取位置权限!"); - return; - } - if (poiEntity == null || poiEntity.getX() == null || poiEntity.getY() == null) { - ToastUtils.Message(getActivity(), "无法获取当前数据的位置,请重新打开此数据尝试!"); - return; - } - // 跳转到指定的Activity - Class toClass = null; - if (Constant.currentNaviType == Constant.NAV_TYPE.CAR) { - toClass = NaviCarActivity.class; - } else if (Constant.currentNaviType == Constant.NAV_TYPE.RIDE) { - toClass = NaviRideActivity.class; - } else { - toClass = NaviWalkActivity.class; - } - Intent naviIntent = new Intent(getActivity(), toClass); - // 使用当前数据起点作为导航的终点,规划路径 - naviIntent.putExtra("start", new LatLng(Constant.currentLocation.getLatitude(), Constant.currentLocation.getLongitude())); - naviIntent.putExtra("end", new LatLng(Double.parseDouble(poiEntity.getY()), Double.parseDouble(poiEntity.getX()))); - getActivity().startActivity(naviIntent); - } /** * diff --git a/app/src/main/java/com/navinfo/outdoor/fragment/TreasureFragment.java b/app/src/main/java/com/navinfo/outdoor/fragment/TreasureFragment.java index 17ba24b..d23ddce 100644 --- a/app/src/main/java/com/navinfo/outdoor/fragment/TreasureFragment.java +++ b/app/src/main/java/com/navinfo/outdoor/fragment/TreasureFragment.java @@ -84,6 +84,7 @@ import com.navinfo.outdoor.util.MapManager; import com.navinfo.outdoor.util.MyTecentLocationSource; import com.navinfo.outdoor.util.NaviUtils; import com.navinfo.outdoor.util.NetWorkUtils; +import com.navinfo.outdoor.util.SystemTTS; import com.navinfo.outdoor.util.TencentMarkerUtils; import com.navinfo.outdoor.util.TimestampUtil; import com.navinfo.outdoor.util.ToastUtils; @@ -110,6 +111,8 @@ import com.tencent.tencentmap.mapsdk.maps.model.Polyline; import com.tencent.tencentmap.mapsdk.maps.model.PolylineOptions; import com.umeng.message.UmengNotificationClickHandler; import com.umeng.message.entity.UMessage; + +import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.MultiPoint; import org.locationtech.jts.geom.Point; @@ -123,11 +126,13 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; +import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.function.Predicate; /** * 寻宝的Fragment @@ -143,9 +148,9 @@ public class TreasureFragment extends BaseFragment implements View.OnClickListen private FrameLayout frameLayout; private GatherGetFragment gatherGetFragment; private String centerEncode; - private List removables; - private List removableScreenMarker; - private List removablesLocality; + private List removables; //存储网络数据的marker数据(线,面,点) + private List removablesLocality; // 存储本地数据的marker数据(线,面,点) + private List removableScreenMarker; // 存储屏幕数据的marker数据(线,面,点) private final int MARKER_BIG = 4; /* * bitmapDescriptor1 @@ -177,6 +182,7 @@ public class TreasureFragment extends BaseFragment implements View.OnClickListen private TextView tvTenantGaps; private TencentMarkerUtils tencentMarkerUtils; private ImageView imgAutoMatchRoad; // 自动匹配道路 + private ImageView ivNaviDistance; // 按距离自动导航 public static TreasureFragment newInstance(Bundle bundle) { TreasureFragment fragment = new TreasureFragment(); @@ -351,6 +357,79 @@ public class TreasureFragment extends BaseFragment implements View.OnClickListen // }).setFullScreen(true); } }); + ivNaviDistance = findViewById(R.id.img_navi_distance); + + ivNaviDistance.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Constant.NAV_NEAREST_POI = !view.isSelected(); + view.setSelected(Constant.NAV_NEAREST_POI); + // 如果是被选中,则发送导航到最近POI的指令 + if (Constant.NAV_NEAREST_POI) { + SystemTTS.getInstance(getContext()).playText("开始自动规划"); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + handler.postDelayed(autoNaviRunnable, 2000); + } + } else { + SystemTTS.getInstance(getContext()).playText("停止自动规划"); + handler.removeCallbacks(autoNaviRunnable); + } + } + }); + } + + /** + * 导航到最近的POIEntity + * */ + @RequiresApi(api = Build.VERSION_CODES.N) + private void navi2NearestPoiEntity() { + if (removables == null || removables.isEmpty()) { + SystemTTS.getInstance(getContext()).playText("无法获取任务数据"); + ivNaviDistance.setSelected(false); + return; + } + Geometry currentGeometry = GeometryTools.createGeometry(new double[]{Constant.currentLocation.getLongitude(), Constant.currentLocation.getLatitude()}); + Removable minRemoveable = removables.stream().filter(new Predicate() { + @Override + public boolean test(Removable removable) { + if (removable instanceof Marker) { + return true; + } + return false; + } + }).min((removable, t1) -> { + Marker marker1 = (Marker) removable; + Marker marker2 = (Marker) t1; + // 判断距离用户当前位置的距离 + JobSearchBean.BodyBean.ListBean bean1 = (JobSearchBean.BodyBean.ListBean) marker1.getTag(); + JobSearchBean.BodyBean.ListBean bean2 = (JobSearchBean.BodyBean.ListBean) marker2.getTag(); + // 转换geo + Geometry geometry1 = GeometryTools.createGeometry(Geohash.getInstance().decode(bean1.getGeo())); + Geometry geometry2 = GeometryTools.createGeometry(Geohash.getInstance().decode(bean2.getGeo())); + if (currentGeometry.distance(geometry1)= Build.VERSION_CODES.N) { + navi2NearestPoiEntity(); + } + } + }; @Subscribe public void onEvent(Message data) { @@ -849,6 +936,13 @@ public class TreasureFragment extends BaseFragment implements View.OnClickListen removableScreenMarker.get(i).remove(); } removableScreenMarker.clear(); + + // 抽屉隐藏,如果当前自动规划按钮被选中 + if (ivNaviDistance.isSelected()) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + handler.postDelayed(autoNaviRunnable, 3000); + } + } } } else if (data.what == Constant.MAIN_BUTTON_VISITABLE) {//控制主界面各个按钮显隐状态的what值 setMainButtonVisitable((Integer) data.obj); diff --git a/app/src/main/java/com/navinfo/outdoor/util/NaviUtils.java b/app/src/main/java/com/navinfo/outdoor/util/NaviUtils.java index 39a6fa2..7072f54 100644 --- a/app/src/main/java/com/navinfo/outdoor/util/NaviUtils.java +++ b/app/src/main/java/com/navinfo/outdoor/util/NaviUtils.java @@ -2,6 +2,7 @@ package com.navinfo.outdoor.util; import android.app.Activity; import android.content.Context; +import android.content.Intent; import android.util.Log; import android.view.View; import android.widget.RadioButton; @@ -13,6 +14,9 @@ import androidx.appcompat.app.AppCompatActivity; import com.kongzue.dialog.v3.CustomDialog; import com.navinfo.outdoor.R; +import com.navinfo.outdoor.activity.NaviCarActivity; +import com.navinfo.outdoor.activity.NaviRideActivity; +import com.navinfo.outdoor.activity.NaviWalkActivity; import com.navinfo.outdoor.api.Constant; import com.tencent.map.navi.CalcRouteCallback; import com.tencent.map.navi.INaviView; @@ -437,6 +441,26 @@ public class NaviUtils { } } + /** + * 仅进行路径规划,无需导航 + * */ + public TencentNaviManager searchRouteOnly(Activity mContext, Constant.NAV_TYPE nav_type, NaviPoi start, NaviPoi end, TencentRouteSearchCallback routeSearchCallback) throws Exception { + TencentNaviManager naviManager = null; + if (nav_type == Constant.NAV_TYPE.CAR) { + naviManager = new TencentCarNaviManager(mContext); + CarRouteSearchOptions options = CarRouteSearchOptions.create(); + ((TencentCarNaviManager)naviManager).searchRoute(start, end, new ArrayList<>(), options, routeSearchCallback); + } else if (nav_type == Constant.NAV_TYPE.RIDE) { + naviManager = new TencentRideNaviManager(mContext); + RideRouteSearchOptions options = RideRouteSearchOptions.create(); + ((TencentRideNaviManager)naviManager).searchRoute(start, end, options, routeSearchCallback); + } else { + naviManager = new TencentWalkNaviManager(mContext); + ((TencentWalkNaviManager)naviManager).searchRoute(start, end, routeSearchCallback); + } + return naviManager; + } + /** * 算路回调 */ @@ -450,8 +474,8 @@ public class NaviUtils { @Override public void onRouteSearchSuccess(ArrayList arrayList) { // 添加道路Route到地图,默认选取第一条 - addRoutes(arrayList); - zoomToRoute(arrayList.get(0)); + addRoutes(arrayList, tencentMap); + zoomToRoute(arrayList.get(0), tencentMap); try { // 自动开始导航 if (Constant.currentNaviType == Constant.NAV_TYPE.CAR) { @@ -512,7 +536,7 @@ public class NaviUtils { } } - private void addRoutes(ArrayList mRouteDatas) { + public void addRoutes(ArrayList mRouteDatas, TencentMap map) { RouteData routeData = mRouteDatas.get(0); ArrayList traffics = getTrafficItemsFromList(routeData.getTrafficIndexList()); List mRoutePoints = routeData.getRoutePoints(); @@ -550,11 +574,13 @@ public class NaviUtils { .arrow(true) .colors(trafficColors, trafficColorsIndex) .zIndex(10); - - Polyline polyline = tencentMap.addPolyline(options); + if (map == null) { + map = tencentMap; + } + Polyline polyline = map.addPolyline(options); } - private void zoomToRoute(RouteData routeData) { + public void zoomToRoute(RouteData routeData, TencentMap map) { int marginLeft = mContext.getResources().getDimensionPixelSize(R.dimen.navigation_line_margin_left); int marginTop = mContext.getResources().getDimensionPixelSize(R.dimen.navigation_line_margin_top); int marginRight = mContext.getResources().getDimensionPixelSize(R.dimen.navigation_line_margin_right); @@ -563,7 +589,10 @@ public class NaviUtils { builder.include(routeData.getRoutePoints()); LatLngBounds bounds = builder.build(); - tencentMap.moveCamera(CameraUpdateFactory.newLatLngBoundsRect(bounds, marginLeft, marginRight, marginTop, marginBottom)); + if (map == null) { + map = tencentMap; + } + map.moveCamera(CameraUpdateFactory.newLatLngBoundsRect(bounds, marginLeft, marginRight, marginTop, marginBottom)); } @@ -622,6 +651,34 @@ public class NaviUtils { } } + /** + * 开始路径规划 + * */ + public void startNav(Activity mContext, LatLng startLatlng, LatLng endLatlng) { + if (Constant.currentLocation == null) { + ToastUtils.Message(mContext, "无法获取当前位置,请检查是否授权应用获取位置权限!"); + return; + } + if (startLatlng == null || endLatlng == null) { + ToastUtils.Message(mContext, "无法获取个人位置或数据位置信息,请重新打开此数据尝试!"); + return; + } + // 跳转到指定的Activity + Class toClass = null; + if (Constant.currentNaviType == Constant.NAV_TYPE.CAR) { + toClass = NaviCarActivity.class; + } else if (Constant.currentNaviType == Constant.NAV_TYPE.RIDE) { + toClass = NaviRideActivity.class; + } else { + toClass = NaviWalkActivity.class; + } + Intent naviIntent = new Intent(mContext, toClass); + // 使用当前数据起点作为导航的终点,规划路径 + naviIntent.putExtra("start", startLatlng); + naviIntent.putExtra("end", endLatlng); + mContext.startActivity(naviIntent); + } + private TencentNaviManager getNaviManager() { if (naviManager!=null) { return naviManager; diff --git a/app/src/main/res/drawable/selector_navi_distance.xml b/app/src/main/res/drawable/selector_navi_distance.xml new file mode 100644 index 0000000..576723b --- /dev/null +++ b/app/src/main/res/drawable/selector_navi_distance.xml @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_auto_take_pictures.xml b/app/src/main/res/layout/activity_auto_take_pictures.xml index db870fa..17093ac 100644 --- a/app/src/main/res/layout/activity_auto_take_pictures.xml +++ b/app/src/main/res/layout/activity_auto_take_pictures.xml @@ -129,7 +129,7 @@ android:id="@+id/btn_switch" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="20dp" + android:layout_marginTop="25dp" android:layout_marginEnd="25dp" android:src="@mipmap/switcher" android:padding="@dimen/default_widget_padding" @@ -158,6 +158,18 @@ app:layout_constraintTop_toBottomOf="@id/btn_setting" app:layout_constraintRight_toRightOf="parent"> + + + + + android:layout_marginTop="15dp" + app:layout_constraintLeft_toLeftOf="@id/img_navi_distance" + app:layout_constraintTop_toBottomOf="@id/img_navi_distance"/>