This commit is contained in:
unknown
2020-07-09 14:57:02 +08:00
51 changed files with 1544 additions and 131 deletions

2
.idea/misc.xml generated
View File

@@ -4,7 +4,7 @@
<asm skipDebug="false" skipFrames="false" skipCode="false" expandFrames="false" />
<groovy codeStyle="LEGACY" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
</project>

View File

@@ -134,6 +134,10 @@ android {
buildConfigField 'int', 'NET_ENV', '4'
}
}
packagingOptions {
exclude 'META-INF/io.netty.versions.properties'
}
}
def generateVersionCode() {

View File

@@ -3,6 +3,7 @@ package com.mogo.utils;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.text.TextUtils;
@@ -46,4 +47,14 @@ public class AppUtils {
return true;
}
}
public static String getApplicationLabel( Context context, String pkgName ) {
try {
PackageManager pm = context.getPackageManager();
ApplicationInfo appInfo = pm.getApplicationInfo( pkgName, PackageManager.GET_META_DATA );
return pm.getApplicationLabel( appInfo ).toString();
} catch ( Exception e ) {
return null;
}
}
}

View File

@@ -27,43 +27,40 @@ PASSWORD=xintai2018
RELEASE=false
# 模块版本
## 工程内模块
MOGO_COMMONS_VERSION=1.2.1.11
MOGO_UTILS_VERSION=1.2.1.11
MAP_AMAP_VERSION=1.2.1.11
MAP_AUTONAVI_VERSION=1.2.1.11
MOGO_MAP_VERSION=1.2.1.11
MOGO_MAP_API_VERSION=1.2.1.11
MOGO_SERVICE_VERSION=1.2.1.11
MOGO_SERVICE_API_VERSION=1.2.1.11
MOGO_CONNECTION_VERSION=1.2.1.11
MOGO_MODULE_APPS_VERSION=1.2.1.11
MOGO_MODULE_NAVI_VERSION=1.2.1.11
MOGO_MODULE_SHARE_VERSION=1.2.1.11
MOGO_MODULE_COMMON_VERSION=1.2.1.11
MOGO_MODULE_MAIN_VERSION=1.2.1.11
MOGO_MODULE_MAP_VERSION=1.2.1.11
MOGO_MODULE_SERVICE_VERSION=1.2.1.11
MOGO_MODULE_EXTENSIONS_VERSION=1.2.1.11
MOGO_MODULE_SEARCH_VERSION=1.2.1.11
MOGO_MODULE_BACK_VERSION=1.2.1.11
MOGO_MODULE_GPS_SIMULATOR_VERSION=1.2.1.11
MOGO_MODULE_GPS_SIMULATOR_DEBUG_VERSION=1.2.1.11
MOGO_MODULE_GPS_SIMULATOR_NOOP_VERSION=1.2.1.11
MOGO_MODULE_AUTHORIZE_VERSION=1.2.1.11
MOGO_MODULE_GUIDE_VERSION=1.2.1.11
MOGO_MODULE_MEDIA_VERSION=1.2.1.11
MOGO_COMMONS_VERSION=1.2.1.13
MOGO_UTILS_VERSION=1.2.1.13
MAP_AMAP_VERSION=1.2.1.13
MAP_AUTONAVI_VERSION=1.2.1.13
MOGO_MAP_VERSION=1.2.1.13
MOGO_MAP_API_VERSION=1.2.1.13
MOGO_SERVICE_VERSION=1.2.1.13
MOGO_SERVICE_API_VERSION=1.2.1.13
MOGO_CONNECTION_VERSION=1.2.1.13
MOGO_MODULE_APPS_VERSION=1.2.1.13
MOGO_MODULE_NAVI_VERSION=1.2.1.13
MOGO_MODULE_SHARE_VERSION=1.2.1.13
MOGO_MODULE_COMMON_VERSION=1.2.1.14
MOGO_MODULE_MAIN_VERSION=1.2.1.13
MOGO_MODULE_MAP_VERSION=1.2.1.13
MOGO_MODULE_SERVICE_VERSION=1.2.1.13
MOGO_MODULE_EXTENSIONS_VERSION=1.2.1.13
MOGO_MODULE_SEARCH_VERSION=1.2.1.13
MOGO_MODULE_BACK_VERSION=1.2.1.13
MOGO_MODULE_GPS_SIMULATOR_VERSION=1.2.1.13
MOGO_MODULE_GPS_SIMULATOR_DEBUG_VERSION=1.2.1.13
MOGO_MODULE_GPS_SIMULATOR_NOOP_VERSION=1.2.1.13
MOGO_MODULE_AUTHORIZE_VERSION=1.2.1.13
MOGO_MODULE_GUIDE_VERSION=1.2.1.13
MOGO_MODULE_MEDIA_VERSION=1.2.1.13
MOGO_MODULE_MAIN_LAUNCHER_VERSION = 1.2.1.11
MOGO_MODULE_MAIN_INDEPENDENT_VERSION = 1.2.1.11
MOGO_MODULE_MAIN_LAUNCHER_VERSION = 1.2.1.13
MOGO_MODULE_MAIN_INDEPENDENT_VERSION = 1.2.1.13
MOGO_MODULE_OBU_VERSION = 1.2.1.10-SNAPSHOT
MOGO_MODULE_LEFT_PANEL_VERSION = 1.2.1.10-SNAPSHOT
## 工程外部模块
# 探路
MOGO_MODULE_TANLU_VERSION=1.2.1.12
MOGO_MODULE_TANLU_VERSION=1.3.0.1-SNAPSHOT
# 车聊聊
CARCHATTING_VERSION=1.3.1
# 车聊聊接口
@@ -75,14 +72,18 @@ MOGO_MODULE_GUIDESHOW_PROVIDER_VERSION=1.0.2-SNAPSHOT
# 在线车辆F
MOGO_MODULE_ONLINECAR_VERSION=1.0.3.2
# v2x
MOGO_MODULE_V2X_VERSION=1.1.52
MOGO_MODULE_V2X_VERSION=1.2.3-dev
# 推送
MOGO_MODULE_PUSH_VERSION=1.0.1
# 广告资源位
MOGO_MODULE_AD_CARD_VERSION=1.0.1
# 探路上报和分享模块
TANLULIB_VERSION=1.2.1.12
TANLULIB_VERSION=1.3.0.1-SNAPSHOT
MOGO_MODULE_EVENT_PANEL_VERSION = 1.0.0-SNAPSHOT
MOGO_MODULE_EVENT_PANEL_NOOP_VERSION = 1.0.0-SNAPSHOT
#左侧面板模块
MOGO_MODULE_LEFT_PANEL_VERSION = 1.2.1.10-SNAPSHOT
MOGO_MODULE_LEFT_PANEL_NOOP_VERSION = 1.2.1.10-SNAPSHOT
# Boost分包
BOOST_MULTIDEX_VERSION=1.0.0

View File

