package com.dayu.pipirrapp.fragment; import static com.dayu.pipirrapp.net.Constants.BASE_URL; import static com.dayu.pipirrapp.tool.InspectionUtils.addInspectionLocationData; import static com.dayu.pipirrapp.tool.InspectionUtils.updateInspectionLocationData; import android.content.Context; import android.content.Intent; import android.location.LocationManager; import android.os.Build; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.webkit.ValueCallback; import android.webkit.WebResourceError; import android.webkit.WebResourceRequest; import android.webkit.WebResourceResponse; import android.webkit.WebView; import android.webkit.WebViewClient; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.lifecycle.Observer; import com.dayu.pipirrapp.MyApplication; import com.dayu.pipirrapp.R; import com.dayu.pipirrapp.bean.db.CenterPointBean; import com.dayu.pipirrapp.bean.db.InspectionBean; import com.dayu.pipirrapp.bean.db.InspectionLocationBean; import com.dayu.pipirrapp.bean.db.LatLonBean; import com.dayu.pipirrapp.bean.db.MarkerBean; import com.dayu.pipirrapp.bean.net.CenterPointResult; import com.dayu.pipirrapp.bean.net.InspectionRequest; import com.dayu.pipirrapp.bean.net.LoginResult; import com.dayu.pipirrapp.bean.net.MarkerResult; import com.dayu.pipirrapp.dao.DaoSingleton; import com.dayu.pipirrapp.databinding.FragmentMapBinding; import com.dayu.pipirrapp.js.MyWebViewInterface; import com.dayu.pipirrapp.net.ApiManager; import com.dayu.pipirrapp.net.BaseResponse; import com.dayu.pipirrapp.net.Constants; import com.dayu.pipirrapp.net.subscribers.SubscriberListener; import com.dayu.pipirrapp.observer.MapFragmenObserver; import com.dayu.pipirrapp.service.MyLocationService; import com.dayu.pipirrapp.tool.InspectionUtils; import com.dayu.pipirrapp.utils.CommonData; import com.dayu.pipirrapp.utils.CommonKeyName; import com.dayu.pipirrapp.utils.DateUtils; import com.dayu.pipirrapp.utils.MapJpgUtils; import com.dayu.pipirrapp.utils.MyLog; import com.dayu.pipirrapp.utils.SharedPreferencesHelper; import com.dayu.pipirrapp.utils.ToastUtil; import com.dayu.pipirrapp.utils.WebViewUtils; import com.dayu.pipirrapp.view.ConfirmDialog; import com.jeremyliao.liveeventbus.LiveEventBus; import com.tencent.bugly.crashreport.CrashReport; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Random; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.schedulers.Schedulers; /** * author: zuo * Date: 2023/12/20 * Time: 10:16 * 备注:地图页 */ public class MapFragment extends BaseFragment { static String TAG = "MapFragment"; FragmentMapBinding binding; //定位相关 LocationManager locationManager; WebView mWebView; CenterPointBean centerPointBean; String strMarkerJson; //当前巡检状态 int mInspectionState; MapFragmenObserver mapFragmenObserver; //当前巡检记录的相关信息 InspectionBean mInspectionBean; LatLonBean lastLatLonBean; InspectionRequest inspectionRequest; @Override public void onAttach(@NonNull Context context) { super.onAttach(context); Log.i(TAG, "onAttach"); mapFragmenObserver = new MapFragmenObserver(); requireActivity().getLifecycle().addObserver(mapFragmenObserver); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i(TAG, "onCreate"); mInspectionState = SharedPreferencesHelper.getInstance(this.getContext()).get(CommonKeyName.inspectionState, 0); } @Override public void onStart() { super.onStart(); Log.i(TAG, "onStart"); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { binding = FragmentMapBinding.inflate(inflater, container, false); mapFragmenObserver.setmWebView(binding.webView); Log.i("MapFragment", "onCreateView"); mWebView = binding.webView; mWebView = WebViewUtils.initWebView(mWebView); MyWebViewInterface myWebViewInterface = new MyWebViewInterface(MapFragment.this); mWebView.addJavascriptInterface(myWebViewInterface, "Android"); mWebView.loadUrl("file:///android_asset/index.html"); getCenterPoint(); initView(); initLocalData(); getMarkerData(); //显示巡检状态 chageInspecState(mInspectionState); return binding.getRoot(); } /** * 初始化各个状态 */ private void initState() { //开启定位 } /** * 初始化本地数据 */ public void initLocalData() { centerPointBean = DaoSingleton.getInstance(MapFragment.this.getContext()).centerPointDao().findFirst(); List markerBeans = DaoSingleton.getInstance(MapFragment.this.getContext()).markerDao().findAll(); strMarkerJson = WebViewUtils.beanToJson(markerBeans); jumpCenterPoint(); setMapMarker(); } /** * 跳转地图中心点 */ public void jumpCenterPoint() { if (centerPointBean != null) { Log.d(TAG, "jumpCenterPoint>>>>>>>>>>>>>>>>>>>" + centerPointBean.getLng() + "\",\"" + centerPointBean.getLat()); mWebView.evaluateJavascript("javascript:setCenterAndZoom(\"" + centerPointBean.getLng() + "\",\"" + centerPointBean.getLat() + "\",\"" + centerPointBean.getZoomMp() + "\")", value -> { }); } } /** * 添加标注点 */ public void setMapMarker() { Log.i("mWebView", "addMarker????????????" + strMarkerJson); mWebView.evaluateJavascript("javascript:addMarker(\"" + strMarkerJson + "\")", new ValueCallback() { @Override public void onReceiveValue(String value) { Log.i("mWebView", "addMarker!!!!!!!!!" + value); } }); } /** * 获取取水口列表 */ private void getMarkerData() { ApiManager.getInstance().requestGetHideLoading(this.getContext(), Constants.BASE_URL + "/project/intake/all", MarkerResult.class, null, new SubscriberListener>() { @Override public void onNext(BaseResponse t) { if (t.isSuccess()) { if (t.isSuccess()) { if (t.getContent().getObj() != null && !t.getContent().getObj().isEmpty()) { List markerBeans = new ArrayList<>(); for (int i = 0; i < t.getContent().getObj().size(); i++) { MarkerResult.Obj result = t.getContent().getObj().get(i); //保存数据 MarkerBean markerBean = new MarkerBean(); markerBean.setLng(result.getLng()); markerBean.setLat(result.getLat()); markerBean.setBlockId(result.getBlockId()); markerBean.setName(result.getName()); markerBean.setRemarks(result.getRemarks()); markerBean.setTownId(result.getTownId()); markerBean.setVillageId(result.getVillageId()); markerBean.setCountyId(result.getCountyId()); markerBeans.add(markerBean); } strMarkerJson = WebViewUtils.beanToJson(markerBeans); setMapMarker(); DaoSingleton.getInstance(MapFragment.this.getContext()).markerDao().deleteAll(); // 使用 RxJava 异步插入数据 DaoSingleton.getAsynchInstance(MapFragment.this.getContext()).markerDao().insertAll(markerBeans) .subscribeOn(Schedulers.io()) // 在 IO 线程上执行 .observeOn(AndroidSchedulers.mainThread()) // 在主线程上观察 .subscribe(() -> { // 插入成功 Log.i("mWebView", "数据插入成功"); }, throwable -> { // 插入失败 Log.e("mWebView", "数据插入失败: " + throwable.getMessage()); }); } } } else { ToastUtil.showToast(MapFragment.this.getContext(), t.getMsg()); } } }); } /** * 添加标注点 */ public void addMarker() { Random random = new Random(); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("["); // 中国经纬度范围 double minLongitude = 73.43; double maxLongitude = 135.05; double minLatitude = 3.52; double maxLatitude = 53.57; for (int i = 0; i < 1000; i++) { stringBuilder.append("["); // 生成随机经度 double longitude = minLongitude + (maxLongitude - minLongitude) * random.nextDouble(); stringBuilder.append(longitude); stringBuilder.append(","); // 生成随机纬度 double latitude = minLatitude + (maxLatitude - minLatitude) * random.nextDouble(); stringBuilder.append(latitude); stringBuilder.append(",\"237取水口\"],"); } stringBuilder.append("[116.417854,39.921988,\"235取水口\"]]"); String jsonData = stringBuilder.toString().replace("\\", "\\\\").replace("\"", "\\\""); Log.i("mWebView", "addMarker????????????" + jsonData); mWebView.evaluateJavascript("javascript:addMarker(\"" + jsonData + "\")", new ValueCallback() { @Override public void onReceiveValue(String value) { Log.i("mWebView", "addMarker!!!!!!!!!" + value); } }); } void initView() { mWebView.setWebViewClient(new WebViewClient() { @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { String url = request.getUrl().toString(); Log.i(TAG, "加载地址>>>" + url); //判断当前是否为加载瓦片 if (MapJpgUtils.getInsatance().isTianDiTuTileRequest(url)) { String androidUrl = url.replace(CommonData.webKey, CommonData.androidKey); // 检查本地缓存 File cachedTile = MapJpgUtils.getInsatance().getCachedTile(androidUrl); if (cachedTile != null && cachedTile.exists()) { Log.i(TAG, "本地缓存>>>" + androidUrl); // if (MapJpgUtils.getInsatance().validateImageFile(androidUrl,request.)) // 判断缓存是否过期 // if (!MapJpgUtils.getInsatance(MapFragment.this.getContext()).isCacheExpired(cachedTile)) { try { // 从缓存加载瓦片 return new WebResourceResponse("image/jpg", "utf-8", new FileInputStream(cachedTile)); } catch (FileNotFoundException e) { e.printStackTrace(); } // } } else { //下载瓦片 ApiManager.getInstance().donwLoadTile(androidUrl); } Log.i(TAG, "在线加载>>>" + url); } return super.shouldInterceptRequest(view, request); } @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { super.onReceivedError(view, request, error); // 捕获加载过程中发生的错误 int errorCode = error.getErrorCode(); String description = error.getDescription().toString(); String failingUrl = request.getUrl().toString(); Log.e("setWebViewClient", "errorCode:" + errorCode + ">>>>description:" + description + ">>>>failingUrl:" + failingUrl); // 处理错误,例如显示错误页面或提示用户 // view.loadUrl("file:///android_asset/error.html"); } @Override public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) { super.onReceivedHttpError(view, request, errorResponse); // 捕获HTTP错误(如404, 500等) int statusCode = errorResponse.getStatusCode(); String description = errorResponse.getReasonPhrase(); Log.e("setWebViewClient", "statusCode:" + statusCode + ">>>>description:" + description); // 根据HTTP状态码处理错误 } }); //巡检按钮 binding.inspectButton.setOnClickListener(v -> { chageInspecState(InspectionUtils.STAT_INSPECTION); }); //暂停巡检 binding.inspectPause.setOnClickListener(v -> { if (mInspectionState == InspectionUtils.STAT_INSPECTION) { chageInspecState(InspectionUtils.PAUSE_INSPECTION); } else { chageInspecState(InspectionUtils.STAT_INSPECTION); } }); //停止巡检 binding.inspectClose.setOnClickListener(v -> { chageInspecState(InspectionUtils.STOP_INSPECTION); }); } public void showWaterIntakeDetail(String data) { MyLog.i(data); binding.bottomLL.setVisibility(View.VISIBLE); } /** * 获取地图中心点 */ private void getCenterPoint() { ApiManager.getInstance().requestGet(this.getContext(), Constants.BASE_URL + "/base/dict_item/map_center", CenterPointResult.class, null, new SubscriberListener>() { @Override public void onNext(BaseResponse t) { if (t.isSuccess()) { if (centerPointBean == null) { centerPointBean = new CenterPointBean(); } centerPointBean.setLat(t.getContent().getLat()); centerPointBean.setLng(t.getContent().getLng()); centerPointBean.setZoomMp(t.getContent().getZoomMp()); DaoSingleton.getInstance(MapFragment.this.getContext()).centerPointDao().insert(centerPointBean); jumpCenterPoint(); } else { ToastUtil.showToast(MapFragment.this.getContext(), t.getMsg()); } } }); } public void closeWaterIntakeDetail() { binding.bottomLL.setVisibility(View.GONE); } /** * 上报巡检记录 */ private void pushLocationData(InspectionLocationBean inspectionLocationBean) { inspectionRequest.setInspectId(inspectionLocationBean.getInspectId()); inspectionRequest.setInspectorId(inspectionLocationBean.getInspectorId()); if (mInspectionBean != null) { inspectionRequest.setStartTime(mInspectionBean.getStartTime()); inspectionRequest.setStopTime(mInspectionBean.getStopTime()); } InspectionRequest.Track track = new InspectionRequest.Track(); track.setLat(inspectionLocationBean.getLat()); track.setLng(inspectionLocationBean.getLng()); track.setLocateTime(inspectionLocationBean.getLocateTime()); inspectionRequest.getTracks().clear(); inspectionRequest.addTracks(track); ApiManager.getInstance().requestPostHideLoading(MapFragment.this.getContext(), BASE_URL + "/app/inspect/save", LoginResult.class, inspectionRequest.toMap(inspectionRequest), new SubscriberListener>() { @Override public void onNext(BaseResponse t) { try { if (t.isSuccess()) { inspectionLocationBean.setPost(true); updateInspectionLocationData(MapFragment.this.getContext(), inspectionLocationBean); } else { } } catch (Exception e) { e.printStackTrace(); CrashReport.postCatchedException(e); } } }); } /** * 开始巡检 */ private void startInspection() { DaoSingleton.getAsynchInstance(this.getContext()).inspectionDao().getMostRecentInspectionWithNoStopTime() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()).subscribe(inspectionBean -> { // 更新 UI mInspectionBean = inspectionBean; }); } /** * 定位监听 */ private Observer locationObserver = new Observer() { @Override public void onChanged(Object o) { if (mInspectionBean != null) { LatLonBean latLonBean = (LatLonBean) o; if (InspectionUtils.isThanMinMeters(lastLatLonBean, latLonBean)) { //大于最小距离 lastLatLonBean = latLonBean; Log.i("chageInspecState", "lat:" + latLonBean.getLatitude() + ",log:" + latLonBean.getLongitude()); InspectionLocationBean inspectionLocationBean = createInspectionLocation(latLonBean); addInspectionLocationData(MapFragment.this.getContext(), inspectionLocationBean); //更新到地图 mWebView.evaluateJavascript("javascript:updateLocation(\"" + latLonBean.getLongitude() + "\",\"" + latLonBean.getLatitude() + "\")", value -> { }); //上传坐标 pushLocationData(inspectionLocationBean); } else { Log.d(TAG, "isThanMinMeters>>>false"); } } } }; /** * 创建InspectionLocationBean */ private InspectionLocationBean createInspectionLocation(LatLonBean latLonBean) { InspectionLocationBean inspectionLocationBean = new InspectionLocationBean(); inspectionLocationBean.setInspectId(mInspectionBean.getInspectId()); inspectionLocationBean.setLocateTime(DateUtils.getNowDateStr()); inspectionLocationBean.setPost(false); inspectionLocationBean.setInspectorId(MyApplication.myApplication.userId); inspectionLocationBean.setLng(String.valueOf(latLonBean.getLongitude())); inspectionLocationBean.setLat(String.valueOf(latLonBean.getLatitude())); return inspectionLocationBean; } /** * 修改巡检状态 */ private void chageInspecState(int inspectionState) { Intent location = new Intent(this.getActivity(), MyLocationService.class); location.putExtra("isSingle", false); //0没有开始,1开始,2暂停,3关闭 switch (inspectionState) { case 0: binding.inspectButton.setVisibility(View.VISIBLE); binding.inspectRL.setVisibility(View.GONE); binding.inspectButton.setText("巡"); LiveEventBus.get(CommonKeyName.locationData).removeObserver(locationObserver); //关闭定位 this.getActivity().stopService(location); break; case 1: //添加新的巡检记录 startInspection(); //获取定位服务传过来的坐标点 LiveEventBus.get(CommonKeyName.locationData).observeForever(locationObserver); binding.inspectRL.setVisibility(View.VISIBLE); binding.inspectButton.setVisibility(View.GONE); binding.inspectPause.setText("暂停"); binding.stateText.setText("已开启巡检"); binding.inspectRL.setBackgroundColor(this.getContext().getResources().getColor(R.color.base_blue)); //开启定位 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { this.getActivity().startForegroundService(location); } else { this.getActivity().startService(location); } mInspectionBean = InspectionUtils.startInspection(this.getContext()); inspectionRequest = new InspectionRequest(); break; case 2://暂停 LiveEventBus.get(CommonKeyName.locationData).removeObserver(locationObserver); //关闭定位 this.getActivity().stopService(location); binding.stateText.setText("已暂停巡检"); binding.inspectPause.setText("继续"); binding.inspectRL.setBackgroundColor(this.getContext().getResources().getColor(R.color.inspect_rl_bg_color)); break; case 3: ConfirmDialog confirmDialog = new ConfirmDialog(MapFragment.this.getActivity(), "提示", "确认关闭巡检吗?", new ConfirmDialog.ConfirmOnClickListener() { @Override public void onClick(ConfirmDialog confirmDialog, View v) { confirmDialog.dismiss(); chageInspecState(InspectionUtils.NO_INSPECTION); } }); confirmDialog.show(); break; default: } mInspectionState = inspectionState; } }