diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 0d156937bb..663459aa50 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -3,18 +3,9 @@ - diff --git a/.idea/misc.xml b/.idea/misc.xml index cd77a1f062..21e99e2dc0 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/modules/mogo-module-common/src/main/java/com/mogo/module/common/entity/V2XMessageEntity.java b/modules/mogo-module-common/src/main/java/com/mogo/module/common/entity/V2XMessageEntity.java index 3531741702..40ee54edc5 100644 --- a/modules/mogo-module-common/src/main/java/com/mogo/module/common/entity/V2XMessageEntity.java +++ b/modules/mogo-module-common/src/main/java/com/mogo/module/common/entity/V2XMessageEntity.java @@ -100,6 +100,8 @@ public class V2XMessageEntity implements Serializable { int ALERT_ROAD_LIVE_CAR_WARNING = 1_007; // 道路事件违章停车 int ALERT_ILLEGAL_PARK_WARNING = 1_008; + // 呼叫、请求直播事件 + int ALERT_VOICE_CALL_FOR_LIVECAR_SHOW = 1_009; // 自车求助 int ALERT_CAR_FOR_HELP = 8_000; // obu事件 @@ -117,6 +119,7 @@ public class V2XMessageEntity implements Serializable { V2XTypeEnum.ALERT_ROAD_LIVE_CAR_WARNING, V2XTypeEnum.ALERT_ILLEGAL_PARK_WARNING, V2XTypeEnum.ALERT_CAR_FOR_HELP, + V2XTypeEnum.ALERT_VOICE_CALL_FOR_LIVECAR_SHOW, V2XTypeEnum.ALERT_OBU_EVENT, }) @Target({ diff --git a/modules/mogo-module-v2x/build.gradle b/modules/mogo-module-v2x/build.gradle index b80c5fc2de..1c8bc102ab 100644 --- a/modules/mogo-module-v2x/build.gradle +++ b/modules/mogo-module-v2x/build.gradle @@ -61,6 +61,10 @@ dependencies { implementation rootProject.ext.dependencies.androidxviewpager2 implementation rootProject.ext.dependencies.localbroadcastmanager + implementation rootProject.ext.dependencies.videoarmv7 + implementation rootProject.ext.dependencies.videoarm64 + implementation rootProject.ext.dependencies.videojava + kapt rootProject.ext.dependencies.roomAnnotationProcessor kapt rootProject.ext.dependencies.aroutercompiler diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/V2XModuleProvider.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/V2XModuleProvider.java index 84eb75fb33..2846401c23 100644 --- a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/V2XModuleProvider.java +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/V2XModuleProvider.java @@ -27,6 +27,7 @@ import com.mogo.module.v2x.entity.net.V2XStrategyPushRes; import com.mogo.module.v2x.network.V2XRefreshCallback; import com.mogo.module.v2x.receiver.SceneBroadcastReceiver; import com.mogo.module.v2x.scenario.impl.V2XScenarioManager; +import com.mogo.module.v2x.scenario.scene.livecar.V2XVoiceCallLiveBiz; import com.mogo.module.v2x.scenario.scene.park.V2XIllegalParkScenario; import com.mogo.module.v2x.scenario.scene.park.V2XIllegalParkWindow; import com.mogo.module.v2x.utils.FatigueDrivingUtils; @@ -126,7 +127,7 @@ public class V2XModuleProvider implements V2XVoiceManager.INSTANCE.init(context); registerListener(); initData(); - + initBiz(context); // 注册广播接收场景弹窗使用的 SceneBroadcastReceiver localReceiver = new SceneBroadcastReceiver(); LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context); @@ -138,6 +139,10 @@ public class V2XModuleProvider implements V2XObuManager.getInstance().init(); } + private void initBiz(Context context) { + V2XVoiceCallLiveBiz.getInstance().init(context); + } + private void initData() { try { // 查询ACC状态 diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/entity/net/V2XLiveCrossRoad.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/entity/net/V2XLiveCrossRoad.java new file mode 100644 index 0000000000..d99dec5ce4 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/entity/net/V2XLiveCrossRoad.java @@ -0,0 +1,109 @@ +package com.mogo.module.v2x.entity.net; + +import com.mogo.commons.data.BaseData; + +import java.io.Serializable; + +/** + * author : unknown + * desc : 路口实况返回数据 + */ +public class V2XLiveCrossRoad extends BaseData implements Serializable { + public V2XLiveCrossRoadEntity result; + + public V2XLiveCrossRoadEntity getResult() { + return result; + } + + public void setResult(V2XLiveCrossRoadEntity result) { + this.result = result; + } + + @Override + public String toString() { + return "V2XLiveCrossRoad{" + + "result=" + result + + ", code=" + code + + ", msg='" + msg + '\'' + + '}'; + } + + public class V2XLiveCrossRoadEntity { + private int cameraParentId; + private int cameraId; + private String url; + private Double lat; + private Double lon; + private Double distance; + + public V2XLiveCrossRoadEntity(int cameraParentId, int cameraId, String url, Double lat, Double lon, Double distance) { + this.cameraParentId = cameraParentId; + this.cameraId = cameraId; + this.url = url; + this.lat = lat; + this.lon = lon; + this.distance = distance; + } + + public int getCameraParentId() { + return cameraParentId; + } + + public void setCameraParentId(int cameraParentId) { + this.cameraParentId = cameraParentId; + } + + public int getCameraId() { + return cameraId; + } + + public void setCameraId(int cameraId) { + this.cameraId = cameraId; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public Double getLat() { + return lat; + } + + public void setLat(Double lat) { + this.lat = lat; + } + + public Double getLon() { + return lon; + } + + public void setLon(Double lon) { + this.lon = lon; + } + + public Double getDistance() { + return distance; + } + + public void setDistance(Double distance) { + this.distance = distance; + } + + @Override + public String toString() { + return "V2XLiveCrossRoadEntity{" + + "cameraParentId=" + cameraParentId + + ", cameraId=" + cameraId + + ", url='" + url + '\'' + + ", lat=" + lat + + ", lon=" + lon + + ", distance=" + distance + + '}'; + } + } + +} diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/network/V2XApiService.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/network/V2XApiService.java index 2345952ffa..4ce5ecd7b6 100644 --- a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/network/V2XApiService.java +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/network/V2XApiService.java @@ -4,6 +4,7 @@ import com.mogo.commons.data.BaseData; import com.mogo.module.common.entity.MarkerResponse; import com.mogo.module.v2x.entity.net.V2XDemoUserInfoRes; import com.mogo.module.v2x.entity.net.V2XLiveCarRes; +import com.mogo.module.v2x.entity.net.V2XLiveCrossRoad; import com.mogo.module.v2x.entity.net.V2XLivePushVoRes; import com.mogo.module.v2x.entity.net.V2XSeekHelpRes; import com.mogo.module.v2x.entity.net.V2XStrategyPushRes; @@ -147,4 +148,12 @@ public interface V2XApiService { @FormUrlEncoded @POST("/deva/poiInfoFabulous/car/poi/no/RespondingToHelp/v1") Observable respondingToHelp(@FieldMap Map params); + + /** + * 查询路口实况 + */ + @FormUrlEncoded + @POST("/yycp-geo-fence-carService/car/camera/no/nextTest/v1") +// @POST("/yycp-geo-fence-carService/car/camera/no/next/v1") + Observable queryCrossRoadsLive(@FieldMap Map parameters); } diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/network/V2XRefreshModel.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/network/V2XRefreshModel.java index 947cdffe39..1346610074 100644 --- a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/network/V2XRefreshModel.java +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/network/V2XRefreshModel.java @@ -4,18 +4,22 @@ import android.content.Context; import android.text.TextUtils; import com.alibaba.android.arouter.launcher.ARouter; +import com.mogo.commons.AbsMogoApplication; import com.mogo.commons.data.BaseData; import com.mogo.commons.network.ParamsProvider; import com.mogo.commons.network.SubscribeImpl; import com.mogo.commons.network.Utils; import com.mogo.map.MogoLatLng; +import com.mogo.map.location.MogoLocation; import com.mogo.module.common.entity.MarkerResponse; import com.mogo.module.service.ServiceConst; import com.mogo.module.service.network.RefreshBody; import com.mogo.module.v2x.V2XConst; +import com.mogo.module.v2x.V2XServiceManager; import com.mogo.module.v2x.entity.net.V2XDemoUserInfoRes; import com.mogo.module.v2x.entity.net.V2XLiveCarBroadcastReq; import com.mogo.module.v2x.entity.net.V2XLiveCarRes; +import com.mogo.module.v2x.entity.net.V2XLiveCrossRoad; import com.mogo.module.v2x.entity.net.V2XLivePushVoRes; import com.mogo.module.v2x.entity.net.V2XSeekHelpRes; import com.mogo.module.v2x.entity.net.V2XStrategyPushRes; @@ -548,4 +552,42 @@ public class V2XRefreshModel { }); } } + + public void queryCrossRoadsLive(V2XRefreshCallback callback) { + if (mV2XApiService != null) { + final Map map = new ParamsProvider.Builder(mContext).build(); + MogoLocation lastKnowLocation = V2XServiceManager.getMapService().getSingletonLocationClient(AbsMogoApplication.getApp()).getLastKnowLocation(); + double lat = lastKnowLocation.getLatitude(); + double lon = lastKnowLocation.getLongitude(); + String tmpLat = String.valueOf(lat); + String tmpLon = String.valueOf(lon); + float bearing = lastKnowLocation.getBearing(); + String json = "{\"lat\":" + tmpLat + ",\"lon\":" + tmpLon + ",\"direction\":" + bearing + "}"; + map.put("sn", Utils.getSn()); + map.put("data", json); + mV2XApiService.queryCrossRoadsLive(map) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SubscribeImpl(RequestOptions.create(mContext)) { + @Override + public void onSuccess(V2XLiveCrossRoad o) { + super.onSuccess(o); + if (callback != null) { + callback.onSuccess(o); + } + } + + @Override + public void onError(String message, int code) { + super.onError(message, code); + if (callback != null) { + if (TextUtils.isEmpty(message)) { + message = "网络错误,请稍后重试"; + } + callback.onFail(message); + } + } + }); + } + } } diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/impl/V2XScenarioManager.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/impl/V2XScenarioManager.java index 029ffe5284..0e51fb64bb 100644 --- a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/impl/V2XScenarioManager.java +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/impl/V2XScenarioManager.java @@ -14,6 +14,7 @@ import com.mogo.module.v2x.scenario.scene.animation.V2XAnimationScenario; import com.mogo.module.v2x.scenario.scene.fatigue.V2XFatigueDrivingScenario; import com.mogo.module.v2x.scenario.scene.help.V2XCarForHelpScenario; import com.mogo.module.v2x.scenario.scene.livecar.V2XPushLiveCarScenario; +import com.mogo.module.v2x.scenario.scene.livecar.V2XVoiceCallLiveScenario; import com.mogo.module.v2x.scenario.scene.park.V2XIllegalParkScenario; import com.mogo.module.v2x.scenario.scene.push.V2XPushEventScenario; import com.mogo.module.v2x.scenario.scene.road.V2XRoadEventScenario; @@ -96,6 +97,9 @@ public class V2XScenarioManager implements IV2XScenarioManager { case V2XMessageEntity.V2XTypeEnum.ALERT_ILLEGAL_PARK_WARNING: mV2XScenario = V2XIllegalParkScenario.getInstance(); break; + case V2XMessageEntity.V2XTypeEnum.ALERT_VOICE_CALL_FOR_LIVECAR_SHOW: + mV2XScenario = V2XVoiceCallLiveScenario.getInstance(); + break; default: Logger.e(MODULE_NAME, "当前V2X消息类型未定义。"); TipToast.tip("当前V2X消息类型未定义"); diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XVoiceCallLiveBiz.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XVoiceCallLiveBiz.java new file mode 100644 index 0000000000..3fa4c42b92 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XVoiceCallLiveBiz.java @@ -0,0 +1,148 @@ +package com.mogo.module.v2x.scenario.scene.livecar; + +import android.content.Context; +import android.text.TextUtils; + +import com.mogo.commons.voice.AIAssist; +import com.mogo.module.common.entity.V2XMessageEntity; +import com.mogo.module.common.entity.V2XPushMessageEntity; +import com.mogo.module.v2x.R; +import com.mogo.module.v2x.V2XDemoManager; +import com.mogo.module.v2x.V2XServiceManager; +import com.mogo.module.v2x.entity.net.V2XDemoUserInfoRes; +import com.mogo.module.v2x.utils.ToastUtils; +import com.mogo.module.v2x.voice.V2XVoiceCallbackListener; +import com.mogo.module.v2x.voice.V2XVoiceManager; +import com.mogo.service.statusmanager.StatusDescriptor; +import com.mogo.utils.logger.Logger; + +import static com.mogo.module.v2x.V2XConst.MODULE_NAME; +import static com.mogo.module.v2x.voice.V2XVoiceConstants.COMMAND_ZHIDAO_V2X_AHEAD_LIVE; +import static com.mogo.module.v2x.voice.V2XVoiceConstants.COMMAND_ZHIDAO_V2X_CALL_FRONT_CAR_DEMO_UN_WAKEUP; +import static com.mogo.module.v2x.voice.V2XVoiceConstants.COMMAND_ZHIDAO_V2X_CROSSROADS_LIVE; +import static com.mogo.module.v2x.voice.V2XVoiceConstants.COMMAND_ZHIDAO_V2X_OPEN_ROAD_CAMERA_LIVE_UN_WAKEUP; +import static com.mogo.service.statusmanager.StatusDescriptor.MAIN_PAGE_RESUME; + +/** + * author : unknown + * desc : TODO 演示使用的语音呼叫查看直播车辆 或者 路口实况 业务模块 + */ +public class V2XVoiceCallLiveBiz { + + private static final String REGISTER_LIFECYCLE_TAG = V2XVoiceCallLiveBiz.class.getSimpleName(); + + private V2XVoiceCallLiveBiz() { + + } + + private static volatile V2XVoiceCallLiveBiz mV2XVoiceCallLiveBiz; + + public static V2XVoiceCallLiveBiz getInstance() { + if (mV2XVoiceCallLiveBiz == null) { + synchronized (V2XVoiceCallLiveBiz.class) { + if (mV2XVoiceCallLiveBiz == null) { + mV2XVoiceCallLiveBiz = new V2XVoiceCallLiveBiz(); + } + } + } + return mV2XVoiceCallLiveBiz; + } + + private Context mContext; + + //语音词指令 查看前车视频回调 + private V2XVoiceCallbackListener v2XVoiceCallbackFrontLiveCarListener = (command, intent) -> { + Logger.d(MODULE_NAME, "语音词指令 查看前车视频回调"); + getFrontCarLive(); + }; + + //语音词指令 查看路口实况回调 + private V2XVoiceCallbackListener v2XVoiceCallbackOpenRoadCameraListener = (command, intent) -> { + Logger.d(MODULE_NAME, "语音词指令 查看路口实况回调"); + AIAssist.getInstance(mContext).speakTTSVoice(mContext.getString(R.string.v2x_voice_see_crossroad_live)); + getOpenRoadCameraLive(); + }; + + public void init(Context context) { + Logger.d(MODULE_NAME, "init"); + this.mContext = context; + registerLifecycleChange(); + registerVoice(); + } + + private void registerLifecycleChange() { + V2XServiceManager.getMoGoStatusManager().registerStatusChangedListener(REGISTER_LIFECYCLE_TAG, MAIN_PAGE_RESUME, (descriptor, isTrue) -> { + if (descriptor == StatusDescriptor.MAIN_PAGE_RESUME) { + if (isTrue) { + registerVoice(); + } else { + unRegisterVoice(); + } + } + }); + } + + private void registerVoice() { + V2XVoiceManager.INSTANCE.registerUnWakeVoice(COMMAND_ZHIDAO_V2X_CALL_FRONT_CAR_DEMO_UN_WAKEUP, v2XVoiceCallbackFrontLiveCarListener) + .registerUnWakeVoice(COMMAND_ZHIDAO_V2X_OPEN_ROAD_CAMERA_LIVE_UN_WAKEUP, v2XVoiceCallbackOpenRoadCameraListener) + .registerWakeCmd(COMMAND_ZHIDAO_V2X_AHEAD_LIVE, v2XVoiceCallbackFrontLiveCarListener) + .registerWakeCmd(COMMAND_ZHIDAO_V2X_CROSSROADS_LIVE, v2XVoiceCallbackOpenRoadCameraListener); + } + + private void unRegisterVoice() { + V2XVoiceManager.INSTANCE.unRegisterUnWakeVoice(COMMAND_ZHIDAO_V2X_CALL_FRONT_CAR_DEMO_UN_WAKEUP) + .unRegisterUnWakeVoice(COMMAND_ZHIDAO_V2X_OPEN_ROAD_CAMERA_LIVE_UN_WAKEUP) + .unRegisterWakeCmd(COMMAND_ZHIDAO_V2X_AHEAD_LIVE).unRegisterWakeCmd(COMMAND_ZHIDAO_V2X_CROSSROADS_LIVE); + } + + public void getFrontCarLive() { + V2XDemoUserInfoRes.ResultBean.UserListBean.UserInfoBean userInfoBean = V2XDemoManager.getInstance().getV2XDemoUserInfoEntity1().getUserInfo(); + String liveCarSn = userInfoBean.getSn(); + if (TextUtils.isEmpty(liveCarSn)) { + ToastUtils.showShort("附近没有可直播车机"); + Logger.d(MODULE_NAME, "getFrontCarLive : sn is null"); + return; + } + V2XMessageEntity v2XMessageEntity = buildCallLiveParams(liveCarSn, null); + V2XVoiceCallLiveScenario.getInstance().setV2XWindow(new V2XVoiceCallLiveCarWindow()); + V2XVoiceCallLiveScenario.getInstance().init(v2XMessageEntity); + } + + public void getOpenRoadCameraLive() { + String liveUrl = "rtmp://154.8.189.110:19350/live/10_1"; + V2XMessageEntity v2XMessageEntity = buildCallLiveParams(null, liveUrl); + V2XVoiceCallLiveScenario.getInstance().setV2XWindow(new V2XVoiceCrossRoadLiveWindow()); + V2XVoiceCallLiveScenario.getInstance().init(v2XMessageEntity); +// V2XRefreshModel.getInstance(mContext).queryCrossRoadsLive(new V2XRefreshCallback() { +// @Override +// public void onSuccess(V2XLiveCrossRoad result) { +// if (result != null && result.getResult().getUrl() != null) { +// String liveUrl = result.getResult().getUrl(); +// V2XMessageEntity v2XMessageEntity = buildCallLiveParams(null, liveUrl); +// V2XVoiceCallLiveScenario.getInstance().setV2XWindow(new V2XVoiceCrossRoadLiveWindow()); +// V2XVoiceCallLiveScenario.getInstance().init(v2XMessageEntity); +// } else { +// Logger.d(MODULE_NAME, "getOpenRoadCameraLive 路口实况直播地址为空"); +// } +// } +// +// @Override +// public void onFail(String msg) { +// Logger.d(MODULE_NAME, "getOpenRoadCameraLive : " + msg); +// } +// }); + } + + private V2XMessageEntity buildCallLiveParams(String sn, String liveUrl) { + V2XPushMessageEntity v2XPushMessageEntity = new V2XPushMessageEntity(); + v2XPushMessageEntity.setVideoSn(sn); + v2XPushMessageEntity.setVideoUrl(liveUrl); + v2XPushMessageEntity.setShowWindow(true); + V2XMessageEntity v2XMessageEntity = new V2XMessageEntity<>(); + v2XMessageEntity.setType(V2XMessageEntity.V2XTypeEnum.ALERT_VOICE_CALL_FOR_LIVECAR_SHOW); + v2XMessageEntity.setContent(v2XPushMessageEntity); + v2XMessageEntity.setShowState(true); + return v2XMessageEntity; + } + +} diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XVoiceCallLiveCarWindow.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XVoiceCallLiveCarWindow.java new file mode 100644 index 0000000000..fd4c5474e4 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XVoiceCallLiveCarWindow.java @@ -0,0 +1,143 @@ +package com.mogo.module.v2x.scenario.scene.livecar; + +import android.content.Context; +import android.os.Handler; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.mogo.module.common.entity.MarkerCarInfo; +import com.mogo.module.common.entity.V2XPushMessageEntity; +import com.mogo.module.v2x.R; +import com.mogo.module.v2x.V2XServiceManager; +import com.mogo.module.v2x.listener.V2XWindowStatusListener; +import com.mogo.module.v2x.scenario.view.IV2XWindow; +import com.mogo.module.v2x.view.V2XCarLiveVideoView; +import com.mogo.utils.logger.Logger; + +import static com.mogo.module.v2x.V2XConst.MODULE_NAME; + +public class V2XVoiceCallLiveCarWindow extends RelativeLayout + implements IV2XWindow { + + private V2XCarLiveVideoView mV2XCarLiveVideoView; + private TextView tvCountDown; + private ImageView ivVideoPlayingSign; + private boolean isVideoPlay = false; + + // 处理道路事件,30秒倒计时 + private Handler handlerV2XEvent = new Handler(); + private Runnable runnableV2XEvent; + private static final int COUNT_DOWN_TIMER = 1_000; + private static final int ALL_EXPIRE_TIMER = 1_000 * 30; + private static int EXPIRE_TIMER = ALL_EXPIRE_TIMER; + + public V2XVoiceCallLiveCarWindow() { + this(V2XServiceManager.getContext(), null); + Logger.d(MODULE_NAME, "V2XVoiceCallLiveCarWindow INIT"); + } + + public V2XVoiceCallLiveCarWindow(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public V2XVoiceCallLiveCarWindow(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(context); + } + + private void initView(Context context) { + Logger.w(MODULE_NAME, "V2X===初始化语音呼叫直播视图"); + LayoutInflater.from(context).inflate(R.layout.window_see_carlive_video, this); + mV2XCarLiveVideoView = findViewById(R.id.videoPlayer); + tvCountDown = findViewById(R.id.tvCountDown); + ivVideoPlayingSign = findViewById(R.id.ivVideoPlayingSign); + mV2XCarLiveVideoView.addOnVideoStatusChangeListener(videoPlaying -> { + isVideoPlay = videoPlaying; + if (isVideoPlay) { + startCountDown(); + } else { + stopCountDown(); + } + }); + } + + @Override + public void show(V2XPushMessageEntity entity) { + if (entity != null) { + Logger.w(MODULE_NAME, "更新直播信息。。。。。" + entity); + // 启动播放 + MarkerCarInfo.CarLiveInfo carLiveInfo = new MarkerCarInfo.CarLiveInfo(); + carLiveInfo.setVideoChannel(entity.getVideoChannel()); + carLiveInfo.setVideoSn(entity.getVideoSn()); + carLiveInfo.setVideoUrl(entity.getVideoUrl()); + Logger.w(MODULE_NAME, "更新直播信息 END"); + mV2XCarLiveVideoView.setCarLiveInfo(carLiveInfo); + if (isVideoPlay) { + startCountDown(); + } + } + } + + @Override + public void close() { + // 停止倒计时 + stopCountDown(); + if (V2XServiceManager + .getMogoTopViewManager().isViewAdded(this)) { + //移除窗体 + V2XServiceManager + .getMogoTopViewManager() + .removeView(this); + } + } + + @Override + public View getView() { + return this; + } + + @Override + public void setWindowStatusListener(V2XWindowStatusListener listener) { + + } + + /** + * 窗体倒计时 + */ + private void startCountDown() { + // 倒计时 + if (runnableV2XEvent == null) { + runnableV2XEvent = () -> { + EXPIRE_TIMER = EXPIRE_TIMER - COUNT_DOWN_TIMER; + Logger.d(MODULE_NAME, "V2X=== Window 30秒倒计时开始,当前 :" + EXPIRE_TIMER / COUNT_DOWN_TIMER + " 秒"); + tvCountDown.setVisibility(View.VISIBLE); + ivVideoPlayingSign.setVisibility(View.VISIBLE); + tvCountDown.setText(String.valueOf(EXPIRE_TIMER / COUNT_DOWN_TIMER)); + if (EXPIRE_TIMER > 0) { + handlerV2XEvent.postDelayed(runnableV2XEvent, COUNT_DOWN_TIMER); + } else { + close(); + } + }; + } else { + handlerV2XEvent.removeCallbacks(runnableV2XEvent); + } + Logger.d(MODULE_NAME, "V2X=== Window 展示开始倒计时"); + handlerV2XEvent.postDelayed(runnableV2XEvent, COUNT_DOWN_TIMER); + } + + private void stopCountDown() { + Logger.d(MODULE_NAME, "V2X=== Window 倒计时停止。。。"); + if (handlerV2XEvent != null && runnableV2XEvent != null) { + handlerV2XEvent.removeCallbacks(runnableV2XEvent); + runnableV2XEvent = null; + tvCountDown.setVisibility(View.GONE); + ivVideoPlayingSign.setVisibility(View.GONE); + EXPIRE_TIMER = ALL_EXPIRE_TIMER; + } + } +} diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XVoiceCallLiveScenario.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XVoiceCallLiveScenario.java new file mode 100644 index 0000000000..8e8af5abc2 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XVoiceCallLiveScenario.java @@ -0,0 +1,143 @@ +package com.mogo.module.v2x.scenario.scene.livecar; + +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.Nullable; + +import com.mogo.module.common.entity.V2XMessageEntity; +import com.mogo.module.common.entity.V2XPushMessageEntity; +import com.mogo.module.v2x.R; +import com.mogo.module.v2x.V2XConst; +import com.mogo.module.v2x.V2XServiceManager; +import com.mogo.module.v2x.scenario.impl.AbsV2XScenario; +import com.mogo.module.v2x.utils.V2XUtils; +import com.mogo.service.windowview.IMogoTopViewStatusListener; +import com.mogo.utils.TipToast; +import com.mogo.utils.logger.Logger; + +import static com.mogo.module.v2x.V2XConst.MODULE_NAME; + +/** + * author : unknown + * desc : TODO 演示使用的语音呼叫查看直播场景,包括车辆直播 或者 路口实况 window,区分不同页面window逻辑实现 + */ +public class V2XVoiceCallLiveScenario extends AbsV2XScenario implements IMogoTopViewStatusListener { + + private V2XVoiceCallLiveScenario() { + + } + + private static volatile V2XVoiceCallLiveScenario mV2XVoiceCallLiveCarScenario; + + public static V2XVoiceCallLiveScenario getInstance() { + if (mV2XVoiceCallLiveCarScenario == null) { + synchronized (V2XVoiceCallLiveScenario.class) { + if (mV2XVoiceCallLiveCarScenario == null) { + mV2XVoiceCallLiveCarScenario = new V2XVoiceCallLiveScenario(); + } + } + } + return mV2XVoiceCallLiveCarScenario; + } + + @Override + public void init(@Nullable V2XMessageEntity v2XMessageEntity) { + if (v2XMessageEntity == null) { + TipToast.shortTip("附近没有可直播车机"); + } + if (v2XMessageEntity.isShowState()) { + if (!isSameScenario(v2XMessageEntity) + && V2XServiceManager.getMoGoStatusManager().isMainPageLaunched()) { + setV2XMessageEntity(v2XMessageEntity); + Logger.d(V2XConst.MODULE_NAME, "v2XMessageEntity : " + v2XMessageEntity + " getVideoSn : " + v2XMessageEntity.getContent().getVideoSn()); + if (v2XMessageEntity != null) { + Logger.d(V2XConst.MODULE_NAME, "准备展示直播窗口"); + show(); + } else { + TipToast.shortTip("附近没有可直播车机"); + Logger.e(V2XConst.MODULE_NAME, "直播地址为null"); + } + } else { + setV2XMessageEntity(v2XMessageEntity); + Logger.w(V2XConst.MODULE_NAME, "要处理的场景已经存在,丢弃这次初始化"); + } + } else { + close(); + } + } + + @Override + public void show() { + if (getV2XMessageEntity() != null && getV2XMessageEntity().getContent() != null) { + showWindow(); + } + } + + @Override + public void showWindow() { + if (getV2XWindow() != null) { + getV2XWindow().show(getV2XMessageEntity().getContent()); + ViewGroup.LayoutParams layoutParams = + new ViewGroup.LayoutParams( + (int) V2XUtils.getApp().getResources().getDimension(R.dimen.module_v2x_event_window_width), + (int) V2XUtils.getApp().getResources().getDimension(R.dimen.module_v2x_event_see_live_window_height)); + V2XServiceManager + .getMogoTopViewManager() + .addView(getV2XWindow().getView(), layoutParams, this); + V2XServiceManager.getMoGoV2XStatusManager().setLiveCarWindowShow(TAG, true); + } + } + + @Override + public void closeWindow() { + if (getV2XWindow() != null) { + getV2XWindow().close(); + } + V2XServiceManager.getMoGoV2XStatusManager().setLiveCarWindowShow(TAG, false); + } + + @Override + public void showButton() { + + } + + @Override + public void closeButton() { + + } + + @Override + public void drawPOI() { + + } + + @Override + public void clearPOI() { + + } + + @Override + public void onViewAdded(View view) { + Logger.d(MODULE_NAME, "展示 Window 动画结束"); + } + + @Override + public void onViewRemoved(View view) { + Logger.d(MODULE_NAME, "关闭 Window 动画结束"); + getV2XWindow().close(); + V2XServiceManager.getMoGoV2XStatusManager().setLiveCarWindowShow(TAG, false); + } + + @Override + public void beforeViewAddAnim(View view) { + Logger.d(MODULE_NAME, "展示 Window 开始"); + } + + @Override + public void beforeViewRemoveAnim(View view) { + Logger.d(MODULE_NAME, "关闭 Window 开始"); + setV2XMessageEntity(null); + V2XServiceManager.getMoGoV2XStatusManager().setLiveCarWindowShow(TAG, false); + } +} diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XVoiceCrossRoadLiveWindow.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XVoiceCrossRoadLiveWindow.java new file mode 100644 index 0000000000..025321de65 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/scenario/scene/livecar/V2XVoiceCrossRoadLiveWindow.java @@ -0,0 +1,145 @@ +package com.mogo.module.v2x.scenario.scene.livecar; + +import android.content.Context; +import android.os.Handler; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.mogo.module.common.entity.MarkerCarInfo; +import com.mogo.module.common.entity.V2XPushMessageEntity; +import com.mogo.module.v2x.R; +import com.mogo.module.v2x.V2XServiceManager; +import com.mogo.module.v2x.listener.V2XWindowStatusListener; +import com.mogo.module.v2x.scenario.view.IV2XWindow; +import com.mogo.module.v2x.view.V2XCrossRoadVideoView; +import com.mogo.utils.logger.Logger; + +import static com.mogo.module.v2x.V2XConst.MODULE_NAME; + +public class V2XVoiceCrossRoadLiveWindow extends RelativeLayout + implements IV2XWindow { + + private V2XCrossRoadVideoView mV2XCrossRoadVideoView; + private TextView tvCountDown; + private ImageView ivVideoPlayingSign; + private boolean isVideoPlay = false; + + // 处理道路事件,30秒倒计时 + private Handler handlerV2XEvent = new Handler(); + private Runnable runnableV2XEvent; + private static final int COUNT_DOWN_TIMER = 1_000; + private static final int ALL_EXPIRE_TIMER = 1_000 * 30; + private static int EXPIRE_TIMER = ALL_EXPIRE_TIMER; + + public V2XVoiceCrossRoadLiveWindow() { + this(V2XServiceManager.getContext(), null); + Logger.d(MODULE_NAME, "V2XVoiceCallLiveCarWindow INIT"); + } + + public V2XVoiceCrossRoadLiveWindow(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public V2XVoiceCrossRoadLiveWindow(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(context); + } + + private void initView(Context context) { + Logger.w(MODULE_NAME, "V2X===初始化语音呼叫直播视图"); + LayoutInflater.from(context).inflate(R.layout.window_see_crossroadlive_video, this); + mV2XCrossRoadVideoView = findViewById(R.id.videoPlayer); + tvCountDown = findViewById(R.id.tvCountDown); + ivVideoPlayingSign = findViewById(R.id.ivVideoPlayingSign); + mV2XCrossRoadVideoView.addOnVideoStatusChangeListener(videoPlaying -> { + isVideoPlay = videoPlaying; + if (isVideoPlay) { + startCountDown(); + } else { + stopCountDown(); + } + }); + } + + @Override + public void show(V2XPushMessageEntity entity) { + if (entity != null) { + Logger.w(MODULE_NAME, "更新直播信息。。。。。" + entity); + // 启动播放 + MarkerCarInfo.CarLiveInfo carLiveInfo = new MarkerCarInfo.CarLiveInfo(); + carLiveInfo.setVideoChannel(entity.getVideoChannel()); + carLiveInfo.setVideoSn(entity.getVideoSn()); + carLiveInfo.setVideoUrl(entity.getVideoUrl()); + Logger.w(MODULE_NAME, "更新直播信息 END"); + mV2XCrossRoadVideoView.setCarLiveInfo(carLiveInfo); + if (isVideoPlay) { + startCountDown(); + } + } + } + + @Override + public void close() { + // 停止倒计时 + stopCountDown(); + if (V2XServiceManager + .getMogoTopViewManager().isViewAdded(this)) { + //移除窗体 + V2XServiceManager + .getMogoTopViewManager() + .removeView(this); + } + } + + @Override + public View getView() { + return this; + } + + @Override + public void setWindowStatusListener(V2XWindowStatusListener listener) { + + } + + /** + * 窗体倒计时 + */ + private void startCountDown() { + // 倒计时 + if (runnableV2XEvent == null) { + runnableV2XEvent = () -> { + EXPIRE_TIMER = EXPIRE_TIMER - COUNT_DOWN_TIMER; + Logger.d(MODULE_NAME, "V2X=== Window 30秒倒计时开始,当前 :" + EXPIRE_TIMER / COUNT_DOWN_TIMER + " 秒"); + tvCountDown.setVisibility(View.VISIBLE); + ivVideoPlayingSign.setVisibility(View.VISIBLE); + tvCountDown.setText(String.valueOf(EXPIRE_TIMER / COUNT_DOWN_TIMER)); + if (EXPIRE_TIMER > 0) { + handlerV2XEvent.postDelayed(runnableV2XEvent, COUNT_DOWN_TIMER); + } else { + Logger.d(MODULE_NAME, "V2X=== Window 30秒倒计时结束。。。"); + // 移出Window详细信息 + close(); + } + }; + } else { + handlerV2XEvent.removeCallbacks(runnableV2XEvent); + } + Logger.d(MODULE_NAME, "V2X=== Window 展示开始倒计时"); + handlerV2XEvent.postDelayed(runnableV2XEvent, COUNT_DOWN_TIMER); + } + + private void stopCountDown() { + Logger.d(MODULE_NAME, "V2X=== Window 倒计时停止。。。"); + if (handlerV2XEvent != null && runnableV2XEvent != null) { + handlerV2XEvent.removeCallbacks(runnableV2XEvent); + runnableV2XEvent = null; + tvCountDown.setVisibility(View.GONE); + ivVideoPlayingSign.setVisibility(View.GONE); + EXPIRE_TIMER = ALL_EXPIRE_TIMER; + } + } +} diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/view/SimpleCoverVideoPlayer.kt b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/view/SimpleCoverVideoPlayer.kt new file mode 100644 index 0000000000..1fbf84639a --- /dev/null +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/view/SimpleCoverVideoPlayer.kt @@ -0,0 +1,178 @@ +package com.mogo.module.v2x.view + +import android.content.Context +import android.util.AttributeSet +import android.view.Surface +import android.view.View +import android.widget.ImageView +import com.mogo.module.v2x.R +import com.shuyu.gsyvideoplayer.GSYVideoManager +import com.shuyu.gsyvideoplayer.utils.GSYVideoType +import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer +import com.shuyu.gsyvideoplayer.video.base.GSYVideoView +import com.shuyu.gsyvideoplayer.video.base.GSYVideoViewBridge + +class SimpleCoverVideoPlayer : StandardGSYVideoPlayer { + + companion object { + const val PLAY_EVT_PLAY_LOADING = 1000 + const val PLAY_EVT_PLAY_BEGIN = 2000 + const val PLAY_EVT_PLAY_ERROR = 3000 + } + + private var playListener: PlayListener? = null + private lateinit var start: ImageView + + interface PlayListener { + fun onPlayEvent(event: Int) + } + + constructor(context: Context?) : super(context) + constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) + constructor(context: Context?, fullFlag: Boolean?) : super(context, fullFlag) + + override fun init(context: Context) { + super.init(context) + start = findViewById(R.id.start) + if (mThumbImageViewLayout != null + && (mCurrentState == -1 || mCurrentState == GSYVideoView.CURRENT_STATE_NORMAL || mCurrentState == GSYVideoView.CURRENT_STATE_ERROR) + ) { + mThumbImageViewLayout.visibility = View.VISIBLE + } + } + + override fun getLayoutId(): Int { + return R.layout.item_v2x_crossroad_live_video + } + + override fun getGSYVideoManager(): GSYVideoViewBridge { + GSYVideoManager.instance().initContext(context.applicationContext) + return GSYVideoManager.instance() + } + + override fun setProgressAndTime( + progress: Int, + secProgress: Int, + currentTime: Int, + totalTime: Int, + forceChange: Boolean + ) { + super.setProgressAndTime(progress, secProgress, currentTime, totalTime, forceChange) + if (progress != 0) { + mProgressBar?.progress = progress + } + } + + fun setPlayListener(listener: PlayListener) { + this.playListener = listener + } + + override fun updateStartImage() { + } + + override fun changeUiToCompleteShow() { + super.changeUiToCompleteShow() + mBottomContainer?.visibility = View.INVISIBLE + mProgressBar?.visibility = View.GONE + } + + override fun hideAllWidget() { + super.hideAllWidget() + mBottomContainer?.visibility = View.INVISIBLE + mProgressBar?.visibility = View.GONE + } + + override fun changeUiToPrepareingClear() { + super.changeUiToPrepareingClear() + mBottomContainer?.visibility = View.INVISIBLE + mProgressBar?.visibility = View.GONE + } + + override fun changeUiToPlayingBufferingClear() { + super.changeUiToPlayingBufferingClear() + mBottomContainer?.visibility = View.INVISIBLE + mProgressBar?.visibility = View.GONE + + } + + override fun changeUiToClear() { + super.changeUiToClear() + mBottomContainer?.visibility = View.INVISIBLE + mProgressBar?.visibility = View.GONE + } + + override fun changeUiToCompleteClear() { + super.changeUiToCompleteClear() + mBottomContainer?.visibility = View.INVISIBLE + mProgressBar?.visibility = View.GONE + } + + override fun onAutoCompletion() { + super.onAutoCompletion() + mProgressBar?.progress = 0 + } + + override fun showWifiDialog() { + //直接播放,不显示WIFI对话框 + startPlayLogic() + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + mProgressBar?.progress = 0 + mFullPauseBitmap = null + } + + override fun onClick(v: View?) { + super.onClick(v) + } + + override fun onCompletion() { + isPostBufferUpdate = false + } + + override fun onSurfaceUpdated(surface: Surface) { + super.onSurfaceUpdated(surface) + if (mThumbImageViewLayout != null && mThumbImageViewLayout.visibility == View.VISIBLE) { + mThumbImageViewLayout.visibility = View.INVISIBLE + } + } + + override fun onPrepared() { + super.onPrepared() + playListener?.onPlayEvent(PLAY_EVT_PLAY_LOADING) + } + + private var isPostBufferUpdate = false + + override fun onBufferingUpdate(percent: Int) { + super.onBufferingUpdate(percent) + if (!isPostBufferUpdate && percent == 0) { + isPostBufferUpdate = true + playListener?.onPlayEvent(PLAY_EVT_PLAY_BEGIN) + } + } + + override fun onError(what: Int, extra: Int) { + super.onError(what, extra) + playListener?.onPlayEvent(PLAY_EVT_PLAY_ERROR) + isPostBufferUpdate = false + } + + override fun setViewShowState(view: View?, visibility: Int) { + if (view === mThumbImageViewLayout && visibility != View.VISIBLE) { + return + } + super.setViewShowState(view, visibility) + } + + override fun onSurfaceAvailable(surface: Surface) { + super.onSurfaceAvailable(surface) + mProgressBar?.visibility = View.GONE + if (GSYVideoType.getRenderType() != GSYVideoType.TEXTURE) { + if (mThumbImageViewLayout != null && mThumbImageViewLayout.visibility == View.VISIBLE) { + mThumbImageViewLayout.visibility = View.INVISIBLE + } + } + } +} \ No newline at end of file diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/view/V2XCarLiveVideoView.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/view/V2XCarLiveVideoView.java new file mode 100644 index 0000000000..9db24bde03 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/view/V2XCarLiveVideoView.java @@ -0,0 +1,280 @@ +package com.mogo.module.v2x.view; + +import android.content.Context; +import android.content.Intent; +import android.graphics.PorterDuff; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ProgressBar; +import android.widget.TextView; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.content.ContextCompat; + +import com.mogo.commons.AbsMogoApplication; +import com.mogo.commons.voice.AIAssist; +import com.mogo.module.common.entity.MarkerCarInfo; +import com.mogo.module.v2x.R; +import com.mogo.module.v2x.V2XServiceManager; +import com.mogo.module.v2x.entity.net.V2XLivePushVoRes; +import com.mogo.module.v2x.network.V2XRefreshCallback; +import com.mogo.module.v2x.utils.V2XUtils; +import com.mogo.module.v2x.voice.V2XVoiceCallbackListener; +import com.mogo.module.v2x.voice.V2XVoiceConstants; +import com.mogo.module.v2x.voice.V2XVoiceManager; +import com.mogo.utils.logger.Logger; +import com.tencent.rtmp.ITXLivePlayListener; +import com.tencent.rtmp.TXLiveConstants; +import com.tencent.rtmp.TXLivePlayer; +import com.tencent.rtmp.ui.TXCloudVideoView; + +import static com.mogo.module.v2x.V2XConst.MODULE_NAME; + +/** + * author : donghongyu + * e-mail : 1358506549@qq.com + * date : 2020-02-0623:07 + * desc : + * version: 1.0 + */ +public class V2XCarLiveVideoView extends RoundLayout { + private final String TAG = "V2XLiveGSYVideoView"; + + private TXCloudVideoView mTxcVideoView; + private ProgressBar mLoading; + private TXLivePlayer mLivePlayer; + private ConstraintLayout mClLoadError; + private TextView mTvRefreshButton; + + private MarkerCarInfo.CarLiveInfo mCarLiveInfo; + // 重新刷新直播流 + private V2XVoiceCallbackListener v2XVoiceCallbackRefreshListener = new V2XVoiceCallbackListener() { + @Override + public void onCallback(String command, Intent intent) { + mLoading.setVisibility(VISIBLE); + mClLoadError.setVisibility(GONE); + if (mCarLiveInfo != null) { + startLive(mCarLiveInfo); + } + } + }; + + public V2XCarLiveVideoView(Context context) { + this(context, null); + } + + public V2XCarLiveVideoView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public V2XCarLiveVideoView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(context); + } + + private void initView(Context context) { + LayoutInflater.from(context) + .inflate(R.layout.view_video_layout_see_live, this); + //mPlayerView 即 step1 中添加的界面 view + mTxcVideoView = findViewById(R.id.txcVideoView); + //创建 player 对象 + mLivePlayer = new TXLivePlayer(context); + //关键 player 对象与界面 view + mLivePlayer.setPlayerView(mTxcVideoView); + mLivePlayer.setMute(true); + mLivePlayer.enableHardwareDecode(true); + + mLoading = findViewById(R.id.loading); + mLoading.getIndeterminateDrawable().setColorFilter(ContextCompat.getColor(context, R.color.live_video_progress_bar_loading_color), PorterDuff.Mode.MULTIPLY); + + mClLoadError = findViewById(R.id.clLoadError); + mTvRefreshButton = findViewById(R.id.tvRefreshButton); + mTvRefreshButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mLoading.setVisibility(VISIBLE); + mClLoadError.setVisibility(GONE); + if (mCarLiveInfo != null) { + startLive(mCarLiveInfo); + } + } + }); + } + + /** + * 设置直播信息 + */ + public void setCarLiveInfo(MarkerCarInfo.CarLiveInfo carLiveInfo) { + mCarLiveInfo = carLiveInfo; + } + + /** + * 开始直播 + * + * @param carLiveInfo 要直播的车机,如果没有直播的地址需要重新获取最新的直播地址 + */ + public void startLive(MarkerCarInfo.CarLiveInfo carLiveInfo) { + // 进行直播播放 + if (mLivePlayer != null + && carLiveInfo != null) { + if (!TextUtils.isEmpty(carLiveInfo.getVideoUrl())) { + AIAssist.getInstance(AbsMogoApplication.getApp()).speakTTSVoice(AbsMogoApplication.getApp().getString(R.string.v2x_voice_see_front_car_live)); + setCarLiveInfo(carLiveInfo); + playLiveVideo(carLiveInfo); + } + // 根据SN重新获取直播流地址 + else { + V2XServiceManager + .getV2XRefreshModel() + .livePush(new V2XRefreshCallback() { + @Override + public void onSuccess(V2XLivePushVoRes result) { + AIAssist.getInstance(AbsMogoApplication.getApp()).speakTTSVoice(AbsMogoApplication.getApp().getString(R.string.v2x_voice_see_front_car_live)); + mClLoadError.setVisibility(GONE); + mClLoadError.setVisibility(GONE); + try { + MarkerCarInfo.CarLiveInfo carRealLiveInfo = new MarkerCarInfo.CarLiveInfo(); + carRealLiveInfo.setVideoUrl(result.getResult().getPlayUrl().getRtmp()); + carRealLiveInfo.setVideoSn(carLiveInfo.getVideoSn()); + carRealLiveInfo.setVideoChannel(result.getResult().getVideoChannel()); + setCarLiveInfo(carLiveInfo); + playLiveVideo(carRealLiveInfo); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void onFail(String msg) { + Logger.e(MODULE_NAME, "播放器:" + msg); + AIAssist.getInstance(AbsMogoApplication.getApp()).speakTTSVoice(AbsMogoApplication.getApp().getString(R.string.v2x_voice_see_front_car_live_error)); + mLoading.setVisibility(GONE); + mClLoadError.setVisibility(VISIBLE); + } + }, carLiveInfo.getVideoSn(), 0); + } + } + } + + /** + * 播放直播流,且开始心跳 + */ + private void playLiveVideo(MarkerCarInfo.CarLiveInfo carLiveInfo) { + startHeartLive(carLiveInfo); + if (mLivePlayer != null) { + mLivePlayer.startPlay(carLiveInfo.getVideoUrl(), TXLivePlayer.PLAY_TYPE_LIVE_RTMP); + mLivePlayer.setPlayListener(new ITXLivePlayListener() { + @Override + public void onPlayEvent(int event, Bundle bundle) { + Logger.w(MODULE_NAME, "播放器:onPlayEvent==" + event + "===bundle===" + bundle); + if (event == TXLiveConstants.PLAY_EVT_PLAY_LOADING) { + mLoading.setVisibility(VISIBLE); + mClLoadError.setVisibility(GONE); + } else if (event == TXLiveConstants.PLAY_EVT_PLAY_BEGIN) { + refreshStatusToListener(true); + mLoading.setVisibility(GONE); + mClLoadError.setVisibility(GONE); + } else if (event < 0) { + refreshStatusToListener(false); + AIAssist.getInstance(V2XUtils.getApp()).speakTTSVoice("直播获取识败,可以对我说重试", null); + stopLive(mCarLiveInfo); + mLoading.setVisibility(GONE); + mClLoadError.setVisibility(VISIBLE); + // 注册语音交互 + V2XVoiceManager.INSTANCE + .registerWakeCmd(V2XVoiceConstants.COMMAND_ZHIDAO_V2X_REFRESH_CAR_LIVE, + v2XVoiceCallbackRefreshListener) + .registerUnWakeVoice(V2XVoiceConstants.COMMAND_ZHIDAO_V2X_REFRESH_LIVE_UN_WAKEUP, + v2XVoiceCallbackRefreshListener); + } + } + + @Override + public void onNetStatus(Bundle bundle) { + //Logger.w(MODULE_NAME, "播放器:onNetStatus===bundle===" + bundle); + } + }); + } + } + + // 刷新直播心跳 + private void startHeartLive(MarkerCarInfo.CarLiveInfo carLiveInfo) { + try { + if (!TextUtils.isEmpty(carLiveInfo.getVideoSn()) + && !TextUtils.isEmpty(carLiveInfo.getVideoChannel())) { + V2XServiceManager + .getV2XRefreshModel() + .refreshHeartBeat(carLiveInfo.getVideoSn(), + carLiveInfo.getVideoChannel(), + null); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void stopLive(MarkerCarInfo.CarLiveInfo carLiveInfo) { + try { + Logger.w(MODULE_NAME, "心跳:关闭直播..."); + // 暂停 + mLivePlayer.pause(); + // true 代表清除最后一帧画面 + mLivePlayer.stopPlay(true); + mTxcVideoView.onDestroy(); + // 停止推流 + V2XServiceManager + .getV2XRefreshModel() + .livePush(new V2XRefreshCallback() { + @Override + public void onSuccess(V2XLivePushVoRes result) { + Logger.d(MODULE_NAME, "播放器:" + result); + } + + @Override + public void onFail(String msg) { + Logger.e(MODULE_NAME, "播放器:" + msg); + } + }, carLiveInfo.getVideoSn(), 1); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (mCarLiveInfo != null) { + startLive(mCarLiveInfo); + } + } + + @Override + protected void onDetachedFromWindow() { + stopLive(mCarLiveInfo); + mLoading.setVisibility(VISIBLE); + // 反注册语音交互 + V2XVoiceManager.INSTANCE + .unRegisterWakeCmd(V2XVoiceConstants.COMMAND_ZHIDAO_V2X_REFRESH_CAR_LIVE) + .unRegisterUnWakeVoice(V2XVoiceConstants.COMMAND_ZHIDAO_V2X_REFRESH_LIVE_UN_WAKEUP); + super.onDetachedFromWindow(); + } + + private void refreshStatusToListener(boolean videoPlaying) { + if (onVideoStatusChange != null) { + onVideoStatusChange.videoPlaying(videoPlaying); + } + } + + private OnVideoStatusChange onVideoStatusChange; + + public void addOnVideoStatusChangeListener(OnVideoStatusChange onVideoStatusChange) { + this.onVideoStatusChange = onVideoStatusChange; + } + + public interface OnVideoStatusChange { + void videoPlaying(boolean videoPlaying); + } +} diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/view/V2XCrossRoadVideoView.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/view/V2XCrossRoadVideoView.java new file mode 100644 index 0000000000..2bdac21791 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/view/V2XCrossRoadVideoView.java @@ -0,0 +1,263 @@ +package com.mogo.module.v2x.view; + +import android.content.Context; +import android.content.Intent; +import android.graphics.PorterDuff; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.widget.ProgressBar; +import android.widget.TextView; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.content.ContextCompat; + +import com.mogo.commons.AbsMogoApplication; +import com.mogo.commons.voice.AIAssist; +import com.mogo.module.common.entity.MarkerCarInfo; +import com.mogo.module.v2x.R; +import com.mogo.module.v2x.entity.net.V2XLiveCrossRoad; +import com.mogo.module.v2x.network.V2XRefreshCallback; +import com.mogo.module.v2x.network.V2XRefreshModel; +import com.mogo.module.v2x.utils.V2XUtils; +import com.mogo.module.v2x.voice.V2XVoiceCallbackListener; +import com.mogo.module.v2x.voice.V2XVoiceConstants; +import com.mogo.module.v2x.voice.V2XVoiceManager; +import com.mogo.utils.logger.Logger; +import com.shuyu.gsyvideoplayer.GSYVideoManager; +import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder; +import com.shuyu.gsyvideoplayer.cache.CacheFactory; +import com.shuyu.gsyvideoplayer.cache.ProxyCacheManager; +import com.shuyu.gsyvideoplayer.model.VideoOptionModel; +import com.shuyu.gsyvideoplayer.player.IjkPlayerManager; +import com.shuyu.gsyvideoplayer.player.PlayerFactory; +import com.shuyu.gsyvideoplayer.utils.GSYVideoType; + +import java.util.ArrayList; +import java.util.List; + +import tv.danmaku.ijk.media.player.IjkMediaPlayer; + +import static com.mogo.module.v2x.V2XConst.MODULE_NAME; +import static com.mogo.module.v2x.view.SimpleCoverVideoPlayer.PLAY_EVT_PLAY_BEGIN; +import static com.mogo.module.v2x.view.SimpleCoverVideoPlayer.PLAY_EVT_PLAY_LOADING; + +/** + * author : donghongyu + * e-mail : 1358506549@qq.com + * date : 2020-02-0623:07 + * desc : + * version: 1.0 + */ +public class V2XCrossRoadVideoView extends RoundLayout { + + private static final String TAG = "CrossRoadVideo"; + + private SimpleCoverVideoPlayer mTxcVideoView; + private GSYVideoOptionBuilder gsyVideoOptionBuilder = new GSYVideoOptionBuilder(); + private ProgressBar mLoading; + private ConstraintLayout mClLoadError; + private TextView mTvRefreshButton; + private boolean init = false; + + private MarkerCarInfo.CarLiveInfo mCarLiveInfo; + // 重新刷新直播流 + private V2XVoiceCallbackListener v2XVoiceCallbackRefreshListener = new V2XVoiceCallbackListener() { + @Override + public void onCallback(String command, Intent intent) { + mLoading.setVisibility(VISIBLE); + mClLoadError.setVisibility(GONE); + if (mCarLiveInfo != null) { + startLive(mCarLiveInfo); + } + } + }; + + public V2XCrossRoadVideoView(Context context) { + this(context, null); + } + + public V2XCrossRoadVideoView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public V2XCrossRoadVideoView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(context); + } + + private void initView(Context context) { + if(init){ + return; + } + Logger.d("V2XCrossRoadVideoView", "V2X===初始化语音呼叫路口直播视图"); + LayoutInflater.from(context) + .inflate(R.layout.view_video_layout_see_crossroad, this); + //mPlayerView 即 step1 中添加的界面 view + mTxcVideoView = findViewById(R.id.txcVideoView); + initGSYVideoConfig(); + + mLoading = findViewById(R.id.loading); + mLoading.getIndeterminateDrawable().setColorFilter(ContextCompat.getColor(context, R.color.live_video_progress_bar_loading_color), PorterDuff.Mode.MULTIPLY); + + mClLoadError = findViewById(R.id.clLoadError); + mTvRefreshButton = findViewById(R.id.tvRefreshButton); + mTvRefreshButton.setOnClickListener(v -> { + mLoading.setVisibility(VISIBLE); + mClLoadError.setVisibility(GONE); + if (mCarLiveInfo != null) { + startLive(mCarLiveInfo); + } + }); + init = true; + } + + private void initGSYVideoConfig() { + PlayerFactory.setPlayManager(IjkPlayerManager.class); + CacheFactory.setCacheManager(ProxyCacheManager.class); + List list = new ArrayList<>(); + list.add(new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp")); + list.add(new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_flags", "prefer_tcp")); + list.add(new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "allowed_media_types", "video")); + list.add(new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "timeout", 20000)); + list.add(new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "buffer_size", 1316)); + + list.add(new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "infbuf", 1)); + list.add(new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzeduration", 1)); + + list.add(new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 10240)); + list.add(new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", 1)); + list.add(new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_clear", 1)); + list.add(new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_timeout", -1)); + list.add(new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzeduration",1)); + list.add(new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "packet-buffering", 0)); + list.add(new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "reconnect",10)); + + GSYVideoManager.instance().setOptionModelList(list); + GSYVideoType.enableMediaCodec(); + GSYVideoType.enableMediaCodecTexture(); + GSYVideoType.setShowType(GSYVideoType.SCREEN_MATCH_FULL); + } + + /** + * 设置直播信息 + */ + public void setCarLiveInfo(MarkerCarInfo.CarLiveInfo carLiveInfo) { + mCarLiveInfo = carLiveInfo; + } + + /** + * 开始直播 + * + * @param carLiveInfo 要直播的车机,如果没有直播的地址需要重新获取最新的直播地址 + */ + public void startLive(MarkerCarInfo.CarLiveInfo carLiveInfo) { + initView(this.getContext()); + // 进行直播播放 + if (mTxcVideoView != null + && carLiveInfo != null) { + if (!TextUtils.isEmpty(carLiveInfo.getVideoUrl())) { + setCarLiveInfo(carLiveInfo); + playLiveVideo(carLiveInfo); + } + //重新获取直播流地址 + else { + V2XRefreshModel.getInstance(AbsMogoApplication.getApp()).queryCrossRoadsLive(new V2XRefreshCallback() { + @Override + public void onSuccess(V2XLiveCrossRoad result) { + if (result != null && result.getResult().getUrl() != null) { + String liveUrl = result.getResult().getUrl(); + MarkerCarInfo.CarLiveInfo carLiveInfo = new MarkerCarInfo.CarLiveInfo(); + carLiveInfo.setVideoUrl(liveUrl); + setCarLiveInfo(carLiveInfo); + playLiveVideo(carLiveInfo); + } else { + Logger.d(MODULE_NAME, "startLive 路口实况直播地址为空"); + } + } + + @Override + public void onFail(String msg) { + //获取路口实况失败 + Logger.d(MODULE_NAME, "获取路口实况失败"); + } + }); + } + } + } + + /** + * 播放直播流,且开始心跳 + */ + private void playLiveVideo(MarkerCarInfo.CarLiveInfo carLiveInfo) { + if (mTxcVideoView != null) { + mTxcVideoView.setPlayListener(event -> { + Logger.w(MODULE_NAME, "播放器:onPlayEvent==" + event); + if (event == PLAY_EVT_PLAY_LOADING) { + mLoading.setVisibility(VISIBLE); + mClLoadError.setVisibility(GONE); + } else if (event == PLAY_EVT_PLAY_BEGIN) { + refreshStatusToListener(true); + mLoading.setVisibility(GONE); + mClLoadError.setVisibility(GONE); + } else if (event < 0) { + refreshStatusToListener(false); + AIAssist.getInstance(V2XUtils.getApp()).speakTTSVoice("直播获取识败,可以对我说重试", null); + stopLive(); + mLoading.setVisibility(GONE); + mClLoadError.setVisibility(VISIBLE); + // 注册语音交互 + V2XVoiceManager.INSTANCE + .registerUnWakeVoice(V2XVoiceConstants.COMMAND_ZHIDAO_V2X_REFRESH_LIVE_UN_WAKEUP, + v2XVoiceCallbackRefreshListener); + } + }); + gsyVideoOptionBuilder.setUrl(carLiveInfo.getVideoUrl()).setCacheWithPlay(false).setPlayTag(TAG) + .build(mTxcVideoView); + mTxcVideoView.getStartButton().performClick(); + } + } + + public void stopLive() { + try { + Logger.w(MODULE_NAME, "关闭直播..."); + GSYVideoManager.releaseAllVideos(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (mCarLiveInfo != null) { + startLive(mCarLiveInfo); + } + } + + @Override + protected void onDetachedFromWindow() { + stopLive(); + mLoading.setVisibility(VISIBLE); + // 反注册语音交互 + V2XVoiceManager.INSTANCE + .unRegisterUnWakeVoice(V2XVoiceConstants.COMMAND_ZHIDAO_V2X_REFRESH_LIVE_UN_WAKEUP); + super.onDetachedFromWindow(); + } + + private void refreshStatusToListener(boolean videoPlaying) { + if (onVideoStatusChange != null) { + onVideoStatusChange.videoPlaying(videoPlaying); + } + } + + private OnVideoStatusChange onVideoStatusChange; + + public void addOnVideoStatusChangeListener(OnVideoStatusChange onVideoStatusChange) { + this.onVideoStatusChange = onVideoStatusChange; + } + + public interface OnVideoStatusChange { + void videoPlaying(boolean videoPlaying); + } +} diff --git a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/voice/V2XVoiceConstants.java b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/voice/V2XVoiceConstants.java index 78aefa1956..7c96329347 100644 --- a/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/voice/V2XVoiceConstants.java +++ b/modules/mogo-module-v2x/src/main/java/com/mogo/module/v2x/voice/V2XVoiceConstants.java @@ -86,6 +86,16 @@ public class V2XVoiceConstants { */ public static final String COMMAND_ZHIDAO_V2X_REFRESH_CAR_LIVE = "com.zhidao.user.action.retry"; + /** + * 唤醒词:查看前车视频 + */ + public static final String COMMAND_ZHIDAO_V2X_AHEAD_LIVE = "com.zhidao.ahead.live"; + + /** + * 唤醒词:查看周围路口直播 + */ + public static final String COMMAND_ZHIDAO_V2X_CROSSROADS_LIVE = "com.zhidao.crossroads.live"; + /** * 应用内免唤醒 * 发起定向车聊聊 @@ -200,6 +210,19 @@ public class V2XVoiceConstants { public static final String COMMAND_ZHIDAO_V2X_ILLEGAL_PARKMARKER_FEEDBACK_YOUYONG_UN_WAKEUP = "COMMAND_ZHIDAO_V2X_ILLEGAL_PARKMARKER_FEEDBACK_YOUYONG_UN_WAKEUP"; public static final String[] COMMAND_ZHIDAO_V2X_ILLEGAL_PARKMARKER_FEEDBACK_YOUYONG_UN_WAKEUP_WORDS = {"有用"}; + /** + * 应用内免唤醒 + * "查看前车视频","查看前车直播","查看前车视角" + */ + public static final String COMMAND_ZHIDAO_V2X_CALL_FRONT_CAR_DEMO_UN_WAKEUP = "COMMAND_ZHIDAO_V2X_CALL_FRONT_CAR_DEMO_UN_WAKEUP"; + public static final String[] COMMAND_ZHIDAO_V2X_CALL_FRONT_CAR_DEMO_UN_WAKEUP_WORDS = {"查看前车视频", "查看前车直播", "查看前车视角"}; + + /** + * 应用内免唤醒 + */ + public static final String COMMAND_ZHIDAO_V2X_OPEN_ROAD_CAMERA_LIVE_UN_WAKEUP = "COMMAND_ZHIDAO_V2X_OPEN_ROAD_CAMERA_LIVE_UN_WAKEUP"; + public static final String[] COMMAND_ZHIDAO_V2X_OPEN_ROAD_CAMERA_LIVE_UN_WAKEUP_WORDS = {"查看路口实况", "查看路口直播", "查看路口视频"}; + /** * 违章停车 * 没用 @@ -252,6 +275,10 @@ public class V2XVoiceConstants { sVoiceCmds.put(COMMAND_ZHIDAO_V2X_OPEN_SURROUNDING_EVENT_UN_WAKEUP, COMMAND_ZHIDAO_V2X_OPEN_SURROUNDING_EVENT_UN_WAKEUP_WORDS); sVoiceCmds.put(COMMAND_ZHIDAO_V2X_OPEN_SHEAR_EVENT_UN_WAKEUP, COMMAND_ZHIDAO_V2X_OPEN_SHEAR_EVENT_UN_WAKEUP_WORDS); + //2020-6-24 顺义演示需求添加,现合并至launcher 更新时间:2020-08-25 + sVoiceCmds.put(COMMAND_ZHIDAO_V2X_CALL_FRONT_CAR_DEMO_UN_WAKEUP, COMMAND_ZHIDAO_V2X_CALL_FRONT_CAR_DEMO_UN_WAKEUP_WORDS); + sVoiceCmds.put(COMMAND_ZHIDAO_V2X_OPEN_ROAD_CAMERA_LIVE_UN_WAKEUP, COMMAND_ZHIDAO_V2X_OPEN_ROAD_CAMERA_LIVE_UN_WAKEUP_WORDS); + //默认 /* sCmds.add(COMMAND_ZHIDAO_V2X_CALL_CHATTING); diff --git a/modules/mogo-module-v2x/src/main/res/drawable/v2x_shape_bg_count_down_corner_14.xml b/modules/mogo-module-v2x/src/main/res/drawable/v2x_shape_bg_count_down_corner_14.xml new file mode 100644 index 0000000000..9f90c34357 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/res/drawable/v2x_shape_bg_count_down_corner_14.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/modules/mogo-module-v2x/src/main/res/layout/item_v2x_crossroad_live_video.xml b/modules/mogo-module-v2x/src/main/res/layout/item_v2x_crossroad_live_video.xml new file mode 100644 index 0000000000..938a27fd1b --- /dev/null +++ b/modules/mogo-module-v2x/src/main/res/layout/item_v2x_crossroad_live_video.xml @@ -0,0 +1,23 @@ + + + + + + + + + diff --git a/modules/mogo-module-v2x/src/main/res/layout/item_v2x_see_crossroad_live_video.xml b/modules/mogo-module-v2x/src/main/res/layout/item_v2x_see_crossroad_live_video.xml new file mode 100644 index 0000000000..50615a0a07 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/res/layout/item_v2x_see_crossroad_live_video.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/mogo-module-v2x/src/main/res/layout/item_v2x_see_frontcar_live_video.xml b/modules/mogo-module-v2x/src/main/res/layout/item_v2x_see_frontcar_live_video.xml new file mode 100644 index 0000000000..8ecc584a7d --- /dev/null +++ b/modules/mogo-module-v2x/src/main/res/layout/item_v2x_see_frontcar_live_video.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/mogo-module-v2x/src/main/res/layout/view_video_layout_see_crossroad.xml b/modules/mogo-module-v2x/src/main/res/layout/view_video_layout_see_crossroad.xml new file mode 100644 index 0000000000..9a5eda56df --- /dev/null +++ b/modules/mogo-module-v2x/src/main/res/layout/view_video_layout_see_crossroad.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + diff --git a/modules/mogo-module-v2x/src/main/res/layout/view_video_layout_see_live.xml b/modules/mogo-module-v2x/src/main/res/layout/view_video_layout_see_live.xml new file mode 100644 index 0000000000..0ad6257f83 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/res/layout/view_video_layout_see_live.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + diff --git a/modules/mogo-module-v2x/src/main/res/layout/window_see_carlive_video.xml b/modules/mogo-module-v2x/src/main/res/layout/window_see_carlive_video.xml new file mode 100644 index 0000000000..0859547799 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/res/layout/window_see_carlive_video.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/modules/mogo-module-v2x/src/main/res/layout/window_see_crossroadlive_video.xml b/modules/mogo-module-v2x/src/main/res/layout/window_see_crossroadlive_video.xml new file mode 100644 index 0000000000..02a8789b35 --- /dev/null +++ b/modules/mogo-module-v2x/src/main/res/layout/window_see_crossroadlive_video.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/modules/mogo-module-v2x/src/main/res/values-xhdpi/dimens.xml b/modules/mogo-module-v2x/src/main/res/values-xhdpi/dimens.xml index 45ca7333ff..9fe6c5b6a6 100644 --- a/modules/mogo-module-v2x/src/main/res/values-xhdpi/dimens.xml +++ b/modules/mogo-module-v2x/src/main/res/values-xhdpi/dimens.xml @@ -4,11 +4,13 @@ 32px 32px + 1060px 350px 450px 390px 220px + 670px 147px diff --git a/modules/mogo-module-v2x/src/main/res/values/dimens.xml b/modules/mogo-module-v2x/src/main/res/values/dimens.xml index c6458087a1..9533e2707f 100644 --- a/modules/mogo-module-v2x/src/main/res/values/dimens.xml +++ b/modules/mogo-module-v2x/src/main/res/values/dimens.xml @@ -4,11 +4,13 @@ 18px 20px + 642px 194px 250px 190px 130px + 670px 82px diff --git a/modules/mogo-module-v2x/src/main/res/values/strings.xml b/modules/mogo-module-v2x/src/main/res/values/strings.xml index 2413b8f3d5..bb63975aa1 100644 --- a/modules/mogo-module-v2x/src/main/res/values/strings.xml +++ b/modules/mogo-module-v2x/src/main/res/values/strings.xml @@ -8,5 +8,9 @@ 周围5公里,共 %d 条交通信息 去分享 刷新 + 小智已为您查询到前方最近车辆直播视频,请查看 + 诶呀呀,没有查到前方车辆直播视屏,过一会再试试吧 + 已为您打开路口直播实况 + 诶呀呀,周围没有可用路口实况直播