diff --git a/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/constant/BusPassengerConst.kt b/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/constant/BusPassengerConst.kt index 38f614a10b..e2ba5ec9e0 100644 --- a/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/constant/BusPassengerConst.kt +++ b/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/constant/BusPassengerConst.kt @@ -44,5 +44,7 @@ class BusPassengerConst { // 订单总里程 const val BUS_SP_KEY_ORDER_SUM_DIS = "BUS_SP_KEY_ORDER_SUM_DIS" + + const val QUERY_BUS_P_STATION_DELAY = 3 * 1000L } } \ No newline at end of file diff --git a/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java b/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java index 64830672fe..a6f3aa85bf 100644 --- a/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java +++ b/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java @@ -4,6 +4,8 @@ import android.content.Context; import android.content.Intent; import android.location.Location; import android.net.ConnectivityManager; +import android.os.Handler; +import android.os.Message; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -56,6 +58,7 @@ import mogo_msg.MogoReportMsg; import system_master.SystemStatusInfo; import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS_P; +import static com.mogo.och.bus.passenger.constant.BusPassengerConst.QUERY_BUS_P_STATION_DELAY; import static com.mogo.och.bus.passenger.constant.BusPassengerConst.STATION_STATUS_STOPPED; /** @@ -88,6 +91,18 @@ public class BusPassengerModel { private int mNextStationIndex = 0;// 要到达站的index private List mTwoStationsRouts = new ArrayList<>(); + private static final int MSG_QUERY_BUS_P_STATION = 1001; + private final Handler handler = new Handler(new Handler.Callback() { + @Override + public boolean handleMessage(Message msg) { + if ( msg.what == MSG_QUERY_BUS_P_STATION ) { + queryDriverOperationStatus(); + return true; + } + return false; + } + }); + private BusPassengerModel() { } @@ -96,6 +111,7 @@ public class BusPassengerModel { initListeners(); // TODO: 2022/3/31 queryDriverOperationStatus(); + startOrStopOrderLoop(true); } public void setDriverStatusCallback(IBusPassegerDriverStatusCallback callback){ @@ -106,13 +122,16 @@ public class BusPassengerModel { this.mRouteLineInfoCallback = callback; } + private void queryDriverOperationDelay() { + handler.sendEmptyMessageDelayed( MSG_QUERY_BUS_P_STATION, QUERY_BUS_P_STATION_DELAY ); + } + private void queryDriverOperationStatus() { BusPassengerServiceManager.getInstance().queryDriverOperationStatus(mContext , new BusPassengerServiceCallback() { @Override public void onSuccess(BusPassengerOperationStatusResponse data) { if (data == null || data.data == null) return; - startOrStopOrderLoop(data.data.serviceStatus == 1); if(mDriverStatusCallback != null){ mDriverStatusCallback.changeOperationStatus(data.data.serviceStatus == 1); mDriverStatusCallback.updatePlateNumber(data.data.plateNumber); @@ -121,7 +140,8 @@ public class BusPassengerModel { @Override public void onFail(int code, String msg) { - queryDriverOperationStatus(); + //延迟3s再次查询 + queryDriverOperationDelay(); } }); } @@ -141,7 +161,10 @@ public class BusPassengerModel { @Override public void onFail(int code, String msg) { - + //code = 1003; message = bus车辆已收车或未出车; + if (code == 1003){ + queryDriverOperationDelay(); + } } }); } @@ -409,7 +432,9 @@ public class BusPassengerModel { //要前往的站在轨迹中对应的点 int nextRouteIndex = CoordinateCalculateRouteUtil.getArrivedPointIndex(mRoutePoints ,stationNext.getGcjLon(),stationNext.getGcjLat()); - mTwoStationsRouts.addAll(mRoutePoints.subList(currentRouteIndex,nextRouteIndex)); + if (currentRouteIndex < nextRouteIndex){ //如果找到的next在起点的轨迹前面,直接舍弃这个轨迹,不显示 + mTwoStationsRouts.addAll(mRoutePoints.subList(currentRouteIndex,nextRouteIndex)); + } } }else { //只有两个站点的时候整个路线就是两个站点之间的轨迹 mTwoStationsRouts.clear(); diff --git a/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/ui/BusPassengerMapDirectionView.java b/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/ui/BusPassengerMapDirectionView.java index a663e20563..f4ba291f5c 100644 --- a/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/ui/BusPassengerMapDirectionView.java +++ b/OCH/mogo-och-bus-passenger/src/main/java/com/mogo/och/bus/passenger/ui/BusPassengerMapDirectionView.java @@ -57,8 +57,8 @@ public class BusPassengerMapDirectionView private int mCurrentIndex = -1; private int zoomLevel = 13; - private List mCoordinatesLatLng = new ArrayList<>(); - private List mLinePointsLatLng = new ArrayList<>(); + private List mCoordinatesLatLng = new ArrayList<>(); //站点坐标数据 + private List mLinePointsLatLng = new ArrayList<>(); //轨迹坐标数据 private Polyline mPolyline; private CameraUpdate mCameraUpdate; private Context mContext; @@ -197,7 +197,7 @@ public class BusPassengerMapDirectionView mCarMarker.setToTop(); } - if (mLinePointsLatLng.size() > 1){ + if (mLinePointsLatLng.size() > 0){ //圈定地图显示范围 //存放经纬度 LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder(); @@ -208,12 +208,13 @@ public class BusPassengerMapDirectionView //第二个参数为四周留空宽度 mAMap.moveCamera(CameraUpdateFactory.newLatLngBoundsRect(boundsBuilder.build(),100,100,100,100)); - }else { - //设置希望展示的地图缩放级别 - CameraPosition cameraPosition = new CameraPosition.Builder() - .target(mCarMarker.getPosition()).tilt(0).bearing(location.getBearing()).zoom(zoomLevel).build(); - mAMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); } +// else { +// //设置希望展示的地图缩放级别 +// CameraPosition cameraPosition = new CameraPosition.Builder() +// .target(mCarMarker.getPosition()).tilt(0).bearing(location.getBearing()).zoom(zoomLevel).build(); +// mAMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); +// } } @@ -368,7 +369,7 @@ public class BusPassengerMapDirectionView mLinePointsLatLng.clear(); mLinePointsLatLng.addAll(routeLineLatLngs); - if (mCoordinatesLatLng.size() > 0 && mCurrentIndex != currentIndex) { + if (mLinePointsLatLng.size() > 0 && mCurrentIndex != currentIndex) { if (mAMap != null && mLineMarkers.size() > 0) { mCurrentIndex = currentIndex; for (int i = 0; i < mLineMarkers.size(); i++) { diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/bean/BusResetLineStatusRequest.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/bean/BusResetLineStatusRequest.java new file mode 100644 index 0000000000..595ceafce3 --- /dev/null +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/bean/BusResetLineStatusRequest.java @@ -0,0 +1,24 @@ +package com.mogo.och.bus.bean; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; + +public +/** + * @author congtaowang + * @since 2021/3/22 + * + * 小巴车重置路线状态请求参数 + */ +class BusResetLineStatusRequest { + + private String sn; + public BusResetLineStatusRequest() { + this.sn = MoGoAiCloudClientConfig.getInstance().getSn(); + } + + public String getSn() { + return sn; + } + + +} diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/callback/IRefreshBusStationsCallback.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/callback/IRefreshBusStationsCallback.java index ae4a8b9713..40ea27c44a 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/callback/IRefreshBusStationsCallback.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/callback/IRefreshBusStationsCallback.java @@ -10,4 +10,5 @@ import java.util.List; */ public interface IRefreshBusStationsCallback { void refreshBusStations(String lineName,List stationList, int currentStation, int nextStation, boolean isArrived); + void clearBusStationsMarkers(); } diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java index c83715f9f1..adbbf2c0eb 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java @@ -5,8 +5,10 @@ import static com.mogo.och.bus.constant.BusConst.TIMER_START_AUTOPILOT_INTERVAL; import android.animation.ObjectAnimator; import android.content.Intent; +import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.view.animation.LinearInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; @@ -49,6 +51,9 @@ import com.mogo.och.bus.model.BusOrderModel; import com.mogo.och.bus.util.BDRouteDataTestUtils; import com.mogo.och.bus.view.SlidePanelView; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.ThreadMode; + import mogo.telematics.pad.MessagePad; import record_cache.RecordPanelOuterClass; @@ -67,7 +72,8 @@ public abstract class BaseBusTabFragment private RelativeLayout ctvAutopilotStatus; private ImageView ctvAutopilotStatusIv; private TextView ctvAutopilotStatusTv; - protected TextView tvOperationStatus; + protected TextView tvArrived; +// protected TextView tvOperationStatus; protected RelativeLayout mSettingBtn; protected RelativeLayout mBadcaseBtn; protected RelativeLayout mAICollectBtn; @@ -119,7 +125,8 @@ public abstract class BaseBusTabFragment // mTrafficLightView = findViewById(R.id.bus_traffic_light_view); // CallerHmiManager.INSTANCE.setProxyTrafficLightView(mTrafficLightView); - tvOperationStatus = findViewById(R.id.module_mogo_och_operation_status); +// tvOperationStatus = findViewById(R.id.module_mogo_och_operation_status); + tvArrived = findViewById(R.id.module_mogo_och_arrived_tv); flSpeed = (FrameLayout) findViewById(R.id.fl_speed); mTrafficDataView = (TrafficDataView) findViewById(R.id.bus_arc); @@ -145,6 +152,10 @@ public abstract class BaseBusTabFragment .inVisibleWithoutMarkers(DataTypes.TYPE_MARKER_ADAS, BusConst.TYPE_MARKER_BUS_ORDER); MogoMapUIController.getInstance().changeMapVisualAngle(VisualAngleMode.MODE_LONG_SIGHT, null); mSwitchMapModeImage.setImageResource(R.drawable.bus_switch_map_long); + } else { + MogoMarkerManager.getInstance(AbsMogoApplication.getApp()).visibleAllMarkers(); + MogoMapUIController.getInstance().changeMapVisualAngle(VisualAngleMode.MODE_MEDIUM_SIGHT, null); + mSwitchMapModeImage.setImageResource(R.drawable.bus_switch_map_medium); } } }); @@ -160,19 +171,15 @@ public abstract class BaseBusTabFragment }); } initListener(); + setAutopilotBtnStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); ctvAutopilotStatus.setOnClickListener(new OnPreventFastClickListener(){ @Override public void onClickImpl(View v) { - if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE){ - restartAutopilot(); - }else { - ToastUtils.showShort(getResources().getString(R.string.bus_auto_disable_tip)); - } + restartAutopilot(); } }); - setAutopilotBtnStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); // 模拟 不可自动驾驶,目前场景是刚开机,adas还未和工控机连接 findViewById(R.id.btnAutopilotDisable).setOnClickListener(view -> debugAutoPilotStatus(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) @@ -195,8 +202,12 @@ public abstract class BaseBusTabFragment findViewById(R.id.btnAutopilotRoute).setOnClickListener(view -> debugArrivedRoute()); - tvOperationStatus.setOnClickListener(view -> { - onChangeOperationStatus(); +// tvOperationStatus.setOnClickListener(view -> { +// onChangeOperationStatus(); +// }); + + tvArrived.setOnClickListener(view -> { + onArriveStation(); }); mSettingBtn = findViewById(R.id.module_mogo_och_setting_layout); @@ -207,11 +218,6 @@ public abstract class BaseBusTabFragment // mBadcaseBtn的visible显示逻辑在showBadcaseEntrance内处理 mBadcaseBtn = findViewById(R.id.module_mogo_och_badcase_rl); -// CallerHmiManager.INSTANCE.registerBadCaseCallback( -// () -> { // onShow() -// return mBadcaseBtn; }, -// () -> { // onHide() -// return null; }); if (mBadcaseBtn != null) { CallerDevaToolsManager.INSTANCE.initBadCase(mBadcaseBtn); @@ -226,6 +232,16 @@ public abstract class BaseBusTabFragment } } + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container + , @Nullable Bundle savedInstanceState) { + EventBus.getDefault().register(this); + return super.onCreateView(inflater, container, savedInstanceState); + } + + protected abstract void onArriveStation(); + private void updateSwitchMapIcon(){ if (MogoMapUIController.getInstance().getCurrentMapVisualAngle().isLongSight()) { mSwitchMapModeImage.setImageResource(R.drawable.bus_switch_map_long); @@ -246,6 +262,7 @@ public abstract class BaseBusTabFragment if (!HmiBuildConfig.isShowBadCaseView) { CallerAutopilotRecordListenerManager.INSTANCE.removeListener(TAG); } + EventBus.getDefault().unregister(this); } @@ -285,9 +302,25 @@ public abstract class BaseBusTabFragment slidePanelView.setText(text); slidePanelView.setVisibility(View.VISIBLE); }); + setArrivedClikable(false); } } + /** + * 设置进站按钮状态 + * @param isClickable + */ + public void setArrivedClikable(boolean isClickable){ + getActivity().runOnUiThread(() -> { + tvArrived.setEnabled(isClickable); + if (isClickable){ + tvArrived.setTextColor(getResources().getColor(R.color.bus_white)); + }else { + tvArrived.setTextColor(getResources().getColor(R.color.bus_arrived_btn_un_clickable_color)); + } + }); + } + /** * 隐藏滑动按钮 */ @@ -321,13 +354,13 @@ public abstract class BaseBusTabFragment ctvAutopilotStatusTv.setText(getResources().getString(R.string.bus_loading_autopilot_runnig_tv)); ctvAutopilotStatusIv.setImageResource(R.drawable.bus_disable_autopilot_icon); ctvAutopilotStatus.setSelected(false); - ctvAutopilotStatus.setFocusableInTouchMode(true); + ctvAutopilotStatus.setClickable(true); } else { ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.bus_autopilot_text_color_normal)); ctvAutopilotStatusTv.setText(getResources().getString(R.string.bus_loading_autopilot_runnig_tv)); ctvAutopilotStatusIv.setImageResource(R.drawable.bus_ic_autopilot); - ctvAutopilotStatus.setFocusableInTouchMode(true); + ctvAutopilotStatus.setClickable(true); if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE == autopilotStatus) {//1可用 ctvAutopilotStatus.setSelected(false); }else if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING == autopilotStatus){ @@ -343,12 +376,12 @@ public abstract class BaseBusTabFragment ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.bus_autopilot_text_color_normal)); ctvAutopilotStatusTv.setText(getResources().getString(R.string.bus_loading_autopilot_success_tv)); ctvAutopilotStatus.setSelected(false); - ctvAutopilotStatus.setFocusableInTouchMode(false); + ctvAutopilotStatus.setClickable(false); }else { ctvAutopilotStatusIv.setImageResource(R.drawable.bus_wrong_autopilot_icon); ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.bus_autopilot_text_color_normal)); ctvAutopilotStatusTv.setText(getResources().getString(R.string.bus_loading_autopilot_failure_tv)); - ctvAutopilotStatus.setFocusableInTouchMode(false); + ctvAutopilotStatus.setClickable(false); ctvAutopilotStatus.setSelected(false); } UiThreadHandler.postDelayed(new Runnable() { @@ -442,7 +475,7 @@ public abstract class BaseBusTabFragment ctvAutopilotStatusTv.setText(getResources().getString(R.string.bus_loading_autopilot_tv)); ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.bus_autopilot_text_color_normal)); ctvAutopilotStatus.setSelected(false); - ctvAutopilotStatus.setFocusableInTouchMode(true); + ctvAutopilotStatus.setClickable(true); ctvAutopilotStatusIv.setImageResource(R.drawable.bus_loading_autopilot_icon); if (autopilotLoadingAnimator == null) { autopilotLoadingAnimator = ObjectAnimator.ofFloat(ctvAutopilotStatusIv, "rotation", 0f, 360f); diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BusFragment.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BusFragment.java index ff6d6b5d2c..7278755f1a 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BusFragment.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/fragment/BusFragment.java @@ -9,11 +9,12 @@ import android.widget.TextView; import androidx.annotation.NonNull; import com.mogo.commons.AbsMogoApplication; -import com.mogo.commons.debug.DebugConfig; import com.mogo.commons.voice.AIAssist; import com.mogo.eagle.core.data.map.CenterLine; +import com.mogo.eagle.core.data.temp.EventBusOperation; import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager; +import com.mogo.eagle.core.function.call.hmi.CallerHmiManager; import com.mogo.eagle.core.function.call.map.CallerHDMapManager; import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.mogo.eagle.core.utilcode.util.ToastUtils; @@ -28,6 +29,9 @@ import com.mogo.och.bus.ui.BusSwitchLineActivity; import com.mogo.och.bus.view.SlidePanelView; import com.mogo.och.common.module.utils.OCHThreadPoolManager; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + import java.util.List; import mogo.telematics.pad.MessagePad; @@ -50,7 +54,7 @@ public class BusFragment extends BaseBusTabFragment private TextView mLineName; private int mCurrentStation = 0; - private View mBus; +// private View mBus; private BusStationBean startStation = null; private BusStationBean endStation = null; @@ -63,48 +67,45 @@ public class BusFragment extends BaseBusTabFragment @Override protected void initViews() { super.initViews(); - mBus = findViewById(R.id.module_och_bus_tag); +// mBus = findViewById(R.id.module_och_bus_tag); mCurrentStationName = findViewById(R.id.module_och_bus_current_station); mCurrentTag = findViewById(R.id.module_och_bus_current_station_anchor); mNextStationName = findViewById(R.id.module_och_bus_order_end_station); mNextTag = findViewById(R.id.module_och_bus_next_station_anchor); mSwitchLine = findViewById(R.id.switch_line_btn); + mSwitchLine.setTag(0); mLineName = findViewById(R.id.module_och_bus_line_name); - if (DebugConfig.isDebug()) { - mBus.setOnClickListener(view -> { - ToastUtils.showShort("重置了车站状态"); - mPresenter.queryBusRoutes(); - }); - - //debug下调用测试面板 - mCurrentStationName.setOnLongClickListener(v -> { + //调用测试面板 + mCurrentStationName.setOnLongClickListener(v -> { debugTestBar(); showHideTestBar(); return true; }); - } +// } CallerLogger.INSTANCE.d(M_BUS + TAG, "initView: " + CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); // 初始化的时候设置 UI 按钮状态 - switch (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()) { - case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE: - hideAutopilotBiz(); - break; - case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE: - showAutopilotBiz(); - onAutopilotStatusChanged(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE); - break; - case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING: - showAutopilotBiz(); - onAutopilotStatusChanged(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING); - break; - default: - break; - } + showAutopilotBiz(); + mSwitchLine.setOnClickListener(this); } + @Subscribe(threadMode = ThreadMode.MAIN) + public void onClickChangeOperationStatus(EventBusOperation eventBusOperation){ + if (eventBusOperation.getId() == 0){ // 查询 + mPresenter.queryOperationStatus(); + }else if (eventBusOperation.getId() == 1){ // 出车/收车切换 + CallerLogger.INSTANCE.d(M_BUS + TAG,"bus出车/收车"); + onChangeOperationStatus(); + } + } + + @Override + protected void onArriveStation() { + mPresenter.onAutopilotArriveAtStation(null); + } + @Override protected void debugArrivedStation() { mPresenter.onAutopilotArriveAtStation(null); @@ -235,10 +236,14 @@ public class BusFragment extends BaseBusTabFragment } private void showOrHideSwitchLineBtn(boolean isShow) { - if (isShow){ - mSwitchLine.setVisibility(View.VISIBLE); - }else { - mSwitchLine.setVisibility(View.GONE); + if (isShow){//显示切换路线 +// mSwitchLine.setVisibility(View.VISIBLE); + mSwitchLine.setTag(0); + mSwitchLine.setText(getResources().getString(R.string.bus_switch_line_btn)); + }else {//显示结束路线 +// mSwitchLine.setVisibility(View.GONE); + mSwitchLine.setTag(1); + mSwitchLine.setText(getResources().getString(R.string.bus_close_line_btn)); } } @@ -296,26 +301,35 @@ public class BusFragment extends BaseBusTabFragment */ public void changeOperationStatus(boolean launch) { isOperationStatus = launch; + + CallerHmiManager.INSTANCE.changeBusOperationStatus(launch); + if (launch) { // 出车的时候重制站点状态 mPresenter.queryBusRoutes(); - tvOperationStatus.setText("收车"); +// tvOperationStatus.setText("收车"); + tvArrived.setVisibility(View.VISIBLE); showPanel(); } else { AIAssist.getInstance(getContext()).speakTTSVoice("已收车"); - tvOperationStatus.setText("出车"); +// tvOperationStatus.setText("出车"); + tvArrived.setVisibility(View.GONE); hideSlidePanel(); hidPanel(); - //移除起点终点 - if (null != startStation) { - setOrRemoveMapMaker(false, BusConst.BUS_START_MAP_MAKER, startStation.getLat() - , startStation.getLon(),R.raw.star_marker); - } - if (null != endStation) { - setOrRemoveMapMaker(false, BusConst.BUS_END_MAP_MAKER, endStation.getLat() - , endStation.getLon(),R.raw.end_marker); - } + clearBusStationsMarkers(); + } + } + + public void clearBusStationsMarkers(){ + CallerLogger.INSTANCE.d(M_BUS + TAG,"clearBusStationsMarkers()"); + if (null != startStation) { + setOrRemoveMapMaker(false, BusConst.BUS_START_MAP_MAKER, startStation.getLat() + , startStation.getLon(),R.raw.star_marker); + } + if (null != endStation) { + setOrRemoveMapMaker(false, BusConst.BUS_END_MAP_MAKER, endStation.getLat() + , endStation.getLon(),R.raw.end_marker); } } @@ -392,12 +406,12 @@ public class BusFragment extends BaseBusTabFragment ToastUtils.showLong(getResources().getString(R.string.bus_switch_line_btn_warning1)); return; } - if (mCurrentStation > 0) { - ToastUtils.showLong(getResources().getString(R.string.bus_switch_line_btn_warning2)); - return; + if ((int)mSwitchLine.getTag() == 0){//切换路线 + Intent intent = new Intent(getContext(), BusSwitchLineActivity.class); + startActivity(intent); + }else {//结束路线 + mPresenter.resetCurrentLineStatus(); } - Intent intent = new Intent(getContext(), BusSwitchLineActivity.class); - startActivity(intent); } } } diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusLineModel.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusLineModel.java index 3fca5e55d8..0d79156db8 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusLineModel.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusLineModel.java @@ -64,7 +64,7 @@ public class BusLineModel { } public void commitSwitchLineId(int lineId){ - BusServiceManager.getInstance().resetStationStatus(mContext,lineId, new IBusServiceCallback() { + BusServiceManager.getInstance().switchLine(mContext,lineId, new IBusServiceCallback() { @Override public void onSuccess(BusRoutesResponse o) { if (mBusLinesCallback != null){ diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusOrderModel.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusOrderModel.java index d875ea8929..f8e5b3bd17 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusOrderModel.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusOrderModel.java @@ -11,7 +11,6 @@ import android.location.Location; import android.os.Handler; import android.os.Message; import android.text.TextUtils; -import android.util.Log; import androidx.annotation.NonNull; @@ -25,6 +24,7 @@ import com.mogo.eagle.core.data.BaseData; import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters; import com.mogo.eagle.core.data.config.FunctionBuildConfig; import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotPlanningListener; +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager; import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager; import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotPlanningListenerManager; @@ -444,26 +444,24 @@ public class BusOrderModel { } /** - * 测试、重置站点状态 + * 重置路线站点状态--结束路线,当前路线恢复到始发站 */ - public void debugResetStationStatus() { - CallerLogger.INSTANCE.d( M_BUS + TAG, "测试、重置站点状态"); - BusServiceManager.getInstance().resetStationStatus(mContext, currentLineId + public void resetCurrentLineStatus() { + CallerLogger.INSTANCE.d( M_BUS + TAG, "结束当前路线"); + BusServiceManager.getInstance().resetCurrentLineStatus(mContext, currentLineId , new IBusServiceCallback() { @Override public void onSuccess(BusRoutesResponse o) { - CallerLogger.INSTANCE.d(M_BUS + TAG, "获取到小巴路线数据: " + o); + CallerLogger.INSTANCE.d(M_BUS + TAG, "结束当前路线成功: " + o); isGoingToNextStation = false; - if (o.getResult() == null || o.getResult().getSites() == null || o.getResult().getSites().isEmpty()) { - return; + if (o.code == 0){ // 重置成功 + queryBusRoutes(); } - renderBusStationsStatus(o.getResult()); } @Override public void onFail(String failMsg) { - // 重复请求小巴路线,直至成功 - queryBusStationDelay(); + ToastUtils.showShort(failMsg); } }); @@ -520,11 +518,14 @@ public class BusOrderModel { ) private void leaveStationSuccess(BusRoutesResult result, boolean isRestart) { renderBusStationsStatus(result); - if (slidePannelHideCallback != null) { - slidePannelHideCallback.hideSlidePanel(); +// if (slidePannelHideCallback != null) { +// slidePannelHideCallback.hideSlidePanel(); +// } + //开启自动驾驶 2.10.0: 如果自动驾驶状态下开启, 非自动驾驶状态下不开启,需手动点击自动驾驶按钮开启 + if (isRestart || CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() + == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING){ + startAutopilot(isRestart); } - //开启自动驾驶 - startAutopilot(isRestart); if (isGoingToNextStation) { // 为了避免恢复自动驾驶时重复的接口请求 return; @@ -682,6 +683,7 @@ public class BusOrderModel { private void closeBeautificationMode() { if (FunctionBuildConfig.isDemoMode) {//收车结束美化 FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = false; + CallerAutoPilotManager.INSTANCE.setIgnoreConditionDraw(false); CallerAutoPilotManager.INSTANCE.setIPCDemoMode(false); CallerLogger.INSTANCE.d(M_BUS + TAG, "美化模式-ignore:置为false(收车)"); } @@ -801,6 +803,7 @@ public class BusOrderModel { && backgroundCurrentStationIndex <= stationList.size()-1) && stationList.get(backgroundCurrentStationIndex).isLeaving()){//行驶过程中设置美化 FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = true; + CallerAutoPilotManager.INSTANCE.setIgnoreConditionDraw(true); CallerAutoPilotManager.INSTANCE.setIPCDemoMode(true); CallerLogger.INSTANCE.d(M_BUS + TAG, "美化模式-ignore:置为true(每次滑动出发)"); } @@ -818,6 +821,12 @@ public class BusOrderModel { BusTrajectoryManager.getInstance().syncTrajectoryInfo(); } + public void clearBusStationDatas(){ + if (refreshBusStationsCallback != null){ + refreshBusStationsCallback.clearBusStationsMarkers(); + } + } + /** * 根据订单状态、获取下一站靠站的的站点 * @@ -941,6 +950,7 @@ public class BusOrderModel { if (FunctionBuildConfig.isDemoMode && backgroundCurrentStationIndex <= stationList.size() - 1) {//到达一站结束美化 FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = false; + CallerAutoPilotManager.INSTANCE.setIgnoreConditionDraw(false); CallerAutoPilotManager.INSTANCE.setIPCDemoMode(false); CallerLogger.INSTANCE.d(M_BUS + TAG, "美化模式-ignore:置为false(到最后一站)"); } diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/net/BusServiceManager.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/net/BusServiceManager.java index 5ce01cf7c4..44284cb122 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/net/BusServiceManager.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/net/BusServiceManager.java @@ -11,6 +11,7 @@ import com.mogo.eagle.core.network.RequestOptions; import com.mogo.eagle.core.network.SubscribeImpl; import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; import com.mogo.och.bus.bean.BusQueryLinesResponse; +import com.mogo.och.bus.bean.BusResetLineStatusRequest; import com.mogo.och.bus.bean.BusRoutePlanningUpdateReqBean; import com.mogo.och.bus.bean.BusRoutesResponse; import com.mogo.och.bus.bean.CarHeartbeatReqBean; @@ -74,13 +75,27 @@ public class BusServiceManager { * @param lineId * @param callback */ - public void resetStationStatus(Context context, int lineId, IBusServiceCallback callback){ - mService.resetStationStatus(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + public void switchLine(Context context, int lineId, IBusServiceCallback callback){ + mService.switchLine(MoGoAiCloudClientConfig.getInstance().getServiceAppId() ,MoGoAiCloudClientConfig.getInstance().getToken(),new BusResetDrivingLineRequest(lineId)) .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) .subscribe(getSubscribeImpl(context,callback,"debugResetStationStatus")); } + /** + * 结束当前路线,当前路线状态重置到始发站 + * @param context + * @param lineId + * @param callback + */ + public void resetCurrentLineStatus(Context context, int lineId, IBusServiceCallback callback){ + mService.resetCurrentLineStatus(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + ,MoGoAiCloudClientConfig.getInstance().getToken() + ,new BusResetLineStatusRequest()) + .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) + .subscribe(getSubscribeImpl(context,callback,"resetCurrentLineStatus")); + } + /** * 离站上报 * @param context @@ -189,7 +204,8 @@ public class BusServiceManager { public void queryBusLines(Context context, IBusServiceCallback callback){ mService.queryBusLines(MoGoAiCloudClientConfig.getInstance().getServiceAppId() - ,MoGoAiCloudClientConfig.getInstance().getToken(),MoGoAiCloudClientConfig.getInstance().getSn()) + ,MoGoAiCloudClientConfig.getInstance().getToken() + ,MoGoAiCloudClientConfig.getInstance().getSn()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(getSubscribeImpl(context,callback,"queryBusLines")); diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/net/IBusApiService.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/net/IBusApiService.java index f4c50754fb..291fb9f67f 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/net/IBusApiService.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/net/IBusApiService.java @@ -3,6 +3,7 @@ import com.mogo.eagle.core.data.BaseData; import com.mogo.och.bus.bean.BusOperationStatusRequest; import com.mogo.och.bus.bean.BusOrdersResponse; import com.mogo.och.bus.bean.BusQueryLinesResponse; +import com.mogo.och.bus.bean.BusResetLineStatusRequest; import com.mogo.och.bus.bean.BusRoutePlanningUpdateReqBean; import com.mogo.och.bus.bean.BusRoutesResponse; import com.mogo.och.bus.bean.CarHeartbeatReqBean; @@ -42,8 +43,6 @@ public interface IBusApiService { Observable querySiteByCoordinate(@Header ("appId") String appId, @Header("ticket") String ticket, @Body BusQueryLineStationsRequest request); /** - * 重置巴士路线: 点击小巴车tab 或者出车后会使用 - * * @param request 请求参数{"destLine":1,"sn":"F803EB2046PZD00229"} 这个接口是重置bus线路的, 不是重置线路中站点的 * @return 返回值是重置后的车站列表 */ @@ -51,7 +50,7 @@ public interface IBusApiService { // @POST( "/autopilot-car-hailing/car/v2/bus/drivingLine/reset" ) @POST( "/autopilot-car-hailing/car/v2/driver/bus/drivingLine/reset" ) // @POST( "/mock/268/autopilot-car-hailing/bus/api/drivingLine/reset" ) - Observable resetStationStatus(@Header ("appId") String appId, @Header("ticket") String ticket, @Body BusResetDrivingLineRequest request); + Observable switchLine(@Header ("appId") String appId, @Header("ticket") String ticket, @Body BusResetDrivingLineRequest request); /** * 离站,通知服务器 @@ -150,5 +149,9 @@ public interface IBusApiService { @Headers( {"Content-type:application/json;charset=UTF-8"} ) @POST( "/autopilot-car-hailing/location/v2/driver/bus/saveLineCoordinate" ) Observable updateOrderRoute(@Header ("appId") String appId, @Header("ticket") String ticket, @Body BusRoutePlanningUpdateReqBean data); + + @Headers( {"Content-type:application/json;charset=UTF-8"} ) + @POST("/autopilot-car-hailing/operation/v1/driver/bus/line/resetStart") + Observable resetCurrentLineStatus(@Header ("appId") String appId, @Header("ticket") String ticket, @Body BusResetLineStatusRequest data); } diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusLinePresenter.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusLinePresenter.java index c2f6fb57da..bafd9f298b 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusLinePresenter.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusLinePresenter.java @@ -53,6 +53,7 @@ public class BusLinePresenter extends Presenter implements IB @Override public void onChangeLineIdSuccess() { + BusOrderModel.getInstance().clearBusStationDatas(); runOnUIThread(() -> mView.onChangeLineIdSuccess()); } diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java index fadc4ad8d1..15b161f032 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java @@ -60,7 +60,7 @@ public class BusPresenter extends Presenter @Override public void onCreate(@NonNull LifecycleOwner owner) { super.onCreate(owner); - BusOrderModel.getInstance().queryOperationStatus(); + queryOperationStatus(); BusOrderModel.getInstance().queryBusRoutes(); initModelListener(); } @@ -90,8 +90,12 @@ public class BusPresenter extends Presenter BusOrderModel.getInstance().queryBusRoutes(); } - public void debugResetStationStatus() { - BusOrderModel.getInstance().debugResetStationStatus(); + public void queryOperationStatus(){ + BusOrderModel.getInstance().queryOperationStatus(); + } + + public void resetCurrentLineStatus() { + BusOrderModel.getInstance().resetCurrentLineStatus(); } public void autoDriveToNextStation(boolean isRestart) { @@ -133,6 +137,11 @@ public class BusPresenter extends Presenter } } + @Override + public void clearBusStationsMarkers() { + runOnUIThread(() -> mView.clearBusStationsMarkers()); + } + private void functionDemoModeChange() { // CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel ="," functionDemoModeChange ="+mCurrentStation); if (FunctionBuildConfig.isDemoMode @@ -148,6 +157,7 @@ public class BusPresenter extends Presenter public void hideSlidePanel() { if (mView != null) { runOnUIThread(() -> mView.hideSlidePanel()); + runOnUIThread(()-> mView.setArrivedClikable(true)); } } @@ -175,9 +185,9 @@ public class BusPresenter extends Presenter currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE; // 设置UI【自动驾驶】按钮是否展示 runOnUIThread(() -> mView.onAutopilotEnableChange(true)); - if (BusOrderModel.getInstance().isGoingToNextStation()) { - runOnUIThread(() -> mView.hideSlidePanel()); - } +// if (BusOrderModel.getInstance().isGoingToNextStation()) { +// runOnUIThread(() -> mView.hideSlidePanel()); +// } if (FunctionBuildConfig.isDemoMode && ( (mCurrentStation > 0 && mCurrentStation < mStationList.size() - 1) diff --git a/OCH/mogo-och-bus/src/main/res/layout/bus_base_fragment.xml b/OCH/mogo-och-bus/src/main/res/layout/bus_base_fragment.xml index 4bd073fff0..3cd819092e 100644 --- a/OCH/mogo-och-bus/src/main/res/layout/bus_base_fragment.xml +++ b/OCH/mogo-och-bus/src/main/res/layout/bus_base_fragment.xml @@ -61,7 +61,7 @@ android:layout_marginLeft="@dimen/dp_13" app:layout_constraintTop_toBottomOf="@id/module_mogo_och_autopilot_status" app:layout_goneMarginTop="@dimen/module_mogo_och_station_panel_container_margin_top_no_call" - tools:visibility="visible" /> + android:visibility="gone"/> @@ -92,17 +94,33 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" /> - + + + + + + + + + + + + + + + + + + + android:src="@drawable/bad_case_selector" /> - + + + + + + + + + + + + + + + + + app:layout_constraintTop_toBottomOf="@+id/module_och_bus_line_name" /> 40px + 32px 13px 12px 350px diff --git a/OCH/mogo-och-bus/src/main/res/values-xhdpi-2560x1600/dimens.xml b/OCH/mogo-och-bus/src/main/res/values-xhdpi-2560x1600/dimens.xml index db56121992..dee684f3e6 100644 --- a/OCH/mogo-och-bus/src/main/res/values-xhdpi-2560x1600/dimens.xml +++ b/OCH/mogo-och-bus/src/main/res/values-xhdpi-2560x1600/dimens.xml @@ -91,6 +91,7 @@ 40px + 32px 13px 12px 350px diff --git a/OCH/mogo-och-bus/src/main/res/values/colors.xml b/OCH/mogo-och-bus/src/main/res/values/colors.xml index 600e6c2c33..96338fac55 100644 --- a/OCH/mogo-och-bus/src/main/res/values/colors.xml +++ b/OCH/mogo-och-bus/src/main/res/values/colors.xml @@ -44,4 +44,5 @@ #FF006D43 #FFFFE198 #FFFF9B00 + #59FFFFFF \ No newline at end of file diff --git a/OCH/mogo-och-bus/src/main/res/values/dimens.xml b/OCH/mogo-och-bus/src/main/res/values/dimens.xml index 85e4768fcc..ce34734e02 100644 --- a/OCH/mogo-och-bus/src/main/res/values/dimens.xml +++ b/OCH/mogo-och-bus/src/main/res/values/dimens.xml @@ -89,6 +89,7 @@ 270px 30px + 30px 13px 12px 288px diff --git a/OCH/mogo-och-bus/src/main/res/values/strings.xml b/OCH/mogo-och-bus/src/main/res/values/strings.xml index fdbca6ea6b..992ab6c19c 100644 --- a/OCH/mogo-och-bus/src/main/res/values/strings.xml +++ b/OCH/mogo-och-bus/src/main/res/values/strings.xml @@ -11,7 +11,8 @@ 终点: 确认 切换路线 - 自动驾驶中,不可切换路线 + 结束路线 + 自动驾驶状态中,不可切换或结束路线 当前行程未完成,不可切换路线 当前车辆无路线\n请联系运营人员绑定 起点: @@ -24,4 +25,5 @@ 当前站点: 下一站: 自动驾驶状态为0不可用 + 进站 diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/AnimatorDrawableUtil.java b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/AnimatorDrawableUtil.java index bbf9d779eb..513bfa6c34 100644 --- a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/AnimatorDrawableUtil.java +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/AnimatorDrawableUtil.java @@ -35,7 +35,7 @@ public class AnimatorDrawableUtil { //图片资源的ID列表 private List mResourceIdList = null; //定时任务器 - private Timer mTimer = null; + private final Timer mTimer = new Timer(); //定时任务 private AnimTimerTask mTimeTask = null; //记录播放位置 @@ -44,7 +44,7 @@ public class AnimatorDrawableUtil { private boolean isLooping = false; public AnimatorDrawableUtil() { - mTimer = new Timer(); +// mTimer = new Timer(); } /** @@ -139,18 +139,25 @@ public class AnimatorDrawableUtil { */ public void start(boolean loop, int duration, AnimationLisenter lisenter) { this.lisenter = lisenter; - stop(); +// stop(); if (mResourceIdList == null || mResourceIdList.size() == 0) { return; } - if (mTimer == null) { - mTimer = new Timer(); +// if (mTimer == null) { +// mTimer = new Timer(); +// } + try { + isLooping = loop; + mFrameIndex = 0; + mState = STATE_RUNNING; + if (mTimeTask != null){ + return; + } + mTimeTask = new AnimTimerTask(); + mTimer.schedule(mTimeTask, 0, duration); + }catch (Exception e){ + e.printStackTrace(); } - isLooping = loop; - mFrameIndex = 0; - mState = STATE_RUNNING; - mTimeTask = new AnimTimerTask(); - mTimer.schedule(mTimeTask, 0, duration); if (lisenter != null){ lisenter.startAnimation(); } @@ -163,7 +170,7 @@ public class AnimatorDrawableUtil { if (mTimer != null) { mTimer.purge(); mTimer.cancel(); - mTimer = null; +// mTimer = null; } if (mTimeTask != null) { mFrameIndex = 0; diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/ToastUtilsOch.java b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/ToastUtilsOch.java new file mode 100644 index 0000000000..829093f3a7 --- /dev/null +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/utils/ToastUtilsOch.java @@ -0,0 +1,17 @@ +package com.mogo.och.common.module.utils; + +import com.mogo.commons.debug.DebugConfig; +import com.mogo.eagle.core.utilcode.util.ToastUtils; + +public class ToastUtilsOch { + public static void showWithCodeMessage(int code,String message){ + if(message==null){ + return; + } + if (DebugConfig.isDebug()) { + ToastUtils.showShort(code+","+message); + }else { + ToastUtils.showShort(message); + } + } +} 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 06ce8ec0f4..c3070eb0ba 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 @@ -67,7 +67,10 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import io.reactivex.Observable; +import io.reactivex.disposables.Disposable; import io.reactivex.exceptions.UndeliverableException; import io.reactivex.functions.Consumer; import io.reactivex.plugins.RxJavaPlugins; @@ -108,6 +111,9 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback private ITaxiPassengerVeloctityCallback mVeloctityCallback;//道路限速返回 + private Disposable subscribe; + private int delayTime = 2; + private double mLongitude, mLatitude; private List mLocationsModels = new ArrayList<>(); @@ -209,6 +215,9 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback startOrStopOrderLoop(false); startOrStopQueryOrderRemaining(false); releaseListeners(); + if(subscribe!=null&&!subscribe.isDisposed()){ + subscribe.dispose(); + } } private void initListeners() { @@ -720,13 +729,17 @@ public class TaxiPassengerModel implements IOCHTaxiPassengerNaviChangedCallback startOrStopRouteAndWipe(true); } }else { - queryOrderRouteList(); + subscribe = Observable.timer(delayTime, TimeUnit.SECONDS).subscribe(aLong -> { + queryOrderRouteList(); + }); } } @Override public void onFail(int code, String msg) { - queryOrderRouteList(); + subscribe = Observable.timer(delayTime, TimeUnit.SECONDS).subscribe(aLong -> { + queryOrderRouteList(); + }); } }); } diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/presenter/TaxiPassengerServingOrderPresenter.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/presenter/TaxiPassengerServingOrderPresenter.java index 48cb45f36e..089dee2fc9 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/presenter/TaxiPassengerServingOrderPresenter.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/presenter/TaxiPassengerServingOrderPresenter.java @@ -24,11 +24,8 @@ import com.mogo.och.taxi.passenger.model.TaxiPassengerGeocodeSearchModel; import com.mogo.och.taxi.passenger.model.TaxiPassengerModel; import com.mogo.och.taxi.passenger.ui.TaxiPassengerServingOrderFragment; -import java.util.ArrayList; import java.util.List; -import mogo.telematics.pad.MessagePad; - import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_TAXI_P; /** @@ -54,9 +51,11 @@ public class TaxiPassengerServingOrderPresenter extends Presenter mView.onCarLocationChanged(location)); + long currentTimeMillis = System.currentTimeMillis(); + if(currentTimeMillis-startTime { - OverlayLeftViewUtils.INSTANCE.showOverlayView(getActivity(),0,true,-1,true); - //showOrHideArrivedEndLayout(true, "北京北京北京", "1527481606997577728"); - //showOrHidePressengerCheckPager(true, "开始站点开", "开始站点开始站点开始", "2", "京A888888", "18811539480"); - //OCHFloatWindowManager.getInstance().ShowFloatWindow(getContext()); - }); } private void initArrivedView(){ diff --git a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerStartAutopilotView.java b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerStartAutopilotView.java index 5d8aba7836..7f93833b86 100644 --- a/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerStartAutopilotView.java +++ b/OCH/mogo-och-taxi-passenger/src/main/java/com/mogo/och/taxi/passenger/ui/TaxiPassengerStartAutopilotView.java @@ -101,9 +101,9 @@ public class TaxiPassengerStartAutopilotView extends RelativeLayout implements V mAutopilotBtnBg = view.findViewById(R.id.taxi_p_autopilot_btn_bg); mCarIv = view.findViewById(R.id.taxi_p_autopilot_starting); - initBtnAnimatonDrawable(); - - initCarStartingFrame(); +// initBtnAnimatonDrawable(); +// +// initCarStartingFrame(); } private void initCarStartingFrame() { diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_mogo_consult_title_icon.png b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_mogo_consult_title_icon.png index 1efa8c1b03..56452fe256 100644 Binary files a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_mogo_consult_title_icon.png and b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_mogo_consult_title_icon.png differ diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_mogo_movies_title_icon.png b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_mogo_movies_title_icon.png old mode 100755 new mode 100644 index 0768e35563..72dc087fd4 Binary files a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_mogo_movies_title_icon.png and b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi-2560x1440/taxi_p_mogo_movies_title_icon.png differ diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_mogo_consult_title_icon.png b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_mogo_consult_title_icon.png index 1efa8c1b03..56452fe256 100644 Binary files a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_mogo_consult_title_icon.png and b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_mogo_consult_title_icon.png differ diff --git a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_mogo_movies_title_icon.png b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_mogo_movies_title_icon.png old mode 100755 new mode 100644 index 0768e35563..72dc087fd4 Binary files a/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_mogo_movies_title_icon.png and b/OCH/mogo-och-taxi-passenger/src/main/res/drawable-xhdpi/taxi_p_mogo_movies_title_icon.png differ diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/DriverStatusQueryRespBean.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/DriverStatusQueryRespBean.java index d40b1222f2..ac630c9ecf 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/DriverStatusQueryRespBean.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/DriverStatusQueryRespBean.java @@ -5,13 +5,14 @@ import com.mogo.eagle.core.data.BaseData; /** * Created by pangfan on 2021/8/19 * - * 收车/出车状态查询返回数据结构 + * 状态查询返回数据结构 */ public class DriverStatusQueryRespBean extends BaseData { public Result data; public static class Result { - public int serviceStatus; //0收车,1出车 + public int servingStatus; //1接单,1暂停接单 + public int driverStatus; //1登录,0登出 public String orderNo; public int purpose; // 1 运营, 2 测试, 3演示 } diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/DriverStatusUpdateReqBean.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/DriverStatusUpdateReqBean.java index 73481aa296..cb018309d7 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/DriverStatusUpdateReqBean.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/DriverStatusUpdateReqBean.java @@ -3,14 +3,12 @@ package com.mogo.och.taxi.bean; /** * Created by pangfan on 2021/8/19 * - * 收车/出车状态更新请求数据结构 + * 状态更新请求数据结构 */ public class DriverStatusUpdateReqBean { public String sn; - public int status; //0收车,1出车 - public DriverStatusUpdateReqBean(String sn, int status) { + public DriverStatusUpdateReqBean(String sn) { this.sn = sn; - this.status = status; } } diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/TaxiLoginReqBean.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/TaxiLoginReqBean.java new file mode 100644 index 0000000000..0591d3f878 --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/TaxiLoginReqBean.java @@ -0,0 +1,30 @@ +package com.mogo.och.taxi.bean; + +/** + * Created by pangfan on 2021/8/19 + * 司机端准备好或者乘客已验证上车请求参数 + */ +public class TaxiLoginReqBean { + + public String phone; + public String captcha; + public String sn; + public Location4Login loc; + + public TaxiLoginReqBean(String phone, String code, String sn,Location4Login location4Login) { + this.phone = phone; + this.captcha = code; + this.sn = sn; + this.loc = location4Login; + } + + public static class Location4Login{ + double lat; + double lon; + + public Location4Login(double lat, double lon) { + this.lat = lat; + this.lon = lon; + } + } +} diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/TaxiLoginRespBean.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/TaxiLoginRespBean.java new file mode 100644 index 0000000000..c1265a9be3 --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/TaxiLoginRespBean.java @@ -0,0 +1,18 @@ +package com.mogo.och.taxi.bean; + +import com.mogo.eagle.core.data.BaseData; + +/** + * Created by pangfan on 2021/8/19 + * 司机端准备好或者乘客已验证上车请求参数 + */ +public class TaxiLoginRespBean extends BaseData { + + public TaxiLoginRespBean.Result data; + + public static class Result { + public Double lat; + public Double lon; + } + +} diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/TaxiLoginSmsReqBean.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/TaxiLoginSmsReqBean.java new file mode 100644 index 0000000000..3a4d4d7a4f --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/TaxiLoginSmsReqBean.java @@ -0,0 +1,14 @@ +package com.mogo.och.taxi.bean; + +/** + * Created by pangfan on 2021/8/19 + * 司机端准备好或者乘客已验证上车请求参数 + */ +public class TaxiLoginSmsReqBean { + + public String phone; + + public TaxiLoginSmsReqBean(String phone) { + this.phone = phone; + } +} diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/TaxiLogoutReqBean.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/TaxiLogoutReqBean.java new file mode 100644 index 0000000000..ced9b2eddb --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/bean/TaxiLogoutReqBean.java @@ -0,0 +1,25 @@ +package com.mogo.och.taxi.bean; + +/** + * Created by pangfan on 2021/8/19 + * 司机端准备好或者乘客已验证上车请求参数 + */ +public class TaxiLogoutReqBean { + public String sn; + public Location4Login loc; + + public TaxiLogoutReqBean(String sn, Location4Login location4Login) { + this.sn = sn; + this.loc = location4Login; + } + + public static class Location4Login{ + double lat; + double lon; + + public Location4Login(double lat, double lon) { + this.lat = lat; + this.lon = lon; + } + } +} diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/callback/ITaxiCarStatusCallback.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/callback/ITaxiCarStatusCallback.java index 531a6e1cf6..ac0eddc08a 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/callback/ITaxiCarStatusCallback.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/callback/ITaxiCarStatusCallback.java @@ -3,10 +3,12 @@ package com.mogo.och.taxi.callback; /** * Created on 2021/9/8 * - * Model->Presenter回调:出车/收车状态变更 + * Model->Presenter回调:接单车状态变更 登录状态变更 */ public interface ITaxiCarStatusCallback { void onCarStatusChanged(boolean inOperation,String role); void onServiceDataUpdate(long dailyTimeDuration, long dailyOrderNum); + + void onCarLoginStatusChange(boolean isLogin); } diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/callback/ITaxiLoginCallback.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/callback/ITaxiLoginCallback.java new file mode 100644 index 0000000000..a8f35171cb --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/callback/ITaxiLoginCallback.java @@ -0,0 +1,18 @@ +package com.mogo.och.taxi.callback; + +import androidx.annotation.NonNull; + +import com.mogo.och.taxi.bean.OrderQueryRespBean; +import com.mogo.och.taxi.bean.OrderQueryRouteInfoRespBean; + +import java.util.List; + +/** + * Created on 2021/9/8 + * + * Model->Presenter回调:订单相关(进行中/待服务单变更,当前进行单状态变更,新到预约单,抢单,抢单结果状态等等) + */ +public interface ITaxiLoginCallback { + void getPhoneCodeSuccess(); + void loginSuccess(); +} diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/constant/TaxiConst.kt b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/constant/TaxiConst.kt index cd34ecc455..41a1280592 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/constant/TaxiConst.kt +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/constant/TaxiConst.kt @@ -80,5 +80,7 @@ class TaxiConst { const val TYPE_MARKER_TAXI_ORDER = "TYPE_MARKER_TAXI_ORDER" const val TIMER_START_AUTOPILOT_INTERVAL = 20 * 1000L + + const val WAIT_TAKEN = 100046 } } \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/constant/TaxiLoginStatusEnum.kt b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/constant/TaxiLoginStatusEnum.kt new file mode 100644 index 0000000000..5e19782f5e --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/constant/TaxiLoginStatusEnum.kt @@ -0,0 +1,27 @@ +package com.mogo.och.taxi.constant + +/** + * Created on 2022/08/19 + * + * + * 0 初始状态, + * 10 已登录, + * 20 已登出, + */ +enum class TaxiLoginStatusEnum(val code: Int) { + None( 0 ), + Login( 10), + Logout( 20),; + + companion object { + @JvmStatic + fun valueOf(code: Int): TaxiLoginStatusEnum? { + for (value in values()) { + if (value.code == code) { + return value + } + } + return None + } + } +} \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/constant/TaxiOpenOrderStatusEnum.kt b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/constant/TaxiOpenOrderStatusEnum.kt new file mode 100644 index 0000000000..b583f28d3c --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/constant/TaxiOpenOrderStatusEnum.kt @@ -0,0 +1,27 @@ +package com.mogo.och.taxi.constant + +/** + * Created on 2022/08/19 + * + * + * 0 初始状态, + * 10 接单状态 可接单, + * 20 暂停接到哪 不可接单, + */ +enum class TaxiOpenOrderStatusEnum(val code: Int) { + None( 0 ), + Ordering( 10), + UnOrdering( 20),; + + companion object { + @JvmStatic + fun valueOf(code: Int): TaxiOpenOrderStatusEnum? { + for (value in values()) { + if (value.code == code) { + return value + } + } + return None + } + } +} \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiLoginModel.kt b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiLoginModel.kt new file mode 100644 index 0000000000..bdef0b53fd --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiLoginModel.kt @@ -0,0 +1,135 @@ +package com.mogo.och.taxi.model + +import android.annotation.SuppressLint +import android.content.Context +import com.mogo.eagle.core.data.BaseData +import com.mogo.eagle.core.utilcode.util.NetworkUtils +import com.mogo.och.taxi.model.TaxiLoginModel +import com.mogo.och.taxi.callback.ITaxiLoginCallback +import com.mogo.module.common.MogoApisHandler +import com.mogo.map.navi.IMogoCarLocationChangedListener2 +import com.mogo.och.taxi.network.TaxiServiceManager +import com.mogo.och.taxi.network.TaxiServiceCallback +import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.och.taxi.R +import com.mogo.och.taxi.bean.TaxiLoginReqBean +import com.mogo.och.taxi.bean.TaxiLoginRespBean +import com.mogo.och.taxi.constant.TaxiLoginStatusEnum +import com.mogo.och.taxi.utils.StatusManager + +/** + * Created by pangfan on 2021/8/19 + * + * + * 网约车 - 出租车业务逻辑处理 + */ +@SuppressLint("StaticFieldLeak") +object TaxiLoginModel{ + + private val TAG = "TaxiLoginModel" + private var mContext: Context? = null + var iTaxiLoginCallback: ITaxiLoginCallback? = null + private var mLongitude = 0.0 + private var mLatitude = 0.0 + fun init(context: Context) { + mContext = context.applicationContext + // 达到起始站围栏监听 + MogoApisHandler.getInstance() + .apis + .registerCenterApi + .registerCarLocationChangedListener(TAG, mCarLocationChangedListener2) + } + + fun hasInit():Boolean{ + if(mContext==null&& iTaxiLoginCallback==null){ + return false; + } + return true + } + + // 自车定位 + private val mCarLocationChangedListener2 = IMogoCarLocationChangedListener2 { location -> + mLongitude = location.longitude + mLatitude = location.latitude + } + + fun getiTaxiLoginCallback(): ITaxiLoginCallback? { + return iTaxiLoginCallback + } + + fun setiTaxiLoginCallback(iTaxiLoginCallback: ITaxiLoginCallback?) { + this.iTaxiLoginCallback = iTaxiLoginCallback + } + + fun release() { + mContext = null + iTaxiLoginCallback = null + // 注销到达起始站围栏监听 + MogoApisHandler.getInstance().apis.registerCenterApi + .unregisterCarLocationChangedListener(TAG, mCarLocationChangedListener2) + } + + /** + * 获取手机验证码 + */ + fun getPhoneCode(phone: String?) { + TaxiServiceManager.getInstance().getPhoneCode(mContext, phone, + object : TaxiServiceCallback { + override fun onSuccess(data: BaseData?) { + if (null != data && 0 == data.code) { + // 获取验证码成功 + ToastUtils.showShort(mContext?.getString(R.string.module_och_taxi_login_get_code_success)) + iTaxiLoginCallback?.getPhoneCodeSuccess() + } else { + if (data != null) { + ToastUtils.showShort(data.code) + } + } + } + + override fun onError() { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort(mContext?.getString(R.string.network_error_tip)) + } else { + ToastUtils.showShort(mContext?.getString(R.string.request_error_tip)) + } + } + + override fun onFail(code: Int, msg: String) { + ToastUtils.showShort("$code,$msg") + } + }) + } + + fun gotoLogin(phone: String, code: String) { + val location4Login = TaxiLoginReqBean.Location4Login(mLatitude, mLongitude) + TaxiServiceManager.getInstance().gotoLoginBycode(mContext, phone, code, location4Login, + object : TaxiServiceCallback { + override fun onSuccess(data: TaxiLoginRespBean?) { + if (null != data && 0 == data.code) { + // 获取验证码成功 + ToastUtils.showShort(mContext?.getString(R.string.module_och_taxi_login_login_success)) + StatusManager.setLoginStatus(TaxiLoginStatusEnum.Login) + iTaxiLoginCallback?.loginSuccess() + } else { + if (data != null) { + ToastUtils.showShort(data.code) + } + } + } + + override fun onError() { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort(mContext?.getString(R.string.network_error_tip)) + } else { + ToastUtils.showShort(mContext?.getString(R.string.request_error_tip)) + } + } + + override fun onFail(code: Int, msg: String) { + ToastUtils.showShort("$code,$msg") + } + }) + } + +} \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModel.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModel.java index 0e2c7f5ea3..06b77b0491 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModel.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModel.java @@ -36,6 +36,7 @@ import com.mogo.map.navi.IMogoCarLocationChangedListener2; import com.mogo.module.common.MogoApisHandler; import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil; import com.mogo.och.common.module.utils.PinYinUtil; +import com.mogo.och.common.module.utils.ToastUtilsOch; import com.mogo.och.taxi.R; import com.mogo.och.taxi.bean.DriverServiceDataRespBean; import com.mogo.och.taxi.bean.DriverStatusQueryRespBean; @@ -49,6 +50,7 @@ import com.mogo.och.taxi.bean.OrdersListQueryRespBean; import com.mogo.och.taxi.bean.OrdersNewBookingQueryRespBean; import com.mogo.och.taxi.bean.QueryOrderRouteResp; import com.mogo.och.taxi.bean.TaxiDataBaseRespBean; +import com.mogo.och.taxi.bean.TaxiLogoutReqBean; import com.mogo.och.taxi.bean.TaxiOrPassengerReadyReqBean; import com.mogo.och.taxi.callback.ITaxiADASStatusCallback; import com.mogo.och.taxi.callback.ITaxiCarStatusCallback; @@ -60,6 +62,7 @@ import com.mogo.och.taxi.constant.TaxiOrderStatusEnum; import com.mogo.och.taxi.constant.TaxiOrderTypeEnum; import com.mogo.och.taxi.network.TaxiServiceCallback; import com.mogo.och.taxi.network.TaxiServiceManager; +import com.mogo.och.taxi.utils.StatusManager; import com.mogo.och.taxi.utils.TaxiAnalyticsManager; import com.mogo.och.taxi.utils.OrderUtil; import com.mogo.aicloud.services.socket.IMogoLifecycleListener; @@ -76,7 +79,10 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.TimeUnit; +import io.reactivex.Observable; +import io.reactivex.disposables.Disposable; import io.reactivex.exceptions.UndeliverableException; import io.reactivex.functions.Consumer; import io.reactivex.plugins.RxJavaPlugins; @@ -103,7 +109,6 @@ public class TaxiModel { private Context mContext; private volatile int mPrevAPStatus = -1; //前一次自动驾驶状态值 - private volatile int mOCHCarStatus = -1; //出车/收车状态:1 出车;0 收车 private volatile String mPrevOrderNo = ""; //前一次的新到单id(当次和前一次orderId相同时,本次不再弹出) private volatile OrderQueryRespBean.Result mNewBookingOrder; //新到待抢预约单 private volatile OrderQueryRespBean.Result mCurrentOCHOrder; //当前订单 @@ -111,9 +116,10 @@ public class TaxiModel { private volatile List mWaitServiceList = Collections.emptyList(); //待服务订单 private ITaxiADASStatusCallback mADASStatusCallback; //Model->Presenter:自动驾驶状态相关 - private ITaxiCarStatusCallback mCarStatusCallback; //Model->Presenter:出车/收车状态 + private ITaxiCarStatusCallback mCarStatusCallback; //Model->Presenter:接单状态、登录状态和司机今日接单状态 private ITaxiControllerStatusCallback mControllerStatusCallback; //Model->Presenter:VR mode等 private ITaxiOrderStatusCallback mOrderStatusCallback; //Model->Presenter:订单变更 + private Disposable subscribe; private volatile boolean isRestartAutopilot = false; @@ -187,16 +193,16 @@ public class TaxiModel { CallerLogger.INSTANCE.d(M_TAXI + TAG, "Undeliverable exception"); } }); - - if (NetworkUtils.isConnected(mContext)) { - queryCarStatus(); - } + queryCarStatus(); } public void release() { startOrStopOrderLoop(false); startOrStopCalculateRouteInfo(false); releaseListeners(); + if(subscribe!=null&&!subscribe.isDisposed()){ + subscribe.dispose(); + } } private void initListeners() { @@ -255,17 +261,28 @@ public class TaxiModel { } } - //查询出车/收车状态 + /** + * 接单状态和登录状态查询 + * 1、初始化查下状态 + * 2、点击更新接单状态 如果是初始化状态就查下状态 + * 3、点击更新接单状态后 查询状态 + * 4、网络状态波动时 查询状态 + * 5、登出后更新状态 + */ public void queryCarStatus() { TaxiServiceManager.getInstance().queryDriverServiceStatus(mContext, new TaxiServiceCallback() { @Override public void onSuccess(DriverStatusQueryRespBean data) { if (null != data && 0 == data.code) { - mOCHCarStatus = data.data.serviceStatus == 1 ? 1 : 0; + StatusManager.setLoginStatus(data.data.driverStatus); + StatusManager.setOpenOrderStatus(data.data.servingStatus); //更新view - CallerLogger.INSTANCE.d(M_TAXI + TAG, "changeCarStatus:" + mOCHCarStatus); - startOrStopOrderLoop(mOCHCarStatus == 1); + CallerLogger.INSTANCE.d(M_TAXI + TAG, "changeCarStatus:" + StatusManager.getLoginStatus()); + startOrStopOrderLoop(StatusManager.isLogin()&&StatusManager.isOpeningOrderStatus()); + if(mCarStatusCallback!=null) { + mCarStatusCallback.onCarLoginStatusChange(StatusManager.isLogin()); + } String role = ""; if (TaxiDriverRoleEnum.DEMO.getCode() == data.data.purpose) { role = TaxiConst.DEMO_USER; @@ -273,7 +290,7 @@ public class TaxiModel { role = TaxiConst.TEST_USER; } if (mCarStatusCallback != null) { - mCarStatusCallback.onCarStatusChanged(mOCHCarStatus == 1, role); + mCarStatusCallback.onCarStatusChanged(StatusManager.isOpeningOrderStatus(), role); } } @@ -286,30 +303,39 @@ public class TaxiModel { } else { ToastUtils.showShort(mContext.getString(R.string.request_error_tip)); } -// queryCarStatus(); + subscribe = Observable.timer(5, TimeUnit.SECONDS).subscribe(aLong -> { + queryCarStatus(); + }); } @Override public void onFail(int code, String msg) { - ToastUtils.showShort(code + "," + msg); -// queryCarStatus(); + ToastUtilsOch.showWithCodeMessage(code,msg); + if(code==TaxiConst.WAIT_TAKEN){ + subscribe = Observable.timer(3, TimeUnit.SECONDS).subscribe(aLong -> { + queryCarStatus(); + }); + }else { + if (mCarStatusCallback != null) { + mCarStatusCallback.onCarLoginStatusChange(StatusManager.isLogin()); + } + } } }); } - //更新出车收车状态 + //更新接单状态 public void updateCarStatus() { - if (mOCHCarStatus == -1) { + if(!StatusManager.isLogin()){ queryCarStatus(); return; } - final int status = mOCHCarStatus == 1 ? 0 : 1; - TaxiServiceManager.getInstance().updateDriverServiceStatus(mContext, status, + TaxiServiceManager.getInstance().changeOrderServing(mContext,StatusManager.isOpeningOrderStatus(), new TaxiServiceCallback() { @Override public void onSuccess(BaseData data) { if (null != data && 0 == data.code) { - mOCHCarStatus = status; + //StatusManager.changeOrderStatus(); queryCarStatus(); } } @@ -325,9 +351,10 @@ public class TaxiModel { @Override public void onFail(int code, String msg) { - ToastUtils.showShort(code + "," + msg); + ToastUtilsOch.showWithCodeMessage(code, msg); } }); + } /** @@ -470,7 +497,7 @@ public class TaxiModel { @Override public void onFail(int code, String msg) { - ToastUtils.showShort(code + "," + msg); + ToastUtilsOch.showWithCodeMessage(code,msg); } }); } @@ -499,7 +526,7 @@ public class TaxiModel { @Override public void onFail(int code, String msg) { - ToastUtils.showShort(code + "," + msg); + ToastUtilsOch.showWithCodeMessage(code,msg); } }); } @@ -553,7 +580,7 @@ public class TaxiModel { @Override public void onFail(int code, String msg) { - ToastUtils.showShort(code + "," + msg); + ToastUtilsOch.showWithCodeMessage(code,msg); } }); } @@ -647,7 +674,7 @@ public class TaxiModel { @Override public void onFail(int code, String msg) { - ToastUtils.showShort(code + "," + msg); + ToastUtilsOch.showWithCodeMessage(code,msg); } }); } @@ -741,7 +768,7 @@ public class TaxiModel { @Override public void onFail(int code, String msg) { - ToastUtils.showShort(code + "," + msg); + ToastUtilsOch.showWithCodeMessage(code,msg); } }); } @@ -832,6 +859,7 @@ public class TaxiModel { && mCurrentOCHOrder.orderStatus == TaxiOrderStatusEnum.OnTheWayToEnd.getCode()) { // 当美化模式(演示模式)开启时: 订单对应自动驾驶开启后,置true FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = true; + CallerAutoPilotManager.INSTANCE.setIgnoreConditionDraw(true); CallerAutoPilotManager.INSTANCE.setIPCDemoMode(true); CallerLogger.INSTANCE.d(M_TAXI + TAG, "美化模式-ignore:置为true(更新本地order信息)"); } @@ -839,6 +867,7 @@ public class TaxiModel { //清除订单信息 public void clearCurrentOCHOrder() { + startOrStopCalculateRouteInfo(false); mCurrentOCHOrder = null; TaxiTrajectoryManager.getInstance().syncTrajectoryInfo(); SharedPrefsMgr.getInstance(mContext).remove(TaxiConst.SP_KEY_OCH_TAXI_ORDER); @@ -846,6 +875,7 @@ public class TaxiModel { if (FunctionBuildConfig.isDemoMode) { // 当美化模式(演示模式)开启时: 取消或订单已完成时,置false FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = false; + CallerAutoPilotManager.INSTANCE.setIgnoreConditionDraw(false); CallerAutoPilotManager.INSTANCE.setIPCDemoMode(false); CallerLogger.INSTANCE.d(M_TAXI + TAG, "美化模式-ignore:置为false(已完成or清除当前订单)"); } @@ -972,7 +1002,7 @@ public class TaxiModel { CallerLogger.INSTANCE.d(M_TAXI + TAG, "onIntentReceived = %s", intentStr); if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intentStr)) { if (NetworkUtils.isConnected(mContext)) { - startOrStopOrderLoop(mOCHCarStatus == 1); + startOrStopOrderLoop(StatusManager.isLogin()&&StatusManager.isOpeningOrderStatus()); queryCarStatus(); } } @@ -1135,6 +1165,7 @@ public class TaxiModel { if (FunctionBuildConfig.isDemoMode) { // 当美化模式(演示模式)开启时: 订单对应自动驾驶开启后,置true FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = true; + CallerAutoPilotManager.INSTANCE.setIgnoreConditionDraw(true); CallerAutoPilotManager.INSTANCE.setIPCDemoMode(true); CallerLogger.INSTANCE.d(M_TAXI + TAG, "美化模式-ignore:置为true(到达出发点且已开启自动驾驶)"); } @@ -1166,11 +1197,16 @@ public class TaxiModel { mPrevAPStatus = state; }else if (state == IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING){ - if (FunctionBuildConfig.isDemoMode - && checkCurrentOCHOrder() - && (getCurOrderStatus() == TaxiOrderStatusEnum.OnTheWayToEnd - || getCurOrderStatus() == TaxiOrderStatusEnum.ArriveAtEnd)) { - // 当美化模式(演示模式)开启时:且有订单、且为去往目的地状态,维持自动驾驶icon开启状态 + if (FunctionBuildConfig.isDemoMode){ + if (checkCurrentOCHOrder() + && (getCurOrderStatus() == TaxiOrderStatusEnum.OnTheWayToEnd + || getCurOrderStatus() == TaxiOrderStatusEnum.ArriveAtEnd)){//订单中 + // 当美化模式(演示模式)开启时:且有订单、且为去往目的地状态,维持自动驾驶icon开启状态 + }else { //美化模式下没订单,显示人工驾驶 + if (mADASStatusCallback != null){ + mADASStatusCallback.onAutopilotDisable(); + } + } return; } if (state != mPrevAPStatus && mADASStatusCallback != null){ @@ -1198,6 +1234,7 @@ public class TaxiModel { if (FunctionBuildConfig.isDemoMode) { // 当美化模式(演示模式)开启时: 到达目的地,置false FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = false; + CallerAutoPilotManager.INSTANCE.setIgnoreConditionDraw(false); CallerAutoPilotManager.INSTANCE.setIPCDemoMode(false); CallerLogger.INSTANCE.d(M_TAXI + TAG, "美化模式-ignore:置为false(到达目的地)"); } @@ -1292,14 +1329,30 @@ public class TaxiModel { queryOrderRouteList(mCurrentOCHOrder.orderNo); } Logger.d(M_TAXI + TAG, "--------mRoutePoints.size---------- " + mRoutePoints.size()); + + if (mRoutePoints.size() > 0){ + reportTotalDisAndTime(); + } //开启实时计算剩余距离,剩余时间,预计时间 startOrStopCalculateRouteInfo(true); } + private void reportTotalDisAndTime() { + float lastSumLength = CoordinateCalculateRouteUtil.calculateRouteSumLength(mRoutePoints); + double lastTime = lastSumLength / TaxiConst.TAXI_AVERAGE_SPEED * 3.6; //秒 +// if (mOrderStatusCallback != null) { +// mOrderStatusCallback.onCurrentOrderDistToEndChanged((long) lastSumLength, (long) lastTime); +// } + reportOrderRemain((long) lastSumLength, (long) lastTime); + } + /** * 实时计算当前剩余里程和时间 */ public void dynamicCalculateRouteInfo() { + if (mLatitude <= 0.0 || mLongitude <= 0.0){ + return; + } if (mRoutePoints.size() > 0){ List lastPoints = CoordinateCalculateRouteUtil .getRemainPointListByCompare(mRoutePoints, mLongitude, mLatitude); @@ -1367,7 +1420,7 @@ public class TaxiModel { TaxiModelLoopManager.getInstance().startCalculateRouteInfoLoop(); } else { mRoutePoints.clear(); - TaxiModelLoopManager.getInstance().stopCalculateRouteInfLoop(); + TaxiModelLoopManager.getInstance().stopCalculateRouteInfoLoop(); } } @@ -1524,4 +1577,33 @@ public class TaxiModel { mOrderStatusCallback.onCurrentOrderStatusChanged(mCurrentOCHOrder); } } + + // 登出 + public void logout() { + TaxiLogoutReqBean.Location4Login location4Login = new TaxiLogoutReqBean.Location4Login(mLatitude, mLongitude); + TaxiServiceManager.getInstance().logout(mContext,location4Login, + new TaxiServiceCallback() { + @Override + public void onSuccess(BaseData data) { + if (null != data && 0 == data.code) { + mCarStatusCallback.onCarLoginStatusChange(false); + queryCarStatus(); + } + } + + @Override + public void onError() { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort(mContext.getString(R.string.network_error_tip)); + } else { + ToastUtils.showShort(mContext.getString(R.string.request_error_tip)); + } + } + + @Override + public void onFail(int code, String msg) { + ToastUtilsOch.showWithCodeMessage(code,msg); + } + }); + } } diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModelLoopManager.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModelLoopManager.java index 63f281cacf..3a771ca3ae 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModelLoopManager.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/model/TaxiModelLoopManager.java @@ -166,9 +166,9 @@ public class TaxiModelLoopManager { }); } - public void stopCalculateRouteInfLoop() { + public void stopCalculateRouteInfoLoop() { if (mCalculateRouteDisposable != null) { - CallerLogger.INSTANCE.i(M_TAXI + TAG, "stopCalculateRouteInfLoop()"); + CallerLogger.INSTANCE.i(M_TAXI + TAG, "stopCalculateRouteInfoLoop()"); mCalculateRouteDisposable.dispose(); mCalculateRouteDisposable = null; } diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/network/TaxiServiceApiNew.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/network/TaxiServiceApiNew.java index 8c8a6a7c0e..8b29d4039d 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/network/TaxiServiceApiNew.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/network/TaxiServiceApiNew.java @@ -20,6 +20,10 @@ import com.mogo.och.taxi.bean.OrdersListQueryRespBean; import com.mogo.och.taxi.bean.OrdersNewBookingQueryRespBean; import com.mogo.och.taxi.bean.QueryOrderRouteResp; import com.mogo.och.taxi.bean.TaxiDataBaseRespBean; +import com.mogo.och.taxi.bean.TaxiLoginReqBean; +import com.mogo.och.taxi.bean.TaxiLoginRespBean; +import com.mogo.och.taxi.bean.TaxiLoginSmsReqBean; +import com.mogo.och.taxi.bean.TaxiLogoutReqBean; import com.mogo.och.taxi.bean.TaxiOrPassengerReadyReqBean; import com.mogo.och.taxi.bean.UpdateOrderDisAndTimeReqBean; @@ -150,28 +154,6 @@ interface TaxiServiceApiNew { Observable updateOrderStatus(@Header ("appId") String appId,@Header("ticket") String ticket ,@Body OrderStatusUpdateReqBean data); - /** - * 收车/出车状态更新 - * @param data - * @return - */ - @Headers( {"Content-type:application/json;charset=UTF-8"} ) -// @POST( "/autopilot-car-hailing/api/v1/driver/serviceStatus/update" ) - @POST( "/autopilot-car-hailing/car/v2/driver/taxi/serviceStatus/update" ) - Observable updateDriverServiceStatus(@Header ("appId") String appId,@Header("ticket") String ticket - ,@Body DriverStatusUpdateReqBean data); - - /** - * 收车/出车状态查询 - * @param sn - * @return - */ - @Headers( {"Content-type:application/json;charset=UTF-8"} ) -// @GET( "/autopilot-car-hailing/api/v1/driver/serviceStatus/query" ) - @GET( "/autopilot-car-hailing/car/v2/driver/taxi/serviceStatus/query" ) - Observable queryDriverServiceStatus(@Header ("appId") String appId - ,@Header("ticket") String ticket,@Query("sn") String sn); - /** * 车机端上传心跳数据(只在出车状态时上传):包含高德坐标系经纬度 * @param data @@ -307,4 +289,65 @@ interface TaxiServiceApiNew { @POST( "/autopilot-car-hailing/cab/flow/v1/driver/taxi/orderCompleted" ) Observable orderCompleted(@Header ("appId") String appId , @Header("ticket") String ticket,@Body TaxiOrPassengerReadyReqBean data); + + + /** + * 获取手机验证码 + * + * @return + */ + @Headers( {"Content-type:application/json;charset=UTF-8"} ) +// @GET( "/autopilot-car-hailing/api/v1/driver/serviceStatus/query" ) + @POST( "/autopilot-car-hailing/driver/v2/driver/taxi/sendSms" ) + Observable getPhoneCode(@Header ("appId") String appId + ,@Header("ticket") String ticket,@Body TaxiLoginSmsReqBean data); + /** + * 通过验证码登录 + * @param appId + * @param ticket + * @param data + * @return + */ + @Headers( {"Content-type:application/json;charset=UTF-8"} ) + @POST( "/autopilot-car-hailing/cab/flow/v1/driver/taxi/startOperation" ) + Observable gotoLoginBycode(@Header ("appId") String appId + , @Header("ticket") String ticket, @Body TaxiLoginReqBean data); + /** + * 登出接口 + */ + @Headers({"Content-type:application/json;charset=UTF-8"}) + @POST("/autopilot-car-hailing/cab/flow/v1/driver/taxi/endOperation") + Observable logout(@Header ("appId") String appId,@Header("ticket") String ticket, + @Body TaxiLogoutReqBean data); + /** + * 暂停接单 + * @param data + * @return + */ + @Headers( {"Content-type:application/json;charset=UTF-8"} ) +// @POST( "/autopilot-car-hailing/api/v1/driver/serviceStatus/update" ) + @POST( "/autopilot-car-hailing/cab/flow/v1/driver/taxi/stopOrderServing" ) + Observable stopOrderServing(@Header ("appId") String appId,@Header("ticket") String ticket + ,@Body DriverStatusUpdateReqBean data); + /** + * 暂停接单 + * @param data + * @return + */ + @Headers( {"Content-type:application/json;charset=UTF-8"} ) +// @POST( "/autopilot-car-hailing/api/v1/driver/serviceStatus/update" ) + @POST( "/autopilot-car-hailing/cab/flow/v1/driver/taxi/resetOrderServing" ) + Observable resetOrderServing(@Header ("appId") String appId,@Header("ticket") String ticket + ,@Body DriverStatusUpdateReqBean data); + /** + * 接单状态和登录状态查询 + * @param sn + * @return + */ + @Headers( {"Content-type:application/json;charset=UTF-8"} ) +// @GET( "/autopilot-car-hailing/api/v1/driver/serviceStatus/query" ) + @GET( "/autopilot-car-hailing/operation/v1/driver/taxi/loginStatus" ) + Observable queryDriverServiceStatusAndLoginStatus(@Header ("appId") String appId + ,@Header("ticket") String ticket,@Query("sn") String sn); + } diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/network/TaxiServiceManager.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/network/TaxiServiceManager.java index 279623f531..333ca64fd9 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/network/TaxiServiceManager.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/network/TaxiServiceManager.java @@ -4,6 +4,7 @@ import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_TAX import android.content.Context; +import com.mogo.cloud.passport.MoGoAiCloudClient; import com.mogo.cloud.passport.MoGoAiCloudClientConfig; import com.mogo.eagle.core.data.BaseData; import com.mogo.eagle.core.network.MoGoRetrofitFactory; @@ -30,12 +31,17 @@ import com.mogo.och.taxi.bean.OrdersListQueryRespBean; import com.mogo.och.taxi.bean.OrdersNewBookingQueryRespBean; import com.mogo.och.taxi.bean.QueryOrderRouteResp; import com.mogo.och.taxi.bean.TaxiDataBaseRespBean; +import com.mogo.och.taxi.bean.TaxiLoginReqBean; +import com.mogo.och.taxi.bean.TaxiLoginRespBean; +import com.mogo.och.taxi.bean.TaxiLoginSmsReqBean; +import com.mogo.och.taxi.bean.TaxiLogoutReqBean; import com.mogo.och.taxi.bean.TaxiOrPassengerReadyReqBean; import com.mogo.och.taxi.bean.UpdateOrderDisAndTimeReqBean; import com.mogo.och.taxi.constant.TaxiConst; import java.util.List; +import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; @@ -232,31 +238,44 @@ public class TaxiServiceManager { .subscribe(getSubscribeImpl(context, callback, "updateOrderStatus")); } + /** - * 收车/出车状态更新 + * 暂停接单 * @param context - * @param status * @param callback */ - public void updateDriverServiceStatus(Context context, int status, - TaxiServiceCallback callback) { - mOCHTaxiServiceApi.updateDriverServiceStatus(MoGoAiCloudClientConfig.getInstance().getServiceAppId() - ,MoGoAiCloudClientConfig.getInstance().getToken() - ,new DriverStatusUpdateReqBean( - MoGoAiCloudClientConfig.getInstance().getSn(), status)) - .subscribeOn(Schedulers.io()) + public void changeOrderServing(Context context,boolean isOrdering, + TaxiServiceCallback callback) { + Observable baseDataObservable = null; + if(isOrdering) {// 正在接单去暂停 + baseDataObservable = mOCHTaxiServiceApi.stopOrderServing(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + , MoGoAiCloudClientConfig.getInstance().getToken() + , new DriverStatusUpdateReqBean( + MoGoAiCloudClientConfig.getInstance().getSn())); + }else {// 没有接单去接单 + baseDataObservable = mOCHTaxiServiceApi.resetOrderServing(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + , MoGoAiCloudClientConfig.getInstance().getToken() + , new DriverStatusUpdateReqBean( + MoGoAiCloudClientConfig.getInstance().getSn())); + } + baseDataObservable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(getSubscribeImpl(context, callback, "updateDriverServiceStatus")); } /** - * 收车/出车状态查询 + * 接单状态和登录状态查询 * @param context * @param callback */ public void queryDriverServiceStatus(Context context, TaxiServiceCallback callback) { - mOCHTaxiServiceApi.queryDriverServiceStatus(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + if(MoGoAiCloudClientConfig.getInstance().getToken().isEmpty()){ + callback.onFail(TaxiConst.WAIT_TAKEN,"等待令牌中请稍等"); + MoGoAiCloudClient.getInstance().refreshToken(); + return; + } + mOCHTaxiServiceApi.queryDriverServiceStatusAndLoginStatus(MoGoAiCloudClientConfig.getInstance().getServiceAppId() ,MoGoAiCloudClientConfig.getInstance().getToken() ,MoGoAiCloudClientConfig.getInstance().getSn()) .subscribeOn(Schedulers.io()) @@ -436,6 +455,52 @@ public class TaxiServiceManager { } + /** + * 获取手机验证码 + * @param context + * @param callback + */ + public void getPhoneCode(Context context,String phone, + TaxiServiceCallback callback) { + mOCHTaxiServiceApi.getPhoneCode(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + , MoGoAiCloudClientConfig.getInstance().getToken() + , new TaxiLoginSmsReqBean(phone)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(getSubscribeImpl(context, callback, "getPhoneCode")); + } + /** + * 通过验证码登录 + * @param context + * @param callback + */ + public void gotoLoginBycode(Context context, String phone, String code, + TaxiLoginReqBean.Location4Login location4Login, + TaxiServiceCallback callback) { + String sn = MoGoAiCloudClientConfig.getInstance().getSn(); + mOCHTaxiServiceApi.gotoLoginBycode(MoGoAiCloudClientConfig.getInstance().getServiceAppId() + , MoGoAiCloudClientConfig.getInstance().getToken() + , new TaxiLoginReqBean(phone, code, sn, location4Login)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(getSubscribeImpl(context, callback, "gotoLoginBycode")); + } + + /** + * 登出 + */ + public void logout(Context context, TaxiLogoutReqBean.Location4Login location4Login, TaxiServiceCallback callback) { + mOCHTaxiServiceApi.logout( + MoGoAiCloudClientConfig.getInstance().getServiceAppId(), + MoGoAiCloudClientConfig.getInstance().getToken(), + new TaxiLogoutReqBean(MoGoAiCloudClientConfig.getInstance().getSn(), location4Login)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(getSubscribeImpl(context, callback, "logout")); + } + + + private SubscribeImpl getSubscribeImpl( Context context, TaxiServiceCallback callback, String apiName) { return new SubscribeImpl(RequestOptions.create(context)) { diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/TaxiLoginPresenter.kt b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/TaxiLoginPresenter.kt new file mode 100644 index 0000000000..1497683ddc --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/TaxiLoginPresenter.kt @@ -0,0 +1,112 @@ +package com.mogo.och.taxi.presenter + +import androidx.lifecycle.LifecycleOwner +import com.mogo.commons.AbsMogoApplication +import com.mogo.commons.mvp.Presenter +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.RegexUtils +import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.och.taxi.R +import com.mogo.och.taxi.callback.ITaxiLoginCallback +import com.mogo.och.taxi.model.TaxiLoginModel +import com.mogo.och.taxi.ui.TaxiLoginDialogFragment +import io.reactivex.Observable +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.Disposable +import io.reactivex.schedulers.Schedulers +import java.util.concurrent.TimeUnit + +/** + * @author congtaowang + * @since 2021/1/18 + * + * 描述 + */ +class TaxiLoginPresenter(view: TaxiLoginDialogFragment?) : + Presenter(view), ITaxiLoginCallback { + + private var countDownDisposable: Disposable? = null + + init { + initListeners() + } + + private fun initListeners() { + TaxiLoginModel.init(AbsMogoApplication.getApp()) + TaxiLoginModel.setiTaxiLoginCallback(this) + } + + fun getPhoneCode(phone:String){ + if(!TaxiLoginModel.hasInit()){ + initListeners() + } + if (!RegexUtils.isMobileExact(phone)) { + ToastUtils.showShort(R.string.module_och_taxi_login_phone_error) + mView?.inputPhoneError() + return + } + TaxiLoginModel.getPhoneCode(phone) + } + + override fun onCreate(owner: LifecycleOwner) { + super.onCreate(owner) + CallerLogger.d(SceneConstant.M_TAXI + TAG, "网约车-出租车登陆") + } + + + + override fun onDestroy(owner: LifecycleOwner) { + super.onDestroy(owner) + TaxiLoginModel.release() + countDownDisposable?.let { + if (!it.isDisposed) { + it.dispose() + } + } + } + + companion object { + private val TAG = TaxiLoginPresenter::class.java.simpleName + } + + override fun getPhoneCodeSuccess() { + val countDownSeconds = 60L; + countDownDisposable = Observable.intervalRange(0, countDownSeconds, 0, 1, TimeUnit.SECONDS) + .map { aLong -> countDownSeconds - aLong } + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + mView?.setCountDownText("${it}s",false) + CallerLogger.d(SceneConstant.M_TAXI_P + TAG, "倒计时:$it") + }, { + CallerLogger.d(SceneConstant.M_TAXI_P + TAG, "倒计时onError:${it}") + it.printStackTrace() + mView?.setCountDownText(context.getString(R.string.module_och_taxi_login_get_code),true) + }, { + CallerLogger.d(SceneConstant.M_TAXI_P + TAG, "倒计时onComplete") + mView?.setCountDownText(context.getString(R.string.module_och_taxi_login_get_code),true) + }) + } + + override fun loginSuccess() { + mView?.loginSuccess() + } + + fun gotoLogin(phone: String, code: String) { + if(!TaxiLoginModel.hasInit()){ + initListeners() + } + if (!RegexUtils.isMobileExact(phone)) { + ToastUtils.showShort(R.string.module_och_taxi_login_phone_error) + mView?.inputPhoneError() + return + } + if(code.isBlank()||code.length<4){ + ToastUtils.showShort(R.string.module_och_taxi_login_code_error) + return + } + mView?.closeSoftInput() + TaxiLoginModel.gotoLogin(phone,code) + } +} \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/TaxiPresenter.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/TaxiPresenter.java index add02f86c8..5bd2c9cb2f 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/TaxiPresenter.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/presenter/TaxiPresenter.java @@ -41,6 +41,9 @@ public class TaxiPresenter extends Presenter implements ITaxiADASS private static final String TAG = TaxiPresenter.class.getSimpleName(); + private boolean isFirstShow = true; + private int preAutopilotStatus = 0; + public TaxiPresenter(TaxiFragment view) { super(view); TaxiModel.getInstance().init(AbsMogoApplication.getApp()); @@ -61,6 +64,16 @@ public class TaxiPresenter extends Presenter implements ITaxiADASS TaxiModel.getInstance().release(); } + @Override + public void onResume(@NonNull LifecycleOwner owner) { + super.onResume(owner); + if(isFirstShow){ + isFirstShow = false; + }else { + TaxiModel.getInstance().queryCarStatus(); + } + } + private void initListeners() { TaxiModel.getInstance().setADASStatusCallback(this); TaxiModel.getInstance().setCarStatusCallback(this); @@ -100,6 +113,13 @@ public class TaxiPresenter extends Presenter implements ITaxiADASS TaxiModel.getInstance().jumpPassengerCheckDone(); } + /** + * 登录成功后查询登录状态 + */ + public void queryLoginStatus() { + TaxiModel.getInstance().queryCarStatus(); + } + /** * 司机确认车辆环境可开启自动驾驶 */ @@ -107,7 +127,7 @@ public class TaxiPresenter extends Presenter implements ITaxiADASS TaxiModel.getInstance().confirmAutopilotConditionByDriver(); } - // 更新出车/收车状态 + // 更新接单状态 public void updateCarStatus() { TaxiModel.getInstance().updateCarStatus(); } @@ -158,6 +178,11 @@ public class TaxiPresenter extends Presenter implements ITaxiADASS TaxiModel.getInstance().orderCompleted(); } + // 登出 + public void logout() { + TaxiModel.getInstance().logout(); + } + @Override public void onAutopilotArriveEnd() { @@ -167,24 +192,30 @@ public class TaxiPresenter extends Presenter implements ITaxiADASS public void onAutopilotEnable() { runOnUIThread(() -> mView.updateAutopilotStatus( IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE)); + preAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE; } @Override public void onAutopilotDisable() { runOnUIThread(() -> mView.updateAutopilotStatus( IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE)); + preAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE; } @Override public void onAutopilotRunning() { - runOnUIThread(() -> mView.updateAutopilotStatus( - IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING)); + if (preAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING){ + runOnUIThread(() -> mView.updateAutopilotStatus( + IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING)); + } + preAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING; } @Override public void onManMachineCoDriving() { runOnUIThread(() -> mView.onManMachineCoDriving(IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING)); + preAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING; } @Override @@ -197,6 +228,15 @@ public class TaxiPresenter extends Presenter implements ITaxiADASS runOnUIThread(() -> mView.onServiceDataUpdate(dailyTimeDuration,dailyOrderNum)); } + @Override + public void onCarLoginStatusChange(boolean isLogin) { + if(isLogin){ + mView.hideLoginDialogFragment(); + }else { + mView.showLoginDialogFragment(); + } + } + @Override public void onOrdersInServiceChanged(@NonNull @NotNull List inServiceList) { diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/BaseTaxiTabFragment.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/BaseTaxiTabFragment.java index e1f8da1bc8..32c19748a4 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/BaseTaxiTabFragment.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/BaseTaxiTabFragment.java @@ -5,6 +5,8 @@ import static com.mogo.och.taxi.constant.TaxiConst.TIMER_START_AUTOPILOT_INTERVA import android.animation.ObjectAnimator; import android.os.Handler; import android.os.Looper; +import android.os.SystemClock; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.animation.LinearInterpolator; @@ -19,6 +21,7 @@ import androidx.annotation.Nullable; import androidx.constraintlayout.widget.Group; import androidx.fragment.app.FragmentTransaction; +import com.mogo.cloud.httpdns.util.L; import com.mogo.commons.AbsMogoApplication; import com.mogo.commons.debug.DebugConfig; import com.mogo.commons.mvp.IView; @@ -65,7 +68,6 @@ public abstract class BaseTaxiTabFragment { // onAutopilotStatusChanged(false); @@ -178,7 +180,7 @@ public abstract class BaseTaxiTabFragment onGoToTaxiOrders()); mSettingBtn = findViewById(R.id.module_och_taxi_setting_layout); mSettingBtn.setOnClickListener(v -> { @@ -237,9 +245,6 @@ public abstract class BaseTaxiTabFragment { if (groupTestPanel.getVisibility() == View.VISIBLE) { groupTestPanel.setVisibility(View.GONE); @@ -258,7 +263,7 @@ public abstract class BaseTaxiTabFragment taxiLoginDialogFragment = null; private WeakReference personalDialogFragment = null; protected double mCurLatitude = 0.0; protected double mCurLongitude = 0.0; + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + EventBus.getDefault().register(this); + return super.onCreateView(inflater, container, savedInstanceState); + } + @Override public int getStationPanelViewId() { return R.layout.taxi_panel; @@ -148,11 +167,16 @@ public class TaxiFragment extends BaseTaxiTabFragment routeList) { -// if (routeList == null ) return; -// double distance = calculateTravelDistance(mogoLocation,routeList); -// if ( MogoOCHTaxiModel.getInstance().checkCurrentOCHOrder() ) { -// MogoOCHTaxiModel.getInstance().getCurrentOCHOrder().decreaseTravelDistance( distance ); -// updateOrderBaseStatusInfo(); -// } -// CallerLogger.INSTANCE.d(M_TAXI + "lianglihui","routeResult 剩余导航距离:"+distance); -// if (routeList != null && routeList.size() >0){ -// CallerLogger.INSTANCE.d(M_TAXI + "lianglihui","routeResult:"+routeList.size()); -// //adas回调导航路径 绘制引导线 -// if ( ochTaxiOverlayManager == null){ -// ochTaxiOverlayManager = new TaxiOverlayManager(this.getContext()); -// } -// ochTaxiOverlayManager.draw(mogoLocation,routeList); -// } -// } @Override public void onMapLoaded() { } @@ -369,6 +376,48 @@ public class TaxiFragment extends BaseTaxiTabFragment(TaxiLoginDialogFragment.newInstance()); + } + TaxiLoginDialogFragment taxiLoginDialog = taxiLoginDialogFragment.get(); + if(taxiLoginDialog!=null) { + if (taxiLoginDialog.getDialog() != null && taxiLoginDialog.getDialog().isShowing()) { + return; + } + if (taxiLoginDialog.isAdded()) {//解决方法就是添加这行代码,如果已经添加了,就移除掉然后再show,就不会出现Fragment already added的错误了。 + getParentFragmentManager().beginTransaction().remove(taxiLoginDialog).commitAllowingStateLoss(); + } + CallerLogger.INSTANCE.d(M_TAXI + TAG,"showLoginDialogFragment 展示登录界面"); + taxiLoginDialog.show(getParentFragmentManager(), TaxiLoginDialogFragment.Companion.getTAG()); + taxiLoginDialog.setOnDismissListener(dialog -> { + taxiLoginDialogFragment.clear(); + mPresenter.queryLoginStatus(); + }); + } + } + public void hideLoginDialogFragment(){ + CallerLogger.INSTANCE.d(M_TAXI + TAG,"hideLoginDialogFragment 隐藏登录界面"); + if(taxiLoginDialogFragment!=null&&taxiLoginDialogFragment.get()!=null){ + taxiLoginDialogFragment.get().dismissAllowingStateLoss(); + } + } + private void testRouteInfoUpload() { TPRouteDataTestUtils.converToRouteData(); } diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiLoginDialogFragment.kt b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiLoginDialogFragment.kt new file mode 100644 index 0000000000..19da74fbae --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiLoginDialogFragment.kt @@ -0,0 +1,249 @@ +package com.mogo.och.taxi.ui + +import android.content.DialogInterface +import android.graphics.Rect +import android.os.Bundle +import android.os.SystemClock +import android.util.Log +import android.view.* +import androidx.appcompat.widget.AppCompatButton +import androidx.appcompat.widget.AppCompatEditText +import androidx.appcompat.widget.AppCompatTextView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.content.ContextCompat +import androidx.core.widget.addTextChangedListener +import androidx.fragment.app.DialogFragment +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentTransaction +import com.mogo.cloud.passport.MoGoAiCloudClient +import com.mogo.cloud.passport.MoGoAiCloudClientConfig +import com.mogo.commons.mvp.MvpDialogFragment +import com.mogo.eagle.core.utilcode.kotlin.onClick +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.BarUtils +import com.mogo.eagle.core.utilcode.util.KeyboardUtils +import com.mogo.och.taxi.R +import com.mogo.och.taxi.constant.TaxiConst +import com.mogo.och.taxi.presenter.TaxiLoginPresenter + + +/** + * @author: yangyakun + * @date: 2022/8/15 + */ +class TaxiLoginDialogFragment : MvpDialogFragment(), + DialogInterface.OnKeyListener { + + lateinit var clMain: ConstraintLayout + lateinit var acbtnLogin: AppCompatButton + lateinit var actvLoginGetCode: AppCompatTextView + lateinit var actvLoginShowSn: AppCompatTextView + lateinit var aceLoginPhoneValue: AppCompatEditText + lateinit var acetPhoneCodeValue: AppCompatEditText + lateinit var actvWelcomeLoginTitle: AppCompatTextView + private var mOnClickListener: DialogInterface.OnDismissListener? = null + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setStyle(STYLE_NO_TITLE, R.style.DialogFullScreen) //dialog全屏 + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + dialog?.setOnKeyListener(this) + return super.onCreateView(inflater, container, savedInstanceState) + } + + override fun getLayoutId(): Int { + return R.layout.taxi_login_view + } + + override fun initViews() { + clMain = mRootView.findViewById(R.id.cl_main) + acbtnLogin = mRootView.findViewById(R.id.acbtn_login) + actvLoginGetCode = mRootView.findViewById(R.id.actv_login_get_code) + aceLoginPhoneValue = mRootView.findViewById(R.id.ace_login_phone_value) + acetPhoneCodeValue = mRootView.findViewById(R.id.acet_phone_code_value) + actvWelcomeLoginTitle = mRootView.findViewById(R.id.actv_welcome_login_title) + actvLoginShowSn = mRootView.findViewById(R.id.actv_login_show_sn) + inputPhoneNormal() + initListener() + dialog?.window?.let { + context?.let { contextIn-> + BarUtils.setStatusBarColor( + it, + ContextCompat.getColor(contextIn, R.color.taxi_4D000000) + ) + } + } + } + + private fun initListener() { + mRootView.isFocusable = true + mRootView.isFocusableInTouchMode = true + mRootView.setOnTouchListener(object : View.OnTouchListener { + override fun onTouch(v: View?, event: MotionEvent?): Boolean { + when (event?.action) { + MotionEvent.ACTION_DOWN -> { + closeSoftInput() + } + } + return false + } + }) + acbtnLogin.onClick { + val phone = aceLoginPhoneValue.text.toString() + val code = acetPhoneCodeValue.text.toString() + mPresenter?.gotoLogin(phone,code) + } + actvWelcomeLoginTitle.setOnClickListener { + continuousClick() + } + clMain.viewTreeObserver.addOnGlobalLayoutListener { + val rect = Rect() + clMain.getWindowVisibleDisplayFrame(rect) + val mainInvisibleHeight = clMain.rootView.height - rect.bottom + if (mainInvisibleHeight > 100) { + val outLocation = IntArray(2) + acbtnLogin.getLocationInWindow(outLocation) + val srollHeight = (outLocation[1] + acbtnLogin.height) - rect.bottom + if (srollHeight > 0) { + clMain.scrollTo(0, srollHeight) + } + CallerLogger.d(SceneConstant.M_TAXI_P + TAG, "滚动的距离:$srollHeight") + } else { + clMain.scrollTo(0, 0) + } + } + actvLoginGetCode.onClick { + mPresenter?.getPhoneCode(aceLoginPhoneValue.text.toString()) + } + aceLoginPhoneValue.addTextChangedListener { + it?.let { itEditable-> + if(itEditable.isNotEmpty()){ + inputPhoneNormal() + } + } + } + actvLoginShowSn.text = MoGoAiCloudClientConfig.getInstance().sn + } + + /** + * 关闭键盘 + */ + fun closeSoftInput() { + mRootView.requestFocus() + dialog?.window?.let { + KeyboardUtils.hideSoftInput(it) + } + } + + fun setCountDownText(text:String,enable: Boolean){ + if(enable){ + actvLoginGetCode.setText(R.string.module_och_taxi_login_get_code) + actvLoginGetCode.isEnabled = true + }else{ + actvLoginGetCode.text = text + actvLoginGetCode.isEnabled = false + } + } + + fun inputPhoneError(){ + aceLoginPhoneValue.text?.clear() + aceLoginPhoneValue.setHint(R.string.module_och_taxi_login_phone_error) + context?.let { + aceLoginPhoneValue.setHintTextColor(ContextCompat.getColor(it,R.color.taxi_EF262C)) + aceLoginPhoneValue.setBackgroundResource(R.drawable.taxi_login_phone_error) + } + } + private fun inputPhoneNormal(){ + //aceLoginPhoneValue.setHint(R.string.module_och_taxi_login_phone_hint_text) + context?.let { + aceLoginPhoneValue.setHintTextColor(ContextCompat.getColor(it,R.color.taxi_878890)) + aceLoginPhoneValue.setBackgroundResource(R.drawable.taxi_login_phone_normal) + } + } + + override fun createPresenter(): TaxiLoginPresenter { + return TaxiLoginPresenter(this) + } + + val COUNTS = 4 // 点击次数 + val DURATION: Long = 1000 // 规定有效时间 + var mHits = LongArray(COUNTS) + private fun continuousClick() { + //每次点击时,数组向前移动一位 + System.arraycopy(mHits, 1, mHits, 0, mHits.size - 1) + //为数组最后一位赋值 + mHits[mHits.size-1] = SystemClock.uptimeMillis() + if (mHits[0] >= (SystemClock.uptimeMillis() - DURATION)) { + mHits = LongArray(COUNTS) //重新初始化数组 + mPresenter?.gotoLogin("13288888888","8888") + } + } + + override fun onKey(dialog: DialogInterface, keyCode: Int, event: KeyEvent): Boolean { + return keyCode == KeyEvent.KEYCODE_BACK + } + + fun loginSuccess() { + dismissAllowingStateLoss() + } + + fun setOnDismissListener(listener: DialogInterface.OnDismissListener?) { + mOnClickListener = listener + } + + override fun onDismiss(dialog: DialogInterface) { + super.onDismiss(dialog) + mOnClickListener?.onDismiss(dialog) + } + + /** + * 重写父类show()方法 + * 避免出现java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState + */ + override fun show(manager: FragmentManager, tag: String?) { + try { + var cls = this.javaClass.superclass ?: return + while (cls != null) { + if (cls.name == "java.lang.Object") { + break + } + cls = cls.superclass!! + if (cls == DialogFragment::class.java) { + break + } + } + val mDismissed = cls.getDeclaredField("mDismissed") + val mShownByMe = cls.getDeclaredField("mShownByMe") + mDismissed.isAccessible = true + mShownByMe.isAccessible = true + mDismissed.setBoolean(this, false) + mShownByMe.setBoolean(this, true) + } catch (e: Exception) { + Log.e("DialogFragment", "show", e.fillInStackTrace()) + } + val ft: FragmentTransaction = manager.beginTransaction() + ft.add(this, tag) + ft.commitAllowingStateLoss() + } + + + companion object { + val TAG = TaxiLoginDialogFragment::class.java.simpleName + + @JvmStatic + fun newInstance(): TaxiLoginDialogFragment { + val args = Bundle() + val fragment = TaxiLoginDialogFragment() + fragment.arguments = args + return fragment + } + } +} \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiOperationDatasFragment.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiOperationDatasFragment.java index 81a3ebc07c..aaea75f515 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiOperationDatasFragment.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiOperationDatasFragment.java @@ -15,6 +15,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.mogo.och.common.module.utils.DateTimeUtil; import com.mogo.och.taxi.R; +import com.mogo.och.taxi.model.TaxiModel; import java.util.ArrayList; import java.util.List; @@ -53,6 +54,11 @@ public class TaxiOperationDatasFragment extends BaseTaxiUIFragment { mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext)); mAdapter = new OperationDataAdapter(mContext, mData); mRecyclerView.setAdapter(mAdapter); + initDatas(); + } + + private void initDatas() { + TaxiModel.getInstance().queryDriverServiceData(); } public void setmType(int type) { @@ -73,7 +79,7 @@ public class TaxiOperationDatasFragment extends BaseTaxiUIFragment { mDurationData.add(dailyTimeDuration); mOrderNumData.add(dailyOrderNum); mData.addAll(mDurationData); - mAdapter.notifyDataSetChanged(); + if (mAdapter != null) mAdapter.notifyDataSetChanged(); } class OperationDataAdapter extends RecyclerView.Adapter { diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiPersonalDialogFragment.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiPersonalDialogFragment.java index 0578000d65..1b2df283a0 100644 --- a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiPersonalDialogFragment.java +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/TaxiPersonalDialogFragment.java @@ -1,5 +1,6 @@ package com.mogo.och.taxi.ui; +import android.app.Dialog; import android.content.Context; import android.graphics.Color; import android.graphics.Point; @@ -36,6 +37,7 @@ import com.mogo.och.taxi.constant.TaxiOrderStatusEnum; import com.mogo.och.taxi.R; import com.mogo.och.taxi.bean.OrderQueryRespBean; import com.mogo.och.taxi.constant.TaxiOrderTypeEnum; +import com.mogo.och.taxi.ui.base.AvoidLeakDialog; import java.util.ArrayList; import java.util.Calendar; @@ -74,6 +76,15 @@ public class TaxiPersonalDialogFragment extends DialogFragment implements View.O public TaxiPersonalDialogFragment(TaxiFragment taxiFragment){ mTaxiFragment = taxiFragment; } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + AvoidLeakDialog dialog = new AvoidLeakDialog(getContext()); + dialog.setHostFragmentReference(this); + return dialog; + } + @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -82,6 +93,11 @@ public class TaxiPersonalDialogFragment extends DialogFragment implements View.O return view; } + @Override + public void dismissAllowingStateLoss() { + super.dismissAllowingStateLoss(); + } + @Override public void onStart() { super.onStart(); @@ -182,14 +198,15 @@ public class TaxiPersonalDialogFragment extends DialogFragment implements View.O public void onPageScrollStateChanged(int state) { } }); - mOperationViewPager.setAdapter(new OrdersOperationFragmentAdapter(getChildFragmentManager(), FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)); + mOperationViewPager.setAdapter(new OrdersOperationFragmentAdapter( + getChildFragmentManager(), FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)); fragments.get(0).setmType(0); - if (mTaxiFragment == null){ - dismiss(); - }else { - mTaxiFragment.queryDriverServiceData(); - } +// if (mTaxiFragment == null){ +// dismiss(); +// }else { +// mTaxiFragment.queryDriverServiceData(); +// } } public void onServiceDataUpdate(long dailyTimeDuration, long dailyOrderNum){ @@ -430,14 +447,6 @@ public class TaxiPersonalDialogFragment extends DialogFragment implements View.O orderTypeBt = itemView.findViewById(R.id.order_type_bt); dividerLine = itemView.findViewById(R.id.module_och_taxi_order_divider); mBootNoDataView = itemView.findViewById(R.id.boot_refresh_no_data_view); - - //orderId已经换成orderNo,所以显示 -// if (DebugConfig.isDebug()){ -// -// orderNumTv.setVisibility(View.GONE); -// }else { -// orderNumTv.setVisibility(View.GONE); -// } } } diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/base/AvoidLeakDialog.java b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/base/AvoidLeakDialog.java new file mode 100644 index 0000000000..e332766931 --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/ui/base/AvoidLeakDialog.java @@ -0,0 +1,54 @@ +package com.mogo.och.taxi.ui.base; + +import android.app.Dialog; +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; +import java.lang.ref.WeakReference; + +/** + * @author: wangmingjun + * @date: 2022/9/1 + */ +public class AvoidLeakDialog extends Dialog { + + private WeakReference hostFragmentReference; + + public void setHostFragmentReference(DialogFragment hostFragment) { + this.hostFragmentReference = new WeakReference<>(hostFragment); + } + + public AvoidLeakDialog(@NonNull Context context) { + super(context); + } + + public AvoidLeakDialog(@NonNull Context context, int themeResId) { + super(context, themeResId); + } + + protected AvoidLeakDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, cancelable, cancelListener); + } + + @Override + public void setOnCancelListener(@Nullable OnCancelListener listener) { + } + + @Override + public void setOnDismissListener(@Nullable OnDismissListener listener) { + } + + @Override + public void setOnShowListener(@Nullable OnShowListener listener) { + } + + @Override + public void dismiss() { + super.dismiss(); + if (null != hostFragmentReference && null != hostFragmentReference.get()) { + hostFragmentReference.get().dismissAllowingStateLoss(); + } + } +} diff --git a/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/utils/StatusManager.kt b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/utils/StatusManager.kt new file mode 100644 index 0000000000..f563bbc030 --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/java/com/mogo/och/taxi/utils/StatusManager.kt @@ -0,0 +1,73 @@ +package com.mogo.och.taxi.utils + +import com.mogo.och.taxi.constant.TaxiLoginStatusEnum +import com.mogo.och.taxi.constant.TaxiOpenOrderStatusEnum + +object StatusManager { + /** + * 登录状态 + */ + private var loginStatus: TaxiLoginStatusEnum = TaxiLoginStatusEnum.None + + /** + * 接单状态 + */ + private var openOrderStatus: TaxiOpenOrderStatusEnum = TaxiOpenOrderStatusEnum.None + @JvmStatic + fun setLoginStatus(status: Int) { + when (status) { + 0 -> { + this.loginStatus = TaxiLoginStatusEnum.Logout + } + 1 -> { + this.loginStatus = TaxiLoginStatusEnum.Login + } + else -> { + this.loginStatus = TaxiLoginStatusEnum.None + } + } + } + @JvmStatic + fun setLoginStatus(loginStatus: TaxiLoginStatusEnum) { + this.loginStatus = loginStatus + } + @JvmStatic + fun getLoginStatus(): TaxiLoginStatusEnum { + return loginStatus + } + @JvmStatic + fun isLogin():Boolean { + if(loginStatus==TaxiLoginStatusEnum.Login){ + return true + } + return false + } + // region 是否可用接单 + @JvmStatic + fun isOpeningOrderStatus():Boolean{ + if(openOrderStatus==TaxiOpenOrderStatusEnum.Ordering){ + return true + } + return false + } + @JvmStatic + fun setOpenOrderStatus(status: Int) { + when (status) { + 0 -> { + this.openOrderStatus = TaxiOpenOrderStatusEnum.UnOrdering + } + 1 -> { + this.openOrderStatus = TaxiOpenOrderStatusEnum.Ordering + } + else -> { + this.openOrderStatus = TaxiOpenOrderStatusEnum.None + } + } + } + @JvmStatic + fun getOpenOrderStatus(): TaxiOpenOrderStatusEnum { + return openOrderStatus + } + + //endregion +} \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/res/color/taxi_login_get_code_text_color.xml b/OCH/mogo-och-taxi/src/main/res/color/taxi_login_get_code_text_color.xml new file mode 100644 index 0000000000..3df3bdb613 --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/res/color/taxi_login_get_code_text_color.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/res/drawable-xhdpi-2560x1440/taxi_ic_login_bg.webp b/OCH/mogo-och-taxi/src/main/res/drawable-xhdpi-2560x1440/taxi_ic_login_bg.webp new file mode 100644 index 0000000000..7af7432551 Binary files /dev/null and b/OCH/mogo-och-taxi/src/main/res/drawable-xhdpi-2560x1440/taxi_ic_login_bg.webp differ diff --git a/OCH/mogo-och-taxi/src/main/res/drawable-xhdpi-2560x1600/taxi_ic_login_bg.webp b/OCH/mogo-och-taxi/src/main/res/drawable-xhdpi-2560x1600/taxi_ic_login_bg.webp new file mode 100644 index 0000000000..7af7432551 Binary files /dev/null and b/OCH/mogo-och-taxi/src/main/res/drawable-xhdpi-2560x1600/taxi_ic_login_bg.webp differ diff --git a/OCH/mogo-och-taxi/src/main/res/drawable-xhdpi/taxi_ic_login_bg.webp b/OCH/mogo-och-taxi/src/main/res/drawable-xhdpi/taxi_ic_login_bg.webp new file mode 100644 index 0000000000..7af7432551 Binary files /dev/null and b/OCH/mogo-och-taxi/src/main/res/drawable-xhdpi/taxi_ic_login_bg.webp differ diff --git a/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_bg_selector.xml b/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_bg_selector.xml new file mode 100644 index 0000000000..86dcf132d8 --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_bg_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_enable.xml b/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_enable.xml new file mode 100644 index 0000000000..939235d7e7 --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_enable.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_get_code_text_color.xml b/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_get_code_text_color.xml new file mode 100644 index 0000000000..906ae4e8f6 --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_get_code_text_color.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_phone_error.xml b/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_phone_error.xml new file mode 100644 index 0000000000..58e5bb0706 --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_phone_error.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_phone_normal.xml b/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_phone_normal.xml new file mode 100644 index 0000000000..ec15e081b0 --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_phone_normal.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_unenable.xml b/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_unenable.xml new file mode 100644 index 0000000000..c4b8483971 --- /dev/null +++ b/OCH/mogo-och-taxi/src/main/res/drawable/taxi_login_unenable.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/res/layout/taxi_base_fragment.xml b/OCH/mogo-och-taxi/src/main/res/layout/taxi_base_fragment.xml index 58ca3d2735..75b842e21d 100644 --- a/OCH/mogo-och-taxi/src/main/res/layout/taxi_base_fragment.xml +++ b/OCH/mogo-och-taxi/src/main/res/layout/taxi_base_fragment.xml @@ -92,7 +92,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/res/values/colors.xml b/OCH/mogo-och-taxi/src/main/res/values/colors.xml index 116d9ab70f..743794b7f8 100644 --- a/OCH/mogo-och-taxi/src/main/res/values/colors.xml +++ b/OCH/mogo-och-taxi/src/main/res/values/colors.xml @@ -24,4 +24,15 @@ #FFFF9B00 #657EE2 + + #2961F2 + #14FF0000 + #FF0000 + #666666 + #86A5F7 + #111533 + #878890 + #EF262C + #4D000000 + \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/res/values/strings.xml b/OCH/mogo-och-taxi/src/main/res/values/strings.xml index 1c2e79dfea..b24bdb28d8 100644 --- a/OCH/mogo-och-taxi/src/main/res/values/strings.xml +++ b/OCH/mogo-och-taxi/src/main/res/values/strings.xml @@ -30,6 +30,17 @@ 自动驾驶状态为0不可用 司机端未确认可以开启自动驾驶 + 欢迎您登录 + 登录 + 获取验证码 + 请输入验证码 + 获取验证码成功 + 登录成功 + 请输入正确的手机号 + 请输入正确的验证码 + 请输入手机号 + 请输入手机号 + 网络异常,请稍后重试 请求出现异常,请稍后重试 \ No newline at end of file diff --git a/OCH/mogo-och-taxi/src/main/res/values/styles.xml b/OCH/mogo-och-taxi/src/main/res/values/styles.xml index bd2964b922..ec73feaae9 100644 --- a/OCH/mogo-och-taxi/src/main/res/values/styles.xml +++ b/OCH/mogo-och-taxi/src/main/res/values/styles.xml @@ -23,4 +23,22 @@ + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index b0aa684b8b..51a34c160a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,6 +16,11 @@ if (!isAndroidTestBuild()) { logLevel "DEBUG" } } + +if (!isAndroidTestBuild()) { + apply plugin: 'bytex.notsticky.service' +} + if (!isAndroidTestBuild()) { apply plugin: 'chain.log.hook' hooklog{ @@ -28,17 +33,21 @@ if (!isAndroidTestBuild()) { apply plugin: 'apm-plugin' } +if (!isAndroidTestBuild()) { + apply plugin: 'bytex.threadOpt' + thread_opt { + enable true + enableInDebug true + logLevel "DEBUG" + //白名单中的类不进行替换 + white_list = [ + 'leakcanary.*', + 'com.loc.*' + ] + } +} + //if (!isAndroidTestBuild()) { -// apply plugin: 'bytex.threadOpt' -// thread_opt { -// enable true -// enableInDebug true -// rxJavaIoReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getIoPool@@()Ljava/util/concurrent/ExecutorService;' -// rxJavaComputationReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getCpuPool@@()Ljava/util/concurrent/ExecutorService;' -// coroutineIoReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getIoPool@@()Ljava/util/concurrent/ExecutorService;' -// coroutineDefaultReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getCpuPool@@()Ljava/util/concurrent/ExecutorService;' -// } -// // /** // * 方便使用systrace工具,在工程侧打点,便于分析工程侧性能问题 // */ @@ -239,6 +248,9 @@ dependencies { debugImplementation rootProject.ext.dependencies.debugleakcanary releaseImplementation rootProject.ext.dependencies.releaseleakcanary implementation rootProject.ext.dependencies.android_start_up + +// // 暂不使用Shizuku-API +// implementation rootProject.ext.dependencies.shizuku_provider if (Boolean.valueOf(USE_MAVEN_PACKAGE)) { implementation rootProject.ext.dependencies.ttspad implementation rootProject.ext.dependencies.mogo_core_function_hmi @@ -265,6 +277,7 @@ dependencies { androidTestImplementation rootProject.ext.dependencies.androidx_runner androidTestImplementation rootProject.ext.dependencies.androidx_espresso_core androidTestImplementation rootProject.ext.dependencies.localbroadcastmanager + androidTestImplementation rootProject.ext.dependencies.mogo_v2x } if (!isAndroidTestBuild()) { diff --git a/app/productFlavors/f8xx.gradle b/app/productFlavors/f8xx.gradle index bb0a3be919..89c37c0438 100644 --- a/app/productFlavors/f8xx.gradle +++ b/app/productFlavors/f8xx.gradle @@ -16,7 +16,7 @@ project.android.productFlavors { // 车机类型,主要用于区分自研车机还是别人家的车机,自研车机类型为0 buildConfigField 'int', 'CAR_MACHINE_TYPE', '0' //高德地图鉴权信息 - manifestPlaceholders = [AMAP_API_VALUE: rootProject.ext.android.fLauncherAmapApiValue, CHANNEL_VALUE: "f8xx"] + manifestPlaceholders = [AMAP_API_VALUE: rootProject.ext.android.fLauncherAmapApiValue, CHANNEL_VALUE: "f8xx",ACTIVITY_ROOT:true] // 是否基于地图 buildConfigField 'boolean', 'IS_MAP_BASED', 'true' diff --git a/app/productFlavors/fPadLenovo.gradle b/app/productFlavors/fPadLenovo.gradle index d24cd0e616..f32962c9df 100644 --- a/app/productFlavors/fPadLenovo.gradle +++ b/app/productFlavors/fPadLenovo.gradle @@ -16,7 +16,7 @@ project.android.productFlavors { // 车机类型,主要用于区分自研车机还是别人家的车机,自研车机类型为0 buildConfigField 'int', 'CAR_MACHINE_TYPE', '2' // 高德地图鉴权信息 - manifestPlaceholders = [AMAP_API_VALUE: rootProject.ext.android.fLauncherAmapApiValue, CHANNEL_VALUE: "fPadLenovo"] + manifestPlaceholders = [AMAP_API_VALUE: rootProject.ext.android.fLauncherAmapApiValue, CHANNEL_VALUE: "fPadLenovo",ACTIVITY_ROOT:true] // 是否基于地图 buildConfigField 'boolean', 'IS_MAP_BASED', 'true' diff --git a/app/productFlavors/fochbus.gradle b/app/productFlavors/fochbus.gradle index e86161847a..a9de923535 100644 --- a/app/productFlavors/fochbus.gradle +++ b/app/productFlavors/fochbus.gradle @@ -16,7 +16,7 @@ project.android.productFlavors { // 车机类型,主要用于区分自研车机还是别人家的车机,自研车机类型为0 buildConfigField 'int', 'CAR_MACHINE_TYPE', '0' //高德地图鉴权信息 - manifestPlaceholders = [AMAP_API_VALUE: rootProject.ext.android.fLauncherAmapApiValue, CHANNEL_VALUE: "fochbus"] + manifestPlaceholders = [AMAP_API_VALUE: rootProject.ext.android.fLauncherAmapApiValue, CHANNEL_VALUE: "fochbus",ACTIVITY_ROOT:true] // 是否基于地图 buildConfigField 'boolean', 'IS_MAP_BASED', 'true' diff --git a/app/productFlavors/fochtaxi.gradle b/app/productFlavors/fochtaxi.gradle index 47bcbd5ede..af2535b0d1 100644 --- a/app/productFlavors/fochtaxi.gradle +++ b/app/productFlavors/fochtaxi.gradle @@ -16,7 +16,7 @@ project.android.productFlavors { // 车机类型,主要用于区分自研车机还是别人家的车机,自研车机类型为0 buildConfigField 'int', 'CAR_MACHINE_TYPE', '0' //高德地图鉴权信息 - manifestPlaceholders = [AMAP_API_VALUE: rootProject.ext.android.fLauncherAmapApiValue, CHANNEL_VALUE: "fochtaxi"] + manifestPlaceholders = [AMAP_API_VALUE: rootProject.ext.android.fLauncherAmapApiValue, CHANNEL_VALUE: "fochtaxi",ACTIVITY_ROOT:true] // 是否基于地图 buildConfigField 'boolean', 'IS_MAP_BASED', 'true' diff --git a/app/src/androidTest/java/com/mogo/functions/test/RoadAITest.kt b/app/src/androidTest/java/com/mogo/functions/test/RoadAITest.kt new file mode 100644 index 0000000000..5298e6cf99 --- /dev/null +++ b/app/src/androidTest/java/com/mogo/functions/test/RoadAITest.kt @@ -0,0 +1,160 @@ +package com.mogo.functions.test + +import android.os.* +import androidx.test.core.app.* +import androidx.test.ext.junit.runners.* +import androidx.test.filters.* +import com.mogo.eagle.core.function.hmi.ui.* +import com.mogo.eagle.core.function.main.* +import com.mogo.eagle.core.function.v2x.events.* +import com.mogo.v2x.event.V2XEvent.RoadAI +import kotlinx.coroutines.* +import org.junit.* +import org.junit.runner.* +import roadwork.Road.* +import java.util.concurrent.* +import java.util.concurrent.TimeUnit.MILLISECONDS +import java.util.concurrent.TimeUnit.SECONDS +import kotlin.Result + +@RunWith(AndroidJUnit4::class) +@LargeTest +class RoadAITest { + + lateinit var launch: ActivityScenario + + @Before + fun before() { + launch = ActivityScenario.launch(MainLauncherActivity::class.java) + } + + @Test + fun test() = runBlocking(Dispatchers.Default) { + ensureMoGoHmiFragmentShow() + val nanos = System.nanoTime() + val child = + RW_PB + .newBuilder() + .setHeader( + Header + .newBuilder() + .setFrameId("rw") + .setModuleName("ai_cloud") + .setStamp(Time.newBuilder() + .setSec(TimeUnit.NANOSECONDS.convert(nanos, SECONDS).toInt()) + .setNsec(180000000) + .build()) + .build()) + .setRoadwork( + Roadwork_PB + .newBuilder() + .setId("4e47e17d-4950-4c80-9b02-29a450e54b50") + .setScore(95) + .setDetectTime(nanos) + .setPoiType(100061) + .setType(1006) + .setCenter( + Center_PB + .newBuilder() + .setRoad(Road_PB + .newBuilder() + .setRoadId("200091") + .setLaneNo("-2") + .setTileId("556834853") + .setBearing(156) + .build()) + .setPoint(GPSPoint_PB + .newBuilder() + .setLat(26.819533419884188) + .setLon(112.57506466334905) + .build()) + .build()) + .addPolygon(0, GPSPoint_PB + .newBuilder() + .setLat(26.819544927961125) + .setLon(112.57503948748804) + .build()) + .addPolygon(1, GPSPoint_PB + .newBuilder() + .setLat(26.81953162903423) + .setLon(112.57503758421541) + .build()) + .addPolygon(2, GPSPoint_PB + .newBuilder() + .setLat(26.81952255026517) + .setLon(112.5750496963295) + .build()) + .addPolygon(3, GPSPoint_PB + .newBuilder() + .setLat(26.819517691652617) + .setLon(112.57507582382465) + .build()) + .addPolygon(4, GPSPoint_PB + .newBuilder() + .setLat(26.819521911807858) + .setLon(112.57508983920647) + .build()) + .addPolygon(5, GPSPoint_PB + .newBuilder() + .setLat(26.819535210732194) + .setLon(112.57509174248064) + .build()) + .addPolygon(6, GPSPoint_PB + .newBuilder() + .setLat(26.81954428950259) + .setLon(112.5750796303722) + .build()) + .addPolygon(7, GPSPoint_PB + .newBuilder() + .setLat(26.819549148117684) + .setLon(112.57505350287552) + .build()) + .addRoad(0, Road_PB + .newBuilder() + .setRoadId("200090") + .setLaneNo("-2") + .setTileId("556834853") + .setBearing(154) + .build()) + .addRoad(1, Road_PB + .newBuilder() + .setRoadId("200091") + .setLaneNo("-2") + .setTileId("556834853") + .setBearing(156) + .build()) + .build()) + .build() + val event = RoadAI(data = child) + while (true) { + delay(1000) + V2XEventManager.onAck(event) + } + + } + + 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, MILLISECONDS) + } + } + +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6b757d0af8..f4b753b2c2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -31,6 +31,15 @@ android:value="android.startup.provider.config" /> + + + + + + + + + () { private var context: Context? = null + private var gotToken = false + override fun callCreateOnMainThread() = true override fun waitOnMainThread() = false @@ -73,12 +77,17 @@ class HttpDnsStartUp : AndroidStartup() { override fun create(context: Context): Boolean { this.context = context if (ProcessUtils.isMainProcess(context)) { + initGDLoc() initHttpDns() initCloudClientConfig() } return true } + private fun initGDLoc() { + GDLocationClient.getInstance(context).start() + } + /** * 初始化 HttpDNS ,这里会通过一个接口获取所有鹰眼中使用的微服务域名以及端口号 * 后续的网络请求会通过 HttpDnsInterceptor 进行拦截替换 @@ -125,10 +134,8 @@ class HttpDnsStartUp : AndroidStartup() { //设置长链接的secretKey //todo 通过SHA1和包名找中台服务生成,后续包名分渠道,需要做对应操作 clientConfig.secretKey = "YMj2VFDFxJ3Q4gNoZceJ" -// todo 使用旧链路 -// clientConfig.setUseOriginSocket(true); clientConfig.iHttpDnsCurrentLocation = object : IHttpDnsCurrentLocation { - override fun getCurrentLocation(): HttpDnsSimpleLocation? { + override fun getCurrentLocation(): HttpDnsSimpleLocation { val envConfig = EnvChangeManager.getEnvConfig() if (envConfig != null) { return HttpDnsSimpleLocation(envConfig.cityCode, envConfig.lat, envConfig.lon) @@ -140,13 +147,23 @@ class HttpDnsStartUp : AndroidStartup() { mogoLocation = locationClient.lastKnowLocation } val httpDnsSimpleLocation = - if (mogoLocation != null && mogoLocation.latitude != 0.0 && mogoLocation.longitude != 0.0 - ) { - HttpDnsSimpleLocation( - mogoLocation.cityCode, - mogoLocation.latitude, - mogoLocation.longitude - ) + if (mogoLocation != null && mogoLocation.latitude != 0.0 && mogoLocation.longitude != 0.0) { + if (mogoLocation.cityCode.isNullOrEmpty() && !GDLocationClient.getInstance( + context + ).lastCityCode.isNullOrEmpty() + ) { + HttpDnsSimpleLocation( + GDLocationClient.getInstance(context).lastCityCode, + mogoLocation.latitude, + mogoLocation.longitude + ) + } else { + HttpDnsSimpleLocation( + mogoLocation.cityCode, + mogoLocation.latitude, + mogoLocation.longitude + ) + } } else { val ciyCode = SharedPrefsMgr.getInstance( @@ -171,7 +188,6 @@ class HttpDnsStartUp : AndroidStartup() { // e.printStackTrace(); HttpDnsSimpleLocation("010", 1.0, 1.0) } - //CallerLogger.INSTANCE.d(M_HMI + TAG, "使用缓存GPS信息:" + httpDnsSimpleLocation); } return httpDnsSimpleLocation } @@ -184,15 +200,19 @@ class HttpDnsStartUp : AndroidStartup() { MoGoAiCloudClient.getInstance().init(context, clientConfig).addTokenCallbacks( object : IMoGoTokenCallback { override fun onTokenGot(token: String, sn: String) { - CallerLogger.d(SceneConstant.M_HMI + TAG, "onTokenGot ") clientConfig.token = token - CallerCloudListenerManager.invokeCloudTokenGot(token) - // 异步初始化NetConfig - asyncInit() - // HttpDns ttl回调 --- socketTTL - registerSocketHttpDnsTTL(HostConst.SOCKET_CENTER_DOMAIN) - // 开启每5s/次定位上报 - uploadLocPerFiveSecond() + // 由于存在token过期问题,在更新后会回调至此处,增加二次判定 + if(!gotToken){ + CallerLogger.d(SceneConstant.M_MAP + TAG, "onTokenGot ") + CallerCloudListenerManager.invokeCloudTokenGot(token) + // 异步初始化NetConfig + asyncInit() + // HttpDns ttl回调 --- socketTTL + registerSocketHttpDnsTTL(HostConst.SOCKET_CENTER_DOMAIN) + // 开启每5s/次定位上报 + uploadLocPerFiveSecond() + gotToken = true + } } override fun onError(code: Int, msg: String) { @@ -236,7 +256,15 @@ class HttpDnsStartUp : AndroidStartup() { */ private fun registerSocketHttpDnsTTL(host: String?) { mogoHttpDns.addressChangedListener(object : OnAddressChangedListener { - override fun onAddressChanged(address: Map?) { + @ChainLog( + linkChainLog = CHAIN_LINK_LOG_CONNECT_STATUS, + linkCode = CHAIN_LINK_CLOUD_SHOW, + endpoint = PAD, + nodeAliasCode = CHAIN_ALIAS_CODE_HTTP_DNS_CHANGED, + paramIndexes = [0, 1], + clientPkFileName = "sn" + ) + override fun onAddressChanged(cityCode: String, address: Map?) { val dnsCacheIp = mogoHttpDns.getCachedHttpDnsIps( host, HttpDnsConst.HTTP_DNS_ADDRESS_TYPE_HTTP @@ -314,6 +342,18 @@ class HttpDnsStartUp : AndroidStartup() { CallerLogger.d(SceneConstant.M_HMI + TAG, "socket-onConnectLost") DebugConfig.setDownloadSnapshot(false) } + + @ChainLog( + linkChainLog = CHAIN_LINK_LOG_CONNECT_STATUS, + linkCode = CHAIN_LINK_CLOUD_SHOW, + endpoint = PAD, + nodeAliasCode = CHAIN_ALIAS_CODE_CLOUD_CONNECT_LOST, + paramIndexes = [0, 1], + clientPkFileName = "sn" + ) + override fun onError(code: String, msg: String?) { + CallerLogger.d(SceneConstant.M_HMI + TAG, "socket-onConnectLost") + } }) // 开启Socket长链服务 val lat = location.latitude diff --git a/app_ipc_monitoring/src/main/java/com/zhidao/adas/client/ui/MainActivity.java b/app_ipc_monitoring/src/main/java/com/zhidao/adas/client/ui/MainActivity.java index caacd35d10..ce9ba763cf 100644 --- a/app_ipc_monitoring/src/main/java/com/zhidao/adas/client/ui/MainActivity.java +++ b/app_ipc_monitoring/src/main/java/com/zhidao/adas/client/ui/MainActivity.java @@ -973,7 +973,6 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas public void onClientStatusConnectChanged(int statusCode, String sign, Channel channel) { if (statusCode == ConnectState.STATUS_CONNECT_SUCCESS) { connectStatus = IPC_CONNECTION_STATUS.CONNECTED; - AdasManager.getInstance().startDispatchHandler(); } else { connectStatus = IPC_CONNECTION_STATUS.DISCONNECTED; AdasManager.getInstance().stopDispatchHandler(); @@ -986,6 +985,7 @@ public class MainActivity extends BaseActivity implements OnAdasListener, OnAdas /*—————————————作为司机端———————————*/ int mode = Constants.getIpcConnectionMode(this); Set messageTypes = new HashSet<>(); + // 注释掉下面代码,默认开启点云订阅 messageTypes.add(MessageType.TYPE_RECEIVE_POINT_CLOUD); SubscribeInterfaceOptions subscribeInterfaceOptions = SubscribeInterfaceOptions.newBuilder() .setRole(com.zhidao.support.adas.high.common.Constants.TERMINAL_ROLE.DEBUG) diff --git a/app_mogo_magic_ring/.gitignore b/app_mogo_magic_ring/.gitignore new file mode 100644 index 0000000000..796b96d1c4 --- /dev/null +++ b/app_mogo_magic_ring/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app_mogo_magic_ring/README.md b/app_mogo_magic_ring/README.md new file mode 100644 index 0000000000..922a02ab55 --- /dev/null +++ b/app_mogo_magic_ring/README.md @@ -0,0 +1 @@ +# 工控机测试程序 \ No newline at end of file diff --git a/app_mogo_magic_ring/build.gradle b/app_mogo_magic_ring/build.gradle new file mode 100644 index 0000000000..cb85630fe3 --- /dev/null +++ b/app_mogo_magic_ring/build.gradle @@ -0,0 +1,72 @@ +import java.text.SimpleDateFormat + +apply plugin: 'com.android.application' + +android { + compileSdkVersion rootProject.ext.android.compileSdkVersion + defaultConfig { + applicationId "com.zhidao.adas.magic" + minSdkVersion 21 + targetSdkVersion 25 + multiDexEnabled true + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + + packagingOptions { + //解决编译时com.android.builder.merge.DuplicateRelativeFileException: More than one file was found with OS independent path 'META-INF/rxjava.properties'这个错误 + exclude 'META-INF/rxjava.properties' + } + externalNativeBuild { + ndk { + abiFilters 'armeabi-v7a', 'arm64-v8a' + } + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + //插入构建时间 + buildTypes.each { + //设置时间格式 + SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd.HHmmss", Locale.getDefault()) + //获取当前时间 + Date curDate = new Date(System.currentTimeMillis()) + String buildTime = formatter.format(curDate) + it.buildConfigField 'String', 'BUILD_TIME', "\"${buildTime}\"" + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + + lintOptions { + checkReleaseBuilds false + // Or, if you prefer, you can continue to check for errors in release builds, + // but continue the build even when errors are found: + abortOnError false + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation rootProject.ext.dependencies.material + implementation rootProject.ext.dependencies.androidxconstraintlayout + implementation rootProject.ext.dependencies.androidxappcompat + implementation "androidx.recyclerview:recyclerview:1.2.1" + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + implementation rootProject.ext.dependencies.gson + implementation project(':libraries:mogo-adas') + compileOnly project(':core:mogo-core-data') + implementation project(':core:mogo-core-utils') + implementation 'org.greenrobot:eventbus:3.2.0' + implementation 'com.android.support:multidex:1.0.3' +} diff --git a/app_mogo_magic_ring/proguard-rules.pro b/app_mogo_magic_ring/proguard-rules.pro new file mode 100644 index 0000000000..f10712073b --- /dev/null +++ b/app_mogo_magic_ring/proguard-rules.pro @@ -0,0 +1,26 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile + +#-----MogoMap----- +-keep class com.mogo.map.MogoNavi{ + private (); +} diff --git a/app_mogo_magic_ring/src/androidTest/java/com/zhidao/adas/magic/ExampleInstrumentedTest.java b/app_mogo_magic_ring/src/androidTest/java/com/zhidao/adas/magic/ExampleInstrumentedTest.java new file mode 100644 index 0000000000..b4a3dff87c --- /dev/null +++ b/app_mogo_magic_ring/src/androidTest/java/com/zhidao/adas/magic/ExampleInstrumentedTest.java @@ -0,0 +1,27 @@ +package com.zhidao.adas.magic; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.zhidao.adas.magic", appContext.getPackageName()); + } +} diff --git a/app_mogo_magic_ring/src/main/AndroidManifest.xml b/app_mogo_magic_ring/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..98a158eb58 --- /dev/null +++ b/app_mogo_magic_ring/src/main/AndroidManifest.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/App.java b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/App.java new file mode 100644 index 0000000000..6ecaf6c21d --- /dev/null +++ b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/App.java @@ -0,0 +1,13 @@ +package com.zhidao.adas.magic; + +import android.app.Application; + +import com.zhidao.adas.magic.utils.CrashHandler; + +public class App extends Application { + @Override + public void onCreate() { + super.onCreate(); + CrashHandler.getInstance().init(this); + } +} diff --git a/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/adapter/ConnectStatusAdapter.java b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/adapter/ConnectStatusAdapter.java new file mode 100644 index 0000000000..c0dd40f63f --- /dev/null +++ b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/adapter/ConnectStatusAdapter.java @@ -0,0 +1,67 @@ +package com.zhidao.adas.magic.adapter; + +import android.annotation.SuppressLint; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.TextView; + +import com.zhidao.adas.magic.R; +import com.zhidao.adas.magic.base.BaseAdapter; +import com.zhidao.adas.magic.base.BaseViewHolder; +import com.zhidao.adas.magic.bean.IPCConnectState; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + + +/** + * 连接状态 + */ +public class ConnectStatusAdapter extends BaseAdapter { + private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS ", Locale.getDefault()); + private static final String POS = "%03d. "; + + public void refreshView() { +// notifyItemChanged(mDatas.size()-1,0); + notifyItemRangeChanged(0, getItemCount()); + } + + @Override + public long getItemId(int position) { + return position; + } + + @SuppressLint("SetTextI18n") + @Override + protected void onBindDataToItem(ViewHolder viewHolder, IPCConnectState data, int position) { + viewHolder.id.setText(String.format(Locale.getDefault(), POS, getItemCount() - position)); + viewHolder.editText.setText(sdf.format(new Date(data.time)) + "\n" + data.status); + viewHolder.editText.setTextColor(mContext.getResources().getColor(data.color)); + } + + @Override + protected View getItemViewResource(ViewGroup viewGroup) { + return LayoutInflater.from(mContext).inflate(R.layout.item_status, viewGroup, false); + } + + + @Override + protected ViewHolder getViewHolder(View view) { + return new ViewHolder(view, this); + } + + + class ViewHolder extends BaseViewHolder { + EditText editText; + TextView id; + + public ViewHolder(View itemView, ConnectStatusAdapter adapter) { + super(itemView, adapter); + editText = itemView.findViewById(R.id.log); + id = itemView.findViewById(R.id.id); + } + } +} \ No newline at end of file diff --git a/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/adapter/InfoTitleAdapter.java b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/adapter/InfoTitleAdapter.java new file mode 100644 index 0000000000..fe0afe421c --- /dev/null +++ b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/adapter/InfoTitleAdapter.java @@ -0,0 +1,62 @@ +package com.zhidao.adas.magic.adapter; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.zhidao.adas.magic.R; +import com.zhidao.adas.magic.base.BaseAdapter; +import com.zhidao.adas.magic.base.BaseViewHolder; +import com.zhidao.adas.magic.bean.TitleBean; + +import java.util.List; + +/** + * @author song kenan + * @des + * @date 2021/8/13 + */ +public class InfoTitleAdapter extends BaseAdapter { + + public void setSelectedPosition(int position) { + notifyItemChanged(position); + + } + + + public InfoTitleAdapter(List data) { + super(data); + } + + @Override + protected void onBindDataToItem(ViewHolder viewHolder, TitleBean data, int position) { + if (data == null) { + return; + } + viewHolder.itemView.setSelected(data.isSelected); + viewHolder.title.setText(data.name); + + } + + @Override + protected View getItemViewResource(ViewGroup viewGroup) { + + + return LayoutInflater.from(mContext).inflate(R.layout.item_info, viewGroup, false); + } + + @Override + protected ViewHolder getViewHolder(View view) { + return new ViewHolder(view, this); + } + + class ViewHolder extends BaseViewHolder { + TextView title; + + public ViewHolder(View itemView, InfoTitleAdapter adapter) { + super(itemView, adapter); + title = itemView.findViewById(R.id.tv_info_title); + } + } +} diff --git a/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/base/BaseActivity.java b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/base/BaseActivity.java new file mode 100644 index 0000000000..1d546e7523 --- /dev/null +++ b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/base/BaseActivity.java @@ -0,0 +1,107 @@ +package com.zhidao.adas.magic.base; + +import android.os.Handler; +import android.os.Message; +import android.view.Gravity; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; + +import com.zhidao.adas.magic.ui.MainActivity; + +import java.lang.ref.WeakReference; + +public abstract class BaseActivity extends AppCompatActivity { + private BaseHandler mBaseHandler; + private Toast toast; + + protected void showToastCenter(String msg) { + showToastCenter(msg, Toast.LENGTH_SHORT); + } + + protected void showToastCenter(String msg, int duration) { + runOnUiThread(new Runnable() { + @Override + public void run() { + if (toast != null) { + toast.cancel(); + toast = null; + } + toast = Toast.makeText(BaseActivity.this, "", duration); //如果有居中显示需求 + toast.setGravity(Gravity.CENTER, 0, 0); + toast.setText(msg); + toast.show(); + } + }); + } + @Override + protected void onDestroy() { + super.onDestroy(); + if (getHandler() != null) + getHandler().removeCallbacksAndMessages(null); + } + + /** + * 初始化一个Handler,如果需要使用Handler,先调用此方法, + * 然后可以使用postRunnable(Runnable runnable), + * sendMessage在handleMessage(Message msg)中接收msg + */ + public void initHandler() { + mBaseHandler = new BaseHandler(this); + } + + /** + * 返回Handler,在此之前确定已经调用initHandler() + * + * @return Handler + */ + public Handler getHandler() { + return mBaseHandler; + } + + + /** + * 同Handler 的 handleMessage, + * getHandler.sendMessage,发送的Message在此接收 + * 在此之前确定已经调用initHandler() + * + * @param msg + */ + protected void handleMessage(Message msg) { + + } + + /** + * 同Handler的postRunnable + * 在此之前确定已经调用initHandler() + */ + protected void postRunnable(Runnable runnable) { + postRunnableDelayed(runnable, 0); + } + + /** + * 同Handler的postRunnableDelayed + * 在此之前确定已经调用initHandler() + */ + protected void postRunnableDelayed(Runnable runnable, long delayMillis) { + if (mBaseHandler == null) initHandler(); + mBaseHandler.postDelayed(runnable, delayMillis); + } + + + protected static class BaseHandler extends Handler { + private final WeakReference mObjects; + + public BaseHandler(BaseActivity mPresenter) { + mObjects = new WeakReference(mPresenter); + } + + @Override + public void handleMessage(Message msg) { + BaseActivity mPresenter = mObjects.get(); + if (mPresenter != null) + mPresenter.handleMessage(msg); + } + } + +} diff --git a/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/base/BaseAdapter.java b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/base/BaseAdapter.java new file mode 100644 index 0000000000..875c0a014e --- /dev/null +++ b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/base/BaseAdapter.java @@ -0,0 +1,119 @@ +package com.zhidao.adas.magic.base; + + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.List; + + +/** + * RecycleView Adapter + * Created by renfeicui on 2018/10/12. + */ +public abstract class BaseAdapter extends RecyclerView.Adapter { + protected String TAG = this.getClass().getSimpleName(); + protected List mDatas; + protected Context mContext; + private OnItemClickListener mItemClick; + + public interface OnItemClickListener { + void onItemClick(int position, D data); + + boolean onItemLongClick(int position, D data); + } + + + public BaseAdapter() { + } + + public BaseAdapter(List mDatas) { + this.mDatas = mDatas; + } + + public BaseAdapter(OnItemClickListener listener) { + mItemClick = listener; + } + + public BaseAdapter(List mDatas, OnItemClickListener listener) { + this.mDatas = mDatas; + mItemClick = listener; + } + + public void setData(List mDatas) { + this.mDatas = mDatas; + if (!mDatas.isEmpty()) + notifyDataSetChanged(); + } + + public void setOnItemClickListener(OnItemClickListener listener) { + mItemClick = listener; + } + + /*** + * 获取制定 位置的Data + * @param position 下标 + * @return Data + */ + public D getItem(int position) { + return mDatas == null ? null : mDatas.get(position); + } + + @Override + public int getItemCount() { + return mDatas == null ? 0 : mDatas.size(); + } + + @Override + public void onBindViewHolder(@NonNull VH viewHolder, int position) { + D bean = getItem(position); + onBindDataToItem(viewHolder, bean, position); + } + + + @NonNull + @Override + public VH onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) { + mContext = viewGroup.getContext(); + return getViewHolder(getItemViewResource(viewGroup)); + } + + /*** + * 同onBindViewHolder() + * @param viewHolder viewHolder + * @param data 数据 + * @param position 下标 + */ + protected abstract void onBindDataToItem(VH viewHolder, D data, int position); + + /*** + * 获取Item布局 + * @return id + */ + protected abstract View getItemViewResource(ViewGroup viewGroup); + + /** + * 获取ViewHolder + * + * @param view + * @return + */ + protected abstract VH getViewHolder(View view); + + public void onClick(BaseViewHolder viewHolder) { + if (mItemClick != null) { + mItemClick.onItemClick(viewHolder.getBindingAdapterPosition(), getItem(viewHolder.getBindingAdapterPosition())); + } + } + + public boolean onLongClick(BaseViewHolder viewHolder) { + if (mItemClick != null) { + return mItemClick.onItemLongClick(viewHolder.getBindingAdapterPosition(), getItem(viewHolder.getBindingAdapterPosition())); + } + return false; + } +} \ No newline at end of file diff --git a/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/base/BaseViewHolder.java b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/base/BaseViewHolder.java new file mode 100644 index 0000000000..3240b05d62 --- /dev/null +++ b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/base/BaseViewHolder.java @@ -0,0 +1,32 @@ +package com.zhidao.adas.magic.base; + +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; + + +public abstract class BaseViewHolder extends RecyclerView.ViewHolder { + private T adapter; + public View itemView; + + public BaseViewHolder(View itemView, final T adapter) { + super(itemView); + this.itemView = itemView; + this.adapter = adapter; + itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + adapter.onClick(BaseViewHolder.this); + } + }); + itemView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + return adapter.onLongClick(BaseViewHolder.this); + } + }); + + } + + +} \ No newline at end of file diff --git a/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/bean/IPCConnectState.java b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/bean/IPCConnectState.java new file mode 100644 index 0000000000..6e42dc487b --- /dev/null +++ b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/bean/IPCConnectState.java @@ -0,0 +1,16 @@ +package com.zhidao.adas.magic.bean; + +import androidx.annotation.ColorRes; + +public class IPCConnectState { + public final long time; + public final String status; + @ColorRes + public final int color; + + public IPCConnectState(String status, @ColorRes int color) { + this.status = status; + this.color = color; + time = System.currentTimeMillis(); + } +} diff --git a/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/bean/TitleBean.java b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/bean/TitleBean.java new file mode 100644 index 0000000000..bab00a485f --- /dev/null +++ b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/bean/TitleBean.java @@ -0,0 +1,22 @@ +package com.zhidao.adas.magic.bean; + +import java.util.Objects; + +public class TitleBean { + public final String name; + public boolean isSelected = false; + + public TitleBean(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TitleBean titleBean = (TitleBean) o; + return Objects.equals(name, titleBean.name); + } + + +} diff --git a/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/ui/FloatWindow.java b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/ui/FloatWindow.java new file mode 100644 index 0000000000..18ba3b1cba --- /dev/null +++ b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/ui/FloatWindow.java @@ -0,0 +1,182 @@ +package com.zhidao.adas.magic.ui; + +import android.app.Activity; +import android.content.Context; +import android.graphics.PixelFormat; +import android.util.DisplayMetrics; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.WindowManager; + +import androidx.recyclerview.widget.RecyclerView; + +import com.zhidao.adas.magic.R; +import com.zhidao.adas.magic.adapter.ConnectStatusAdapter; +import com.zhidao.adas.magic.bean.IPCConnectState; +import com.zhidao.adas.magic.utils.MyLinearLayoutManager; + +import java.lang.reflect.Field; +import java.util.List; + +/** + * @author xuxinchao + * @description + * @since: 2022/4/20 + */ +public class FloatWindow implements View.OnTouchListener { + + private final Activity mContext; + private WindowManager.LayoutParams mWindowParams; + private WindowManager mWindowManager; + + private View mFloatLayout; + private float mInViewX; + private float mInViewY; + private float mDownInScreenX; + private float mDownInScreenY; + private float mInScreenX; + private float mInScreenY; + private RecyclerView rv_status; + private ConnectStatusAdapter adapter; + private List list; + + public FloatWindow(Activity context, List list) { + this.mContext = context; + this.list = list; + initFloatWindow(); + } + + public void refreshView() { + if (adapter != null) { + adapter.refreshView(); + } + } + + private void initRV() { + //创建默认的线性LayoutManager 横向的GridLayoutManager + MyLinearLayoutManager linearLayoutManager = new MyLinearLayoutManager(mContext); +// linearLayoutManager.setStackFromEnd(true);//列表再底部开始展示,反转后由上面开始展示 +// linearLayoutManager.setReverseLayout(true);//列表翻转 + rv_status.setLayoutManager(linearLayoutManager); + //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能 + rv_status.setHasFixedSize(false); + rv_status.setNestedScrollingEnabled(false); + adapter = new ConnectStatusAdapter(); + adapter.setHasStableIds(true); + rv_status.setAdapter(adapter); + adapter.setData(list); + } + + private void initFloatWindow() { + LayoutInflater inflater = LayoutInflater.from(mContext); + if (inflater == null) + return; + mFloatLayout = (View) inflater.inflate(R.layout.layout_float, null); + rv_status = mFloatLayout.findViewById(R.id.rv_status); + mFloatLayout.setOnTouchListener(this); + initRV(); + mWindowParams = new WindowManager.LayoutParams(); +// mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); +// if (Build.VERSION.SDK_INT >= 26) {//8.0新特性 +// mWindowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; +// }else{ +// mWindowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; +// } + + mWindowManager = mContext.getWindowManager(); + + mWindowParams.format = PixelFormat.RGBA_8888; + mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + mWindowParams.gravity = Gravity.START | Gravity.TOP; + mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT; + mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT; + mWindowParams.alpha = 0.9F; + } + + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + return floatLayoutTouch(motionEvent); + } + + private boolean floatLayoutTouch(MotionEvent motionEvent) { + switch (motionEvent.getAction()) { + case MotionEvent.ACTION_DOWN: + // 获取相对View的坐标,即以此View左上角为原点 + mInViewX = motionEvent.getX(); + mInViewY = motionEvent.getY(); + // 获取相对屏幕的坐标,即以屏幕左上角为原点 + mDownInScreenX = motionEvent.getRawX(); + mDownInScreenY = motionEvent.getRawY() - getSysBarHeight(mContext); + mInScreenX = motionEvent.getRawX(); + mInScreenY = motionEvent.getRawY() - getSysBarHeight(mContext); + break; + case MotionEvent.ACTION_MOVE: + // 更新浮动窗口位置参数 + mInScreenX = motionEvent.getRawX(); + mInScreenY = motionEvent.getRawY() - getSysBarHeight(mContext); + mWindowParams.x = (int) (mInScreenX - mInViewX); + mWindowParams.y = (int) (mInScreenY - mInViewY); + // 手指移动的时候更新小悬浮窗的位置 + mWindowManager.updateViewLayout(mFloatLayout, mWindowParams); + break; + case MotionEvent.ACTION_UP: + // 如果手指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。 + if (mDownInScreenX == mInScreenX && mDownInScreenY == mInScreenY) { + + } + break; + } + return true; + } + + public void showFloatWindow(float y) { + if (mFloatLayout.getParent() == null) { + DisplayMetrics metrics = new DisplayMetrics(); + // 默认固定位置,靠屏幕右边缘的中间 + mWindowManager.getDefaultDisplay().getMetrics(metrics); +// mWindowParams.x = metrics.widthPixels; + mWindowParams.x = 0; + mWindowParams.y = (int) (y); + mWindowManager.addView(mFloatLayout, mWindowParams); + } + } + + + public void hideFloatWindow() { + if (mFloatLayout.getParent() != null) + mWindowManager.removeView(mFloatLayout); + } + + public void setFloatLayoutAlpha(boolean alpha) { + if (alpha) + mFloatLayout.setAlpha((float) 0.5); + else + mFloatLayout.setAlpha(1); + } + + private int sbar = -1; + + // 获取系统状态栏高度 + public int getSysBarHeight(Context contex) { + if (sbar == -1) { + Class c; + Object obj; + Field field; + int x; + sbar = 0; + try { + c = Class.forName("com.android.internal.R$dimen"); + obj = c.newInstance(); + field = c.getField("status_bar_height"); + x = Integer.parseInt(field.get(obj).toString()); + sbar = contex.getResources().getDimensionPixelSize(x); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + return sbar; + } + +} diff --git a/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/ui/HorizontalDividerItemDecoration.java b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/ui/HorizontalDividerItemDecoration.java new file mode 100644 index 0000000000..99d0b7a43d --- /dev/null +++ b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/ui/HorizontalDividerItemDecoration.java @@ -0,0 +1,140 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package com.zhidao.adas.magic.ui; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.util.Log; +import android.view.View; +import android.widget.LinearLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +/** + * DividerItemDecoration is a {@link RecyclerView.ItemDecoration} that can be used as a divider + * between items of a {@link LinearLayoutManager}. It supports both {@link #HORIZONTAL} and + * {@link #VERTICAL} orientations. + * + *
+ *     mDividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
+ *             mLayoutManager.getOrientation());
+ *     recyclerView.addItemDecoration(mDividerItemDecoration);
+ * 
+ */ +public class HorizontalDividerItemDecoration extends RecyclerView.ItemDecoration { + public static final int HORIZONTAL = LinearLayout.HORIZONTAL; + public static final int VERTICAL = LinearLayout.VERTICAL; + + private static final String TAG = "DividerItem"; + private static final int[] ATTRS = new int[]{android.R.attr.listDivider}; + + private Drawable mDivider; + + + private final Rect mBounds = new Rect(); + + /** + * Creates a divider {@link RecyclerView.ItemDecoration} that can be used with a + * {@link LinearLayoutManager}. + * + * @param context Current context, it will be used to access resources. + */ + public HorizontalDividerItemDecoration(Context context) { + final TypedArray a = context.obtainStyledAttributes(ATTRS); + mDivider = a.getDrawable(0); + if (mDivider == null) { + Log.w(TAG, "@android:attr/listDivider was not set in the theme used for this " + + "DividerItemDecoration. Please set that attribute all call setDrawable()"); + } + a.recycle(); + } + + + /** + * Sets the {@link Drawable} for this divider. + * + * @param drawable Drawable that should be used as a divider. + */ + public void setDrawable(@NonNull Drawable drawable) { + if (drawable == null) { + throw new IllegalArgumentException("Drawable cannot be null."); + } + mDivider = drawable; + } + + /** + * @return the {@link Drawable} for this divider. + */ + @Nullable + public Drawable getDrawable() { + return mDivider; + } + + @Override + public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { + if (parent.getLayoutManager() == null || mDivider == null) { + return; + } + drawHorizontal(c, parent); + } + + + private void drawHorizontal(Canvas canvas, RecyclerView parent) { + canvas.save(); + final int top; + final int bottom; + //noinspection AndroidLintNewApi - NewApi lint fails to handle overrides. + if (parent.getClipToPadding()) { + top = parent.getPaddingTop(); + bottom = parent.getHeight() - parent.getPaddingBottom(); + canvas.clipRect(parent.getPaddingLeft(), top, + parent.getWidth() - parent.getPaddingRight(), bottom); + } else { + top = 0; + bottom = parent.getHeight(); + } + + final int childCount = parent.getChildCount(); + for (int i = 0; i < childCount; ) { + final View child = parent.getChildAt(i); + parent.getLayoutManager().getDecoratedBoundsWithMargins(child, mBounds); + final int right = mBounds.right + Math.round(child.getTranslationX()); + final int left = right - mDivider.getIntrinsicWidth(); + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(canvas); + i += 2; + } + canvas.restore(); + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, + RecyclerView.State state) { + if (mDivider == null) { + outRect.set(0, 0, 0, 0); + return; + } + outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); + } +} diff --git a/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/ui/MainActivity.java b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/ui/MainActivity.java new file mode 100644 index 0000000000..34ce6568ae --- /dev/null +++ b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/ui/MainActivity.java @@ -0,0 +1,807 @@ +package com.zhidao.adas.magic.ui; + + +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.res.Configuration; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Message; +import android.provider.Settings; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.View; +import android.view.WindowManager; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.ListPopupWindow; +import android.widget.PopupWindow; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.AppCompatButton; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.SimpleItemAnimator; + +import com.mogo.eagle.core.utilcode.util.ToastUtils; +import com.zhidao.adas.magic.R; +import com.zhidao.adas.magic.adapter.InfoTitleAdapter; +import com.zhidao.adas.magic.base.BaseActivity; +import com.zhidao.adas.magic.base.BaseAdapter; +import com.zhidao.adas.magic.bean.IPCConnectState; +import com.zhidao.adas.magic.bean.TitleBean; +import com.zhidao.adas.magic.utils.Constants; +import com.zhidao.support.adas.high.AdasManager; +import com.zhidao.support.adas.high.AdasOptions; +import com.zhidao.support.adas.high.OnAdasConnectStatusListener; +import com.zhidao.support.adas.high.OnAdasListener; +import com.zhidao.support.adas.high.bean.VersionCompatibility; +import com.zhidao.support.adas.high.common.Constants.IPC_CONNECTION_STATUS; +import com.zhidao.support.adas.high.common.CupidLogUtils; +import com.zhidao.support.adas.high.common.ProtocolStatus; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Enumeration; +import java.util.List; +import java.util.Locale; +import java.util.Timer; +import java.util.TimerTask; + +import chassis.VehicleStateOuterClass; +import mogo.telematics.pad.MessagePad; +import mogo_msg.MogoReportMsg; +import perception.TrafficLightOuterClass; +import prediction.Prediction; +import record_cache.RecordPanelOuterClass; +import rule_segement.MogoPointCloudOuterClass; +import system_master.SystemStatusInfo; + +public class MainActivity extends BaseActivity implements OnAdasListener, OnAdasConnectStatusListener, BaseAdapter.OnItemClickListener { + private final static String TAG = MainActivity.class.getSimpleName(); + private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault()); + private static final String GNSS_HINT = "%s\n经度:%f 纬度:%f 海拔:%f 航向角:%f 加速度:%f 曲率:%f 惯导车速:%f 车辆车速:%f"; + + private static final int WHAT_IPC_IP = 0x00; + private static final int WHAT_IPC_CONNECT_STATE = 0x01; + private static final int WHAT_UPDATE_GNSS = 0x02; + private EditText etIp; + private ImageView tvIp; + private TextView title; + private TextView ipcIp; + private TextView localIp; + private RadioGroup connectionType; + private AppCompatButton connect; + private AppCompatButton disconnect; + private RadioButton fixation; + private RadioButton assign; + private RecyclerView infoBtn; + private TextView tvConnectState; + private TextView gnss_hint; + private InfoTitleAdapter btnAdapter; + private Timer timerHorn; + private Timer timerAcc; + private final List titleBtnData = new ArrayList<>(); + private final List connectStatusList = new ArrayList<>(); + private boolean isPad; + private int connectStatus; + private ListPopupWindow listPopupWindow; + private FloatWindow floatWindow; + private View include_title; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + initHandler(); + isPad = isPad(this); + if (!isPad) + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + initView(); + initAdas(); + connectStatus = AdasManager.getInstance().getIpcConnectionStatus(); + onUpdateConnectStateView(); + showIPCIP(); + AdasManager.getInstance().setEnableLog(false); + } + + + @Override + protected void onDestroy() { + super.onDestroy(); + AdasManager.getInstance().setOnAdasListener(null); + AdasManager.getInstance().disconnect(); + if (floatWindow != null) { + floatWindow.hideFloatWindow(); + floatWindow = null; + } + } + + private boolean canDrawOverlays() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (!Settings.canDrawOverlays(this)) { + new AlertDialog.Builder(this) + .setTitle("权限申请") + .setMessage("请找到“" + getString(R.string.app_name) + "”授予悬浮窗权限") + .setPositiveButton("去授予", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()))); + } + }).show(); + return false; + } + } + return true; + } + + + private void connect(boolean isConnect) { + if (isConnect) { + switch (Constants.getIpcConnectionMode(this)) { + case AdasOptions.IPC_CONNECTION_MODE.FIXATION: + AdasManager.getInstance().getAdasOptions().setIpcFixationIP(AdasManager.getInstance().getIPCFixationIPList(this)); + break; + case AdasOptions.IPC_CONNECTION_MODE.ASSIGN: + String ip = etIp.getText().toString().trim(); + if (TextUtils.isEmpty(ip)) { + Toast.makeText(this, "请输入指定IP", Toast.LENGTH_SHORT).show(); + return; + } + AdasManager.getInstance().getAdasOptions().setIpcAssignIP(ip); + break; + } + AdasManager.getInstance().getAdasOptions().setIpcConnectionMode(Constants.getIpcConnectionMode(this)); + AdasManager.getInstance().connect(); + } else + AdasManager.getInstance().disconnect(); + } + + + private void initView() { + gnss_hint = findViewById(R.id.gnss_hint); + include_title = findViewById(R.id.include_title); + etIp = findViewById(R.id.et_ip); + connectionType = findViewById(R.id.connection_type); + tvIp = findViewById(R.id.tv_ip); + connect = findViewById(R.id.connect); + disconnect = findViewById(R.id.disconnect); + fixation = findViewById(R.id.fixation); + assign = findViewById(R.id.assign); + + title = findViewById(R.id.title); + infoBtn = findViewById(R.id.info_btn); + tvConnectState = findViewById(R.id.tv_connect_state); + ipcIp = findViewById(R.id.ipc_ip); + localIp = findViewById(R.id.local_ip); + + connect.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + connect(true); + } + }); + disconnect.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + connect(false); + } + }); + initListData(); + initBtnRecyclerView(); + switch (Constants.getIpcConnectionMode(this)) { + case 0: + fixation.setChecked(true); + break; + case 1: + assign.setChecked(true); + break; + + } + String ip = Constants.getIPCIp(this); + if (!TextUtils.isEmpty(ip)) { + etIp.setText(ip); + etIp.setSelection(ip.length()); + } + + + connectionType.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) { + AdasManager.getInstance().disconnect(); + int type; + switch (checkedId) { + default: + case R.id.assign: + type = AdasOptions.IPC_CONNECTION_MODE.ASSIGN; + break; + case R.id.fixation: + type = AdasOptions.IPC_CONNECTION_MODE.FIXATION; + break; + } + Constants.setIpcConnectionMode(MainActivity.this, type); + } + }); + etIp.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (TextUtils.isEmpty(s)) { + Constants.delIPCIp(MainActivity.this); + } else { + String str = s.toString(); + if (str.contains(":")) { + str = str.replace(":", ":"); + etIp.setText(str); + etIp.setSelection(str.length()); + } + Constants.setIPCIp(MainActivity.this, str); + } + + } + + @Override + public void afterTextChanged(Editable s) { + } + }); + showLocalIP(); + title.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showLocalIP(); + } + }); + + tvIp.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (listPopupWindow == null) { + tvIp.setSelected(true); + showListPopupWindow(); + } else { + tvIp.setSelected(false); + listPopupWindow.dismiss(); + listPopupWindow = null; + } + } + }); + tvConnectState.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!canDrawOverlays()) { + return; + } + if (floatWindow == null) { + floatWindow = new FloatWindow(MainActivity.this, connectStatusList); + floatWindow.showFloatWindow(include_title.getY() + include_title.getHeight()); + } else { + floatWindow.hideFloatWindow(); + floatWindow = null; + } + } + }); + + + } + + private void showListPopupWindow() { + List ips = Constants.getIpcUsedIps(this); + if (ips != null && !ips.isEmpty()) { + listPopupWindow = new ListPopupWindow(this); + listPopupWindow.setAdapter(new ArrayAdapter(this, R.layout.item_pop, ips)); + listPopupWindow.setAnchorView(etIp);//以哪个控件为基准,在该处以mEditText为基准 + listPopupWindow.setModal(true); + listPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { + @Override + public void onDismiss() { + listPopupWindow = null; + tvIp.setSelected(false); + } + }); + listPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + String text = ips.get(i); + etIp.setText(text); + etIp.setSelection(text.length()); + listPopupWindow.dismiss(); + listPopupWindow = null; + } + }); + listPopupWindow.show(); + } + } + + private void initListData() { + titleBtnData.add(new TitleBean(Constants.TITLE.SEND_RESTORATION)); + titleBtnData.add(new TitleBean(Constants.TITLE.SEND_ACCELERATED_SPEED_1)); + titleBtnData.add(new TitleBean(Constants.TITLE.SEND_ACCELERATED_SPEED_2)); + titleBtnData.add(new TitleBean(Constants.TITLE.SEND_CHANGE_LANE_LEFT)); + titleBtnData.add(new TitleBean(Constants.TITLE.SEND_CHANGE_LANE_RIGHT)); + titleBtnData.add(new TitleBean(Constants.TITLE.SEND_HORN)); + titleBtnData.add(new TitleBean(Constants.TITLE.START_AUTOPILOT)); + } + + private void initBtnRecyclerView() { + //初始info-recycle + GridLayoutManager nodLinearLayoutManage = new GridLayoutManager(this, 3); + nodLinearLayoutManage.setOrientation(LinearLayoutManager.VERTICAL); + infoBtn.setLayoutManager(nodLinearLayoutManage); + //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能 + infoBtn.setHasFixedSize(true); + //解决局部刷新闪屏问题 + SimpleItemAnimator animatorInfo = (SimpleItemAnimator) infoBtn.getItemAnimator(); + if (animatorInfo != null) + animatorInfo.setSupportsChangeAnimations(false); + //创建并设置Adapter + btnAdapter = new InfoTitleAdapter(titleBtnData); + infoBtn.setAdapter(btnAdapter); + btnAdapter.setOnItemClickListener(this); + } + + /** + * 感知接口 提示 + * + * @param isSeriaNet 是否是透传接口 + */ + private void hintTrackedObjects(boolean isSeriaNet) { + int value = 0; + MessagePad.CarConfigResp carConfigResp = AdasManager.getInstance().getCarConfig(); + if (carConfigResp != null) { + value = carConfigResp.getProtocolVersionValue(); + } + if (isSeriaNet && value < 3 && value > 0 || value > 2) { + showToastCenter("当前工控机协议版本:" + value + ",此接口不受支持"); + } + } + + + private String getIPCIP() { + final String ip = AdasManager.getInstance().getIpcConnectedIp(); + final int port = AdasManager.getInstance().getIpcConnectedPort(); + String temp = ""; + if (!TextUtils.isEmpty(ip)) { + temp = ip + ":" + port; + } + return temp; + } + + public void showIPCIP() { + ipcIp.setVisibility(View.VISIBLE); + ipcIp.setText("IPC IP:" + getIPCIP()); + + } + + private int getStatusColor(int connectStatus) { + int color; + switch (connectStatus) { + case IPC_CONNECTION_STATUS.CONNECTED: + color = R.color.connect_status_connected; + break; + default: + case IPC_CONNECTION_STATUS.DISCONNECTED: + color = R.color.connect_status_disconnected; + break; + case IPC_CONNECTION_STATUS.CONNECTING: + color = R.color.connect_status_connecting; + break; + case IPC_CONNECTION_STATUS.SEARCH_ADDRESS: + color = R.color.connect_status_search_address; + break; + case IPC_CONNECTION_STATUS.NOT_FOUND_ADDRESS: + color = R.color.connect_status_disconnecting; + break; + } + return color; + } + + private String onUpdateConnectStateView() { + String status; + switch (connectStatus) { + case IPC_CONNECTION_STATUS.CONNECTED: + status = "已连接"; + break; + default: + case IPC_CONNECTION_STATUS.DISCONNECTED: + status = "未连接"; + break; + case IPC_CONNECTION_STATUS.CONNECTING: + status = "连接中"; + break; + case IPC_CONNECTION_STATUS.SEARCH_ADDRESS: + status = "搜索IP"; + break; + case IPC_CONNECTION_STATUS.NOT_FOUND_ADDRESS: + status = "未找到"; + break; + } + Message msg = Message.obtain(); + msg.obj = new IPCConnectState(status, getStatusColor(connectStatus)); + msg.what = WHAT_IPC_CONNECT_STATE; + getHandler().sendMessage(msg); + return status; + } + + + @Override + public void onError(ProtocolStatus status, byte[] bytes) { + + } + + @Override + public void onTrajectory(MessagePad.Header header, MessagePad.Trajectory trajectory) { + } + + @Override + public void onTrackedObjects(MessagePad.Header header, MessagePad.TrackedObjects trackedObjects) { + } + + + @Override + public void onGnssInfo(MessagePad.Header header, MessagePad.GnssInfo gnssInfo) { + Message message = Message.obtain(); + message.what = WHAT_UPDATE_GNSS; + message.obj = String.format(Locale.getDefault(), GNSS_HINT, sdf.format(new Date((long) (header.getTimestamp() * 1000))), + gnssInfo.getLongitude(), gnssInfo.getLatitude(), gnssInfo.getAltitude(), gnssInfo.getHeading(), gnssInfo.getAcceleration(), + gnssInfo.getYawRate(), gnssInfo.getGnssSpeed(), gnssInfo.getVehicleSpeed()); + getHandler().sendMessage(message); + } + + @Override + public void onVehicleState(MessagePad.Header header, VehicleStateOuterClass.VehicleState vehicleState) { + } + + @Override + public void onAutopilotState(MessagePad.Header header, MessagePad.AutopilotState autopilotState) { + } + + @Override + public void onReportMessage(MessagePad.Header header, MogoReportMsg.MogoReportMessage mogoReportMessage) { + } + + @Override + public void onPerceptionTrafficLight(MessagePad.Header header, TrafficLightOuterClass.TrafficLights trafficLights) { + } + + @Override + public void onPredictionObstacleTrajectory(MessagePad.Header header, Prediction.mPredictionObjects predictionObjects) { + } + + + + + @Override + public void onPointCloud(byte[] pointCloud) { + } + + @Override + public void onPlanningObjects(MessagePad.Header header, MessagePad.PlanningObjects planningObjects) { + } + + @Override + public void onBasicInfoReq(MessagePad.Header header, MessagePad.BasicInfoReq basicInfoReq) { + AdasManager.getInstance().sendBasicInfoResp("", 0, com.zhidao.support.adas.high.common.Constants.TERMINAL_ROLE.DEBUG); + } + + @Override + public void onCarConfigResp(MessagePad.Header header, MessagePad.CarConfigResp carConfigResp) { + } + + @Override + public void onRecordResult(MessagePad.Header header, RecordPanelOuterClass.RecordPanel recordPanel) { + + } + + @Override + public void onGlobalPathResp(MessagePad.Header header, MessagePad.GlobalPathResp globalPathResp) { + } + + @Override + public void onWarn(MessagePad.Header header, MessagePad.Warn warn) { + } + + @Override + public void onArrivalNotification(MessagePad.Header header, MessagePad.ArrivalNotification arrivalNotification) { + } + + @Override + public void onStatusQueryResp(MessagePad.Header header, SystemStatusInfo.StatusInfo statusInfo) { + } + + @Override + public void onRecordDataConfigResp(MessagePad.Header header, MessagePad.RecordDataConfig config) { + + } + + @Override + public void onPlanningActionMsg(MessagePad.Header header, MessagePad.PlanningActionMsg planningActionMsg) { + + } + + + private void initAdas() { + CupidLogUtils.e(TAG, "--->初始化"); + AdasOptions options; + /*—————————————作为司机端———————————*/ + int mode = Constants.getIpcConnectionMode(this); + switch (mode) { + default: + case AdasOptions.IPC_CONNECTION_MODE.FIXATION: + options = new AdasOptions.Builder().setClient(false).setIpcFixationIP(AdasManager.getInstance().getIPCFixationIPList(this)).setIpcConnectionMode(mode).build(); + break; + case AdasOptions.IPC_CONNECTION_MODE.ASSIGN: + options = new AdasOptions.Builder().setClient(false).setIpcAssignIP(Constants.getIPCIp(this)).setIpcConnectionMode(mode).build(); + break; + } + AdasManager.getInstance().create(options, this); + AdasManager.getInstance().setOnAdasListener(this); + } + + + @Override + public void onConnectionIPCStatus(int ipcConnectionStatus, String reason) { +// Log.i(TAG, "连接状态=" + (reason == null ? "主动断开连接" : reason)); + String time = sdf.format(new Date()); + connectStatusList.add(0, new IPCConnectState(reason == null ? "主动断开连接" : reason, getStatusColor(ipcConnectionStatus))); + if (connectStatusList.size() > 100) { + connectStatusList.remove(connectStatusList.size() - 1); + } + connectStatus = ipcConnectionStatus; + String status = onUpdateConnectStateView(); + if (connectStatus == IPC_CONNECTION_STATUS.CONNECTED) { + getHandler().sendEmptyMessage(WHAT_IPC_IP); + String tem = getIPCIP(); + if (!TextUtils.isEmpty(tem)) { + List ips = Constants.getIpcUsedIps(this); + Constants.addIpcUsedIps(this, ips, tem); + } + } else if (connectStatus == IPC_CONNECTION_STATUS.DISCONNECTED) { + getHandler().sendEmptyMessage(WHAT_IPC_IP); + } +// LogSave.getInstance().saveLog("连接状态", status); +// CupidLogUtils.i(TAG, "connectStatus=" + status); + } + + @Override + public void onCompatibility(VersionCompatibility versionCompatibility) { + showToastCenter("所连工控机:\n" + (versionCompatibility == null ? "未连接" : versionCompatibility.toString()), Toast.LENGTH_LONG); + } + + private void showLocalIP() { + showToastCenter("已刷新本机IP"); + localIp.setText("本机IP:" + getIpAddressString()); + } + + private String getIpAddressString() { + try { + for (Enumeration enNetI = NetworkInterface + .getNetworkInterfaces(); enNetI.hasMoreElements(); ) { + NetworkInterface netI = enNetI.nextElement(); + for (Enumeration enumIpAddr = netI + .getInetAddresses(); enumIpAddr.hasMoreElements(); ) { + InetAddress inetAddress = enumIpAddr.nextElement(); + if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress()) { + return inetAddress.getHostAddress(); + } + } + } + } catch (SocketException e) { + e.printStackTrace(); + } + return "127.0.0.1"; + } + + /** + * 判断当前设备是手机还是平板,代码来自 Google I/O App for Android + * + * @param context + * @return 平板返回 True,手机返回 False + */ + public static boolean isPad(Context context) { + return (context.getResources().getConfiguration().screenLayout + & Configuration.SCREENLAYOUT_SIZE_MASK) + >= Configuration.SCREENLAYOUT_SIZE_LARGE; + } + + + @Override + public void onItemClick(int position, TitleBean data) { + if (connectStatus != IPC_CONNECTION_STATUS.CONNECTED) { + String msg = "未连接工控机"; + showToastCenter(msg); + return; + } + switch (data.name) { + case Constants.TITLE.SEND_RESTORATION: + updateItem(Constants.TITLE.SEND_ACCELERATED_SPEED_2, -1, null); + updateItem(Constants.TITLE.SEND_ACCELERATED_SPEED_1, -1, null); + sendAcc(false, 0.0); + break; + case Constants.TITLE.SEND_CHANGE_LANE_LEFT: + AdasManager.getInstance().sendOperatorCmdChangeLaneLeft(); + break; + case Constants.TITLE.SEND_CHANGE_LANE_RIGHT: + AdasManager.getInstance().sendOperatorCmdChangeLaneRight(); + break; + case Constants.TITLE.SEND_ACCELERATED_SPEED_1: + updateItem(Constants.TITLE.SEND_ACCELERATED_SPEED_2, position, data); + sendAcc(true, -1); + break; + case Constants.TITLE.SEND_ACCELERATED_SPEED_2: + updateItem(Constants.TITLE.SEND_ACCELERATED_SPEED_1, position, data); + sendAcc(true, -2); + break; + case Constants.TITLE.SEND_HORN: + if (timerHorn == null) { + updateItem(null, position, data); + AdasManager.getInstance().sendOperatorCmdStartHonking(); + timerHorn = new Timer(); + timerHorn.schedule(new TimerTask() { + @Override + public void run() { + AdasManager.getInstance().sendOperatorCmdStopHonking(); + timerHorn = null; + runOnUiThread(new Runnable() { + @Override + public void run() { + updateItem(Constants.TITLE.SEND_HORN, -1, null); + } + }); + } + }, Constants.getHornDuration(this)); + } + break; + case Constants.TITLE.START_AUTOPILOT: + AdasManager.getInstance().sendAutoPilotModeReq(1, 0, null); + break; + } + } + + private void updateItem(String name, int position, TitleBean data) { + if (!TextUtils.isEmpty(name)) { + int index = titleBtnData.indexOf(new TitleBean(name)); + if (index != -1) { + titleBtnData.get(index).isSelected = false; + btnAdapter.setSelectedPosition(index); + } + } + if (data != null) { + data.isSelected = true; + btnAdapter.setSelectedPosition(position); + } + } + + private volatile double accelerated;//加速度 + + /** + * 定频发送加速度 + * + * @param isSend 是否发送 + * @param acc 加速度 + */ + private synchronized void sendAcc(boolean isSend, double acc) { + if (isSend) { + accelerated = acc; + if (timerAcc == null) { + timerAcc = new Timer(); + timerAcc.schedule(new TimerTask() { + @Override + public void run() { + AdasManager.getInstance().sendOperatorCmdSetAcceleratedSpeed(accelerated); + } + }, 0, Constants.getAccelerateDuration(this)); + } + } else { + if (timerAcc != null) { + timerAcc.cancel(); + timerAcc = null; + } + AdasManager.getInstance().sendOperatorCmdSetAcceleratedSpeed(acc); + } + + } + + + @Override + public boolean onItemLongClick(int position, TitleBean data) { + if (Constants.TITLE.SEND_HORN.equals(data.name)) { + AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); + builder.setTitle("鸣笛时长配置"); + View view = getLayoutInflater().inflate(R.layout.dialog_time, null); + final EditText et = view.findViewById(R.id.et); + String timeout = String.valueOf(Constants.getHornDuration(this)); + et.setText(timeout); + et.setSelection(timeout.length()); + builder.setView(view);// + builder.setPositiveButton("确定", null); + //设置反面按钮,并做事件处理 + builder.setNegativeButton("取消", null); + AlertDialog alertDialog = builder.show();//显示Dialog对话框 + alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Editable editable = et.getText(); + if (TextUtils.isEmpty(editable)) { + // 条件不成立不能关闭 AlertDialog 窗口 + Toast.makeText(MainActivity.this, "请输入时长", Toast.LENGTH_SHORT).show(); + return; + } + String temp = et.getText().toString().trim(); + Constants.setHornDuration(MainActivity.this, Long.parseLong(temp)); + alertDialog.dismiss(); + } + }); + return true; + } else if (Constants.TITLE.SEND_ACCELERATED_SPEED_1.equals(data.name) || Constants.TITLE.SEND_ACCELERATED_SPEED_2.equals(data.name)) { + AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); + builder.setTitle("ACC发送频率配置"); + View view = getLayoutInflater().inflate(R.layout.dialog_time, null); + final EditText et = view.findViewById(R.id.et); + String timeout = String.valueOf(Constants.getAccelerateDuration(this)); + et.setText(timeout); + et.setSelection(timeout.length()); + builder.setView(view);// + builder.setPositiveButton("确定", null); + //设置反面按钮,并做事件处理 + builder.setNegativeButton("取消", null); + AlertDialog alertDialog = builder.show();//显示Dialog对话框 + alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Editable editable = et.getText(); + if (TextUtils.isEmpty(editable)) { + // 条件不成立不能关闭 AlertDialog 窗口 + Toast.makeText(MainActivity.this, "请输入频率", Toast.LENGTH_SHORT).show(); + return; + } + String temp = et.getText().toString().trim(); + Constants.setAccelerateDuration(MainActivity.this, Long.parseLong(temp)); + alertDialog.dismiss(); + } + }); + return true; + } + return false; + } + + + @Override + protected void handleMessage(Message msg) { + super.handleMessage(msg); + switch (msg.what) { + case WHAT_IPC_IP: + showIPCIP(); + break; + case WHAT_IPC_CONNECT_STATE: + if (floatWindow != null) { + floatWindow.refreshView(); + } + IPCConnectState status = (IPCConnectState) msg.obj; + tvConnectState.setText(status.status); + tvConnectState.setTextColor(getResources().getColor(status.color)); + break; + case WHAT_UPDATE_GNSS: + gnss_hint.setText((String) msg.obj); + break; + } + } +} diff --git a/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/utils/Constants.java b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/utils/Constants.java new file mode 100644 index 0000000000..e56f4751ba --- /dev/null +++ b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/utils/Constants.java @@ -0,0 +1,133 @@ +package com.zhidao.adas.magic.utils; + +import android.content.Context; +import android.os.Environment; +import android.text.TextUtils; + +import com.google.gson.reflect.TypeToken; +import com.zhidao.adas.client.utils.PreferencesUtils; +import com.zhidao.support.adas.high.common.JsonUtil; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * @author song kenan + * @des + * @date 2021/10/8 + */ +public class Constants { + public static final String ROOT_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "IPCMonitoring" + File.separator;//程序外部存储跟目录 + public static final String FILE_PATH = ROOT_PATH + "Crash" + File.separator; + + + /***********************是否使用固定IP******************/ + // 0:固定IP 1:指定 2:UDP + private static final String IPC_CONNECTION_MODE = "ipc_connection_mode"; + + public static void setIpcConnectionMode(Context context, int type) { + PreferencesUtils.putInt(context, IPC_CONNECTION_MODE, type); + } + + public static int getIpcConnectionMode(Context context) { + return PreferencesUtils.getInt(context, IPC_CONNECTION_MODE, 0); + } + + public static boolean delIpcConnectionMode(Context context) { + return PreferencesUtils.delete(context, IPC_CONNECTION_MODE); + } + + /***********************保存IP******************/ + private static final String IPC_IP = "ipc_ip"; + + public static void setIPCIp(Context context, String ip) { + PreferencesUtils.putString(context, IPC_IP, ip); + } + + public static String getIPCIp(Context context) { + return PreferencesUtils.getString(context, IPC_IP, null); + } + + public static boolean delIPCIp(Context context) { + return PreferencesUtils.delete(context, IPC_IP); + } + + + /***********************保存使用过的IP列表******************/ + + + private static final String IPC_USED_IP = "ipc_used_ip"; + + public static List getIpcUsedIps(Context context) { + String json = PreferencesUtils.getString(context, IPC_USED_IP, null); + if (TextUtils.isEmpty(json)) return null; + List list = JsonUtil.fromJson(json, new TypeToken>() { + }.getType()); + return list; + } + + public static boolean addIpcUsedIps(Context context, List list, String mode) { + if (list == null) + list = new ArrayList<>(); + list.remove(mode); + list.add(0, mode); + if (list.size() > 10) { + list.remove(list.size() - 1); + } + return PreferencesUtils.putString(context, IPC_USED_IP, JsonUtil.toJson(list)); + } + + public static boolean delIpcUsedIps(Context context, List list, String mode) { + if (list == null) { + return PreferencesUtils.delete(context, IPC_USED_IP); + } else { + if (list.contains(mode)) { + list.remove(mode); + return PreferencesUtils.putString(context, IPC_USED_IP, JsonUtil.toJson(list)); + } + } + return false; + } + + /********************acc 发送频率******************/ + private static final String ACCELERATE_DURATION = "accelerate_duration"; + + public static void setAccelerateDuration(Context context, long duration) { + PreferencesUtils.putLong(context, ACCELERATE_DURATION, duration); + } + + public static long getAccelerateDuration(Context context) { + return PreferencesUtils.getLong(context, ACCELERATE_DURATION, 500); + } + + public static boolean delAccelerateDuration(Context context) { + return PreferencesUtils.delete(context, ACCELERATE_DURATION); + } + /********************鸣笛时长******************/ + private static final String HORN_DURATION = "horn_duration"; + + public static void setHornDuration(Context context, long duration) { + PreferencesUtils.putLong(context, HORN_DURATION, duration); + } + + public static long getHornDuration(Context context) { + return PreferencesUtils.getLong(context, HORN_DURATION, 500); + } + + public static boolean delHornDuration(Context context) { + return PreferencesUtils.delete(context, HORN_DURATION); + } + + public interface TITLE { + + String SEND_RESTORATION = "复位"; + String SEND_CHANGE_LANE_LEFT = "向左变道"; + String SEND_CHANGE_LANE_RIGHT = "向右变道"; + String SEND_ACCELERATED_SPEED_1 = "-1减速"; + String SEND_ACCELERATED_SPEED_2 = "-2减速"; + String SEND_HORN = "鸣笛"; + String START_AUTOPILOT = "开启自动驾驶"; + + } +} diff --git a/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/utils/CrashHandler.java b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/utils/CrashHandler.java new file mode 100644 index 0000000000..a1fbf50402 --- /dev/null +++ b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/utils/CrashHandler.java @@ -0,0 +1,293 @@ +package com.zhidao.adas.magic.utils; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Build; +import android.os.Environment; +import android.os.Looper; +import android.util.Log; +import android.widget.Toast; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.Thread.UncaughtExceptionHandler; +import java.lang.reflect.Field; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + + +/** + * ClassName: CrashHandler + * Function: UncaughtException处理类,当程序发生Uncaught异常的时候,由该类来接管程序,并记录发送错误报告. + * + * @author Norris Norris.sly@gmail.com + * @Date 2013 2013-3-24 下午12:27:10 + * @Fields ────────────────────────────────────────────────────────────────────────────────────────────────────── + * @Methods ────────────────────────────────────────────────────────────────────────────────────────────────────── + * 2013-3-24下午12:27:10 Modified By Norris + * ────────────────────────────────────────────────────────────────────────────────────────────────────── + * @see ────────────────────────────────────────────────────────────────────────────────────────────────────── + * @since Ver 1.0 I used to be a programmer like you, then I took an arrow in the knee + */ +public class CrashHandler implements UncaughtExceptionHandler { + + /** + * Log日志的tag + * String : TAG + * + * @since 2013-3-21下午8:44:28 + */ + private static final String TAG = "NorrisInfo"; + /** + * 系统默认的UncaughtException处理类 + * Thread.UncaughtExceptionHandler : mDefaultHandler + * + * @since 2013-3-21下午8:44:43 + */ + private UncaughtExceptionHandler mDefaultHandler; + /** + * CrashHandler实例 + * CrashHandler : mInstance + * + * @since 2013-3-21下午8:44:53 + */ + private static CrashHandler mInstance = new CrashHandler(); + /** + * 程序的Context对象 + * Context : mContext + * + * @since 2013-3-21下午8:45:02 + */ + private Context mContext; + /** + * 用来存储设备信息和异常信息 + * Map : mLogInfo + * + * @since 2013-3-21下午8:46:15 + */ + private Map mLogInfo = new HashMap(); + /** + * 用于格式化日期,作为日志文件名的一部分(FIXME 注意在windows下文件名无法使用:等符号!) + * SimpleDateFormat : mSimpleDateFormat + * + * @since 2013-3-21下午8:46:39 + */ + private SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("yyyyMMdd_HH-mm-ss"); + + /** + * Creates a new instance of CrashHandler. + */ + private CrashHandler() { + } + + /** + * getInstance:{获取CrashHandler实例 ,单例模式 } + * ────────────────────────────────── + * + * @return CrashHandler + * @throws + * @since I used to be a programmer like you, then I took an arrow in the knee Ver 1.0 + * ────────────────────────────────────────────────────────────────────────────────────────────────────── + * 2013-3-21下午8:52:24 Modified By Norris + * ────────────────────────────────────────────────────────────────────────────────────────────────────── + */ + public static CrashHandler getInstance() { + return mInstance; + } + + /** + * init:{初始化} + * ────────────────────────────────── + * + * @param paramContext + * @return void + * @throws + * @since I used to be a programmer like you, then I took an arrow in the knee Ver 1.0 + * ────────────────────────────────────────────────────────────────────────────────────────────────────── + * 2013-3-21下午8:52:45 Modified By Norris + * ────────────────────────────────────────────────────────────────────────────────────────────────────── + */ + public void init(Context paramContext) { + mContext = paramContext; + // 获取系统默认的UncaughtException处理器 + mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); + // 设置该CrashHandler为程序的默认处理器 + Thread.setDefaultUncaughtExceptionHandler(this); + } + + /** + * 当UncaughtException发生时会转入该重写的方法来处理 + * (non-Javadoc) + * + * @see UncaughtExceptionHandler#uncaughtException(Thread, Throwable) + */ + public void uncaughtException(Thread paramThread, Throwable paramThrowable) { + // 获取设备参数信息 + getDeviceInfo(mContext); +// mLogInfo.put("versionName", String.valueOf(BuildConfig.VERSION_CODE)); +// mLogInfo.put("versionCode", BuildConfig.VERSION_NAME); + // 保存日志文件 + String result = saveCrashLogToFile(paramThrowable); + mDefaultHandler.uncaughtException(paramThread, paramThrowable); +// if (!handleException(paramThrowable) && mDefaultHandler != null) { +// // 如果自定义的没有处理则让系统默认的异常处理器来处理 +// mDefaultHandler.uncaughtException(paramThread, paramThrowable); +// } else { +//// try { +//// // 如果处理了,让程序继续运行1秒再退出,保证文件保存并上传到服务器 +//// paramThread.sleep(1000); +//// } catch (InterruptedException e) { +//// e.printStackTrace(); +//// } +// // 退出程序 +// android.os.Process.killProcess(android.os.Process.myPid()); +// System.exit(1); +// } + } + + /** + * handleException:{自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.} + * ────────────────────────────────── + * + * @param paramThrowable + * @return true:如果处理了该异常信息;否则返回false. + * @throws + * @since I used to be a programmer like you, then I took an arrow in the knee Ver 1.0 + * ────────────────────────────────────────────────────────────────────────────────────────────────────── + * 2013-3-24下午12:28:53 Modified By Norris + * ────────────────────────────────────────────────────────────────────────────────────────────────────── + */ + public boolean handleException(Throwable paramThrowable) { + if (paramThrowable == null) + return false; + new Thread() { + public void run() { + Looper.prepare(); + Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出", Toast.LENGTH_SHORT).show(); + Looper.loop(); + } + }.start(); + // 获取设备参数信息 + getDeviceInfo(mContext); + // 保存日志文件 + String result = saveCrashLogToFile(paramThrowable); + //上传崩溃日志 + return true; + } + + /** + * getDeviceInfo:{获取设备参数信息} + * ────────────────────────────────── + * + * @param paramContext + * @throws + * @since I used to be a programmer like you, then I took an arrow in the knee Ver 1.0 + * ────────────────────────────────────────────────────────────────────────────────────────────────────── + * 2013-3-24下午12:30:02 Modified By Norris + * ────────────────────────────────────────────────────────────────────────────────────────────────────── + */ + public void getDeviceInfo(Context paramContext) { + try { + // 获得包管理器 + PackageManager mPackageManager = paramContext.getPackageManager(); + // 得到该应用的信息,即主Activity + PackageInfo mPackageInfo = mPackageManager.getPackageInfo( + paramContext.getPackageName(), PackageManager.GET_ACTIVITIES); + if (mPackageInfo != null) { + String versionName = mPackageInfo.versionName == null ? "null" + : mPackageInfo.versionName; + String versionCode = mPackageInfo.versionCode + ""; + mLogInfo.put("versionName", versionName); + mLogInfo.put("versionCode", versionCode); + } + } catch (NameNotFoundException e) { + e.printStackTrace(); + } + // 反射机制 + Field[] mFields = Build.class.getDeclaredFields(); + // 迭代Build的字段key-value 此处的信息主要是为了在服务器端手机各种版本手机报错的原因 + for (Field field : mFields) { + try { + field.setAccessible(true); + mLogInfo.put(field.getName(), field.get("").toString()); + Log.d(TAG, field.getName() + ":" + field.get("")); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + + /** + * saveCrashLogToFile:{将崩溃的Log保存到本地} + * TODO 可拓展,将Log上传至指定服务器路径 + * ────────────────────────────────── + * + * @param paramThrowable + * @return FileName + * @throws + * @since I used to be a programmer like you, then I took an arrow in the knee Ver 1.0 + * ────────────────────────────────────────────────────────────────────────────────────────────────────── + * 2013-3-24下午12:31:01 Modified By Norris + * ────────────────────────────────────────────────────────────────────────────────────────────────────── + */ + + + private String saveCrashLogToFile(Throwable paramThrowable) { + StringBuffer mStringBuffer = new StringBuffer(); + for (Map.Entry entry : mLogInfo.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + mStringBuffer.append(key + "=" + value + "\r\n"); + } + Writer mWriter = new StringWriter(); + PrintWriter mPrintWriter = new PrintWriter(mWriter); + paramThrowable.printStackTrace(mPrintWriter); + paramThrowable.printStackTrace(); + Throwable mThrowable = paramThrowable.getCause(); + // 迭代栈队列把所有的异常信息写入writer中 + while (mThrowable != null) { + mThrowable.printStackTrace(mPrintWriter); + // 换行 每个个异常栈之间换行 + mThrowable = mThrowable.getCause(); + } + + //记得关闭 + + String mResult = mWriter.toString(); + // String mResult = mWriter.toString().replace("\n", "").replace(":", "").replace("/", "").replace("\t", ""); + mStringBuffer.append(mResult); + // 保存文件,设置文件名 + String mTime = mSimpleDateFormat.format(new Date()); + String mFileName = mContext.getPackageName() + "_Exception-" + mTime + ".log"; + if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + try { + File mDirectory = new File(Constants.FILE_PATH); + Log.d(TAG, mDirectory.toString()); + if (!mDirectory.exists()) + mDirectory.mkdirs(); + FileOutputStream mFileOutputStream = new FileOutputStream(mDirectory + File.separator + mFileName); + mFileOutputStream.write(mStringBuffer.toString().getBytes()); + mFileOutputStream.close(); + return mResult; + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return mResult; + } + + +} diff --git a/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/utils/MyLinearLayoutManager.java b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/utils/MyLinearLayoutManager.java new file mode 100644 index 0000000000..f7d60f4afe --- /dev/null +++ b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/utils/MyLinearLayoutManager.java @@ -0,0 +1,36 @@ +package com.zhidao.adas.magic.utils; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +public class MyLinearLayoutManager extends LinearLayoutManager { + public MyLinearLayoutManager(Context context) { + super(context); + } + + public MyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { + super(context, orientation, reverseLayout); + } + + public MyLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + public boolean supportsPredictiveItemAnimations() { + return false; + } + + @Override + public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { + //override this method and implement code as below + try { + super.onLayoutChildren(recycler, state); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/utils/PreferencesUtils.java b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/utils/PreferencesUtils.java new file mode 100644 index 0000000000..f9a8006feb --- /dev/null +++ b/app_mogo_magic_ring/src/main/java/com/zhidao/adas/magic/utils/PreferencesUtils.java @@ -0,0 +1,286 @@ +package com.zhidao.adas.client.utils; + +import android.content.Context; +import android.content.SharedPreferences; + +public class PreferencesUtils { + + public static String PREFERENCE_NAME = "control"; + + public static boolean hasString(Context context, String key) { + if (context == null) return false; + SharedPreferences settings = context.getSharedPreferences( + PREFERENCE_NAME, Context.MODE_PRIVATE); + return settings.contains(key); + } + + /** + * put string preferences + * + * @param context + * @param key The name of the preference to modify + * @param value The new value for the preference + * @return True if the new values were successfully written to persistent + * storage. + */ + public static boolean putString(Context context, String key, String value) { + + if (context == null) return false; + SharedPreferences settings = context.getSharedPreferences( + PREFERENCE_NAME, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit(); + editor.putString(key, value); + return editor.commit(); + } + + /** + * get string preferences + * + * @param context + * @param key The name of the preference to retrieve + * @return The preference value if it exists, or null. Throws + * ClassCastException if there is a preference with this name that + * is not a string + * @see #getString(Context, String, String) + */ + public static String getString(Context context, String key) { + if (context == null) return null; + return getString(context, key, null); + } + + /** + * get string preferences + * + * @param context + * @param key The name of the preference to retrieve + * @param defaultValue Value to return if this preference does not exist + * @return The preference value if it exists, or defValue. Throws + * ClassCastException if there is a preference with this name that + * is not a string + */ + public static String getString(Context context, String key, + String defaultValue) { + + if (context == null) return defaultValue; + SharedPreferences settings = context.getSharedPreferences( + PREFERENCE_NAME, Context.MODE_PRIVATE); + return settings.getString(key, defaultValue); + } + + /** + * put int preferences + * + * @param context + * @param key The name of the preference to modify + * @param value The new value for the preference + * @return True if the new values were successfully written to persistent + * storage. + */ + public static boolean putInt(Context context, String key, int value) { + + if (context == null) return false; + SharedPreferences settings = context.getSharedPreferences( + PREFERENCE_NAME, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit(); + editor.putInt(key, value); + return editor.commit(); + } + + /** + * get int preferences + * + * @param context + * @param key The name of the preference to retrieve + * @return The preference value if it exists, or -1. Throws + * ClassCastException if there is a preference with this name that + * is not a int + * @see #getInt(Context, String, int) + */ + public static int getInt(Context context, String key) { + + if (context == null) return -1; + SharedPreferences settings = context.getSharedPreferences( + PREFERENCE_NAME, Context.MODE_PRIVATE); + return getInt(context, key, -1); + } + + /** + * get int preferences + * + * @param context + * @param key The name of the preference to retrieve + * @param defaultValue Value to return if this preference does not exist + * @return The preference value if it exists, or defValue. Throws + * ClassCastException if there is a preference with this name that + * is not a int + */ + public static int getInt(Context context, String key, int defaultValue) { + if (context == null) return defaultValue; + SharedPreferences settings = context.getSharedPreferences( + PREFERENCE_NAME, Context.MODE_PRIVATE); + return settings.getInt(key, defaultValue); + } + + /** + * put long preferences + * + * @param context + * @param key The name of the preference to modify + * @param value The new value for the preference + * @return True if the new values were successfully written to persistent + * storage. + */ + public static boolean putLong(Context context, String key, long value) { + if (context == null) return false; + SharedPreferences settings = context.getSharedPreferences( + PREFERENCE_NAME, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit(); + editor.putLong(key, value); + return editor.commit(); + } + + /** + * get long preferences + * + * @param context + * @param key The name of the preference to retrieve + * @return The preference value if it exists, or -1. Throws + * ClassCastException if there is a preference with this name that + * is not a long + * @see #getLong(Context, String, long) + */ + public static long getLong(Context context, String key) { + if (context == null) return -1; + return getLong(context, key, -1); + } + + /** + * get long preferences + * + * @param context + * @param key The name of the preference to retrieve + * @param defaultValue Value to return if this preference does not exist + * @return The preference value if it exists, or defValue. Throws + * ClassCastException if there is a preference with this name that + * is not a long + */ + public static long getLong(Context context, String key, long defaultValue) { + if (context == null) return defaultValue; + SharedPreferences settings = context.getSharedPreferences( + PREFERENCE_NAME, Context.MODE_PRIVATE); + + return settings.getLong(key, defaultValue); + } + + /** + * put float preferences + * + * @param context + * @param key The name of the preference to modify + * @param value The new value for the preference + * @return True if the new values were successfully written to persistent + * storage. + */ + public static boolean putFloat(Context context, String key, float value) { + if (context == null) return false; + SharedPreferences settings = context.getSharedPreferences( + PREFERENCE_NAME, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit(); + editor.putFloat(key, value); + return editor.commit(); + } + + /** + * get float preferences + * + * @param context + * @param key The name of the preference to retrieve + * @return The preference value if it exists, or -1. Throws + * ClassCastException if there is a preference with this name that + * is not a float + * @see #getFloat(Context, String, float) + */ + public static float getFloat(Context context, String key) { + if (context == null) return -1; + return getFloat(context, key, -1); + } + + /** + * get float preferences + * + * @param context + * @param key The name of the preference to retrieve + * @param defaultValue Value to return if this preference does not exist + * @return The preference value if it exists, or defValue. Throws + * ClassCastException if there is a preference with this name that + * is not a float + */ + public static float getFloat(Context context, String key, float defaultValue) { + if (context == null) return defaultValue; + SharedPreferences settings = context.getSharedPreferences( + PREFERENCE_NAME, Context.MODE_PRIVATE); + return settings.getFloat(key, defaultValue); + } + + /** + * put boolean preferences + * + * @param context + * @param key The name of the preference to modify + * @param value The new value for the preference + * @return True if the new values were successfully written to persistent + * storage. + */ + public static boolean putBoolean(Context context, String key, boolean value) { + if (context == null) return false; + SharedPreferences settings = context.getSharedPreferences( + PREFERENCE_NAME, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit(); + editor.putBoolean(key, value); + return editor.commit(); + } + + /** + * get boolean preferences, default is false + * + * @param context + * @param key The name of the preference to retrieve + * @return The preference value if it exists, or false. Throws + * ClassCastException if there is a preference with this name that + * is not a boolean + * @see #getBoolean(Context, String, boolean) + */ + public static boolean getBoolean(Context context, String key) { + if (context == null) return false; + return getBoolean(context, key, false); + } + + /** + * get boolean preferences + * + * @param context + * @param key The name of the preference to retrieve + * @param defaultValue Value to return if this preference does not exist + * @return The preference value if it exists, or defValue. Throws + * ClassCastException if there is a preference with this name that + * is not a boolean + */ + public static boolean getBoolean(Context context, String key, + boolean defaultValue) { + if (context == null) return defaultValue; + SharedPreferences settings = context.getSharedPreferences( + PREFERENCE_NAME, Context.MODE_PRIVATE); + return settings.getBoolean(key, defaultValue); + } + + + public static boolean delete(Context context, String key) { + if (context == null) return false; + SharedPreferences settings = context.getSharedPreferences( + PREFERENCE_NAME, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit(); + editor.remove(key); + return editor.commit(); + } + +} diff --git a/app_mogo_magic_ring/src/main/res/drawable/bg_adas_dialog.xml b/app_mogo_magic_ring/src/main/res/drawable/bg_adas_dialog.xml new file mode 100644 index 0000000000..cbfb69f454 --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/drawable/bg_adas_dialog.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/app_mogo_magic_ring/src/main/res/drawable/btn_bg.xml b/app_mogo_magic_ring/src/main/res/drawable/btn_bg.xml new file mode 100644 index 0000000000..ba61bf76b4 --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/drawable/btn_bg.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app_mogo_magic_ring/src/main/res/drawable/ic_pack_up.xml b/app_mogo_magic_ring/src/main/res/drawable/ic_pack_up.xml new file mode 100644 index 0000000000..328407001b --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/drawable/ic_pack_up.xml @@ -0,0 +1,9 @@ + + + diff --git a/app_mogo_magic_ring/src/main/res/drawable/ic_pull.xml b/app_mogo_magic_ring/src/main/res/drawable/ic_pull.xml new file mode 100644 index 0000000000..2a5cad0c1e --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/drawable/ic_pull.xml @@ -0,0 +1,9 @@ + + + diff --git a/app_mogo_magic_ring/src/main/res/drawable/icon.xml b/app_mogo_magic_ring/src/main/res/drawable/icon.xml new file mode 100644 index 0000000000..0e2c205a40 --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/drawable/icon.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app_mogo_magic_ring/src/main/res/drawable/item_bg.xml b/app_mogo_magic_ring/src/main/res/drawable/item_bg.xml new file mode 100644 index 0000000000..3476874a12 --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/drawable/item_bg.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app_mogo_magic_ring/src/main/res/drawable/item_text_color.xml b/app_mogo_magic_ring/src/main/res/drawable/item_text_color.xml new file mode 100644 index 0000000000..4b611429b1 --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/drawable/item_text_color.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/app_mogo_magic_ring/src/main/res/drawable/selector_history_ip.xml b/app_mogo_magic_ring/src/main/res/drawable/selector_history_ip.xml new file mode 100644 index 0000000000..a36a8d2aa8 --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/drawable/selector_history_ip.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app_mogo_magic_ring/src/main/res/layout/activity_main.xml b/app_mogo_magic_ring/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000000..e8bd0716bd --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/layout/activity_main.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app_mogo_magic_ring/src/main/res/layout/dialog_time.xml b/app_mogo_magic_ring/src/main/res/layout/dialog_time.xml new file mode 100644 index 0000000000..acd118ceb8 --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/layout/dialog_time.xml @@ -0,0 +1,29 @@ + + + + + + + \ No newline at end of file diff --git a/app_mogo_magic_ring/src/main/res/layout/include_line.xml b/app_mogo_magic_ring/src/main/res/layout/include_line.xml new file mode 100644 index 0000000000..c7d8f0f77a --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/layout/include_line.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app_mogo_magic_ring/src/main/res/layout/item_info.xml b/app_mogo_magic_ring/src/main/res/layout/item_info.xml new file mode 100644 index 0000000000..7fda3f9417 --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/layout/item_info.xml @@ -0,0 +1,21 @@ + + + + + + \ No newline at end of file diff --git a/app_mogo_magic_ring/src/main/res/layout/item_main.xml b/app_mogo_magic_ring/src/main/res/layout/item_main.xml new file mode 100644 index 0000000000..56460fa16e --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/layout/item_main.xml @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app_mogo_magic_ring/src/main/res/layout/item_pop.xml b/app_mogo_magic_ring/src/main/res/layout/item_pop.xml new file mode 100644 index 0000000000..501a4044bd --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/layout/item_pop.xml @@ -0,0 +1,12 @@ + + diff --git a/app_mogo_magic_ring/src/main/res/layout/item_status.xml b/app_mogo_magic_ring/src/main/res/layout/item_status.xml new file mode 100644 index 0000000000..a4cfdf3b81 --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/layout/item_status.xml @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/app_mogo_magic_ring/src/main/res/layout/layout_float.xml b/app_mogo_magic_ring/src/main/res/layout/layout_float.xml new file mode 100644 index 0000000000..7e199841eb --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/layout/layout_float.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/app_mogo_magic_ring/src/main/res/values/colors.xml b/app_mogo_magic_ring/src/main/res/values/colors.xml new file mode 100644 index 0000000000..bfe52b115c --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/values/colors.xml @@ -0,0 +1,20 @@ + + + #008577 + #00574B + #D81B60 + #FFD700 + #102b6a + #224b8f + #FFFFFF + #000000 + #FF1493 + #DC143C + #32CD32 + #708090 + #32CD32 + #DC143C + #FF00FF + #DAA520 + #1E90FF + diff --git a/app_mogo_magic_ring/src/main/res/values/strings.xml b/app_mogo_magic_ring/src/main/res/values/strings.xml new file mode 100644 index 0000000000..34406718c6 --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ + + 蘑戒 + 复位按钮:下发减速命令之后需要复位操作\n减速按钮:单机触发减速,长按配置减速发送频率\n鸣笛按钮:单机触发鸣笛,长按配置鸣笛时长 + + diff --git a/app_mogo_magic_ring/src/main/res/values/styles.xml b/app_mogo_magic_ring/src/main/res/values/styles.xml new file mode 100644 index 0000000000..71a18efd24 --- /dev/null +++ b/app_mogo_magic_ring/src/main/res/values/styles.xml @@ -0,0 +1,34 @@ + + + + + + + +