From 54358b2ef0921463c59071fb0ee5a36fb7781f0f Mon Sep 17 00:00:00 2001
From: xiaoyan <xiaoyan159@163.com>
Date: Tue, 21 Feb 2023 15:11:12 +0800
Subject: [PATCH] =?UTF-8?q?fix:=20=E5=A2=9E=E5=8A=A0=E5=AF=B9=E8=AF=9D?=
 =?UTF-8?q?=E6=A1=86=E4=BE=9D=E8=B5=96=E4=B8=BADialogX?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 app/build.gradle                              |   23 +-
 app/src/main/AndroidManifest.xml              |    5 +
 .../AutoTakePicture4PoiVideoActivity.java     | 1987 +++++++++++++++++
 .../activity/AutoTakePictureActivity.java     |   35 +-
 .../navinfo/outdoor/api/UserApplication.java  |    8 +-
 .../navinfo/outdoor/base/BaseFragment.java    |   11 +-
 .../outdoor/fragment/TreasureFragment.java    |   37 +-
 app/src/main/res/layout/activity_picture.xml  |    2 +-
 app/src/main/res/layout/camera_setting.xml    |    2 +-
 .../main/res/layout/camera_setting_pre.xml    |    2 +-
 xrecyclerview/build.gradle                    |    6 +-
 11 files changed, 2075 insertions(+), 43 deletions(-)
 create mode 100644 app/src/main/java/com/navinfo/outdoor/activity/AutoTakePicture4PoiVideoActivity.java

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 @@
         <activity
             android:name=".activity.VideoActivity"
             android:screenOrientation="portrait" /> <!-- 自动拍照界面 -->
+        <!-- 自动捕捉道路任务 -->
         <activity
             android:name=".activity.AutoTakePictureActivity"
+            android:screenOrientation="landscape" />
+        <!-- 自动捕捉POI录像任务 -->
+        <activity
+            android:name=".activity.AutoTakePicture4PoiVideoActivity"
             android:screenOrientation="portrait" />
         <activity
             android:name=".activity.UserActivity"
