diff --git a/app/build.gradle b/app/build.gradle
index 4d4059c..4134a89 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,11 +1,16 @@
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-kapt'
-apply plugin: 'kotlin-android-extensions'
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'kotlin-kapt'
+}
+//apply plugin: 'com.android.application'
+//apply plugin: 'kotlin-android'
+//apply plugin: 'kotlin-kapt'
+//apply plugin: 'kotlin-android-extensions'
android {
- compileSdkVersion 32
- buildToolsVersion '29.0.2'
+ compileSdkVersion 31
+// buildToolsVersion '29.0.2'
//ndkVersion '23.0.7123448'
defaultConfig {
@@ -53,6 +58,9 @@ android {
pickFirst 'lib/x86_64/libc++_shared.so'
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
}
+ buildFeatures {
+ viewBinding true
+ }
}
//efs {
// //是否对启动过程进程插桩的开关,如果使用自动集成监控则必须开启
@@ -96,7 +104,6 @@ dependencies {
implementation 'com.gyf.immersionbar:immersionbar:3.0.0'
implementation 'com.gyf.immersionbar:immersionbar-components:3.0.0'
-
//网络框架
implementation 'com.lzy.net:okgo:3.0.4'
implementation 'com.lzy.net:okrx2:2.0.2'
@@ -123,6 +130,8 @@ dependencies {
implementation 'com.github.bumptech.glide:glide:4.8.0'
//弹窗 https://github.com/kongzue/DialogV3
implementation 'com.kongzue.dialog_v3x:dialog:3.2.4'
+ implementation "com.kongzue.dialogx:DialogX:0.0.47"
+ implementation "com.kongzue.dialogx.style:DialogXMIUIStyle:0.0.47"
//xRecyclerview下拉刷新控件
implementation project(':xrecyclerview')
//拍照功能 https://github.com/natario1/CameraView
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 36b06e9..b9295b7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -145,8 +145,13 @@
+
+
+
trackLocRemovables/*用户轨迹图标marker*/;
+ private boolean isMapSlide = false; // 地图是否为靠在侧边的小图模式
+ private ImageView ivZoomAdd/*zoom放大*/, ivZoomDel/*zoom缩小*/, ivLocation/*定位按钮*/,
+ ivPicRoadImage/*道路拍摄水平线*/, ivPicVideoImage/*视频拍摄水平线*/;
+ private View layerMapController;
+ private ImageView btnSwitch; // 切换地图大小的按钮
+ private ViewGroup layerChange; // 切换地图和相机的父控件
+ private BitmapDescriptor pileDescriptor = BitmapDescriptorFactory
+ .fromResource(R.drawable.circle);
+ private TencentMarkerUtils tencentMarkerUtils;
+ private List removables; // 地图上渲染的网络获取的道路任务
+ private List removablesLocality; // 地图上渲染的本地道路任务
+ private HashMap> removableHashMap;
+ private List roadLinkEntityList/*请求到的待匹配道路数据*/, roadMatchEntityList/*已匹配起始点的道路数据*/;
+ private int satelliteCount; // 卫星颗数
+ private static double MATCH_START_BUFFER_DISTANCE=50e-5; // 匹配起点用到的buffer距离,此处5米使用简易判断
+ private static double MATCH_BUFFER_DISTANCE=30e-5; // 匹配途经点用到的buffer距离,此处5米使用简易判断
+ private static float /*UNMATCH_GIVE_UP_DISTANCE_BUFFER = 0.2f*//*放弃的距离匹配阈值*//*, */MATCH_CONFIRM_FINISH_BUFFER=0.75f/*完全匹配的距离阈值*/;
+ private static int /*UNMATCH_BUFFER_START_BUFFER = 5*//*匹配开始后连续未匹配的个数*//*,*/ UNMATCH_BUFFER_MIDDLE_BUFFER = 20/*匹配过程中连续未匹配的个数*/;
+ // private static float UNMATCH_COUNT_BUFFER = UNMATCH_GIVE_UP_DISTANCE_BUFFER/(1-UNMATCH_GIVE_UP_DISTANCE_BUFFER);
+ private final String tmpPicFoldPath = Constant.PICTURE_FOLDER+"/tmp";
+ private LocationRecorderDao recorderDao;
+ private PoiDao poiDao;
+ private SimpleDateFormat picFormatter = new SimpleDateFormat("yyyyMMdd HHmmss");
+ private Button btnClearMatch, btnStopPicture;
+ private Point lastPositionPoint; // 最近一次的定位,用来过滤距离较近的点位
+ private static int BRIGHTNESS=40, FRAMENESS=30;
+ private Button btnSetting;
+ private Switch locationSwitch;
+ private boolean locationEnable=true;
+ private ImageView imgViewSettingHook; // 调起隐藏设置的按钮
+ private Point oldCurrentLocation = null; // 记录上一次的位置信息
+ private MediaPlayer mediaPlayer;
+ private ImageView imgNaviDistance/*自动规划到距离最近的数据开关*/, imgRoadDirection; // 道路方向匹配开关
+ private Polyline currentNaviLine; // 当前界面上正显示的导航路径线,重绘路径时需要清除此前已绘制的路径
+ private boolean startMatchEnableDirection = true; // 是否启用方向匹配起点
+ private Logger logger;
+ private ImageView imgLocationType;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ SharedPreferences sharedPreferences = getSharedPreferences("pic", Context.MODE_PRIVATE);
+ BRIGHTNESS = sharedPreferences.getInt("brightness", 40);
+ FRAMENESS = sharedPreferences.getInt("framness", 30);
+
+ // 设置当前界面亮度为40%
+ setWindowBrightness(BRIGHTNESS);
+ // 初始化提示音播放器
+ mediaPlayer=MediaPlayer.create(this, R.raw.ding);
+ // 启动GPS定位
+ LocationLifeCycle.getInstance().startGPSLocation();
+ }
+
+ @Override
+ protected int getLayout() {
+ EventBus.getDefault().register(this);
+ return R.layout.activity_auto_take_pictures;
+ }
+
+ @SuppressLint("SimpleDateFormat")
+ @Override
+ protected void initView() {
+ super.initView();
+ if (!EventBus.getDefault().isRegistered(this)) {
+ EventBus.getDefault().register(this);
+ }
+
+ layerChange = findViewById(R.id.layer_change);
+ systemTTS = SystemTTS.getInstance(AutoTakePicture4PoiVideoActivity.this);
+ tvMapView = findViewById(R.id.text_map_view);
+ tvMapView.setOnClickListener(this);
+ ivZoomAdd = findViewById(R.id.iv_zoom_add);
+ ivZoomAdd.setOnClickListener(this);
+ layerMapController = findViewById(R.id.layer_map_controller);
+ ivZoomDel = findViewById(R.id.iv_zoom_del);
+ ivZoomDel.setOnClickListener(this);
+ ivLocation = findViewById(R.id.iv_location);
+ ivLocation.setOnClickListener(this);
+ camera = findViewById(R.id.camera);
+ camera.setSnapshotMaxWidth(1920);
+ camera.setSnapshotMaxHeight(1440);
+ camera.setOnClickListener(this);
+ btnSwitch = findViewById(R.id.btn_switch);
+ btnSwitch.setOnClickListener(this);
+ ivPicRoadImage = findViewById(R.id.iv_pic_road);
+ 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);
+ imgRoadDirection = findViewById(R.id.img_road_direction);
+ imgRoadDirection.setSelected(true);
+ imgLocationType = findViewById(R.id.img_location_type);
+ imgLocationType.setOnClickListener(this::onClick);
+
+ //获取地图
+ tencentMap = tvMapView.getMap();
+ //获取地图UI 设置对象
+ UiSettings uiSettings = tencentMap.getUiSettings();
+ //设置logo的大小
+ uiSettings.setLogoScale(0.7f);
+ uiSettings.setRotateGesturesEnabled(false);//禁止地图旋转手势.
+ uiSettings.setTiltGesturesEnabled(false);//禁止倾斜手势.
+ setLocMarkerStyle(LOCATION_TYPE_LOCATION_ROTATE);
+ tencentMap.setLocationSource(new MyTecentLocationSource(this));
+ tencentMap.setMyLocationEnabled(true);
+ DisplayMetrics dm = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics(dm);
+ FrameLayout.LayoutParams layoutParamsMap = (FrameLayout.LayoutParams) tvMapView.getLayoutParams();//相机的宽高
+ layoutParamsMap.width = dm.widthPixels / 3;
+ layoutParamsMap.height = dm.heightPixels / 3;
+ tvMapView.setLayoutParams(layoutParamsMap);
+
+ ivPicRoadImage.setVisibility(View.VISIBLE);
+ ivPicVideoImage.setVisibility(View.GONE);
+
+ trackLocRemovables = new ArrayList<>();
+
+ // 清空所有匹配的数据
+ btnClearMatch.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (roadMatchEntityList!=null&&!roadMatchEntityList.isEmpty()) {
+ cancelReciverTask(roadMatchEntityList)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Consumer() {
+ @Override
+ public void accept(PoiEntity poiEntity) throws Exception {
+
+ }
+ }, new Consumer() {
+ @Override
+ public void accept(Throwable throwable) throws Exception {
+ Toast.makeText(AutoTakePicture4PoiVideoActivity.this, throwable.getMessage(), Toast.LENGTH_SHORT).show();
+ }
+ }, new Action() {
+ @Override
+ public void run() throws Exception {
+ // 重新刷新地图
+ initRoadLine2Map();
+ // 执行结束后清空已匹配列表
+ roadMatchEntityList.clear();
+ }
+ });
+ }
+ }
+ });
+
+ btnStopPicture.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onBackPressed();
+ }
+ });
+
+ btnSetting = findViewById(R.id.btn_setting);
+ btnSetting.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ CustomDialog.show(new OnBindView(R.layout.camera_setting) {
+ @Override
+ public void onBind(CustomDialog dialog, View v) {
+ EditText startDistance = v.findViewById(R.id.edt_camera_setting_start_distance);
+ startDistance.setText(MATCH_START_BUFFER_DISTANCE*100000+"");
+
+ EditText midDistance = v.findViewById(R.id.edt_camera_setting_mid_distance);
+ midDistance.setText(MATCH_BUFFER_DISTANCE*100000+"");
+
+// EditText startCount = v.findViewById(R.id.edt_camera_setting_start_count);
+// startCount.setText(UNMATCH_BUFFER_START_BUFFER+"");
+
+ EditText midCount = v.findViewById(R.id.edt_camera_setting_mid_count);
+ midCount.setText(UNMATCH_BUFFER_MIDDLE_BUFFER+"");
+
+// EditText unmatchPecent = v.findViewById(R.id.edt_camera_setting_unmatch_pecent);
+// unmatchPecent.setText(UNMATCH_GIVE_UP_DISTANCE_BUFFER+"");
+
+ EditText matchPecent = v.findViewById(R.id.edt_camera_setting_match_pecent);
+ matchPecent.setText(MATCH_CONFIRM_FINISH_BUFFER+"");
+
+ Button btnConfirm = v.findViewById(R.id.btn_camera_setting_confirm);
+ btnConfirm.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (!startDistance.getText().toString().isEmpty()) {
+ MATCH_START_BUFFER_DISTANCE = Double.parseDouble(startDistance.getText().toString())/100000;
+ }
+ if (!midDistance.getText().toString().isEmpty()) {
+ MATCH_BUFFER_DISTANCE = Double.parseDouble(midDistance.getText().toString())/100000;
+ }
+// if (!startCount.getText().toString().isEmpty()) {
+// UNMATCH_BUFFER_START_BUFFER = Integer.parseInt(startCount.getText().toString());
+// }
+ if (!midCount.getText().toString().isEmpty()) {
+ UNMATCH_BUFFER_MIDDLE_BUFFER = Integer.parseInt(midCount.getText().toString());
+ }
+// if (!unmatchPecent.getText().toString().isEmpty()) {
+// UNMATCH_GIVE_UP_DISTANCE_BUFFER = Float.parseFloat(unmatchPecent.getText().toString());
+// }
+ if (!matchPecent.getText().toString().isEmpty()) {
+ MATCH_CONFIRM_FINISH_BUFFER = Float.parseFloat(matchPecent.getText().toString());
+ }
+ Toast.makeText(AutoTakePicture4PoiVideoActivity.this, "设置完成", Toast.LENGTH_SHORT).show();
+ dialog.dismiss();
+ }
+ });
+ }
+ }).setFullScreen(true);
+ }
+ });
+ locationSwitch = findViewById(R.id.location_switch);
+ locationSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ locationEnable = isChecked;
+ }
+ });
+
+ imgViewSettingHook = findViewById(R.id.image_view);
+ imgViewSettingHook.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (btnSetting.isShown()) {
+ return;
+ }
+ settingHookClickCount++;
+ if(lastClickTime > 0){
+ long secondClickTime = System.currentTimeMillis();//距离上次开机时间
+ long dtime = secondClickTime - lastClickTime;
+ if(dtime <800){
+ if (settingHookClickCount>8) {
+ Toast.makeText(AutoTakePicture4PoiVideoActivity.this, "打开设置功能", Toast.LENGTH_SHORT).show();
+ btnSetting.setVisibility(View.VISIBLE);
+ locationSwitch.setVisibility(View.VISIBLE);
+ imgRoadDirection.setVisibility(View.VISIBLE);
+ } else {
+ if (settingHookClickCount>3) {
+ Toast.makeText(AutoTakePicture4PoiVideoActivity.this, "再点击"+(9-settingHookClickCount)+"下打开设置功能", Toast.LENGTH_SHORT).show();
+ }
+ }
+ } else{
+ lastClickTime = 0;
+ settingHookClickCount = 1;
+ }
+ }
+ lastClickTime = System.currentTimeMillis();
+ }
+ });
+
+ imgNaviDistance.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ imgNaviDistance.setSelected(!imgNaviDistance.isSelected());
+ if (view.isSelected()) {
+ // 开始自动匹配
+ if (roadMatchEntityList.isEmpty()) {
+ navi2NearestPoiEntity();
+ }
+ } else {
+ if (currentNaviLine!=null) {
+ currentNaviLine.remove();
+ }
+ }
+ }
+ });
+
+ imgRoadDirection.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ view.setSelected(!view.isSelected());
+ startMatchEnableDirection = view.isSelected();
+ }
+ });
+ }
+ private long lastClickTime = 0;
+ private int settingHookClickCount = 1;
+
+
+ @Override
+ protected void initData() {
+ super.initData();
+ tencentMarkerUtils = new TencentMarkerUtils();
+ removables = new ArrayList<>();//存储网络数据的marker数据(线,面,点)
+ removablesLocality = new ArrayList<>();//存储本地的marker数据(线,面,点)
+ removableHashMap = new HashMap<>();//key wkt value :存储的数据类型
+ roadLinkEntityList = new ArrayList<>();
+ roadMatchEntityList = new ArrayList<>();
+ recorderDao = PoiDatabase.getInstance(AutoTakePicture4PoiVideoActivity.this).getRecorderDao();
+ poiDao = PoiDatabase.getInstance(AutoTakePicture4PoiVideoActivity.this).getPoiDao();
+
+ camera.setMode(Mode.PICTURE);
+ initCameraSize();
+ tencentMap.addOnMapLoadedCallback(new TencentMap.OnMapLoadedCallback() {
+ @Override
+ public void onMapLoaded() {
+ tencentMap.setMapFrameRate(30);
+ initRoadLine2Map(); // 获取道路任务,渲染在地图上
+ }
+ });
+
+ tencentMap.setOnMapClickListener(new TencentMap.OnMapClickListener() {
+ @Override
+ public void onMapClick(LatLng latLng) {
+ Message msg = handler.obtainMessage(0x105);
+ msg.obj = TencentLocationObtain.obtainTecentLocation(latLng);
+ handler.sendMessage(msg);
+ }
+ });
+
+ tencentMap.addTencentMapGestureListener(new TencentMapGestureListener() {
+ @Override
+ public boolean onDoubleTap(float v, float v1) {
+ return false;
+ }
+
+ @Override
+ public boolean onSingleTap(float v, float v1) {
+ return false;
+ }
+
+ @Override
+ public boolean onFling(float v, float v1) {
+ return false;
+ }
+
+ @Override
+ public boolean onScroll(float v, float v1) {
+ return false;
+ }
+
+ @Override
+ public boolean onLongPress(float v, float v1) {
+ return false;
+ }
+
+ @Override
+ public boolean onDown(float v, float v1) {
+ setLocMarkerStyle(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);
+ return false;
+ }
+
+ @Override
+ public boolean onUp(float v, float v1) {
+ return false;
+ }
+
+ @Override
+ public void onMapStable() {
+
+ }
+ });
+ camera.addCameraListener(new CameraListener() {
+ @Override
+ public void onPictureTaken(@NonNull PictureResult result) {
+ super.onPictureTaken(result);
+ if (camera == null || camera.getSnapshotSize()==null) {
+ return;
+ }
+ // 获取照片数据
+ if (result != null && result.getData() != null && result.getData().length > 0) {
+ super.onPictureTaken(result);
+ System.out.println("收到拍照按钮jieguo:"+result.getSize().toString());
+ // 道路拍照必须为横向拍照
+ // TODO 测试时先解除竖向拍摄检查
+ if (Objects.requireNonNull(camera.getSnapshotSize()).getWidth() < camera.getSnapshotSize().getHeight()) {
+ ToastUtils.Message(AutoTakePicture4PoiVideoActivity.this, "不允许竖向拍摄...");
+ systemTTS.playText("不允许竖向拍摄");
+ return;
+ }
+
+ File tmpPicFolder = new File(tmpPicFoldPath);
+ if (!tmpPicFolder.exists()) {
+ tmpPicFolder.mkdirs();
+ }
+ String currentName = System.currentTimeMillis()+"";
+ File picFile = new File(tmpPicFolder.getAbsolutePath(), currentName);
+ synchronized (picFile) {
+ // 生成点位marker
+ addTrackMarker();
+ result.toFile(picFile, new FileCallback() {
+ @Override
+ public void onFileReady(@Nullable File file) {
+ // 在数据库中记录照片、轨迹位置以及卫星颗数
+ LocationRecorder recorder = new LocationRecorder();
+ recorder.setTime(Long.parseLong(file.getName()));
+ // 记录主定位方式
+ recorder.setTencentLocationX(LocationLifeCycle.getInstance().getMainLocation().getLongitude());
+ recorder.setTencentLocationY(LocationLifeCycle.getInstance().getMainLocation().getLatitude());
+ // 记录辅助定位方式
+ MyLocation gpsLocation = LocationLifeCycle.getInstance().getReferenceLocation();
+ if (gpsLocation!=null) {
+ recorder.setGpsLocationX(gpsLocation.getLongitude());
+ recorder.setGpsLocationY(gpsLocation.getLatitude());
+ }
+ recorder.setBearing(LocationLifeCycle.getInstance().getMainLocation().getBearing());
+ recorder.setImgFileName(file.getAbsolutePath());
+ recorder.setRssi(GPSUtils.getInstance(AutoTakePicture4PoiVideoActivity.this).getSateliteCount());
+ recorder.setSatelliteCount(GPSUtils.getInstance(AutoTakePicture4PoiVideoActivity.this).getSateliteCount());
+ Observable.just(recorder).observeOn(Schedulers.io())
+ .filter(roadMatchEntity -> roadMatchEntity!=null)
+ .subscribe(new Consumer() {
+ @Override
+ public void accept(LocationRecorder locationRecorder) throws Exception {
+ recorderDao.insertLocationRecorder(recorder);
+ }
+ });
+ }
+ });
+ }
+ }
+ }
+ });
+
+ SharedPreferences spf = getSharedPreferences("MatchEntity", Context.MODE_PRIVATE);
+ Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
+ String matchedData = spf.getString("match-data", null);
+ if (matchedData!=null) {
+ List dataList = gson.fromJson(matchedData, new TypeToken>(){}.getType());
+ roadMatchEntityList.addAll(dataList);
+ }
+ // 清空缓存数据
+ spf.edit().remove("match-data");
+ spf.edit().commit();
+ }
+
+ /**
+ * 根据网络数据和本地数据库数据,更新地图上渲染的道路任务
+ * */
+ private void initRoadLine2Map() {
+ if (Constant.USHERED != null) {
+ // 刷新筛选的本地数据
+ tencentMarkerUtils.initLocalMarker(AutoTakePicture4PoiVideoActivity.this, tencentMap, removablesLocality, removableHashMap, new TencentMarkerUtils.MarkerInitCallback() {
+ @Override
+ public void onMarkerInit(Map> removableHashMap, List uploadByNet, List listData) {
+
+ }
+ });
+ }
+ if (LocationLifeCycle.getInstance().getMainLocation() != null) { //筛选从服务器获取到的数据
+ // 注意,此处只获取道路数据
+ tencentMarkerUtils.initNetMarkerList(AutoTakePicture4PoiVideoActivity.this, LocationLifeCycle.getInstance().getTencentLocation(), tencentMap, removables,
+ "3"/*只获取poi录像数据*/,"0"/*只获取未领取的数据*/, removableHashMap, 50, new TencentMarkerUtils.MarkerInitCallback() {
+
+ @Override
+ public void onMarkerInit(Map> removableHashMap, List uploadByNet,
+ List listData) {
+ // 根据获取到的网络数据,整理数据的起终点数据,方便接下来自动捕捉数据
+ roadLinkEntityList.clear();
+ if (listData!=null) {
+ listData.stream().forEach(
+ it -> {
+ String geometryStr = Geohash.getInstance().decode(it.getGeo());
+ Geometry geometry = GeometryTools.createGeometry(geometryStr);
+ RoadMatchEntity roadMatchEntity = new RoadMatchEntity();
+ roadMatchEntity.setId(it.getId());
+ roadMatchEntity.setDataDetail(it);
+ roadMatchEntity.setGeometry((LineString) geometry);
+// roadMatchEntity.setBuffer(geometry.buffer(MATCH_BUFFER_DISTANCE).toString());
+ // 实时设置当前任务的起始角度
+ if (geometry instanceof LineString) {
+ LineString lineString = (LineString) geometry;
+ // 计算前两个点的坐标角度
+ // 获取当前数据的前两个点的方向
+ Coordinate[] coordinates = lineString.getCoordinates();
+ // 循环取出当前数据的坐标点,为防止出现重复点,需要循环做判断
+ Coordinate[] lineCoordinates = new Coordinate[2];
+ lineCoordinates[0] = coordinates[0];
+ lineCoordinates[1] = coordinates[0];
+ for (Coordinate c: coordinates) {
+ if (c.x!=lineCoordinates[0].x&&c.y!=lineCoordinates[0].y) {
+ lineCoordinates[1] = c;
+ break;
+ }
+ }
+ if (lineCoordinates[0]!=lineCoordinates[1]) {
+ double dataBearing = getBearing(lineCoordinates[0].x, lineCoordinates[1].x, lineCoordinates[0].y, lineCoordinates[1].y);
+ roadMatchEntity.setAngle(dataBearing);
+ }
+ roadMatchEntity.setsPoint(lineString.getStartPoint().toString());
+ roadMatchEntity.setePoint(lineString.getEndPoint().toString());
+ }
+ roadLinkEntityList.add(roadMatchEntity);
+ }
+ );
+ // 如果当前自动规划打开且没有正在匹配的任务,自动规划下一条最近的任务
+ if (imgNaviDistance.isSelected()&&roadMatchEntityList.isEmpty()) {
+ navi2NearestPoiEntity();
+ }
+ }
+ }
+ });
+ } else {
+ ToastUtils.Message(AutoTakePicture4PoiVideoActivity.this, "未开启定位服务");
+ }
+ }
+
+ Observer receiveObserver = new Observer() {
+ @Override
+ public void onSubscribe(Disposable d) {
+
+ }
+
+ @Override
+ public void onNext(PoiEntity poiEntity) {
+ write2Log("领取任务成功:", poiEntity.getId());
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ systemTTS.playText("注意,领取任务失败!");
+ if (AutoTakePicture4PoiVideoActivity.this!=null) {
+ write2Log("领取任务失败:", e.getMessage()+",网络状态-:"+ NetWorkUtils.getNetworkTypeName(AutoTakePicture4PoiVideoActivity.this));
+ }
+ }
+
+ @Override
+ public void onComplete() {
+ initRoadLine2Map();
+ }
+ };
+
+ /**
+ * 开始自动匹配
+ * */
+ private double minDistance = MATCH_START_BUFFER_DISTANCE; // 最小距离,需要在匹配过程点时判断哪个任务是距离最小的
+ private void startMatchRoadLink(Point currentPoint) {
+ if (roadLinkEntityList == null/*没有需要匹配的道路数据*/ || currentPoint == null/*没有位置信息*/) {
+ write2Log("开始匹配:", "roadLinkEntityList == null:"+(roadLinkEntityList == null)+",currentPoint == null:"+(currentPoint == null));
+ return;
+ }
+ double[] speedAndBearing = getSpeedAndBearing(currentPoint);
+ double currentSpeed = speedAndBearing[0]; // 当前速度
+ double currentBearing = speedAndBearing[1]; // 当前方向
+ double matchMiddleDistance = MATCH_BUFFER_DISTANCE;
+ // 如果速度大于70,则动态调整起点捕捉范围
+ if (currentSpeed>=70) {
+ matchMiddleDistance = MATCH_BUFFER_DISTANCE*1.5;
+ }
+ // 此处开始匹配起点
+ write2Log("开始匹配起点位置:", "currentLocation:"+currentPoint.toString()+",可匹配数据个数:"+roadLinkEntityList.size());
+ List matchStartList = roadLinkEntityList.stream()
+ // 筛选当前任务与起点距离
+ .filter(it-> {
+ if (GeometryTools.createGeometry(it.getsPoint()).distance(currentPoint) {
+ if (startMatchEnableDirection) {
+ double dataBearing = it.getAngle();
+ if (Math.abs(dataBearing-currentBearing)<=90 || Math.abs(dataBearing-currentBearing)>=270) {
+ return true;
+ } else {
+ // 根据方向判定无法匹配
+ write2Log("方向不匹配:", "currentBearing:"+currentBearing+",数据角度:"+dataBearing+",数据id:"+it.getDataDetail().getId());
+ return false;
+ }
+ } else {
+ return true;
+ }
+ })
+ // 判断筛选出的数据是否已经在匹配列表中,如果不存在,需要自动领取该任务、记录开始采集时间
+ .filter(
+ o -> {
+ if (roadMatchEntityList.stream().noneMatch(roadMatchEntity -> o.getId()==roadMatchEntity.getId())) {
+ return true; // 如果列表中不存在当前数据,不过滤,断点使用,增加return
+ } else {
+ return false;
+ }
+ })
+ .collect(Collectors.toList());
+ if (matchStartList!=null&&!matchStartList.isEmpty()) {
+ // 存在新匹配到的数据
+ matchStartList.stream().forEach(
+ roadMatchEntity -> {
+ // 记录开始采集时间
+ roadMatchEntity.setStartMatchTime(System.currentTimeMillis());
+ // TODO:自动发送请求领取任务
+ receiverRoadTask(roadMatchEntity).subscribe(receiveObserver);
+ });
+
+ // 语音提醒
+ if (roadMatchEntityList.isEmpty()) {
+ // 当前没有已匹配的数据,提示用户“叮~捕捉任务”
+ mediaPlayer.start();
+ systemTTS.playText("捕捉任务");
+ } else {
+ // 当前存在已匹配的任务,有新匹配的任务,提示“叮~任务拍摄中”
+ mediaPlayer.start();
+ systemTTS.playText("任务拍摄中");
+ }
+
+ // 将匹配到的数据加入到已匹配列表中
+ roadMatchEntityList.addAll(matchStartList);
+ } else {
+ write2Log("匹配起点数据为空:", "当前位置为:"+currentPoint.toString()+"当前角度:"+currentBearing);
+ }
+
+ // 尝试用当前位置点匹配已经匹配到的roadLink,如果能匹配到,需要将该点记录,如果无法匹配,则需要评估已匹配的link是否需要被剔除
+ minDistance = MATCH_START_BUFFER_DISTANCE; // 使用距离起终点的最大阈值初始化最小距离
+ if (!roadMatchEntityList.isEmpty()) {
+ // 因为单个点位只能匹配一条任务,需要获取当前点位距离所有任务最近的距离
+ roadMatchEntityList.stream().forEach(it->{
+ double currentDistance = GeometryTools.createGeometry(it.getGeometry()).distance(currentPoint);
+ it.setCurrentLineDistance(currentDistance);
+ if (currentDistance<=minDistance) {
+ minDistance = currentDistance;
+ }
+ });
+
+ List unMatchList = new ArrayList<>();
+ Map finishEntityMap = new HashMap<>();
+ double finalMatchMiddleDistance = matchMiddleDistance;
+ roadMatchEntityList.stream().forEach(
+ roadMatchEntity -> {
+ double currentDistance = roadMatchEntity.getCurrentLineDistance();
+ boolean isMatch=currentDistance<= finalMatchMiddleDistance; // 当前点位是否可以和link匹配到
+ if (isMatch) { // 可以匹配到
+ if (roadMatchEntity.getCurrentLineDistance()<=minDistance) { // 并且该条数据还是最近的点, 将当前点位匹配到此任务下(注意,当距离完全相等时,同一点位可能同时匹配到多个任务)
+ if (roadMatchEntity.getMatchPointList().size() == 0) { // 可以匹配到,并且从未匹配过,更新任务的开始时间
+ roadMatchEntity.setStartMatchTime(System.currentTimeMillis());
+ }
+ // 更新连续匹配的个数
+ roadMatchEntity.setMatchCount(roadMatchEntity.getMatchCount()+1);
+ // 匹配到最近的任务,将当前点加入到已匹配道路中
+ roadMatchEntity.getMatchPointList().add(new MyCoordinate(currentPoint.getX(), currentPoint.getY()));
+ // 如果连续匹配个数大于1(可以连成线),更新已匹配长度
+ if (roadMatchEntity.getMatchCount()>1) {
+ roadMatchEntity.setMatchedLength(
+ roadMatchEntity.getMatchedLength()
+ +
+ // 加上最后两个点的长度
+ GeometryTools.getLineStringByMyCoordinate(roadMatchEntity.getMatchPointList().subList(roadMatchEntity.getMatchPointList().size()-2, roadMatchEntity.getMatchPointList().size())).getLength()
+ );
+ }
+ } else { // 在阈值内,但是并非最近的点
+ roadMatchEntity.setMatchCount(0); // 连续匹配个数置为0
+ }
+ roadMatchEntity.setUnMatchCount(0); // 有匹配的数据,则连续未匹配个数归0(即使不是最近的数据,在阈值内即认为可匹配,未匹配点数也置为0)
+
+ double currentEndDistance = currentPoint.distance(GeometryTools.createGeometry(roadMatchEntity.getePoint())); // 当前距离终点的距离
+ // 记录本次的匹配距离,如果本次匹配距离大于上一次,且上一次匹配终点时间不为0(说明已经提前匹配到终点了),则结束匹配,否则继续等待匹配,设置过EndMathchTime的数据即为可以结束匹配的数据,下一次如果未匹配,也可以结束
+ if (roadMatchEntity.getEndMathchTime()>0/*endMatchTime不为0,说明该数据已经匹配到终点*/&¤tEndDistance>roadMatchEntity.getLastEndDistance()) {
+ finishEntityMap.put(roadMatchEntity.getId(), roadMatchEntity);
+ // 更新终点时间为距离终点逐渐变大时的时间
+ roadMatchEntity.setEndMathchTime(System.currentTimeMillis());
+ }
+ // 匹配距离超过指定阈值,认为该条数据可完成,记录当前位置与终点的距离,当距离从小变大时,完成该任务
+ if (roadMatchEntity.getMatchPointList().size()>=2&&roadMatchEntity.getMatchedLength()/roadMatchEntity.getLength()>=MATCH_CONFIRM_FINISH_BUFFER) {
+ roadMatchEntity.setEndMathchTime(System.currentTimeMillis());
+ // 匹配到终点后,记录该条数据的最新一次匹配距离,当下一次匹配距离大于当前距离,则认为该数据完全匹配,结束匹配
+ roadMatchEntity.setLastEndDistance(currentEndDistance);
+ }
+ //=============如果在匹配范围内,但是该数据并非最近的点,不需要记录匹配,也无需增加未匹配点的个数
+ } else { // 无法匹配
+ // 更新连续无法匹配的点位个数
+ roadMatchEntity.setUnMatchCount(roadMatchEntity.getUnMatchCount()+1);
+ // 有未匹配的数据,连续匹配个数也归0
+ roadMatchEntity.setMatchCount(0);// 设置连续匹配的数据个数为0
+ roadMatchEntity.getUnMatchPointList().add(new MyCoordinate(currentPoint.getX(), currentPoint.getY()));
+ // 当连续未匹配个数大于等于20个时,该任务被认为可以结束(舍弃或完成-需根据匹配到的数据长度与任务长度做对比)
+ if (roadMatchEntity.getUnMatchCount()>=UNMATCH_BUFFER_MIDDLE_BUFFER) { // 连续未匹配大于阈值时
+ List matchPointList = roadMatchEntity.getMatchPointList();
+ if (matchPointList == null || matchPointList.size()<2) { // 已匹配的点位不足2个,无法计算长度,直接放弃该任务
+ unMatchList.add(roadMatchEntity);
+ } else {
+ if (roadMatchEntity.getMatchedLength()/roadMatchEntity.getLength()>=MATCH_CONFIRM_FINISH_BUFFER) { // 已匹配距离与任务长度距离比例超过指定阈值,该任务可完成
+ roadMatchEntity.setEndMathchTime(System.currentTimeMillis());
+ finishEntityMap.put(roadMatchEntity.getId(), roadMatchEntity);
+ } else {
+ unMatchList.add(roadMatchEntity);
+ }
+ }
+ }
+ }
+ }
+ );
+
+
+ if (!finishEntityMap.isEmpty()) {
+ // 过滤掉已完成的link
+ for (RoadMatchEntity finishEntity: finishEntityMap.values()) {
+ roadMatchEntityList.remove(finishEntity);
+ }
+ // TODO 完成的entity数据,需要自动生成对应的数据,还需要自动复制对应的照片,通知服务器采集完成
+ finishRoadTask(finishEntityMap);
+ // 只有在没有正在拍摄的任务,所有任务都拍摄完成时才会提示
+ if (roadMatchEntityList.isEmpty()) {
+ // 语音提示用户
+ mediaPlayer.start();
+ systemTTS.playText("拍摄完成");
+ }
+ }
+
+ if (!unMatchList.isEmpty()) {
+ cancelReciverTask(unMatchList).subscribe(new Observer() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ // 过滤需要舍弃的link
+ for (RoadMatchEntity unMatchEntity: unMatchList) {
+ roadMatchEntityList.remove(unMatchEntity);
+ }
+ }
+
+ @Override
+ public void onNext(PoiEntity poiEntity) {
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ Toast.makeText(AutoTakePicture4PoiVideoActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void onComplete() {
+ // 重新刷新地图
+ initRoadLine2Map();
+ }
+ });
+ }
+ }
+ // 如果当前已经不存在正在采集的数据,则停止记录经纬度和拍照
+ if (roadMatchEntityList.isEmpty()) {
+ stopRecordLocation();
+ } else {
+ startRecordLocation();
+ }
+ }
+
+ /**
+ * 导航到最近的道路任务
+ * */
+ @RequiresApi(api = Build.VERSION_CODES.N)
+ private void navi2NearestPoiEntity() {
+ if (roadLinkEntityList == null || roadLinkEntityList.isEmpty()) {
+ SystemTTS.getInstance(this).playText("附近当前没有可匹配的任务");
+ return;
+ }
+ // RxJava处理,子线程中做后台计算路径规划
+ Geometry currentGeometry = GeometryTools.createGeometry(new double[]{LocationLifeCycle.getInstance().getMainLocation().getLongitude(), LocationLifeCycle.getInstance().getMainLocation().getLatitude()});
+ Observable.create(
+ new ObservableOnSubscribe() {
+ @Override
+ public void subscribe(ObservableEmitter emitter) throws Exception {
+ RoadMatchEntity minRoadLink = roadLinkEntityList.stream()
+ // 过滤已经匹配到的数据
+ .filter(roadMatchEntity -> {
+ if (roadMatchEntityList.contains(roadMatchEntity)) {
+ return false;
+ }
+ return true;
+ })
+ .min((t1, t2) -> {
+ // 判断距离用户当前位置的距离
+ JobSearchBean.BodyBean.ListBean bean1 = t1.getDataDetail();
+ JobSearchBean.BodyBean.ListBean bean2 = t2.getDataDetail();
+ // 转换geo
+ Geometry geometry1 = GeometryTools.createGeometry(Geohash.getInstance().decode(bean1.getGeo()));
+ Geometry geometry2 = GeometryTools.createGeometry(Geohash.getInstance().decode(bean2.getGeo()));
+ if (currentGeometry.distance(geometry1)>currentGeometry.distance(geometry2)) {
+ return 1;
+ } else if (currentGeometry.distance(geometry1)() {
+ @Override
+ public void accept(RoadMatchEntity minRoadLink) throws Exception {
+ JobSearchBean.BodyBean.ListBean bean = minRoadLink.getDataDetail();
+ Coordinate endPoint = GeometryTools.createGeometry(Geohash.getInstance().decode(bean.getGeo())).getCoordinates()[0];
+ ToastUtils.Message(AutoTakePicture4PoiVideoActivity.this, "已为您规划距离最近的任务路径:"+bean.getName());
+ // 跳转到对应的导航界面
+ try {
+ if (Constant.currentNaviType == null) {
+ NaviUtils.getInstance().selectNaviType(AutoTakePicture4PoiVideoActivity.this, new NaviUtils.SelectNaviTypeListener() {
+ @Override
+ public void selectNaviType(Constant.NAV_TYPE nav_type) {
+ // 显示导航类型选择的对话框
+ Constant.currentNaviType = nav_type;
+ try {
+ tencentNaviManager = NaviUtils.getInstance().searchRouteOnly(AutoTakePicture4PoiVideoActivity.this, Constant.currentNaviType, new NaviPoi(LocationLifeCycle.getInstance().getMainLocation().getLatitude(), LocationLifeCycle.getInstance().getMainLocation().getLongitude()), new NaviPoi(endPoint.getY(), endPoint.getX()), routeSearchCallback);
+ } catch (Exception e) {
+ e.printStackTrace();
+ com.github.lazylibrary.util.ToastUtils.showToast(AutoTakePicture4PoiVideoActivity.this, e.getMessage());
+ }
+ }
+ });
+ } else {
+ // 已选择导航方式
+ tencentNaviManager = NaviUtils.getInstance().searchRouteOnly(AutoTakePicture4PoiVideoActivity.this, Constant.currentNaviType, new NaviPoi(LocationLifeCycle.getInstance().getMainLocation().getLatitude(), LocationLifeCycle.getInstance().getMainLocation().getLongitude()), new NaviPoi(endPoint.getY(), endPoint.getX()), routeSearchCallback);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ com.github.lazylibrary.util.ToastUtils.showToast(AutoTakePicture4PoiVideoActivity.this, e.getMessage());
+ }
+ }
+ });
+ }
+
+ private TencentNaviManager tencentNaviManager;
+ TencentRouteSearchCallback routeSearchCallback = new TencentRouteSearchCallback() {
+ @Override
+ public void onRouteSearchFailure(int i, String s) {
+
+ }
+
+ @Override
+ public void onRouteSearchSuccess(ArrayList arrayList) {
+ currentNaviLine = drawNaviLine(arrayList.get(0));
+ }
+
+ @Override
+ public void onCalcRouteSuccess(CalcRouteResult calcRouteResult) {
+ }
+
+ @Override
+ public void onCalcRouteFailure(CalcRouteResult calcRouteResult) {
+
+ }
+ };
+
+ /**
+ * 绘制导航线路
+ * */
+ private Polyline drawNaviLine(RouteData routeData) {
+ if (currentNaviLine!=null) {
+ currentNaviLine.remove();
+ }
+ Polyline polyline = NaviUtils.getInstance().addRoutes(routeData, tencentMap);
+ NaviUtils.getInstance().zoomToRoute(AutoTakePicture4PoiVideoActivity.this, routeData, tencentMap);
+ if (tencentNaviManager!=null) {
+// if (Constant.currentNaviType == Constant.NAV_TYPE.CAR) {
+// } else if (Constant.currentNaviType == Constant.NAV_TYPE.RIDE) {
+//
+// } else {
+//
+// }
+ tencentNaviManager.setNaviCallback(new TencentNaviCallback() {
+ @Override
+ public void onStartNavi() {
+
+ }
+
+ @Override
+ public void onStopNavi() {
+ polyline.remove();
+ }
+
+ @Override
+ public void onOffRoute() {
+
+ }
+
+ @Override
+ public void onRecalculateRouteSuccess(int i, ArrayList arrayList) {
+ }
+
+ @Override
+ public void onRecalculateRouteSuccessInFence(int i) {
+
+ }
+
+ @Override
+ public void onRecalculateRouteFailure(int i, int i1, String s) {
+
+ }
+
+ @Override
+ public void onRecalculateSuccess(CalcRouteResult calcRouteResult) {
+
+ }
+
+ @Override
+ public void onRecalculateFailure(CalcRouteResult calcRouteResult) {
+
+ }
+
+ @Override
+ public void onRecalculateRouteStarted(int i) {
+
+ }
+
+ @Override
+ public void onRecalculateRouteCanceled() {
+
+ }
+
+ @Override
+ public void onArrivedDestination() {
+ polyline.remove();
+ }
+
+ @Override
+ public void onPassedWayPoint(int i) {
+
+ }
+
+ @Override
+ public void onUpdateRoadType(int i) {
+
+ }
+
+ @Override
+ public void onUpdateParallelRoadStatus(ParallelRoadStatus parallelRoadStatus) {
+
+ }
+
+ @Override
+ public void onUpdateAttachedLocation(AttachedLocation attachedLocation) {
+
+ }
+
+ @Override
+ public void onFollowRouteClick(String s, ArrayList arrayList) {
+
+ }
+
+ @Override
+ public int onVoiceBroadcast(NaviTts naviTts) {
+ return 0;
+ }
+
+ @Override
+ public void onEnterIdleSection(IdleRangeInfo idleRangeInfo) {
+
+ }
+ });
+ }
+ return polyline;
+ }
+
+ /**
+ * 清除导航的路线
+ * */
+ private void clearNaviLine(Polyline polyline) {
+ polyline.remove();
+ }
+
+ /**
+ * 初始化领取任务的管理栈
+ * */
+ private Observable receiverRoadTask(RoadMatchEntity entity) {
+ write2Log("开始领取任务:", entity.getId()+"");
+ return Observable.just(entity).subscribeOn(Schedulers.io()).observeOn(Schedulers.computation())
+ .filter(roadMatchEntity -> roadMatchEntity!=null)
+ .map(new Function() {
+ @Override
+ public PoiEntity apply(RoadMatchEntity roadMatchEntity) throws Exception {
+
+ PoiEntity poiEntity = translateRoadMatchEntity(roadMatchEntity);
+ // 首先发送领取任务的请求
+ OkGoBuilder okGoBuilder = OkGoBuilder
+ .getInstance()
+ .time(30)
+ .Builder(AutoTakePicture4PoiVideoActivity.this)
+ .url(HttpInterface.RECEIVED_ROAD_TASK + "/" + entity.getDataDetail().getId())
+ .cls(TaskByNetBean.class)
+ .params(new HttpParams())
+ .token(Constant.ACCESS_TOKEN);
+ Response response = okGoBuilder.getSynchronization();
+ Gson gson = new Gson();
+ String body = response.body().string();
+ TaskByNetBean taskByNetBean = gson.fromJson(body, TaskByNetBean.class);
+ Log.d("AutoTake:", body);
+ if (taskByNetBean.getCode() == 200) {
+ // 继续保存
+ TaskByNetBean.BodyBean listBean = taskByNetBean.getBody();
+ if (listBean != null) {
+ PoiEntity taskIdPoiEntity = PoiDatabase.getInstance(AutoTakePicture4PoiVideoActivity.this).getPoiDao()
+ .getTaskIdPoiEntity(poiEntity.getTaskId());
+ if (taskIdPoiEntity == null) {//数据库没有这条数据
+ PoiEntity poiListEntity = new PoiEntity();
+ poiListEntity.setTaskId(poiEntity.getTaskId());
+ poiListEntity.setName(listBean.getName());
+ poiListEntity.setMemo(listBean.getMemo());
+ poiListEntity.setCreateTime(listBean.getEndDate());
+ poiListEntity.setAddress(listBean.getAddress());
+ poiListEntity.setType(listBean.getType());
+ poiListEntity.setPrecision(String.valueOf(listBean.getPrice()));
+ poiListEntity.setIsExclusive(listBean.getIsExclusive());
+ poiListEntity.setTaskStatus(1);
+ poiListEntity.setGeoWkt(listBean.getGeo());
+ String encodeStr = listBean.getGeo();
+ String geo = Geohash.getInstance().decode(encodeStr);
+ // 生成对应的x和y poiEntity.setX
+ GeometryTools.obitainPoiEntityXY(geo, poiListEntity);
+ InsertAndUpdateUtils.getInstance().insertOrUpdate(AutoTakePicture4PoiVideoActivity.this, poiListEntity);
+ }
+ }
+ } else if (taskByNetBean.getCode() == 230) { // Token过期
+ systemTTS.playText("注意,Token过期,请重新登陆!");
+ write2Log("领取任务失败:", "Token过期:"+taskByNetBean.getMessage());
+ FlushTokenUtil.flushToken(AutoTakePicture4PoiVideoActivity.this);
+ Message msg = handler.obtainMessage(0x103);
+ msg.obj = entity;
+ handler.sendMessageDelayed(msg, 10*1000); // 10秒后重试
+ } else {
+ systemTTS.playText("注意,领取任务失败!");
+ ToastUtils.Message(AutoTakePicture4PoiVideoActivity.this,taskByNetBean.getMessage());
+ write2Log("领取任务失败:", "领取失败:"+taskByNetBean.getMessage());
+ Message msg = handler.obtainMessage(0x103);
+ msg.obj = entity;
+ handler.sendMessageDelayed(msg, 10*1000); // 10秒后重试
+ }
+ return poiEntity;
+ }
+ }
+ )
+ .observeOn(AndroidSchedulers.mainThread());
+ }
+
+ /**
+ * 取消领取任务
+ * */
+ private Observable cancelReciverTask(List cancelMatchLinkList) {
+ return Observable.fromIterable(cancelMatchLinkList)
+ .subscribeOn(Schedulers.io())
+ .observeOn(Schedulers.computation())
+ .filter(roadMatchEntity -> roadMatchEntity!=null)
+ .flatMap(roadMatchEntity -> {
+ PoiEntity poiEntity = poiDao.getTaskIdPoiEntity(roadMatchEntity.getId());
+ if (poiEntity!=null) {
+ return sendCancelRequest(poiEntity);
+ } else {
+ return Observable.empty();
+ }
+ })
+ .observeOn(AndroidSchedulers.mainThread());
+ }
+
+ private Observable sendCancelRequest(PoiEntity origin) {
+ return Observable.just(origin)
+ .subscribeOn(Schedulers.io()).observeOn(Schedulers.computation())
+ .map(new Function() {
+ @Override
+ public PoiEntity apply(PoiEntity poiEntity) throws Exception {
+ if (poiEntity!=null) {
+ HttpParams httpParams = new HttpParams();
+ httpParams.put("taskIds", poiEntity.getTaskId());
+ httpParams.put("auditIds", "");
+ OkGoBuilder okGoBuilder = OkGoBuilder.getInstance()
+ .time(30)
+ .Builder(AutoTakePicture4PoiVideoActivity.this)
+ .url(HttpInterface.UNRECEIVED_POLYGON_TASK)
+ .cls(UnPolygonTaskBean.class)
+ .params(httpParams)
+ .token(Constant.ACCESS_TOKEN);
+ Response synchronization = okGoBuilder.getSynchronization();
+ try {
+ String bodyString = synchronization.body().string();
+ Gson gson = new Gson();
+ UnPolygonTaskBean response = gson.fromJson(bodyString, UnPolygonTaskBean.class);
+ if (response.getCode() == 200) {
+ PoiDatabase.getInstance(AutoTakePicture4PoiVideoActivity.this).getPoiDao().deletePoiEntity(poiEntity);
+ // 不需要删除照片,自动采集时照片是临时保存在tmp目录下
+ } else if (response.getCode() == 230) {
+ FlushTokenUtil.flushToken(AutoTakePicture4PoiVideoActivity.this);
+ Message msg = handler.obtainMessage(0x106);
+ msg.obj = poiEntity;
+ handler.sendMessageDelayed(msg, 10*1000); // 10秒后重试
+ } else {
+ ToastUtils.Message(AutoTakePicture4PoiVideoActivity.this, response.getMessage());
+ Message msg = handler.obtainMessage(0x106);
+ msg.obj = poiEntity;
+ handler.sendMessageDelayed(msg, 10*1000); // 10秒后重试
+ }
+ return poiEntity;
+ } catch (IOException e) {
+ throw e;
+ }
+ } else {
+ throw new Exception("");
+ }
+ }
+ });
+ }
+
+ private PoiEntity translateRoadMatchEntity(RoadMatchEntity roadMatchEntity) {
+ PoiEntity poiListEntity = new PoiEntity();
+ JobSearchBean.BodyBean.ListBean listBean = roadMatchEntity.getDataDetail();
+ poiListEntity.setTaskId(listBean.getId());
+ poiListEntity.setGeoWkt(listBean.getGeo());
+ poiListEntity.setName(listBean.getName());
+ poiListEntity.setAddress(listBean.getAddress());
+ poiListEntity.setTelPhone(listBean.getTelephone());
+ poiListEntity.setPrecision(listBean.getPrice() + "");
+ poiListEntity.setDist(listBean.getDist() + "");
+ poiListEntity.setDescribe(listBean.getMemo());
+ poiListEntity.setCreateTime(listBean.getEndDate());
+ poiListEntity.setType(listBean.getType());
+ poiListEntity.setRecord_way(listBean.getCanReceived());
+ poiListEntity.setIsExclusive(listBean.getIsExclusive());
+ String beanGeo = listBean.getGeo();
+ String geo = Geohash.getInstance().decode(beanGeo);
+ // 生成对应的x和y poiEntity.setX
+ GeometryTools.obitainPoiEntityXY(geo, poiListEntity);
+ return poiListEntity;
+ }
+
+ /**
+ * 结束采集,对照片归档
+ * */
+ private int finishTaskCount = 0;
+ private boolean wantBack = false; // 用户是否想要退出当前界面,如果当前有正在处理的图片转移任务,会阻挡用户退出,此时该值状态置为true,当照片处理完后,可以对话框提示用户退出
+ private void finishRoadTask(Map finishEntityMap) {
+ if (finishEntityMap!=null&&!finishEntityMap.isEmpty()) {
+ finishTaskCount++;
+
+ Observable.fromIterable(finishEntityMap.values())
+ .subscribeOn(Schedulers.io()).observeOn(Schedulers.computation())
+ .filter(roadMatchEntity -> roadMatchEntity!=null)
+ .map(roadMatchEntity -> {
+ // 判断是否已领取,未领取则调用领取数据接口
+ PoiEntity poiEntity = poiDao.getTaskIdPoiEntity(roadMatchEntity.getId());
+ if (poiEntity == null) {
+ // 数据库中不存在,尝试再次领取
+ InsertAndUpdateUtils.getInstance().insertOrUpdate(AutoTakePicture4PoiVideoActivity.this, translateRoadMatchEntity(roadMatchEntity));
+ // 调用网络领取任务
+ receiverRoadTask(roadMatchEntity).subscribe(receiveObserver);
+ }
+
+ List recorderList = recorderDao.getLocationRecorderByTime(roadMatchEntity.getStartMatchTime(), roadMatchEntity.getEndMathchTime());
+ File recorderFolder = new File(Constant.PICTURE_FOLDER+"/"+poiEntity.getId());
+ if (!recorderFolder.exists()) {
+ recorderFolder.mkdirs();
+ }
+ // 编辑paper.txt
+ // 复制图片文件
+ File paperFile = new File(recorderFolder.getAbsolutePath(), "paper.txt");
+ for (int i = 0; i < recorderList.size(); i++) {
+ File originImg = new File(recorderList.get(i).getImgFileName());
+ File destFile = new File(recorderFolder.getAbsolutePath()+"/"+i+".jpg");
+ if (!destFile.exists()) {
+ FileUtils.copyFile(originImg.getAbsolutePath(), destFile.getAbsolutePath());
+ }
+ FileUtils.writeFile(paperFile.getAbsolutePath(), recorderList.get(i).toString(picFormatter ,i), true);
+ }
+
+ return poiEntity;
+ })
+ .doOnNext(poiEntity -> {
+ // 网络提交数据
+ if (poiEntity!=null) {
+ // 提交数据,更新状态
+ roadSaveWork(poiEntity);
+ /*poiEntity.setTaskStatus(3);
+ InsertAndUpdateUtils.getInstance().insertOrUpdate(AutoTakePictureActivity.this, poiEntity);*/
+ finishEntityMap.remove(poiEntity.getTaskId());
+ }
+ })
+ .observeOn(AndroidSchedulers.mainThread())
+ .onErrorResumeNext(Observable.empty())
+ .subscribe(new Consumer() {
+ @Override
+ public void accept(PoiEntity poiEntity) {
+// // 已经处理过该任务,将其从finish列表中移除
+// if (poiEntity!=null) {
+// finishEntityMap.remove(poiEntity.getTaskId());
+// }
+
+ }
+ }, new Consumer() {
+ @Override
+ public void accept(Throwable throwable) {
+ // 此处异常可能是服务返回的数据无法解析,但http正常返回了,因此可能为程序问题,不再重复尝试上报
+ systemTTS.playText("注意,领取任务失败!");
+ XLog.e("完成失败:"+throwable.getMessage());
+ ToastUtils.Message(AutoTakePicture4PoiVideoActivity.this, throwable.getMessage());
+ finishTaskCount--;
+ if (finishTaskCount == 0) {
+ showExitDialog(true);
+ }
+ }
+ }, new Action() {
+ @Override
+ public void run() throws Exception {
+ // 重新绘制网络任务和本地任务
+ initRoadLine2Map();
+ finishTaskCount--;
+ if (finishTaskCount == 0) {
+ showExitDialog(false);
+ }
+ }
+ });
+ }
+ }
+
+ private void showExitDialog(boolean hasError) {
+ StringBuilder dialogMessage = new StringBuilder("任务数据处理完成,是否退出当前界面");
+ if (hasError) {
+ dialogMessage.append("(注意,其中有部分任务处理失败)");
+ }
+ MessageDialog.show("退出当前界面", dialogMessage)
+ .setOkButton("确定", new OnDialogButtonClickListener() {
+ @Override
+ public boolean onClick(MessageDialog dialog, View v) {
+ dialog.dismiss();
+ AutoTakePicture4PoiVideoActivity.this.finish();
+ return false;
+ }
+ })
+ .setCancelButton("取消", new OnDialogButtonClickListener() {
+ @Override
+ public boolean onClick(MessageDialog dialog, View v) {
+ dialog.dismiss();
+ wantBack = false;
+ return false;
+ }
+ })
+ .show();
+ }
+
+ private void roadSaveWork(PoiEntity poiEntity) throws IOException {
+ // 设置当前数据状态为本地保存
+ poiEntity.setTaskStatus(2);
+ // 更新数据库中状态
+ InsertAndUpdateUtils.getInstance().insertOrUpdate(AutoTakePicture4PoiVideoActivity.this, poiEntity);
+
+ HttpParams httpParams = new HttpParams();
+ httpParams.put("taskId", poiEntity.getTaskId());
+ httpParams.put("name", poiEntity.getName());
+ httpParams.put("address", poiEntity.getAddress());
+ httpParams.put("workType", 0);
+ httpParams.put("memo", poiEntity.getMemo());
+ // 增加对应九天平台的参数
+ httpParams.put("existence", 0);
+ httpParams.put("description", "");
+
+ OkGoBuilder okGoBuilder = OkGoBuilder.getInstance()
+ .time(30)
+ .Builder(AutoTakePicture4PoiVideoActivity.this)
+ .url(HttpInterface.ROAD_TASK_SUBMIT)
+ .cls(RoadSaveBean.class)
+ .params(httpParams)
+ .token(Constant.ACCESS_TOKEN);
+ Response synchronization = okGoBuilder.getSynchronization();
+ Gson gson = new Gson();
+ RoadSaveBean submitBean = gson.fromJson(synchronization.body().string(), RoadSaveBean.class);
+ if (submitBean.getCode() == 200) {
+ Integer body = submitBean.getBody();
+ if (body != null && body != 0) {
+ poiEntity.setBodyId(body);
+ poiEntity.setTaskStatus(3);
+ // 更新数据库中状态
+ InsertAndUpdateUtils.getInstance().insertOrUpdate(AutoTakePicture4PoiVideoActivity.this, poiEntity);
+ } else {
+ Message obtain1 = Message.obtain();
+ obtain1.what = Constant.NEST_WORD_REGISTER;
+ obtain1.obj = "道路:" + poiEntity.getName() + " 保存本地失败";
+ EventBus.getDefault().post(obtain1);
+ }
+ } else if (submitBean.getCode() == 230) { // Token过期
+ systemTTS.playText("注意,Token过期,请重新登陆!");
+ FlushTokenUtil.flushToken(AutoTakePicture4PoiVideoActivity.this);
+ Message msg = handler.obtainMessage(0x104);
+ msg.obj = poiEntity;
+ handler.sendMessageDelayed(msg, 10*1000); // 10秒后重试
+ } else {
+ systemTTS.playText("注意,领取任务失败!");
+ ToastUtils.Message(AutoTakePicture4PoiVideoActivity.this,submitBean.getMessage());
+ Message msg = handler.obtainMessage(0x104);
+ msg.obj = poiEntity;
+ handler.sendMessageDelayed(msg, 10*1000); // 10秒后重试
+ }
+ }
+
+ /**
+ * 开始记录位置信息
+ * */
+ private void startRecordLocation() {
+ // 只有以前不记录照片,此刻才需要发送新的消息开始拍摄
+ if (!handler.hasMessages(0x101)) {
+ handler.sendEmptyMessage(0x101);
+ }
+ }
+ /**
+ * 停止记录位置信息
+ * */
+ private void stopRecordLocation() {
+ if (handler.hasMessages(0x101)) {
+ handler.removeMessages(0x101);
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.btn_switch:
+// handler.sendEmptyMessageDelayed(0x102, 2000);// 利用handler延迟发送更改状态信息
+ benSwitch();
+ break;
+ case R.id.iv_zoom_add://放大
+ CameraUpdate cameraUpdateIn = CameraUpdateFactory.zoomIn();
+ tencentMap.animateCamera(cameraUpdateIn);
+ setLocMarkerStyle(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);
+ break;
+ case R.id.iv_zoom_del://缩小
+ CameraUpdate cameraUpdateOut = CameraUpdateFactory.zoomOut();
+ tencentMap.animateCamera(cameraUpdateOut);
+ setLocMarkerStyle(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);
+ break;
+ case R.id.iv_location://定位:
+ if (LocationLifeCycle.getInstance().getMainLocation() != null) {
+ CameraUpdate cameraSigma = CameraUpdateFactory
+ .newCameraPosition(new CameraPosition(new LatLng(LocationLifeCycle.getInstance().getMainLocation().getLatitude(), LocationLifeCycle.getInstance().getMainLocation().getLongitude()), //中心点坐标,地图目标经纬度
+ 17, //目标缩放级别
+ 0, //目标倾斜角[0.0 ~ 45.0] (垂直地图时为0)
+ 0)); //目标旋转角 0~360° (正北方为0)
+ tencentMap.animateCamera(cameraSigma);
+ }
+ // 设置当前地图的定位显示模式为跟随
+ setLocMarkerStyle(LOCATION_TYPE_LOCATION_ROTATE);
+ break;
+ case R.id.img_location_type: // 切换定位方式
+ imgLocationType.setSelected(!imgLocationType.isSelected());
+ if (imgLocationType.isSelected()) { // 选中状态,切换为GPS为主定位
+ LocationLifeCycle.getInstance().setMainLocationFrom(LocationLifeCycle.LOCATION_FROM.ORIGIN);
+ } else {
+ LocationLifeCycle.getInstance().setMainLocationFrom(LocationLifeCycle.LOCATION_FROM.TENCENT);
+ }
+ break;
+ }
+ }
+
+ private Bitmap getBitMap() {
+ Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.locaiton_auto_pictures);
+ int width = bitmap.getWidth();
+ int height = bitmap.getHeight();
+ int newWidth = 55;
+ int newHeight = 55;
+ float widthScale = ((float) newWidth) / width;
+ float heightScale = ((float) newHeight) / height;
+ Matrix matrix = new Matrix();
+ matrix.postScale(widthScale, heightScale);
+ bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
+ return bitmap;
+ }
+
+ /*设置定位图标样式*/
+ private void setLocMarkerStyle(int type) {
+ MyLocationStyle locationStyle = new MyLocationStyle();
+ //LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER
+ locationStyle = locationStyle.myLocationType(type);
+ //创建图标
+ BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(getBitMap());
+ locationStyle.icon(bitmapDescriptor);
+ //设置定位圆形区域的边框宽度;
+ locationStyle.fillColor(getResources().getColor(android.R.color.transparent));
+ locationStyle.strokeWidth(1);
+ tencentMap.setMyLocationStyle(locationStyle);
+ if (LOCATION_TYPE_LOCATION_ROTATE == type) {
+ ivLocation.setEnabled(false);
+ } else {
+ ivLocation.setEnabled(true);
+ }
+ }
+
+ public void benSwitch() {
+ FrameLayout.LayoutParams layoutParamsMap = (FrameLayout.LayoutParams) tvMapView.getLayoutParams();//地图的宽高
+ int heightMap = tvMapView.getMeasuredHeight();
+ int widthMap = tvMapView.getMeasuredWidth();
+ FrameLayout.LayoutParams layoutParamsCamera = (FrameLayout.LayoutParams) camera.getLayoutParams();//相机的宽高
+ int heightCamera = camera.getMeasuredHeight();
+ int widthCamera = camera.getMeasuredWidth();
+ layerChange.removeAllViews();
+ if (widthMap > widthCamera) {
+ layoutParamsCamera.width = widthMap;
+ layoutParamsCamera.height = heightMap;
+ layoutParamsMap.height = heightCamera;
+ layoutParamsMap.width = widthCamera;
+ camera.setLayoutParams(layoutParamsCamera);
+ tvMapView.setLayoutParams(layoutParamsMap);
+ layerChange.addView(camera);
+ layerChange.addView(tvMapView);
+ initMapBig();
+ } else {
+ layoutParamsMap.height = heightCamera;
+ layoutParamsMap.width = widthCamera;
+ layoutParamsCamera.height = heightMap;
+ layoutParamsCamera.width = widthMap;
+ camera.setLayoutParams(layoutParamsCamera);
+ tvMapView.setLayoutParams(layoutParamsMap);
+ layerChange.addView(tvMapView);
+ layerChange.addView(camera);
+ initMapShort();
+ }
+ }
+
+ //小图
+ private void initMapBig() {
+ isMapSlide = false;
+ layerMapController.setVisibility(View.GONE);
+ setLocMarkerStyle(LOCATION_TYPE_LOCATION_ROTATE);
+ // 道路水平方向图标显示
+ ivPicRoadImage.setVisibility(View.VISIBLE);
+ }
+
+ //大图
+ private void initMapShort() {
+ isMapSlide = true;
+ layerMapController.setVisibility(View.VISIBLE);
+ setLocMarkerStyle(LOCATION_TYPE_LOCATION_ROTATE);
+ // 道路水平方向图标不显示
+ ivPicRoadImage.setVisibility(View.GONE);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ tvMapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ camera.open();
+ tvMapView.onResume();
+ camera.setPreviewFrameRate(FRAMENESS);
+// CameraOptions cameraOptions = camera.getCameraOptions();
+// if (FRAMENESS>=cameraOptions.getPreviewFrameRateMinValue()&&FRAMENESS<=cameraOptions.getPreviewFrameRateMaxValue()) {
+// camera.setPreviewFrameRate(FRAMENESS);
+// } else {
+// camera.setPreviewFrameRate(0);
+// }
+ }
+
+ /**
+ * 设置相机的拍照size
+ * */
+ private void initCameraSize() {
+ SizeSelector maxWidth = SizeSelectors.maxWidth(1920);
+ SizeSelector maxHeight = SizeSelectors.maxHeight(1440);
+ SizeSelector minWidth = SizeSelectors.minWidth(1440);
+ SizeSelector minHeight = SizeSelectors.minHeight(1080);
+ SizeSelector maxDimensions = SizeSelectors.and(maxWidth, maxHeight); // Matches sizes bigger than 1000x2000.
+ SizeSelector minDimensions = SizeSelectors.and(minWidth, minHeight); // Matches sizes bigger than 1000x2000.
+ SizeSelector verticalRatio = SizeSelectors.aspectRatio(AspectRatio.of(1080, 1920), 0.2f); // Matches 1:1 sizes.
+ SizeSelector horzentalRatio = SizeSelectors.aspectRatio(AspectRatio.of(1920, 1080), 0.2f); // Matches 1:1 sizes.
+
+ SizeSelector result = SizeSelectors.or(
+ SizeSelectors.and(verticalRatio, maxDimensions, minDimensions), // Try to match both constraints
+ SizeSelectors.and(horzentalRatio, maxDimensions, minDimensions), // Try to match both constraints
+ verticalRatio, // If none is found, at least try to match the aspect ratio
+ horzentalRatio, // If none is found, at least try to match the aspect ratio
+ SizeSelectors.biggest() // If none is found, take the biggest
+ );
+ camera.setPictureSize(result);
+ camera.setPreviewStreamSize(result);
+ /**
+ * app:cameraPictureSizeAspectRatio="1920:1080"
+ * app:cameraPictureSizeBiggest="true"
+ * app:cameraPictureSizeMaxArea="3686400"
+ * app:cameraPictureSizeMaxHeight="1920"
+ * app:cameraPictureSizeMaxWidth="1920"
+ * app:cameraPictureSizeMinArea="1166400"
+ * app:cameraPictureSizeMinHeight="1080"
+ * app:cameraPictureSizeMinWidth="1080"
+ * app:cameraPictureSizeSmallest="true"
+ * */
+ }
+
+ @Override
+ protected void onRestart() {
+ super.onRestart();
+ this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ tvMapView.onRestart();
+ }
+
+ @Override
+ public void onSaveInstanceState(@NonNull Bundle outState) {
+ super.onSaveInstanceState(outState);
+ Message obtain = Message.obtain();
+ obtain.what = Constant.PICTURE_VIDEO_WORD;
+ obtain.obj = true;
+ EventBus.getDefault().post(obtain);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ tvMapView.onPause();
+ camera.close();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ tvMapView.onStop();
+ }
+
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ stopRecordLocation();
+ camera.destroy();
+ tvMapView.onDestroy();
+ trackLocRemovables.stream().forEach(it->it.remove());
+ trackLocRemovables.clear();
+ if (EventBus.getDefault().isRegistered(this)) {
+ EventBus.getDefault().unregister(this);
+ }
+ if (roadMatchEntityList!=null&&!roadLinkEntityList.isEmpty()) {
+ // roadMatchEntity已匹配数据如果存在,缓存
+ SharedPreferences.Editor editor = getSharedPreferences("MatchEntity", Context.MODE_PRIVATE).edit();
+ Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
+ editor.putString("match-data", gson.toJson(roadMatchEntityList));
+ editor.commit();
+ }
+ if (mediaPlayer!=null) {
+ mediaPlayer.release();
+ }
+ // 退出后切换主定位模式为腾讯定位
+ LocationLifeCycle.getInstance().setMainLocationFrom(LocationLifeCycle.LOCATION_FROM.TENCENT);
+ LocationLifeCycle.getInstance().stopGPSLocation();
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (finishTaskCount>0) {
+ MessageDialog.show("提示", "后台正在处理已拍摄完成的任务,请稍后再退出当前界面");
+ wantBack = true;
+ return;
+ }
+ MessageDialog.show("提示", "退出自动采集模式?", "是", "否")
+ .setOkButton(new OnDialogButtonClickListener() {
+ @Override
+ public boolean onClick(BaseDialog baseDialog, View v) {
+ stopRecordLocation();
+ Observable.create(new ObservableOnSubscribe() {
+ @Override
+ public void subscribe(ObservableEmitter emitter) throws Exception {
+ // 查询所有已领取的任务,在返回前全部自动取消领取这些任务
+ List receivedPoiEntityList = poiDao.getPoiEntityByTaskStatus(1, 4);
+ if (receivedPoiEntityList!=null&&!receivedPoiEntityList.isEmpty()) {
+ receivedPoiEntityList.stream().forEach(poiEntity -> {
+ emitter.onNext(poiEntity);
+ });
+ }
+ emitter.onComplete();
+ }
+ }).subscribeOn(Schedulers.io())
+ .flatMap(
+ poiEntity -> {
+ if (poiEntity!=null) {
+ return sendCancelRequest(poiEntity);
+ } else {
+ return Observable.empty();
+ }
+ }
+ )
+ .filter(poiEntity -> poiEntity!=null)
+ .observeOn(AndroidSchedulers.mainThread())
+ .doFinally(new Action() {
+ @Override
+ public void run() throws Exception {
+ showLoadingDialog("正在删除缓存照片...");
+ }
+ })
+ .observeOn(Schedulers.io())
+ .doOnComplete(new Action() {
+ @Override
+ public void run() throws Exception {
+ // 删除缓存目录
+ FileUtils.deleteFile(tmpPicFoldPath);
+ }
+ })
+ .observeOn(AndroidSchedulers.mainThread())
+ .doFinally(new Action() {
+ @Override
+ public void run() throws Exception {
+ showLoadingDialog("正在删除缓存照片...");
+ }
+ })
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ showLoadingDialog("正在取消已领取的任务...");
+ }
+
+ @Override
+ public void onNext(PoiEntity o) {
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ Toast.makeText(AutoTakePicture4PoiVideoActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
+ AutoTakePicture4PoiVideoActivity.this.finish();
+ }
+
+ @Override
+ public void onComplete() {
+// // 重新刷新地图
+// initRoadLine2Map();
+ // 通知主界面刷新
+ Message obtains = Message.obtain();
+ obtains.what = Constant.JOB_WORD_MONITOR;
+ obtains.obj = true;
+ EventBus.getDefault().post(obtains);
+
+ dismissLoadingDialog();
+ // 执行结束后清空已匹配列表
+ roadMatchEntityList.clear();
+ AutoTakePicture4PoiVideoActivity.this.finish();
+ }
+ });
+ return false;
+ }
+ });
+ }
+
+ /**
+ * 添加轨迹点
+ */
+ public void addTrackMarker() {
+ LatLng latLng = null;
+ latLng = new LatLng(LocationLifeCycle.getInstance().getMainLocation().getLatitude(), LocationLifeCycle.getInstance().getMainLocation().getLongitude());
+// if (GPSUtils.getInstance(AutoTakePictureActivity.this).getSateliteCount() != 0) {
+// latLng = new LatLng(LocationLifeCycle.getInstance().getMainLocation().getLatitude(), LocationLifeCycle.getInstance().getMainLocation().getLongitude());
+// } else {
+// if (gpsLocation == null) {
+// latLng = new LatLng(LocationLifeCycle.getInstance().getMainLocation().getLatitude(), LocationLifeCycle.getInstance().getMainLocation().getLongitude());
+// } else {
+// double[] doubles = Gps.toGCJ02Point(gpsLocation.getLatitude(), gpsLocation.getLongitude());
+// latLng = new LatLng(doubles[0],doubles[1]);
+// }
+// }
+ Marker marker = tencentMap.addMarker(new MarkerOptions(latLng)
+ .icon(pileDescriptor)
+ .alpha(0.9f)
+ .flat(true)
+ .clockwise(false));
+ trackLocRemovables.add(marker);
+ }
+
+ // 设置当前界面亮度
+ private void setWindowBrightness(int brightness) {
+// Window window = getWindow();
+// WindowManager.LayoutParams lp = window.getAttributes();
+// lp.screenBrightness = brightness / 255.0f;
+// window.setAttributes(lp);
+ }
+
+
+ private Handler handler = new Handler(new Handler.Callback() {
+ @Override
+ public boolean handleMessage(@NonNull Message msg) {
+ if (msg.what == 0x101) {
+ System.out.println("收到拍照按钮请求");
+ camera.takePictureSnapshot();
+ handler.sendEmptyMessageDelayed(0x101, 500);
+ } else if (msg.what == 0x102) {
+ } else if (msg.what == 0x103) {
+ RoadMatchEntity roadMatchEntity = (RoadMatchEntity) msg.obj;
+ receiverRoadTask(roadMatchEntity).subscribe(receiveObserver);
+ } else if (msg.what == 0x104) {
+ PoiEntity poiEntity = (PoiEntity) msg.obj;
+ try {
+ roadSaveWork(poiEntity);
+ } catch (Exception e) {
+
+ }
+ } else if (msg.what == 0x105) { // 测试用例,当用户点击地图时,会自动返回当前点击位置
+ if (locationEnable) {
+ return false;
+ }
+ TencentLocation tencentLocation = (TencentLocation) msg.obj;
+ if (tencentMap != null && !isMapSlide) {
+ CameraUpdate cameraSigma = CameraUpdateFactory.newCameraPosition(new CameraPosition(
+ new LatLng(tencentLocation.getLatitude(), tencentLocation.getLongitude()), //中心点坐标,地图目标经纬度
+ 17, //目标缩放级别
+ 0, //目标倾斜角
+ 0)); //目标旋转角 0~360° (正北方为0)
+ tencentMap.animateCamera(cameraSigma);
+ }
+ // 判断当前点位和上一个点位的距离,如果距离过近,忽略该点
+ Point currentPoint = (Point) GeometryTools.createGeometry(new LatLng(tencentLocation.getLatitude(), tencentLocation.getLongitude()));
+ if (lastPositionPoint!=null&&lastPositionPoint.distance(currentPoint)<3e-7) { // 如果当前点小于最小距离阈值,过滤该数据
+ return false;
+ }
+ lastPositionPoint = currentPoint;
+ startMatchRoadLink(currentPoint);
+ } else if (msg.what == 0x106) {
+ PoiEntity poiEntity = (PoiEntity) msg.obj;
+ try {
+ sendCancelRequest(poiEntity).subscribe(new Observer() {
+ @Override
+ public void onSubscribe(Disposable d) {
+
+ }
+
+ @Override
+ public void onNext(PoiEntity poiEntity) {
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+
+ }
+
+ @Override
+ public void onComplete() {
+
+ }
+ });
+ } catch (Exception e) {
+
+ }
+ }
+ return false;
+ }
+ });
+
+ private double[] getSpeedAndBearing(Point currentPoint) {
+ double[] speedAndBearing = new double[2];
+
+ double bearing = 0;
+// if (Constant.currentLocation.getDirection() != 0) {
+// bearing = (float) Constant.currentLocation.getDirection();
+// } else {
+// // 使用上一个点和当前点位的向量计算方向
+// if (oldCurrentLocation!=null&&oldCurrentLocation.getLatitude()!=Constant.currentLocation.getLatitude()&&oldCurrentLocation.getLongitude()!=Constant.currentLocation.getLongitude()) {
+// bearing = getBearing(oldCurrentLocation.getLongitude(), Constant.currentLocation.getLongitude(), oldCurrentLocation.getLatitude(), Constant.currentLocation.getLatitude());
+// }
+// }
+ // 使用上一个点和当前点位的向量计算方向
+ if (oldCurrentLocation!=null&&oldCurrentLocation.getX()!=currentPoint.getX()&&oldCurrentLocation.getY()!=currentPoint.getY()) {
+ bearing = getBearing(oldCurrentLocation.getX(), currentPoint.getX(), oldCurrentLocation.getY(), currentPoint.getY());
+ }
+
+ float speed = LocationLifeCycle.getInstance().getMainLocation().getSpeed();//米/秒
+ if (speed != 0) {
+ speed = (speed * 3600 / 1000);//km/h
+ } else {
+ if (oldCurrentLocation != null) {
+ LatLng startLatLng = new LatLng(oldCurrentLocation.getY(), oldCurrentLocation.getX());//旧的坐标
+ LatLng endLatLng = new LatLng(currentPoint.getY(), currentPoint.getX());//新的坐标
+ double geometry = GeometryTools.distanceToDouble(startLatLng, endLatLng);//米
+ speed = (float) (geometry * 3600 / 1000);
+ }
+ }
+ oldCurrentLocation = currentPoint;
+ speedAndBearing[0] = speed;
+ speedAndBearing[1] = bearing;
+
+ return speedAndBearing;
+ }
+
+ private double getBearing(double startLongitude, double endLongitude, double startLatitude, double endLatitude) {
+ double x = endLongitude - startLongitude;
+ double y = endLatitude - startLatitude;
+ double angle = Math.atan(x / y)*180/Math.PI;
+ if((x>0&&y<0)||(x<0&&y<0)){
+ angle=angle+180;
+ }
+ angle = (angle+720)%360;
+ return angle;
+ }
+
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void onEventMessageMainThread(Message msg) {
+ if (msg.what == Constant.EVENT_WHAT_LOCATION_CHANGE) { // 用户位置更新
+ if (!locationEnable) {
+ write2Log("onEventMessageMainThread", "关闭了获取GPS定位开关");
+ return;
+ }
+ TencentLocation tencentLocation = (TencentLocation) msg.obj;
+// if (tencentMap != null && ivLocation!=null && !ivLocation.isEnabled()) { // 当定位按钮禁用,
+// CameraUpdate cameraSigma = CameraUpdateFactory.newCameraPosition(new CameraPosition(
+// new LatLng(tencentLocation.getLatitude(), tencentLocation.getLongitude()), //中心点坐标,地图目标经纬度
+// 17, //目标缩放级别
+// 0, //目标倾斜角
+// 0)); //目标旋转角 0~360° (正北方为0)
+// tencentMap.animateCamera(cameraSigma);
+// }
+ // 判断当前点位和上一个点位的距离,如果距离过近,忽略该点
+ Point currentPoint = (Point) GeometryTools.createGeometry(new LatLng(tencentLocation.getLatitude(), tencentLocation.getLongitude()));
+ if (lastPositionPoint!=null&&lastPositionPoint.distance(currentPoint)<5e-7) { // 如果当前点小于最小距离阈值,过滤该数据
+ write2Log("onEventMessageMainThread", "距离上一点位距离过近:currentPoint-"+currentPoint.toString()+"lastPositionPoint:"+lastPositionPoint.toString());
+ return;
+ }
+ lastPositionPoint = currentPoint;
+ startMatchRoadLink(currentPoint);
+ }
+ }
+ private void write2Log(String tag, String log) {
+ if (logger == null) {
+ Printer filePrinter = new FilePrinter // 打印日志到文件的打印器
+ .Builder(Constant.LOG_FOLDER) // 指定保存日志文件的路径
+ .fileNameGenerator(new DateFileNameGenerator() {
+ ThreadLocal mLocalDateFormat = new ThreadLocal() {
+
+ @Override
+ protected SimpleDateFormat initialValue() {
+ return new SimpleDateFormat("yyyy-MM-dd", Locale.US);
+ }
+ };
+ @Override
+ public boolean isFileNameChangeable() {
+ return true;
+ }
+
+ @Override
+ public String generateFileName(int logLevel, long timestamp) {
+ SimpleDateFormat sdf = mLocalDateFormat.get();
+ sdf.setTimeZone(TimeZone.getDefault());
+ return "AutoTakePicture-"+sdf.format(new Date(timestamp));
+ }
+ }) // 指定日志文件名生成器,默认为 ChangelessFileNameGenerator("log")
+ .flattener(new ClassicFlattener())
+ .build();
+ logger = XLog.printers(filePrinter).build();
+ }
+ logger.v(null, tag, log);
+ }
+}
\ No newline at end of file
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 7520939..5316df4 100644
--- a/app/src/main/java/com/navinfo/outdoor/activity/AutoTakePictureActivity.java
+++ b/app/src/main/java/com/navinfo/outdoor/activity/AutoTakePictureActivity.java
@@ -49,12 +49,11 @@ import com.github.lazylibrary.util.NetWorkUtils;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
-import com.kongzue.dialog.interfaces.OnDialogButtonClickListener;
-import com.kongzue.dialog.util.BaseDialog;
-import com.kongzue.dialog.util.DialogSettings;
-import com.kongzue.dialog.v3.CustomDialog;
-import com.kongzue.dialog.v3.MessageDialog;
-import com.kongzue.dialog.v3.WaitDialog;
+import com.kongzue.dialogx.dialogs.CustomDialog;
+import com.kongzue.dialogx.dialogs.MessageDialog;
+import com.kongzue.dialogx.interfaces.BaseDialog;
+import com.kongzue.dialogx.interfaces.OnBindView;
+import com.kongzue.dialogx.interfaces.OnDialogButtonClickListener;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.model.HttpParams;
import com.navinfo.outdoor.R;
@@ -269,7 +268,6 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
EventBus.getDefault().register(this);
}
- this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
layerChange = findViewById(R.id.layer_change);
systemTTS = SystemTTS.getInstance(AutoTakePictureActivity.this);
tvMapView = findViewById(R.id.text_map_view);
@@ -361,7 +359,7 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
btnSetting.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- CustomDialog.show(AutoTakePictureActivity.this, R.layout.camera_setting, new CustomDialog.OnBindView() {
+ CustomDialog.show(new OnBindView(R.layout.camera_setting) {
@Override
public void onBind(CustomDialog dialog, View v) {
EditText startDistance = v.findViewById(R.id.edt_camera_setting_start_distance);
@@ -405,7 +403,7 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
MATCH_CONFIRM_FINISH_BUFFER = Float.parseFloat(matchPecent.getText().toString());
}
Toast.makeText(AutoTakePictureActivity.this, "设置完成", Toast.LENGTH_SHORT).show();
- dialog.doDismiss();
+ dialog.dismiss();
}
});
}
@@ -1406,18 +1404,19 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
if (hasError) {
dialogMessage.append("(注意,其中有部分任务处理失败)");
}
- MessageDialog.show(AutoTakePictureActivity.this, "退出当前界面", dialogMessage)
- .setOkButton("确定", new OnDialogButtonClickListener() {
+ MessageDialog.show("退出当前界面", dialogMessage)
+ .setOkButton("确定", new OnDialogButtonClickListener() {
@Override
- public boolean onClick(BaseDialog baseDialog, View v) {
+ public boolean onClick(MessageDialog dialog, View v) {
+ dialog.dismiss();
AutoTakePictureActivity.this.finish();
return false;
}
})
- .setCancelButton("取消", new OnDialogButtonClickListener() {
+ .setCancelButton("取消", new OnDialogButtonClickListener() {
@Override
- public boolean onClick(BaseDialog baseDialog, View v) {
- baseDialog.doDismiss();
+ public boolean onClick(MessageDialog dialog, View v) {
+ dialog.dismiss();
wantBack = false;
return false;
}
@@ -1732,13 +1731,13 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
@Override
public void onBackPressed() {
- DialogSettings.style = DialogSettings.STYLE.STYLE_IOS;
if (finishTaskCount>0) {
- MessageDialog.show(this, "提示", "后台正在处理已拍摄完成的任务,请稍后再退出当前界面");
+ MessageDialog.show("提示", "后台正在处理已拍摄完成的任务,请稍后再退出当前界面");
wantBack = true;
return;
}
- MessageDialog.show(this, "提示", "退出自动采集模式?", "是", "否").setOnOkButtonClickListener(new OnDialogButtonClickListener() {
+ MessageDialog.show("提示", "退出自动采集模式?", "是", "否")
+ .setOkButton(new OnDialogButtonClickListener() {
@Override
public boolean onClick(BaseDialog baseDialog, View v) {
stopRecordLocation();
diff --git a/app/src/main/java/com/navinfo/outdoor/api/UserApplication.java b/app/src/main/java/com/navinfo/outdoor/api/UserApplication.java
index c355cf1..6508fae 100644
--- a/app/src/main/java/com/navinfo/outdoor/api/UserApplication.java
+++ b/app/src/main/java/com/navinfo/outdoor/api/UserApplication.java
@@ -10,6 +10,9 @@ import android.util.Log;
import androidx.lifecycle.ProcessLifecycleOwner;
+import com.kongzue.dialogx.DialogX;
+import com.kongzue.dialogx.style.MIUIStyle;
+import com.kongzue.dialogx.style.MaterialStyle;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.cache.CacheEntity;
import com.lzy.okgo.cache.CacheMode;
@@ -62,7 +65,10 @@ public class UserApplication extends Application {
config.setDeviceId(deviceID);
// 或者设置开发者自己的的设备号config.setDeviceId(xxxxxxxx);
TencentNavi.init(this, config);
-
+ // 初始化对话框组件
+ DialogX.init(this);
+ DialogX.globalStyle = new MIUIStyle();
+ DialogX.globalTheme = DialogX.THEME.LIGHT;
}
public static UserApplication getUserApplication() {
diff --git a/app/src/main/java/com/navinfo/outdoor/base/BaseFragment.java b/app/src/main/java/com/navinfo/outdoor/base/BaseFragment.java
index 4bfb675..5a49bee 100644
--- a/app/src/main/java/com/navinfo/outdoor/base/BaseFragment.java
+++ b/app/src/main/java/com/navinfo/outdoor/base/BaseFragment.java
@@ -23,15 +23,8 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import com.navinfo.outdoor.R;
-import com.kongzue.dialog.interfaces.OnBackClickListener;
-import com.kongzue.dialog.v3.WaitDialog;
-import com.navinfo.outdoor.R;
-import com.navinfo.outdoor.activity.HomeActivity;
import com.navinfo.outdoor.activity.WebActivity;
-import com.navinfo.outdoor.http.HttpInterface;
-import com.navinfo.outdoor.util.BackHandlerHelper;
import com.navinfo.outdoor.util.FragmentBackHandler;
-import com.navinfo.outdoor.util.NetWorkUtils;
import java.util.HashMap;
import java.util.Map;
@@ -82,7 +75,7 @@ public abstract class BaseFragment extends Fragment implements FragmentBackHandl
}
protected T findViewById(@IdRes int id) {
- return Objects.requireNonNull(getView()).findViewById(id);
+ return requireView().findViewById(id);
}
protected void debounce(View view) {
@@ -99,7 +92,7 @@ public abstract class BaseFragment extends Fragment implements FragmentBackHandl
if (alertDialog != null) {
alertDialog.dismiss();
}
- alertDialog = new AlertDialog.Builder(Objects.requireNonNull(getActivity())).create();
+ alertDialog = new AlertDialog.Builder(requireActivity()).create();
Objects.requireNonNull(alertDialog.getWindow()).setBackgroundDrawable(new ColorDrawable());
alertDialog.setCancelable(false);
alertDialog.setOnKeyListener((dialog, keyCode, event) -> {
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 205d902..d9f3799 100644
--- a/app/src/main/java/com/navinfo/outdoor/fragment/TreasureFragment.java
+++ b/app/src/main/java/com/navinfo/outdoor/fragment/TreasureFragment.java
@@ -53,9 +53,13 @@ import com.kongzue.dialog.util.BaseDialog;
import com.kongzue.dialog.util.DialogSettings;
import com.kongzue.dialog.v3.MessageDialog;
import com.kongzue.dialog.v3.ShareDialog;
+import com.kongzue.dialogx.dialogs.PopMenu;
+import com.kongzue.dialogx.interfaces.OnIconChangeCallBack;
+import com.kongzue.dialogx.interfaces.OnMenuItemClickListener;
import com.lzy.okgo.model.HttpParams;
import com.lzy.okgo.model.Progress;
import com.navinfo.outdoor.R;
+import com.navinfo.outdoor.activity.AutoTakePicture4PoiVideoActivity;
import com.navinfo.outdoor.activity.AutoTakePictureActivity;
import com.navinfo.outdoor.activity.FragmentManagement;
import com.navinfo.outdoor.activity.WebActivity;
@@ -313,8 +317,37 @@ public class TreasureFragment extends BaseFragment implements View.OnClickListen
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void onClick(View v) {
- Intent autoMatchIntent = new Intent(getContext(), AutoTakePictureActivity.class);
- startActivity(autoMatchIntent);
+ PopMenu.show(v, new String[]{"道路任务", "POI录像"})
+ .setOverlayBaseView(true)
+ .setAlignGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL)
+ .setOnIconChangeCallBack(new OnIconChangeCallBack() {
+ @Override
+ public int getIcon(PopMenu dialog, int index, String menuText) {
+ switch (index){
+ case 0:
+ return R.drawable.marker_road_show;
+ case 1:
+ return R.drawable.marker_poi_video_show;
+ default:
+ break;
+ }
+ return 0;
+ }
+ })
+ .setOnMenuItemClickListener(new OnMenuItemClickListener() {
+ @Override
+ public boolean onClick(PopMenu dialog, CharSequence text, int index) {
+ if (index == 0) { // 自动捕捉道路任务
+ Intent autoMatchIntent = new Intent(getContext(), AutoTakePictureActivity.class);
+ startActivity(autoMatchIntent);
+ } else if (index == 1) {
+ Intent autoMatchIntent = new Intent(getContext(), AutoTakePicture4PoiVideoActivity.class);
+ startActivity(autoMatchIntent);
+ }
+ return false;
+ }
+ });
+
// // 设置亮度和摄像机刷新率
// CustomDialog.show((AppCompatActivity) getActivity(), R.layout.camera_setting_pre, new CustomDialog.OnBindView() {
// @Override
diff --git a/app/src/main/res/layout/activity_picture.xml b/app/src/main/res/layout/activity_picture.xml
index 119113d..db5459d 100644
--- a/app/src/main/res/layout/activity_picture.xml
+++ b/app/src/main/res/layout/activity_picture.xml
@@ -132,7 +132,7 @@
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@+id/btn_switch"
- android:background="@color/whiteAlpha50"
+ android:background="@color/white50"
android:padding="@dimen/default_widget_padding"
android:textColor="@color/colorRead"
android:format="00:00:00"
diff --git a/app/src/main/res/layout/camera_setting.xml b/app/src/main/res/layout/camera_setting.xml
index 7a23c59..a67b3e1 100644
--- a/app/src/main/res/layout/camera_setting.xml
+++ b/app/src/main/res/layout/camera_setting.xml
@@ -2,7 +2,7 @@