merge shunyi func

This commit is contained in:
unknown
2020-08-25 17:27:56 +08:00
parent 609aede0c6
commit 24988cce45
28 changed files with 1819 additions and 14 deletions

View File

@@ -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状态

View File

@@ -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 +
'}';
}
}
}

View File

@@ -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<BaseData> respondingToHelp(@FieldMap Map<String, Object> params);
/**
* 查询路口实况
*/
@FormUrlEncoded
@POST("/yycp-geo-fence-carService/car/camera/no/nextTest/v1")
// @POST("/yycp-geo-fence-carService/car/camera/no/next/v1")
Observable<V2XLiveCrossRoad> queryCrossRoadsLive(@FieldMap Map<String, Object> parameters);
}

View File

@@ -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<V2XLiveCrossRoad> callback) {
if (mV2XApiService != null) {
final Map<String, Object> 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<V2XLiveCrossRoad>(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);
}
}
});
}
}
}

View File

@@ -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消息类型未定义");

View File

@@ -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<V2XPushMessageEntity> 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<V2XPushMessageEntity> v2XMessageEntity = buildCallLiveParams(null, liveUrl);
V2XVoiceCallLiveScenario.getInstance().setV2XWindow(new V2XVoiceCrossRoadLiveWindow());
V2XVoiceCallLiveScenario.getInstance().init(v2XMessageEntity);
// V2XRefreshModel.getInstance(mContext).queryCrossRoadsLive(new V2XRefreshCallback<V2XLiveCrossRoad>() {
// @Override
// public void onSuccess(V2XLiveCrossRoad result) {
// if (result != null && result.getResult().getUrl() != null) {
// String liveUrl = result.getResult().getUrl();
// V2XMessageEntity<V2XPushMessageEntity> 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<V2XPushMessageEntity> buildCallLiveParams(String sn, String liveUrl) {
V2XPushMessageEntity v2XPushMessageEntity = new V2XPushMessageEntity();
v2XPushMessageEntity.setVideoSn(sn);
v2XPushMessageEntity.setVideoUrl(liveUrl);
v2XPushMessageEntity.setShowWindow(true);
V2XMessageEntity<V2XPushMessageEntity> v2XMessageEntity = new V2XMessageEntity<>();
v2XMessageEntity.setType(V2XMessageEntity.V2XTypeEnum.ALERT_VOICE_CALL_FOR_LIVECAR_SHOW);
v2XMessageEntity.setContent(v2XPushMessageEntity);
v2XMessageEntity.setShowState(true);
return v2XMessageEntity;
}
}

View File

@@ -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<V2XPushMessageEntity> {
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;
}
}
}

View File

@@ -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<V2XPushMessageEntity> 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<V2XPushMessageEntity> 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);
}
}

View File

@@ -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<V2XPushMessageEntity> {
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;
}
}
}

View File

@@ -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
}
}
}
}

View File

@@ -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<V2XLivePushVoRes>() {
@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<V2XLivePushVoRes>() {
@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);
}
}

View File

@@ -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<VideoOptionModel> 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<V2XLiveCrossRoad>() {
@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);
}
}

View File

@@ -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);