feat: 增加批量上传及删除的打点记录

This commit is contained in:
xiaoyan 2023-03-02 18:07:23 +08:00
parent 2b6163fe45
commit baebb9e5cf
8 changed files with 166 additions and 69 deletions

View File

@ -90,6 +90,7 @@ import com.navinfo.outdoor.util.TencentLocationObtain;
import com.navinfo.outdoor.util.TencentMarkerUtils;
import com.navinfo.outdoor.util.TimestampUtil;
import com.navinfo.outdoor.util.ToastUtils;
import com.navinfo.outdoor.util.XLogUtils;
import com.otaliastudios.cameraview.CameraListener;
import com.otaliastudios.cameraview.CameraLogger;
import com.otaliastudios.cameraview.CameraOptions;
@ -236,7 +237,7 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
private ImageView imgNaviDistance/*自动规划到距离最近的数据开关*/, imgRoadDirection; // 道路方向匹配开关
private Polyline currentNaviLine; // 当前界面上正显示的导航路径线重绘路径时需要清除此前已绘制的路径
private boolean startMatchEnableDirection = true; // 是否启用方向匹配起点
private Logger logger;
private Logger logger = XLogUtils.Companion.getInstance().getAutoTakePictureLogWriter();
private ImageView imgLocationType;
@Override
@ -704,14 +705,14 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
@Override
public void onNext(PoiEntity poiEntity) {
write2Log("领取任务成功:", poiEntity.getId());
logger.d("领取任务成功:", poiEntity.getId());
}
@Override
public void onError(Throwable e) {
systemTTS.playText("注意,领取任务失败!");
if (AutoTakePictureActivity.this!=null) {
write2Log("领取任务失败:", e.getMessage()+",网络状态-:"+ NetWorkUtils.getNetworkTypeName(AutoTakePictureActivity.this));
logger.d("领取任务失败:", e.getMessage()+",网络状态-:"+ NetWorkUtils.getNetworkTypeName(AutoTakePictureActivity.this));
}
}
@ -727,7 +728,7 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
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));
logger.d("开始匹配:", "roadLinkEntityList == null:"+(roadLinkEntityList == null)+",currentPoint == null"+(currentPoint == null));
return;
}
double[] speedAndBearing = getSpeedAndBearing(currentPoint);
@ -739,7 +740,7 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
matchMiddleDistance = MATCH_BUFFER_DISTANCE*1.5;
}
// 此处开始匹配起点
write2Log("开始匹配起点位置:", "currentLocation:"+currentPoint.toString()+",可匹配数据个数:"+roadLinkEntityList.size());
logger.d("开始匹配起点位置:", "currentLocation:"+currentPoint.toString()+",可匹配数据个数:"+roadLinkEntityList.size());
List<RoadMatchEntity> matchStartList = roadLinkEntityList.stream()
// 筛选当前任务与起点距离
.filter(it-> {
@ -757,7 +758,7 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
return true;
} else {
// 根据方向判定无法匹配
write2Log("方向不匹配:", "currentBearing:"+currentBearing+",数据角度:"+dataBearing+",数据id:"+it.getDataDetail().getId());
logger.d("方向不匹配:", "currentBearing:"+currentBearing+",数据角度:"+dataBearing+",数据id:"+it.getDataDetail().getId());
return false;
}
} else {
@ -798,7 +799,7 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
// 将匹配到的数据加入到已匹配列表中
roadMatchEntityList.addAll(matchStartList);
} else {
write2Log("匹配起点数据为空:", "当前位置为:"+currentPoint.toString()+"当前角度:"+currentBearing);
logger.d("匹配起点数据为空:", "当前位置为:"+currentPoint.toString()+"当前角度:"+currentBearing);
}
// 尝试用当前位置点匹配已经匹配到的roadLink如果能匹配到需要将该点记录如果无法匹配则需要评估已匹配的link是否需要被剔除
@ -1154,7 +1155,7 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
* 初始化领取任务的管理栈
* */
private Observable<PoiEntity> receiverRoadTask(RoadMatchEntity entity) {
write2Log("开始领取任务:", entity.getId()+"");
logger.d("开始领取任务:", entity.getId()+"");
return Observable.just(entity).subscribeOn(Schedulers.io()).observeOn(Schedulers.computation())
.filter(roadMatchEntity -> roadMatchEntity!=null)
.map(new Function<RoadMatchEntity, PoiEntity>() {
@ -1203,7 +1204,7 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
}
} else if (taskByNetBean.getCode() == 230) { // Token过期
systemTTS.playText("注意Token过期请重新登陆");
write2Log("领取任务失败:", "Token过期"+taskByNetBean.getMessage());
logger.d("领取任务失败:", "Token过期"+taskByNetBean.getMessage());
FlushTokenUtil.flushToken(AutoTakePictureActivity.this);
Message msg = handler.obtainMessage(0x103);
msg.obj = entity;
@ -1211,7 +1212,7 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
} else {
systemTTS.playText("注意,领取任务失败!");
ToastUtils.Message(AutoTakePictureActivity.this,taskByNetBean.getMessage());
write2Log("领取任务失败:", "领取失败:"+taskByNetBean.getMessage());
logger.d("领取任务失败:", "领取失败:"+taskByNetBean.getMessage());
Message msg = handler.obtainMessage(0x103);
msg.obj = entity;
handler.sendMessageDelayed(msg, 10*1000); // 10秒后重试
@ -1977,7 +1978,7 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
public void onEventMessageMainThread(Message msg) {
if (msg.what == Constant.EVENT_WHAT_LOCATION_CHANGE) { // 用户位置更新
if (!locationEnable) {
write2Log("onEventMessageMainThread", "关闭了获取GPS定位开关");
logger.d("onEventMessageMainThread", "关闭了获取GPS定位开关");
return;
}
TencentLocation tencentLocation = (TencentLocation) msg.obj;
@ -1992,41 +1993,11 @@ public class AutoTakePictureActivity extends BaseActivity implements View.OnClic
// 判断当前点位和上一个点位的距离如果距离过近忽略该点
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());
logger.d("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);
}
}

View File

@ -1,19 +1,5 @@
package com.navinfo.outdoor.activity;
import com.elvishew.xlog.LogConfiguration;
import com.elvishew.xlog.LogLevel;
import com.elvishew.xlog.XLog;
import com.elvishew.xlog.flattener.ClassicFlattener;
import com.elvishew.xlog.printer.AndroidPrinter;
import com.elvishew.xlog.printer.ConsolePrinter;
import com.elvishew.xlog.printer.Printer;
import com.elvishew.xlog.printer.file.FilePrinter;
import com.elvishew.xlog.printer.file.backup.BackupStrategy2;
import com.elvishew.xlog.printer.file.backup.FileSizeBackupStrategy2;
import com.elvishew.xlog.printer.file.backup.NeverBackupStrategy;
import com.elvishew.xlog.printer.file.clean.FileLastModifiedCleanStrategy;
import com.elvishew.xlog.printer.file.naming.DateFileNameGenerator;
import com.elvishew.xlog.printer.file.naming.LevelFileNameGenerator;
import com.github.lazylibrary.util.ShellUtils;
import com.google.gson.Gson;
import com.kongzue.dialog.interfaces.OnDialogButtonClickListener;

View File

@ -147,7 +147,7 @@ public class MainActivity extends BaseActivity {
LogConfiguration logConfiguration = new LogConfiguration.Builder()
// .enableStackTrace(5)
.enableBorder()
// .enableBorder()
.tag("XLog").build();
Printer androidPrinter = new AndroidPrinter(true); // 通过 android.util.Log 打印日志的打印器
Printer consolePrinter = new ConsolePrinter(); // 通过 System.out 打印日志到控制台的打印器

View File

@ -23,6 +23,7 @@ import com.navinfo.outdoor.util.PoiEntityDeleteUtil;
import org.greenrobot.eventbus.EventBus;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
@ -39,6 +40,18 @@ public class StaySubmitAdapter extends RecyclerView.Adapter<StaySubmitAdapter.Vi
return allRoad;
}
public List<PoiEntity> getCheckedPoiEntity() {
List<PoiEntity> poiEntityList = new ArrayList<>();
if (allRoad!=null&&!allRoad.isEmpty()) {
for (PoiEntity poiEntity: allRoad) {
if (poiEntity.isChecked()) {
poiEntityList.add(poiEntity);
}
}
}
return poiEntityList;
}
public void setAllRoad(List<PoiEntity> allRoad) {
this.allRoad.clear();
this.allRoad.addAll(allRoad);

View File

@ -19,6 +19,7 @@ import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.elvishew.xlog.Logger;
import com.github.lazylibrary.util.FileUtils;
import com.kongzue.dialog.interfaces.OnDialogButtonClickListener;
import com.kongzue.dialog.interfaces.OnMenuItemClickListener;
@ -45,6 +46,7 @@ import com.navinfo.outdoor.util.PoiEntityDeleteUtil;
import com.navinfo.outdoor.util.PoiSaveUtils;
import com.navinfo.outdoor.util.TimestampUtil;
import com.navinfo.outdoor.util.ToastUtils;
import com.navinfo.outdoor.util.XLogUtils;
import com.umeng.umcrash.UMCrash;
import org.greenrobot.eventbus.EventBus;
@ -60,6 +62,12 @@ import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
/**
* 记录-待提交的fragment
*/
@ -71,6 +79,7 @@ public class StaySubmitFragment extends BaseFragment implements View.OnClickList
private CheckBox cbSelect;
private File logFile;
private StringBuilder staySubmitBuilder;
private Logger logger = XLogUtils.Companion.getInstance().getUploadLogWriter();
public static StaySubmitFragment newInstance(Bundle bundle) {
StaySubmitFragment fragment = new StaySubmitFragment();
@ -305,6 +314,12 @@ public class StaySubmitFragment extends BaseFragment implements View.OnClickList
});
break;
case R.id.tv_delete:
List<PoiEntity> checkedPoiEntityList = staySubmitAdapter.getCheckedPoiEntity();
if (checkedPoiEntityList == null || checkedPoiEntityList.isEmpty()) {
ToastUtils.Message(getActivity(), "没有勾选任何数据!");
return;
}
logger.d("用户点击批量删除按钮+++++++++++++++++++++++");
staySubmitBuilder.append(TimestampUtil.time()).append(",").append("点击了删除按钮 ,");
if (Constant.isPresent) {
DialogSettings.style = DialogSettings.STYLE.STYLE_IOS;
@ -312,7 +327,8 @@ public class StaySubmitFragment extends BaseFragment implements View.OnClickList
@SuppressLint("SetTextI18n")
@Override
public boolean onClick(BaseDialog baseDialog, View v) {
initRequest(staySubmitAdapter.getAllRoad());
logger.d("用户点击确认批量删除按钮+++++++++++++++++++++++");
initRequest(staySubmitAdapter.getCheckedPoiEntity());
return false;
}
});
@ -322,6 +338,7 @@ public class StaySubmitFragment extends BaseFragment implements View.OnClickList
break;
case R.id.btn_stay_submit://提交
staySubmitBuilder.append(TimestampUtil.time()).append(",").append("点击了提交的按钮 ,");
logger.d("用户点击批量上传提交按钮+++++++++++++++++++++++");
if (Constant.isPresent) {
if (poiEntities == null) {
poiEntities = new ArrayList<>();
@ -348,20 +365,11 @@ public class StaySubmitFragment extends BaseFragment implements View.OnClickList
}
}
private void initRequest(List<PoiEntity> allRoad) {
private void initRequest(List<PoiEntity> poiEntities) {
showLoadingDialog();
new Thread(new Runnable() {
@Override
public void run() {
ArrayList<PoiEntity> poiEntities = new ArrayList<>();
synchronized (allRoad) {
for (PoiEntity poiEntity : allRoad) {
if (poiEntity.isChecked()) {
poiEntities.add(poiEntity);
PoiEntityDeleteUtil.getInstance().deleteUtil(getContext(), poiEntity);
}
}
}
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
@Override
@ -396,7 +404,34 @@ public class StaySubmitFragment extends BaseFragment implements View.OnClickList
public void onSuccess(UnPolygonTaskBean response, int id) {
dismissLoadingDialog();
if (response.getCode() == 200) {
staySubmitAdapter.setAllCheckedDelete();
// 启动线程删除对应的图片文件
Observable.fromIterable(poiEntities)
.subscribeOn(Schedulers.io())
.doOnNext(new Consumer<PoiEntity>() {
@Override
public void accept(PoiEntity poiEntity) throws Exception {
PoiEntityDeleteUtil.getInstance().deleteUtil(getContext(), poiEntity);
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<PoiEntity>() {
@Override
public void accept(PoiEntity poiEntity) throws Exception {
logger.d("数据被删除:"+poiEntity.getId()+"-"+poiEntity.getName()+"-"+poiEntity.getTaskId()+"-"+poiEntity.getBodyId());
}
},
new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
}
},
new Action() { // 最终结束的处理
@Override
public void run() throws Exception {
staySubmitAdapter.setAllCheckedDelete();
}
});
} else if (response.getCode() == 230) {
FlushTokenUtil.flushToken(getActivity());
} else {

View File

@ -2,6 +2,7 @@ package com.navinfo.outdoor.room;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;
import androidx.room.TypeConverters;

View File

@ -5,6 +5,12 @@ import android.os.Message;
import android.util.Log;
import android.widget.Toast;
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.ToastUtils;
import com.github.lazylibrary.util.ZipUtil;
import com.google.gson.Gson;
@ -28,12 +34,16 @@ import org.greenrobot.eventbus.EventBus;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.AbstractMap;
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.function.Predicate;
import java.util.stream.Collectors;
@ -58,6 +68,7 @@ public class PoiSaveUtils {
private int anInt = 0; // 上传成功的个数
private int bInt = 0; // 上传失败的个数
private int uploadCount = 0; // 上传的总个数
private Logger logger = XLogUtils.Companion.getInstance().getUploadLogWriter();
public static PoiSaveUtils getInstance(Activity mContext) {
if (instance == null) {
@ -76,12 +87,14 @@ public class PoiSaveUtils {
*/
public void uploadPoiEntityBatch(List<PoiEntity> poiEntityList) {
if (poiEntityList != null&&!poiEntityList.isEmpty()) {
logger.d("开始批量上传-------------------------共"+poiEntityList.size()+"");
// 因为道路任务和POI录像任务需要分包提交因此和其他要素分开分别放在两个管道里
List<Map.Entry<Integer, PoiEntity>> chargePoiEntityList = new ArrayList<>();/*充电站POI列表*/
List<Map.Entry<Integer, PoiEntity>> spliteFilePoiEntityList = new ArrayList<>();/*充电站POI列表*/
List<Map.Entry<Integer, PoiEntity>> otherPoiEntityList = new ArrayList<>();/*充电站POI列表*/
for (int i = 0; i < poiEntityList.size(); i++) {
PoiEntity poiEntity = poiEntityList.get(i);
logger.d("准备数据:"+poiEntity.getId()+"-"+poiEntity.getName());
if (Constant.submitIdSet.contains(poiEntity.getId())) {
continue;
}
@ -101,6 +114,7 @@ public class PoiSaveUtils {
@Override
public void accept(Map.Entry<Integer, PoiEntity> integerPoiEntityEntry) throws Exception {
PoiEntity poiEntity = integerPoiEntityEntry.getValue();
logger.d("开始上传充电站数据:"+poiEntity.getId()+"-"+poiEntity.getName());
if (savePoiNet(poiEntity) == 200&&saveChargingPileByChargingStation(poiEntity)) { // 网络保存成功
if (savePoiNet(poiEntity) == 200) { // 网络保存-冗余操作
// 开始上传流程
@ -125,6 +139,7 @@ public class PoiSaveUtils {
@Override
public void accept(Map.Entry<Integer, PoiEntity> integerPoiEntityEntry) throws Exception {
PoiEntity poiEntity = integerPoiEntityEntry.getValue();
logger.d("开始上传普通数据:"+poiEntity.getId()+"-"+poiEntity.getName());
if (savePoiNet(poiEntity) == 200) { // 网络保存成功
//走上传流程
uploadPoiNet(integerPoiEntityEntry);
@ -141,6 +156,7 @@ public class PoiSaveUtils {
@Override
public void accept(Map.Entry<Integer, PoiEntity> integerPoiEntityEntry) throws Exception {
PoiEntity poiEntity = integerPoiEntityEntry.getValue();
logger.d("开始上传分包数据:"+poiEntity.getId()+"-"+poiEntity.getName());
if (savePoiNet(poiEntity) == 200) { // 网络保存成功
//走上传流程
if (poiEntity == null) {
@ -236,6 +252,7 @@ public class PoiSaveUtils {
PoiDatabase.getInstance(mContext).getPoiDao().updatePoiEntity(poiEntity);
Constant.submitIdSet.remove(poiEntity.getId());
sendRefreshItem(poiEntity);
logger.d("数据上传失败:"+poiEntity.getId()+"-"+poiEntity.getName()+"-"+errorInfo);
}
/**
* 处理poi数据上传成功
@ -247,6 +264,7 @@ public class PoiSaveUtils {
PoiDatabase.getInstance(mContext).getPoiDao().updatePoiEntity(poiEntity);
Constant.submitIdSet.remove(poiEntity.getId());
sendRefreshItem(poiEntity);
logger.d("数据上传成功:"+poiEntity.getId()+"-"+poiEntity.getName());
}
/*

View File

@ -0,0 +1,73 @@
package com.navinfo.outdoor.util
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.navinfo.outdoor.api.Constant
import java.text.SimpleDateFormat
import java.util.*
class XLogUtils {
val uploadLogWriter by lazy {
obtainUploadLogWriter()
}
val autoTakePictureLogWriter by lazy {
obtainAutoTakePictureLogWriter()
}
companion object {
val instance by lazy { XLogUtils() }
}
fun obtainUploadLogWriter(): Logger {
val filePrinter: Printer = FilePrinter.Builder(Constant.LOG_FOLDER) // 指定保存日志文件的路径
.fileNameGenerator(object : DateFileNameGenerator() {
var mLocalDateFormat: ThreadLocal<SimpleDateFormat?> =
object : ThreadLocal<SimpleDateFormat?>() {
override fun initialValue(): SimpleDateFormat {
return SimpleDateFormat("yyyy-MM-dd", Locale.US)
}
}
override fun isFileNameChangeable(): Boolean {
return true
}
override fun generateFileName(logLevel: Int, timestamp: Long): String {
val sdf = mLocalDateFormat.get()
sdf!!.timeZone = TimeZone.getDefault()
return "批量上传-" + Constant.USHERED+ "-"+ sdf.format(Date(timestamp))
}
}) // 指定日志文件名生成器,默认为 ChangelessFileNameGenerator("log")
.flattener(ClassicFlattener())
.build()
return XLog.printers(filePrinter).build()
}
fun obtainAutoTakePictureLogWriter(): Logger {
val filePrinter: Printer = FilePrinter.Builder(Constant.LOG_FOLDER) // 指定保存日志文件的路径
.fileNameGenerator(object : DateFileNameGenerator() {
var mLocalDateFormat: ThreadLocal<SimpleDateFormat?> =
object : ThreadLocal<SimpleDateFormat?>() {
override fun initialValue(): SimpleDateFormat {
return SimpleDateFormat("yyyy-MM-dd", Locale.US)
}
}
override fun isFileNameChangeable(): Boolean {
return true
}
override fun generateFileName(logLevel: Int, timestamp: Long): String {
val sdf = mLocalDateFormat.get()
sdf!!.timeZone = TimeZone.getDefault()
return "AutoTakePicture-"+ Constant.USHERED+ "-" + sdf.format(Date(timestamp))
}
}) // 指定日志文件名生成器,默认为 ChangelessFileNameGenerator("log")
.flattener(ClassicFlattener())
.build()
return XLog.printers(filePrinter).build()
}
}