From 9d8185a958302dd5077ff4b312e7c54b3da75a89 Mon Sep 17 00:00:00 2001 From: xiaoyan Date: Wed, 10 May 2023 14:40:04 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=A2=9E=E5=8A=A0=E6=A0=B9=E6=8D=AE?= =?UTF-8?q?=E8=BD=A8=E8=BF=B9=E5=A4=8D=E5=88=B6=E5=9B=BE=E7=89=87=E7=9A=84?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../outdoor/activity/PicturesActivity.java | 247 +++++++++++++++++- .../navinfo/outdoor/http/HttpInterface.java | 4 +- .../drawable/ic_baseline_arrow_drop_up_24.xml | 5 + app/src/main/res/layout/activity_pictures.xml | 19 ++ 4 files changed, 269 insertions(+), 6 deletions(-) create mode 100644 app/src/main/res/drawable/ic_baseline_arrow_drop_up_24.xml diff --git a/app/src/main/java/com/navinfo/outdoor/activity/PicturesActivity.java b/app/src/main/java/com/navinfo/outdoor/activity/PicturesActivity.java index eeb8567..2f63c19 100644 --- a/app/src/main/java/com/navinfo/outdoor/activity/PicturesActivity.java +++ b/app/src/main/java/com/navinfo/outdoor/activity/PicturesActivity.java @@ -1,6 +1,7 @@ package com.navinfo.outdoor.activity; import android.annotation.SuppressLint; +import android.app.DatePickerDialog; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -16,6 +17,7 @@ import android.os.Handler; import android.os.Message; import android.util.DisplayMetrics; import android.util.Log; +import android.util.Pair; import android.view.View; import android.view.ViewGroup; import android.view.Window; @@ -23,6 +25,7 @@ import android.view.WindowManager; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; +import android.widget.DatePicker; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.RadioButton; @@ -43,6 +46,9 @@ import com.navinfo.outdoor.R; import com.navinfo.outdoor.api.Constant; import com.navinfo.outdoor.api.UserApplication; import com.navinfo.outdoor.base.BaseActivity; +import com.navinfo.outdoor.bean.LocationRecorder; +import com.navinfo.outdoor.room.LocationRecorderDao; +import com.navinfo.outdoor.room.PoiDatabase; import com.navinfo.outdoor.room.PoiEntity; import com.navinfo.outdoor.util.AWMp4ParserHelper; import com.navinfo.outdoor.util.BackHandlerHelper; @@ -77,6 +83,7 @@ import com.tencent.tencentmap.mapsdk.maps.UiSettings; import com.tencent.tencentmap.mapsdk.maps.interfaces.Removable; import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptor; import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptorFactory; +import com.tencent.tencentmap.mapsdk.maps.model.CamerParameter; import com.tencent.tencentmap.mapsdk.maps.model.CameraPosition; import com.tencent.tencentmap.mapsdk.maps.model.LatLng; import com.tencent.tencentmap.mapsdk.maps.model.Marker; @@ -104,12 +111,14 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.Objects; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; import static com.tencent.tencentmap.mapsdk.maps.model.MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE; import static com.tencent.tencentmap.mapsdk.maps.model.MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER; @@ -121,7 +130,7 @@ import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Action; -import io.reactivex.functions.Consumer; +import io.reactivex.functions.Predicate; import io.reactivex.schedulers.Schedulers; /** @@ -133,7 +142,7 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen private CameraView camera; private TencentMap tencentMap; private TextureMapView tvMapView; - private List removables; + private List removables, trackRemovableList; private Polyline polyline; private String finalVideoPath, geoWkt, detail; // 摄像后最终保存的文件名 private ViewGroup layerChange; // 切换地图和相机的父控件 @@ -185,6 +194,13 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen }); private boolean booleanExtra; private ImageView imgLocationType; // 切换定位方式 + private ImageView imgTrackSelectRange, imgTrackSelectConfirm; // 自助选择轨迹对应照片 + private LocationRecorderDao recorderDao; + private BitmapDescriptor trackDescriptor = BitmapDescriptorFactory + .fromResource(R.drawable.ic_baseline_arrow_drop_up_24); + private BitmapDescriptor pileDescriptor = BitmapDescriptorFactory + .fromResource(R.drawable.circle); + private long trackStartTime, trackEndTime; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -197,6 +213,7 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen setWindowBrightness(BRIGHTNESS); LocationLifeCycle.getInstance().startGPSLocation(); speedCheck = new PicturesSpeedCheck(); + recorderDao = PoiDatabase.getInstance(PicturesActivity.this).getRecorderDao(); } @Override @@ -229,6 +246,7 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen } formatter = new SimpleDateFormat("yyyyMMdd HHmmss"); removables = new ArrayList<>();//存储轨迹的marker + trackRemovableList = new ArrayList<>(); // 存储自动捕捉时的轨迹marker layerChange = findViewById(R.id.layer_change); this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); systemTTS = SystemTTS.getInstance(PicturesActivity.this); @@ -483,6 +501,53 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen }); imgLocationType = findViewById(R.id.img_location_type); imgLocationType.setOnClickListener(this::onClick); + imgTrackSelectRange = findViewById(R.id.img_track_select_point); + imgTrackSelectRange.setOnClickListener(this::onClick); + imgTrackSelectConfirm = findViewById(R.id.img_track_select_confirm); + imgTrackSelectConfirm.setOnClickListener(this::onClick); + tencentMap.setOnMarkerClickListener(new TencentMap.OnMarkerClickListener() { + @Override + public boolean onMarkerClick(Marker marker) { + if (marker.getTag() instanceof LocationRecorder) { + LocationRecorder locationRecorder = (LocationRecorder) marker.getTag(); + // 设置为起点或终点 + MessageDialog.show(PicturesActivity.this, "选择起终点", "当前点位时间为:"+ formatter.format(new Date(locationRecorder.getTime()))+",设置为起点或终点", + "起点", "取消", "终点") + .setOnOkButtonClickListener(new OnDialogButtonClickListener() { + @Override + public boolean onClick(BaseDialog baseDialog, View v) { + // 设置该点位起点 + if (trackEndTime!=0&&trackStartTime>=locationRecorder.getTime()) { + ToastUtils.Message(PicturesActivity.this, "开始时间不能在结束时间之后!"); + } else { + trackStartTime = locationRecorder.getTime(); + marker.setIcon(pileDescriptor); + } + return false; + } + }) + .setOnCancelButtonClickListener(new OnDialogButtonClickListener() { + @Override + public boolean onClick(BaseDialog baseDialog, View v) { + return false; + } + }) + .setOnOtherButtonClickListener(new OnDialogButtonClickListener() { + @Override + public boolean onClick(BaseDialog baseDialog, View v) { + if (trackStartTime!=0&&locationRecorder.getTime()<=trackStartTime) { + ToastUtils.Message(PicturesActivity.this, "结束时间不能在开始时间之前!"); + } else { + trackEndTime = locationRecorder.getTime(); + marker.setIcon(pileDescriptor); + } + return false; + } + }); + } + return false; + } + }); } class Jpg2WebpRunnable implements Runnable { @@ -725,6 +790,182 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen LocationLifeCycle.getInstance().setMainLocationFrom(LocationLifeCycle.LOCATION_FROM.TENCENT); ToastUtils.Message(PicturesActivity.this, "切换为网络定位"); } + break; + case R.id.img_track_select_point: // 切换显示自动捕捉时的轨迹信息 + imgTrackSelectRange.setSelected(!imgTrackSelectRange.isSelected()); + if (imgTrackSelectRange.isSelected()) { // 已选中 + setLocMarkerStyle(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER); + Calendar mCalendar = Calendar.getInstance(); + // 地图上显示轨迹 + // 创建 DatePickerDialog 实例 + DatePickerDialog datePickerDialog = new DatePickerDialog( + PicturesActivity.this, + new DatePickerDialog.OnDateSetListener() { + @Override + public void onDateSet(DatePicker datePicker, int year, int month, int dayOfMonth) { + // 获取到年月日,根据日期获取指定日期内的所有轨迹信息 + // 更新当前选择的日期 + mCalendar.set(Calendar.YEAR, year); + mCalendar.set(Calendar.MONTH, month); + mCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth); + + // 获取最早时间戳(当天的0点0分0秒) + mCalendar.set(Calendar.HOUR_OF_DAY, 0); + mCalendar.set(Calendar.MINUTE, 0); + mCalendar.set(Calendar.SECOND, 0); + mCalendar.set(Calendar.MILLISECOND, 0); + long earliestTimestamp = mCalendar.getTimeInMillis(); + + // 获取最晚时间戳(当天的23点59分59秒999毫秒) + mCalendar.set(Calendar.HOUR_OF_DAY, 23); + mCalendar.set(Calendar.MINUTE, 59); + mCalendar.set(Calendar.SECOND, 59); + mCalendar.set(Calendar.MILLISECOND, 999); + long latestTimestamp = mCalendar.getTimeInMillis(); + + // 根据最早和最晚时间戳,读取LocationRecorder数据表的数据 + showLoadingDialog(); + Observable.create(new ObservableOnSubscribe>() { + @Override + public void subscribe(ObservableEmitter> emitter) throws Exception { + List locationRecorderByTime = recorderDao.getLocationRecorderByTime(earliestTimestamp, latestTimestamp); + emitter.onNext(locationRecorderByTime); + emitter.onComplete(); + } + }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new io.reactivex.functions.Consumer>() { + @Override + public void accept(List locationRecorderByTime) throws Exception { + if (locationRecorderByTime==null||locationRecorderByTime.isEmpty()) { + ToastUtils.Message(PicturesActivity.this, "该时间段内没有可用的轨迹数据"); + } else { + tencentMap.animateCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition( + new LatLng(locationRecorderByTime.get(0).getTencentLocationY(), locationRecorderByTime.get(0).getTencentLocationX()), //中心点坐标,地图目标经纬度 + 17, //目标缩放级别 + 0, //目标倾斜角[0.0 ~ 45.0] (垂直地图时为0) + 0)), new TencentMap.CancelableCallback() { + @Override + public void onFinish() { + // 显示轨迹 + for (int i = 0; i < locationRecorderByTime.size()&&i<4000; i++) { + LocationRecorder locationRecorder = locationRecorderByTime.get(i); + Marker marker = tencentMap.addMarker(new MarkerOptions(new LatLng(locationRecorder.getTencentLocationY(), locationRecorder.getTencentLocationX())) +// .icon(trackDescriptor) +// .rotation((float) locationRecorder.getBearing()) +// .alpha(0.9f) +// .flat(true) + .tag(locationRecorder) +// .clockwise(false) + ); + trackRemovableList.add(marker); + } +// for (LocationRecorder locationRecorder: locationRecorderByTime) { +// Marker marker = tencentMap.addMarker(new MarkerOptions(new LatLng(locationRecorder.getTencentLocationY(), locationRecorder.getTencentLocationX())) +//// .icon(trackDescriptor) +//// .rotation((float) locationRecorder.getBearing()) +//// .alpha(0.9f) +//// .flat(true) +//// .tag(locationRecorder) +//// .clockwise(false) +// ); +// trackRemovableList.add(marker); +// } + dismissLoadingDialog(); + } + + @Override + public void onCancel() { + + } + }); //目标旋转角 0~360° (正北方为0)); + } + } + }); + } + }, + mCalendar.get(Calendar.YEAR), + mCalendar.get(Calendar.MONTH), + mCalendar.get(Calendar.DAY_OF_MONTH) + ); + // 显示 DatePickerDialog + datePickerDialog.show(); + } else { // 未选中 + setLocMarkerStyle(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE); + // 地图上隐藏轨迹 + trackRemovableList.stream().forEach(new Consumer() { + @Override + public void accept(Removable removable) { + removable.remove(); + } + }); + trackRemovableList.clear(); + trackStartTime = 0; + trackEndTime = 0; + } + break; + case R.id.img_track_select_confirm: + // 用户确认从该时间段内选择照片 + if (trackStartTime <= 0 || trackEndTime<=0 || trackStartTime >= trackEndTime) { + ToastUtils.Message(PicturesActivity.this, "起止时间选择有误,请确认!"); + return; + } + Observable.create(new ObservableOnSubscribe>() { + @Override + public void subscribe(ObservableEmitter> emitter) throws Exception { + List locationRecorderByTime = recorderDao.getLocationRecorderByTime(trackStartTime, trackEndTime); + final int[] index = {0}; + locationRecorderByTime.forEach(new Consumer() { + @Override + public void accept(LocationRecorder locationRecorder) { + if (new File(locationRecorder.getImgFileName()).exists()) { + emitter.onNext(new Pair(index[0]++, locationRecorder)); + } + } + }); + emitter.onComplete(); + } + }).subscribeOn(Schedulers.io()) + .observeOn(Schedulers.io()) + .doOnNext(new io.reactivex.functions.Consumer>() { + @Override + public void accept(Pair integerLocationRecorderPair) throws Exception { + // 转移图片文件 + File pictureFolder = new File(finalVideoPath).getParentFile(); + File originImg = new File(integerLocationRecorderPair.second.getImgFileName()); + File destFile = new File(pictureFolder.getParentFile().getAbsolutePath()+"/"+integerLocationRecorderPair.first+".jpg"); + if (!destFile.exists()) { + FileUtils.copyFile(originImg.getAbsolutePath(), destFile.getAbsolutePath()); + } + FileUtils.writeFile(paperFile.getAbsolutePath(), integerLocationRecorderPair.second.toString(formatter ,integerLocationRecorderPair.first), true); + } + }).subscribe(new Observer>() { + @Override + public void onSubscribe(Disposable d) { + showLoadingDialog(); + File pictureFolder = new File(finalVideoPath).getParentFile(); + FileUtils.deleteFile(pictureFolder.getAbsolutePath()); + if (!pictureFolder.exists()) { + pictureFolder.mkdirs(); + } + paperFile.delete(); + } + + @Override + public void onNext(Pair integerLocationRecorderPair) { + setLoadingDialogText("处理中:"+integerLocationRecorderPair.first); + } + + @Override + public void onError(Throwable e) { + dismissLoadingDialog(); + } + + @Override + public void onComplete() { + dismissLoadingDialog(); + } + }); + + break; } } @@ -1177,8 +1418,6 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen } else { latLng = new LatLng(LocationLifeCycle.getInstance().getTencentLocation().getLatitude(), LocationLifeCycle.getInstance().getTencentLocation().getLongitude()); } - BitmapDescriptor pileDescriptor = BitmapDescriptorFactory - .fromResource(R.drawable.circle); Marker marker = tencentMap.addMarker(new MarkerOptions(latLng) .icon(pileDescriptor) .alpha(0.9f) diff --git a/app/src/main/java/com/navinfo/outdoor/http/HttpInterface.java b/app/src/main/java/com/navinfo/outdoor/http/HttpInterface.java index e9a998b..9485327 100644 --- a/app/src/main/java/com/navinfo/outdoor/http/HttpInterface.java +++ b/app/src/main/java/com/navinfo/outdoor/http/HttpInterface.java @@ -2,9 +2,9 @@ package com.navinfo.outdoor.http; public class HttpInterface { // public static final String IP = "http://172.23.138.133:9999/m4";//测试接口-IP - public static final String IP0 = "http://dtxbmaps.navinfo.com/dtxb/dev/m4";//开发接口-外网 + public static final String IP = "http://dtxbmaps.navinfo.com/dtxb/dev/m4";//开发接口-外网 public static final String IP1 = "http://dtxbmaps.navinfo.com/dtxb/test/m4";//测试接口-外网 - public static final String IP = "http://dtxbmaps.navinfo.com/dtxb/m4";//正式接口 + public static final String IP0 = "http://dtxbmaps.navinfo.com/dtxb/m4";//正式接口 public static final String USER_PATH = "/user/";//我的 public static final String MSG_LIST_PATH = "/msgList/";//发现 public static final String USER_LOGIN_PATH = "/userlogin/";//登录 diff --git a/app/src/main/res/drawable/ic_baseline_arrow_drop_up_24.xml b/app/src/main/res/drawable/ic_baseline_arrow_drop_up_24.xml new file mode 100644 index 0000000..d9f55b8 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_arrow_drop_up_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_pictures.xml b/app/src/main/res/layout/activity_pictures.xml index 5445530..46b00cf 100644 --- a/app/src/main/res/layout/activity_pictures.xml +++ b/app/src/main/res/layout/activity_pictures.xml @@ -173,6 +173,25 @@ android:layout_marginTop="@dimen/default_widget_padding" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_setting"> + + +