@@ -1,6 +1,7 @@
package com.mogo.module.apps;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
@@ -9,16 +10,17 @@ import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.mogo.commons.device.Devices;
import com.mogo.commons.mvp.MvpFragment;
import com.mogo.commons.voice.AIAssist;
import com.mogo.module.apps.adapter.AppIndicatorAdapter;
import com.mogo.module.apps.anim.AnimWrapper;
import com.mogo.module.apps.applaunch.AppLauncher;
import com.mogo.module.apps.applaunch.BaseAppLauncher;
import com.mogo.module.apps.applaunch.InternalFunctionLauncher;
import com.mogo.module.apps.model.AppInfo;
import com.mogo.module.apps.model.NavigatorApps;
import com.mogo.module.apps.view.OnAiAssistClickListener;
import com.mogo.utils.AppUtils;
import com.mogo.utils.CommonUtils;
import java.util.HashMap;
import java.util.Map;
@@ -58,7 +60,7 @@ public class AppNavigatorFragment extends MvpFragment< AppNavigatorView, AppNavi
mAppIndicatorAdapter = new AppIndicatorAdapter( getContext(), NavigatorApps.getApps() );
mAppIndicatorAdapter.setOnItemClickedListener( ( data, position ) -> {
mLauncher.launch( getContext(), data );
trackNavigatorClickEvent( data.getTrackType() );
trackNavigatorClickEvent( data );
} );
mNavigatorAppsList.setAdapter( mAppIndicatorAdapter );
@@ -118,9 +120,18 @@ public class AppNavigatorFragment extends MvpFragment< AppNavigatorView, AppNavi
AppsListActivity.start( getActivity() );
}
private void trackNavigatorClickEvent( int type ) {
private void trackNavigatorClickEvent( AppInfo app ) {
final Map< String, Object > properties = new HashMap<>();
properties.put( "type", type );
String appLabel = AppUtils.getApplicationLabel( getContext(), app.getPackageName() );
properties.put( "appname", app.getName() );
if ( !TextUtils.isEmpty( appLabel ) ) {
properties.put( "appname", appLabel );
}
if ( !TextUtils.equals( "全部应用", app.getName() ) ) {
properties.put( "appversion", CommonUtils.getVersionName( getContext(), app.getPackageName() ) );
} else {
properties.put( "appversion", CommonUtils.getVersionName( getContext() ) );
}
AppServiceHandler.getMogoAnalytics().track( "Launcher_APP_Icon", properties );
}

View File

@@ -27,7 +27,7 @@ public class InternalFunctionLauncher extends BaseAppLauncher {
@Override
public void launch( Context context, AppInfo appInfo ) {
switch ( appInfo.getPackageName() ) {
case "com.mogo.launcher.navi.search":
case "com.autonavi.amapauto":
if ( CustomNaviInterrupter.getInstance().interrupt() ) {
try {
LaunchUtils.launchByPkg( context, "com.autonavi.amapauto" );

View File

@@ -13,10 +13,10 @@ import java.util.List;
*/
public class NavigatorApps {
private static AppInfo app = new AppInfo( "导航", "com.mogo.launcher.navi.search", "", 0, null, R.drawable.module_apps_ic_navigator_navi, 1 );
private static AppInfo app_ = new AppInfo( "导航", "com.mogo.launcher.navi.search", "", 0, null, R.drawable.module_apps_ic_navigator_navi_disable, 1 );
private static AppInfo app = new AppInfo( "高德地图", "com.autonavi.amapauto", "", 0, null, R.drawable.module_apps_ic_navigator_navi, 1 );
private static AppInfo app_ = new AppInfo( "高德地图", "com.autonavi.amapauto", "", 0, null, R.drawable.module_apps_ic_navigator_navi_disable, 1 );
// private static AppInfo app2 = new AppInfo( "音乐", "com.tencent.wecarflow", "", 0, null, R.drawable.module_apps_ic_navigator_media, 2 );
private static AppInfo app2 = new AppInfo( "音乐", "cn.kuwo.kwmusiccar", "", 0, null, R.drawable.module_apps_ic_navigator_media, 2 );
private static AppInfo app2 = new AppInfo( "酷我音乐", "cn.kuwo.kwmusiccar", "", 0, null, R.drawable.module_apps_ic_navigator_media, 2 );
private static AppInfo app3 = new AppInfo( "车聊聊", "com.zhidao.imdemo", "", 0, null, R.drawable.module_apps_ic_navigator_im, 6 );
private static AppInfo app4 = new AppInfo( "全部应用", "com.mogo.launcher.applist", "", 0, null, R.drawable.module_apps_ic_navigator_applist, 4 );

View File

@@ -5,12 +5,8 @@ import android.view.View;
import com.mogo.commons.debug.DebugConfig;
import com.mogo.commons.device.Devices;
import com.mogo.commons.voice.AIAssist;
import com.mogo.module.apps.AppServiceHandler;
import com.mogo.utils.TipToast;
import java.util.HashMap;
import java.util.Map;
public
/**
* @author congtaowang
@@ -32,11 +28,9 @@ class OnAiAssistClickListener implements View.OnClickListener {
public void onClick( View v ) {
if ( Devices.isBind() || !DebugConfig.isActiveAIAssistFlag() ) {
AIAssist.startAssistant( v.getContext() );
trackNavigatorClickEvent( 5 );
} else {
if ( mDebugModeOpen ) {
AIAssist.startAssistant( v.getContext(), 1 );
trackNavigatorClickEvent( 5 );
return;
}
if ( mClickCounter == 0 ) {
@@ -60,10 +54,4 @@ class OnAiAssistClickListener implements View.OnClickListener {
}
}
private void trackNavigatorClickEvent( int type ) {
final Map< String, Object > properties = new HashMap<>();
properties.put( "type", type );
AppServiceHandler.getMogoAnalytics().track( "Launcher_APP_Icon", properties );
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -0,0 +1,88 @@
package com.mogo.module.common.entity;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020/3/11 4:25 PM
* desc : V2X事件列表展示
* version: 1.0
*/
public class V2XEventShowEntity implements Serializable {
// 0---默认展示详情1--直播4--道路事件详情
private int viewType;
// 道路事件详情
private V2XRoadEventEntity v2XRoadEventEntity;
// 直播车机 @see viewType = 1
private V2XLiveCarInfoEntity v2XLiveCarInfoRes;
// 直播车机列表
private List<V2XLiveCarInfoEntity> v2XLiveCarList;
public int getViewType() {
return viewType;
}
public void setViewType(int viewType) {
this.viewType = viewType;
}
public V2XRoadEventEntity getV2XRoadEventEntity() {
return v2XRoadEventEntity;
}
public void setV2XRoadEventEntity(V2XRoadEventEntity v2XRoadEventEntity) {
this.v2XRoadEventEntity = v2XRoadEventEntity;
}
public V2XLiveCarInfoEntity getV2XLiveCarInfoRes() {
return v2XLiveCarInfoRes;
}
public void setV2XLiveCarInfoRes(V2XLiveCarInfoEntity v2XLiveCarInfoRes) {
this.v2XLiveCarInfoRes = v2XLiveCarInfoRes;
}
public List<V2XLiveCarInfoEntity> getV2XLiveCarList() {
return v2XLiveCarList;
}
public void setV2XLiveCarList(List<V2XLiveCarInfoEntity> v2XLiveCarList) {
this.v2XLiveCarList = v2XLiveCarList;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
V2XEventShowEntity that = (V2XEventShowEntity) o;
return viewType == that.viewType &&
Objects.equals(v2XRoadEventEntity, that.v2XRoadEventEntity) &&
Objects.equals(v2XLiveCarInfoRes, that.v2XLiveCarInfoRes) &&
Objects.equals(v2XLiveCarList, that.v2XLiveCarList);
}
@Override
public int hashCode() {
return Objects.hash(viewType, v2XRoadEventEntity, v2XLiveCarInfoRes, v2XLiveCarList);
}
@Override
public String toString() {
return "V2XEventShowEntity{" +
"viewType=" + viewType +
", v2XRoadEventEntity=" + v2XRoadEventEntity +
", v2XLiveCarInfoRes=" + v2XLiveCarInfoRes +
", v2XLiveCarList=" + v2XLiveCarList +
'}';
}
}

View File

@@ -0,0 +1,66 @@
package com.mogo.module.common.entity;
import java.util.Objects;
/**
* 可直播车机基本信息,再通过 appDataService/integratedServices/app/push/no/livePush/v1
* 获取直播信息
* @author donghongyu
*/
public class V2XLiveCarInfoEntity {
private String sn;
private double lon;
private double lat;
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public double getLon() {
return lon;
}
public void setLon(double lon) {
this.lon = lon;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
V2XLiveCarInfoEntity that = (V2XLiveCarInfoEntity) o;
return Double.compare(that.lon, lon) == 0 &&
Double.compare(that.lat, lat) == 0 &&
Objects.equals(sn, that.sn);
}
@Override
public int hashCode() {
return Objects.hash(sn, lon, lat);
}
@Override
public String toString() {
return "V2XLiveCarEntity{" +
"sn='" + sn + '\'' +
", lon=" + lon +
", lat=" + lat +
'}';
}
}

View File

@@ -0,0 +1,125 @@
package com.mogo.module.common.entity;
import androidx.annotation.IntDef;
import java.io.Serializable;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Objects;
/**
* e-mail : 1358506549@qq.com
* date : 2020/5/15 4:35 PM
* desc : V2X 场景消息聚合
* version: 1.0
*
* @author donghongyu
*/
public class V2XMessageEntity<T> implements Serializable {
/**
* 场景类型
*
* @see V2XTypeEnum
*/
@MessageType
int type;
/**
* 是否展示对话框
* true-展示false-不展示
*/
boolean showState;
/**
* 场景具体的数据内容
*/
T content;
public int getType() {
return type;
}
public void setType(@MessageType int type) {
this.type = type;
}
public boolean isShowState() {
return showState;
}
public void setShowState(boolean showState) {
this.showState = showState;
}
public T getContent() {
return content;
}
public void setContent(T content) {
this.content = content;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
V2XMessageEntity<?> that = (V2XMessageEntity<?>) o;
return type == that.type &&
content.equals(that.content);
}
@Override
public int hashCode() {
return Objects.hash(type, content);
}
/**
* V2X 场景类型
*/
public interface V2XTypeEnum {
// 道路事件预警
int ALERT_ROAD_WARNING = 1_000;
// 他车求助预警
int ALERT_SEEK_WARNING = 1_001;
// 疲劳驾驶预警
int ALERT_FATIGUE_DRIVING = 1_002;
// 后台推送展示 Window
int ALERT_PUSH_WINDOW_WARNING = 1_003;
// 后台推送展示 Toast
int ALERT_PUSH_TOAST_WARNING = 1_004;
// 后台推送展示 展示的直播
int ALERT_PUSH_LIVE_CAR_WARNING = 1_005;
// V2X场景动画展示
int ALERT_ANIMATION_WARNING = 1_006;
// 道路事件直播预警
int ALERT_ROAD_LIVE_CAR_WARNING = 1_007;
// 道路事件违章停车
int ALERT_ILLEGAL_PARK_WARNING = 1_008;
// 自车求助
int ALERT_CAR_FOR_HELP = 8_000;
}
@IntDef(value = {
V2XTypeEnum.ALERT_ROAD_WARNING,
V2XTypeEnum.ALERT_SEEK_WARNING,
V2XTypeEnum.ALERT_FATIGUE_DRIVING,
V2XTypeEnum.ALERT_PUSH_WINDOW_WARNING,
V2XTypeEnum.ALERT_PUSH_TOAST_WARNING,
V2XTypeEnum.ALERT_PUSH_LIVE_CAR_WARNING,
V2XTypeEnum.ALERT_ANIMATION_WARNING,
V2XTypeEnum.ALERT_ROAD_LIVE_CAR_WARNING,
V2XTypeEnum.ALERT_ILLEGAL_PARK_WARNING,
V2XTypeEnum.ALERT_CAR_FOR_HELP,
})
@Target({
ElementType.PARAMETER,
ElementType.FIELD,
ElementType.METHOD,
}) //表示注解作用范围,参数注解,成员注解,方法注解
@Retention(RetentionPolicy.SOURCE) //表示注解所存活的时间,在运行时,而不会存在 .class 文件中
public @interface MessageType { //接口,定义新的注解类型
}
}

View File

@@ -0,0 +1,31 @@
package com.mogo.module.common.entity;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020/3/31 4:53 PM
* desc : V2X 道路事件类型
* version: 1.0
*/
public interface V2XPoiTypeEnum extends MarkerPoiTypeEnum {
// 前方静止or慢速车辆报警
String ALERT_FRONT_CAR = "99999";
// 限行管理
String ALERT_TRAFFIC_CONTROL = "99998";
// 红绿灯事件、是建议以多少速度驶过
String ALERT_TRAFFIC_LIGHT_SUGGEST = "99997";
// 红绿灯事件、一种是绿灯不足3秒
String ALERT_TRAFFIC_LIGHT_WARNING = "99996";
// 故障车辆
int ALERT_CAR_TROUBLE_WARNING = 20007;
// TODO 这里目前是演示DEMO会用到想着是打算商用先这么处理的
// 取快递
String ALERT_TRAFFIC_EXPRESS = "99995";
// 顺风车
String ALERT_TRAFFIC_TAXI = "99994";
// 疲劳驾驶
String ALERT_FATIGUE_DRIVING = "99993";
// 违章停车
String ALERT_ILLEGAL_PARK = "99992";
}

View File

@@ -0,0 +1,264 @@
package com.mogo.module.common.entity;
import android.text.TextUtils;
import java.io.Serializable;
import java.util.Objects;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020-02-0315:49
* desc : V2X警报数据
* version: 1.0
*/
public class V2XPushMessageEntity implements Serializable {
// 0---默认展示详情1--直播2--停车场3--加油站4--道路事件详情
private int viewType;
private String sceneId;
private String sceneName;
private short sceneCategory;
private short sceneLevel;
private String sceneDescription;
private boolean zoom;
private int zoomScale;
private String alarmContent;
private String tts;
private String videoUrl;
private String videoSn;
private String videoChannel;
private int expireTime;
private double lat;
private double lon;
private String sn;
private String headImgUrl;
private String msgImgUrl;
private String address;
private double distance;
private boolean isShowWindow;
public int getViewType() {
return viewType;
}
public void setViewType(int viewType) {
this.viewType = viewType;
}
public String getSceneId() {
return sceneId;
}
public void setSceneId(String sceneId) {
this.sceneId = sceneId;
}
public String getSceneName() {
return sceneName;
}
public void setSceneName(String sceneName) {
this.sceneName = sceneName;
}
public short getSceneCategory() {
return sceneCategory;
}
public void setSceneCategory(short sceneCategory) {
this.sceneCategory = sceneCategory;
}
public short getSceneLevel() {
return sceneLevel;
}
public void setSceneLevel(short sceneLevel) {
this.sceneLevel = sceneLevel;
}
public String getSceneDescription() {
return sceneDescription;
}
public void setSceneDescription(String sceneDescription) {
this.sceneDescription = sceneDescription;
}
public boolean isZoom() {
return zoom;
}
public void setZoom(boolean zoom) {
this.zoom = zoom;
}
public String getAlarmContent() {
if (TextUtils.isEmpty(alarmContent)) {
return "";
}
return alarmContent;
}
public void setAlarmContent(String alarmContent) {
this.alarmContent = alarmContent;
}
public String getTts() {
if (TextUtils.isEmpty(tts)) {
return "";
}
return tts;
}
public void setTts(String tts) {
this.tts = tts;
}
public String getVideoUrl() {
return videoUrl;
}
public void setVideoUrl(String videoUrl) {
this.videoUrl = videoUrl;
}
public String getVideoSn() {
return videoSn;
}
public void setVideoSn(String videoSn) {
this.videoSn = videoSn;
}
public String getVideoChannel() {
return videoChannel;
}
public void setVideoChannel(String videoChannel) {
this.videoChannel = videoChannel;
}
public int getExpireTime() {
return expireTime;
}
public void setExpireTime(int expireTime) {
this.expireTime = expireTime;
}
public int getZoomScale() {
return zoomScale;
}
public void setZoomScale(int zoomScale) {
this.zoomScale = zoomScale;
}
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 String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public String getHeadImgUrl() {
return headImgUrl;
}
public void setHeadImgUrl(String headImgUrl) {
this.headImgUrl = headImgUrl;
}
public String getMsgImgUrl() {
return msgImgUrl;
}
public void setMsgImgUrl(String msgImgUrl) {
this.msgImgUrl = msgImgUrl;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public double getDistance() {
return distance;
}
public void setDistance(double distance) {
this.distance = distance;
}
public boolean isShowWindow() {
return isShowWindow;
}
public void setShowWindow(boolean showWindow) {
isShowWindow = showWindow;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
V2XPushMessageEntity that = (V2XPushMessageEntity) o;
return Objects.equals(sceneId, that.sceneId) &&
Objects.equals(tts, that.tts);
}
@Override
public int hashCode() {
return Objects.hash(sceneId, tts);
}
@Override
public String toString() {
return "V2XPushMessageEntity{" +
"viewType=" + viewType +
", sceneId='" + sceneId + '\'' +
", sceneName='" + sceneName + '\'' +
", sceneCategory=" + sceneCategory +
", sceneLevel=" + sceneLevel +
", sceneDescription='" + sceneDescription + '\'' +
", zoom=" + zoom +
", zoomScale=" + zoomScale +
", alarmContent='" + alarmContent + '\'' +
", tts='" + tts + '\'' +
", videoUrl='" + videoUrl + '\'' +
", videoSn='" + videoSn + '\'' +
", videoChannel='" + videoChannel + '\'' +
", expireTime=" + expireTime +
", lat=" + lat +
", lon=" + lon +
", sn='" + sn + '\'' +
", headImgUrl='" + headImgUrl + '\'' +
", msgImgUrl='" + msgImgUrl + '\'' +
", address='" + address + '\'' +
", distance=" + distance +
", isShowWindow=" + isShowWindow +
'}';
}
}

View File

@@ -0,0 +1,298 @@
package com.mogo.module.common.entity;
import android.text.TextUtils;
import java.io.Serializable;
import java.util.Objects;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020/4/13 11:17 AM
* desc : 道路事件的聚合位置、详情用于V2X情况下展示
* version: 1.0
*/
public class V2XRoadEventEntity implements Serializable {
/**
* @see MarkerPoiTypeEnum
*/
// 事件类型
private String poiType;
// 事件位置
private MarkerLocation location;
// 具体的信息
private MarkerExploreWay noveltyInfo;
// tts 提示
private String tts;
// ADAS 展示文案
private String alarmContent;
// 距离当前车辆的距离
private double distance;
// 默认展示时间
private int expireTime;
// 展示Button
private boolean isShowEventButton;
// 绑定 MarkerView 的数据, 业务需要啥数据就传入啥数据
private Object bindObj;
public MarkerLocation getLocation() {
return location;
}
public void setLocation(MarkerLocation location) {
this.location = location;
}
public String getPoiType() {
if (TextUtils.isEmpty(poiType)) {
return "";
}
return poiType;
}
public void setPoiType(String poiType) {
this.poiType = poiType;
}
public String getTts(boolean haveLiveCar) {
tts = "前方#" + (int) getDistance() + "米#";
switch (getPoiType()) {
// 停车场
case V2XPoiTypeEnum.FOURS_PARKING:
tts += "停车场";
break;
// 加油站
case V2XPoiTypeEnum.GAS_STATION:
tts += "加油站";
break;
// 交通检查
case V2XPoiTypeEnum.TRAFFIC_CHECK:
tts += "交通检查";
break;
// 封路
case V2XPoiTypeEnum.ROAD_CLOSED:
tts += "道路封路";
break;
// 施工
case V2XPoiTypeEnum.FOURS_ROAD_WORK:
tts += "道路施工";
break;
// 拥堵
case V2XPoiTypeEnum.FOURS_BLOCK_UP:
tts += "道路拥堵";
break;
// 积水
case V2XPoiTypeEnum.FOURS_PONDING:
tts += "道路积水";
break;
// 浓雾
case V2XPoiTypeEnum.FOURS_FOG:
tts += "出现浓雾";
break;
// 结冰
case V2XPoiTypeEnum.FOURS_ICE:
tts += "路面结冰";
break;
// 事故
case V2XPoiTypeEnum.FOURS_ACCIDENT:
tts += "交通事故";
break;
default:
tts += "道路事件";
break;
}
if (haveLiveCar) {
tts += ",查看实况请说确定。";
setShowEventButton(true);
} else {
tts += ",请注意躲避。";
setShowEventButton(false);
}
return tts;
}
/**
* 检测到附近#道路施工#,确认该信息是否正确?您可以说“正确”或“错误”帮助其他车友。
*/
public String getTtsWithFeedback() {
tts = "检测到附近";
switch (getPoiType()) {
// 停车场
case V2XPoiTypeEnum.FOURS_PARKING:
tts += "有停车场";
break;
// 加油站
case V2XPoiTypeEnum.GAS_STATION:
tts += "有加油站";
break;
// 交通检查
case V2XPoiTypeEnum.TRAFFIC_CHECK:
tts += "交通检查";
break;
// 封路
case V2XPoiTypeEnum.ROAD_CLOSED:
tts += "封路";
break;
// 施工
case V2XPoiTypeEnum.FOURS_ROAD_WORK:
tts += "施工";
break;
// 拥堵
case V2XPoiTypeEnum.FOURS_BLOCK_UP:
tts += "道路拥堵";
break;
// 积水
case V2XPoiTypeEnum.FOURS_PONDING:
tts += "道路积水";
break;
// 浓雾
case V2XPoiTypeEnum.FOURS_FOG:
tts += "出现浓雾";
break;
// 结冰
case V2XPoiTypeEnum.FOURS_ICE:
tts += "路面结冰";
break;
// 事故
case V2XPoiTypeEnum.FOURS_ACCIDENT:
tts += "交通事故";
break;
default:
tts += "道路事件";
break;
}
tts += ",确认该信息是否正确?您可以说“正确”或“错误”帮助其他车友。";
return tts;
}
public String getTts() {
return tts;
}
public void setTts(String tts) {
this.tts = tts;
}
public boolean isShowEventButton() {
return isShowEventButton;
}
public void setShowEventButton(boolean showEventButton) {
isShowEventButton = showEventButton;
}
public String getAlarmContent() {
switch (getPoiType()) {
// 停车场
case V2XPoiTypeEnum.FOURS_PARKING:
alarmContent = "停车场附近";
break;
// 加油站
case V2XPoiTypeEnum.GAS_STATION:
alarmContent = "加油站附近";
break;
// 交通检查
case V2XPoiTypeEnum.TRAFFIC_CHECK:
alarmContent = "前方交通检查";
break;
// 封路
case V2XPoiTypeEnum.ROAD_CLOSED:
alarmContent = "前方封路";
break;
// 施工
case V2XPoiTypeEnum.FOURS_ROAD_WORK:
alarmContent = "前方施工";
break;
// 拥堵
case V2XPoiTypeEnum.FOURS_BLOCK_UP:
alarmContent = "前方道路拥堵";
break;
// 积水
case V2XPoiTypeEnum.FOURS_PONDING:
alarmContent = "前方道路积水";
break;
// 浓雾
case V2XPoiTypeEnum.FOURS_FOG:
alarmContent = "前方出现浓雾";
break;
// 结冰
case V2XPoiTypeEnum.FOURS_ICE:
alarmContent = "前方路面结冰";
break;
// 事故
case V2XPoiTypeEnum.FOURS_ACCIDENT:
alarmContent = "前方交通事故";
break;
default:
tts += "道路事件";
break;
}
return alarmContent;
}
public void setAlarmContent(String alarmContent) {
this.alarmContent = alarmContent;
}
public double getDistance() {
return distance;
}
public void setDistance(double distance) {
this.distance = distance;
}
public int getExpireTime() {
return expireTime;
}
public void setExpireTime(int expireTime) {
this.expireTime = expireTime;
}
public MarkerExploreWay getNoveltyInfo() {
return noveltyInfo;
}
public void setNoveltyInfo(MarkerExploreWay noveltyInfo) {
this.noveltyInfo = noveltyInfo;
}
public Object getBindObj() {
return bindObj;
}
public void setBindObj(Object bindObj) {
this.bindObj = bindObj;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
V2XRoadEventEntity that = (V2XRoadEventEntity) o;
return Objects.equals(noveltyInfo.getInfoId(), that.noveltyInfo.getInfoId()) &&
Objects.equals(poiType, that.poiType);
}
@Override
public int hashCode() {
return Objects.hash(poiType, noveltyInfo.getInfoId());
}
@Override
public String toString() {
return "V2XRoadEventEntity{" +
"poiType='" + poiType + '\'' +
", location=" + location +
", noveltyInfo=" + noveltyInfo +
", tts='" + tts + '\'' +
", alarmContent='" + alarmContent + '\'' +
", distance=" + distance +
", expireTime=" + expireTime +
", isShowEventButton=" + isShowEventButton +
", bindObj=" + bindObj +
'}';
}
}

View File

@@ -0,0 +1,27 @@
package com.mogo.module.common.entity;
/**
* author : donghongyu
* e-mail : 1358506549@qq.com
* date : 2020/3/31 4:53 PM
* desc : V2X 道路提醒类型
* version: 1.0
*/
public interface V2XWindowTypeEnum {
// 默认展示详情
int DEFAULT_WINDOW = 0;
// 直播
int LIVE_CAR_WINDOW = 1;
// 道路事件详情
int ROAD_EVENT_WINDOW = 2;
// 推送事件详情
int PUSH_EVENT_WINDOW = 3;
// 演示动画场景
int ANIMATION_WINDOW = 4;
// 疲劳驾驶
int FATIGUE_DRIVING_WINDOW = 5;
// 他人故障求助
int SEEK_HELP_WINDOW = 6;
// 违章停车
int ILLEGAL_PARK_WINDOW = 7;
}

View File

@@ -87,4 +87,8 @@ class EventPanelModuleProvider : IEventPanelProvider {
return null
}
override fun isPanelShow(): Boolean {
return false
}
}

View File

@@ -49,6 +49,9 @@ dependencies {
implementation rootProject.ext.dependencies.rxandroid
implementation rootProject.ext.dependencies.androidxviewpager2
implementation rootProject.ext.dependencies.androidxrecyclerview
implementation rootProject.ext.dependencies.room
kapt rootProject.ext.dependencies.roomAnnotationProcessor
implementation rootProject.ext.dependencies.roomRxjava
if (Boolean.valueOf(RELEASE)) {
compileOnly rootProject.ext.dependencies.modulecommon

View File

@@ -1,26 +0,0 @@
package com.zhidao.mogo.module.event.panel;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.zhidao.mogo.module.event.panel.test", appContext.getPackageName());
}
}

View File

@@ -8,4 +8,8 @@ package com.zhidao.mogo.module.event.panel
object EventPanelConstants {
const val MODULE_NAME = "MODULE_EVENT_PANEL"
const val PATH_NAME = "/event/panel"
const val ROAD_EVENT_USEFUL = "2"
const val ROAD_EVENT_UNUSEFUL = "1"
const val ROAD_EVENT_USEFUL_STATUS_UNSET = "0"
}

View File

@@ -16,6 +16,8 @@ import com.mogo.utils.logger.Logger
import com.zhidao.mogo.module.event.panel.EventPanelConstants.MODULE_NAME
import com.zhidao.mogo.module.event.panel.EventPanelConstants.PATH_NAME
import com.zhidao.mogo.module.event.panel.fragment.EventPanelFragment
import com.zhidao.mogo.module.event.panel.util.MogoApiManager
import com.zhidao.mogo.module.event.panel.util.TripRecordDataManager
/**
* 事件面板provider
@@ -31,6 +33,8 @@ class EventPanelModuleProvider : IEventPanelProvider {
*/
override fun init(context: Context) {
Logger.d(MODULE_NAME, "模块初始化====")
MogoApiManager.init(context)
TripRecordDataManager.init(context)
}
override fun createFragment(context: Context, data: Bundle?): Fragment? {
@@ -44,6 +48,10 @@ class EventPanelModuleProvider : IEventPanelProvider {
EventPanelFragment.getInstance().showPanel()
}
override fun isPanelShow(): Boolean {
return EventPanelFragment.getInstance().isPanelShow()
}
/**
* 隐藏面板

View File

@@ -0,0 +1,25 @@
package com.zhidao.mogo.module.event.panel.bean
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.zhidao.mogo.module.event.panel.EventPanelConstants.ROAD_EVENT_USEFUL_STATUS_UNSET
/**
* 出行记录本地存储封装类,此类标识了数据库表名以及字段名
*
* @author tongchenfei
*/
@Entity
data class TripRecord(@PrimaryKey(autoGenerate = false)
var id: Int,
var eventId: String = "",
var eventType: Int,
/**
* 是否有用
* 1 - 没用
* 2 - 有用
* 0 - 未设置
*/
var usefulStatus: String = ROAD_EVENT_USEFUL_STATUS_UNSET,
var entity: String = "",
var recordTime: Long = System.currentTimeMillis())

View File

@@ -0,0 +1,40 @@
package com.zhidao.mogo.module.event.panel.dao
import androidx.room.*
import com.zhidao.mogo.module.event.panel.bean.TripRecord
import io.reactivex.Single
@Dao
interface TripRecordDao {
/**
* 查询当日数据
* @param limitTime 当日0点的时间戳
*/
@Query(value = "SELECT * FROM TripRecord WHERE recordTime > :limitTime ORDER BY recordTime DESC")
fun queryAllTripRecord(limitTime:Long):Single<List<TripRecord>>
/**
* 根据事件id获取出行动态
*
* @param eventId 事件id [com.mogo.module.common.entity.V2XRoadEventEntity.noveltyInfo.infoId]
*/
@Query(value = "SELECT * FROM TripRecord WHERE eventId = :eventId")
fun queryTripRecordByEventId(eventId:String):Single<TripRecord>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg tripRecord: TripRecord)
@Update
fun update(vararg tripRecord: TripRecord)
@Delete
fun delete(vararg tripRecord: TripRecord)
/**
* 删除超时的数据即当天0时以前的数据
* 虽然注解是Query但是目的是执行后面的sql语句所以就不要在意这些细节了
*
* @param limitTime 当日0点的时间戳
*/
@Query(value = "DELETE FROM TripRecord WHERE recordTime < :limitTime")
fun deleteOvertimeTripRecord(limitTime: Long)
}

View File

@@ -0,0 +1,25 @@
package com.zhidao.mogo.module.event.panel.dao
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.zhidao.mogo.module.event.panel.bean.TripRecord
@Database(entities = [TripRecord::class], version = 1, exportSchema = false)
abstract class TripRecordDatabase : RoomDatabase() {
companion object{
private var instance:TripRecordDatabase? = null
fun getInstance(context: Context):TripRecordDatabase{
if (instance == null) {
synchronized(TripRecordDatabase::class.java) {
if (instance == null) {
instance = Room.databaseBuilder(context, TripRecordDatabase::class.java, "TripRecordDatabase.db").build()
}
}
}
return instance!!
}
}
abstract fun getTripRecordDao():TripRecordDao
}

View File

@@ -31,7 +31,13 @@ class EventPanelFragment : MvpFragment<EventPanelFragment, EventPanelPresenter>(
override fun initViews() {
Logger.d(MODULE_NAME, "EventPanelFragment init view===")
vpEventPanel.adapter = EventPagerAdapter(this)
btnShowOrHidePanels.setOnClickListener {
if (vpEventPanel.visibility == View.GONE) {
showPanel()
}else{
hidePanel()
}
}
}
override fun createPresenter(): EventPanelPresenter {
return EventPanelPresenter(this)
@@ -39,11 +45,17 @@ class EventPanelFragment : MvpFragment<EventPanelFragment, EventPanelPresenter>(
fun showPanel(){
Logger.d(MODULE_NAME,"in fragment show panel")
clPanelContainer.visibility = View.VISIBLE
vpEventPanel.visibility = View.VISIBLE
btnShowOrHidePanels.text = "隐藏面板"
}
fun hidePanel(){
Logger.d(MODULE_NAME,"in fragment hide panel")
clPanelContainer.visibility = View.GONE
vpEventPanel.visibility = View.GONE
btnShowOrHidePanels.text = "显示面板"
}
fun isPanelShow():Boolean{
return vpEventPanel.visibility == View.VISIBLE
}
}

View File

@@ -1,31 +1,42 @@
package com.zhidao.mogo.module.event.panel.fragment
import android.util.Log
import com.mogo.commons.mvp.MvpFragment
import com.mogo.module.common.entity.V2XMessageEntity
import com.mogo.utils.logger.Logger
import com.zhidao.mogo.module.event.panel.EventPanelConstants.MODULE_NAME
import com.zhidao.mogo.module.event.panel.R
import com.zhidao.mogo.module.event.panel.bean.TripRecord
import com.zhidao.mogo.module.event.panel.presenter.TripRecordPresenter
import kotlinx.android.synthetic.main.module_event_panel_fragment_trip_record.*
import kotlin.random.Random
/**
* 出行动态fragment
*/
class TripRecordFragment: MvpFragment<TripRecordFragment, TripRecordPresenter>() {
/**
* 布局资源
*
* @return
*/
class TripRecordFragment : MvpFragment<TripRecordFragment, TripRecordPresenter>() {
private val tripRecordList = ArrayList<TripRecord>()
override fun getLayoutId(): Int = R.layout.module_event_panel_fragment_trip_record
/**
* 初始化控件必须在初始化完成之后才可以实例化presenter避免
* presenter 生命周期错乱
*/
override fun initViews() {
btnQuery.setOnClickListener {
Log.d(MODULE_NAME, "local list: $tripRecordList")
mPresenter.queryAllTripRecord()
}
}
override fun createPresenter(): TripRecordPresenter = TripRecordPresenter(this)
fun refreshTripRecordList(tripRecords: List<TripRecord>) {
Logger.d(MODULE_NAME, "刷新出行动态列表:$tripRecords")
tripRecordList.clear()
tripRecordList.addAll(tripRecords)
}
/**
* 创建 presenter 实例
*
* @return
* 刷新单个出行动态,如果无此动态,新增动态
*/
override fun createPresenter(): TripRecordPresenter = TripRecordPresenter(this)
fun refreshTripRecord(tripRecord: TripRecord) {
Logger.d(MODULE_NAME, "刷新单个出行动态: $tripRecord")
}
}

View File

@@ -0,0 +1,18 @@
package com.zhidao.mogo.module.event.panel.listener
import com.zhidao.mogo.module.event.panel.bean.TripRecord
/**
* 数据库异步操作数据回调
*/
interface ITripRecordCallback {
/**
* 查询全部出行动态成功
*/
fun queryTripRecordListSuccess(tripRecordList:List<TripRecord>)
/**
* 有出行动态新增或更新后,回调此接口
*/
fun insertOrUpdateTripRecordSuccess(tripRecord:TripRecord)
}

View File

@@ -1,7 +1,33 @@
package com.zhidao.mogo.module.event.panel.presenter
import androidx.lifecycle.LifecycleOwner
import com.mogo.commons.mvp.Presenter
import com.zhidao.mogo.module.event.panel.bean.TripRecord
import com.zhidao.mogo.module.event.panel.fragment.TripRecordFragment
import com.zhidao.mogo.module.event.panel.listener.ITripRecordCallback
import com.zhidao.mogo.module.event.panel.util.TripRecordDataManager
class TripRecordPresenter(view: TripRecordFragment) : Presenter<TripRecordFragment>(view) {
}
class TripRecordPresenter(view: TripRecordFragment) : Presenter<TripRecordFragment>(view),ITripRecordCallback {
init {
TripRecordDataManager.addTripRecordCallback(this)
}
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
TripRecordDataManager.removeTripRecordCallback(this)
}
fun queryAllTripRecord(){
TripRecordDataManager.queryAllTripRecord()
}
override fun queryTripRecordListSuccess(tripRecordList: List<TripRecord>) {
mView.refreshTripRecordList(tripRecordList)
}
override fun insertOrUpdateTripRecordSuccess(tripRecord: TripRecord) {
mView.refreshTripRecord(tripRecord)
}
}

View File

@@ -0,0 +1,14 @@
package com.zhidao.mogo.module.event.panel.util
import android.content.Context
import com.alibaba.android.arouter.launcher.ARouter
import com.mogo.service.IMogoServiceApis
import com.mogo.service.MogoServicePaths
object MogoApiManager {
lateinit var serviceApis:IMogoServiceApis
fun init(context: Context) {
serviceApis = ARouter.getInstance().build(MogoServicePaths.PATH_SERVICE_APIS).navigation(context) as IMogoServiceApis
}
}

View File

@@ -0,0 +1,183 @@
package com.zhidao.mogo.module.event.panel.util
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.util.Log
import androidx.lifecycle.LifecycleOwner
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.mogo.module.common.entity.V2XMessageEntity
import com.mogo.module.common.entity.V2XMessageEntity.V2XTypeEnum.*
import com.mogo.module.common.entity.V2XRoadEventEntity
import com.mogo.utils.ThreadPoolService
import com.mogo.utils.logger.Logger
import com.mogo.utils.network.utils.GsonUtil
import com.zhidao.mogo.module.event.panel.EventPanelConstants.MODULE_NAME
import com.zhidao.mogo.module.event.panel.bean.TripRecord
import com.zhidao.mogo.module.event.panel.dao.TripRecordDao
import com.zhidao.mogo.module.event.panel.dao.TripRecordDatabase
import com.zhidao.mogo.module.event.panel.listener.ITripRecordCallback
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import java.util.*
import kotlin.collections.ArrayList
private const val BROADCAST_SCENE_EVENT_ACTION = "com.v2x.scene_local_broadcast"
private const val BROADCAST_SCENE_MODIFY_ACTION = "com.zhidao.tanlu.dataerror"
private const val BROADCAST_SCENE_EXTRA_KEY = "V2XMessageEntity"
private const val BORADCAST_SCENE_MODIFY_EVENT_ID_KEY = "id"
private const val BROADCAST_SCENE_MODIFY_EVENT_UPDATE_TYPE_KEY = "updateType"
/**
* 出行动态的数据管理类由于TripRecordFragment初始化时机较晚所以封装一个单例类提早初始化
*/
object TripRecordDataManager {
lateinit var context: Context
private val sceneEventReceiver = SceneEventReceiver()
private lateinit var tripRecordDao:TripRecordDao
private val tripRecordCallbackList = ArrayList<ITripRecordCallback>()
fun init(context: Context) {
this.context = context
LocalBroadcastManager.getInstance(context).registerReceiver(sceneEventReceiver, IntentFilter(BROADCAST_SCENE_EVENT_ACTION))
context.registerReceiver(sceneEventReceiver, IntentFilter(BROADCAST_SCENE_MODIFY_ACTION))
tripRecordDao = TripRecordDatabase.getInstance(TripRecordDataManager.context).getTripRecordDao()
}
fun addTripRecordCallback(callback: ITripRecordCallback) {
tripRecordCallbackList.add(callback)
}
fun removeTripRecordCallback(callback: ITripRecordCallback) {
tripRecordCallbackList.remove(callback)
}
private val compositeDisposable = CompositeDisposable()
fun queryAllTripRecord() {
val queryDisposable = tripRecordDao.queryAllTripRecord(countLimitTime()).subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).map {
Logger.d(MODULE_NAME, "delete over time record when query thread is ${Thread.currentThread().name}")
tripRecordDao.deleteOvertimeTripRecord(countLimitTime())
it
}.observeOn(AndroidSchedulers.mainThread()).subscribe { it ->
Log.d(MODULE_NAME, "db query: $it, thread is ${Thread.currentThread().name}")
tripRecordCallbackList.forEach {callback->
callback.queryTripRecordListSuccess(it)
}
}
compositeDisposable.add(queryDisposable)
}
private fun insertTripRecord(record: TripRecord) {
val disposable = Single.create<TripRecord> {
Logger.d(MODULE_NAME, "准备将数据插入数据库: $record")
tripRecordDao.insert(record)
it.onSuccess(record)
}.subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).map {
// 为了防止只进不出,所以在插入新数据时,进行过期数据删除操作
Logger.d(MODULE_NAME, "delete over time record when insert: $it")
tripRecordDao.deleteOvertimeTripRecord(countLimitTime())
record
}.observeOn(AndroidSchedulers.mainThread()).subscribe{ it->
Logger.d(MODULE_NAME, "插入+删除操作完成,做界面展示===$it")
tripRecordCallbackList.forEach { callback->
callback.insertOrUpdateTripRecordSuccess(it)
}
}
compositeDisposable.add(disposable)
}
fun updateTripRecords(vararg records: TripRecord) {
ThreadPoolService.execute {
tripRecordDao.update(*records)
}
}
fun deleteTripRecords(vararg records: TripRecord) {
ThreadPoolService.execute {
tripRecordDao.delete(*records)
}
}
/**
* 计算约束时间即当日0时
*/
private fun countLimitTime(): Long {
val calendar = Calendar.getInstance()
calendar.time = Date()
calendar.set(Calendar.HOUR_OF_DAY, 0)
calendar.set(Calendar.MINUTE, 0)
calendar.set(Calendar.SECOND, 0)
return calendar.timeInMillis
}
fun release(owner: LifecycleOwner) {
if(!compositeDisposable.isDisposed) {
compositeDisposable.dispose()
}
}
/**
* 处理道路事件推送,保存到本地数据库
* 目前只处理道路事件,违章提醒,他车求助,其他事件暂不处理
*/
private fun dealSceneMessage(type: Int, content: Any) {
if (type in arrayOf(ALERT_ROAD_WARNING, ALERT_ILLEGAL_PARK_WARNING, ALERT_SEEK_WARNING)) {
val eventId = if(type == V2XMessageEntity.V2XTypeEnum.ALERT_ROAD_WARNING){
val event = content as V2XRoadEventEntity
event.noveltyInfo.infoId
}else{
""
}
Logger.d(MODULE_NAME, "处理场景事件,准备插入数据库===eventId: $eventId")
insertTripRecord(TripRecord(id = content.hashCode(), eventId = eventId, eventType = type, entity = GsonUtil.jsonFromObject(content)))
}
}
/**
* 本地数据库同步v2x传过来的纠错信息
*/
private fun syncRoadEventModifyState(eventId: String, modifyType: String) {
Logger.d(MODULE_NAME, "准备同步纠错信息: $eventId, $modifyType")
val disposable = tripRecordDao.queryTripRecordByEventId(eventId).subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).map {
Logger.d(MODULE_NAME, "查询将纠错数据: $it")
it.usefulStatus = modifyType
it
}.map {
Logger.d(MODULE_NAME, "准备更新纠错数据: $it")
tripRecordDao.update(it)
it
}.observeOn(AndroidSchedulers.mainThread()).subscribe { it->
Logger.d(MODULE_NAME, "数据纠错更新完成,准备刷新界面==$it")
tripRecordCallbackList.forEach { callback->
callback.insertOrUpdateTripRecordSuccess(it)
}
}
compositeDisposable.add(disposable)
}
class SceneEventReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Logger.d(MODULE_NAME, "收到V2X事件推送===")
when (intent.action) {
BROADCAST_SCENE_EVENT_ACTION -> {
// 道路事件推送
val message = intent.getSerializableExtra(BROADCAST_SCENE_EXTRA_KEY) as V2XMessageEntity<*>
Logger.d(MODULE_NAME, "道路事件推送 type: ${message.type}, content: ${message.content}")
dealSceneMessage(message.type, message.content)
}
BROADCAST_SCENE_MODIFY_ACTION -> {
// 纠错推送
syncRoadEventModifyState(intent.getStringExtra(BORADCAST_SCENE_MODIFY_EVENT_ID_KEY), intent.getStringExtra(BROADCAST_SCENE_MODIFY_EVENT_UPDATE_TYPE_KEY))
}
}
}
}
}

View File

@@ -1,12 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/clPanelContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
android:layout_height="match_parent">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/vpEventPanel"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent"
android:visibility="gone"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnShowOrHidePanels"
android:text="显示面板"
android:textSize="20sp"
android:textColor="#000"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/clPanelContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
@@ -10,6 +11,67 @@
android:layout_height="match_parent"
android:gravity="center"
android:text="Trip Record"
android:textColor="#fff"
android:textColor="#000"
android:textSize="40sp" />
<Button
android:id="@+id/btnInsert"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Insert"
android:textColor="#000"
android:textSize="30sp"
android:layout_marginTop="100dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/btnUpdate"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnUpdate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Update"
android:textColor="#000"
android:textSize="30sp"
android:layout_marginTop="100dp"
app:layout_constraintLeft_toRightOf="@+id/btnInsert"
app:layout_constraintRight_toLeftOf="@+id/btnDelete"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnDelete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Delete"
android:textColor="#000"
android:textSize="30sp"
android:layout_marginTop="100dp"
app:layout_constraintLeft_toRightOf="@+id/btnUpdate"
app:layout_constraintRight_toLeftOf="@+id/btnQuery"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnQuery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Query"
android:textColor="#000"
android:textSize="30sp"
android:layout_marginTop="100dp"
app:layout_constraintLeft_toRightOf="@+id/btnDelete"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnGenerate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="GenerateLimitTime"
android:textColor="#000"
android:textSize="30sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/btnInsert" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,17 +0,0 @@
package com.zhidao.mogo.module.event.panel;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}

View File

@@ -10,6 +10,7 @@ import kotlinx.android.synthetic.main.module_left_panel_simple_speed.*
*
* @author tongchenfei
*/
private const val SPEED_THRESHOLD = 40
class SimpleSpeedFragment: MvpFragment<SimpleSpeedFragment, SimpleSpeedPresenter>() {
override fun getLayoutId(): Int {
return R.layout.module_left_panel_simple_speed
@@ -24,5 +25,11 @@ class SimpleSpeedFragment: MvpFragment<SimpleSpeedFragment, SimpleSpeedPresenter
fun refreshSpeed(speed: Int) {
tvModuleLeftPanelSpeed.text = speed.toString()
if (speed >= SPEED_THRESHOLD) {
// 速度超过90需要改变背景颜色
tvModuleLeftPanelSpeed.setBackgroundResource(R.drawable.module_left_panel_warn_speed_bg)
}else{
tvModuleLeftPanelSpeed.setBackgroundResource(R.drawable.module_left_panel_normal_speed_bg)
}
}
}

View File

@@ -11,6 +11,7 @@ import com.zhidao.mogo.module.left.panel.LeftPanelConst.MODULE_NAME
import com.zhidao.mogo.module.left.panel.fragment.SimpleSpeedFragment
import java.lang.Thread.sleep
import kotlin.concurrent.thread
import kotlin.random.Random
/**
* 临时左侧车速逻辑的presenter

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -1,16 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:id="@+id/ivContainerBg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/module_left_panel_speed_container_bg"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tvModuleLeftPanelSpeed"
android:text="50"
android:text="0"
android:gravity="center"
android:textSize="40sp"
android:textStyle="bold"
android:textSize="@dimen/module_left_panel_simple_speed_text_size"
app:layout_constraintLeft_toLeftOf="@id/ivContainerBg"
app:layout_constraintRight_toRightOf="@id/ivContainerBg"
app:layout_constraintTop_toTopOf="@id/ivContainerBg"
android:layout_marginTop="@dimen/module_left_panel_simple_speed_text_margin_top"
android:textColor="#fff"
android:background="#000" />
android:background="@drawable/module_left_panel_normal_speed_bg" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="当前车速"
android:textColor="#fff"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="@id/tvModuleLeftPanelSpeed"
app:layout_constraintRight_toRightOf="@id/tvModuleLeftPanelSpeed"
app:layout_constraintTop_toBottomOf="@id/tvModuleLeftPanelSpeed"
android:layout_marginTop="@dimen/module_left_panel_simple_speed_title_margin"
android:textSize="@dimen/module_left_panel_simple_speed_title_size" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="module_left_panel_simple_speed_text_size">80px</dimen>
<dimen name="module_left_panel_simple_speed_text_margin_top">69.6px</dimen>
<dimen name="module_left_panel_simple_speed_title_size">20px</dimen>
<dimen name="module_left_panel_simple_speed_title_margin">28px</dimen>
</resources>

View File

@@ -36,7 +36,7 @@
<!-- 左侧浮层,布局位置目前只考虑了1+16独立app情况 -->
<FrameLayout
android:layout_width="@dimen/module_main_id_entrance_fragment_container_marginLeft"
android:layout_width="@dimen/module_main_id_left_panel_fragment_container_width"
android:layout_height="match_parent"
android:id="@+id/module_main_id_left_panel_fragment_container" />

View File

@@ -22,4 +22,6 @@
<dimen name="module_main_id_entrance_fragment_container_marginLeft">800px</dimen>
<dimen name="module_main_entrance_fragment_container_padding">30px</dimen>
<dimen name="module_main_id_left_panel_fragment_container_width">340px</dimen>
</resources>

View File

@@ -21,6 +21,7 @@
<dimen name="module_main_header_fragment_container_marginTop">15px</dimen>
<dimen name="module_main_header_fragment_container_marginLeft">460px</dimen>
<dimen name="module_main_id_entrance_fragment_container_marginLeft">444px</dimen>
<dimen name="module_main_id_left_panel_fragment_container_width">350px</dimen>
<dimen name="module_main_entrance_fragment_container_padding">16px</dimen>
</resources>

View File

@@ -1,6 +1,8 @@
package com.mogo.module.map;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -35,10 +37,12 @@ import com.mogo.service.module.IMogoSearchManager;
import com.mogo.service.module.IMogoSettingManager;
import com.mogo.service.statusmanager.IMogoStatusManager;
import com.mogo.service.strategy.IMogoRefreshStrategyController;
import com.mogo.utils.AppUtils;
import com.mogo.utils.ResourcesHelper;
import com.mogo.utils.UiThreadHandler;
import com.mogo.utils.logger.Logger;
import java.util.List;
import java.util.Map;
/**
@@ -147,6 +151,12 @@ public class MapPresenter extends Presenter< MapView > implements
onChoosePath( intent, key_type );
} else if ( key_type == 10021 ) {
if ( CustomNaviInterrupter.getInstance().interrupt() ) {
// 导航过程中语音指令退出导航,会出现 activity 不走 onResume 的情况
UiThreadHandler.postDelayed( () -> {
if ( isForeground( getContext() ) && !hasOthersActivity() && !mStatusManager.isMainPageOnResume() ) {
mLauncher.backToLauncher( getContext() );
}
}, 500L );
return;
}
onStopNaviInternal();
@@ -181,6 +191,34 @@ public class MapPresenter extends Presenter< MapView > implements
getContext().registerReceiver( broadcastReceiver, inputFilter );
}
private boolean isForeground( Context context ) {
if ( context != null ) {
ActivityManager activityManager = ( ActivityManager ) context.getSystemService( Context.ACTIVITY_SERVICE );
List< ActivityManager.RunningAppProcessInfo > processes = activityManager.getRunningAppProcesses();
for ( ActivityManager.RunningAppProcessInfo processInfo : processes ) {
if ( processInfo.processName.equals( context.getPackageName() ) ) {
if ( processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND ) {
return true;
}
}
}
}
return false;
}
private boolean hasOthersActivity() {
ActivityManager am = ( ActivityManager ) getContext().getSystemService( Context.ACTIVITY_SERVICE );
List< ActivityManager.RunningTaskInfo > list = am.getRunningTasks( 1 );
if ( list != null && !list.isEmpty() ) {
for ( ActivityManager.RunningTaskInfo runningTaskInfo : list ) {
if ( TextUtils.equals( runningTaskInfo.topActivity.getPackageName(), getContext().getPackageName() ) ) {
return runningTaskInfo.numActivities > 1;
}
}
}
return true;
}
/**
* 切换交通态势模式
*
@@ -295,7 +333,7 @@ public class MapPresenter extends Presenter< MapView > implements
private void zoomMap( boolean zoomIn ) {
boolean isLocked = mMogoMapService.getMapUIController().isCarLocked();
MapControlResult result = mView.getUIController().changeZoom( zoomIn );
if (! CustomNaviInterrupter.getInstance().interrupt() ) {
if ( !CustomNaviInterrupter.getInstance().interrupt() ) {
if ( result == MapControlResult.TARGET ) {
UiThreadHandler.postDelayed( () -> {
if ( zoomIn ) {

View File

@@ -35,6 +35,9 @@ public class AppOperationIntentHandler implements IntentHandler {
String app = object.optString( "object" );
String operation = object.optString( "operation" );
if ( TextUtils.equals( "打开", operation ) ) {
if ( TextUtils.isEmpty( sAppPackages.get( app ) ) ) {
return;
}
try {
LaunchUtils.launchByPkg( context, sAppPackages.get( app ) );
} catch ( Exception e ) {

View File

@@ -17,4 +17,10 @@ public interface IEventPanelProvider extends IMogoModuleProvider {
* 隐藏面板
*/
void hidePanel();
/**
* 面板是否在展示
* @return true-正在展示 false-未展示
*/
boolean isPanelShow();
}