diff --git a/app/src/main/java/com/navinfo/outdoor/activity/AutoTakePicture4PoiVideoActivity.java b/app/src/main/java/com/navinfo/outdoor/activity/AutoTakePicture4PoiVideoActivity.java
new file mode 100644
index 0000000..b567c99
--- /dev/null
+++ b/app/src/main/java/com/navinfo/outdoor/activity/AutoTakePicture4PoiVideoActivity.java
@@ -0,0 +1,1987 @@
+package com.navinfo.outdoor.activity;
+
+import static com.tencent.tencentmap.mapsdk.maps.model.MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.ActivityInfo;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
+import android.media.MediaPlayer;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.CompoundButton;
+import android.widget.EditText;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.Switch;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+
+import com.elvishew.xlog.Logger;
+import com.elvishew.xlog.XLog;
+import com.elvishew.xlog.flattener.ClassicFlattener;
+import com.elvishew.xlog.printer.Printer;
+import com.elvishew.xlog.printer.file.FilePrinter;
+import com.elvishew.xlog.printer.file.naming.DateFileNameGenerator;
+import com.github.lazylibrary.util.FileUtils;
+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.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.model.HttpParams;
+import com.navinfo.outdoor.R;
+import com.navinfo.outdoor.api.Constant;
+import com.navinfo.outdoor.base.BaseActivity;
+import com.navinfo.outdoor.bean.JobSearchBean;
+import com.navinfo.outdoor.bean.LocationRecorder;
+import com.navinfo.outdoor.bean.RoadMatchEntity;
+import com.navinfo.outdoor.bean.RoadSaveBean;
+import com.navinfo.outdoor.bean.TaskByNetBean;
+import com.navinfo.outdoor.bean.UnPolygonTaskBean;
+import com.navinfo.outdoor.http.HttpInterface;
+import com.navinfo.outdoor.http.OkGoBuilder;
+import com.navinfo.outdoor.room.InsertAndUpdateUtils;
+import com.navinfo.outdoor.room.LocationRecorderDao;
+import com.navinfo.outdoor.room.PoiDao;
+import com.navinfo.outdoor.room.PoiDatabase;
+import com.navinfo.outdoor.room.PoiEntity;
+import com.navinfo.outdoor.util.FlushTokenUtil;
+import com.navinfo.outdoor.util.GPSUtils;
+import com.navinfo.outdoor.util.Geohash;
+import com.navinfo.outdoor.util.GeometryTools;
+import com.navinfo.outdoor.util.LocationLifeCycle;
+import com.navinfo.outdoor.util.MyLocation;
+import com.navinfo.outdoor.util.MyTecentLocationSource;
+import com.navinfo.outdoor.util.NaviUtils;
+import com.navinfo.outdoor.util.SystemTTS;
+import com.navinfo.outdoor.util.TencentLocationObtain;
+import com.navinfo.outdoor.util.TencentMarkerUtils;
+import com.navinfo.outdoor.util.ToastUtils;
+import com.otaliastudios.cameraview.CameraListener;
+import com.otaliastudios.cameraview.CameraLogger;
+import com.otaliastudios.cameraview.CameraView;
+import com.otaliastudios.cameraview.FileCallback;
+import com.otaliastudios.cameraview.PictureResult;
+import com.otaliastudios.cameraview.controls.Mode;
+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.TencentNaviCallback;
+import com.tencent.map.navi.TencentNaviManager;
+import com.tencent.map.navi.TencentRouteSearchCallback;
+import com.tencent.map.navi.data.AttachedLocation;
+import com.tencent.map.navi.data.CalcRouteResult;
+import com.tencent.map.navi.data.IdleRangeInfo;
+import com.tencent.map.navi.data.NaviPoi;
+import com.tencent.map.navi.data.NaviTts;
+import com.tencent.map.navi.data.ParallelRoadStatus;
+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;
+import com.tencent.tencentmap.mapsdk.maps.TextureMapView;
+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.CameraPosition;
+import com.tencent.tencentmap.mapsdk.maps.model.LatLng;
+import com.tencent.tencentmap.mapsdk.maps.model.Marker;
+import com.tencent.tencentmap.mapsdk.maps.model.MarkerOptions;
+import com.tencent.tencentmap.mapsdk.maps.model.MyLocationStyle;
+import com.tencent.tencentmap.mapsdk.maps.model.Polyline;
+import com.tencent.tencentmap.mapsdk.maps.model.TencentMapGestureListener;
+
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.geom.LineString;
+import org.locationtech.jts.geom.Point;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.TimeZone;
+import java.util.stream.Collectors;
+
+import io.reactivex.Observable;
+import io.reactivex.ObservableEmitter;
+import io.reactivex.ObservableOnSubscribe;
+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.Function;
+import io.reactivex.schedulers.Schedulers;
+import okhttp3.Response;
+
+/**
+ * 拍照
+ * (poi录像 和 道路)
+ */
+@RequiresApi(api = Build.VERSION_CODES.N)
+public class AutoTakePicture4PoiVideoActivity extends BaseActivity implements View.OnClickListener {
+    private static final CameraLogger LOG = CameraLogger.create("AutoTakePictureActivity");
+    private CameraView camera;
+    private TencentMap tencentMap;
+    private TextureMapView tvMapView;
+    private SystemTTS systemTTS;
+    private List<Removable> 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<Removable> removables; // 地图上渲染的网络获取的道路任务
+    private List<Removable> removablesLocality; // 地图上渲染的本地道路任务
+    private HashMap<String, List<Marker>> removableHashMap;
+    private List<RoadMatchEntity> 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<PoiEntity>() {
+                        @Override
+                        public void accept(PoiEntity poiEntity) throws Exception {
+
+                        }
+                    }, new Consumer<Throwable>() {
+                                @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<CustomDialog>(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<LocationRecorder>() {
+                                    @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<RoadMatchEntity> dataList = gson.fromJson(matchedData, new TypeToken<List<RoadMatchEntity>>(){}.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<PoiEntity>() {
+                @Override
+                public void onMarkerInit(Map<String, List<Marker>> removableHashMap, List<Integer> uploadByNet, List<PoiEntity> listData) {
+
+                }
+            });
+        }
+        if (LocationLifeCycle.getInstance().getMainLocation() != null) { //筛选从服务器获取到的数据
+            // 注意,此处只获取道路数据
+            tencentMarkerUtils.initNetMarkerList(AutoTakePicture4PoiVideoActivity.this, LocationLifeCycle.getInstance().getTencentLocation(), tencentMap, removables,
+                    "3"/*只获取poi录像数据*/,"0"/*只获取未领取的数据*/, removableHashMap, 50, new TencentMarkerUtils.MarkerInitCallback<JobSearchBean.BodyBean.ListBean>() {
+
+                @Override
+                public void onMarkerInit(Map<String, List<Marker>> removableHashMap, List<Integer> uploadByNet,
+                                         List<JobSearchBean.BodyBean.ListBean> 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<PoiEntity>() {
+        @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<RoadMatchEntity> matchStartList = roadLinkEntityList.stream()
+                // 筛选当前任务与起点距离
+                .filter(it-> {
+                    if (GeometryTools.createGeometry(it.getsPoint()).distance(currentPoint)<MATCH_START_BUFFER_DISTANCE) {
+                        return true;
+                    } else {
+                        return false;
+                    }
+                })
+                // 筛选方向
+                .filter(it-> {
+                    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<RoadMatchEntity> unMatchList = new ArrayList<>();
+            Map<Integer, RoadMatchEntity> 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,说明该数据已经匹配到终点*/&&currentEndDistance>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<MyCoordinate> 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<PoiEntity>() {
+                    @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<RoadMatchEntity>() {
+                            @Override
+                            public void subscribe(ObservableEmitter<RoadMatchEntity> 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)<currentGeometry.distance(geometry2)) {
+                                                return -1;
+                                            }
+                                            return 0;
+                                        }).get();
+                                emitter.onNext(minRoadLink);
+                                emitter.onComplete();
+                            }
+                        }
+                )
+                .subscribeOn(Schedulers.computation())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(new Consumer<RoadMatchEntity>() {
+                    @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<RouteData> 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<RouteData> 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<LatLng> 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<PoiEntity> receiverRoadTask(RoadMatchEntity entity) {
+        write2Log("开始领取任务:", entity.getId()+"");
+        return Observable.just(entity).subscribeOn(Schedulers.io()).observeOn(Schedulers.computation())
+                .filter(roadMatchEntity -> roadMatchEntity!=null)
+                .map(new Function<RoadMatchEntity, PoiEntity>() {
+                             @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<PoiEntity> cancelReciverTask(List<RoadMatchEntity> 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<PoiEntity> sendCancelRequest(PoiEntity origin) {
+        return Observable.just(origin)
+                .subscribeOn(Schedulers.io()).observeOn(Schedulers.computation())
+                .map(new Function<PoiEntity, PoiEntity>() {
+                    @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<Integer, RoadMatchEntity> 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<LocationRecorder> 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<PoiEntity>() {
+                        @Override
+                        public void accept(PoiEntity poiEntity) {
+//                        // 已经处理过该任务,将其从finish列表中移除
+//                        if (poiEntity!=null) {
+//                            finishEntityMap.remove(poiEntity.getTaskId());
+//                        }
+
+                        }
+                    }, new Consumer<Throwable>() {
+                        @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<MessageDialog>() {
+                    @Override
+                    public boolean onClick(MessageDialog dialog, View v) {
+                        dialog.dismiss();
+                        AutoTakePicture4PoiVideoActivity.this.finish();
+                        return false;
+                    }
+                })
+                .setCancelButton("取消", new OnDialogButtonClickListener<MessageDialog>() {
+                    @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<PoiEntity>() {
+                    @Override
+                    public void subscribe(ObservableEmitter<PoiEntity> emitter) throws Exception {
+                        // 查询所有已领取的任务,在返回前全部自动取消领取这些任务
+                        List<PoiEntity> 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<PoiEntity>() {
+                            @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<PoiEntity>() {
+                        @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<SimpleDateFormat> mLocalDateFormat = new ThreadLocal<SimpleDateFormat>() {
+
+                            @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<CustomDialog>(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<MessageDialog>() {
                     @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<MessageDialog>() {
                     @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 extends View> 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<PopMenu>() {
+                            @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<PopMenu>() {
+                            @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 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="@color/dialogButtonMIUITextGray"
+    android:background="@color/colorGrey"
     android:padding="@dimen/fab_margin"
     android:orientation="vertical">
     <LinearLayout
diff --git a/app/src/main/res/layout/camera_setting_pre.xml b/app/src/main/res/layout/camera_setting_pre.xml
index dc49790..02b1e61 100644
--- a/app/src/main/res/layout/camera_setting_pre.xml
+++ b/app/src/main/res/layout/camera_setting_pre.xml
@@ -2,7 +2,7 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="@color/dialogButtonMIUITextGray"
+    android:background="@color/colorGrey"
     android:padding="@dimen/fab_margin"
     android:orientation="vertical">
     <LinearLayout
diff --git a/xrecyclerview/build.gradle b/xrecyclerview/build.gradle
index 19e9a9c..da5be62 100644
--- a/xrecyclerview/build.gradle
+++ b/xrecyclerview/build.gradle
@@ -2,11 +2,11 @@ apply plugin: 'com.android.library'
 
 
 android {
-    compileSdkVersion 30
-    buildToolsVersion '29.0.2'
+    compileSdkVersion 29
+//    buildToolsVersion '29.0.2'
     defaultConfig {
         minSdkVersion 16
-        targetSdkVersion 30
+        targetSdkVersion 29
         versionCode 1
         versionName "1.0"
     }