diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/callback/IOCHTaxiPassengerNaviChangedCallback.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/callback/IOCHTaxiPassengerNaviChangedCallback.java index 5a47cf6b19..fdd93e1015 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/callback/IOCHTaxiPassengerNaviChangedCallback.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/callback/IOCHTaxiPassengerNaviChangedCallback.java @@ -5,7 +5,7 @@ package com.mogo.och.taxi.passenger.callback; * @date: 2021/12/3 */ public interface IOCHTaxiPassengerNaviChangedCallback { - // 当前位置距离上车点的距离(米)、预估时间(秒) - void onCurrentNaviDistAndTimeChanged(int meters, int timeInSecond); + // 当前位置距离上车点的距离(米)、预估时间(秒) 、当前路的名称 + void onCurrentNaviDistAndTimeChanged(int meters, int timeInSecond, String currentRoadName); void reInitNaviAmap(boolean isPlay,boolean isRestart); } diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/callback/IOCHTaxiPassengerOrderStatusCallback.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/callback/IOCHTaxiPassengerOrderStatusCallback.java index 49437c86de..be5cf3c550 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/callback/IOCHTaxiPassengerOrderStatusCallback.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/callback/IOCHTaxiPassengerOrderStatusCallback.java @@ -17,6 +17,6 @@ public interface IOCHTaxiPassengerOrderStatusCallback { void onCurrentOrderStatusChanged(TaxiPassengerOrderQueryRespBean.Result order); // 当前位置距离上车点的距离(米)、预估时间(秒) - void onCurrentOrderDistToEndChanged(int meters, int timeInSecond); + void onCurrentOrderDistToEndChanged(int meters, int timeInSecond, String currentRoadName); } diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/constant/TaxiPassengerConst.kt b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/constant/TaxiPassengerConst.kt index c2b9f431a0..1b3594e480 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/constant/TaxiPassengerConst.kt +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/constant/TaxiPassengerConst.kt @@ -37,5 +37,8 @@ class TaxiPassengerConst { // 订单信息 const val SP_KEY_OCH_TAXI_ORDER = "SP_KEY_OCH_TAXI_ORDER" + + // 订单总里程 + const val SP_KEY_ORDER_SUM_DIS = "SP_KEY_ORDER_SUM_DIS" } } \ No newline at end of file diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModel.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModel.java index 9a1c435b68..9e254b5f5a 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModel.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerModel.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.Intent; import android.location.Location; import android.net.ConnectivityManager; +import android.os.Looper; import androidx.annotation.Nullable; @@ -11,9 +12,8 @@ import com.amap.api.navi.model.NaviLatLng; import com.elegant.network.utils.GsonUtil; import com.mogo.cloud.commons.utils.CoordinateUtils; import com.mogo.commons.debug.DebugConfig; +import com.mogo.commons.voice.AIAssist; import com.mogo.eagle.core.data.autopilot.ADASTrajectoryInfo; -import com.mogo.eagle.core.data.autopilot.AutopilotGuardianStatusInfo; -import com.mogo.eagle.core.data.autopilot.AutopilotStationInfo; import com.mogo.eagle.core.data.autopilot.AutopilotStatusInfo; import com.mogo.eagle.core.data.config.FunctionBuildConfig; import com.mogo.eagle.core.data.map.MogoLocation; @@ -27,8 +27,10 @@ import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils; import com.mogo.eagle.core.utilcode.mogo.logger.Logger; import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr; import com.mogo.eagle.core.utilcode.util.NetworkUtils; +import com.mogo.eagle.core.utilcode.util.UiThreadHandler; import com.mogo.map.navi.IMogoCarLocationChangedListener2; import com.mogo.module.common.MogoApisHandler; +import com.mogo.och.taxi.passenger.R; import com.mogo.och.taxi.passenger.bean.TaxiPassengerOrderQueryRespBean; import com.mogo.och.taxi.passenger.bean.TaxiPassengerOrdersInServiceQueryRespBean; import com.mogo.och.taxi.passenger.callback.IOCHTaxiPassengerADASStatusCallback; @@ -81,6 +83,12 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback private volatile List mInServiceList = Collections.emptyList(); //进行中订单 private volatile List mWaitServiceList = Collections.emptyList(); //待服务订单 + public void setmTtsLessThan200Tip(int ttsLessThan200Tip) { + this.mTtsLessThan200Tip = ttsLessThan200Tip; + } + + private volatile int mTtsLessThan200Tip = 0;//离终点200米提示播报 + private IOCHTaxiPassengerADASStatusCallback mADASStatusCallback; //Model->Presenter:自动驾驶状态相关 private IOCHTaxiPassengerAutopilotPlanningCallback mAutopilotPlanningCallback; //Model->Presenter:自动驾驶线路规划 @@ -310,22 +318,6 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback }); } - // 车机端上传心跳数据(只在出车状态时上传) -// public void runCarHeartbeat() { -// TaxiPassengerServiceManager.getInstance().runCarHeartbeat(mContext, mLongitude, mLatitude, -// new TaxiPassengerServiceCallback() { -// @Override -// public void onSuccess(BaseData data) { -// -// } -// -// @Override -// public void onFail(int code, String msg) { -// -// } -// }); -// } - // 获取当前订单 public TaxiPassengerOrderQueryRespBean.Result getCurrentOCHOrder() { return mCurrentOCHOrder; @@ -578,25 +570,51 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback }; /** - * + * 导航订单起点到终点 获得剩余时间,里程,预计到达时间 */ public void naviOrderStartToEnd() { - NaviLatLng startNaviLatLng = new NaviLatLng(mLongitude,mLatitude); - NaviLatLng endNaviLatLng = new NaviLatLng(mCurrentOCHOrder.endSiteGcjPoint.get(1), mCurrentOCHOrder.endSiteGcjPoint.get(0)); - TaxiPassengerNaviToDestinationModel.getInstance(mContext).initAMapNavi(startNaviLatLng, endNaviLatLng); - TaxiPassengerNaviToDestinationModel.getInstance(mContext).setOCHTaciNaviChangedCallback(this); + TaxiPassengerNaviToDestinationModel.getInstance(mContext).destroyAmaNavi(); + if (mCurrentOCHOrder != null){ + NaviLatLng startNaviLatLng = new NaviLatLng(mLatitude,mLongitude); + NaviLatLng endNaviLatLng = new NaviLatLng(mCurrentOCHOrder.endSiteGcjPoint.get(1),mCurrentOCHOrder.endSiteGcjPoint.get(0)); + TaxiPassengerNaviToDestinationModel.getInstance(mContext).initAMapNavi(startNaviLatLng, endNaviLatLng); + TaxiPassengerNaviToDestinationModel.getInstance(mContext).setOCHTaciNaviChangedCallback(this); + } +// else { +// NaviLatLng startNaviLatLng = new NaviLatLng(40.200478,116.741377); +// NaviLatLng endNaviLatLng = new NaviLatLng(40.200863,116.732574); +// TaxiPassengerNaviToDestinationModel.getInstance(mContext).initAMapNavi(startNaviLatLng, endNaviLatLng); +// TaxiPassengerNaviToDestinationModel.getInstance(mContext).setOCHTaciNaviChangedCallback(this); +// } } @Override - public void onCurrentNaviDistAndTimeChanged(int meters, int timeInSecond) { + public void onCurrentNaviDistAndTimeChanged(int meters, int timeInSecond, String currentRoadName) { + if (mTtsLessThan200Tip == 0 && meters <= 200){ + mTtsLessThan200Tip = 1; + runOnUIThread(() -> { + AIAssist.getInstance(mContext).speakTTSVoice(mContext.getString(R.string.taxi_p_arrive_end_tts_200)); + }); + } for (IOCHTaxiPassengerOrderStatusCallback callback :mOrderStatusCallbackMap.values()){ - callback.onCurrentOrderDistToEndChanged(meters,timeInSecond); + callback.onCurrentOrderDistToEndChanged(meters,timeInSecond,currentRoadName); } } @Override public void reInitNaviAmap(boolean isPlay, boolean isRestart) { + naviOrderStartToEnd(); + } + private void runOnUIThread(Runnable executor) { + if (executor == null) { + return; + } + if (Looper.myLooper() != Looper.getMainLooper()) { + UiThreadHandler.post(executor); + } else { + executor.run(); + } } } diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerNaviToDestinationModel.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerNaviToDestinationModel.java index 9806e1b9ac..d48aef1510 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerNaviToDestinationModel.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/model/TaxiPassengerNaviToDestinationModel.java @@ -2,7 +2,6 @@ package com.mogo.och.taxi.passenger.model; import android.Manifest; import android.content.Context; -import android.util.Log; import android.widget.Toast; import com.amap.api.navi.AMapNavi; @@ -23,9 +22,11 @@ import com.amap.api.navi.model.AimLessModeStat; import com.amap.api.navi.model.NaviInfo; import com.amap.api.navi.model.NaviLatLng; import com.autonavi.tbt.TrafficFacilityInfo; -import com.mogo.eagle.core.utilcode.mogo.toast.TipToast; +import com.mogo.eagle.core.utilcode.mogo.logger.Logger; +import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr; import com.mogo.eagle.core.utilcode.util.NetworkUtils; import com.mogo.och.taxi.passenger.callback.IOCHTaxiPassengerNaviChangedCallback; +import com.mogo.och.taxi.passenger.constant.TaxiPassengerConst; import com.mogo.och.taxi.passenger.utils.PermissionUtil; import java.util.ArrayList; @@ -37,6 +38,9 @@ import java.util.concurrent.atomic.AtomicInteger; * @date: 2021/12/6 */ public class TaxiPassengerNaviToDestinationModel implements AMapNaviListener { + + private final String TAG = TaxiPassengerNaviToDestinationModel.class.getSimpleName(); + private static Context mContext; private AMapNavi mAMapNavi = null; protected final List sList = new ArrayList(); @@ -45,6 +49,13 @@ public class TaxiPassengerNaviToDestinationModel implements AMapNaviListener { private IOCHTaxiPassengerNaviChangedCallback mNaviChangedCallback; private AtomicInteger errorCount = new AtomicInteger(0); private boolean isPlay; + + private volatile int mFirstcalculateDriveRoute = 0; + public void setFirstcalculateDriveRoute(int firstcalculateDriveRoute) { + this.mFirstcalculateDriveRoute = firstcalculateDriveRoute; + } + + public static TaxiPassengerNaviToDestinationModel getInstance(Context context) { mContext = context; return SingletonHolder.INSTANCE; @@ -63,6 +74,14 @@ public class TaxiPassengerNaviToDestinationModel implements AMapNaviListener { mAMapNavi.stopSpeak(); sList.add(startLatLng); eList.add(endLatLng); + int strategy = 0; + try { + //再次强调,最后一个参数为true时代表多路径,否则代表单路径 + strategy = mAMapNavi.strategyConvert(true, false, false, false, false); + } catch (Exception e) { + e.printStackTrace(); + } + mAMapNavi.calculateDriveRoute(sList, eList, mWayPointList, strategy); }catch (Exception e) { e.printStackTrace(); } @@ -84,6 +103,8 @@ public class TaxiPassengerNaviToDestinationModel implements AMapNaviListener { mAMapNavi.destroy(); mAMapNavi = null; mNaviChangedCallback = null; + sList.clear(); + eList.clear(); } } @@ -98,38 +119,27 @@ public class TaxiPassengerNaviToDestinationModel implements AMapNaviListener { @Override public void onInitNaviSuccess() { //初始化成功 - /** - * 方法: int strategy=mAMapNavi.strategyConvert(congestion, avoidhightspeed, cost, hightspeed, multipleroute); 参数: - * - * @congestion 躲避拥堵 - * @avoidhightspeed 不走高速 - * @cost 避免收费 - * @hightspeed 高速优先 - * @multipleroute 多路径 - * - * 说明: 以上参数都是boolean类型,其中multipleroute参数表示是否多条路线,如果为true则此策略会算出多条路线。 - * 注意: 不走高速与高速优先不能同时为true 高速优先与避免收费不能同时为true - */ - int strategy = 0; - try { - //再次强调,最后一个参数为true时代表多路径,否则代表单路径 - strategy = mAMapNavi.strategyConvert(true, false, false, false, false); - } catch (Exception e) { - e.printStackTrace(); - } - mAMapNavi.calculateDriveRoute(sList, eList, mWayPointList, strategy); } @Override public void onCalculateRouteSuccess(int[] ints) { //多路径算路成功回调 + Logger.d(TAG,"onCalculateRouteSuccess"); mAMapNavi.startNavi(NaviType.GPS); } @Override public void onNaviInfoUpdate(NaviInfo naviinfo) { //导航过程中的信息更新,请看NaviInfo的具体说明 + Logger.d(TAG,"naviinfo = "+naviinfo.getPathRetainDistance()+" ,"+naviinfo.getPathRetainTime() + +" ,"+naviinfo.getCurrentRoadName()); + + if (mFirstcalculateDriveRoute == 0 && SharedPrefsMgr.getInstance(mContext).getInt(TaxiPassengerConst.SP_KEY_ORDER_SUM_DIS,0) == 0){ + mFirstcalculateDriveRoute = 1; + SharedPrefsMgr.getInstance(mContext).putInt(TaxiPassengerConst.SP_KEY_ORDER_SUM_DIS,naviinfo.getPathRetainDistance()); + } if (null != mNaviChangedCallback){ - mNaviChangedCallback.onCurrentNaviDistAndTimeChanged(naviinfo.getPathRetainDistance(),naviinfo.getPathRetainTime());// 米、秒 + mNaviChangedCallback.onCurrentNaviDistAndTimeChanged(naviinfo.getPathRetainDistance() + ,naviinfo.getPathRetainTime(),naviinfo.getCurrentRoadName());// 米、秒 } } @@ -149,14 +159,12 @@ public class TaxiPassengerNaviToDestinationModel implements AMapNaviListener { } } if (!NetworkUtils.isConnected(mContext) || result.getErrorCode() == 2){ - TipToast.longTip("网络异常,请重试"); if (mNaviChangedCallback != null){ mNaviChangedCallback.reInitNaviAmap(isPlay,false); } return; } if (!PermissionUtil.isLocServiceEnable(mContext) || !PermissionUtil.checkPermission(mContext,new String[]{Manifest.permission.ACCESS_FINE_LOCATION})){ - TipToast.longTip("请开启车机定位后重试"); if (mNaviChangedCallback != null){ mNaviChangedCallback.reInitNaviAmap(isPlay,false); } @@ -167,8 +175,8 @@ public class TaxiPassengerNaviToDestinationModel implements AMapNaviListener { // }else if (result.getErrorCode() == 6){ // TipToast.longTip("终点坐标错误"); // } - Log.i("dm", "路线计算失败:错误码=" + result.getErrorCode() + ",Error Message= " + result.getErrorDetail()); - Log.i("dm", "错误码详细链接见:http://lbs.amap.com/api/android-navi-sdk/guide/tools/errorcode/"); + Logger.i(TAG, "路线计算失败:错误码=" + result.getErrorCode() + ",Error Message= " + result.getErrorDetail()); + Logger.i(TAG, "错误码详细链接见:http://lbs.amap.com/api/android-navi-sdk/guide/tools/errorcode/"); } @Override public void onStartNavi(int type) { diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/presenter/BaseTaxiPassengerPresenter.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/presenter/BaseTaxiPassengerPresenter.java index 64a6827865..bc4f790b38 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/presenter/BaseTaxiPassengerPresenter.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/presenter/BaseTaxiPassengerPresenter.java @@ -9,15 +9,20 @@ import androidx.lifecycle.LifecycleOwner; import com.mogo.commons.AbsMogoApplication; import com.mogo.commons.mvp.Presenter; +import com.mogo.commons.voice.AIAssist; import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; import com.mogo.eagle.core.utilcode.mogo.logger.Logger; +import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr; import com.mogo.eagle.core.utilcode.util.UiThreadHandler; +import com.mogo.och.taxi.passenger.R; import com.mogo.och.taxi.passenger.bean.TaxiPassengerOrderQueryRespBean; import com.mogo.och.taxi.passenger.callback.IOCHTaxiPassengerADASStatusCallback; import com.mogo.och.taxi.passenger.callback.IOCHTaxiPassengerControllerStatusCallback; import com.mogo.och.taxi.passenger.callback.IOCHTaxiPassengerOrderStatusCallback; +import com.mogo.och.taxi.passenger.constant.TaxiPassengerConst; import com.mogo.och.taxi.passenger.constant.TaxiPassengerOrderStatusEnum; import com.mogo.och.taxi.passenger.model.TaxiPassengerModel; +import com.mogo.och.taxi.passenger.model.TaxiPassengerNaviToDestinationModel; import com.mogo.och.taxi.passenger.ui.TaxiPassengerBaseFragment; /** @@ -118,26 +123,49 @@ public class BaseTaxiPassengerPresenter extends Presenter list = new ArrayList<>(); - for (int i = 0; i < 200; i++) { - MessagePad.Location.Builder builder = MessagePad.Location.newBuilder(); - AutopilotRouteInfo.RouteModels routeModels = new AutopilotRouteInfo.RouteModels(); - if (i <= 100) { - builder.setLatitude(40.199248903658166); - builder.setLongitude(116.73435586102245 + i * 0.0001); - } else { - builder.setLatitude(40.199248903658166 + i * 0.0001); - builder.setLongitude(116.73435586102245 + 100 * 0.0001); + try { + JSONObject jsonObject = new JSONObject(listStr); + JSONArray jsonElements = jsonObject.getJSONArray("models"); + for (int i = 0; i < jsonElements.length(); i++){ + JSONObject s = jsonElements.getJSONObject(i); + MessagePad.Location.Builder routeModels = MessagePad.Location.newBuilder(); + routeModels.setLatitude(s.getDouble("lat")); + routeModels.setLongitude(s.getDouble("lon")); + list.add(routeModels.build()); } - list.add(builder.build()); + } catch (JSONException e) { + e.printStackTrace(); } + mPresenter.routeResult(list); return true; } @@ -142,7 +330,7 @@ public class TaxiPassengerServingOrderFragment extends */ private void setSeekBarMax() { //计算订单起点和终点距离 - int maxInt = TaxiPassengerModel.getInstance().calculateOrderDistanceSum(); + int maxInt = SharedPrefsMgr.getInstance(getContext()).getInt(TaxiPassengerConst.SP_KEY_ORDER_SUM_DIS,0); Logger.d(TAG, "maxInt = " + maxInt); mProgressSeekBar.setMax(maxInt); } @@ -151,9 +339,10 @@ public class TaxiPassengerServingOrderFragment extends * 行驶进度值更新 */ @RequiresApi(api = Build.VERSION_CODES.N) - private void updateDriveProcessLoading(int progressLoading) { + private void updateDriveProcessLoading(int progressLoading,String currentRoadName) { + mProgessDes.setText(currentRoadName); mProgressSeekBar.setProgress( - TaxiPassengerModel.getInstance().calculateOrderDistanceSum() - progressLoading + SharedPrefsMgr.getInstance(getContext()).getInt(TaxiPassengerConst.SP_KEY_ORDER_SUM_DIS,0) - progressLoading , true); } @@ -234,24 +423,32 @@ public class TaxiPassengerServingOrderFragment extends if (TaxiPassengerOrderStatusEnum.OnTheWayToEndStation.getCode() == order.orderStatus) { mTPOrderStatus.setText(R.string.taxi_p_start_to_end); + setSeekBarMax(); return; } } + /** + * 剩余里程,剩余时间,当前定位点所在道路 + * @param meters + * @param timeInSecond + * @param currentRoadName + */ @RequiresApi(api = Build.VERSION_CODES.N) - public void onCurrentOrderDistToEndChanged(int meters, int timeInSecond) { - Calendar calendarArrive = TaxiPassengerUtils.formatLongToCalendar(System.currentTimeMillis() + timeInSecond); - String arriveTime = TaxiPassengerUtils.formatCalendarToString(calendarArrive, TaxiPassengerUtils.TAXI_HH_mm); + public void onCurrentOrderDistToEndChanged(int meters, int timeInSecond, String currentRoadName) { DecimalFormat fnum = new DecimalFormat("##0.00"); String remainDis = fnum.format((float) meters / 1000); int remainTime = (int) timeInSecond / 60; + Calendar beforeTime = Calendar.getInstance(); + beforeTime.add(Calendar.MINUTE,remainTime); + String arriveTime = TaxiPassengerUtils.formatCalendarToString(beforeTime,TaxiPassengerUtils.TAXI_HH_mm); updateOrderDisAndTimeView(remainDis, remainTime, arriveTime); - updateDriveProcessLoading(meters); + updateDriveProcessLoading(meters,currentRoadName); } private void updateOrderDisAndTimeView(String remainDis, int remainTime, String arriveTime) { mTPOrderRemainDis.setText(remainDis); - mTPOrderRemainTime.setText(remainTime); + mTPOrderRemainTime.setText(String.valueOf(remainTime)); mTPOrderRemainArriveTime.setText(arriveTime); } @@ -270,10 +467,13 @@ public class TaxiPassengerServingOrderFragment extends */ private void updateSpeedView(float newSpeed) { int speed = (int) (Math.abs(newSpeed) * 3.6F); // 倒车时工控机反馈定位信息中speed为负值 + Logger.d(TAG,"mLimitingVelocity = "+mLimitingVelocity); if (speed < mLimitingVelocity) { mTPSpeedTv.setText(getSpeedTextStyle(String.valueOf(speed), true)); + mSpeedLayoutBg.setBackgroundResource(R.drawable.taxi_p_speed_light_green_bg); } else { mTPSpeedTv.setText(getSpeedTextStyle(String.valueOf(speed), false)); + mSpeedLayoutBg.setBackgroundResource(R.drawable.taxi_p_speed_light_red_bg); } } @@ -288,6 +488,7 @@ public class TaxiPassengerServingOrderFragment extends if (isNormal) { return TaxiPassengerUtils.getGradientFontSpan(content , 0xFFCEEEFF, 0xFFA1DAFF); + } else {//超速 return TaxiPassengerUtils.getGradientFontSpan(content , 0xFFFE2505, 0xFFFF6F62); diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_arrive_end_panel_bg.png b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_arrive_end_panel_bg.png new file mode 100644 index 0000000000..8c7c04a122 Binary files /dev/null and b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_arrive_end_panel_bg.png differ diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_arrow_nor.png b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_arrow_nor.png index b7e671cd13..b9d70e5fbb 100644 Binary files a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_arrow_nor.png and b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_arrow_nor.png differ diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_seekbar_point_icon.png b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_seekbar_point_icon.png new file mode 100644 index 0000000000..ab00b6fde3 Binary files /dev/null and b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_seekbar_point_icon.png differ diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_speed_light_green_bg.png b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_speed_light_green_bg.png new file mode 100644 index 0000000000..d6116cae01 Binary files /dev/null and b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_speed_light_green_bg.png differ diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_speed_light_red_bg.png b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_speed_light_red_bg.png new file mode 100644 index 0000000000..4fa0e570fa Binary files /dev/null and b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_speed_light_red_bg.png differ diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_arrive_end_panel_bg.png b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_arrive_end_panel_bg.png new file mode 100644 index 0000000000..8c7c04a122 Binary files /dev/null and b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_arrive_end_panel_bg.png differ diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_arrow_nor.png b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_arrow_nor.png index b7e671cd13..b9d70e5fbb 100644 Binary files a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_arrow_nor.png and b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_arrow_nor.png differ diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_seekbar_point_icon.png b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_seekbar_point_icon.png new file mode 100644 index 0000000000..ab00b6fde3 Binary files /dev/null and b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_seekbar_point_icon.png differ diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_speed_light_green_bg.png b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_speed_light_green_bg.png new file mode 100644 index 0000000000..d6116cae01 Binary files /dev/null and b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_speed_light_green_bg.png differ diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_speed_light_red_bg.png b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_speed_light_red_bg.png new file mode 100644 index 0000000000..4fa0e570fa Binary files /dev/null and b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_speed_light_red_bg.png differ diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable/taxi_p_map_bottom_shape.xml b/OCH/mogo-och-taxi-passenger/src/main/res/drawable/taxi_p_map_bottom_shape.xml new file mode 100644 index 0000000000..9fb453ea1b --- /dev/null +++ b/OCH/mogo-och-taxi-passenger/src/main/res/drawable/taxi_p_map_bottom_shape.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable/taxi_p_seekbar_calculator_layer.xml b/OCH/mogo-och-taxi-passenger/src/main/res/drawable/taxi_p_seekbar_calculator_layer.xml index 67c9174e63..efc0d4f4df 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/res/drawable/taxi_p_seekbar_calculator_layer.xml +++ b/OCH/mogo-och-taxi-passenger/src/main/res/drawable/taxi_p_seekbar_calculator_layer.xml @@ -1,28 +1,17 @@ - - + - - - - - + diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_activity_serving_order_view.xml b/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_activity_serving_order_view.xml index 55300eafb6..ba7d3ebfb0 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_activity_serving_order_view.xml +++ b/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_activity_serving_order_view.xml @@ -8,11 +8,22 @@ + + @@ -128,6 +140,7 @@ android:layout_toRightOf="@+id/taxi_p_order_remain_distance" android:text="KM" android:textColor="#FFFFFF" + android:includeFontPadding="false" android:textSize="20px" /> @@ -139,6 +152,7 @@ android:layout_centerHorizontal="true" android:layout_marginTop="@dimen/dp_10" android:text="距离" + android:includeFontPadding="false" android:textColor="#8FB3EF" android:textSize="20px" /> @@ -165,6 +179,7 @@ android:layout_height="wrap_content" android:text="0" android:textColor="#84D4FF" + android:includeFontPadding="false" android:textSize="42px" android:textStyle="bold" /> @@ -177,6 +192,7 @@ android:layout_toRightOf="@+id/taxi_p_order_remain_time" android:text="分钟" android:textColor="#FFFFFF" + android:includeFontPadding="false" android:textSize="20px" /> @@ -188,6 +204,7 @@ android:layout_centerHorizontal="true" android:layout_marginTop="@dimen/dp_10" android:text="剩余" + android:includeFontPadding="false" android:textColor="#8FB3EF" android:textSize="20px" /> @@ -207,6 +224,7 @@ android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:text="0" + android:includeFontPadding="false" android:textColor="#84D4FF" android:textSize="42px" android:textStyle="bold" /> @@ -219,6 +237,7 @@ android:layout_centerHorizontal="true" android:layout_marginTop="@dimen/dp_10" android:text="到达" + android:includeFontPadding="false" android:textColor="#8FB3EF" android:textSize="20px" /> @@ -235,25 +254,43 @@ + app:layout_constraintBottom_toBottomOf="parent"/> + + + + diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_base_fragment.xml b/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_base_fragment.xml index f013f01624..a751710d99 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_base_fragment.xml +++ b/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_base_fragment.xml @@ -113,4 +113,55 @@ android:layout_marginRight="@dimen/taxi_p_traffic_light_layout_margin_right" android:layout_marginTop="@dimen/taxi_p_traffic_light_layout_margin_top" android:visibility="gone"/> + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_map_view.xml b/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_map_view.xml index a01aa831cd..dfd776809b 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_map_view.xml +++ b/OCH/mogo-och-taxi-passenger/src/main/res/layout/taxi_p_map_view.xml @@ -3,8 +3,8 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" - app:taxi_right_bottom_radius="40px" - app:taxi_left_bottom_radius="40px"> + app:taxi_right_bottom_radius="@dimen/dp_40" + app:taxi_left_bottom_radius="@dimen/dp_40"> 120px 39px 20px + + 82px + 42px + + 120px + 28px \ No newline at end of file diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/values-xhdpi-2560x1440/dimens.xml b/OCH/mogo-och-taxi-passenger/src/main/res/values-xhdpi-2560x1440/dimens.xml index 84694a1e19..0305e67e98 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/res/values-xhdpi-2560x1440/dimens.xml +++ b/OCH/mogo-och-taxi-passenger/src/main/res/values-xhdpi-2560x1440/dimens.xml @@ -24,6 +24,12 @@ 120px 120px + 82px + 42px + + 120px + 28px + 83px 40px diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/values/colors.xml b/OCH/mogo-och-taxi-passenger/src/main/res/values/colors.xml index 351f21c4f7..46ba8a611c 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/res/values/colors.xml +++ b/OCH/mogo-och-taxi-passenger/src/main/res/values/colors.xml @@ -25,4 +25,9 @@ #FF9B00 #80000000 + + #F8B70A + #C6D9FA + + #D1193D66 \ No newline at end of file diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/values/dimens.xml b/OCH/mogo-och-taxi-passenger/src/main/res/values/dimens.xml index 957abe6b50..88098feac9 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/res/values/dimens.xml +++ b/OCH/mogo-och-taxi-passenger/src/main/res/values/dimens.xml @@ -108,4 +108,10 @@ 120px 39px 20px + + 82px + 42px + + 120px + 28px \ No newline at end of file diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/values/strings.xml b/OCH/mogo-och-taxi-passenger/src/main/res/values/strings.xml index 25755a228e..98094604c0 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/res/values/strings.xml +++ b/OCH/mogo-och-taxi-passenger/src/main/res/values/strings.xml @@ -20,4 +20,8 @@ 服务完成 准备出发 正在前往目的地 + 即将到达目的地,请您收好好随声物品,准备下车 + 已达到目的地,请从右侧下车,感谢乘坐蘑菇车联无人驾驶车 + 已到达 + 感谢您使用蘑菇车联自动驾驶出行服务,期待下次与您相遇 \ No newline at end of file diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/values/styles.xml b/OCH/mogo-och-taxi-passenger/src/main/res/values/styles.xml index d6aa45e6b8..aa3f10f3cf 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/res/values/styles.xml +++ b/OCH/mogo-och-taxi-passenger/src/main/res/values/styles.xml @@ -10,4 +10,13 @@ + + + \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/MogoOCHTaxiModelNew.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/MogoOCHTaxiModelNew.java index c0f8dfc642..15f1857d92 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/MogoOCHTaxiModelNew.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/MogoOCHTaxiModelNew.java @@ -8,6 +8,8 @@ import android.util.Log; import androidx.annotation.Nullable; +import com.amap.api.maps.CoordinateConverter; +import com.amap.api.maps.model.LatLng; import com.elegant.network.utils.GsonUtil; import com.mogo.cloud.commons.utils.CoordinateUtils; import com.mogo.commons.debug.DebugConfig; @@ -1047,7 +1049,6 @@ public class MogoOCHTaxiModelNew { @Override public void onAutopilotRotting(MessagePad.GlobalPathResp routeList) { if (null != routeList && routeList.getWayPointsList().size() > 0){ -// mAutopilotPlanningCallback.routeResult(routeList.getModels()); updateOrderRoute(routeList.getWayPointsList()); } } @@ -1065,14 +1066,7 @@ public class MogoOCHTaxiModelNew { */ public void updateOrderRoute(List models) { - List points = new ArrayList<>(); - - for (int i =0; i < models.size(); i++){ - OrderRouteUpdateReqBean.Result point = new OrderRouteUpdateReqBean.Result(); - point.latitude = models.get(i).getLatitude(); - point.longitude = models.get(i).getLongitude(); - points.add(point); - } + List points = CoordinateConverterFrom84ForList(mContext,models); OCHTaxiServiceManagerNew.getInstance().updateOrderRoute(mContext, mCurrentOCHOrder.orderNo , points, new OCHTaxiServiceCallback() { @@ -1088,5 +1082,25 @@ public class MogoOCHTaxiModelNew { }); } + private List CoordinateConverterFrom84ForList(Context mContext, List mogoLatLngList) { + List points = new ArrayList<>(); + for (MessagePad.Location m : mogoLatLngList) { + LatLng mogoLatLng = CoordinateConverterFrom84(mContext, m); + OrderRouteUpdateReqBean.Result result = new OrderRouteUpdateReqBean.Result(); + result.latitude = mogoLatLng.latitude; + result.longitude = mogoLatLng.longitude; + points.add(result); + } + return points; + } + + private LatLng CoordinateConverterFrom84(Context mContext, MessagePad.Location mogoLatLng) { + CoordinateConverter mCoordinateConverter = new CoordinateConverter(mContext); + mCoordinateConverter.from(CoordinateConverter.CoordType.GPS); + mCoordinateConverter.coord(new LatLng(mogoLatLng.getLatitude(), mogoLatLng.getLongitude())); + LatLng latLng = mCoordinateConverter.convert(); + return latLng; + } + } diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/OCHTaxiFragment.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/OCHTaxiFragment.java index ae27507194..aede461144 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/OCHTaxiFragment.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/OCHTaxiFragment.java @@ -1,5 +1,6 @@ package com.mogo.och.taxi.ui; +import android.content.Context; import android.os.Build; import android.os.Bundle; import android.view.View; @@ -10,8 +11,11 @@ import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.fragment.app.FragmentTransaction; +import com.amap.api.maps.CoordinateConverter; +import com.amap.api.maps.model.LatLng; import com.mogo.commons.debug.DebugConfig; import com.mogo.eagle.core.data.autopilot.AutopilotRouteInfo; +import com.mogo.eagle.core.data.map.MogoLatLng; import com.mogo.eagle.core.utilcode.mogo.logger.Logger; import com.mogo.module.common.MogoApisHandler; import com.mogo.och.taxi.R; @@ -22,6 +26,10 @@ import com.mogo.och.taxi.model.MogoOCHTaxiModelNew; import com.mogo.och.taxi.presenter.OCHTaxiPresenter; import com.mogo.och.taxi.utils.PinYinUtil; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; @@ -317,21 +325,224 @@ public class OCHTaxiFragment extends BaseOchTaxiTabFragment { + + String listStr = "{\"models\":[{\n" + + "\t\t\"lat\": 40.19927810144466,\n" + + "\t\t\"lon\": 116.73527259387767\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19927836356079,\n" + + "\t\t\"lon\": 116.73513114732762\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19927759500293,\n" + + "\t\t\"lon\": 116.73497660879111\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.199264819842284,\n" + + "\t\t\"lon\": 116.73480063747202\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.1992510141554,\n" + + "\t\t\"lon\": 116.73463922037767\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.199245872804,\n" + + "\t\t\"lon\": 116.73445960685193\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19924673374912,\n" + + "\t\t\"lon\": 116.73427704009703\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19924747108264,\n" + + "\t\t\"lon\": 116.7340707102972\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19924828745573,\n" + + "\t\t\"lon\": 116.73385916927226\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19924941093133,\n" + + "\t\t\"lon\": 116.73364048294795\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19924939253381,\n" + + "\t\t\"lon\": 116.73340837408566\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19924949105934,\n" + + "\t\t\"lon\": 116.73317368725336\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19925040039033,\n" + + "\t\t\"lon\": 116.73296532811216\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.1992515355653,\n" + + "\t\t\"lon\": 116.73277787366743\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.1992512720328,\n" + + "\t\t\"lon\": 116.73263377253741\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.199205174954606,\n" + + "\t\t\"lon\": 116.73249773114644\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.1991015743076,\n" + + "\t\t\"lon\": 116.7324219601283\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.198971862686285,\n" + + "\t\t\"lon\": 116.73239393296355\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19883883071582,\n" + + "\t\t\"lon\": 116.73237676435652\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19870171355796,\n" + + "\t\t\"lon\": 116.73236052150362\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.1985491853193,\n" + + "\t\t\"lon\": 116.73234157857011\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.1983890047355,\n" + + "\t\t\"lon\": 116.73232167996464\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.1982209877466,\n" + + "\t\t\"lon\": 116.73230101645792\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.198037574138326,\n" + + "\t\t\"lon\": 116.73227735486083\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19787327856243,\n" + + "\t\t\"lon\": 116.73225676816314\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19771917207499,\n" + + "\t\t\"lon\": 116.73223814728027\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.197548305175935,\n" + + "\t\t\"lon\": 116.73221624705808\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19739568979691,\n" + + "\t\t\"lon\": 116.73219618210774\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19724703821575,\n" + + "\t\t\"lon\": 116.73217598293311\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.1970956560885,\n" + + "\t\t\"lon\": 116.73215773721505\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19697703483188,\n" + + "\t\t\"lon\": 116.73214337172284\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19687000725696,\n" + + "\t\t\"lon\": 116.73210037067965\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.196833449601726,\n" + + "\t\t\"lon\": 116.73196646708011\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19685833847804,\n" + + "\t\t\"lon\": 116.73181315361103\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.196889170203264,\n" + + "\t\t\"lon\": 116.73164355747393\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19692242860347,\n" + + "\t\t\"lon\": 116.7314555399657\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19696431701069,\n" + + "\t\t\"lon\": 116.7312261834129\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19700025925464,\n" + + "\t\t\"lon\": 116.73102774016093\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19703414798773,\n" + + "\t\t\"lon\": 116.73084270562073\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19707287604138,\n" + + "\t\t\"lon\": 116.73062835248406\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19710951629977,\n" + + "\t\t\"lon\": 116.73041744082339\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19714593807105,\n" + + "\t\t\"lon\": 116.73021414314803\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.197183297026285,\n" + + "\t\t\"lon\": 116.7300057066447\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.1972247359487,\n" + + "\t\t\"lon\": 116.7297751515664\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19726518822745,\n" + + "\t\t\"lon\": 116.72954958923812\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19730538240706,\n" + + "\t\t\"lon\": 116.72932440756041\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19734272112662,\n" + + "\t\t\"lon\": 116.72911631453036\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.197379191549075,\n" + + "\t\t\"lon\": 116.72890982812105\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.197417565369314,\n" + + "\t\t\"lon\": 116.72869447869044\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19746052080799,\n" + + "\t\t\"lon\": 116.72845641541247\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19750040582118,\n" + + "\t\t\"lon\": 116.72823569991117\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19753999704064,\n" + + "\t\t\"lon\": 116.72801998373052\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19757796882569,\n" + + "\t\t\"lon\": 116.72781280504363\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.197617062364586,\n" + + "\t\t\"lon\": 116.72759949431683\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19765391602761,\n" + + "\t\t\"lon\": 116.72739776789756\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19768973009218,\n" + + "\t\t\"lon\": 116.72719980764646\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.197726191028785,\n" + + "\t\t\"lon\": 116.72699719861669\n" + + "\t}, {\n" + + "\t\t\"lat\": 40.19776233489642,\n" + + "\t\t\"lon\": 116.72679516155276\n" + + "\t}]}\n"; + + List list = new ArrayList<>(); - for (int i = 0; i < 200 ; i++){ - MessagePad.Location.Builder builder = MessagePad.Location.newBuilder(); - if (i <= 100){ - builder.setLatitude(40.199248903658166); - builder.setLongitude(116.73435586102245 + i * 0.0001); - }else { - builder.setLatitude(40.199248903658166 + i * 0.0001); - builder.setLongitude(116.73435586102245 + 100 * 0.0001); + + try { + JSONObject jsonObject = new JSONObject(listStr); + JSONArray jsonElements = jsonObject.getJSONArray("models"); + for (int i = 0; i < jsonElements.length(); i++){ + JSONObject s = jsonElements.getJSONObject(i); + MessagePad.Location.Builder builder = MessagePad.Location.newBuilder(); + builder.setLatitude(s.getDouble("lat")); + builder.setLongitude(s.getDouble("lon")); + list.add(builder.build()); } - list.add(builder.build()); + List list1 = CoordinateConverterFrom84ForList(getContext(),list); + MogoOCHTaxiModelNew.getInstance().updateOrderRoute(list1); + } catch (JSONException e) { + e.printStackTrace(); } - MogoOCHTaxiModelNew.getInstance().updateOrderRoute(list); }); } + + public List CoordinateConverterFrom84ForList(Context mContext, List mogoLatLngList) { + List list = new ArrayList<>(); + for (MessagePad.Location m : mogoLatLngList) { + LatLng mogoLatLng = CoordinateConverterFrom84(mContext, m); + MessagePad.Location.Builder builder = MessagePad.Location.newBuilder(); + builder.setLatitude(mogoLatLng.latitude); + builder.setLongitude(mogoLatLng.longitude); + list.add(builder.build()); + } + return list; + } + + public LatLng CoordinateConverterFrom84(Context mContext, MessagePad.Location mogoLatLng) { + CoordinateConverter mCoordinateConverter = new CoordinateConverter(mContext); + mCoordinateConverter.from(CoordinateConverter.CoordType.GPS); + mCoordinateConverter.coord(new LatLng(mogoLatLng.getLatitude(), mogoLatLng.getLongitude())); + LatLng latLng = mCoordinateConverter.convert(); + return latLng; + } + public void clickTestBar(){ View testBar = findViewById(R.id.module_och_taxi_order_status_change_test_bar); if (testBar.getVisibility() == View.VISIBLE) { diff --git a/app/src/androidTest/java/com/mogo/functions/test/AutoPilotBadCaseTest.kt b/app/src/androidTest/java/com/mogo/functions/test/AutoPilotBadCaseTest.kt index 33b6edda37..41984bba30 100644 --- a/app/src/androidTest/java/com/mogo/functions/test/AutoPilotBadCaseTest.kt +++ b/app/src/androidTest/java/com/mogo/functions/test/AutoPilotBadCaseTest.kt @@ -3,8 +3,8 @@ package com.mogo.functions.test import androidx.test.core.app.ActivityScenario import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest -import com.mogo.eagle.core.data.autopilot.AutoPilotRecordResult import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager +import com.mogo.eagle.core.function.hmi.ui.MoGoHmiFragment import com.mogo.eagle.core.function.main.MainLauncherActivity import kotlinx.coroutines.* import kotlinx.coroutines.flow.* @@ -14,6 +14,7 @@ import org.junit.runner.RunWith import record_cache.RecordPanelOuterClass import java.text.SimpleDateFormat import java.util.* +import java.util.concurrent.Executors import java.util.concurrent.TimeUnit import kotlin.random.Random @@ -31,7 +32,7 @@ class AutoPilotBadCaseTest { @ExperimentalCoroutinesApi @Test fun showBadCaseEntrance1(): Unit = runBlocking(Dispatchers.Main) { - delay(5000) + ensureMoGoHmiFragmentShow() var index = 0 (1 until 50) .map { it } @@ -61,7 +62,7 @@ class AutoPilotBadCaseTest { @ExperimentalCoroutinesApi @Test fun showBadCaseEntrance2(): Unit = runBlocking(Dispatchers.Main) { - delay(5000) + ensureMoGoHmiFragmentShow() var index = 0 (1 until 50) .map { it } @@ -118,4 +119,29 @@ class AutoPilotBadCaseTest { .collect() delay(TimeUnit.HOURS.toMillis(2)) } + + private suspend fun ensureMoGoHmiFragmentShow(): MoGoHmiFragment = suspendCancellableCoroutine { + launch.onActivity { itx -> + val executor = Executors.newSingleThreadScheduledExecutor() + executor.scheduleAtFixedRate({ + var find = + itx.supportFragmentManager.fragments.find { it is MoGoHmiFragment } as? MoGoHmiFragment + while (find == null) { + find = + itx.supportFragmentManager.fragments.find { it is MoGoHmiFragment } as? MoGoHmiFragment + + } + while (!find.isResumed) { + Thread.sleep(500) + } + it.resumeWith(Result.success(find)) + try { + Thread.sleep(500) + executor.shutdownNow() + } catch (e: Throwable) { + e.printStackTrace() + } + }, 50, 500, TimeUnit.MILLISECONDS) + } + } } \ No newline at end of file diff --git a/config.gradle b/config.gradle index 24442788dd..bc53544d66 100644 --- a/config.gradle +++ b/config.gradle @@ -28,7 +28,7 @@ ext { androidxcardview : "androidx.cardview:cardview:1.0.0", localbroadcastmanager : "androidx.localbroadcastmanager:localbroadcastmanager:1.0.0", // flexbox - flexbox : 'com.google.android:flexbox:2.0.1', + flexbox : 'com.google.android.flexbox:flexbox:3.0.0', // 测试 junit : "junit:junit:4.12", androidxjunit : "androidx.test.ext:junit:1.1.2", diff --git a/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/MoGoAutopilotProvider.kt b/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/MoGoAutopilotProvider.kt index ae04c9f6cd..ec438bc1e4 100644 --- a/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/MoGoAutopilotProvider.kt +++ b/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/MoGoAutopilotProvider.kt @@ -35,6 +35,7 @@ import com.zhidao.support.adas.high.AdasManager import com.zhidao.support.adas.high.AdasOptions import com.zhidao.support.adas.high.bean.IPCUpgradeInfo import com.zhidao.support.adas.high.common.Constants +import com.zhidao.support.adas.high.common.Constants.IPC_CONNECTION_STATUS import com.zhidao.support.adas.high.common.CupidLogUtils import io.netty.channel.Channel import java.util.concurrent.TimeUnit @@ -332,4 +333,11 @@ class MoGoAutopilotProvider : override fun getGlobalPath() { AdasManager.getInstance().sendGlobalPathReq() } + + /** + * 车机与工控机是否连上了 + */ + override fun isConnected(): Boolean { + return AdasManager.getInstance().ipcConnectionStatus == IPC_CONNECTION_STATUS.CONNECTED + } } \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/build.gradle b/core/function-impl/mogo-core-function-devatools/build.gradle index 89f499a564..da21494c74 100644 --- a/core/function-impl/mogo-core-function-devatools/build.gradle +++ b/core/function-impl/mogo-core-function-devatools/build.gradle @@ -82,6 +82,7 @@ dependencies { implementation rootProject.ext.dependencies.androidxappcompat implementation rootProject.ext.dependencies.androidxconstraintlayout implementation rootProject.ext.dependencies.androidxrecyclerview + implementation rootProject.ext.dependencies.flexbox if (Boolean.valueOf(USE_MAVEN_PACKAGE)) { implementation rootProject.ext.dependencies.mogoserviceapi diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt index 251d6abdc6..7b7ea646ed 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt @@ -8,6 +8,7 @@ import com.mogo.eagle.core.data.chain.ChainLogParam import com.mogo.eagle.core.data.constants.MogoServicePaths import com.mogo.eagle.core.function.api.devatools.IDevaToolsProvider import com.zhjt.mogo_core_function_devatools.badcase.BadCaseManager +import com.zhjt.mogo_core_function_devatools.feedback.FeedbackManager import com.zhjt.mogo_core_function_devatools.logcatch.MogoLogCatchManager import com.zhjt.mogo_core_function_devatools.trace.TraceManager.Companion.traceManager import record_cache.RecordPanelOuterClass @@ -56,8 +57,11 @@ class DevaToolsProvider : IDevaToolsProvider { BadCaseManager.onReceiveBadCaseRecord(record) } + override fun showFeedbackWindow(ctx: Context) { + FeedbackManager.showFeedbackWindow(ctx) + } + override fun onDestroy() { MogoLogCatchManager.onDestroy() } - } \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/BadCaseManager.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/BadCaseManager.kt index 2bf4e937eb..1d6a1531e9 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/BadCaseManager.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/BadCaseManager.kt @@ -4,6 +4,7 @@ import android.transition.AutoTransition import android.transition.TransitionManager import android.view.View import android.view.ViewGroup +import android.view.WindowManager import androidx.lifecycle.Lifecycle.Event import androidx.lifecycle.Lifecycle.Event.ON_DESTROY import androidx.lifecycle.LifecycleCoroutineScope @@ -16,9 +17,10 @@ import com.mogo.eagle.core.function.call.hmi.CallerHmiManager import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.kotlin.lifecycleOwner import com.mogo.eagle.core.utilcode.kotlin.onClick +import com.mogo.eagle.core.utilcode.kotlin.toast import com.mogo.eagle.core.utilcode.util.ToastUtils import com.mogo.eagle.core.utilcode.util.Utils -import com.zhjt.mogo_core_function_devatools.badcase.api.entity.BadCaseResponse.Reason +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.BadCaseResponse.Reason import com.zhjt.mogo_core_function_devatools.badcase.biz.BadCasePresenter import com.zhjt.mogo_core_function_devatools.badcase.biz.BadCaseView import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord @@ -36,8 +38,7 @@ internal object BadCaseManager : LifecycleEventObserver { * 超过此时间,case入口自动消失 */ - private val CASE_EXPIRE_DURATION: Long = - TimeUnit.HOURS.toMillis(4)/* TimeUnit.SECONDS.toMillis(10) */ + private val CASE_EXPIRE_DURATION: Long = TimeUnit.HOURS.toMillis(4)/* TimeUnit.SECONDS.toMillis(10) */ private var onShow: (() -> Unit)? = null private var onHide: (() -> Unit)? = null @@ -190,20 +191,20 @@ internal object BadCaseManager : LifecycleEventObserver { hideFloat = null }, onSelect = { reason -> - val uploadResult = - presenter.upload(mutableMapOf().also { itx -> - itx["carLicense"] = MoGoAiCloudClientConfig.getInstance().sn - itx["filename"] = record.fileName ?: "" - itx["filesize"] = record.total.toString() - itx["key"] = record.key ?: "" - itx["reason"] = reason.reason ?: "" - itx["duration"] = record.duration.toInt().toString() - itx["timestamp"] = record.timestamp - }) + val uploadResult = presenter.upload(mutableMapOf().also { itx -> + itx["carLicense"] = MoGoAiCloudClientConfig.getInstance().sn + itx["filename"] = record.fileName ?: "" + itx["filesize"] = record.total.toString() + itx["key"] = record.key ?: "" + itx["reason"] = reason.reason ?: "" + itx["duration"] = record.duration.toInt().toString() + itx["timestamp"] = record.timestamp + itx["channel"] = "0" + }) if (uploadResult == null || uploadResult.code != 200) { - ToastUtils.showShort("接管反馈失败") + it.context.toast("上报失败") } else { - ToastUtils.showShort("接管反馈成功") + it.context.toast("上报成功") record.consumed = true withContext(Dispatchers.IO) { presenter.deleteRecord(record) @@ -246,14 +247,11 @@ internal object BadCaseManager : LifecycleEventObserver { } } - private fun showBadCaseFloat( - onDismiss: () -> Unit, - onSelect: suspend (reason: Reason) -> Unit - ) { + private fun showBadCaseFloat(onDismiss: () -> Unit, onSelect:suspend (reason: Reason) -> Unit) { val context = viewHolder?.get()?.context ?: Utils.getApp() - BadCaseView(context).also { - it.register(record, onDismiss, onSelect) - hideFloat = CallerHmiManager.showBadCaseFloat(floatView = it) + BadCaseView(context).also { itx -> + itx.register(record, onDismiss, onSelect) + hideFloat = CallerHmiManager.showFloatWindow("BadCaseFloat", floatView = itx, WindowManager.LayoutParams().also { it.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE}) } } diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/entity/BadCaseResponse.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/entity/BadCaseResponse.kt deleted file mode 100644 index e4d4382e7e..0000000000 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/entity/BadCaseResponse.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.zhjt.mogo_core_function_devatools.badcase.api.entity - -import androidx.annotation.Keep -import com.google.gson.annotations.Expose - -@Keep -internal class BadCaseResponse { - var code: Int = -1 - var data: List? = null - var msg: String? = null - var success: Boolean = false - var total: Int = -1 - - @Expose(serialize = false, deserialize = false) - var isBuildIn: Boolean = false - - @Keep - class Reason { - var id: String? = null - var reason: String? = null - - /** - * 业务字段,不参与序列化和反序列化 - */ - @Expose(deserialize = false, serialize = false) - var isChecked: Boolean = false - } -} diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCasePresenter.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCasePresenter.kt index 6bd32d01fd..2cbff00cc6 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCasePresenter.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCasePresenter.kt @@ -2,7 +2,7 @@ package com.zhjt.mogo_core_function_devatools.badcase.biz import android.util.Log import com.zhjt.mogo_core_function_devatools.badcase.BadCaseManager -import com.zhjt.mogo_core_function_devatools.badcase.api.entity.UploadResult +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.UploadResult import com.zhjt.mogo_core_function_devatools.badcase.repository.Repository import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord @@ -12,7 +12,7 @@ internal class BadCasePresenter: IBadCasePresenter { Repository() } - override suspend fun loadBadCases() = repository.loadBadCases() + override suspend fun loadBadCases(isDriven: Boolean) = repository.loadBadCases(isDriven) override suspend fun insertRecord(record: AutoPilotRecord) { try { @@ -49,4 +49,8 @@ internal class BadCasePresenter: IBadCasePresenter { Log.d(BadCaseManager.TAG, " --- 2 ----") return repository.getLastModified() } + + override suspend fun getTaskId(): Int { + return repository.getTaskId() + } } \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCaseView.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCaseView.kt index ace4779a78..732f057f5c 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCaseView.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/BadCaseView.kt @@ -21,7 +21,7 @@ import androidx.recyclerview.widget.RecyclerView import com.mogo.eagle.core.utilcode.kotlin.* import com.mogo.eagle.core.utilcode.rv.divider.CommonDividerItemDecoration import com.zhjt.mogo_core_function_devatools.R -import com.zhjt.mogo_core_function_devatools.badcase.api.entity.BadCaseResponse +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.BadCaseResponse import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord import kotlinx.android.synthetic.main.layout_badcase_collect.view.* import kotlinx.coroutines.launch @@ -58,7 +58,7 @@ internal class BadCaseView: ConstraintLayout { LayoutInflater.from(context).inflate(R.layout.layout_badcase_collect, this, true) background = ColorDrawable(Color.parseColor("#F0151D41")) isClickable = true - layoutParams = ViewGroup.LayoutParams(960.toPixels().toInt(), 1528.toPixels().toInt()) + layoutParams = ViewGroup.LayoutParams(960.PX, 1528.PX) close?.onClick { onDismiss?.invoke() } @@ -69,8 +69,8 @@ internal class BadCaseView: ConstraintLayout { } } ok?.also { - val enabled = gradient(radius = 16.toPixels().toInt(), orientation = GradientDrawable.Orientation.LEFT_RIGHT, centerX = 0.06f, startColor = Color.rgb(35, 146, 252), endColor = Color.rgb(28, 75, 252)) - val disabled = gradient(radius = 16.toPixels().toInt(), orientation = GradientDrawable.Orientation.LEFT_RIGHT, centerX = 0.06f, startColor = Color.rgb(24, 71, 129), endColor = Color.rgb(21, 46, 129)) + val enabled = gradient(radius = 16.PX, orientation = GradientDrawable.Orientation.LEFT_RIGHT, centerX = 0.06f, startColor = Color.rgb(35, 146, 252), endColor = Color.rgb(28, 75, 252)) + val disabled = gradient(radius = 16.PX, orientation = GradientDrawable.Orientation.LEFT_RIGHT, centerX = 0.06f, startColor = Color.rgb(24, 71, 129), endColor = Color.rgb(21, 46, 129)) it.background = object : StateListDrawable() {}.also { itx -> itx.addState(intArrayOf(android.R.attr.state_enabled), enabled) itx.addState(StateSet.WILD_CARD, disabled) @@ -86,7 +86,7 @@ internal class BadCaseView: ConstraintLayout { scope.launchWhenCreated { time_of_take_over?.text = "接管时间: ${SimpleDateFormat("yyyy.MM.dd HH:mm", Locale.getDefault()).format(record?.toLongTime() ?: System.currentTimeMillis())}" showLoading() - presenter.loadBadCases().also { + presenter.loadBadCases(true).also { cases = it refresh(it) } @@ -101,7 +101,7 @@ internal class BadCaseView: ConstraintLayout { it.addItemDecoration( CommonDividerItemDecoration .Builder() - .verticalInnerSpace(50.toPixels().toInt()) + .verticalInnerSpace(50.PX) .build()) it.adapter = object : RecyclerView.Adapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BadCaseViewHolder = BadCaseViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_badcase_item, parent, false)) diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/IBadCasePresenter.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/IBadCasePresenter.kt index f30877fd2a..f7a5b262d2 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/IBadCasePresenter.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/biz/IBadCasePresenter.kt @@ -1,13 +1,13 @@ package com.zhjt.mogo_core_function_devatools.badcase.biz -import com.zhjt.mogo_core_function_devatools.badcase.api.entity.BadCaseResponse -import com.zhjt.mogo_core_function_devatools.badcase.api.entity.UploadResult +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.BadCaseResponse.Reason +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.UploadResult import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord internal interface IBadCasePresenter { - suspend fun loadBadCases(): List + suspend fun loadBadCases(isDriven: Boolean): List suspend fun updateLastModified(timestamp: Long) @@ -20,4 +20,6 @@ internal interface IBadCasePresenter { suspend fun getUnConsumedRecords(): List suspend fun deleteRecord(record: AutoPilotRecord) + + suspend fun getTaskId(): Int } \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/Repository.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/Repository.kt index b4916f254d..99604fe8bf 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/Repository.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/Repository.kt @@ -3,8 +3,8 @@ package com.zhjt.mogo_core_function_devatools.badcase.repository import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.zhjt.mogo_core_function_devatools.badcase.BadCaseManager -import com.zhjt.mogo_core_function_devatools.badcase.api.entity.BadCaseResponse.Reason -import com.zhjt.mogo_core_function_devatools.badcase.api.entity.UploadResult +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.BadCaseResponse.Reason +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.UploadResult import com.zhjt.mogo_core_function_devatools.badcase.repository.db.BadCaseDbModel import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord import com.zhjt.mogo_core_function_devatools.badcase.repository.net.BadCaseNetModel @@ -25,8 +25,8 @@ internal class Repository { BadCaseStore } - suspend fun loadBadCases(): List { - return net.get()?.data?.takeIf { it.isNotEmpty() }?.also { store.updateRecords(it) } ?: store.records().takeIf { it.isNotEmpty() } ?: getBuildIn() + suspend fun loadBadCases(isDriven: Boolean): List { + return net.get()?.data?.takeIf { it.isNotEmpty() }?.also { store.updateRecords(it, isDriven) } ?: store.records(isDriven).takeIf { it.isNotEmpty() } ?: getBuildIn(isDriven) } suspend fun uploadLastModified(timestamp: Long) { @@ -38,40 +38,44 @@ internal class Repository { return store.getLastModified() } - private fun getBuildIn(): List { + private fun getBuildIn(isDriven: Boolean): List { CallerLogger.d("$M_DEVA${BadCaseManager.TAG}", "-- load cases from buildin -- 1 --") val data = mutableListOf() - data += Reason().also { - it.id = "1" - it.reason = "变道有干扰" - } - data += Reason().also { - it.id = "2" - it.reason = "遇红绿灯未停车" - } - data += Reason().also { - it.id = "3" - it.reason = "遇障碍物未停车" - } - data += Reason().also { - it.id = "4" - it.reason = "无法绕行" - } - data += Reason().also { - it.id = "5" - it.reason = "画龙" - } - data += Reason().also { - it.id = "6" - it.reason = "转弯过于靠近路侧" - } - data += Reason().also { - it.id = "7" - it.reason = "无故退出自动驾驶" - } - data += Reason().also { - it.id = "8" - it.reason = "其它" + if (isDriven) { + data += Reason().also { + it.id = "1" + it.reason = "变道有干扰" + } + data += Reason().also { + it.id = "2" + it.reason = "遇红绿灯未停车" + } + data += Reason().also { + it.id = "3" + it.reason = "遇障碍物未停车" + } + data += Reason().also { + it.id = "4" + it.reason = "无法绕行" + } + data += Reason().also { + it.id = "5" + it.reason = "画龙" + } + data += Reason().also { + it.id = "6" + it.reason = "转弯过于靠近路侧" + } + data += Reason().also { + it.id = "7" + it.reason = "无故退出自动驾驶" + } + data += Reason().also { + it.id = "8" + it.reason = "其它" + } + } else { + TODO() } return data } @@ -91,4 +95,8 @@ internal class Repository { suspend fun getAllUnConsumedRecord(): List? { return db.dao().getAllUnConsumedRecords() } + + suspend fun getTaskId(): Int { + return store.getTaskIdAndIncrement() + } } \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/BadCaseNetModel.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/BadCaseNetModel.kt index 6fdb7e6f1e..40702a3b3c 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/BadCaseNetModel.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/BadCaseNetModel.kt @@ -4,9 +4,9 @@ import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_ import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.network.MoGoRetrofitFactory import com.zhjt.mogo_core_function_devatools.badcase.BadCaseManager -import com.zhjt.mogo_core_function_devatools.badcase.api.BadCaseApi -import com.zhjt.mogo_core_function_devatools.badcase.api.entity.BadCaseResponse -import com.zhjt.mogo_core_function_devatools.badcase.api.entity.UploadResult +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.BadCaseApi +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.BadCaseResponse +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.UploadResult import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseHost internal class BadCaseNetModel { diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/BadCaseApi.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/api/BadCaseApi.kt similarity index 64% rename from core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/BadCaseApi.kt rename to core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/api/BadCaseApi.kt index 07350f1355..989a46e1ad 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/BadCaseApi.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/api/BadCaseApi.kt @@ -1,7 +1,7 @@ -package com.zhjt.mogo_core_function_devatools.badcase.api +package com.zhjt.mogo_core_function_devatools.badcase.repository.net.api -import com.zhjt.mogo_core_function_devatools.badcase.api.entity.BadCaseResponse -import com.zhjt.mogo_core_function_devatools.badcase.api.entity.UploadResult +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.BadCaseResponse +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.UploadResult import retrofit2.Response import retrofit2.http.FieldMap import retrofit2.http.FormUrlEncoded diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/api/entity/BadCaseResponse.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/api/entity/BadCaseResponse.kt new file mode 100644 index 0000000000..27dfff91ca --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/api/entity/BadCaseResponse.kt @@ -0,0 +1,45 @@ +package com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity + +import androidx.annotation.Keep +import com.google.gson.annotations.Expose + +@Keep +internal class BadCaseResponse { + var code: Int = -1 + var data: List? = null + var msg: String? = null + var success: Boolean = false + var total: Int = -1 + + @Expose(serialize = false, deserialize = false) + var isBuildIn: Boolean = false + + @Keep + class Reason { + var id: String? = null + var reason: String? = null + + /** + * 业务字段,不参与序列化和反序列化 + */ + @Expose(deserialize = false, serialize = false) + var isChecked: Boolean = false + + + override fun equals(other: Any?): Boolean { + if (javaClass != other?.javaClass) return false + other as Reason + if (id != other.id) return false + if (reason != other.reason) return false + if (isChecked != other.isChecked) return false + return true + } + + override fun hashCode(): Int { + var result = id?.hashCode() ?: 0 + result = 31 * result + (reason?.hashCode() ?: 0) + result = 31 * result + isChecked.hashCode() + return result + } + } +} diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/entity/UploadResult.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/api/entity/UploadResult.kt similarity index 80% rename from core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/entity/UploadResult.kt rename to core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/api/entity/UploadResult.kt index 8661560732..ac7babc0c3 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/api/entity/UploadResult.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/net/api/entity/UploadResult.kt @@ -1,4 +1,4 @@ -package com.zhjt.mogo_core_function_devatools.badcase.api.entity +package com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity import androidx.annotation.Keep diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/store/BadCaseStore.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/store/BadCaseStore.kt index 0ad0314a3a..6eaf12a945 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/store/BadCaseStore.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/badcase/repository/store/BadCaseStore.kt @@ -7,7 +7,7 @@ import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_ import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.util.Utils import com.zhjt.mogo_core_function_devatools.badcase.BadCaseManager -import com.zhjt.mogo_core_function_devatools.badcase.api.entity.BadCaseResponse.Reason +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.BadCaseResponse.Reason import com.zhjt.mogo_core_function_devatools.badcase.generated.BadCauses import com.zhjt.mogo_core_function_devatools.badcase.generated.Cause import kotlinx.coroutines.FlowPreview @@ -55,15 +55,10 @@ internal object BadCaseStore { private val store: DataStore by lazy { - DataStoreFactory.create(serializer = serializer) { - File( - Utils.getApp().filesDir, - "bad_cases.pb" - ) - } + DataStoreFactory.create(serializer = serializer) { File(Utils.getApp().filesDir, "bad_cases.pb") } } - suspend fun updateRecords(reasons: List): BadCauses { + suspend fun updateRecords(reasons: List, isDriven: Boolean): BadCauses { CallerLogger.d("$M_DEVA${BadCaseManager.TAG}", "--- updateRecords ---") val data = mutableListOf() reasons.forEach { itx -> @@ -74,7 +69,11 @@ internal object BadCaseStore { } } return store.updateData { itx -> - itx.toBuilder().clearData().addAllData(data).build() + if (isDriven) { + itx.toBuilder().clearDrivenData().addAllDrivenData(data).build() + } else { + itx.toBuilder().clearDrivingData().addAllDrivingData(data).build() + } } } @@ -101,10 +100,10 @@ internal object BadCaseStore { } @OptIn(FlowPreview::class) - suspend fun records(): List { - CallerLogger.d("$M_DEVA${BadCaseManager.TAG}", "-- load cases from pb -- 1 -- ") + suspend fun records(isDriven: Boolean): List { val causes = store.data.firstOrNull() - return causes?.dataList?.map { + val list = if (isDriven) causes?.drivenDataList else causes?.drivingDataList + return list?.map { Reason().also { itx -> itx.id = it.id itx.reason = it.reason @@ -114,4 +113,18 @@ internal object BadCaseStore { acc } ?: emptyList() } + + suspend fun getTaskIdAndIncrement(): Int { + val causes = store.data.firstOrNull() + val ret = causes?.taskId ?: 0 + return ret.also { + store.updateData { itx -> + var old = ret + if (old == Int.MAX_VALUE) { + old = 0 + } + itx.toBuilder().setTaskId(old + 1).build() + } + } + } } \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/FeedbackManager.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/FeedbackManager.kt new file mode 100644 index 0000000000..6b3ed93c25 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/FeedbackManager.kt @@ -0,0 +1,210 @@ +package com.zhjt.mogo_core_function_devatools.feedback + +import android.content.Context +import android.text.TextUtils +import android.util.Log +import android.view.WindowManager +import android.widget.TextView +import com.mogo.cloud.passport.MoGoAiCloudClientConfig +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager +import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager +import com.mogo.eagle.core.function.call.hmi.CallerHmiManager +import com.mogo.eagle.core.utilcode.kotlin.onDetach +import com.mogo.eagle.core.utilcode.kotlin.safeCancel +import com.mogo.eagle.core.utilcode.kotlin.scope +import com.mogo.eagle.core.utilcode.kotlin.toast +import com.mogo.eagle.core.utilcode.mogo.toast.TipToast +import com.mogo.eagle.core.utilcode.util.ThreadUtils +import com.zhjt.mogo_core_function_devatools.R +import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.BadCaseResponse.Reason +import com.zhjt.mogo_core_function_devatools.badcase.toRecord +import com.zhjt.mogo_core_function_devatools.feedback.biz.FeedBackView +import com.zhjt.mogo_core_function_devatools.feedback.biz.bean.Feedback.BadCase +import com.zhjt.mogo_core_function_devatools.feedback.biz.impl.FeedbackPresenter +import com.zhjt.mogo_core_function_devatools.feedback.callback.IFeedbackCallback +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.Channel +import record_cache.RecordPanelOuterClass +import java.lang.IllegalStateException +import kotlin.Result.Companion + +internal object FeedbackManager { + + const val TAG = "feedback" + private var hideFloat: (() -> Unit)? = null + private val presenter by lazy { FeedbackPresenter() } + + @OptIn(ExperimentalCoroutinesApi::class) + private var autoPilotCallback = Channel(Channel.RENDEZVOUS) + @Synchronized + get() = if (field.isClosedForReceive || field.isClosedForSend) { + field = Channel(Channel.RENDEZVOUS) + field + } else field + + + fun showFeedbackWindow(ctx: Context) { + CallerHmiManager.showFloatWindow("FeedbackWindow", FeedBackView(ctx).also { itx -> + itx.registerCallback(object : IFeedbackCallback { + override fun onClose() { + hideFloat?.invoke() + } + override fun onBadCaseItemClicked(reason: Reason) { + val oldData = itx.adapter.data ?: return + if (reason.isChecked) { + return + } + reason.isChecked = true + val badCase = oldData.firstOrNull() as? BadCase + badCase?.reasons?.filterNot { it.id == reason.id }?.forEach { + it.isChecked = false + } + itx.adapter.notifyItemChanged(0) + } + override fun onStartBadCaseRecord(record: TextView) { + if (!CallerAutoPilotManager.isConnected()) { + TipToast.shortTip("请检查车机与域控制器连接是否正常") + return + } + val data = itx.adapter.data ?: return + val badCase = data.firstOrNull() as? BadCase ?: return + val checked = badCase.reasons.find { it.isChecked } + if (checked == null) { + TipToast.shortTip("请选择一个Case") + return + } + record.scope.launch { + val taskId = presenter.getBadCaseTaskId() + val listener = object : IMoGoAutopilotIdentifyListener { + override fun onAutopilotRecordResult(recordPanel: RecordPanelOuterClass.RecordPanel) { + super.onAutopilotRecordResult(recordPanel) + val newRecord = recordPanel.toRecord() ?: return + Log.d(TAG, "-- 收到工控机录制任务回调 -- $recordPanel") + if (newRecord.type == 1 && newRecord.id == taskId) { + if (newRecord.stat == 100 || newRecord.stat == 101) { + Log.d(TAG, "录制Bag完成, 触发结束录制全量日志 ...") + stopRecordLog(newRecord) + launch { + send(newRecord) + } + } + if (newRecord.stat == 300) { + Log.d(TAG, "录制Bag开始, 触发录制全量日志 ...") + startRecordLog(newRecord) + } + } + } + } + CallerAutopilotIdentifyListenerManager.addListener("Feedback", listener) + record.onDetach { + CallerAutopilotIdentifyListenerManager.removeListener("Feedback") + hideFloat = null + } + record.text = "结束录制" + record.setTag(R.id.feed_back_badcase_tag, 1) + record.setTag(R.id.feed_back_badcase_taskid_tag, taskId) + recordBag(1, taskId, 20) + Log.d(TAG, "延时20秒开始....") + delay(20000) //延时20秒 + Log.d(TAG, "延时20秒结束....") + stopRecordBag(1, taskId) + upload(record.context, badCase, checked) + }.also { + record.setTag(R.id.feed_back_badcase_job, it) + } + } + + override fun onStopBadCaseRecord(record: TextView) { + val data = itx.adapter.data ?: return + val badCase = data.firstOrNull() as? BadCase ?: return + val checked = badCase.reasons.find { it.isChecked } ?: throw IllegalStateException("这种状态不存在") + val taskId = (record.getTag(R.id.feed_back_badcase_taskid_tag) as? Int) ?: throw IllegalStateException("TaskId 不存在") + val oldJob = record.getTag(R.id.feed_back_badcase_job) as? Job + record.scope.launch { + stopRecordBag(1, taskId) + oldJob?.safeCancel() + upload(record.context, badCase, checked) + } + } + }) + }, WindowManager.LayoutParams().also { it.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN }).also { hideFloat = it } + } + + private fun startRecordLog(record: AutoPilotRecord) { + //val fileName = record.fileName + //TODO zhongchao 添加全量日志开始录制 + } + + private fun stopRecordLog(newRecord: AutoPilotRecord) { + //val fileName = record.fileName + //TODO zhongchao 添加全量日志结束录制 + } + + private suspend fun upload(ctx: Context, badCase: BadCase, checked: Reason) { + val result = receive() + val remark = badCase.remark.text + presenter.upload(mutableMapOf().also { itx -> + itx["carLicense"] = MoGoAiCloudClientConfig.getInstance().sn + itx["filename"] = result.fileName ?: "" + itx["filesize"] = result.total.toString() + itx["key"] = result.key ?: "" + itx["reason"] = checked.reason ?: "" + itx["duration"] = result.duration.toInt().toString() + itx["timestamp"] = result.timestamp + itx["channel"] = "1" + if (!TextUtils.isEmpty(remark)) { + itx["remark"] = remark.toString() + } + }).also { + if (it == null || it.code != 200) { + ctx.toast("上报失败") + } else { + ctx.toast("上报成功") + hideFloat?.invoke() + } + } + } + + private suspend fun send(record: AutoPilotRecord) = autoPilotCallback.send(record) + + private suspend fun receive(): AutoPilotRecord = autoPilotCallback.receive() + + private suspend fun recordBag(type: Int, id: Int, duration: Int) = suspendCancellableCoroutine { + val future = ThreadUtils.getIoPool().submit { + try { + CallerAutoPilotManager.recordPackage(type, id, duration) + it.resumeWith(Result.success(Unit)) + } catch (t: Throwable) { + it.resumeWith(Companion.failure(t)) + } + } + it.invokeOnCancellation { + try { + future.cancel(true) + } catch (t: Throwable) { + t.printStackTrace() + } + + } + } + + private suspend fun stopRecordBag(type: Int, id: Int) = suspendCancellableCoroutine { + val future = ThreadUtils.getIoPool().submit { + try { + CallerAutoPilotManager.stopRecord(type, id) + it.resumeWith(Result.success(Unit)) + } catch (t: Throwable) { + it.resumeWith(Companion.failure(t)) + } + } + it.invokeOnCancellation { + try { + future.cancel(true) + } catch (t: Throwable) { + t.printStackTrace() + } + } + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/FeedBackView.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/FeedBackView.kt new file mode 100644 index 0000000000..290c2ab5c9 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/FeedBackView.kt @@ -0,0 +1,93 @@ +package com.zhjt.mogo_core_function_devatools.feedback.biz + +import android.content.Context +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.GradientDrawable +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.lifecycle.Lifecycle.Event.ON_DESTROY +import androidx.lifecycle.lifecycleScope +import androidx.recyclerview.widget.LinearLayoutManager +import com.mogo.eagle.core.utilcode.kotlin.* +import com.zhjt.mogo_core_function_devatools.R +import com.zhjt.mogo_core_function_devatools.feedback.biz.adapter.FeedbackAdapter +import com.zhjt.mogo_core_function_devatools.feedback.biz.bean.Feedback +import com.zhjt.mogo_core_function_devatools.feedback.biz.impl.FeedbackPresenter +import com.zhjt.mogo_core_function_devatools.feedback.callback.IFeedbackCallback +import kotlinx.android.synthetic.main.layout_fb.view.* + + +internal class FeedBackView : ConstraintLayout { + + private var cb: IFeedbackCallback? = null + + private val presenter by lazy { + FeedbackPresenter() + } + + private val scope by lazy { + lifecycleOwner.lifecycleScope + } + + internal val adapter by lazy { + FeedbackAdapter() + } + + constructor(context: Context) : this(context, null) + constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { + LayoutInflater.from(context).inflate(R.layout.layout_fb, this, true).also { + observe(arrayOf(ON_DESTROY)) { itx -> + if (itx == ON_DESTROY) { + cb = null + } + } + } + layoutParams = ViewGroup.LayoutParams(960.PX, 1528.PX) + close.onClick { + cb?.onClose() + } + + top_mask?.background = gradient(orientation = GradientDrawable.Orientation.TOP_BOTTOM, startColor = Color.parseColor("#151D41"), endColor = Color.parseColor("#05151D41")) + background = ColorDrawable(Color.parseColor("#F0151D41")) + rv?.also { + it.fixGestureConflictForViews(listOf(R.id.et)) + it.itemAnimator?.run { + changeDuration = 0 + addDuration = 0 + moveDuration = 0 + removeDuration = 0 + } + it.adapter = adapter + it.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + loadFeedbackAndRefresh() + } + } + + private fun loadFeedbackAndRefresh() { + scope.launchWhenCreated { + showLoading() + presenter.loadFeedBacks().also { + adapter.data = it + } + hideLoading() + } + } + + private fun showLoading() { + pb?.visibility = View.VISIBLE + } + + private fun hideLoading() { + pb?.visibility = View.GONE + } + + fun registerCallback(cb: IFeedbackCallback) { + this.cb = cb + this.adapter.setCallback(cb) + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/IFeedbackPresenter.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/IFeedbackPresenter.kt new file mode 100644 index 0000000000..31dfbea827 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/IFeedbackPresenter.kt @@ -0,0 +1,14 @@ +package com.zhjt.mogo_core_function_devatools.feedback.biz + +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.UploadResult +import com.zhjt.mogo_core_function_devatools.feedback.biz.bean.Feedback + + +internal interface IFeedbackPresenter { + + suspend fun loadFeedBacks(): List + + suspend fun getBadCaseTaskId(): Int + + suspend fun upload(params: Map): UploadResult? +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/adapter/FeedbackAdapter.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/adapter/FeedbackAdapter.kt new file mode 100644 index 0000000000..5867a49358 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/adapter/FeedbackAdapter.kt @@ -0,0 +1,63 @@ +package com.zhjt.mogo_core_function_devatools.feedback.biz.adapter + +import android.util.Log +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.RecyclerView +import com.zhjt.mogo_core_function_devatools.feedback.FeedbackManager +import com.zhjt.mogo_core_function_devatools.feedback.biz.adapter.vh.BadCaseFBViewHolder +import com.zhjt.mogo_core_function_devatools.feedback.biz.adapter.vh.base.FeedbackViewHolder +import com.zhjt.mogo_core_function_devatools.feedback.biz.bean.Feedback +import com.zhjt.mogo_core_function_devatools.feedback.biz.bean.Feedback.BadCase +import com.zhjt.mogo_core_function_devatools.feedback.biz.diff.FeedbackDiffCallback +import com.zhjt.mogo_core_function_devatools.feedback.callback.IFeedbackCallback + +internal class FeedbackAdapter: RecyclerView.Adapter>() { + + companion object { + const val ITEM_TYPE_BAD_CASE = 0x0101 + } + + private var cb: IFeedbackCallback? = null + + var data: List? = null + @Synchronized + set(value) { + val result = DiffUtil.calculateDiff(FeedbackDiffCallback(field, value)) + result.dispatchUpdatesTo(this) + field = value + } + + override fun getItemViewType(position: Int): Int { + val data = data ?: return super.getItemViewType(position) + when(val item = data[position]) { + is BadCase -> { + Log.d(FeedbackManager.TAG, "item->$item") + return ITEM_TYPE_BAD_CASE + } + } + return super.getItemViewType(position) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FeedbackViewHolder { + when (viewType) { + ITEM_TYPE_BAD_CASE -> { + return BadCaseFBViewHolder(cb, parent) as FeedbackViewHolder + } + else -> { + throw IllegalStateException("不支持ViewType: $viewType") + } + } + } + + override fun onBindViewHolder(holder: FeedbackViewHolder, position: Int) { + val item = data?.get(position) ?: return + holder.onBind(item, position) + } + + override fun getItemCount(): Int = data?.size ?: 0 + + fun setCallback(cb: IFeedbackCallback) { + this.cb = cb + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/adapter/vh/BadCaseFBViewHolder.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/adapter/vh/BadCaseFBViewHolder.kt new file mode 100644 index 0000000000..335d25039d --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/adapter/vh/BadCaseFBViewHolder.kt @@ -0,0 +1,155 @@ +package com.zhjt.mogo_core_function_devatools.feedback.biz.adapter.vh + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.graphics.drawable.GradientDrawable.Orientation.LEFT_RIGHT +import android.graphics.drawable.StateListDrawable +import android.text.Selection +import android.text.TextUtils +import android.text.TextUtils.TruncateAt.END +import android.util.StateSet +import android.util.TypedValue +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.EditText +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.TextView +import androidx.core.content.ContextCompat +import com.google.android.flexbox.FlexboxLayout +import com.mogo.eagle.core.utilcode.kotlin.* +import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.zhjt.mogo_core_function_devatools.R +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.BadCaseResponse.Reason +import com.zhjt.mogo_core_function_devatools.feedback.biz.adapter.vh.base.FeedbackViewHolder +import com.zhjt.mogo_core_function_devatools.feedback.biz.bean.Feedback.BadCase +import com.zhjt.mogo_core_function_devatools.feedback.callback.IFeedbackCallback + +@SuppressLint("SetTextI18n") +internal class BadCaseFBViewHolder(cb: IFeedbackCallback?, parent: ViewGroup): FeedbackViewHolder(cb, + LayoutInflater + .from(parent.context) + .inflate(R.layout.layout_fb_badcase, parent, false)) { + + private val flex by lazy { + itemView.findViewById(R.id.flex) + } + + private val et by lazy { + itemView.findViewById(R.id.et) + } + + init { + itemView.findViewById(R.id.record).also { + it.background = gradient(radius = 16.PX, orientation = LEFT_RIGHT, centerX = 0.06f, startColor = Color.rgb(35, 146, 252), endColor = Color.rgb(28, 75, 252)) + it.onClick { _ -> + val flag = (it.getTag(R.id.feed_back_badcase_tag) as? Int) ?: 0 + if (flag == 0) { + cb?.onStartBadCaseRecord(it) + } else { + cb?.onStopBadCaseRecord(it) + } + } + } + + itemView.findViewById(R.id.et_root).also { + it.background = shape(solid = Color.parseColor("#263869"), radius = 20.PX) + } + val words = itemView.findViewById(R.id.words_count) + et.onClick { + et.requestFocus() + et.isFocusable = true + et.isFocusableInTouchMode = true + } + et.watch( + 200, + onCountChanged = { + words.spannableText(listOf(it.toString(), "/200"), listOf(Color.parseColor("#5EBFFF"), Color.WHITE)) + }, + onTextChanged = { + data().remark.text = it?.toString() ?: "" + }, + onReachMaxCountAction = { + ToastUtils.showShort("已超过最大字符数") + }, + onGetFocus = { + it.background = shape(solid = Color.parseColor("#263869"), radius = 20.PX, stroke = Color.parseColor("#5EBFFF")) + } + ) + } + + override fun onBind(data: BadCase, position: Int) { + super.onBind(data, position) + flex.refresh(data) + val text = data.remark.text + if (!TextUtils.isEmpty(text)) { + et.setText(text) + Selection.setSelection(et.text, et.text.length) + } + } + + private fun FlexboxLayout.refresh(data: BadCase) { + val vh = (tag as? Map<*, *> ?: emptyMap()).toMutableMap() + if (vh.isEmpty()) { + data.reasons.forEach { itx -> + val view = getBadCaseView(context) + val check = view.findViewById(R.id.check) + check.background = StateListDrawable().also { + it.addState(intArrayOf(android.R.attr.state_selected), ContextCompat.getDrawable(itemView.context, R.drawable.icon_ap_badcase_check)) + it.addState(StateSet.WILD_CARD, ContextCompat.getDrawable(itemView.context, R.drawable.icon_ap_badcase_default)) + } + check.isSelected = itx.isChecked + val reason = view.findViewById(R.id.reason) + reason.text = itx.reason + vh[itx] = ViewHolder(check, reason) + view.onClick { + cb?.onBadCaseItemClicked(itx) + } + view.layoutParams = FlexboxLayout.LayoutParams(FlexboxLayout.LayoutParams.MATCH_PARENT, FlexboxLayout.LayoutParams.WRAP_CONTENT).also { + it.flexBasisPercent = 0.5f + } + addView(view) + } + tag = vh + } else { + data.reasons.forEach { + (vh[it] as? ViewHolder)?.run { + check.isSelected = it.isChecked + reason.text = it.reason + } + } + } + } + + private fun getBadCaseView(context: Context): View { + return LinearLayout(context).also { itx -> + itx.orientation = LinearLayout.HORIZONTAL + itx.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) + itx.gravity = Gravity.CENTER_VERTICAL + + //ImageView -- check + val check = ImageView(context) + check.layoutParams = LinearLayout.LayoutParams(70.PX, 70.PX) + check.id = R.id.check + itx.addView(check) + + //TextView -- Reason + val reason = TextView(context) + reason.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { + it.marginStart = 30.PX + it.marginEnd = 20.PX + } + reason.setTextColor(Color.WHITE) + reason.setTextSize(TypedValue.COMPLEX_UNIT_PX, 42.0f) + reason.maxLines = 1 + reason.ellipsize = END + reason.id = R.id.reason + itx.addView(reason) + } + } + + private data class ViewHolder(val check: ImageView, val reason: TextView) +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/adapter/vh/base/FeedbackViewHolder.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/adapter/vh/base/FeedbackViewHolder.kt new file mode 100644 index 0000000000..d058d78327 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/adapter/vh/base/FeedbackViewHolder.kt @@ -0,0 +1,22 @@ +package com.zhjt.mogo_core_function_devatools.feedback.biz.adapter.vh.base + +import android.view.View +import androidx.annotation.CallSuper +import androidx.recyclerview.widget.RecyclerView +import com.zhjt.mogo_core_function_devatools.feedback.biz.bean.Feedback +import com.zhjt.mogo_core_function_devatools.feedback.callback.IFeedbackCallback +import java.util.concurrent.atomic.AtomicReference + +internal open class FeedbackViewHolder(internal val cb: IFeedbackCallback?, view: View): RecyclerView.ViewHolder(view) { + + private val data by lazy { AtomicReference() } + + fun data(): T { + return data.get() + } + + @CallSuper + open fun onBind(data: T, position: Int) { + this.data.set(data) + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/bean/Feedback.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/bean/Feedback.kt new file mode 100644 index 0000000000..7ee31743d4 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/bean/Feedback.kt @@ -0,0 +1,28 @@ +package com.zhjt.mogo_core_function_devatools.feedback.biz.bean + +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.BadCaseResponse.Reason + +internal sealed class Feedback { + + class BadCase(var remark: Remark, var reasons: List): Feedback() { + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + other as BadCase + if (reasons != other.reasons) return false + return true + } + + override fun hashCode(): Int { + return reasons.hashCode() + } + } +} + +/** + * 记录文本编辑框的状态 + * @param text: 文件编辑框中输入的文字 + * @param cursorPos: 光标位置 + */ +data class Remark(var text: CharSequence = "", var cursorPos: Int = 0) diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/diff/FeedbackDiffCallback.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/diff/FeedbackDiffCallback.kt new file mode 100644 index 0000000000..71da2796f2 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/diff/FeedbackDiffCallback.kt @@ -0,0 +1,25 @@ +package com.zhjt.mogo_core_function_devatools.feedback.biz.diff + +import androidx.recyclerview.widget.DiffUtil +import com.zhjt.mogo_core_function_devatools.feedback.biz.bean.Feedback +import com.zhjt.mogo_core_function_devatools.feedback.biz.bean.Feedback.BadCase + +internal class FeedbackDiffCallback(private val oldData: List?, private val newData: List?): DiffUtil.Callback() { + + override fun getOldListSize(): Int { + return oldData?.size ?: 0 + } + + override fun getNewListSize(): Int = newData?.size ?: 0 + + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean = oldData?.takeIf { it.size > oldItemPosition }?.equals(newData?.takeIf { it.size > newItemPosition }) ?: false + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + val oldItem = oldData?.get(oldItemPosition) + val newItem = newData?.get(newItemPosition) + if (oldItem == null || newItem == null) { + return false + } + return oldItem == newItem + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/impl/FeedbackPresenter.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/impl/FeedbackPresenter.kt new file mode 100644 index 0000000000..e6d89e9168 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/biz/impl/FeedbackPresenter.kt @@ -0,0 +1,28 @@ +package com.zhjt.mogo_core_function_devatools.feedback.biz.impl + +import com.zhjt.mogo_core_function_devatools.badcase.biz.BadCasePresenter +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.UploadResult +import com.zhjt.mogo_core_function_devatools.feedback.biz.IFeedbackPresenter +import com.zhjt.mogo_core_function_devatools.feedback.biz.bean.Feedback +import com.zhjt.mogo_core_function_devatools.feedback.biz.bean.Feedback.BadCase +import com.zhjt.mogo_core_function_devatools.feedback.biz.bean.Remark + +internal class FeedbackPresenter: IFeedbackPresenter { + + private val badCase by lazy { + BadCasePresenter() + } + + override suspend fun loadFeedBacks(): List = mutableListOf().also { + //添加BadCase数据 + it += BadCase(Remark(), badCase.loadBadCases(false)) + } + + override suspend fun getBadCaseTaskId(): Int { + return badCase.getTaskId() + } + + override suspend fun upload(params: Map): UploadResult? { + return badCase.upload(params) + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/callback/IFeedbackCallback.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/callback/IFeedbackCallback.kt new file mode 100644 index 0000000000..6bc329121d --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/feedback/callback/IFeedbackCallback.kt @@ -0,0 +1,28 @@ +package com.zhjt.mogo_core_function_devatools.feedback.callback + +import android.view.View +import android.widget.TextView +import com.zhjt.mogo_core_function_devatools.badcase.repository.net.api.entity.BadCaseResponse.Reason + +internal interface IFeedbackCallback { + + /** + * 点击关闭弹窗按钮时回调 + */ + fun onClose() + + /** + * BadCase某一条目被点击了 + */ + fun onBadCaseItemClicked(reason: Reason) + + /** + * 点击开始录制 + */ + fun onStartBadCaseRecord(record: TextView) + + /** + * 点击停止录制 + */ + fun onStopBadCaseRecord(record: TextView) +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/proto/badcase.proto b/core/function-impl/mogo-core-function-devatools/src/main/proto/badcase.proto index d76f5ad9a0..da39b611a9 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/proto/badcase.proto +++ b/core/function-impl/mogo-core-function-devatools/src/main/proto/badcase.proto @@ -6,7 +6,9 @@ option java_outer_classname = "BadCausesProto"; message BadCauses { int64 lastModified = 1; - repeated Cause data = 2 ; + repeated Cause drivenData = 2 ; //被动触发BadCase数据 + int32 taskId = 3; + repeated Cause drivingData = 4; //主动触发BadCase数据 } message Cause { diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/flex_divider.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/flex_divider.xml new file mode 100644 index 0000000000..1b193db85f --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/drawable/flex_divider.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_collect.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_collect.xml index fbc2562dba..3e0e5ae2a7 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_collect.xml +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_collect.xml @@ -103,7 +103,7 @@ android:id="@+id/pb" android:layout_width="wrap_content" android:layout_height="wrap_content" - style="@android:style/Widget.Holo.ProgressBar.Large" + style="@android:style/Widget.Holo.Light.ProgressBar.Inverse" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_item.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_item.xml index 339adbdf24..1c336dfac4 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_item.xml +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_badcase_item.xml @@ -2,15 +2,16 @@ + android:gravity="center_vertical" + tools:ignore="HardcodedText,PxUsage,ContentDescription"> + android:layout_marginStart="113px" /> + + + + + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_fb_badcase.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_fb_badcase.xml new file mode 100644 index 0000000000..4ecd6f8bfa --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/layout/layout_fb_badcase.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/values/ids.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/values/ids.xml new file mode 100644 index 0000000000..eefb61e677 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/values/ids.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/res/values/strings.xml b/core/function-impl/mogo-core-function-devatools/src/main/res/values/strings.xml new file mode 100644 index 0000000000..c29106e01a --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/notification/WarningFloat.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/notification/WarningFloat.kt index 483800259c..a258e6358a 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/notification/WarningFloat.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/notification/WarningFloat.kt @@ -169,6 +169,10 @@ class WarningFloat { this.config.isEnqueue = enqueue } + fun softInputMode(mode: Int) = apply { + this.config.softInputMode = mode + } + /** * 创建浮窗,包括Activity浮窗和系统浮窗,如若系统浮窗无权限,先进行权限申请 */ diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/notification/WarningFloatWindowHelper.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/notification/WarningFloatWindowHelper.kt index 2060d4c113..040628e086 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/notification/WarningFloatWindowHelper.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/notification/WarningFloatWindowHelper.kt @@ -56,6 +56,7 @@ internal class WarningFloatWindowHelper( // 获取 WindowManager windowManager = context.getSystemService(Service.WINDOW_SERVICE) as WindowManager params = WindowManager.LayoutParams().apply { + // 设置窗口类型为应用子窗口,和PopupWindow同类型 type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL format = PixelFormat.RGBA_8888 @@ -73,6 +74,10 @@ internal class WarningFloatWindowHelper( x = config.locationPair.first y = config.locationPair.second } + //添加软键盘展示模式 + if (config.softInputMode != 0) { + softInputMode = config.softInputMode + } } } @@ -89,6 +94,7 @@ internal class WarningFloatWindowHelper( // 为了避免创建的时候闪一下,我们先隐藏视图,不能直接设置GONE,否则定位会出现问题 floatingView.visibility = View.INVISIBLE // 将frameLayout添加到系统windowManager中 + windowManager.addView(frameLayout, params) // 在浮窗绘制完成的时候,设置初始坐标、执行入场动画 diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/notification/WarningNotificationConfig.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/notification/WarningNotificationConfig.kt index 51997f5177..79d025bdd4 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/notification/WarningNotificationConfig.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/notification/WarningNotificationConfig.kt @@ -19,6 +19,9 @@ data class WarningNotificationConfig( var layoutId: Int? = null, var layoutView: View? = null, + // 软键盘模式 + var softInputMode: Int = 0, + // 当前浮窗的tag var floatTag: String? = null, // 是否正在执行动画 diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt index fcb1237545..7e343fef53 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt @@ -6,6 +6,7 @@ import android.text.TextUtils import android.view.Gravity import android.view.View import android.view.WindowManager +import android.view.WindowManager.LayoutParams import android.view.animation.OvershootInterpolator import androidx.lifecycle.lifecycleScope import com.alibaba.android.arouter.facade.annotation.Route @@ -80,8 +81,6 @@ class MoGoHmiFragment : MvpFragment private var toolsView: AutoPilotAndCheckView? = null - private var autoPilotToolsFloat: WarningFloat.Builder? = null - // 检测、自动驾驶速度设置 private var toolsViewFloat: WarningFloat.Builder? = null @@ -223,6 +222,11 @@ class MoGoHmiFragment : MvpFragment override fun showDebugPanelView() { toggleDebugView() } + + override fun showFeedbackView() { + dismissToolsFloatView() + CallerDevaToolsManager.showFeedbackView(it) + } }) } toolsViewFloat = WarningFloat.with(it) @@ -874,7 +878,8 @@ class MoGoHmiFragment : MvpFragment } - override fun showBadCaseFloat(tag: String, floatView: View): () -> Unit { + override fun showFloatWindow(tag: String, floatView: View, attrs: LayoutParams?): () -> Unit { + var floatWindow: WarningFloat.Builder? WarningFloat.with(context ?: Utils.getApp()) .setTag(tag) .setLayout(floatView) @@ -884,7 +889,7 @@ class MoGoHmiFragment : MvpFragment .setAnimator(object : DefaultAnimator() { override fun enterAnim( view: View, - params: WindowManager.LayoutParams, + params: LayoutParams, windowManager: WindowManager, sidePattern: SidePattern ): Animator? = @@ -895,7 +900,7 @@ class MoGoHmiFragment : MvpFragment override fun exitAnim( view: View, - params: WindowManager.LayoutParams, + params: LayoutParams, windowManager: WindowManager, sidePattern: SidePattern ): Animator? = @@ -904,17 +909,20 @@ class MoGoHmiFragment : MvpFragment }) .addWarningStatusListener(object : IMoGoWarningStatusListener { override fun onDismiss() { - autoPilotToolsFloat = null + floatWindow = null } }) .also { - autoPilotToolsFloat = it + floatWindow = it + if (((attrs?.softInputMode?: 0) and LayoutParams.SOFT_INPUT_MASK_ADJUST) != 0) { + it.softInputMode(attrs!!.softInputMode) + } } .show() return { - autoPilotToolsFloat?.let { + floatWindow?.let { WarningFloat.dismiss(it.config.floatTag, false) - autoPilotToolsFloat = null + floatWindow = null } } } diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/tools/AutoPilotAndCheckView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/tools/AutoPilotAndCheckView.kt index 5c2eafcfff..960adf8bbf 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/tools/AutoPilotAndCheckView.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/tools/AutoPilotAndCheckView.kt @@ -13,10 +13,10 @@ import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager import com.mogo.eagle.core.function.hmi.R import com.mogo.eagle.core.function.hmi.ui.utils.KeyBoardUtil +import com.mogo.eagle.core.utilcode.kotlin.onClick import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils import com.mogo.eagle.core.utilcode.util.ToastUtils import kotlinx.android.synthetic.main.view_auto_pilot_check.view.* -import kotlinx.android.synthetic.main.view_check_system.view.* /** * @author ChenFufeng @@ -60,7 +60,9 @@ class AutoPilotAndCheckView @JvmOverloads constructor( ToastUtils.showShort("超过最大限速值60,设置失败") } else -> { + llSpeedPosition.background = resources.getDrawable(R.drawable.pilot_speed_bg) keyBoardUtil?.hideKeyboard() + etInputSpeed.clearFocus() // 设置自动驾驶速度 val isSuccess = CallerAutoPilotManager.setAutoPilotSpeed(speed) when { @@ -85,12 +87,16 @@ class AutoPilotAndCheckView @JvmOverloads constructor( ivDebugPanel.setOnClickListener { clickListener?.showDebugPanelView() } + ivDebugFeedback.onClick { + clickListener?.showFeedbackView() + } etInputSpeed.setOnTouchListener { v, _ -> if (!connectStatus) { ToastUtils.showShort("设置车速失败,请启动域控制器") keyBoardUtil?.hideKeyboard() return@setOnTouchListener true } else { + llSpeedPosition.background = resources.getDrawable(R.drawable.pilot_speed_high_light_bg) if (etInputSpeed.hasFocusable()) { if (keyBoardUtil == null) { keyBoardUtil = KeyBoardUtil(sKeyBoardView, etInputSpeed) @@ -176,5 +182,6 @@ class AutoPilotAndCheckView @JvmOverloads constructor( fun go2CheckPage() fun onClose(v: View) fun showDebugPanelView() + fun showFeedbackView() } } \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xxhdpi/debug_icon_feedback.png b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xxhdpi/debug_icon_feedback.png new file mode 100644 index 0000000000..c1e9c6a265 Binary files /dev/null and b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xxhdpi/debug_icon_feedback.png differ diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/drawable/pilot_speed_bg.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable/pilot_speed_bg.xml index e4fe7e8614..91520788bf 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/res/drawable/pilot_speed_bg.xml +++ b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable/pilot_speed_bg.xml @@ -2,5 +2,4 @@ - \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/drawable/pilot_speed_high_light_bg.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable/pilot_speed_high_light_bg.xml new file mode 100644 index 0000000000..e4fe7e8614 --- /dev/null +++ b/core/function-impl/mogo-core-function-hmi/src/main/res/drawable/pilot_speed_high_light_bg.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_auto_pilot_check.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_auto_pilot_check.xml index 738303d7d5..1cfef277b6 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_auto_pilot_check.xml +++ b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_auto_pilot_check.xml @@ -67,8 +67,7 @@ android:background="@drawable/debug_icon_nor" app:layout_constraintStart_toEndOf="@id/viewCheckStatus" app:layout_constraintTop_toTopOf="@id/viewCheckStatus" - android:layout_marginStart="142px" - /> + android:layout_marginStart="142px" /> + + + + 车辆检测 调试面板 + 反馈 车速设置 系统运行 关机 diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotProvider.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotProvider.kt index 7a018a380b..32c838fee7 100644 --- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotProvider.kt +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotProvider.kt @@ -135,5 +135,8 @@ interface IMoGoAutopilotProvider : IMoGoFunctionServerProvider { */ fun getGlobalPath() - + /** + * 域控制器是否连上了 + */ + fun isConnected(): Boolean } \ No newline at end of file diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt index 2ebc65e4cf..c6f436e918 100644 --- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt @@ -1,5 +1,6 @@ package com.mogo.eagle.core.function.api.devatools +import android.content.Context import android.view.View import com.mogo.eagle.core.data.chain.ChainLogParam import com.mogo.eagle.core.function.api.base.IMoGoFunctionServerProvider @@ -33,4 +34,9 @@ interface IDevaToolsProvider : IMoGoFunctionServerProvider { * 当工控机回调时调用 */ fun onReceiveBadCaseRecord(record: RecordPanelOuterClass.RecordPanel) + + /** + * 展示反馈页面 + */ + fun showFeedbackWindow(ctx: Context) } \ No newline at end of file diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoWaringProvider.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoWaringProvider.kt index b2166aae87..47e7b91465 100644 --- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoWaringProvider.kt +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoWaringProvider.kt @@ -1,6 +1,7 @@ package com.mogo.eagle.core.function.api.hmi.warning import android.view.View +import android.view.WindowManager.LayoutParams import com.mogo.eagle.core.data.enums.WarningDirectionEnum import com.mogo.eagle.core.data.notice.NoticeNormalData import com.mogo.eagle.core.data.notice.NoticeTrafficStylePushData @@ -212,7 +213,7 @@ interface IMoGoWaringProvider : IMoGoHmiViewProxy { * @param tag: 唯一标识 * @return 触发消失时回调 */ - fun showBadCaseFloat(tag: String = "BadCaseFloat", floatView: View): () -> Unit + fun showFloatWindow(tag: String = "BadCaseFloat", floatView: View, attrs: LayoutParams?): () -> Unit } \ No newline at end of file diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutoPilotManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutoPilotManager.kt index 69de58bf2a..5a77da1476 100644 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutoPilotManager.kt +++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutoPilotManager.kt @@ -73,6 +73,13 @@ object CallerAutoPilotManager { providerApi?.recordPackage(type, id, duration) } + /** + * 停止录制bag包 + */ + fun stopRecord(type: Int, id: Int) { + providerApi?.stopRecord(type, id) + } + fun setEnableLog(isEnableLog: Boolean) { providerApi?.setEnableLog(isEnableLog) } @@ -124,4 +131,11 @@ object CallerAutoPilotManager { fun setControlAutopilotCarAuto(isEnable: Boolean) { providerApi?.setControlAutopilotCarAuto(isEnable) } + + /** + * 车机与工控机是否连上了 + */ + fun isConnected(): Boolean { + return providerApi?.isConnected() ?: false + } } \ No newline at end of file diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt index f1bb6c6c5b..6771d327fe 100644 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt +++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt @@ -1,5 +1,7 @@ package com.mogo.eagle.core.function.call.devatools +import android.content.Context +import android.view.ContextMenu import android.view.View import com.mogo.eagle.core.data.constants.MogoServicePaths import com.mogo.eagle.core.data.chain.ChainLogParam @@ -64,4 +66,11 @@ object CallerDevaToolsManager { fun onReceiveBadCaseRecord(record: RecordPanelOuterClass.RecordPanel) { devaToolsProviderApi?.onReceiveBadCaseRecord(record) } + + /** + * 展示反馈界面 + */ + fun showFeedbackView(ctx: Context) { + devaToolsProviderApi?.showFeedbackWindow(ctx) + } } \ No newline at end of file diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt index f17a73c9cd..424815e2b8 100644 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt +++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt @@ -1,6 +1,7 @@ package com.mogo.eagle.core.function.call.hmi import android.view.View +import android.view.WindowManager.LayoutParams import com.alibaba.android.arouter.launcher.ARouter import com.mogo.eagle.core.data.constants.MoGoFragmentPaths import com.mogo.eagle.core.data.enums.WarningDirectionEnum @@ -289,10 +290,10 @@ object CallerHmiManager : CallerBase() { } /** - * 展示BadCase浮层 + * 展示浮层 */ - fun showBadCaseFloat(tag: String = "BadCaseFloat", floatView: View): (() -> Unit)? { - return waringProviderApi?.showBadCaseFloat(tag, floatView) + fun showFloatWindow(tag: String, floatView: View, attrs: LayoutParams? = null): (() -> Unit)? { + return waringProviderApi?.showFloatWindow(tag, floatView, attrs) } /** diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/logger/CallerLogger.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/logger/CallerLogger.kt deleted file mode 100644 index 85f4cb6c61..0000000000 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/logger/CallerLogger.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.mogo.eagle.core.function.call.logger - -import com.mogo.eagle.core.function.call.devatools.scene.Scene.Companion.scene -import com.mogo.eagle.core.utilcode.mogo.logger.Logger - -object CallerLogger { - - fun i(tag: String, message: String, any: Any) { - if (scene.check(tag)) { - Logger.i(tag, message, any) - } - } - - fun d(tag: String, message: String, any: Any) { - if (scene.check(tag)) { - Logger.d(tag, message, any) - } - } - - fun w(tag: String, message: String, any: Any) { - if (scene.check(tag)) { - Logger.w(tag, message, any) - } - } - - fun e(tag: String, message: String, any: Any) { - if (scene.check(tag)) { - Logger.e(tag, message, any) - } - } - -} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xxhdpi/icon_close_nor.png b/core/mogo-core-res/src/main/res/drawable-xxhdpi/icon_close_nor.png similarity index 100% rename from core/function-impl/mogo-core-function-hmi/src/main/res/drawable-xxhdpi/icon_close_nor.png rename to core/mogo-core-res/src/main/res/drawable-xxhdpi/icon_close_nor.png diff --git a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/kotlin/Extensions.kt b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/kotlin/Extensions.kt index c7ad99afb6..69d5b1209c 100644 --- a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/kotlin/Extensions.kt +++ b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/kotlin/Extensions.kt @@ -2,22 +2,41 @@ package com.mogo.eagle.core.utilcode.kotlin import android.content.Context import android.graphics.Color +import android.graphics.Rect import android.graphics.drawable.Drawable import android.graphics.drawable.GradientDrawable -import android.text.TextUtils +import android.text.* +import android.text.style.ForegroundColorSpan import android.util.TypedValue +import android.view.Gravity +import android.view.MotionEvent import android.view.View +import android.view.WindowManager +import android.widget.EditText +import android.widget.PopupWindow +import android.widget.TextView import androidx.annotation.ColorInt import androidx.annotation.IntRange import androidx.core.view.ViewCompat +import androidx.core.widget.doAfterTextChanged +import androidx.core.widget.doBeforeTextChanged +import androidx.fragment.app.FragmentActivity import androidx.lifecycle.* import androidx.lifecycle.Lifecycle.Event +import androidx.lifecycle.Lifecycle.Event.ON_DESTROY +import androidx.recyclerview.widget.RecyclerView +import com.mogo.eagle.core.utilcode.reminder.Reminder +import com.mogo.eagle.core.utilcode.reminder.api.impl.PopupWindowReminder import com.mogo.eagle.core.utilcode.util.ClickUtils import com.mogo.eagle.core.utilcode.util.R import com.mogo.eagle.core.utilcode.util.Utils import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel +import java.lang.IllegalStateException import java.util.* +import java.util.concurrent.TimeUnit +import java.util.concurrent.TimeUnit.SECONDS +import kotlin.math.abs val T.lifecycleOwner: LifecycleOwner get() = getTag(R.id.view_lifecycle_owner) as? LifecycleOwner ?: object : LifecycleOwner, LifecycleEventObserver { @@ -64,6 +83,9 @@ val T.lifecycleOwner: LifecycleOwner setTag(R.id.view_lifecycle_owner, it) } +val T.scope + get() = lifecycleOwner.lifecycleScope + fun View.onClick(block: (View) -> Unit) { this.setOnClickListener { if (ClickUtils.isClickTooFrequent(this)) { @@ -76,6 +98,9 @@ fun View.onClick(block: (View) -> Unit) { val T.lifeCycleScope: LifecycleCoroutineScope get() = (this as? LifecycleOwner)?.lifecycleScope ?: ProcessLifecycleOwner.get().lifecycleScope +val T.lifeCycleOwner: LifecycleOwner + get() = (this as? LifecycleOwner) ?: ProcessLifecycleOwner.get() + fun T.observe(target: Array, block: ((event: Event) -> Unit) ?= null) { block?.let { this.lifecycleOwner.lifecycle.addObserver(object : LifecycleEventObserver { @@ -88,6 +113,18 @@ fun T.observe(target: Array, block: ((event: Event) -> Unit) ?= } } +fun T.onDetach(block: (() -> Unit)? = null) { + block?.also { + this.lifecycleOwner.lifecycle.addObserver(object : LifecycleEventObserver { + override fun onStateChanged(source: LifecycleOwner, event: Event) { + if (event == ON_DESTROY) { + it.invoke() + } + } + }) + } +} + fun Job.safeCancel(cause: String? = null) = try { this.cancel(if (TextUtils.isEmpty(cause)) null else CancellationException(cause)) } catch (t: Throwable) { t.printStackTrace() } @@ -104,8 +141,9 @@ fun Deferred.safeCancel(cause: String? = null) = try { this.cancel(if (TextUtils.isEmpty(cause)) null else CancellationException(cause)) } catch (t: Throwable) { t.printStackTrace() } -fun shape(@ColorInt solid: Int = Color.TRANSPARENT, @ColorInt stroke: Int = Color.TRANSPARENT, @IntRange(from = 0) strokeWidth: Int = 0, @IntRange(from = 0) radius: Int = 0, radii: FloatArray = FloatArray(8).apply { Arrays.fill(this, radius.toFloat()) }, shape: Int = GradientDrawable.RECTANGLE): Drawable { +fun shape(@ColorInt solid: Int = Color.TRANSPARENT, @ColorInt stroke: Int = Color.TRANSPARENT, @IntRange(from = 0) strokeWidth: Int = 0, @IntRange(from = 0) radius: Int = 0, radii: FloatArray = FloatArray(8).apply { Arrays.fill(this, radius.toFloat()) }, shape: Int = GradientDrawable.RECTANGLE, width: Int = 0, height: Int = 0): Drawable { val drawable = GradientDrawable() + drawable.setSize(width, height) drawable.shape = shape drawable.gradientType = GradientDrawable.LINEAR_GRADIENT drawable.setColor(solid) @@ -115,7 +153,7 @@ fun shape(@ColorInt solid: Int = Color.TRANSPARENT, @ColorInt stroke: Int = Colo } fun gradient(shape: Int = GradientDrawable.RECTANGLE, @IntRange(from = 0) radius: Int = 0, radii: FloatArray = FloatArray(8).apply { Arrays.fill(this, radius.toFloat()) }, gradientType: Int = GradientDrawable.LINEAR_GRADIENT, orientation: GradientDrawable.Orientation = GradientDrawable.Orientation.TOP_BOTTOM, centerX: Float = 0.5f, centerY: Float = 0.5f, @ColorInt startColor: Int, @ColorInt centerColor: Int = startColor, @ColorInt endColor: Int): Drawable{ - val drawable = GradientDrawable(orientation, intArrayOf(endColor, centerColor, startColor)) + val drawable = GradientDrawable(orientation, intArrayOf(startColor, centerColor, endColor)) drawable.shape = shape drawable.gradientType = gradientType drawable.orientation = orientation @@ -124,7 +162,146 @@ fun gradient(shape: Int = GradientDrawable.RECTANGLE, @IntRange(from = 0) radius return drawable } -fun Int.toPixels(context: Context? = null): Float { - val ctx = context ?: Utils.getApp() - return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, this.toFloat(), ctx.resources.displayMetrics) +val Int.PX: Int + get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, this.toFloat(), Utils.getApp().resources.displayMetrics).toInt() + +val Int.SP: Int + get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, this.toFloat(), Utils.getApp().resources.displayMetrics).toInt() + + +fun T.watch(@IntRange(from = 1) maxCharCount: Int, onCountChanged:((count: Int) -> Unit)? = null, onTextChanged:((editable: Editable?) -> Unit)? = null, onReachMaxCountAction:((text: T) -> Unit)? = null, onGetFocus:((text: T) -> Unit)? = null) { + doAfterTextChanged { itx -> + onTextChanged?.invoke(itx) + if (itx == null || itx.isEmpty()) { + onCountChanged?.invoke(0) + return@doAfterTextChanged + } + val length = itx.length + if (length > maxCharCount) { + text = itx.delete(maxCharCount, length) + Selection.setSelection(text, maxCharCount) + onCountChanged?.invoke(maxCharCount) + onReachMaxCountAction?.invoke(this) + } else { + onCountChanged?.invoke(length) + } + } + + doBeforeTextChanged { _, _, _, _ -> + onGetFocus?.invoke(this) + } +} + +fun T.spannableText(parts: List, colors: List) { + if (parts.isEmpty() || colors.isEmpty() || parts.size != colors.size) { + return + } + val ssb = SpannableStringBuilder() + parts.forEachIndexed { index, sequence -> + val text = SpannableString(sequence) + text.setSpan(ForegroundColorSpan(colors[index]), 0, sequence.length, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE) + ssb.append(text) + } + text = ssb +} + +fun RecyclerView.fixGestureConflictForViews(ids: List = emptyList()) { + val fixer = GestureConflictFixer(ids) + addOnItemTouchListener(fixer) + addOnScrollListener(fixer) +} + +private class GestureConflictFixer(private val ids: List) : RecyclerView.OnScrollListener(), RecyclerView.OnItemTouchListener { + + private var scrollState = RecyclerView.SCROLL_STATE_IDLE + private var scrollPointerId = -1 + private var initialTouchX = 0 + private var initialTouchY = 0 + private var dx = 0 + private var dy = 0 + + private var intercpted = false + + override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean { + when (e.actionMasked) { + MotionEvent.ACTION_DOWN -> { + scrollPointerId = e.getPointerId(0) + initialTouchX = (e.x + 0.5f).toInt() + initialTouchY = (e.y + 0.5f).toInt() + intercpted = computeIntercepted(initialTouchX, initialTouchY, rv, ids) + } + MotionEvent.ACTION_POINTER_DOWN -> { + val actionIndex = e.actionIndex + scrollPointerId = e.getPointerId(actionIndex) + initialTouchX = (e.getX(actionIndex) + 0.5f).toInt() + initialTouchY = (e.getY(actionIndex) + 0.5f).toInt() + } + MotionEvent.ACTION_MOVE -> { + val index = e.findPointerIndex(scrollPointerId) + if (index >= 0 && scrollState != RecyclerView.SCROLL_STATE_DRAGGING) { + val x = (e.getX(index) + 0.5f).toInt() + val y = (e.getY(index) + 0.5f).toInt() + dx = x - initialTouchX + dy = y - initialTouchY + } + } + MotionEvent.ACTION_UP -> { + intercpted = false + } + } + return false + } + + private fun computeIntercepted(x: Int, y: Int, rv: RecyclerView, ids: List): Boolean { + return ids.takeIf { it.isNotEmpty() }?.find { + val out = Rect() + rv.findViewById(it).getGlobalVisibleRect(out) + out.contains(x, y) + }?.let { it != View.NO_ID } ?: false + } + + override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {} + + override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {} + + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + val oldState = scrollState + scrollState = newState + if (oldState == RecyclerView.SCROLL_STATE_IDLE && newState == RecyclerView.SCROLL_STATE_DRAGGING) { + recyclerView.layoutManager?.let { + if (intercpted) { + recyclerView.stopScroll() + } + } + } + } +} + +fun Context.toast(text: CharSequence, duration: Long = 2, unit: TimeUnit = SECONDS) { + val activity = (this as? FragmentActivity) ?: throw IllegalStateException("please use Activity to trigger toast show.") + activity.lifeCycleScope.launchWhenResumed { + val pop = PopupWindow(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT).also { + it.isOutsideTouchable = false + it.isTouchable = false + it.isFocusable = false + it.setBackgroundDrawable(shape(solid = Color.parseColor("#99000000"), radius = 32.PX)) + } + val tv = TextView(this@toast) + tv.setTextColor(Color.WHITE) + tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, 56.0f) + tv.setPaddingRelative(114.PX, 61.PX, 114.PX, 61.PX) + tv.text = text + pop.contentView = tv + val reminder = object : PopupWindowReminder(pop) { + override fun show() { + pop.showAtLocation(activity.window.decorView, Gravity.CENTER, 0, 0) + lifecycleOwner().lifecycleScope.launch { + delay(unit.toMillis(duration)) + hide() + } + } + override fun isOverride(): Boolean = true + } + Reminder.enqueue(activity.lifeCycleOwner, reminder) + } } diff --git a/libraries/mogo-map/src/main/java/com/mogo/map/AMapMarkerClickHandler.java b/libraries/mogo-map/src/main/java/com/mogo/map/AMapMarkerClickHandler.java index 92ef0d829c..431f29d919 100644 --- a/libraries/mogo-map/src/main/java/com/mogo/map/AMapMarkerClickHandler.java +++ b/libraries/mogo-map/src/main/java/com/mogo/map/AMapMarkerClickHandler.java @@ -2,7 +2,7 @@ package com.mogo.map; import static com.mogo.map.marker.MarkerType.MAP_STATIC; -import com.mogo.eagle.core.utilcode.mogo.logger.Logger; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.mogo.map.marker.AMapMarkerWrapper; import com.mogo.map.marker.IMogoMarker; import com.mogo.map.marker.IMogoMarkerClickListener; @@ -54,7 +54,7 @@ public class AMapMarkerClickHandler { if (MarkerWrapperClickHelper.getInstance().isStaticMarker(marker.getId())){ IMogoMarker iMogoMarker = new AMapMarkerWrapper(marker,new MogoMarkerOptions()); iMogoMarker.setOwner(MAP_STATIC); //TODO 后续可能由于类型比较多,需要owner匹配机制,以及控制owner细粒度 - Logger.d("AMapMarkerWrapper", "traffic marker 点击回调"); + CallerLogger.INSTANCE.d("AMapMarkerWrapper", "traffic marker 点击回调"); return MogoMarkersHandler.getInstance().onStaticMarkerClicked(iMogoMarker); } @@ -62,7 +62,7 @@ public class AMapMarkerClickHandler { if (mogoMarkerMap.containsKey(marker.getId())) { IMogoMarker mogoMarker = mogoMarkerMap.get(marker.getId()); final IMogoMarkerClickListener listener = mogoMarker.getOnMarkerClickListener(); - Logger.d("AMapMarkerWrapper", "marker 点击回调:%s -> %s", mogoMarker, marker); + CallerLogger.INSTANCE.d("AMapMarkerWrapper", "marker 点击回调:%s -> %s", mogoMarker, marker); if (listener != null) { boolean result = listener.onMarkerClicked(mogoMarker); if (result) { diff --git a/libraries/mogo-map/src/main/java/com/mogo/map/AMapWrapper.java b/libraries/mogo-map/src/main/java/com/mogo/map/AMapWrapper.java index c234b670cc..ed51456d90 100644 --- a/libraries/mogo-map/src/main/java/com/mogo/map/AMapWrapper.java +++ b/libraries/mogo-map/src/main/java/com/mogo/map/AMapWrapper.java @@ -3,8 +3,7 @@ package com.mogo.map; import android.content.Context; import android.graphics.Point; -import com.mogo.eagle.core.data.traffic.TrafficData; -import com.mogo.eagle.core.utilcode.mogo.logger.Logger; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.mogo.map.marker.AMapInfoWindowAdapter; import com.mogo.map.marker.AMapMarkerWrapper; import com.mogo.map.marker.IMogoMarker; @@ -53,7 +52,7 @@ public class AMapWrapper implements IMogoMap { private IMogoUiSettings mUiSettings; public AMapWrapper(MapAutoViewHelper map, MapAutoView mapView, IMogoMapUIController controller) { - Logger.i(TAG, "autoop--AMapWrapper: init" + this); + CallerLogger.INSTANCE.i(TAG, "autoop--AMapWrapper: init" + this); this.mAMap = map; sAMap = map; this.mMapView = mapView; @@ -91,7 +90,7 @@ public class AMapWrapper implements IMogoMap { } MarkerOptions markerOptions = ObjectUtils.fromMogo(options); if (markerOptions == null) { - Logger.e(TAG, "marker参数为空"); + CallerLogger.INSTANCE.e(TAG, "marker参数为空"); return null; } final IMogoMarker mogoMarker = new AMapMarkerWrapper(mAMap.addMarker(markerOptions), options); @@ -110,7 +109,7 @@ public class AMapWrapper implements IMogoMap { for (MessagePad.TrackedObject mogoMarkerOptions : optionsArrayList) { MarkerSimpleData markerOptions = ObjectUtils.fromTrafficData(mogoMarkerOptions); if (markerOptions == null) { - Logger.e(TAG, "marker参数为空"); + CallerLogger.INSTANCE.e(TAG, "marker参数为空"); break; } markerOptionsArrayList.add(markerOptions); @@ -259,7 +258,7 @@ public class AMapWrapper implements IMogoMap { @Override public void changeZoom(float zoom) { - Logger.d(TAG, "changeZoom %s", zoom); + CallerLogger.INSTANCE.d(TAG, "changeZoom %s", zoom); if (checkAMap()) { mAMap.setZoom((int) zoom); } @@ -283,7 +282,7 @@ public class AMapWrapper implements IMogoMap { public IMogoPolyline addPolyline(MogoPolylineOptions options) { if (checkAMap()) { PolylineOptions polylineOptions = ObjectUtils.fromMogo(options); - Logger.d(TAG, "addPolyline %s", polylineOptions.toString()); + CallerLogger.INSTANCE.d(TAG, "addPolyline %s", polylineOptions.toString()); if (polylineOptions == null) { return null; } @@ -307,7 +306,7 @@ public class AMapWrapper implements IMogoMap { mAMap = mMapView.getMapAutoViewHelper(); sAMap = mAMap; if (mAMap == null) { - Logger.e(TAG, "自研map实例为空,请检查"); + CallerLogger.INSTANCE.e(TAG, "自研map实例为空,请检查"); return false; } return true; diff --git a/libraries/mogo-map/src/main/java/com/mogo/map/CustomMapApiBuilder.java b/libraries/mogo-map/src/main/java/com/mogo/map/CustomMapApiBuilder.java index f3ade54241..8edf9d30ec 100644 --- a/libraries/mogo-map/src/main/java/com/mogo/map/CustomMapApiBuilder.java +++ b/libraries/mogo-map/src/main/java/com/mogo/map/CustomMapApiBuilder.java @@ -4,7 +4,7 @@ import android.content.Context; import android.util.Log; import com.alibaba.android.arouter.facade.annotation.Route; -import com.mogo.eagle.core.utilcode.mogo.logger.Logger; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.mogo.map.location.ALocationClient; import com.mogo.map.location.IMogoLocationClient; import com.mogo.map.search.GeocodeSearchClient; @@ -85,6 +85,6 @@ public class CustomMapApiBuilder implements IMogoMapApiBuilder { @Override public void init(Context context) { - Logger.d(TAG, "init"); + CallerLogger.INSTANCE.d(TAG, "init"); } } diff --git a/libraries/mogo-map/src/main/java/com/mogo/map/marker/AMapMarkerWrapper.java b/libraries/mogo-map/src/main/java/com/mogo/map/marker/AMapMarkerWrapper.java index 58b3d4783a..cdada69601 100644 --- a/libraries/mogo-map/src/main/java/com/mogo/map/marker/AMapMarkerWrapper.java +++ b/libraries/mogo-map/src/main/java/com/mogo/map/marker/AMapMarkerWrapper.java @@ -7,7 +7,7 @@ import android.view.View; import android.view.animation.Interpolator; import com.mogo.eagle.core.data.map.MogoLatLng; -import com.mogo.eagle.core.utilcode.mogo.logger.Logger; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.mogo.map.marker.anim.OnMarkerAnimationListener; import com.mogo.map.utils.ObjectUtils; import com.zhidaoauto.map.sdk.open.abs.marker.MarkerAnimationListener; @@ -427,7 +427,7 @@ public class AMapMarkerWrapper implements IMogoMarker, Observer { mMarker.setTranslateAnimation( animation ); mMarker.startAnimation(); } catch ( Exception e ) { - Logger.e( TAG, e, "error." ); + CallerLogger.INSTANCE.e( TAG, e, "error." ); } } @@ -495,7 +495,7 @@ public class AMapMarkerWrapper implements IMogoMarker, Observer { mMarker.marker3DIcon( model3D ); return mMarker.getMarkeOptions().getMarkerIconName(); } catch ( Exception e ) { - Logger.e( TAG, e, "use3DResource" ); + CallerLogger.INSTANCE.e( TAG, e, "use3DResource" ); } return null; } @@ -506,7 +506,7 @@ public class AMapMarkerWrapper implements IMogoMarker, Observer { mMarker.getMarkeOptions().setVrIcon( true ); mMarker.setMarkerOptions( mMarker.getMarkeOptions().setMarkerIconName( resName ) ); } catch ( Exception e ) { - Logger.e( TAG, e, "use3DResource" ); + CallerLogger.INSTANCE.e( TAG, e, "use3DResource" ); } } @@ -516,7 +516,7 @@ public class AMapMarkerWrapper implements IMogoMarker, Observer { mMarker.getMarkeOptions().setVrIcon( false ); mMarker.setMarkerOptions( mMarker.getMarkeOptions().setMarkerIconName( resName ) ); } catch ( Exception e ) { - Logger.e( TAG, e, "use3DResource" ); + CallerLogger.INSTANCE.e( TAG, e, "use3DResource" ); } } diff --git a/libraries/mogo-map/src/main/java/com/mogo/map/search/InputtipsSearch.java b/libraries/mogo-map/src/main/java/com/mogo/map/search/InputtipsSearch.java index 07084ebddc..1399d6e2e8 100644 --- a/libraries/mogo-map/src/main/java/com/mogo/map/search/InputtipsSearch.java +++ b/libraries/mogo-map/src/main/java/com/mogo/map/search/InputtipsSearch.java @@ -2,7 +2,7 @@ package com.mogo.map.search; import android.content.Context; -import com.mogo.eagle.core.utilcode.mogo.logger.Logger; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.mogo.map.search.inputtips.IMogoInputtipsListener; import com.mogo.map.search.inputtips.IMogoInputtipsSearch; import com.mogo.map.search.inputtips.MogoTip; @@ -60,7 +60,7 @@ public class InputtipsSearch implements IMogoInputtipsSearch, InputtipsListener mListener.onGetInputtips(getResult(list)); } } else { - Logger.e(TAG, "errorcode = " + i); + CallerLogger.INSTANCE.e(TAG, "errorcode = " + i); } } diff --git a/libraries/mogo-map/src/main/java/com/mogo/map/search/PoiSearchClient.java b/libraries/mogo-map/src/main/java/com/mogo/map/search/PoiSearchClient.java index 8c3971f6ad..1a4d843d8d 100644 --- a/libraries/mogo-map/src/main/java/com/mogo/map/search/PoiSearchClient.java +++ b/libraries/mogo-map/src/main/java/com/mogo/map/search/PoiSearchClient.java @@ -2,7 +2,7 @@ package com.mogo.map.search; import android.content.Context; -import com.mogo.eagle.core.utilcode.mogo.logger.Logger; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.mogo.map.exception.MogoMapException; import com.mogo.map.search.geo.MogoPoiItem; import com.mogo.map.search.poisearch.IMogoPoiSearch; @@ -111,7 +111,7 @@ public class PoiSearchClient implements IMogoPoiSearch, OnPoiSearchListener { @Override public void onPoiSearched( PoiSearchResult poiResult, int errorCode ) { if ( errorCode != 0 ) { - Logger.e( TAG, "errorcode is %d", errorCode ); + CallerLogger.INSTANCE.e( TAG, "errorcode is %d", errorCode ); } if ( mListener != null ) { mListener.onPoiSearched( ObjectUtils.fromAMap( poiResult ), errorCode ); @@ -121,7 +121,7 @@ public class PoiSearchClient implements IMogoPoiSearch, OnPoiSearchListener { @Override public void onPoiItemSearched( PoiItem poiItem, int errorCode ) { if ( errorCode != 0 ) { - Logger.e( TAG, "errorcode is %d", errorCode ); + CallerLogger.INSTANCE.e( TAG, "errorcode is %d", errorCode ); } if ( mListener != null ) { mListener.onPoiItemSearched( ObjectUtils.fromAMap( poiItem ), errorCode ); diff --git a/libraries/mogo-map/src/main/java/com/mogo/map/utils/PointInterpolatorUtil.java b/libraries/mogo-map/src/main/java/com/mogo/map/utils/PointInterpolatorUtil.java index f4013e949e..79aeacc109 100644 --- a/libraries/mogo-map/src/main/java/com/mogo/map/utils/PointInterpolatorUtil.java +++ b/libraries/mogo-map/src/main/java/com/mogo/map/utils/PointInterpolatorUtil.java @@ -2,7 +2,7 @@ package com.mogo.map.utils; import com.mogo.cloud.commons.utils.CoordinateUtils; import com.mogo.eagle.core.data.map.MogoLatLng; -import com.mogo.eagle.core.utilcode.mogo.logger.Logger; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.zhidaoauto.map.sdk.open.query.LonLatPoint; import java.util.List; @@ -38,13 +38,13 @@ public class PointInterpolatorUtil { MogoLatLng current = points.get(i); MogoLatLng next = points.get(i + 1); float distance = CoordinateUtils.calculateLineDistance(current.lon, current.lat, next.lon, next.lat); - Logger.d(TAG, i + ": " + distance); + CallerLogger.INSTANCE.d(TAG, i + ": " + distance); if (distance > DISTANCE_THRESHOLD) { int inter = (int) (distance / DISTANCE_THRESHOLD) + 1; for (int j = 1; j < inter; j++) { double newLat = current.lat + (next.lat - current.lat) * j / inter; double newLon = current.lon + (next.lon - current.lon) * j / inter; - Logger.d(TAG, "distance: " + distance + ", j: " + j + ", nextLat: " + next.lat + ", nextLon: " + next.lon + ", newLat: " + newLat + ", newLon: " + newLon); + CallerLogger.INSTANCE.d(TAG, "distance: " + distance + ", j: " + j + ", nextLat: " + next.lat + ", nextLon: " + next.lon + ", newLat: " + newLat + ", newLon: " + newLon); points.add(i + 1, new MogoLatLng(newLat, newLon)); current = points.get(++i); }