迁移探路模块和tanlulib代码至此

This commit is contained in:
tongchenfei
2020-08-10 11:29:55 +08:00
parent dffd094b67
commit ee53d50cdb
269 changed files with 13646 additions and 4 deletions

2
.idea/gradle.xml generated
View File

@@ -21,6 +21,7 @@
<option value="$PROJECT_DIR$/libraries/map-autonavi" />
<option value="$PROJECT_DIR$/libraries/mogo-map" />
<option value="$PROJECT_DIR$/libraries/mogo-map-api" />
<option value="$PROJECT_DIR$/libraries/tanlulib" />
<option value="$PROJECT_DIR$/main-extensions" />
<option value="$PROJECT_DIR$/main-extensions/mogo-module-main-independent" />
<option value="$PROJECT_DIR$/main-extensions/mogo-module-main-launcher" />
@@ -47,6 +48,7 @@
<option value="$PROJECT_DIR$/modules/mogo-module-share" />
<option value="$PROJECT_DIR$/modules/mogo-module-splash" />
<option value="$PROJECT_DIR$/modules/mogo-module-splash-noop" />
<option value="$PROJECT_DIR$/modules/mogo-module-tanlu" />
<option value="$PROJECT_DIR$/modules/mogo-module-v2x" />
<option value="$PROJECT_DIR$/services" />
<option value="$PROJECT_DIR$/services/mogo-service" />

View File

@@ -256,9 +256,7 @@ dependencies {
implementation rootProject.ext.dependencies.carcallprovider
implementation rootProject.ext.dependencies.carcall
implementation rootProject.ext.dependencies.moduletanlu, {
exclude group: 'com.mogo.module', module: 'module-share'
}
implementation rootProject.ext.dependencies.mogologlib
if (Boolean.valueOf(RELEASE)) {
@@ -273,6 +271,9 @@ dependencies {
implementation rootProject.ext.dependencies.moduleservice
implementation rootProject.ext.dependencies.modulesplash
implementation rootProject.ext.dependencies.moduleV2x
implementation rootProject.ext.dependencies.moduletanlu, {
exclude group: 'com.mogo.module', module: 'module-share'
}
} else {
launcherImplementation project(':main-extensions:mogo-module-main-launcher')
independentImplementation project(':main-extensions:mogo-module-main-independent')
@@ -284,6 +285,9 @@ dependencies {
implementation project(':modules:mogo-module-service')
implementation project(':modules:mogo-module-splash')
implementation project(':modules:mogo-module-v2x')
implementation project(':modules:mogo-module-tanlu'), {
exclude group: 'com.mogo.module', module: 'module-share'
}
}
apply from: "./functions/baseservices.gradle"

1
libraries/tanlulib/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,70 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'android-aspectjx'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
zipAlignEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.3.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'com.zhidaoauto.common:service:1.0.4.10'
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0'
implementation 'com.zhidaoauto.controller:api:1.0.8'
implementation 'com.zhidao.cosupload:cosuploadsdk:1.1.6'
implementation 'com.zhidao.video:video-processor:1.0.2.1'
implementation 'com.foundation.utils:common-utils:1.0.7'
compileOnly rootProject.ext.dependencies.mogocommons
implementation rootProject.ext.dependencies.eventbus
implementation rootProject.ext.dependencies.coroutinescore
implementation rootProject.ext.dependencies.coroutinesandroid
implementation rootProject.ext.dependencies.retrofit
implementation rootProject.ext.dependencies.retrofitconvertergson
implementation rootProject.ext.dependencies.gson
implementation rootProject.ext.dependencies.rxjava
implementation rootProject.ext.dependencies.rxandroid
compileOnly rootProject.ext.dependencies.mogomap
implementation rootProject.ext.dependencies.aspectj
implementation rootProject.ext.dependencies.analytics
}
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()

View File

@@ -0,0 +1,4 @@
-keep class com.zhidao.roadcondition.model.**{*;}
-keep class com.zhidao.roadcondition.service.*{*;}
-keep class com.zhidao.roadcondition.ShareRoadReceiver.*{*;}

View File

@@ -0,0 +1,3 @@
GROUP=com.mogo.module
POM_ARTIFACT_ID=module-tanlu-upload
VERSION_CODE=1

27
libraries/tanlulib/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,27 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-keep class com.zhidao.roadcondition.model.**{*;}
-keep class com.zhidao.roadcondition.service.*{*;}
-keep class com.zhidao.roadcondition.ShareRoadReceiver.*{*;}

View File

@@ -0,0 +1,25 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zhidao.roadcondition">
<application>
<!--分享相关广播-->
<receiver
android:name=".receiver.ShareRoadReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.zhidao.share.roadcondition.action" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
<!--获取图片和视频的服务-->
<service
android:name=".service.MainService"
android:enabled="true" />
<service
android:name=".service.DelayService"
android:exported="false" />
</application>
</manifest>

View File

@@ -0,0 +1,29 @@
package com.zhidao.roadcondition.aspect
import android.util.Log
import com.zhidao.roadcondition.util.CarNet_Alive
import com.zhidao.roadcondition.util.trackNormalEvent
import org.aspectj.lang.annotation.*
@Aspect
class DAUAspectj {
companion object {
const val TAG = "DAUAspectj"
}
@Pointcut("execution(* com.zhidao.roadcondition.splash_module.SplashActivity.initView())")
fun callDAU() {
}
@Pointcut("execution(* com.zhidao.roadcondition.service.RoadInfoService.launchMainActivity(..))")
fun callDAUOther(){
}
@Before("callDAU() || callDAUOther()")
fun trackDAU() {
Log.i(TAG, "trackDAU")
trackNormalEvent(CarNet_Alive, null)
}
}

View File

@@ -0,0 +1,14 @@
package com.zhidao.roadcondition.aspect;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Target({TYPE, METHOD, CONSTRUCTOR})
@Retention(RUNTIME)
public @interface DebugLog {
}

View File

@@ -0,0 +1,112 @@
package com.zhidao.roadcondition.aspect
import android.os.Looper
import android.os.Trace
import android.util.Log
import com.zhidao.roadcondition.BuildConfig
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Pointcut
import org.aspectj.lang.reflect.CodeSignature
import org.aspectj.lang.reflect.MethodSignature
import java.util.concurrent.TimeUnit
@Aspect
class LogAspectj {
companion object {
@Volatile
private var enable: Boolean = BuildConfig.DEBUG
}
@Pointcut("within(@com.zhidao.roadcondition.aspect.DebugLog *)")
fun withinAnnotatedClass() {}
@Pointcut("execution(!synthetic * *(..))&& withinAnnotatedClass()")
fun methodInsideAnnotatedType() {}
@Pointcut("execution(!synthetic *.new(..))&& withinAnnotatedClass()")
fun constructorInsideAnnotatedType() {}
@Pointcut("execution(@com.zhidao.roadcondition.aspect.DebugLog * *(..))|| methodInsideAnnotatedType()")
fun method() {}
@Pointcut("execution(@com.zhidao.roadcondition.aspect.DebugLog *.new(..))|| constructorInsideAnnotatedType()")
fun constructor() {}
@Around("method() || constructor()")
fun logExecute(joinPoint: ProceedingJoinPoint) {
enterMethod(joinPoint)
var startNanos = System.nanoTime()
var result = joinPoint.proceed()
var stopNanos = System.nanoTime()
var lengthMill = TimeUnit.NANOSECONDS.toMillis(stopNanos - startNanos)
exitMethod(joinPoint, result as Any?, lengthMill)
}
private fun enterMethod(joinPoint: ProceedingJoinPoint) {
if (!enable) return
val signature = joinPoint.signature as CodeSignature
val cls = signature.declaringType
val methodName = signature.name
val parameterNames = signature.parameterNames
val parameterValues = joinPoint.args
var builder = StringBuilder("\u21E2 ")
builder.append(methodName).append('(')
parameterValues.forEachIndexed { index, any ->
if (index > 0) {
builder.append(",")
}
builder.append(parameterNames[index]).append('=')
builder.append(parameterValues[index])
}
builder.append(')')
if (Looper.myLooper() != Looper.getMainLooper()) {
builder.append("[Thread:\"").append(Thread.currentThread().name).append("\"]")
}
Log.i(asTag(cls), builder.toString())
val section = builder.toString().substring(2)
Trace.beginSection(section)
}
private fun exitMethod(joinPoint: ProceedingJoinPoint, result: Any?, lengthMill: Long) {
if (!enable) return
Trace.endSection()
val signature = joinPoint.signature
val cls = signature.declaringType
val methodName = signature.name
var hasReturnType = signature is MethodSignature
&& signature.returnType != Void.TYPE
var builder = StringBuilder("\u21E0 ")
.append(methodName)
.append("[")
.append(lengthMill)
.append("ms]")
if (hasReturnType) {
builder.append(" = ")
builder.append(result.let {
result.toString()
})
}
Log.i(asTag(cls), builder.toString())
}
private fun asTag(cls: Class<*>): String {
// if (cls.isAnonymousClass) {
// return asTag(cls.enclosingClass)
// }
return cls.simpleName
}
}

View File

@@ -0,0 +1,39 @@
package com.zhidao.roadcondition.base
import android.app.IntentService
import android.content.Intent
import android.os.IBinder
open class BaseIntentService : IntentService("BaseIntentService") {
protected var tag: String = this.javaClass.simpleName
override fun onHandleIntent(p0: Intent?) {
tag = this.javaClass.simpleName
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
}
override fun onCreate() {
super.onCreate()
}
override fun onStart(intent: Intent?, startId: Int) {
super.onStart(intent, startId)
}
override fun onBind(intent: Intent?): IBinder? {
return super.onBind(intent)
}
override fun setIntentRedelivery(enabled: Boolean) {
super.setIntentRedelivery(enabled)
}
override fun onDestroy() {
super.onDestroy()
}
}

View File

@@ -0,0 +1,10 @@
package com.zhidao.roadcondition.base
import com.zhidao.roadcondition.model.BaseResponse
open class BaseRepository {
suspend fun <T : Any> apiCall(call: suspend () -> BaseResponse<T>): BaseResponse<T> {
return call.invoke()
}
}

View File

@@ -0,0 +1,61 @@
package com.zhidao.roadcondition.constant
public val STRATEGY_TYPE_PHOTO: String = "0FOoOuB7" //拍照的策略ID
public val STRATEGY_TYPE_VIDEO: String = "gVCl9VdW" //拍视频的策略ID
public val SOCKET_MSG_TYPE: Int = 0x040001 //长连接消息类型
public val SOCKET_PRODUCT_LINE: Int = 0x04 //长连接消息产品线id目前SDK是写死的
const val INFORMATION_DATA_SIZE_LIMIT = 50
const val INFORMATION_DEFAULT_MAP_RADIUS = 10
const val REQUESTCODE_MAINACTIVITY = 0
const val REQUESTCODE_MEDIAACTIVITY = 1
const val CUSTOM_SEND_CMD = "custom_send_cmd" //主动上报语音命令
const val VOICE_PREVIOUS_INFO_CMD = "voice_previous_info_cmd" //上一条
const val VOICE_NEXT_INFO_CMD = "voice_next_info_cmd" //下一条
const val SCHEME_SPLASH_TYPE = "channelType"
const val SCHEME_MAIN_TYPE = "type"
const val PARAM_MAIN_PAGE_ACTION = "action" // 判断主页该干什么
const val VAL_ACTION_TQZ = "tqz" //通勤族
const val VAL_ACTION_PLAY_DIRECTLY = "play" //直接播放情报
const val VAL_ACTION_DHLX = "dhlx" //导航路线
const val CONFIG_NEED_AUTH = "0001" //公共配置 是否查询授权
const val CONFIG_ACTIVE_POSITION = "0002" //公共配置 查询运营位配置
//广播action、key
const val AUTONAVI_STANDARD_BROADCAST_SEND = "AUTONAVI_STANDARD_BROADCAST_SEND"
const val AUTONAVI_STANDARD_BROADCAST_ROAD_INFO = "EXTRA_ROAD_INFO"
const val AUTONAVI_STANDARD_BROADCAST_EXTRA_STATE = "EXTRA_STATE"
//EXTRA_STATE
const val AUTO_NAVI_START = 8 //开始导航
const val AUTO_NAVI_END = 9 //结束导航
const val VALUE_DICT_DATA_TYPE = "deva_infomation_type" // dict 数据请求类型:情报类型数据
//上报的类型
const val TANLU_TRAFFIC_CHECK = "10002" //交通检查
const val TANLU_ROAD_CLOSURE = "10003" //封路
const val TANLU_ROAD_WORK = "10006" //施工
const val TANLU_ROAD_CONGESTION = "10007" //拥堵
const val TANLU_ROAD_PONDING = "10008" //积水
const val TANLU_ROAD_HEAVY_FOG = "10010" //大雾
const val TANLU_ROAD_ICING = "10011" //积冰
const val TANLU_ROAD_ACCIDENT = "10013" //事故
const val TANLU_ROAD_CURRENT = "10015" //实时路况
const val DEF_NEWS_LABEL = "拥堵"
const val DEF_NEWS_VALUE = "traffic_jam"
const val DEF_NEWS_TYPE = "0"

View File

@@ -0,0 +1,34 @@
package com.zhidao.roadcondition.constant
import com.mogo.commons.debug.DebugConfig
import com.zhidao.roadcondition.BuildConfig
class HttpConstants {
companion object {
const val DEV_BASE_URL_OWNER = "http://dzt-test.zhidaohulian.com/"
const val RELEASE_BASE_URL_OWNER = "http://dzt.zhidaohulian.com/"
const val SHOW_BASE_URL_OWNER = "http://dzt-show.zhidaohulian.com/"
fun getBaseUrl(): String {
return when (DebugConfig.getNetMode()) {
DebugConfig.NET_MODE_QA -> DEV_BASE_URL_OWNER
DebugConfig.NET_MODE_RELEASE -> RELEASE_BASE_URL_OWNER
DebugConfig.NET_MODE_DEMO -> SHOW_BASE_URL_OWNER
else -> DEV_BASE_URL_OWNER
}
}
// fun getBaseUrl1(): String {
// return when (BuildConfig.BUILD_TYPE) {
// "debug" -> DEV_BASE_URL_OWNER
// "qa" -> DEV_BASE_URL_OWNER
// "release" -> RELEASE_BASE_URL_OWNER
// "show" -> SHOW_BASE_URL_OWNER
// else -> RELEASE_BASE_URL_OWNER
// }
// }
}
}

View File

@@ -0,0 +1,26 @@
package com.zhidao.roadcondition.event
/**
* @description
*
* @author lixiaopeng
* @since 2019-10-13
*/
class GetImageSuccessEvent {
private var imageUrl: String? = null
private var type: String? = null
constructor(imageUrl: String?, type: String?) {
this.imageUrl = imageUrl
this.type = type
}
fun getImageUrl(): String? {
return imageUrl
}
fun getType(): String? {
return type
}
}

View File

@@ -0,0 +1,18 @@
package com.zhidao.roadcondition.event
import org.greenrobot.eventbus.EventBus
class LatLngStickyEventBus {
companion object {
private var mEventBus = EventBus.builder()
.logNoSubscriberMessages(false)
.sendNoSubscriberEvent(false)
.build()
fun getInstance(): EventBus {
return mEventBus
}
}
}

View File

@@ -0,0 +1,19 @@
package com.zhidao.roadcondition.exception
class ApiException : Exception {
companion object{
val NETWORK_API_EXCEPTION = ApiException(1, "network is error")
val NULL_REQUEST_DATA_API_EXCEPTION = ApiException(2, "request data is null")
}
private var code: Int = 0
private var msg: String = ""
constructor(code: Int, msg: String) : super(msg) {
this.code = code
this.msg = msg
}
}

View File

@@ -0,0 +1,5 @@
package com.zhidao.roadcondition.model
class BaseRequest<T>(var sn: String, var data: T?) {
}

View File

@@ -0,0 +1,12 @@
package com.zhidao.roadcondition.model
import com.zhidao.roadcondition.constant.HttpConstants
class BaseResponse<out T>(val code: Int, val msg: String, val result: T) {
fun isSuccess(baseUrl: String): Boolean {
return when (baseUrl) {
HttpConstants.getBaseUrl() -> true
else -> false
}
}
}

View File

@@ -0,0 +1,97 @@
package com.zhidao.roadcondition.model
class CityStrategy {
var video: Video
var pic: Pic
constructor(video: Video, pic: Pic) {
this.video = video
this.pic = pic
}
}
fun Video.getMaxSpeed(): Int {
return if (maxSpeed == 0) {
-1
} else {
maxSpeed
}
}
class Video {
var strategyId: String //策略ID
var reportType: Int //一次性、周期性
var reportTimeInterval: Int //上传时间间隔 单位:分钟
var infoTimeout: Int //情报失效时间 单位:分钟
var minSpeed: Int = -1//最小速度
var maxSpeed: Int = -1//最大速度
var strategyType: Int //策略类型:城市、热门区域、非上报区域等
constructor(
strategyId: String,
reportType: Int,
reportTimeInterval: Int,
infoTimeout: Int,
minSpeed: Int,
maxSpeed: Int,
strategyType: Int
) {
this.strategyId = strategyId
this.reportType = reportType
this.reportTimeInterval = reportTimeInterval
this.infoTimeout = infoTimeout
this.minSpeed = minSpeed
this.maxSpeed = maxSpeed
this.strategyType = strategyType
}
}
fun Pic.getMaxSpeed(): Int {
return if (maxSpeed == 0) {
-1
} else {
maxSpeed
}
}
class Pic {
var strategyId: String //策略ID
var reportType: Int //一次性、周期性
var reportTimeInterval: Int //上传时间间隔 单位:分钟
var infoTimeout: Int //情报失效时间 单位:分钟
var minSpeed: Int = -1 //最小速度
var maxSpeed: Int = -1 //最大速度
var strategyType: Int //策略类型:城市、热门区域、非上报区域等
constructor(
strategyId: String,
reportType: Int,
reportTimeInterval: Int,
infoTimeout: Int,
minSpeed: Int,
maxSpeed: Int,
strategyType: Int
) {
this.strategyId = strategyId
this.reportType = reportType
this.reportTimeInterval = reportTimeInterval
this.infoTimeout = infoTimeout
this.minSpeed = minSpeed
this.maxSpeed = maxSpeed
this.strategyType = strategyType
}
}
class StrategyRequest {
var lon: Double
var lat: Double
var cityCode: String
constructor(lon: Double, lat: Double, cityCode: String) {
this.lon = lon
this.lat = lat
this.cityCode = cityCode
}
}

View File

@@ -0,0 +1,55 @@
package com.zhidao.roadcondition.model
fun CommonConfig.isActiveNonNull():Boolean{
return active!=null
}
//fun CommonConfig.isPromotionNonNull():Boolean{
// return promotion!=null
//}
class CommonConfig {
var active:Active //活动配置
// var promotion:Promotion //Splash页面图片以及语音推广配置
var auth:Auth //授权配置
constructor(active: Active, auth: Auth) {
this.active = active
// this.promotion = promotion
this.auth = auth
}
}
class Active{
var imageUrl:String
var webUrl:String
var status:Int
constructor(imageUrl: String, webUrl: String, status: Int) {
this.imageUrl = imageUrl
this.webUrl = webUrl
this.status = status
}
}
class Promotion{
var imageUrl:String
var voiceContent:String
var status:Int
constructor(imageUrl: String, voiceContent: String, status: Int) {
this.imageUrl = imageUrl
this.voiceContent = voiceContent
this.status = status
}
}
class Auth{
var isNeedAuth:Int
constructor(isNeedAuth: Int) {
this.isNeedAuth = isNeedAuth
}
}

View File

@@ -0,0 +1,24 @@
package com.zhidao.roadcondition.model
data class InformationBody(
val data: String,
val addr: String,
val areaCode: String,
val areaName: String,
val cityCode: String,
val cityName: String,
val generateTime: Long,
val lat: Double,
val lon: Double,
val provinceName: String,
val sn: String,
val street: String,
val type: Int,
val uid: Int,
val infoType: Int,
val infoTimeout:Int,
val trafficInfoType:String, // 上报情报类型
val isShare: Boolean, // 是否分享给附近车机
val direction: Float,
val poiType: String //类型分类
)

View File

@@ -0,0 +1,41 @@
package com.zhidao.roadcondition.model
/**
* @author congtaowang
* @since 2019-11-22
*
* 一次情报的数据
*/
class InformationResource {
var id: Long
var isCosResourceReady: Boolean = false
var isInformationSelected: Boolean = false
var sourceType: Int = 0 // 情报载体类型:图片、视频
var cosParameter: Map<String, String>? = null // 情报参数
var informationType: InformationType? = null //情报类型
var isCustomSend: Boolean = false // 自动上传
var callback: ((customSend: Boolean) -> Unit)? = null
lateinit var newsType: String // 埋点:情报类型
lateinit var operType: String // 埋点:操作类型
constructor(id: Long) {
this.id = id
}
fun isReady() = isCosResourceReady and isInformationSelected
fun release() {
cosParameter = null
informationType = null
callback = null
}
override fun toString(): String {
return "upload information: sourceType=${sourceType}, informationType={${informationType?.dictLabel}, ${informationType?.dictValue}}"
}
}

View File

@@ -0,0 +1,29 @@
package com.zhidao.roadcondition.model
import com.google.gson.Gson
import com.zhidao.roadcondition.constant.DEF_NEWS_LABEL
import com.zhidao.roadcondition.constant.DEF_NEWS_TYPE
import com.zhidao.roadcondition.constant.DEF_NEWS_VALUE
/**
* @author congtaowang
* @since 2019-11-18
*
* 情报类型
*/
data class InformationType(var dictLabel: String, var dictValue: String, var remark: String) {
companion object {
val def = InformationType(DEF_NEWS_LABEL, DEF_NEWS_VALUE, DEF_NEWS_TYPE)
}
override fun equals(other: Any?): Boolean {
when (other) {
is InformationType -> return other.dictValue.compareTo(dictValue) == 0
}
return super.equals(other)
}
override fun toString(): String {
return Gson().toJson(this)
}
}

View File

@@ -0,0 +1,9 @@
package com.zhidao.roadcondition.model
/**
* @author congtaowang
* @since 2019-11-18
*
* 描述
*/
data class InformationTypeResult(var types: List<InformationType>)

View File

@@ -0,0 +1,69 @@
package com.zhidao.roadcondition.model
import android.os.Parcel
import android.os.Parcelable
import com.amap.api.maps.model.LatLng
fun Informations.toLatLng(): LatLng {
return LatLng(lat, lon)
}
class Informations(
var type: Int,
var lon: Double,
var lat: Double,
var addr: String?,
var generateTime: Long,
var cityName: String?,
// var items: ArrayList<Items>,
var distance: Int,
var nickName: String?,
var headImgUrl: String?
) :
Parcelable {
var position = 0
constructor(parcel: Parcel) : this(
parcel.readInt(),
parcel.readDouble(),
parcel.readDouble(),
parcel.readString(),
parcel.readLong(),
parcel.readString(),
// parcel.readArrayList(Items::class.java.classLoader) as ArrayList<Items>,
parcel.readInt(),
parcel.readString(),
parcel.readString()
)
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(type)
parcel.writeDouble(lon)
parcel.writeDouble(lat)
parcel.writeString(addr)
parcel.writeLong(generateTime)
parcel.writeString(cityName)
// parcel.writeList(items)
parcel.writeInt(distance)
parcel.writeString(nickName)
parcel.writeString(headImgUrl)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<Informations> {
override fun createFromParcel(parcel: Parcel): Informations {
return Informations(parcel)
}
override fun newArray(size: Int): Array<Informations?> {
return arrayOfNulls(size)
}
}
}

View File

@@ -0,0 +1,33 @@
package com.zhidao.roadcondition.model
import android.os.Parcel
import android.os.Parcelable
class Items(var url: String?, var thumbnail: String? = null) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readString()
) {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(url)
parcel.writeString(thumbnail)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<Items> {
override fun createFromParcel(parcel: Parcel): Items {
return Items(parcel)
}
override fun newArray(size: Int): Array<Items?> {
return arrayOfNulls(size)
}
}
}

View File

@@ -0,0 +1,62 @@
package com.zhidao.roadcondition.model
import com.amap.api.maps.model.LatLng
import com.amap.api.services.core.LatLonPoint
fun LocationInfo.toLatLng(): LatLng {
return LatLng(latitude,longitude)
}
fun LocationInfo.toLatLngPoint():LatLonPoint{
return LatLonPoint(latitude,longitude)
}
class LocationInfo {
var provinceName: String = "" //省的名称
var cityName: String = "" //城市的名称
var cityCode :String = "" //城市编码
var areaName :String = "" //区县名称
var areaCode :String = "" //区县编码
var street :String = "" //街道名称
var longitude: Double = 0.0
var latitude: Double = 0.0
var address: String = ""
var time: Long = 0L
var direction: Float = 0.0f
constructor()
constructor(longitude: Double, latitude: Double, address: String, time: Long) {
this.longitude = longitude
this.latitude = latitude
this.address = address
this.time = time
}
constructor(
provinceName: String,
cityName: String,
cityCode: String,
areaName: String,
areaCode: String,
street: String,
longitude: Double,
latitude: Double,
address: String,
time: Long,
direction: Float = 0.0f
) {
this.provinceName = provinceName
this.cityName = cityName
this.cityCode = cityCode
this.areaName = areaName
this.areaCode = areaCode
this.street = street
this.longitude = longitude
this.latitude = latitude
this.address = address
this.time = time
this.direction = direction
}
}

View File

@@ -0,0 +1,8 @@
package com.zhidao.roadcondition.model
/**
* 城市策略实体
*/
class Results(var cityStrategy: CityStrategy) {
}

View File

@@ -0,0 +1,68 @@
package com.zhidao.roadcondition.model
import android.util.Log
import com.google.gson.Gson
import com.mogo.commons.network.Utils
import com.zhidao.roadcondition.base.BaseRepository
import com.zhidao.roadcondition.net.HttpClient
import com.zhidao.roadcondition.util.LocationUtil
class StrategyServiceModel : BaseRepository() {
suspend fun getCityStrategy(): BaseResponse<Results> {
return apiCall {
var map = hashMapOf<String, String>()
map["sn"] = Utils.getSn()
val locInfo = LocationUtil.getInstance().getLocationInfo()
map["data"] = Gson().toJson(
StrategyRequest(
locInfo.longitude,
locInfo.latitude,
locInfo.cityCode
)
)
HttpClient.getInstance().getHttpApi().getCityStrategy(map)
}
}
// suspend fun getAuthorization(): BaseResponse<Any> {
// return apiCall {
// HttpClient.getInstance().getHttpApi().getAuthorization(getSn())
// }
// }
//
// suspend fun getAllConfig(): BaseResponse<CommonConfig> {
// return apiCall {
// var map = hashMapOf<String, String>()
// map["sn"] = getSn()
// HttpClient.getInstance().getHttpApi()
// .getAllCommonConfig(map)
// }
// }
//
// suspend fun getSplashConfig(): BaseResponse<SplashConfig> {
// return apiCall {
// var splashConfigRequest =
// SplashConfigRequest("1", "1")
// var splashBodyStr = Gson().toJson(splashConfigRequest)
//
// HttpClient.getInstance().getHttpApi()
// .getSplashConfig(
// mapOf(
// "sn" to getSn(),
// "data" to splashBodyStr
// )
// )
//
// }
// }
suspend fun uploadInformation(informationBody: InformationBody): BaseResponse<Any> {
return apiCall {
var informationBodyStr = Gson().toJson(informationBody)
Log.d("MainServiceController", "uploadInformation informationBody = " + informationBodyStr)
HttpClient.getInstance().getHttpApi()
.uploadInformation(mapOf("sn" to Utils.getSn(), "data" to informationBodyStr))
}
}
}

View File

@@ -0,0 +1,22 @@
package com.zhidao.roadcondition.model.proxy
import androidx.annotation.IntDef
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
const val INFO_TYPE_GONE = 0
const val INFO_TYPE_SHOW = 1
@IntDef(INFO_TYPE_GONE, INFO_TYPE_SHOW)
@Retention(RetentionPolicy.SOURCE)
annotation class ActiveInfoType
fun isActiveShow(@ActiveInfoType type: Int): Boolean {
return when (type) {
INFO_TYPE_GONE -> false
INFO_TYPE_SHOW -> true
else -> false
}
}

View File

@@ -0,0 +1,16 @@
package com.zhidao.roadcondition.model.proxy
import androidx.annotation.IntDef
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
const val INFO_TYPE_IMG = 0 //图片
const val INFO_TYPE_VIDEO = 1
const val INFO_TYPE_VOICE = 2
const val INFO_TYPE_WORD = 3
@IntDef(INFO_TYPE_IMG, INFO_TYPE_VIDEO, INFO_TYPE_VOICE, INFO_TYPE_WORD)
@Retention(RetentionPolicy.SOURCE)
annotation class InformationsType

View File

@@ -0,0 +1,17 @@
package com.zhidao.roadcondition.net
import android.util.Log
import okhttp3.Interceptor
import okhttp3.Response
class CommonInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val oldRequest = chain.request()
val newRequest = oldRequest.newBuilder()
Log.d("CommonInterceptor","addHeader")
newRequest.header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
return chain.proceed(newRequest.build())
}
}

View File

@@ -0,0 +1,71 @@
package com.zhidao.roadcondition.net
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent
import com.zhidao.roadcondition.exception.ApiException
import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers.Main
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import java.util.concurrent.TimeoutException
/**
* 后续考虑加入Lifecycle管理暂时不做扩展
*/
class CoroutineChain {
internal class CoroutineLifecycleListener(private val deferred: Deferred<*>, private val lifecycle: Lifecycle) :
LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun cancelCoroutine() {
if (deferred.isActive) {
deferred.cancel()
}
lifecycle.removeObserver(this)
}
}
infix fun LifecycleOwner.start(start: (() -> Unit)): LifecycleOwner {
start()
return this
}
infix fun <T> LifecycleOwner.request(loader: suspend () -> T): Deferred<T> {
return request(loader, true)
}
fun <T> LifecycleOwner.request(loader: suspend () -> T, needAutoCancel: Boolean = true): Deferred<T> {
val deferred = GlobalScope.async(Dispatchers.IO, start = CoroutineStart.LAZY) {
loader()
}
if (needAutoCancel) {
lifecycle.addObserver(CoroutineLifecycleListener(deferred, lifecycle))
}
return deferred
}
fun <T> Deferred<T>.then(
onSuccess: suspend (T) -> Unit,
onError: suspend (java.lang.Exception) -> Unit,
onComplete: (() -> Unit)? = null
): Job {
return GlobalScope.launch(context = Main) {
try {
val result = this@then.await()
onSuccess(result)
} catch (e: Exception) {
e.printStackTrace()
when (e) {
is UnknownHostException -> onError?.invoke(ApiException.NETWORK_API_EXCEPTION)
is TimeoutException -> onError?.invoke(ApiException.NETWORK_API_EXCEPTION)
is SocketTimeoutException -> onError?.invoke(ApiException.NETWORK_API_EXCEPTION)
else -> onError(e)
}
} finally {
onComplete?.invoke()
}
}
}
}

View File

@@ -0,0 +1,104 @@
package com.zhidao.roadcondition.net
import androidx.lifecycle.LifecycleOwner
import com.zhidao.roadcondition.exception.ApiException
import com.zhidao.roadcondition.exception.ApiException.Companion.NETWORK_API_EXCEPTION
import com.zhidao.roadcondition.exception.ApiException.Companion.NULL_REQUEST_DATA_API_EXCEPTION
import com.zhidao.roadcondition.model.BaseResponse
import kotlinx.coroutines.*
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import java.util.concurrent.TimeoutException
class Request<T> {
private lateinit var loader: suspend () -> T
private var start: (() -> Unit)? = null
private var onSuccess: ((T) -> Unit)? = null
private var onError: ((java.lang.Exception) -> Unit)? = null
private var onComplete: (() -> Unit)? = null
private var addLifecycle: LifecycleOwner? = null
infix fun loader(loader: suspend () -> T) {
this.loader = loader
}
infix fun start(start: (() -> Unit)?) {
this.start = start
}
infix fun onSuccess(onSuccess: ((T) -> Unit)?) {
this.onSuccess = onSuccess
}
infix fun onError(onError: ((java.lang.Exception) -> Unit)?) {
this.onError = onError
}
infix fun onComplete(onComplete: (() -> Unit)?) {
this.onComplete = onComplete
}
infix fun addLifecycle(addLifecycle: LifecycleOwner?) {
this.addLifecycle = addLifecycle
}
fun request() {
request(addLifecycle)
}
fun request(addLifecycle: LifecycleOwner?) {
GlobalScope.launch(context = Dispatchers.Main) {
start?.invoke()
try {
val deferred = GlobalScope.async(Dispatchers.IO, start = CoroutineStart.LAZY) {
loader()
}
addLifecycle?.apply {
lifecycle.addObserver(
CoroutineChain.CoroutineLifecycleListener(
deferred,
lifecycle
)
)
}
val result = deferred.await()
if (result != null && result is BaseResponse<*>) {
if (result.code == 0) {
onSuccess?.invoke(result)
} else {
throw ApiException(result.code, result.msg)
}
} else {
throw NULL_REQUEST_DATA_API_EXCEPTION
}
} catch (e: Exception) {
e.printStackTrace()
//数据打点
when (e) {
is UnknownHostException -> onError?.invoke(NETWORK_API_EXCEPTION)
is TimeoutException -> onError?.invoke(NETWORK_API_EXCEPTION)
is SocketTimeoutException -> onError?.invoke(NETWORK_API_EXCEPTION)
else -> onError?.invoke(java.lang.Exception(e.message))
}
} finally {
onComplete?.invoke()
}
}
}
}
inline fun <T> request(buildRequest: Request<T>.() -> Unit) {
Request<T>().apply(buildRequest).request()
}
inline fun <T> LifecycleOwner.request(buildRequest: Request<T>.() -> Unit) {
Request<T>().apply(buildRequest).request(this)
}

View File

@@ -0,0 +1,28 @@
package com.zhidao.roadcondition.net
import com.zhidao.roadcondition.model.BaseResponse
import com.zhidao.roadcondition.model.CommonConfig
import com.zhidao.roadcondition.model.Results
import okhttp3.MultipartBody
import okhttp3.ResponseBody
import retrofit2.http.*
/**
* 接口声明
*/
interface HttpApi {
//获取城市策略
@FormUrlEncoded
@POST("yycp-geo-fence-carService/car/carStrategy/no/getCityStrategy/v1")
suspend fun getCityStrategy(@FieldMap cityStrategy: Map<String, String>): BaseResponse<Results>
//上报情报数据
@FormUrlEncoded
@POST("/deva/car/path/no/addInfomation/v2")
suspend fun uploadInformation(@FieldMap information: Map<String, String>): BaseResponse<Any>
//获取所有配置
@GET("dataService/car/customConfig/no/getAll/v1")
suspend fun getAllCommonConfig(@QueryMap commonConfigBody: Map<String, String>):BaseResponse<CommonConfig>
}

View File

@@ -0,0 +1,87 @@
package com.zhidao.roadcondition.net
import com.mogo.commons.AbsMogoApplication
import com.zhidao.roadcondition.constant.HttpConstants
import okhttp3.Cache
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.File
import java.util.*
import java.util.concurrent.TimeUnit
class HttpClient {
companion object {
const val DEFAULT_CONNECT_TIME = 30L
const val DEFAULT_WRITE_TIMEOUT = 30L
const val DEFAULT_READ_TIMEOUT = 30L
const val COMMON_PARAM_SN = "sn"
private var baseUrlClientMap = HashMap<String, HttpClient>()
fun getInstance(): HttpClient {
var baseUrl = HttpConstants.getBaseUrl()
var httpClient = baseUrlClientMap[baseUrl]
if (httpClient == null) {
synchronized(HttpClient::class.java) {
if (httpClient == null) {
httpClient = HttpClient(baseUrl)
baseUrlClientMap[baseUrl] = httpClient!!
}
}
}
return httpClient!!
}
fun getInstance(baseUrl: String): HttpClient {
var httpClient = baseUrlClientMap[baseUrl]
if (httpClient == null) {
synchronized(HttpClient::class.java) {
if (httpClient == null) {
httpClient = HttpClient(baseUrl)
baseUrlClientMap[baseUrl] = httpClient!!
}
}
}
return httpClient!!
}
}
private lateinit var retrofit: Retrofit
private lateinit var httpApi: HttpApi
private constructor(baseUrl: String) {
retrofit = Retrofit.Builder()
.client(getOkHttpClient())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(baseUrl)
.build()
httpApi = retrofit.create(HttpApi::class.java)
}
fun getHttpApi(): HttpApi {
return httpApi
}
private fun getOkHttpClient(): OkHttpClient {
val httpLoggingInterceptor = HttpLoggingInterceptor()
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
val cacheFile = File(AbsMogoApplication.getApp().applicationContext.cacheDir, "cache")
val cache = Cache(cacheFile, 1024 * 1024 * 50)
return OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor)
.cache(cache)
.connectTimeout(DEFAULT_CONNECT_TIME, TimeUnit.SECONDS)
.readTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(DEFAULT_WRITE_TIMEOUT, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.build()
}
}

View File

@@ -0,0 +1,43 @@
package com.zhidao.roadcondition.net
import androidx.annotation.NonNull
import okhttp3.MediaType
import okhttp3.RequestBody
import okhttp3.internal.Util
import okio.BufferedSink
class PostCommonBody : RequestBody {
companion object {
val CONTENT_TYPE = MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8")
val charset = Util.UTF_8
fun create(@NonNull content: String): RequestBody {
return PostCommonBody(content)
}
}
private var content: String
constructor(@NonNull content: String) {
this.content = content
}
fun getContent(): String {
return content
}
override fun contentType(): MediaType? {
return CONTENT_TYPE
}
override fun writeTo(sink: BufferedSink) {
if (content.isNullOrEmpty()) {
throw NullPointerException("content == null")
}
val bytes = content.toByteArray(charset)
Util.checkOffsetAndCount(bytes!!.size.toLong(), 0, bytes!!.size.toLong())
sink.write(bytes, 0, bytes!!.size)
}
}

View File

@@ -0,0 +1,28 @@
package com.zhidao.roadcondition.net
import com.zhidao.roadcondition.constant.HttpConstants
import com.zhidao.roadcondition.exception.ApiException
import com.zhidao.roadcondition.model.BaseResponse
import io.reactivex.functions.Function
class ResponseFunction<T> : Function<BaseResponse<T>, T> {
private var baseUrl: String = ""
constructor() {
this.baseUrl = HttpConstants.getBaseUrl()
}
constructor(baseUrl: String) {
this.baseUrl = baseUrl
}
override fun apply(t: BaseResponse<T>): T {
if (t == null || !t.isSuccess(baseUrl)) {
throw ApiException(t.code, t.msg)
}
return t.result
}
}

View File

@@ -0,0 +1,19 @@
package com.zhidao.roadcondition.receiver
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import com.zhidao.roadcondition.service.MainService
class ShareRoadReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d("MainService", "ShareRoadReceiver ------> intent.action = " + intent.action)
if (intent.action == "com.zhidao.share.roadcondition.action") {
var type = intent.getStringExtra("type")
Log.d("MainService", "ShareRoadReceiver type ----> $type")
MainService.launchService(context, type)
}
}
}

View File

@@ -0,0 +1,408 @@
package com.zhidao.roadcondition.service
import android.content.Intent
import android.text.TextUtils
import android.util.Log
import com.hw.videoprocessor.VideoProcessor
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.debug.DebugConfig
import com.mogo.utils.NetworkUtils
import com.mogo.utils.TipToast
import com.zhidao.auto.carcorder.callback.TakePhotoCallback
import com.zhidao.auto.carcorder.callback.TakeVideoCallback
import com.zhidao.auto.carcorder.controller.ZdCarCoderController
import com.zhidao.roadcondition.BuildConfig
import com.zhidao.roadcondition.constant.*
import com.zhidao.roadcondition.event.GetImageSuccessEvent
import com.zhidao.roadcondition.event.LatLngStickyEventBus
import com.zhidao.roadcondition.model.proxy.INFO_TYPE_IMG
import com.zhidao.roadcondition.model.proxy.INFO_TYPE_VIDEO
import com.zhidao.roadcondition.util.*
import com.zhidao.roadcondition.util.StrategyPreferenceUtil.Companion.getStrategyMaxSpeed
import com.zhidao.roadcondition.util.StrategyPreferenceUtil.Companion.getStrategyMinSpeed
import com.zhidao.roadcondition.util.StrategyPreferenceUtil.Companion.getStrategyType
import java.io.File
/**
* @description 记录仪相关操作
*
* @author lixiaopeng
* @since 2019-10-30
*/
object CarCorderController : TakePhotoCallback, TakeVideoCallback {
private lateinit var zdCarCoderController: ZdCarCoderController
val TAG: String = this.javaClass.simpleName
var outputVideoPath: String = ""
var mType: String = "" //1 上报拥堵, 2 封路和查车
private var getVideoFailed: (() -> Unit)? = null
private var interceptors: ArrayList<TakePhotoInterceptor> = ArrayList(1)
fun getVideoFailed(getVideoFailed: (() -> Unit)) {
this.getVideoFailed = getVideoFailed
}
fun registerTakePhotoInterceptor(interceptor: TakePhotoInterceptor) {
interceptor?.apply {
interceptors.add(this)
}
}
fun unregisterTakePhotoInterceptor(interceptor: TakePhotoInterceptor) {
interceptor?.apply {
interceptors.remove(interceptor)
}
}
fun initCarCorderController() {
zdCarCoderController =
ZdCarCoderController.getInstance(AbsMogoApplication.getApp().applicationContext)
zdCarCoderController.addCallback(this)
zdCarCoderController.addVideoCallback(this)
zdCarCoderController.init()
}
fun takePhoto(
photoType: Int,
cameraId: Int,
haveVoice: Boolean,
isCustom: Boolean = false,
type: String
) {
Log.d(TAG, "takePhoto ---------- type = $type" + " >>>mType =" + mType)
CustomStatusHandler.offerPhotoStatus(isCustom)
zdCarCoderController.takePhoto(photoType, cameraId, haveVoice)
trackGetPhoto(1)
this.mType = type
}
/**
* @param isCustom: 是否手动上传
* @param id: 标志是哪一个上传
*/
fun takeVideo(
cameraId: Int,
duration: Int,
isCustom: Boolean = false,
id: Long = 0L,
type: String
) {
Log.d(TAG, "takeVideo -------- type = $type")
Log.d(TAG, "takeVideo -------- isCustom = $isCustom")
this.mType = type
if (DebugConfig.getCarMachineType() == 0) { //自研车机
outputVideoPath = getCompressVideoPath()
CustomStatusHandler.offerVideoStatus(TakeEntity(isCustom, id))
zdCarCoderController.takeVideo(cameraId, duration)
trackGetVideo(1)
} else { //比亚迪
Log.d(TAG, "takeVideo ------ isnet = " + NetworkUtils.isConnected(AbsMogoApplication.getApp().applicationContext))
// if (!NetworkUtils.isConnected(AbsMogoApplication.getApp().applicationContext)) {
// TipToast.shortTip("分享失败,请检查网络")
// } else {
//失败了,传空地址,发起请求
val entity = TakeEntity(isCustom, id)
videoAndThumbMap["video"] = ""
videoAndThumbMap["thumb"] = ""
CosStatusController().sendInformationDirectly(
INFO_TYPE_VIDEO,
videoAndThumbMap,
mType,
entity
)
//地图上打点
taskAsync(3_000) {
try {
LatLngStickyEventBus.getInstance()
.postSticky(GetImageSuccessEvent("", mType))
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
}
// }
}
}
fun release() {
zdCarCoderController.release()
interceptors?.clear()
}
//拍照失败回调
override fun onTakePhotoFail(photoType: Int, camera: Int) {
trackGetPhoto(3)
interceptors.forEach {
it?.onTakePhotoFail(photoType, camera)
}
val isCustom = CustomStatusHandler.pollPhotoStatus()
val entity = TakeEntity(isCustom, 0L)
Log.e(TAG, "onTakePhotoFail -----mType = $mType ")
Log.e(TAG, "onTakePhotoFail -----isCustom = $isCustom ")
//语音播报 1上报路况2交通检查3封路 默认 mType 应该为null
if (mType.equals(TANLU_ROAD_CONGESTION) || mType.equals(TANLU_TRAFFIC_CHECK) || mType.equals(
TANLU_ROAD_CLOSURE
)
|| mType.equals(TANLU_ROAD_CURRENT) || mType.equals(TANLU_ROAD_PONDING) || mType.equals(
TANLU_ROAD_ICING
)
|| mType.equals(TANLU_ROAD_HEAVY_FOG) || mType.equals(TANLU_ROAD_ACCIDENT) || mType.equals(
TANLU_ROAD_WORK
)
) {
taskAsync(1_500) {
try {
// VoiceController.speakVoice("上报失败")
// if (isCustom) {
// sendGetInfoFailedReceiver(mType)
// }
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
}
//获取图片失败也上报,图片不打点
if (isCustom) {
CosStatusController().sendInformationDirectly(
INFO_TYPE_IMG,
mutableMapOf("pic" to "" as String),
mType,
entity
);
}
}
}
private fun sendGetInfoFailedReceiver(type: String) {
Log.e(TAG, "sendGetInfoFailedReceiver ------>")
var intent = Intent()
intent.action = "com.zhidao.roadcondition.getinfo.failed"
intent.putExtra("type", type)
AbsMogoApplication.getApp().applicationContext.sendBroadcast(intent)
}
//拍照成功回调返回图片本地路径
override fun onTakePhotoSuccess(photoType: Int, camera: Int, photoPath: String?) {
trackGetPhoto(2)
Log.d(TAG, "onTakePhotoSuccess -----mType = $mType")
val isCustom = CustomStatusHandler.pollPhotoStatus()
val entity = TakeEntity(isCustom, 0L)
if (!isCustom) {
trackNormalEvent(CarNet_auto_upload, null)
}
var interceptor = false
interceptors.forEach {
interceptor = it?.intercept()
it?.onTakePhotoSuccess(photoType, camera, photoPath)
}
if (interceptor) {
return
}
var minSpeedPic =
getStrategyMinSpeed(
AbsMogoApplication.getApp().applicationContext,
"pic",
getStrategyType("pic")
)
var maxSpeedPic =
getStrategyMaxSpeed(
AbsMogoApplication.getApp().applicationContext,
"pic",
getStrategyType("pic")
)
var speed = LocationUtil.getInstance().getSpeed()
if (!TextUtils.isEmpty(mType)) {
Log.d(TAG, "onTakePhotoSuccess mType != null")
CosStatusController().uploadFile(mutableListOf(photoPath as String), entity, mType)
} else {
Log.d(TAG, "onTakePhotoSuccess mType == null")
Log.d(
TAG,
"onTakePhotoSuccess maxSpeedPic = $maxSpeedPic ---> speed = $speed ---->minSpeedPic= $minSpeedPic"
)
if (maxSpeedPic == -1) {
if (speed >= (Math.abs(minSpeedPic) / 3.6f)) {
Log.d(TAG, "onTakePhotoSuccess abs =" + (Math.abs(minSpeedPic) / 3.6f))
CosStatusController().uploadFile(
mutableListOf(photoPath as String),
entity,
mType
)
}
}
if (minSpeedPic > 0 && maxSpeedPic > 0) {
Log.d(TAG, "onTakePhotoSuccess minSpeedPic > 0 -- speed = $speed")
if ((speed >= (minSpeedPic / 3.6f)) && speed <= (maxSpeedPic / 3.6f)) {
CosStatusController().uploadFile(
mutableListOf(photoPath as String),
entity,
mType
)
}
}
}
}
//获取视频成功
override fun onTakeVideoSuccess(camera: Int, videoPath: String?) {
var thumbnailPath =
AbsMogoApplication.getApp().applicationContext.filesDir.parent + File.separator + "Thumbnail${System.currentTimeMillis()}.jpg"
var isSuccess = getVideoThumbnail(videoPath!!, thumbnailPath)
Log.d(
TAG,
"getVideo onTakeVideoSuccess===$videoPath -----> isSuccess= $isSuccess ----> mType = $mType "
)
val entity = CustomStatusHandler.pollVideoStatus()
if (!entity?.isCustom) {
trackNormalEvent(CarNet_auto_upload_video, null)
}
if (isSuccess) {
var minSpeedVideo = getStrategyMinSpeed(
AbsMogoApplication.getApp().applicationContext, "video",
getStrategyType("video")
)
var maxSpeedVideo = getStrategyMaxSpeed(
AbsMogoApplication.getApp().applicationContext, "video",
getStrategyType("video")
)
var speed = LocationUtil.getInstance().getSpeed()
//TODO
if (BuildConfig.DEBUG) {
//获取视频以及缩略图成功,开始上报
compressVideo(videoPath, thumbnailPath, entity)
return
}
if (entity?.isCustom) {
compressVideo(videoPath, thumbnailPath, entity)
} else {
Log.d(
TAG,
"onTakeVideoSuccess maxSpeedVideo = $maxSpeedVideo --->speed= $speed + minSpeedVideo = $minSpeedVideo"
)
if (maxSpeedVideo == -1) {
Log.d(TAG, "onTakeVideoSuccess 111 abs =" + (Math.abs(minSpeedVideo) / 3.6f))
if (speed >= (Math.abs(minSpeedVideo) / 3.6f)) {
//获取视频以及缩略图成功,开始上报
compressVideo(videoPath, thumbnailPath, entity)
}
}
if (minSpeedVideo > 0 && maxSpeedVideo > 0) {
Log.d(TAG, "onTakeVideoSuccess minSpeedVideo > 0 -- speed = $speed")
if ((speed >= (minSpeedVideo / 3.6f)) && speed <= (maxSpeedVideo / 3.6f)) {
compressVideo(videoPath, thumbnailPath, entity)
}
}
}
trackGetVideo(2)
}
}
var videoAndThumbMap: MutableMap<String, String> = mutableMapOf()
//获取视频失败
override fun onTakeVideoFail(camera: Int) {
trackGetVideo(3)
Log.e(TAG, "getVideo onTakeVideoFail")
getVideoFailed?.invoke()
val entity = CustomStatusHandler.pollVideoStatus()
InformationUploadController.release(entity?.id)
Log.e(TAG, "getVideo onTakeVideoFail entity?.isCustom =" + entity?.isCustom)
if (entity?.isCustom) {
// sendGetInfoFailedReceiver(mType)
}
//失败了,传空地址,发起请求
videoAndThumbMap["video"] = ""
videoAndThumbMap["thumb"] = ""
CosStatusController().sendInformationDirectly(
INFO_TYPE_VIDEO,
videoAndThumbMap,
mType,
entity
)
//地图上打点
taskAsync(3_000) {
try {
LatLngStickyEventBus.getInstance().postSticky(GetImageSuccessEvent("", mType))
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
}
}
/**
* 压缩视频并且上传
*/
fun compressVideo(videoPath: String, thumbnailPath: String, entity: TakeEntity) {
Log.d(
TAG,
"outputVideoPath = " + outputVideoPath + ">> videoPath=" + videoPath + " isCustom = ${entity?.isCustom}"
)
var startTime = System.currentTimeMillis()
Thread(Runnable {
try {
VideoProcessor.processor(AbsMogoApplication.getApp().applicationContext)
.input(videoPath)
.output(outputVideoPath)
.removeAudio(true)
.outWidth(1920)
.outHeight(1080)
.bitrate(2000 * 1024)
.frameRate(25)
.process()
Log.d(TAG, "compress cost time =" + (System.currentTimeMillis() - startTime))
CosStatusController().uploadFile(
mutableListOf(outputVideoPath, thumbnailPath),
entity,
mType
)
//删除压缩前的视频
deletePicFile(videoPath)
} catch (e: Exception) {
Log.e(TAG, "compressVideo e = $e")
//删除压缩前的视频
deletePicFile(videoPath)
e.printStackTrace()
}
}).start()
}
override fun onTakePhotoCancel(photoType: Int, camera: Int) {
Log.d(TAG, "onTakePhotoCancel -----photoType = $photoType")
}
override fun onTakeVideoCancel(camera: Int) {
Log.d(TAG, "onTakeVideoCancel -----camera = $camera")
}
//获取图片
private fun trackGetPhoto(type: Int) {
trackNormalEvent(
CarNet_Get_Picture, mutableMapOf("type" to type),
AbsMogoApplication.getApp().applicationContext
)
}
//获取视频
private fun trackGetVideo(type: Int) {
trackNormalEvent(
CarNet_Get_Video, mutableMapOf("type" to type),
AbsMogoApplication.getApp().applicationContext
)
}
}

View File

@@ -0,0 +1,91 @@
package com.zhidao.roadcondition.service
import android.util.Log
import com.zhidao.cosupload.callback.CosStatusCallback
import com.zhidao.cosupload.callback.CosStatusCallbackManager
/**
* @author congtaowang
* @since 2019-11-25
*
*/
object CosCallbackMapController : CosStatusCallback {
val TAG = "CosCallbackMapController"
val map: MutableMap<String, CosStatusCallback> = mutableMapOf()
var uploadFailed: (() -> Unit)? = null
var mainService: MainService? = null
fun init(mainService: MainService) {
this.mainService = mainService
CosStatusCallbackManager.getInstance().register(this)
}
fun uploadFailed(uploadFailed: (() -> Unit)) {
this.uploadFailed = uploadFailed
}
fun registerCallback(paths: List<String>, callback: CosStatusCallback) {
paths?.let { list ->
list.forEach { path ->
path?.let {
map[path] = callback
}
}
}
}
fun unregisterCallback(path: String?) {
path?.let {
map.remove(path)
}
Log.d(TAG, "size: ${map.size}")
}
fun unregisterCallbacks(paths: Map<String, String>?) {
paths?.let {
it?.keys?.let { keys ->
keys.forEach { path ->
unregisterCallback(path)
}
}
}
}
override fun onStartUpload(eventId: String?, localPath: String?) {
map[localPath]?.let {
it.onStartUpload(eventId, localPath)
}
}
override fun uploadCosFailed(cosPath: String?, eventId: String?, localPath: String?) {
map[localPath]?.let {
it.uploadCosFailed(cosPath, eventId, localPath)
}
}
override fun uploadCosCompleted(
cosPath: String?,
eventId: String?,
downloadUrl: String?,
localPath: String?
) {
map[localPath]?.let {
it.uploadCosCompleted(cosPath, eventId, downloadUrl, localPath)
}
}
override fun onProgress(localPath: String?, progress: Float) {
map[localPath]?.let {
it.onProgress(localPath, progress)
}
}
fun release() {
CosStatusCallbackManager.getInstance().unregister(this)
map.clear()
uploadFailed = null
}
}

View File

@@ -0,0 +1,217 @@
package com.zhidao.roadcondition.service
import android.content.Intent
import android.util.Log
import com.google.gson.Gson
import com.mogo.commons.AbsMogoApplication
import com.zhidao.cosupload.DbPriorityConfig
import com.zhidao.cosupload.callback.CosStatusCallback
import com.zhidao.cosupload.manager.CosUploadManagerImpl
import com.zhidao.roadcondition.constant.*
import com.zhidao.roadcondition.event.GetImageSuccessEvent
import com.zhidao.roadcondition.event.LatLngStickyEventBus
import com.zhidao.roadcondition.model.proxy.INFO_TYPE_IMG
import com.zhidao.roadcondition.model.proxy.INFO_TYPE_VIDEO
import com.zhidao.roadcondition.util.CarNet_Cos_Upload
import com.zhidao.roadcondition.util.LocationUtil
import com.zhidao.roadcondition.util.deletePicFile
import com.zhidao.roadcondition.util.trackNormalEvent
/**
* @description cos上传操作
*
* @author lixiaopeng
* @since 2019-10-30
*/
class CosStatusController : CosStatusCallback {
val TAG: String = this.javaClass.simpleName
//存储单次请求的视频和缩略图url
var videoAndThumbMap: MutableMap<String, String> = mutableMapOf()
//图片上传的eventId
lateinit var mPicEventId: String
private var isRetry = false //是否重试上传过图片
private var mainServiceHttpModel = MainServiceController()
private lateinit var entity: TakeEntity
private var mType: String = ""
//上传文件
fun uploadFile(picPath: MutableList<String>, entity: TakeEntity, type: String) {
CosCallbackMapController.registerCallback(picPath, this)
// CosLogger.setLogStatus(true)
this.entity = entity
this.mType = type
Log.d(TAG, "uploadFile type===$type ---- picPath = $picPath ")
trackUploadCos(3)
if (picPath.contains("backPic")) return
//参数说明: paths本地文件路径上传的本地路径不要重复config文件上传的优先级
mPicEventId =
CosUploadManagerImpl.getInstance(AbsMogoApplication.getApp().applicationContext).eventId
CosUploadManagerImpl.getInstance(AbsMogoApplication.getApp().applicationContext)
.upload(picPath, mPicEventId, DbPriorityConfig.PRIORITY_HIGH)
}
override fun onStartUpload(eventId: String?, localPath: String?) {
}
private fun sendGetInfoFailedReceiver(type: String) {
Log.d(CarCorderController.TAG, "sendGetInfoFailedReceiver ------>")
var intent = Intent()
intent.action = "com.zhidao.roadcondition.getinfo.failed"
intent.putExtra("type", type)
AbsMogoApplication.getApp().applicationContext.sendBroadcast(intent)
}
override fun uploadCosFailed(cosPath: String?, eventId: String?, localPath: String?) {
Log.d(TAG, "uploadCosFailed = $localPath")
Log.d(TAG, "uploadCosFailed CarCorderController.mType = " + CarCorderController.mType)
trackUploadCos(2)
//语音播报 1上报路况2交通检查3封路 默认 mType 应该为null
if (CarCorderController.mType.equals(TANLU_ROAD_CONGESTION) || CarCorderController.mType.equals(
TANLU_TRAFFIC_CHECK
) || CarCorderController.mType.equals(TANLU_ROAD_CLOSURE)
|| CarCorderController.mType.equals(TANLU_ROAD_CURRENT) || CarCorderController.mType.equals(
TANLU_ROAD_PONDING
) || CarCorderController.mType.equals(TANLU_ROAD_ICING)
|| CarCorderController.mType.equals(TANLU_ROAD_HEAVY_FOG) || CarCorderController.mType.equals(
TANLU_ROAD_ACCIDENT
) || CarCorderController.mType.equals(TANLU_ROAD_WORK)
) {
// VoiceController.speakVoice("cos上报失败")
Log.d(TAG, "uploadCosFailed mType = $mType")
if (entity?.isCustom) {
sendGetInfoFailedReceiver("100")
}
}
if (!isRetry) {
isRetry = true
// taskAsync(30_000) { //去掉重试
// try {
// uploadFile(mutableListOf(localPath as String), entity, mType)
// } catch (e: Exception) {
// e.printStackTrace()
// }
// }
} else {
if (localPath!!.endsWith("mp4") || localPath!!.contains("Thumbnail")) {
CosCallbackMapController.uploadFailed?.invoke()
}
CosCallbackMapController.unregisterCallback(localPath)
InformationUploadController.release(entity?.id)
// deletePicFile(localPath)
}
}
override fun uploadCosCompleted(
cosPath: String?,
eventId: String?,
downloadUrl: String?,
localPath: String?
) {
Log.d(TAG, "uploadFile mType= $mType")
Log.d(TAG, "uploadCosCompleted localPath = $localPath")
Log.d(TAG, "uploadCosCompleted downloadUrl = $downloadUrl")
Log.d(TAG, "uploadCosCompleted cosPath = $cosPath")
trackUploadCos(1)
if (localPath!!.endsWith("mp4") || localPath!!.contains("Thumbnail")) {
//如果是视频文件或者缩略图文件
if (localPath.endsWith("mp4")) {
videoAndThumbMap["video"] = downloadUrl!!
Log.i(TAG, "videoAndThumbMap add mp4")
} else {
videoAndThumbMap["thumb"] = downloadUrl!!
Log.i(TAG, "videoAndThumbMap add thumb")
}
Log.d(TAG, "videoAndThumbMap ${videoAndThumbMap}")
if (videoAndThumbMap.size == 2) {
Log.d(TAG, "videoAndThumbMap.size == 2 ")
var locationInfo = LocationUtil.getInstance().getLocationInfo()
val locationStr: String = Gson().toJson(locationInfo)
Log.d(TAG, "locationStr = " + locationStr)
//如果失败,需要提示失败弹框
if (locationInfo.address.isNullOrEmpty() || locationInfo.cityName.isNullOrEmpty() || locationInfo.cityCode.isNullOrEmpty()
|| locationInfo.latitude == 0.0 || locationInfo.areaName.isNullOrEmpty() || locationInfo.street.isNullOrEmpty()
|| locationInfo.areaCode.isNullOrEmpty() || locationInfo.provinceName.isNullOrEmpty()
) {
if (entity?.isCustom) {
sendGetInfoFailedReceiver("100")
}
} else {
//分享成功并打点如果是上报拥堵需要takeVideo
LatLngStickyEventBus.getInstance()
.postSticky(GetImageSuccessEvent(downloadUrl, mType))
//上传录像以及缩略图成功
sendInformation(INFO_TYPE_VIDEO, videoAndThumbMap)
}
}
} else {
//上传图片成功, 如果是上报路况直接上传TODO
Log.d(TAG, "uploadCosCompleted 分享成功 ----mType = $mType")
// if (mType.equals("1") || mType.equals("-1")) {
sendInformationDirectly(
INFO_TYPE_IMG,
mutableMapOf("pic" to downloadUrl as String),
mType,
entity
)
// }
}
Log.d(TAG, "delete file: ${localPath!!}")
CosCallbackMapController.unregisterCallback(localPath)
deletePicFile(localPath)
}
private fun sendInformation(type: Int, map: Map<String, String>) {
Log.d(TAG, "isCustomSend = ${entity?.isCustom}")
// if (entity?.isCustom) {
// InformationUploadController.cosResourceReady(type, map, entity?.isCustom, entity?.id) {
// CosCallbackMapController.mainService?.sendCustomResult(it)
// }
// } else {
sendInformationDirectly(type, map, mType, entity)
// }
}
/**
* 被动上报时直接上报,不用等待、选择情报类型
*/
fun sendInformationDirectly(
type: Int,
map: Map<String, String>,
poiType: String,
entity: TakeEntity
) {
Log.d(TAG, "sendInformationDirectly isCustomSend = ${entity?.isCustom}")
Log.d(TAG, "sendInformationDirectly poiType= $poiType")
mainServiceHttpModel.sendInformationMessage(
type = type,
url = map,
isCustom = entity?.isCustom,
poiType = poiType
) { success ->
CosCallbackMapController.unregisterCallbacks(map)
CosCallbackMapController.mainService?.let {
CosCallbackMapController.mainService?.sendCustomResult(success)
}
}
}
override fun onProgress(localPath: String?, progress: Float) {
}
//上传COS
private fun trackUploadCos(type: Int) {
trackNormalEvent(
CarNet_Cos_Upload, mutableMapOf("type" to type),
AbsMogoApplication.getApp().applicationContext
)
}
}

View File

@@ -0,0 +1,31 @@
package com.zhidao.roadcondition.service
import java.util.*
/**
* @author congtaowang
* @since 2019-11-25
*
* 拍照、拍视频手动、被动状态队列
*/
object CustomStatusHandler {
val takePhotoStatusQueue: Queue<Boolean> = ArrayDeque(5)
val takeVideoStatusQueue: Queue<TakeEntity> = ArrayDeque(5)
fun offerPhotoStatus(status: Boolean) {
takePhotoStatusQueue.offer(status)
}
fun pollPhotoStatus() = takePhotoStatusQueue.poll() ?: false
fun offerVideoStatus(entity: TakeEntity) {
takeVideoStatusQueue.offer(entity)
}
fun pollVideoStatus(): TakeEntity = takeVideoStatusQueue.poll()
}
class TakeEntity(
var isCustom: Boolean, var id: Long
)

View File

@@ -0,0 +1,70 @@
package com.zhidao.roadcondition.service
import android.app.IntentService
import android.content.Context
import android.content.Intent
import android.os.IBinder
import android.util.Log
import com.zhidao.roadcondition.util.*
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.io.File
import java.lang.Exception
class DelayService : IntentService("DelayService") {
companion object {
const val TAG = "DelayService"
fun launchService(context: Context) {
context.startService(Intent(context, DelayService::class.java))
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
}
override fun onCreate() {
super.onCreate()
}
override fun onStart(intent: Intent?, startId: Int) {
super.onStart(intent, startId)
}
override fun onBind(intent: Intent?): IBinder? {
return super.onBind(intent)
}
override fun setIntentRedelivery(enabled: Boolean) {
super.setIntentRedelivery(enabled)
}
override fun onDestroy() {
super.onDestroy()
}
override fun onHandleIntent(intent: Intent?) {
Log.d(TAG, "start delay ----> ")
taskAsync(20_000) {
try {
Log.d(TAG, "delay finish, start Service")
// MainService.launchService(this@DelayService, "0")
//删除一个原始视频(可能没删除的)文件夹下的所有文件(包括子目录内的文件)
val file = File("/mnt/sdcard/DCIM/Camera/video/small/") //输入要删除文件目录的绝对路径
deleteAllFile(file)
val compressFile = File("/mnt/sdcard/Movies/") //压缩过的视频
deleteAllFile(compressFile)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}

View File

@@ -0,0 +1,126 @@
package com.zhidao.roadcondition.service
import android.util.Log
import com.zhidao.roadcondition.model.InformationResource
import com.zhidao.roadcondition.model.InformationType
import com.zhidao.roadcondition.util.*
/**
* @author congtaowang
* @since 2019-11-20
*
* 情报上报控制
*/
object InformationUploadController {
val TAG : String = this.javaClass.simpleName
private var mainServiceHttpModel = MainServiceController()
private val locker: Any = Any()
/**
* 情报
* Long -> 一个情报的id
* InformationResource -> 一个情报的资源
*/
private val informationCache = mutableMapOf<Long, InformationResource>()
/**
* 情报已上传到cos
*/
fun cosResourceReady(
sourceType: Int,
cosParameter: Map<String, String>,
isCustomSend: Boolean,
id: Long,
callback: ((customSend: Boolean) -> Unit)
) {
Log.d(TAG, "cos resource ready. id=${id}")
val ir = getInformationResourceById(id)
ir?.let {
it.isCosResourceReady = true
it.sourceType = sourceType
it.cosParameter = cosParameter
it.isCustomSend = isCustomSend
it.callback = callback
tryUploadInformation(it)
}
}
private fun getInformationResourceById(id: Long): InformationResource? {
if (!informationCache.containsKey(id)) {
informationCache[id] = InformationResource(id)
}
return informationCache[id]
}
/**
* 已选择情报类型
*/
fun informationSelected(
informationType: InformationType,
newsType: String,
operType: String,
id: Long
) {
Log.d(TAG, "information type selected id=${id}, type=${informationType}")
val ir = getInformationResourceById(id)
ir?.let {
it.isInformationSelected = true
it.informationType = informationType
it.newsType = newsType
it.operType = operType
tryUploadInformation(it)
}
}
private fun tryUploadInformation(ir: InformationResource?) {
// synchronized(locker) {
// ir?.let {
// if (!it.isReady()) {
// log(TAG, "source isn't ready.")
// return@let
// }
// mainServiceHttpModel.sendInformationMessage(
// it.sourceType,
// it.cosParameter!!,
// it.isCustomSend,
// it.informationType?.dictValue!!,
// isShare = true
// ) { success ->
// log(TAG, "上传成功!" + ir?.toString())
// trackNormalEvent(
// CarNet_user_upload,
// mutableMapOf(
// TRACK_KEY_TYPE to it.operType,
// TRACK_KEY_NEWS_TYPE to it.newsType
// )
// )
// if (it.isCustomSend) {
// it.callback?.invoke(success)
// }
// informationCache.remove(it.id)
// it.release()
// recordUploadTime()
// }
// }
// }
}
fun release(id: Long) {
val target = informationCache.remove(id)
target?.let {
it.release()
}
}
private fun recordUploadTime() {
putLong("lastUploadTime", System.currentTimeMillis())
}
fun isUpload2Frequently(): Boolean {
val lastUploadTime = getLong("lastUploadTime", 0L)
return System.currentTimeMillis() - lastUploadTime < 10_000L
}
}

View File

@@ -0,0 +1,387 @@
package com.zhidao.roadcondition.service
import android.app.AlarmManager
import android.app.PendingIntent
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.IBinder
import android.util.Log
import com.elegant.analytics.Analytics
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.debug.DebugConfig
import com.zhidao.cosupload.manager.CosUploadManagerImpl
import com.zhidao.roadcondition.BuildConfig
import com.zhidao.roadcondition.constant.*
import com.zhidao.roadcondition.event.GetImageSuccessEvent
import com.zhidao.roadcondition.event.LatLngStickyEventBus
import com.zhidao.roadcondition.util.*
import com.zhidao.roadcondition.util.StrategyPreferenceUtil.Companion.clearStrategyType
import com.zhidao.roadcondition.util.StrategyPreferenceUtil.Companion.getStrategyFrequency
import com.zhidao.roadcondition.util.StrategyPreferenceUtil.Companion.getStrategyInterval
import com.zhidao.roadcondition.util.StrategyPreferenceUtil.Companion.getStrategyType
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Consumer
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.util.concurrent.TimeUnit
/**
* 上报流程服务
*/
class MainService : Service() {
companion object {
fun launchService(context: Context, type: String) {
val intent = Intent(context, MainService::class.java).apply {
putExtra("type", type)
Log.e("MainService", "launchService type = $type")
}
context.startService(intent)
}
}
private lateinit var mainServiceHttpModel: MainServiceController
private var mAlarmManager: AlarmManager =
AbsMogoApplication.getApp().applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager
//是否已经获取过策略
var isGetStrategies: Boolean = false
val TAG: String = this.javaClass.simpleName
//1是一次性2是周期性
var picType: Int = 0
var videoType: Int = 0
var shareType: String = "type"
var isCustom: Boolean = false;
//发送主动上报结果广播给外部
fun sendCustomResult(result: Boolean) {
var intent = Intent(customResultAction)
intent.putExtra("isSuccess", result)
sendBroadcast(intent)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d(TAG, "onStartCommand -----------> ")
//清理多媒体资源和sp策略数据
// DelayService.launchService(this)
clearStrategyType(this)
//初始化埋点
Analytics.getInstance().start(this)
//初始化定位
// LocationUtil.getInstance().initLocation()
//参数说明appKey: app唯一标识比如包名
CosUploadManagerImpl.getInstance(AbsMogoApplication.getApp().applicationContext)
.init(BuildConfig.APPLICATION_ID, 2)
//初始化语音
VoiceController.initVoice()
if (intent != null) {
shareType = intent.getStringExtra("type")
Log.d(TAG, "onStartCommand shareType = $shareType")
if (shareType.equals(TANLU_ROAD_CONGESTION) || shareType.equals(TANLU_TRAFFIC_CHECK) || shareType.equals(
TANLU_ROAD_CLOSURE
) || shareType.equals(TANLU_ROAD_CURRENT)
|| shareType.equals(TANLU_ROAD_PONDING) || shareType.equals(TANLU_ROAD_ICING) || shareType.equals(
TANLU_ROAD_HEAVY_FOG
)
|| shareType.equals(TANLU_ROAD_ACCIDENT) || shareType.equals(
TANLU_ROAD_WORK
)
) {
// takePhoto(1, false, true)
takeVideo(10, isCustom = true, id = id)
}
} else {
Log.e(TAG, "intent == null ")
}
return super.onStartCommand(intent, flags, startId)
}
//定时任务回调广播
var mAlarmBroadCast: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(p0: Context?, p1: Intent) {
Log.d(TAG, "receive alarm!!!!!!!!!!AlarmType===${p1.getIntExtra("AlarmType", 1)}")
if (p1.action == alarmBroadAction) {
if (p1.getIntExtra("AlarmType", 1) == AlarmTypePic) {
//拍照
var number = p1.getLongExtra("number", 1)
takePhoto(number, true)
} else {
//录像
var duration = p1.getIntExtra("duration", 3)
takeVideo(duration, true)
}
} else if (p1.action == "com.zhidao.takevideo.test") {
//视频
takeVideo(p1.getIntExtra("duration", 10))
} else if (p1.action == "com.zhidao.takepic.test") {
//视频
takePhoto(1)
}
}
}
//主动上报图片情报广播
var mCustomSendBroadCast: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(p0: Context?, p1: Intent) {
val id = p1.getLongExtra("id", 0L)
if (p1.action == sendInformationAction) {
takeVideo(10, isCustom = true, id = id)
}
}
}
/**
* 发送获取图片
*/
fun startUploadInformation() {
var customIntent = Intent(sendInformationAction)
sendBroadcast(customIntent)
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onCreate() {
super.onCreate()
Log.d(TAG, "onCreate ------> 1")
init()
//初始化定位
LocationUtil.getInstance().initLocation()
initLocationListener()
loadConfigurations()
LatLngStickyEventBus.getInstance().register(this)
trackNormalEvent(CarNet_MainService_Start, null)
}
private fun init() {
//初始化拍照sdk
CarCorderController.initCarCorderController()
mainServiceHttpModel = MainServiceController()
registReceiver()
// CosStatusController().registerCos(this)
CosCallbackMapController.init(this)
}
/**
* 加载各种配置
*/
private fun loadConfigurations() {
// mainServiceHttpModel.getAuthorization()
// mainServiceHttpModel.getNeedAuth { authStatus ->
// // isNeedAuth = authStatus
// }
// mainServiceHttpModel.getSplashConfig()
}
var id: Long = System.currentTimeMillis()
/**
* 获取图片成功
*/
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true, priority = 98)
fun getImageEvent(getImageSuccessEvent: GetImageSuccessEvent) {
var info = LocationUtil.getInstance().getLocationInfo()
Log.e("MainService", "getImageEvent long = ${info.longitude} ----> lat= ${info.latitude}")
Log.d(
"MainService",
"getImageEvent url = " + getImageSuccessEvent.getImageUrl() + ">>>>type =" + getImageSuccessEvent.getType()
)
sendMarkerInfoReceiver(
info.latitude,
info.longitude,
getImageSuccessEvent.getImageUrl(),
getImageSuccessEvent.getType()
)
}
private fun sendMarkerInfoReceiver(lat: Double, lon: Double, imageUrl: String?, type: String?) {
Log.e("MainService", "sendMarkerInfoReceiver ------> type = $type ")
Log.e("MainService", "sendMarkerInfoReceiver ------> isCustom = $isCustom ")
var intent = Intent()
intent.action = "com.zhidao.roadcondition.marker.info"
intent.putExtra("type", type)
intent.putExtra("imageUrl", imageUrl)
intent.putExtra("lat", lat)
intent.putExtra("lon", lon)
intent.putExtra("custom", isCustom)
sendBroadcast(intent)
}
/**
* 初始化定位监听
*/
private fun initLocationListener() {
//开始开始监听速度,只要超过一次5公里每小时则即开始获取策略进行本地上报 只有release才加此判断qa环境方便测试
LocationUtil.getInstance().setonSpeedlistenner(object : LocationUtil.SpeedListener {
override fun onSpeedGet(speed: Float) {
if (speed > (5 / 3.6f) && !isGetStrategies) {
mainServiceHttpModel.initStrategies {
handleReportStrategy()
}
Log.d("MainService", "initLocationListener more than 5 start upload speed = $speed")
isGetStrategies = true
}
}
})
}
/**
* 上报策略判断
*/
private fun handleReportStrategy() {
//1是一次性2是周期性
picType = getStrategyFrequency(
AbsMogoApplication.getApp().applicationContext,
"pic",
getStrategyType("pic")
)
videoType = getStrategyFrequency(
AbsMogoApplication.getApp().applicationContext,
"video",
getStrategyType("video")
)
Log.d("MainService", "handleReportStrategy picType = $picType ---videoType = $videoType")
if (picType == 1) {
takePhoto(1)
} else if (picType == 2) {
postPhotoAlarmTask(true)
}
if (videoType == 1) {
takeVideo(10)
} else if (videoType == 2) {
postVideoAlarmTask(true)
}
}
private fun registReceiver() {
//注册定时任务回调
val intentFilter = IntentFilter(alarmBroadAction)
intentFilter.addAction("com.zhidao.sendmessage.test")
intentFilter.addAction("com.zhidao.takevideo.test")
intentFilter.addAction("com.zhidao.takepic.test")
registerReceiver(mAlarmBroadCast, intentFilter)
//注册主动上报广播
// var customSendIntentFilter = IntentFilter(sendInformationAction)
// registerReceiver(mCustomSendBroadCast, customSendIntentFilter)
}
//获取图片
private fun takePhoto(picNum: Long, isInterval: Boolean = false, isCustom: Boolean = false) {
Log.d("MainService", "takePhoto -----1----->")
//判断是否授权
// if (isAuthorization(BaseApplication.getAppContext())) {
// log(TAG, "takePhoto -----2----->")
//目前不支持连拍只能定时2秒拍一张 第一期每次只拍一张
Observable.intervalRange(0, 1, 0, 2_000, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(Consumer {
CarCorderController.takePhoto(1, 1, false, isCustom, TANLU_ROAD_CURRENT)
})
// }
postPhotoAlarmTask(isInterval)
this@MainService.isCustom = isCustom
}
//获取录像
private fun takeVideo(
duration: Int,
isInterval: Boolean = false,
isCustom: Boolean = false,
id: Long = 0
) {
Log.d("MainService", "takeVideo --------1---->")
// if (isAuthorization(BaseApplication.getAppContext())) {
// log(TAG, "takeVideo --------2---->")
CarCorderController.takeVideo(1, duration, isCustom, id, if(isCustom) shareType else TANLU_ROAD_CURRENT)
// }
postVideoAlarmTask(isInterval)
this@MainService.isCustom = isCustom
}
private fun postPhotoAlarmTask(isInterval: Boolean = false) {
if (isInterval) {
trackNormalEvent(CarNet_Create_Task, null)
val intent = Intent()
intent.action = alarmBroadAction
intent.putExtra("number", getLong(PIC_NUMBER, PIC_NUMBER_DEFAULT))
intent.putExtra("AlarmType", AlarmTypePic)
var pendingIntent = PendingIntent.getBroadcast(this, AlarmTypePic, intent, 0)
Log.d(
"MainService",
"postPhotoAlarmTask time =" + getStrategyInterval(
AbsMogoApplication.getApp().applicationContext,
"pic",
getStrategyType("pic")
)
)
mAlarmManager.setExact(
AlarmManager.RTC, System.currentTimeMillis() +
getStrategyInterval(
AbsMogoApplication.getApp().applicationContext,
"pic",
getStrategyType("pic")
)
, pendingIntent
)
}
}
//开始倒计时任务
private fun postVideoAlarmTask(isInterval: Boolean = false) {
if (isInterval) {
trackNormalEvent(CarNet_Create_Task, null)
val videoIntent = Intent()
videoIntent.action = alarmBroadAction
videoIntent.putExtra(
"duration", (VIDEO_DURATION_DEFAULT / 1000).toInt()
)
videoIntent.putExtra("AlarmType", AlarmTypeVideo)
var videoPendingIntent =
PendingIntent.getBroadcast(this, AlarmTypeVideo, videoIntent, 0)
Log.d(
"MainService",
"postVideoAlarmTask time =" + getStrategyInterval(
AbsMogoApplication.getApp().applicationContext,
"video",
getStrategyType("video")
)
)
mAlarmManager.setExact(
AlarmManager.RTC, System.currentTimeMillis() +
getStrategyInterval(
AbsMogoApplication.getApp().applicationContext,
"video",
getStrategyType("video")
)
, videoPendingIntent
)
}
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(mAlarmBroadCast)
unregisterReceiver(mCustomSendBroadCast)
CarCorderController.release()
CosCallbackMapController.release()
LatLngStickyEventBus.getInstance().unregister(this)
LatLngStickyEventBus.getInstance().removeAllStickyEvents()
trackNormalEvent(CarNet_MainService_Destory, null)
}
}

View File

@@ -0,0 +1,307 @@
package com.zhidao.roadcondition.service
import android.util.Log
import com.mogo.commons.AbsMogoApplication
import com.zhidao.roadcondition.model.*
import com.zhidao.roadcondition.net.request
import com.zhidao.roadcondition.util.*
import com.zhidao.roadcondition.util.StrategyPreferenceUtil.Companion.setStrategyFrequency
import com.zhidao.roadcondition.util.StrategyPreferenceUtil.Companion.setStrategyInterval
import com.zhidao.roadcondition.util.StrategyPreferenceUtil.Companion.setStrategyMaxSpeed
import com.zhidao.roadcondition.util.StrategyPreferenceUtil.Companion.setStrategyMinSpeed
import com.zhidao.roadcondition.util.StrategyPreferenceUtil.Companion.setStrategyType
import com.zhidao.roadcondition.util.StrategyPreferenceUtil.Companion.setStrategyValidity
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
class MainServiceController {
companion object {
var TAG = this.javaClass.name
}
//逆地理编码是否重试
private var geoRetryed = false
private val strategyeModel by lazy { StrategyServiceModel() }
fun initStrategies(initFinish: (() -> Unit)? = null) {
request<BaseResponse<Results>> {
loader {
strategyeModel.getCityStrategy()
}
onSuccess {
it.result.let { strategy ->
trackNormalEvent(CarNet_Get_Strategy, null)
Log.d(TAG, "pic =" + strategy.cityStrategy.pic)
Log.d(TAG, "video =" + strategy.cityStrategy.video)
syncStrategiesData(strategy.cityStrategy)
initFinish?.invoke()
}
}
onError {
reInitStrategies()
Log.e(TAG, "initStrategies onError ${it.message}")
}
}
}
private fun reInitStrategies() = runBlocking {
launch {
// delay(30_000)
initStrategies()
}
}
//将数据同步到sharePreference中
fun syncStrategiesData(strategy: CityStrategy) {
if (strategy?.pic != null && strategy.video!=null) {
setStrategyType(AbsMogoApplication.getApp().applicationContext, strategy.pic.strategyType, "pic")
setStrategyType(AbsMogoApplication.getApp().applicationContext, strategy.video.strategyType, "video")
setStrategyFrequency(
AbsMogoApplication.getApp().applicationContext,
strategy.pic.strategyType,
"pic",
strategy.pic.reportType
)
setStrategyFrequency(
AbsMogoApplication.getApp().applicationContext,
strategy.video.strategyType,
"video",
strategy.video.reportType
)
setStrategyInterval(
AbsMogoApplication.getApp().applicationContext,
strategy.pic.strategyType,
"pic",
strategy.pic.reportTimeInterval * 60 * 1000L
)
setStrategyInterval(
AbsMogoApplication.getApp().applicationContext,
strategy.video.strategyType,
"video",
strategy.video.reportTimeInterval * 60 * 1000L
)
setStrategyValidity(
AbsMogoApplication.getApp().applicationContext,
strategy.pic.strategyType,
"pic",
strategy.pic.infoTimeout
)
setStrategyValidity(
AbsMogoApplication.getApp().applicationContext,
strategy.video.strategyType,
"video",
strategy.video.infoTimeout
)
setStrategyMaxSpeed(
AbsMogoApplication.getApp().applicationContext,
strategy.pic.strategyType,
"pic",
strategy.pic.getMaxSpeed()
)
setStrategyMaxSpeed(
AbsMogoApplication.getApp().applicationContext,
strategy.video.strategyType,
"video",
strategy.video.getMaxSpeed()
)
setStrategyMinSpeed(
AbsMogoApplication.getApp().applicationContext,
strategy.pic.strategyType,
"pic",
strategy.pic.minSpeed
)
setStrategyMinSpeed(
AbsMogoApplication.getApp().applicationContext,
strategy.video.strategyType,
"video",
strategy.video.minSpeed
)
} else {
Log.d(TAG, "strategy Data is null")
}
}
// fun getAuthorization() {
// request<BaseResponse<Any>> {
// loader {
// strategyeModel.getAuthorization()
// }
// onSuccess {
// it.let {
// var jsonObject = JSONObject(it.result.toString())
// setAuthorization(
// AbsMogoApplication.getApp().applicationContext,
// jsonObject.getBoolean("enable")
// )
// Log.d("MainServiceController", "MainServiceController getAuthorization onSuccess enable=" + jsonObject.getBoolean("enable"))
// }
// }
// onError {
// Log.d("MainServiceController", "getAuthorization error")
// }
// }
// }
// fun getNeedAuth(authStatus: ((Boolean) -> Unit)? = null) {
// request<BaseResponse<CommonConfig>> {
// loader {
// strategyeModel.getAllConfig()
// }
// onSuccess {
// it.let {
// var config = it.result
// config.auth?.let { auth ->
// authStatus?.invoke(auth.isNeedAuth == 1)
// }
// if (config.isActiveNonNull()) {
// //保存运营活动webUrl、imgUrl SP
// setActiveWebUrl(config.active.webUrl)
// setActiveImgUrl(config.active.imageUrl)
// setActiveStatus(config.active.status)
// } else {
// //清除运营活动配置SP
// clearActiveInfo()
// }
//
// }
// }
// onError {
// Log.d("MainServiceController", "getAuthorization error")
// }
// }
//
// //获取加载页面配置
// getSplashConfig()
// }
/**
* 获取加载页面配置
*/
// fun getSplashConfig() {
// request<BaseResponse<SplashConfig>> {
// loader {
// strategyeModel.getSplashConfig()
// }
// onSuccess {
// it.let {
// var splashConfig = it.result
// val timeFlag = getLong(TIME_QUANTUM, 0)
// if (splashConfig != null && !TextUtils.isEmpty(splashConfig.image)) {
// //保存倒计时时间
// Log.d(TAG, "splashConfig.displayTime =" + splashConfig.displayTime)
// putInt(COUNT_DOWN_TIME, splashConfig.displayTime)
// //保存语音播报
// putCommonString(VOICE_TEXT, splashConfig.content)
// //下载图片
// if (!TextUtils.isEmpty(splashConfig.image)) {
// Log.d(TAG, "splashConfig.effectiveFlag =" + splashConfig.effectiveFlag + "-->timeFlag=" + timeFlag)
// if (timeFlag != splashConfig.effectiveFlag) {
// ImageFactory.downloadPic(splashConfig.image)
// }
// }
//
// //保存时间戳
// putLong(TIME_QUANTUM, splashConfig.effectiveFlag)
// } else {
// putCommonString(VOICE_TEXT, "")
// putInt(COUNT_DOWN_TIME, 0)
// putCommonBoolean(IS_SAVE_SPLASH, false)
// }
// }
// }
// onError {
// Log.d(TAG, "getSplashConfig error it.printStackTrace()=" + it.printStackTrace())
// }
// }
// }
//上传情报数据
fun sendInformationMessage(
type: Int,
url: Map<String, String>,
isCustom: Boolean = false,
trafficInfoType:String = "",
isShare:Boolean = false,
poiType:String,
customSend: ((Boolean) -> Unit)? = null
) {
Log.d(TAG, " sendInformationMessage poiType = $poiType");
//删除测试数据
var locationInfo = LocationUtil.getInstance().getLocationInfo();
if (locationInfo.address.isNullOrEmpty()) {
geoLocation(type, url, locationInfo, isCustom,trafficInfoType, isShare, customSend,poiType)
} else {
postInformationMessage(
getInformationBody(type, url, locationInfo, isCustom, trafficInfoType, isShare,poiType),
customSend
)
}
}
//如果address为空则逆地理编码
private fun geoLocation(
type: Int,
url: Map<String, String>,
locationInfo: LocationInfo,
isCustom: Boolean,
trafficInfoType:String,
isShare: Boolean,
customSend: ((Boolean) -> Unit)? = null,
poiType: String
) {
Log.d(TAG, " geoLocation -- poiType = $poiType");
LocationUtil.getInstance()
.geoCodeLocation(locationInfo.toLatLngPoint(), { locInfo: LocationInfo ->
postInformationMessage(
getInformationBody(type, url, locationInfo, isCustom, trafficInfoType, isShare, poiType),
customSend
)
}, {
//转换失败的情况下再重试一次
geoRetryed = if (!geoRetryed) {
geoLocation(type, url, locationInfo, isCustom, trafficInfoType, isShare, customSend, poiType)
true
} else {
false
}
})
}
private fun postInformationMessage(
informationBody: InformationBody,
customSend: ((Boolean) -> Unit)? = null
) {
trackUploadServer(3)
request<BaseResponse<Any>> {
loader {
strategyeModel.uploadInformation(informationBody)
}
onSuccess {
Log.i(TAG, "upload message success ")
trackUploadServer(1)
// CosStatusController().videoAndThumbMap.clear()
customSend?.invoke(true)
}
onError {
Log.i(TAG, "$it upload message ${it.message}")
trackUploadServer(2)
// CosStatusController().videoAndThumbMap.clear()
customSend?.invoke(false)
}
}
}
//上传服务器
private fun trackUploadServer(type: Int) {
trackNormalEvent(
CarNet_Servers_Upload, mutableMapOf("type" to type)
)
}
}

View File

@@ -0,0 +1,8 @@
package com.zhidao.roadcondition.service
val AlarmTypePic: Int = 1 //定时任务类型 1照片
val AlarmTypeVideo: Int = 2 //定时任务类型 2视频
val alarmBroadAction: String = "com.zhidao.roadCondition.AlarmBroadCast" //定时广播
val sendInformationAction: String = "com.zhidao.roadCondition.SendInformation" //主动上报广播
val customResultAction: String = "com.zhidao.roadCondition.CustomResult" //主动上报结果广播

View File

@@ -0,0 +1,14 @@
package com.zhidao.roadcondition.service
import com.zhidao.auto.carcorder.callback.TakePhotoCallback
/**
* @author congtaowang
* @since 2019-11-19
*
* 拍照拦截器
*/
interface TakePhotoInterceptor : TakePhotoCallback {
fun intercept(): Boolean
}

View File

@@ -0,0 +1,58 @@
package com.zhidao.roadcondition.service
import com.mogo.commons.AbsMogoApplication
import com.zhidao.auto.platform.voice.VoiceClient
/**
* @description 声音控制类
*
* @author lixiaopeng
* @since 2019-11-01
*/
object VoiceController {
private lateinit var voiceClient: VoiceClient
fun initVoice() {
voiceClient = VoiceClient(AbsMogoApplication.getApp().applicationContext)
}
/**
* 设置语音命令回调接口
* @param callBack
*/
fun setCallBack(callBack: VoiceClient.VoiceCmdCallBack) {
voiceClient.setCallBack(callBack)
}
/**
* @param speakText 语音播报内容
*/
fun speakVoice(speakText: String) {
voiceClient.speakDefault(speakText)
}
/**
* 注册免唤醒命令
* @param customType 命令
* @param customWakeupCmd 命令对应的唤醒词集合
*/
fun registerCustomWakeupCmd(customType: String, customWakeupCmd: Array<String>) {
voiceClient.registerCustomWakeupCmd(customType, customWakeupCmd)
}
/**
* 取消免唤醒命令
* @param customType 命令
*/
fun unRegisterCustomWakeupCmd(customType: String) {
voiceClient.unRegisterCustomWakeupCmd(customType)
}
/**
* 释放资源(界面销毁的时候调用)
*/
fun release() {
voiceClient.release()
}
}

View File

@@ -0,0 +1,54 @@
package com.zhidao.roadcondition.util
import android.content.Context
import com.elegant.analytics.Analytics
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.network.Utils
import com.zhidao.roadcondition.aspect.DebugLog
import java.util.HashMap
const val CarNet_Alive:String = "CarNet_Alive"//探路日活DAU埋点
const val CarNet_Scheme_Channel:String = "CarNet_Scheme_Channel"//探路Scheme渠道区分
const val APPENTER_FRONT:String = "appenterfront"//探路Scheme渠道区分
const val CarNet_auto_upload:String = "CarNet_auto_upload"//情报自动上传时间(自动上报图片)
const val CarNet_click:String ="CarNet_click"//用户点击查看大图
const val CarNet_right_handle:String ="CarNet_right_handle"//用户切换情报-地图切换
const val CarNet_event_number:String ="CarNet_event_number" //用户获取的信息数量
const val CarNet_user_upload:String ="CarNet_user_upload" //用户主动上报视频type=1 手动点击 type=2 语音
const val CarNet_auto_upload_video:String ="CarNet_auto_upload_video"//自动上报视频
const val CarNet_click_search:String = "CarNet_click_search" //点击地图搜索
const val CarNet_user_get:String = "CarNet_user_get"//用户查看情报(首页视频/图片开始播放即算做用户查看type=1 视频 type=2 图片
const val CarNet_road_search:String = "CarNet_road_search"//有导航路线时的沿途查询
const val CarNet_MainService:String = "CarNet_MainService" //开机
const val CarNet_MainService_Start:String ="CarNet_MainService_Start" //服务开启
const val CarNet_MainService_Destory:String ="CarNet_MainService_Destory" //服务销毁
const val CarNet_Get_Strategy:String = "CarNet_Get_Strategy" //策略拉取成功
const val CarNet_Create_Task:String = "CarNet_Create_Task" //创建定时任务
const val CarNet_Get_Picture:String = "CarNet_Get_Picture" //获取图片,type=1 调用, type=2 成功, type=3 失败
const val CarNet_Get_Video:String = "CarNet_Get_Video" //获取视频,type=1 调用,type=2 成功,type=3 失败
const val CarNet_Cos_Upload:String = "CarNet_Cos_Upload" //上传COS, type=1 成功, type=2 失败, type=3 开始
const val CarNet_Servers_Upload:String = "CarNet_Servers_Upload" //上传服务端, type=1 成功,type=2 失败, type=3 开始
const val CarNet_Voice_Search:String = "CarNet_Voice_Search" //语音搜索路况,type=1 成功,type=2 失败
const val CarNet_USER_SHOW:String = "CarNet_user_show" //情报展示时长,showtime 加载列表时长
const val CarNet_USER_LOAD:String = "CarNet_user_load" //情报加载时长,type=1 视频2图片
const val CarNet_live_broadcast = "CarNet_live_broadcast" // 地图页面点击直播(在线可直播车机)
//自定义埋点
@DebugLog
fun trackNormalEvent(event: String, data: MutableMap<String, Any>?, context: Context = AbsMogoApplication.getApp().applicationContext) {
var data = data
if (data == null) {
data = HashMap()
}
val localParams = HashMap<String, Any>()
//公共参数 time sn
localParams["time"] = System.currentTimeMillis()
localParams["systemversion"] = getSystemVersion(context)
localParams["sn"] = Utils.getSn()
// Log.d("liyz", "data =" + data.toString() + ">>>>event=" + event)
Analytics.getInstance().setCustomParams(localParams)
Analytics.getInstance().track(event, data)
}

View File

@@ -0,0 +1,40 @@
@file:JvmName("DeviceInfo")
package com.zhidao.roadcondition.util
import android.content.Context
import java.lang.reflect.InvocationTargetException
private const val SN_INFO: String = "gsm.serial"
fun getSn(): String {
var serial = ""
try {
var cls = Class.forName("android.os.SystemProperties")
var method = cls.getMethod("get", String::class.java)
serial = method.invoke(cls, SN_INFO) as String
} catch (var4: ClassNotFoundException) {
var4.printStackTrace()
} catch (var5: NoSuchMethodException) {
var5.printStackTrace()
} catch (var6: InvocationTargetException) {
var6.printStackTrace()
} catch (var7: IllegalAccessException) {
var7.printStackTrace()
}
return serial
}
fun getSystemVersion(context: Context): String {
try {
var cls = context.classLoader
var systemProperties = cls.loadClass("android.os.SystemProperties")
var paramTypes = String::class.java
val get = systemProperties.getMethod("get", paramTypes)
val version = get.invoke(systemProperties, *arrayOf<Any>("ro.fota.version")) as String
return if (!version.trim().isNullOrEmpty()) version.trim() else ""
} catch (e: Exception) {
e.printStackTrace()
}
return ""
}

View File

@@ -0,0 +1,184 @@
package com.zhidao.roadcondition.util
import android.graphics.Bitmap
import android.media.MediaMetadataRetriever
import android.os.Environment
import android.util.Log
import okhttp3.MediaType
import okhttp3.MultipartBody
import okhttp3.RequestBody
import java.io.*
import java.text.SimpleDateFormat
import java.util.*
//创建文件上传请求体
fun fileToMultiPart(fileUrl: String): MultipartBody.Part? {
var file = File(fileUrl)
if (file.exists()) {
var requestBody = RequestBody.create(MediaType.parse("image/jpg"), file)
return MultipartBody.Part.createFormData("file", file.name, requestBody)
}
return null
}
fun deletePicFile(filePath: String?): Boolean {
var file = File(filePath)
if (file.exists()) {
//如果图片地址包含此路径则是C上面的拍照需要再删除后摄图片
if (filePath!!.contains("usbotg-1-1.1")) {
//将地址替换成后摄图片地址
var backFile =
File(filePath.replace("frontPic", "backPic").replace("PhotoFront", "PhotoBack"))
if (backFile.exists()) {
return backFile.delete()
}
return file.delete()
} else
return file.delete()
}
return false
}
//删除某个目录下所有文件
fun deleteAllFile(file: File?) { //判断文件不为null或文件目录存在
if (file == null || !file.exists()) {
Log.e("liyz", "文件删除失败,请检查文件路径是否正确")
return
}
//取得这个目录下的所有子文件对象
val files: Array<File> = file.listFiles()
//遍历该目录下的文件对象
for (f in files) {
val name: String = file.getName()
Log.e("liyz", name)
//判断子目录是否存在子目录,如果是文件则删除
if (f.isDirectory()) {
deleteAllFile(f)
} else {
f.delete()
}
}
//删除空文件夹 for循环已经把上一层节点的目录清空。
// file.delete()
}
//根据本地视频文件生成缩略图文件
fun getVideoThumbnail(filePath: String, picPath: String): Boolean {
var b: Bitmap? = null
var retriever = MediaMetadataRetriever()
try {
retriever.setDataSource(filePath)
b = retriever.getFrameAtTime(0)
} catch (e: IllegalArgumentException) {
e.printStackTrace()
} catch (e: RuntimeException) {
e.printStackTrace()
} finally {
try {
retriever.release()
} catch (e: RuntimeException) {
e.printStackTrace()
}
}
return bitmapToFile(b, picPath)
}
//bitmap转为file
fun bitmapToFile(bitmap: Bitmap?, filePath: String): Boolean {
val baos = ByteArrayOutputStream()
bitmap?.compress(Bitmap.CompressFormat.JPEG, 50, baos)
val file = File(filePath)
try {
if (file.exists())
file.delete()
file.createNewFile()
val fos = FileOutputStream(file)
var ins = ByteArrayInputStream(baos.toByteArray())
var x = 0
val b = ByteArray(1024 * 100)
while ({ x = ins.read(b);x }() != -1) {
fos.write(b, 0, x)
}
fos.close()
bitmap?.recycle()
} catch (e: Exception) {
e.printStackTrace()
return false
}
return true
}
//获取压缩后的视频路径
fun getCompressVideoPath(): String {
val moviesDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_MOVIES
)
moviesDir.mkdirs()
val builder = StringBuilder()
builder.append("compress_video_")
.append(SimpleDateFormat("yyyyMMddHHmmss").format(Date()))
val filePrefix = builder.toString()
val fileExtn = ".mp4"
var destPath = File(moviesDir, filePrefix + fileExtn)
var fileNo = 0
while (destPath.exists()) {
fileNo++
destPath = File(moviesDir, filePrefix + fileNo + fileExtn)
}
return destPath.absolutePath
}
/**
* 保存图片到本地
*/
fun saveImageToSdcard(bmp: Bitmap): Boolean {
var currentFile: File
lateinit var fos: FileOutputStream
var picFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
picFile.mkdirs()
val builder = StringBuilder()
builder.append("splash_bg")
val filePrefix = builder.toString()
val fileOut = ".jpg"
currentFile = File(picFile, filePrefix + fileOut)
try {
fos = FileOutputStream(currentFile)
bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos)
fos.flush()
} catch (e: FileNotFoundException) {
e.printStackTrace()
return false
} catch (e: IOException) {
e.printStackTrace()
return false
} finally {
try {
if (fos != null) {
fos.close()
}
} catch (e: IOException) {
e.printStackTrace()
return false
}
}
return true
}
/**
* 获取本地保存的图片地址
*/
fun getImagePath(): String {
return "/mnt/sdcard/Pictures/splash_bg.jpg"
}

View File

@@ -0,0 +1,213 @@
package com.zhidao.roadcondition.util
import android.util.Log
import com.amap.api.location.AMapLocation
import com.amap.api.location.AMapLocationClient
import com.amap.api.location.AMapLocationClientOption
import com.amap.api.location.AMapLocationListener
import com.amap.api.services.core.LatLonPoint
import com.amap.api.services.geocoder.*
import com.mogo.commons.AbsMogoApplication
import com.zhidao.roadcondition.model.LocationInfo
private fun RegeocodeAddress.toLocInfo(
address: RegeocodeAddress,
latlngPoint: LatLonPoint
): LocationInfo {
return LocationInfo(
address.province,
address.city,
address.cityCode,
address.district,
address.adCode,
address.roads[0].name,
latlngPoint.longitude,
latlngPoint.latitude,
address.formatAddress,
System.currentTimeMillis()
)
}
private fun AMapLocation.toLocInfo(location: AMapLocation): LocationInfo {
return LocationInfo(
location.province,
location.city,
location.cityCode,
location.district,
location.adCode,
location.street,
location.longitude,
location.latitude,
location.address,
location.time,
location.bearing
)
}
class LocationUtil private constructor() {
companion object {
private const val TAG = "LocationUtil"
private var instance: LocationUtil? = null
@Synchronized
fun getInstance(): LocationUtil {
if (instance == null) {
instance = LocationUtil()
}
return instance!!
}
}
interface OnMapLocationChangedListener {
fun onChanged(locationInfo: LocationInfo)
}
private var listener: OnMapLocationChangedListener? = null
private var init: Boolean = false
private var mContext = AbsMogoApplication.getApp().applicationContext
private var locationClient: AMapLocationClient? = null
private var locationOption: AMapLocationClientOption? = null
private var speedListener: SpeedListener? = null
private var locationInfo: LocationInfo = LocationInfo()
private var speed: Float = 0.0f
fun initLocation() {
//初始化client
locationOption = getDefaultOption()
locationClient = AMapLocationClient(mContext)
//设置定位参数
locationClient!!.setLocationOption(locationOption)
// 设置定位监听
locationClient!!.setLocationListener(locationListener)
init = true
startLocation()
}
private fun getDefaultOption(): AMapLocationClientOption {
val mOption = AMapLocationClientOption()
mOption.locationMode =
AMapLocationClientOption.AMapLocationMode.Hight_Accuracy//可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式
mOption.isGpsFirst = true//可选设置是否gps优先只在高精度模式下有效。默认关闭
mOption.httpTimeOut = 30000//可选设置网络请求超时时间。默认为30秒。在仅设备模式下无效
mOption.interval = 5000//可选设置定位间隔。默认为2秒
mOption.isNeedAddress = true//可选设置是否返回逆地理地址信息。默认是true
mOption.isOnceLocation = false//可选设置是否单次定位。默认是false
mOption.isOnceLocationLatest = false//可选设置是否等待wifi刷新默认为false.如果设置为true,会自动变为单次定位,持续定位时不要使用
AMapLocationClientOption.setLocationProtocol(AMapLocationClientOption.AMapLocationProtocol.HTTP)//可选, 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP
mOption.isSensorEnable = true//可选设置是否使用传感器。默认是false
mOption.isWifiScan =
true //可选设置是否开启wifi扫描。默认为true如果设置为false会同时停止主动刷新停止以后完全依赖于系统刷新定位位置可能存在误差
mOption.isLocationCacheEnable = false //可选设置是否使用缓存定位默认为true
mOption.geoLanguage =
AMapLocationClientOption.GeoLanguage.DEFAULT//可选,设置逆地理信息的语言,默认值为默认语言(根据所在地区选择语言)
return mOption
}
private fun startLocation() {
if (checkInit()) {
// 设置定位参数
locationClient!!.setLocationOption(locationOption)
// 启动定位
locationClient!!.startLocation()
}
}
fun setOnMapLocationChangedListener(listener: OnMapLocationChangedListener) {
this.listener = listener
}
/**
* 定位监听
*/
private var locationListener: AMapLocationListener = AMapLocationListener { location ->
if (null != location) {
locationInfo.longitude = location.longitude
locationInfo.latitude = location.latitude
locationInfo.address = location.address
locationInfo.time = location.time
locationInfo.provinceName = location.province
locationInfo.cityName = location.city
locationInfo.cityCode = location.cityCode
locationInfo.areaName = location.district
locationInfo.areaCode = location.adCode
locationInfo.street = location.street
locationInfo.direction = location.bearing
listener?.let {
it.onChanged(locationInfo)
}
speed = location.speed
speedListener?.let {
it.onSpeedGet(location.speed)
}
} else {
Log.d(TAG, "定位失败 -> location is null")
}
}
private fun checkInit(): Boolean {
return if (!init) {
initLocation()
init
} else {
true
}
}
fun getLocationInfo(): LocationInfo {
return if (null != locationInfo) {
locationInfo
} else {
if (null == locationClient) {
locationClient = AMapLocationClient(mContext)
this.locationClient = locationClient
}
var location = locationClient!!.lastKnownLocation
location.toLocInfo(location)
}
}
//如果获取到的location address为空可以通过高德逆地理编码获得
fun geoCodeLocation(
latlngPoint: LatLonPoint,
locGeoCode: (((locInfo: LocationInfo) -> Unit)),
onError: ((msg: String) -> Unit)
) {
var geocoderSearch = GeocodeSearch(AbsMogoApplication.getApp().applicationContext)
var regeocodeQuery = RegeocodeQuery(latlngPoint, 200f, GeocodeSearch.AMAP)
geocoderSearch.getFromLocationAsyn(regeocodeQuery)
geocoderSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener {
override fun onRegeocodeSearched(p0: RegeocodeResult?, p1: Int) {
if (p1 == 1000) {
var regeocodeAddress = p0?.regeocodeAddress
regeocodeAddress?.let {
var locInfo = regeocodeAddress.toLocInfo(regeocodeAddress, latlngPoint)
locGeoCode.invoke(locInfo)
}
} else {
onError.invoke("geoCode -> $p1")
}
}
override fun onGeocodeSearched(p0: GeocodeResult?, p1: Int) {
}
})
}
fun getSpeed():Float{
return speed
}
fun setonSpeedlistenner(speedListener: SpeedListener) {
this.speedListener = speedListener
}
interface SpeedListener {
fun onSpeedGet(speed: Float)
}
}

View File

@@ -0,0 +1,78 @@
package com.zhidao.roadcondition.util
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.network.Utils
import com.zhidao.roadcondition.model.InformationBody
import com.zhidao.roadcondition.model.LocationInfo
import com.zhidao.roadcondition.model.proxy.INFO_TYPE_IMG
import com.zhidao.roadcondition.model.proxy.INFO_TYPE_VIDEO
import com.zhidao.roadcondition.util.StrategyPreferenceUtil.Companion.getStrategyType
import com.zhidao.roadcondition.util.StrategyPreferenceUtil.Companion.getStrategyValidity
var array: Array<LocationInfo> = arrayOf(
LocationInfo(116.40320588562773, 39.96661385462713, "测试数据1", 123123213),
LocationInfo(116.41309250805662, 39.970285228355976, "测试数据2", 123123213),
LocationInfo(116.40749205563353, 39.97317943101997, "测试数据3", 12321321321),
LocationInfo(116.39925230953978, 39.97314654304226, "测试数据4", 123123123),
LocationInfo(116.439366, 39.868472, "测试数据5", 123123123),
LocationInfo(116.288164, 39.910547, "测试数据6", 123123123),
LocationInfo(116.330132, 39.989311, "测试数据7", 123123123)
)
fun getInformationBody(
types: Int,
urls: Map<String, String>,
locationInfo: LocationInfo,
isCustom: Boolean,
trafficInfoType:String = "",
isShare:Boolean,
poiType: String
): InformationBody {
var jsonArray = JsonArray()
var type: Int
type = if (types == INFO_TYPE_VIDEO) {
var videoObject = JsonObject()
videoObject.addProperty("thumbnail", urls["thumb"])
videoObject.addProperty("url", urls["video"])
jsonArray.add(videoObject)
INFO_TYPE_VIDEO
} else {
var urlObject = JsonObject()
urlObject.addProperty("url", urls["pic"])
jsonArray.add(urlObject)
INFO_TYPE_IMG
}
var infoType = if (isCustom) 1 else 0
return InformationBody(
jsonArray.toString(),
locationInfo.address,
locationInfo.areaCode,
locationInfo.areaName,
locationInfo.cityCode,
locationInfo.cityName,
System.currentTimeMillis(),
locationInfo.latitude,
locationInfo.longitude,
locationInfo.provinceName,
Utils.getSn(),
locationInfo.street,
type,
0,
infoType,
getStrategyValidity(AbsMogoApplication.getApp().applicationContext, convertUploadTypeOfSP(type), getStrategyType(convertUploadTypeOfSP(type))),
trafficInfoType,
isShare,
locationInfo.direction,
poiType
)
}
private fun convertUploadTypeOfSP(type: Int): String {
return when (type) {
INFO_TYPE_IMG -> "pic"
INFO_TYPE_VIDEO -> "video"
else -> "pic"
}
}

View File

@@ -0,0 +1,171 @@
package com.zhidao.roadcondition.util
import android.content.Context
import android.util.Log
import androidx.core.content.edit
import com.mogo.commons.AbsMogoApplication
import com.zhidao.roadcondition.aspect.DebugLog
const val FILE_NAME = "settings_data"
const val FILE_NAME_NAVI = "settings_navi_data"
const val FILE_NAME_ACTIVE = "settings_active_data"
const val NAVI_INFO = "NAVI_INFO" //沿途导航数据存储
const val NAVI_INFO_STATUS = "NAVI_INFO_STATUS" //沿途导航路线是否存在
const val PARAM_AUTHORIZATION = "PARAM_AUTHORIZATION"
const val PARAM_PROMOTION_CONTENT = "PARAM_PROMOTION_CONTENT"
const val PARAM_ACTIVE_WEB_URL = "PARAM_ACTIVE_WEB_URL"
const val PARAM_ACTIVE_IMG_URL = "PARAM_ACTIVE_IMG_URL"
const val PARAM_ACTIVE_STATUS = "PARAM_ACTIVE_STATUS"
const val LAST_ENTER_TIME = "LAST_ENTER_TIME"
const val PIC_NUMBER = "PIC_NUMBER" //图片拍摄张数
const val VIDEO_DURATION_DEFAULT = 15_000L //视频拍摄时长
const val PIC_NUMBER_DEFAULT = 1L //图片拍摄张数
const val TIME_QUANTUM = "time_quantum" //时间段
const val COUNT_DOWN_TIME = "count_down" //倒计时
const val VOICE_TEXT = "voice_text" //语音播报内容
const val IS_SAVE_SPLASH = "is_save_splash" //是否保存了
//播放开始时间
const val PLAYER_START_TIME = "first_time"
fun clearActiveInfo(context: Context = AbsMogoApplication.getApp().applicationContext) {
var sharedPreferences = context.getSharedPreferences(FILE_NAME_ACTIVE, Context.MODE_PRIVATE)
sharedPreferences.edit {
clear()
val clearActiveInfo = commit()
Log.d(FILE_NAME_NAVI, "clearActiveInfo = $clearActiveInfo")
}
}
fun setActiveWebUrl(content: String, context: Context = AbsMogoApplication.getApp().applicationContext) {
var sharedPreferences = context.getSharedPreferences(FILE_NAME_ACTIVE, Context.MODE_PRIVATE)
sharedPreferences.edit {
putString(PARAM_ACTIVE_WEB_URL, content)
.commit()
}
}
fun setActiveStatus(status: Int, context: Context = AbsMogoApplication.getApp().applicationContext) {
var sharedPreferences = context.getSharedPreferences(FILE_NAME_ACTIVE, Context.MODE_PRIVATE)
sharedPreferences.edit {
putInt(PARAM_ACTIVE_STATUS, status)
.commit()
}
}
fun getActiveStatus(context: Context): Int {
return context.getSharedPreferences(FILE_NAME_ACTIVE, Context.MODE_PRIVATE)
.getInt(PARAM_ACTIVE_STATUS, 0)
}
fun setPromotionContent(content: String, context: Context = AbsMogoApplication.getApp().applicationContext) {
var sharedPreferences = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
sharedPreferences.edit {
putString(PARAM_PROMOTION_CONTENT, content)
.commit()
}
}
fun isAuthorization(context: Context): Boolean {
return context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
.getBoolean(PARAM_AUTHORIZATION, false)
}
@DebugLog
fun setAuthorization(context: Context, authorization: Boolean) {
var sharedPreferences = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
sharedPreferences.edit {
putBoolean(PARAM_AUTHORIZATION, authorization)
.commit()
}
}
@DebugLog
fun setNaviInfo(context: Context, naviInfo: String) {
var sharedPreferences = context.getSharedPreferences(FILE_NAME_NAVI, Context.MODE_PRIVATE)
sharedPreferences.edit {
val naviInfoSave = putString(NAVI_INFO, naviInfo)
.commit()
Log.d(FILE_NAME_NAVI, "naviInfoSave = $naviInfoSave")
}
}
@DebugLog
fun setNaviInfoStatus(context: Context, naviInfoStatus: Boolean) {
var sharedPreferences = context.getSharedPreferences(FILE_NAME_NAVI, Context.MODE_PRIVATE)
sharedPreferences.edit {
val naviInfoSaveStatus = putBoolean(NAVI_INFO_STATUS, naviInfoStatus)
.commit()
Log.d(FILE_NAME_NAVI, "naviInfoSaveStatus = $naviInfoSaveStatus")
}
}
fun clearAllNaviInfo(context: Context) {
var sharedPreferences = context.getSharedPreferences(FILE_NAME_NAVI, Context.MODE_PRIVATE)
sharedPreferences.edit {
clear()
val naviInfoAllClear = commit()
Log.d(FILE_NAME_NAVI, "naviInfoAllClear = $naviInfoAllClear")
}
}
fun putLong(key: String, value: Long) {
var sharedPreferences =
AbsMogoApplication.getApp().applicationContext.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
sharedPreferences.edit {
putLong(key, value).apply()
}
}
fun getLong(key: String, defaultValue: Long): Long {
return AbsMogoApplication.getApp().applicationContext.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
.getLong(key, defaultValue)
}
fun putInt(key: String, value: Int) {
var sharedPreferences =
AbsMogoApplication.getApp().applicationContext.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
sharedPreferences.edit {
putInt(key, value).apply()
}
}
fun getInt(key: String, defaultValue: Int): Int {
return AbsMogoApplication.getApp().applicationContext.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
.getInt(key, defaultValue)
}
fun putCommonString(key: String, value: String) {
var sharedPreferences =
AbsMogoApplication.getApp().applicationContext.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
sharedPreferences.edit {
putString(key, value).apply()
}
}
//fun getCommonString(key: String?, defaultValue: String?): String {
// return AbsMogoApplication.getApp().applicationContext.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
// .getString(key, defaultValue)
//}
//
//fun putCommonBoolean(key: String, value: Boolean) {
// var sharedPreferences =
// AbsMogoApplication.getApp().applicationContext.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
// sharedPreferences.edit {
// putBoolean(key, value).apply()
// }
//}
fun getCommonBoolean(key: String, defaultValue: Boolean): Boolean {
return AbsMogoApplication.getApp().applicationContext.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
.getBoolean(key, defaultValue)
}

View File

@@ -0,0 +1,199 @@
package com.zhidao.roadcondition.util
import android.content.Context
import android.util.Log
import androidx.core.content.edit
import com.mogo.commons.AbsMogoApplication
const val STRATEGY_FILE_NAME = "strategy_data"
const val STRATEGY_TYPE_COPY = "strategy_data_copy"
/**
* 策略SP存储模式STRATEGY_TYPE + 策略类型 + 情报类型 + 对应项
*/
const val STRATEGY_TYPE = "STRATEGY_"
const val FREQUENCY = "FREQUENCY"
const val DEFAULT_FREQUENCY_PIC = 2 //默认上报类型:周期性上报
const val DEFAULT_FREQUENCY_VIDEO = 1 //默认上报类型:单次上报
const val INTERVAL = "INTERVAL"
const val DEFAULT_INTERVAL_PIC = 600_000L //默认图片定时任务默认间隔
const val DEFAULT_INTERVAL_VIDEO = 900_000L //默认视频定时任务默认间隔
const val VALIDITY = "VALIDITY"
const val DEFAULT_VALIDITY = 4 * 60 //默认情报有效期4小时
const val MAX_SPEED = "MAX_SPEED"
const val MIN_SPEED = "MIN_SPEED"
const val DEFAULT_MAX_SPEED = -1
const val DEFAULT_MIN_SPEED = -1
class StrategyPreferenceUtil {
companion object {
//保存策略类型在AccOff的时候清除数据更新时需要在没有情报上传时操作
fun setStrategyType(context: Context, strategyType: Int, type: String) {
var sharedPreferences =
context.getSharedPreferences(STRATEGY_TYPE_COPY, Context.MODE_PRIVATE)
sharedPreferences.edit {
putInt(STRATEGY_TYPE + type, strategyType).commit()
}
}
fun getStrategyType(
type: String,
context: Context = AbsMogoApplication.getApp().applicationContext
): Int {
return context.getSharedPreferences(STRATEGY_TYPE_COPY, Context.MODE_PRIVATE)
.getInt(STRATEGY_TYPE + type, 1)
}
fun clearStrategyType(context: Context) {
var sharedPreferences =
context.getSharedPreferences(STRATEGY_TYPE_COPY, Context.MODE_PRIVATE)
sharedPreferences.edit {
clear()
val clearStrategyType = commit()
Log.d(STRATEGY_TYPE_COPY, "clearStrategyType = $clearStrategyType")
}
}
fun setStrategyFrequency(
context: Context,
strategyType: Int,
infoType: String,
frequency: Int
) {
var sharedPreferences =
context.getSharedPreferences(STRATEGY_FILE_NAME, Context.MODE_PRIVATE)
sharedPreferences.edit {
putInt(
STRATEGY_TYPE + strategyType + "_" + infoType + FREQUENCY,
frequency
).commit()
}
}
fun getStrategyFrequency(context: Context, infoType: String, strategyType: Int = 1): Int {
return context.getSharedPreferences(STRATEGY_FILE_NAME, Context.MODE_PRIVATE)
.getInt(
STRATEGY_TYPE + strategyType + "_" + infoType + FREQUENCY,
convertFrequencyOfInfoType(infoType)
)
}
private fun convertFrequencyOfInfoType(infoType: String): Int {
return when (infoType) {
"pic" -> DEFAULT_FREQUENCY_PIC
"video" -> DEFAULT_FREQUENCY_VIDEO
else -> DEFAULT_FREQUENCY_PIC
}
}
fun setStrategyInterval(
context: Context,
strategyType: Int,
infoType: String,
interval: Long
) {
var sharedPreferences =
context.getSharedPreferences(STRATEGY_FILE_NAME, Context.MODE_PRIVATE)
sharedPreferences.edit {
putLong(
STRATEGY_TYPE + strategyType + "_" + infoType + INTERVAL,
interval
).commit()
}
}
fun getStrategyInterval(context: Context, infoType: String, strategyType: Int = 1): Long {
return context.getSharedPreferences(STRATEGY_FILE_NAME, Context.MODE_PRIVATE)
.getLong(
STRATEGY_TYPE + strategyType + "_" + infoType + INTERVAL,
convertIntervalOfInfoType(infoType)
)
}
private fun convertIntervalOfInfoType(infoType: String): Long {
return when (infoType) {
"pic" -> DEFAULT_INTERVAL_PIC
"video" -> DEFAULT_INTERVAL_VIDEO
else -> DEFAULT_INTERVAL_PIC
}
}
fun setStrategyValidity(
context: Context,
strategyType: Int,
infoType: String,
validity: Int
) {
var sharedPreferences =
context.getSharedPreferences(STRATEGY_FILE_NAME, Context.MODE_PRIVATE)
sharedPreferences.edit {
putInt(
STRATEGY_TYPE + strategyType + "_" + infoType + VALIDITY,
validity
).commit()
}
}
fun getStrategyValidity(context: Context, infoType: String, strategyType: Int = 1): Int {
return context.getSharedPreferences(STRATEGY_FILE_NAME, Context.MODE_PRIVATE)
.getInt(
STRATEGY_TYPE + strategyType + "_" + infoType + VALIDITY,
DEFAULT_VALIDITY
)
}
fun setStrategyMaxSpeed(
context: Context,
strategyType: Int,
infoType: String,
maxSpeed: Int
) {
var sharedPreferences =
context.getSharedPreferences(STRATEGY_FILE_NAME, Context.MODE_PRIVATE)
sharedPreferences.edit {
putInt(
STRATEGY_TYPE + strategyType + "_" + infoType + MAX_SPEED,
maxSpeed
).commit()
}
}
fun getStrategyMaxSpeed(context: Context, infoType: String, strategyType: Int = 1): Int {
return context.getSharedPreferences(STRATEGY_FILE_NAME, Context.MODE_PRIVATE)
.getInt(
STRATEGY_TYPE + strategyType + "_" + infoType + MAX_SPEED,
DEFAULT_MAX_SPEED
)
}
fun setStrategyMinSpeed(
context: Context,
strategyType: Int,
infoType: String,
minSpeed: Int
) {
var sharedPreferences =
context.getSharedPreferences(STRATEGY_FILE_NAME, Context.MODE_PRIVATE)
sharedPreferences.edit {
putInt(
STRATEGY_TYPE + strategyType + "_" + infoType + MIN_SPEED,
minSpeed
).commit()
}
}
fun getStrategyMinSpeed(context: Context, infoType: String, strategyType: Int = 1): Int {
return context.getSharedPreferences(STRATEGY_FILE_NAME, Context.MODE_PRIVATE)
.getInt(
STRATEGY_TYPE + strategyType + "_" + infoType + MIN_SPEED,
DEFAULT_MIN_SPEED
)
}
}
}

View File

@@ -0,0 +1,17 @@
package com.zhidao.roadcondition.util
import android.text.format.DateFormat
const val format = "yy/MM/dd kk:mm:ss"
fun formatDate(time: Long): String {
return DateFormat.format(format, time).toString()
}
fun convertVar(param: Any?): Any? {
return if (param is String) {
"\"$param\""
} else {
param
}
}

View File

@@ -0,0 +1,12 @@
package com.zhidao.roadcondition.util
import android.content.Context
import android.content.Intent
fun isReiceverRegist(context: Context, intentAction: String): Boolean {
val intent = Intent()
intent.action = intentAction
val pm = context.packageManager
val resolveInfos = pm.queryBroadcastReceivers(intent, 0)
return resolveInfos != null && resolveInfos.isNotEmpty()
}

View File

@@ -0,0 +1,26 @@
package com.zhidao.roadcondition.util
import kotlinx.coroutines.*
@PublishedApi
internal var ThreadPool =
newFixedThreadPoolContext(Runtime.getRuntime().availableProcessors() * 2, "ThreadPool")
/**
* 在主线程中顺序执行,协程函数,一般用于最外层
* 该函数会阻塞代码继续执行
*/
inline fun taskBlockOnMainThread(delayTime: Long = 0, noinline job: suspend () -> Unit) = runBlocking {
delay(delayTime)
job()
}
/**
* 并发执行,常用于最外层
* 特点带返回值
*/
inline fun <T> taskAsync(delayTime: Long = 0, noinline job: suspend () -> T) = GlobalScope.async(ThreadPool) {
delay(delayTime)
job()
}

View File

@@ -0,0 +1,17 @@
package com.zhidao.roadcondition
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

View File

@@ -39,7 +39,6 @@ dependencies {
implementation rootProject.ext.dependencies.androidxappcompat
implementation rootProject.ext.dependencies.androidxconstraintlayout
implementation rootProject.ext.dependencies.arouter
implementation rootProject.ext.dependencies.tanluupload
annotationProcessor rootProject.ext.dependencies.aroutercompiler
if (Boolean.valueOf(RELEASE)) {
api rootProject.ext.dependencies.mogoutils
@@ -52,6 +51,7 @@ dependencies {
api rootProject.ext.dependencies.moduleapps
api rootProject.ext.dependencies.moduleextensions
api rootProject.ext.dependencies.mogomoduleback
implementation rootProject.ext.dependencies.tanluupload
} else {
api project(":foudations:mogo-utils")
api project(":foudations:mogo-commons")
@@ -63,6 +63,7 @@ dependencies {
api project(':modules:mogo-module-apps')
api project(':modules:mogo-module-extensions')
api project(':modules:mogo-module-back')
implementation project(':libraries:tanlulib')
}
}

1
modules/mogo-module-tanlu/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,81 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.alibaba.arouter'
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
// buildToolsVersion rootProject.ext.android.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode Integer.valueOf(VERSION_CODE)
versionName getValueFromRootProperties("${project.name.replace("-", "_").toUpperCase()}_VERSION")
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
buildTypes {
release {
minifyEnabled false
zipAlignEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
abortOnError false
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.3.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation rootProject.ext.dependencies.androidxappcompat
implementation rootProject.ext.dependencies.arouter
annotationProcessor rootProject.ext.dependencies.aroutercompiler
implementation rootProject.ext.dependencies.androidxconstraintlayout
implementation rootProject.ext.dependencies.rxjava
implementation rootProject.ext.dependencies.rxandroid
compileOnly rootProject.ext.dependencies.mogomap
compileOnly rootProject.ext.dependencies.mogoutils
compileOnly rootProject.ext.dependencies.mogocommons
compileOnly rootProject.ext.dependencies.mogoserviceapi
compileOnly rootProject.ext.dependencies.modulecommon
compileOnly rootProject.ext.dependencies.moduleshare
compileOnly rootProject.ext.dependencies.carcallprovider
implementation rootProject.ext.dependencies.videoarmv7
implementation rootProject.ext.dependencies.videoarm64
implementation rootProject.ext.dependencies.videojava
implementation rootProject.ext.dependencies.eventbus
// if( Boolean.valueOf(RELEASE)){
// implementation rootProject.ext.dependencies.moduletanlulib
// } else {
// implementation project(":tanlulib")
// }
}
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
repositories {
mavenCentral()
}

View File

@@ -0,0 +1,13 @@
-keep class com.mogo.module.tanlu.model.**{*;}
-keep class com.mogo.module.tanlu.fragment.*{*;}
-keep class com.mogo.module.tanlu.receiver.*{*;}
-keep class com.mogo.module.tanlu.video.*{*;}
-keep interface * implements com.mogo.module.tanlu.net.TanluApiService
-keep interface * implements com.mogo.module.tanlu.callback.AlongTheWayCallback
-keep interface * implements com.mogo.module.tanlu.callback.IThumbsUpCallback
-keep interface * implements com.mogo.module.tanlu.callback.NaviCallback
-keep interface * implements com.mogo.module.tanlu.callback.RoadInfoCallback
-keep interface * implements com.mogo.module.tanlu.callback.RoadLineCallback
-keep interface * implements com.mogo.module.tanlu.callback.UploadShareCallback
-keep interface * implements com.mogo.module.tanlu.callback.VoiceSearchCallback
-keep class com.mogo.module.tanlu.util.*{*;}

View File

@@ -0,0 +1,3 @@
GROUP=com.mogo.module
POM_ARTIFACT_ID=module-tanlu
VERSION_CODE=1

View File

@@ -0,0 +1,40 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-keep class com.mogo.module.tanlu.model.**{*;}
-keep class com.mogo.module.tanlu.fragment.*{*;}
-keep class com.mogo.module.tanlu.receiver.*{*;}
-keep class com.mogo.module.tanlu.video.*{*;}
-keep interface * implements com.mogo.module.tanlu.net.TanluApiService
-keep interface * implements com.mogo.module.tanlu.callback.AlongTheWayCallback
-keep interface * implements com.mogo.module.tanlu.callback.IThumbsUpCallback
-keep interface * implements com.mogo.module.tanlu.callback.NaviCallback
-keep interface * implements com.mogo.module.tanlu.callback.RoadInfoCallback
-keep interface * implements com.mogo.module.tanlu.callback.RoadLineCallback
-keep interface * implements com.mogo.module.tanlu.callback.UploadShareCallback
-keep interface * implements com.mogo.module.tanlu.callback.VoiceSearchCallback
-keep class com.mogo.module.tanlu.util.*{*;}

View File

@@ -0,0 +1,55 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mogo.module.tanlu">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application>
<activity
android:name=".video.FullMediaActivity"
android:hardwareAccelerated="true">
</activity>
<receiver android:name=".receiver.MarkerInfoReceiver">
<intent-filter>
<action android:name="com.zhidao.roadcondition.marker.info" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
<receiver android:name=".receiver.GetInfoFailedReceiver">
<intent-filter>
<action android:name="com.zhidao.roadcondition.getinfo.failed" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
<receiver android:name=".receiver.PushReceiver">
<intent-filter>
<action android:name="com.zhidao.roadcondition.split" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
<receiver android:name=".receiver.ShareDialogReceiver">
<intent-filter>
<action android:name="com.zhidao.sharedialog" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
<receiver android:name=".receiver.DataErrorReceiver">
<intent-filter>
<action android:name="com.zhidao.tanlu.dataerror" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
<receiver android:name=".receiver.NetWorkReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -0,0 +1,13 @@
package com.mogo.module.tanlu.callback;
import com.mogo.module.tanlu.model.InformationAndLiveCarResult;
/**
* @author lixiaopeng
* @description 导航沿途搜索
* @since 2020-01-09
*/
public interface AlongTheWayCallback {
void onSuccess(InformationAndLiveCarResult data);
void onFail(String message, int code);
}

View File

@@ -0,0 +1,44 @@
package com.mogo.module.tanlu.callback;
import com.mogo.service.datamanager.IMogoDataChangedListener;
/**
* @author congtaowang
* @since 2020-02-12
* <p>
* 描述
*/
public class DataSetChangedAdapter implements IMogoDataChangedListener {
private Object mData;
private DataSetChangedAdapter(){
// private constructor
}
private static final class InstanceHolder{
private static final DataSetChangedAdapter INSTANCE = new DataSetChangedAdapter();
}
private IMogoDataChangedListener mDelegate;
public void setDelegate( IMogoDataChangedListener delegate ) {
this.mDelegate = delegate;
}
public static DataSetChangedAdapter getInstance(){
return InstanceHolder.INSTANCE;
}
@Override
public void onDataSetChanged( Object data ) {
mData = data;
if ( mDelegate != null ) {
mDelegate.onDataSetChanged( data );
}
}
public Object getData() {
return mData;
}
}

View File

@@ -0,0 +1,6 @@
package com.mogo.module.tanlu.callback
interface IThumbsUpCallback {
fun onThumbsUpSuccess()
fun onThumbsUpFail()
}

View File

@@ -0,0 +1,13 @@
package com.mogo.module.tanlu.callback;
import com.mogo.module.tanlu.model.NaviResult;
/**
* @author lixiaopeng
* @description 导航沿途数据
* @since 2020-01-09
*/
public interface NaviCallback {
void onSuccess(NaviResult data);
void onFail(String message, int code);
}

View File

@@ -0,0 +1,11 @@
package com.mogo.module.tanlu.callback
import com.mogo.module.common.entity.MarkerExploreWay
import com.mogo.module.tanlu.model.RoadInfos
interface RoadInfoCallback {
fun onLocatSuccess(lat: Double, lon: Double)
fun onQueryRoadInfoSuccess(roadInfoList:List<MarkerExploreWay>)
fun onQueryRoadInfoFail(msg: String, code: Int)
}

View File

@@ -0,0 +1,13 @@
package com.mogo.module.tanlu.callback;
import com.mogo.module.tanlu.model.PathLineResult;
/**
* @author lixiaopeng
* @description 通勤族回调
* @since 2020-01-09
*/
public interface RoadLineCallback {
void onSuccess(PathLineResult data);
void onFail(String message, int code);
}

View File

@@ -0,0 +1,14 @@
package com.mogo.module.tanlu.callback;
import com.mogo.commons.data.BaseData;
/**
* @author lixiaopeng
* @description 上报分享
* @since 2020-01-09
*/
public interface UploadShareCallback {
void onSuccess(BaseData data);
void onFail(String message, int code);
}

View File

@@ -0,0 +1,13 @@
package com.mogo.module.tanlu.callback;
import com.mogo.module.tanlu.model.VoiceSearchResult;
/**
* @author lixiaopeng
* @description 声音控制搜索回调
* @since 2020-01-09
*/
public interface VoiceSearchCallback {
void onSuccess(VoiceSearchResult data);
void onFail(String message, int code);
}

View File

@@ -0,0 +1,34 @@
package com.mogo.module.tanlu.constant
const val REQUESTCODE_MAINACTIVITY = 0
const val REQUESTCODE_MEDIAACTIVITY = 1
//EXTRA_STATE
const val AUTO_NAVI_START = 8 //开始导航
const val AUTO_NAVI_END = 9 //结束导航
// 道路事件名称,用于语音识别区分道路事件
const val TYPE_NAME_BLOCK = "拥堵"
const val TYPE_NAME_TRAFFIC_CHECK = "交通检查"
const val TYPE_NAME_CLOSURE = "封路"
const val TYPE_NAME_ACCIDENT = "交通事故"
const val TYPE_NAME_REAL_TIME_TRAFFIC = "实时路况"
const val TYPE_NAME_STAGNANT_WATER = "积水"
const val TYPE_NAME_ROAD_ICY = "积冰"
const val TYPE_NAME_DENSE_FOG = ""
const val TYPE_NAME_ROAD_CONSTRUCTION = "施工"
/**
* 搜索交通检查
*/
const val VOICE_COMMAND_QUERY_TRAFFIC_CHECK = "com.zhidao.share.traffic.police"
/**
* 搜索封路信息
*/
const val VOICE_COMMAND_QUERY_ROAD_CLOSED = "com.zhidao.share.road.closure.query"
/**
* 其他道路事件,包括事故,实时路况,道路积水,道路积冰,浓雾
*/
const val VOICE_COMMAND_NOVELTY_QUERY = "com.zhidao.novelty.query"

View File

@@ -0,0 +1,13 @@
package com.mogo.module.tanlu.constant;
/**
* @author lixiaopeng
* @description
* @since 2020-01-09
*/
public class HttpConst {
public static final String HOST_DEV = "http://dzt-test.zhidaohulian.com";
public static final String HOST_SHOW = "http://dzt-show.zhidaohulian.com";
public static final String HOST_TEST = "http://dzt-test.zhidaohulian.com";
public static final String HOST_PRODUCT = "https://dzt.zhidaohulian.com";
}

View File

@@ -0,0 +1,112 @@
package com.mogo.module.tanlu.constant;
/**
* @author congtaowang
* @since 2019-12-24
* <p>
* 描述
*/
public class TanluConstants {
/**
* 加油 10001
* 交通检查 10002
* 封路 10003
* 商场打折 10004
* 4S店 10005
* 施工 10006
* 拥堵 10007
* 积水 10008
* 超市折扣 10009
* 浓雾 10010
* 结冰 10011
* 停车场 10012
* 交通事故 10013
* 社保 10014
* 实时路况 10015
*/
public static final String TANLU_ROAD_PONDING = "10008"; //积水
public static final String TANLU_ROAD_ICING = "10011"; //积冰
public static final String TANLU_ROAD_HEAVY_FOG = "10010"; //大雾
public static final String TANLU_ROAD_ACCIDENT = "10013"; //事故
public static final String TANLU_ROAD_CONSTRUCTION = "10006"; //道路施工
public static final String TANLU_ROAD_CONGESTION_COMPAT = "10007"; //拥堵,适配语音不做数值转换
public static final String TANLU_TRAFFIC_CHECK_COMPAT = "10002"; //交通检查,适配语音不做数值转换
public static final String TANLU_ROAD_CLOSURE_COMPAT = "10003"; //封路,适配语音不做数值转换
public static final String TANLU_ROAD_CURRENT = "10015"; //实时路况
public static final String TAG = "/tanlu/ui";
public static final String NAVI_INFO = "navi_info";
public static final String MODEL_NAME = "CARD_TYPE_ROAD_CONDITION";
public static final String[] CMD_PLAY_ROAD_CONDITION = {"播放路况"};
public static final String[] CMD_THE_PREVIOUS = {"上一条"};
public static final String[] CMD_THE_NEXT = {"下一条"};
public static final String[] CMD_UPLOAD_BLOCK = {"上报拥堵"};
public static final String[] CMD_TRAFFIC_CHECK = {"上报交通检查"};
public static final String[] CMD_ROAD_CLOSURE = {"上报封路"};
//上报拥堵
public static final String UPLOAD_ROAD_BLOCK = "command_upload_block";
//上报交通检查
public static final String UPLOAD_TRAFFIC_CHECK = "command_upload_traffic_check";
//上报封路
public static final String UPLOAD_ROAD_CLOSURE = "command_upload_road_closure";
//上报路况
public static final String UPLOAD_ROAD_CONDITION = "command_upload_roadcondition";
//打开探路 免唤醒
public static final String OPEN_ROADCONDITION = "command_open_roadcondition";
//打开探路 唤醒
public static final String OPEN_ROADCONDITION_AWAKE = "com.zhidao.desk.switchCard";
//打开探路 唤醒
public static final String OPEN_ROADCONDITION_AWAKE_COMMAND = "system.application.operation";
//xx堵不堵 唤醒
public static final String SPECIFIEDROAD_SEARCH = "com.zhidao.pathfinder.specifiedroad.search";
//播放 免唤醒
public static final String PLAY_VIDEO = "com.zhidao.tanlu.play";
//播放 唤醒
public static final String PLAY_VIDEO_AWAKEN = "com.zhidao.pathfinder.play.roadCondition";
//分享路况/上报路况/上报拥堵/上报交通检查/上报封路 唤醒
public static final String UPLOAD_ROAD_CONDITION_AWAKEN = "com.zhidao.pathfinder.report.roadCondition";
//关闭分享框 唤醒
public static final String SHARE_DIALOG_CLOSE = "com.zhidao.share.close";
public static final String AWAKE_NOTIFY = "com.zhidao.speech.awake.notify";
//上一条
// public static final String THE_PREVIOUS = "com.zhidao.tanlu.previous";
//下一条
// public static final String THE_NEXT = "com.zhidao.tanlu.next";
//分享封路
public static final String SHARE_ROAD_CLOSURE = "com.zhidao.share.road.closure";
//分享交通检查
public static final String SHARE_TRAFFIC_CHECK = "com.zhidao.share.traffic.check";
//我要分享
public static final String GO_TO_SHARE = "com.zhidao.share";
//埋点数据
//marker点击
public static final String LAUNCHER_ICON_CLICK = "Launcher_Icon_Click";
//分享分类 1路况2油价3交通检查4封路
public static final String LAUNCHER_SHARE_TYPE = "Launcher_Share_type";
//分享/上报按钮点击 from=1 手动点击 from=2 语音打开
public static final String LAUNCHER_SHARE_CLICK = "Launcher_Share_Click";
public static final String CARNET_USER_UPLOAD = "CarNet_user_upload";
public static final String CARNET_ROAD_ENVENT = "v2x_road_event";
//语音搜索
public static final String CARNET_VOICE_SEARCH = "CarNet_Voice_Search";
//视频播放
public static final String CARNET_USER_VIDEO_PLAY = "CarNet_user_video_play";
public static final String LAUNCHER_MARKER_ICON_CLICK = "Launcher_Icon_Click";
}

View File

@@ -0,0 +1,101 @@
package com.mogo.module.tanlu.fragment;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import androidx.fragment.app.Fragment;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.mogo.map.listener.IMogoMapListener;
import com.mogo.map.location.IMogoLocationListener;
import com.mogo.map.marker.IMogoMarkerClickListener;
import com.mogo.map.navi.IMogoNaviListener;
import com.mogo.module.tanlu.callback.DataSetChangedAdapter;
import com.mogo.service.module.IMogoModuleLifecycle;
import com.mogo.service.module.IMogoModuleProvider;
import com.mogo.service.module.ModuleType;
import com.mogo.module.tanlu.constant.TanluConstants;
import com.mogo.utils.logger.Logger;
/**
* @author congtaowang
* @since 2019-12-24
* <p>
* 描述
*/
@Route( path = TanluConstants.TAG )
public class TanluCardViewProvider implements IMogoModuleProvider {
private static final String TAG = "TanluCardViewProvider";
private TanluCardViewFragment fragment;
@Override
public Fragment createFragment( Context context, Bundle data ) {
fragment = new TanluCardViewFragment();
fragment.setArguments( data );
Logger.i( TAG, "createFragment" );
return fragment;
}
@Override
public void init( Context context ) {
Logger.d(TAG, "init --------------> 1");
TanluServiceManager.init( context );
TanluServiceManager.getDataManager().registerDataListener( TanluConstants.MODEL_NAME, DataSetChangedAdapter.getInstance() );
TanluListWindow tanluListWindow = new TanluListWindow(context);
tanluListWindow.initWindow();
}
@Override
public String getModuleName() {
return "CARD_TYPE_ROAD_CONDITION";
}
@Override
public IMogoModuleLifecycle getCardLifecycle() {
return fragment;
}
@Override
public View createView( Context context ) {
// don't
return null;
}
@Override
public IMogoMapListener getMapListener() {
return fragment;
}
@Override
public int getType() {
return ModuleType.TYPE_CARD_FRAGMENT;
}
@Override
public IMogoNaviListener getNaviListener() {
return null;
}
@Override
public IMogoLocationListener getLocationListener() {
return fragment;
}
@Override
public IMogoMarkerClickListener getMarkerClickListener() {
return null;
}
@Override
public String getAppPackage() {
return "";
}
@Override
public String getAppName() {
return "探路";
}
}

View File

@@ -0,0 +1,100 @@
package com.mogo.module.tanlu.fragment;
import android.content.Context;
import com.alibaba.android.arouter.launcher.ARouter;
import com.mogo.map.location.IMogoLocationClient;
import com.mogo.map.search.poisearch.IMogoPoiSearch;
import com.mogo.map.search.poisearch.query.MogoPoiSearchQuery;
import com.mogo.module.carchattingprovider.ICarsChattingProvider;
import com.mogo.service.IMogoServiceApis;
import com.mogo.service.MogoServicePaths;
import com.mogo.service.analytics.IMogoAnalytics;
import com.mogo.service.datamanager.IMogoDataManager;
import com.mogo.service.intent.IMogoIntentManager;
import com.mogo.service.map.IMogoMapService;
import com.mogo.service.module.IMogoRegisterCenter;
import com.mogo.service.statusmanager.IMogoStatusManager;
import com.mogo.service.windowview.IMogoTopViewManager;
import com.zhidao.carchattingprovider.CallChattingProviderConstant;
/**
* @author lixiaopeng
* @since 2020-5-19
* <p>
* 持有服务接口实例
*/
public class TanluServiceManager {
private static String TAG = "TanluServiceManager";
private static IMogoMapService mMapService;
private static IMogoPoiSearch mPoiSearch;
private static IMogoLocationClient mLocationClient;
private static IMogoDataManager mDataManager;
private static IMogoServiceApis mServiceApis;
private static IMogoStatusManager mIMogoStatusManager;
private static IMogoAnalytics mAnalytics;
private static IMogoIntentManager mogoIntentManager;
private static IMogoRegisterCenter mogoRegisterCenter;
private static ICarsChattingProvider mCarsChattingProvider;
private static IMogoTopViewManager mIMogoTopViewManager;
public static void init(Context context) {
mServiceApis = (IMogoServiceApis) ARouter.getInstance().build(MogoServicePaths.PATH_SERVICE_APIS).navigation(context);
mMapService = mServiceApis.getMapServiceApi();
mDataManager = mServiceApis.getDataManagerApi();
mIMogoStatusManager = mServiceApis.getStatusManagerApi();
mAnalytics = mServiceApis.getAnalyticsApi();
mogoIntentManager = mServiceApis.getIntentManagerApi();
mogoRegisterCenter = mServiceApis.getRegisterCenterApi();
mCarsChattingProvider = (ICarsChattingProvider) ARouter.getInstance().build(CallChattingProviderConstant.CAR_CALL_PROVIDER).navigation();
mIMogoTopViewManager = mServiceApis.getTopViewManager();
mPoiSearch = mMapService.getPoiSearch(context, new MogoPoiSearchQuery());
mLocationClient = mMapService.getSingletonLocationClient(context);
}
public static IMogoTopViewManager getIMogoTopViewManager() {
return mIMogoTopViewManager;
}
public static IMogoRegisterCenter getIMogoRegisterCenter() {
return mogoRegisterCenter;
}
public static IMogoMapService getMapService() {
return mMapService;
}
public static IMogoPoiSearch getPoiSearch() {
return mPoiSearch;
}
public static IMogoLocationClient getLocationClient() {
return mLocationClient;
}
public static IMogoAnalytics getAnalytics() {
return mAnalytics;
}
public static IMogoIntentManager getMogoIntentManager() {
return mogoIntentManager;
}
public static IMogoStatusManager getMogoStatusManager() {
return mIMogoStatusManager;
}
public static IMogoDataManager getDataManager() {
return mDataManager;
}
public static IMogoServiceApis getServiceApis() {
return mServiceApis;
}
public static ICarsChattingProvider getCarsChattingProvider() {
return mCarsChattingProvider;
}
}

View File

@@ -0,0 +1,483 @@
package com.mogo.module.tanlu.fragment.recycler;
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorSet;
import android.content.Context;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.mogo.commons.debug.DebugConfig;
import com.mogo.module.common.entity.MarkerExploreWay;
import com.mogo.module.tanlu.R;
import com.mogo.module.tanlu.callback.IThumbsUpCallback;
import com.mogo.module.tanlu.constant.TanluConstants;
import com.mogo.module.tanlu.model.TanluModelData;
import com.mogo.module.tanlu.model.event.ControlClickUpInfo;
import com.mogo.module.tanlu.model.event.StartPlayInfo;
import com.mogo.module.tanlu.model.event.VoiceControlUpInfo;
import com.mogo.module.tanlu.util.ChartUtil;
import com.mogo.module.tanlu.video.SimpleCoverVideoPlayer;
import com.mogo.service.analytics.IMogoAnalytics;
import com.mogo.service.imageloader.IMogoImageloader;
import com.mogo.service.imageloader.MogoImageView;
import com.mogo.utils.TipToast;
import com.mogo.utils.logger.Logger;
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static com.mogo.module.tanlu.util.StringUitlKt.formatDate;
import static com.mogo.module.tanlu.util.Utils.handleDistance;
/**
* @author lixiaopeng
* @description
* @since 2020/3/11
*/
public class TanluSlideAdapterNew extends RecyclerView.Adapter<TanluSlideViewHolderNew> {
private List<MarkerExploreWay> markerExploreWayList = new ArrayList<>();
private static final String TAG = "TanluSlideAdapterNew";
private Context mContext;
private TextView mAddressTv;
private TextView mDistanceTv;
private TextView mTimeTv;
private SimpleCoverVideoPlayer simpleCoverVideoPlayer;
private ImageView autoZoomInImageView;
private MogoImageView mHeadImage;
private ImageView mChatImage;
private ImageView mLikeImage;
private LinearLayout mLikeLayout;
private TextView mTypeTv;
private IMogoImageloader mogoImageloader;
//media
private GSYVideoOptionBuilder gsyVideoOptionBuilder = new GSYVideoOptionBuilder();
private String mVideoUrl = "";
private String mImageUrl = "";
//底层api
private IMogoAnalytics mAnalytics;
private TanluModelData mTanluModelData;
private HashMap<Integer, SimpleCoverVideoPlayer> list = new HashMap<>();
public TanluSlideAdapterNew(Context context, IMogoAnalytics analytics, TanluModelData tanluModelData, IMogoImageloader mogoImageloader) {
this.mContext = context;
this.mAnalytics = analytics;
this.mTanluModelData = tanluModelData;
this.mogoImageloader = mogoImageloader;
EventBus.getDefault().register(this);
}
@NonNull
@Override
public TanluSlideViewHolderNew onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View inflate = LayoutInflater.from(parent.getContext())
.inflate(R.layout.tanlu_item_main_media_recycler_new, parent, false);
return new TanluSlideViewHolderNew(inflate);
}
@Override
public void onBindViewHolder(@NonNull TanluSlideViewHolderNew holder, int position) {
final MarkerExploreWay markerExploreWay = markerExploreWayList.get(position);
if (markerExploreWay == null) {
return;
}
mAddressTv = holder.itemView.findViewById(R.id.tv_information_media_content);
mDistanceTv = holder.itemView.findViewById(R.id.tv_information_media_distance);
mTimeTv = holder.itemView.findViewById(R.id.tv_information_media_time);
simpleCoverVideoPlayer = holder.itemView.findViewById(R.id.video_player_main);
autoZoomInImageView = holder.itemView.findViewById(R.id.tanlu_photo_imageView);
mHeadImage = holder.itemView.findViewById(R.id.tanlu_head_imageView);
mChatImage = holder.itemView.findViewById(R.id.tanlu_chat_imageView);
mLikeImage = holder.itemView.findViewById(R.id.tanlu_like_imageView);
mLikeLayout = holder.itemView.findViewById(R.id.tanlu_like_layout);
mTypeTv = holder.itemView.findViewById(R.id.tv_information_type);
//有可能不是一个对象
simpleCoverVideoPlayer.setVisibility(View.VISIBLE);
autoZoomInImageView.setVisibility(View.GONE);
list.put(position, simpleCoverVideoPlayer);
mTypeTv.setText(getTypeName(markerExploreWay.getPoiType()));
if (markerExploreWay.getPoiType().equals(TanluConstants.TANLU_ROAD_CURRENT)) {
mTypeTv.setBackgroundResource(R.drawable.tanlu_type_button_blue_bg);
} else {
mTypeTv.setBackgroundResource(R.drawable.tanlu_event_type_red_bg);
}
//自研车机
if (DebugConfig.getCarMachineType() == 0) {
if (markerExploreWay.getUserInfo() != null) {
//是否能拨打
ChartUtil.isCanCall(mContext.getApplicationContext(), b -> {
Logger.d(TAG, " isCanCall b = " + b + " >>>sn =" + markerExploreWay.getUserInfo().getSn());
if (b) {
//对方是否在线
ChartUtil.isOnLine(markerExploreWay.getUserInfo().getSn(), mContext.getApplicationContext(), b1 -> {
Logger.d(TAG, " isonline b1 = " + b1 + " >>>sn =" + markerExploreWay.getUserInfo().getSn());
if (b1) {
mChatImage.setVisibility(VISIBLE);
} else {
mChatImage.setVisibility(GONE);
}
});
} else {
mChatImage.setVisibility(GONE);
}
});
} else {
Logger.e(TAG, " markerExploreWay.getUserInfo() == null ");
mChatImage.setVisibility(GONE);
}
}
//加载头像图片
// RequestOptions requestOptions = new RequestOptions()
// .circleCrop()
// .placeholder(R.drawable.tanlu_head_image)
// .error(R.drawable.tanlu_head_image)
// .fallback(R.drawable.tanlu_head_image);
// Glide.with(mContext)
// .load(markerExploreWay.getUserInfo() != null ? markerExploreWay.getUserInfo().getUserHead() : "")
// .apply(requestOptions)
// .into(mHeadImage);
if (mogoImageloader != null) {
mogoImageloader.displayImage(markerExploreWay.getUserInfo() != null ? markerExploreWay.getUserInfo().getUserHead() : "", mHeadImage);
}
//处理数据显示
handleMarkerExploreWay(markerExploreWay);
mChatImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
traceTypeData(markerExploreWay.getInfoId() == null ? "" : markerExploreWay.getInfoId(), "2", markerExploreWay.getSn() == null ? "" : markerExploreWay.getSn());
ChartUtil.callChatting(markerExploreWay.getUserInfo(), markerExploreWay.getLocation());
}
});
mLikeLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//动画
AnimatorSet animatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(mContext, R.anim.v2x_like_heart_animation);
animatorSet.setTarget(mLikeImage);
animatorSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
traceTypeData(markerExploreWay.getInfoId() == null ? "" : markerExploreWay.getInfoId(), "1", markerExploreWay.getSn() == null ? "" : markerExploreWay.getSn());
if (TextUtils.isEmpty(markerExploreWay.getInfoId())) {
TipToast.shortTip("点赞失败");
return;
}
mTanluModelData.thumbsUp(markerExploreWay, new IThumbsUpCallback() {
@Override
public void onThumbsUpSuccess() {
TipToast.shortTip("点赞成功");
Logger.d(TAG, "onThumbsUpSuccess -------->");
}
@Override
public void onThumbsUpFail() {
TipToast.shortTip("点赞失败");
Logger.e(TAG, "onThumbsUpFail -------->");
}
});
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animatorSet.start();
}
});
}
@Override
public int getItemCount() {
return markerExploreWayList == null ? 0 : markerExploreWayList.size();
}
@Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
@Override
public long getItemId(int position) {
return position;
}
/**
* 设置数据
*
* @param datas
*/
public void setDatas(List<MarkerExploreWay> datas) {
if (markerExploreWayList != null) {
markerExploreWayList.clear();
markerExploreWayList.addAll(datas);
Logger.e(TAG, "setDatas size = " + markerExploreWayList.size());
}
}
/**
* 通用的处理数据逻辑
*
* @param markerExploreWay
*/
private void handleMarkerExploreWay(MarkerExploreWay markerExploreWay) {
if (markerExploreWay != null) {
Logger.d(TAG, "markerExploreWay.getFileType() =" + markerExploreWay.getFileType());
if (markerExploreWay.getFileType() == 0) { //图片
refreshPhotoData(markerExploreWay);
} else if (markerExploreWay.getFileType() == 1) { //视频
refreshVideoData(markerExploreWay);
}
} else {
Logger.e(TAG, "handleMarkerExploreWay == null");
}
}
/**
* 刷新单个视频数据,更新位置positon
*/
private void refreshVideoData(MarkerExploreWay markerExploreWay) {
if (markerExploreWay.getItems() == null) {
showDefaultImage();
return;
}
if (markerExploreWay.getItems().size() == 0) {
showDefaultImage();
return;
}
String videoUrl = markerExploreWay.getItems().get(0).getUrl();
mImageUrl = markerExploreWay.getItems().get(0).getThumbnail();
Logger.d(TAG, "refreshVideoData mImageUrl = " + mImageUrl);
mAddressTv.setText(markerExploreWay.getAddr());
Logger.e(TAG, "refreshVideoData markerExploreWay.getAddr() = " + markerExploreWay.getAddr() + " >>>>videoUrl = " + videoUrl);
mDistanceTv.setText("距离" + handleDistance(markerExploreWay.getDistance()));
mTimeTv.setText(formatDate(markerExploreWay.getGenerateTime()));
//判断是图片还是视频,第一个时,上一个不可点击
autoZoomInImageView.setVisibility(View.GONE);
//视频配置
mVideoUrl = videoUrl;
if (!TextUtils.isEmpty(videoUrl) && !TextUtils.isEmpty(mImageUrl)) {
autoZoomInImageView.setVisibility(View.GONE);
simpleCoverVideoPlayer.setVisibility(View.VISIBLE);
//加载封面图
simpleCoverVideoPlayer.loadCoverImage(mImageUrl, mContext);
gsyVideoOptionBuilder.setUrl(videoUrl).setCacheWithPlay(false).setPlayTag(TAG)
.build(simpleCoverVideoPlayer);
simpleCoverVideoPlayer.getStartButton().performClick();
} else {
simpleCoverVideoPlayer.setVisibility(GONE);
autoZoomInImageView.setVisibility(View.VISIBLE);
//加载图片
RequestOptions requestOptions = new RequestOptions()
.placeholder(R.drawable.tanlu_normal_image)
.error(R.drawable.tanlu_normal_image)
.fallback(R.drawable.tanlu_normal_image);
Glide.with(mContext)
.load(mImageUrl)
.apply(requestOptions)
.into(autoZoomInImageView);
}
traceVideoPlayStatusData();
}
/**
* 刷新单个图片数据
*/
private void refreshPhotoData(MarkerExploreWay markerExploreWay) {
if (markerExploreWay.getItems() == null) {
Logger.e(TAG, "refreshPhotoData markerExploreWay.getItems() == null");
showDefaultImage();
return;
}
if (markerExploreWay.getItems().size() == 0) {
Logger.e(TAG, "refreshPhotoData markerExploreWay.getItems().size() == 0");
showDefaultImage();
return;
}
mAddressTv.setText(markerExploreWay.getAddr());
mDistanceTv.setText("距离 " + handleDistance(markerExploreWay.getDistance()));
mTimeTv.setText(formatDate(markerExploreWay.getGenerateTime()));
String imageUrl = markerExploreWay.getItems().get(0).getUrl();
simpleCoverVideoPlayer.setVisibility(View.GONE);
autoZoomInImageView.setVisibility(View.VISIBLE);
Logger.d(TAG, "refreshPhotoData imageUrl = " + imageUrl);
//加载图片
RequestOptions requestOptions = new RequestOptions()
.placeholder(R.drawable.tanlu_normal_image)
.error(R.drawable.tanlu_normal_image)
.fallback(R.drawable.tanlu_normal_image);
Glide.with(mContext)
.load(imageUrl)
.apply(requestOptions)
.into(autoZoomInImageView);
}
private void showDefaultImage() {
simpleCoverVideoPlayer.setVisibility(View.GONE);
autoZoomInImageView.setVisibility(View.VISIBLE);
}
/**
* 上传播放
*/
private void traceVideoPlayStatusData() {
if (mAnalytics != null) {
mAnalytics.track(TanluConstants.CARNET_USER_VIDEO_PLAY, null);
}
}
private void traceTypeData(String id, String type, String sn) {
Map<String, Object> properties = new HashMap<>();
properties.put("dbid", id);
properties.put("type", type);
properties.put("sn", sn);
mAnalytics.track(TanluConstants.CARNET_ROAD_ENVENT, properties);
}
/**
* 上一条逻辑
*/
private void handlePrevious() {
//判断是图片还是视频,第一个时,上一个不可点击
Logger.d(TAG, " handlePrevious >> size= " + markerExploreWayList.size());
EventBus.getDefault().post(new ControlClickUpInfo("1"));
}
/**
* 下一条逻辑
*/
private void handleNext() {
//判断是图片还是视频,最后一个时,下一个不可点击
Logger.d(TAG, " handleNext >> size= " + markerExploreWayList.size());
EventBus.getDefault().post(new ControlClickUpInfo("2"));
}
/**
* @param event
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void onPushInfo(final VoiceControlUpInfo event) {
Logger.d(TAG, "TanluSlideAdapter onPushInfo -----type = " + event.type);
if (event.type.equals("1")) { //上一条
handlePrevious();
} else if (event.type.equals("2")) { //下一条
handleNext();
}
}
/**
* 开始播放
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void onHandlePlay(final StartPlayInfo info) {
int finalPosition = info.mPosition;
Logger.d(TAG, "onHandlePlay size = " + list.size() + " >> info.mPosition = " + info.mPosition + " >> finalPosition = " + finalPosition);
// if (list.size() > finalPosition) {
SimpleCoverVideoPlayer coverVideoPlayer = list.get(finalPosition);
coverVideoPlayer.release();
coverVideoPlayer.getStartButton().performClick();
traceVideoPlayStatusData();
// }
}
public void release() {
if (list != null) {
list.clear();
}
}
private String getTypeName(String type) {
String typeName = "";
switch (type) {
case TanluConstants.TANLU_TRAFFIC_CHECK_COMPAT:
typeName = "交通检查";
break;
case TanluConstants.TANLU_ROAD_CLOSURE_COMPAT:
typeName = "封路";
break;
case TanluConstants.TANLU_ROAD_CONSTRUCTION:
typeName = "道路施工";
break;
case TanluConstants.TANLU_ROAD_CONGESTION_COMPAT:
typeName = "道路拥堵";
break;
case TanluConstants.TANLU_ROAD_PONDING:
typeName = "道路积水";
break;
case TanluConstants.TANLU_ROAD_ICING:
typeName = "路面结冰";
break;
case TanluConstants.TANLU_ROAD_HEAVY_FOG:
typeName = "出现浓雾";
break;
case TanluConstants.TANLU_ROAD_ACCIDENT:
typeName = "交通事故";
break;
case TanluConstants.TANLU_ROAD_CURRENT:
typeName = "实时路况";
break;
default:
typeName = "道路拥堵";
break;
}
return typeName;
}
}

View File

@@ -0,0 +1,19 @@
package com.mogo.module.tanlu.fragment.recycler;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
/**
* @author lixiaopeng
* @description
* @since 2020/3/11
*/
public class TanluSlideViewHolderNew extends RecyclerView.ViewHolder{
public TanluSlideViewHolderNew(@NonNull View itemView) {
super(itemView);
}
}

View File

@@ -0,0 +1,5 @@
package com.mogo.module.tanlu.model
import com.mogo.commons.data.BaseData
data class BaseDataCompat<T>(var result:T?):BaseData()

View File

@@ -0,0 +1,17 @@
package com.mogo.module.tanlu.model
class CarsLive {
var sn: String
var lat: Double
var lon: Double
var direction: Int
var canLive: Int
constructor(sn: String, lat: Double, lon: Double, direction: Int, canLive: Int) {
this.sn = sn
this.lat = lat
this.lon = lon
this.direction = direction
this.canLive = canLive
}
}

View File

@@ -0,0 +1,12 @@
package com.mogo.module.tanlu.model
/**
* @description
*
* @author lixiaopeng
* @since 2019-10-24
*/
data class Center (
val lat: Double,//weidu
val lon: Double
)

View File

@@ -0,0 +1,16 @@
package com.mogo.module.tanlu.model;
/**
* @author lixiaopeng
* @description
* @since 2020-01-09
*/
public class End {
public Double lat;
public Double lon;
public End(Double lat, Double lon) {
this.lat = lat;
this.lon = lon;
}
}

View File

@@ -0,0 +1,80 @@
package com.mogo.module.tanlu.model;
import android.os.Parcel;
import android.os.Parcelable;
import com.mogo.commons.data.BaseData;
import java.util.ArrayList;
/**
* @author lixiaopeng
* @description 列表数据
* @since 2020-01-05
*/
public class Information extends BaseData implements Parcelable {
public int type;
public Double lon;
public Double lat;
public String addr;
public Long generateTime;
public String cityName;
public ArrayList<Items> items;
public int distance;
public String nickName;
public String headImgUrl;
public String phone;
public String trafficInfoType;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.type);
dest.writeValue(this.lon);
dest.writeValue(this.lat);
dest.writeString(this.addr);
dest.writeValue(this.generateTime);
dest.writeString(this.cityName);
dest.writeTypedList(this.items);
dest.writeInt(this.distance);
dest.writeString(this.nickName);
dest.writeString(this.headImgUrl);
dest.writeString(this.phone);
dest.writeString(this.trafficInfoType);
}
public Information() {
}
protected Information(Parcel in) {
this.type = in.readInt();
this.lon = (Double) in.readValue(Double.class.getClassLoader());
this.lat = (Double) in.readValue(Double.class.getClassLoader());
this.addr = in.readString();
this.generateTime = (Long) in.readValue(Long.class.getClassLoader());
this.cityName = in.readString();
this.items = in.createTypedArrayList(Items.CREATOR);
this.distance = in.readInt();
this.nickName = in.readString();
this.headImgUrl = in.readString();
this.phone = in.readString();
this.trafficInfoType = in.readString();
}
public static final Creator<Information> CREATOR = new Creator<Information>() {
@Override
public Information createFromParcel(Parcel source) {
return new Information(source);
}
@Override
public Information[] newArray(int size) {
return new Information[size];
}
};
}

View File

@@ -0,0 +1,38 @@
package com.mogo.module.tanlu.model;
import com.mogo.commons.data.BaseData;
/**
* @author lixiaopeng
* @description
* @since 2020-01-09
*/
public class InformationAndLiveCarResult extends BaseData {
private Result onTheWayData;
private Result infoMationResult;
private Sns snResult;
public Result getOnTheWayData() {
return onTheWayData;
}
public void setOnTheWayData(Result onTheWayData) {
this.onTheWayData = onTheWayData;
}
public Result getInfoMationResult() {
return infoMationResult;
}
public void setInfoMationResult(Result infoMationResult) {
this.infoMationResult = infoMationResult;
}
public Sns getSnResult() {
return snResult;
}
public void setSnResult(Sns snResult) {
this.snResult = snResult;
}
}

View File

@@ -0,0 +1,33 @@
package com.mogo.module.tanlu.model
import android.os.Parcel
import android.os.Parcelable
class Items(var url: String? = null, var thumbnail: String? = null) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readString()
) {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(url)
parcel.writeString(thumbnail)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<Items> {
override fun createFromParcel(parcel: Parcel): Items {
return Items(parcel)
}
override fun newArray(size: Int): Array<Items?> {
return arrayOfNulls(size)
}
}
}

View File

@@ -0,0 +1,21 @@
package com.mogo.module.tanlu.model
class LocationCarsWithRadius {
var coordinates: List<Double>
var radius: Int
var type: String
var keyWord: String? = null
constructor(coordinates: List<Double>, radius: Int, type: String, keyWord: String) {
this.coordinates = coordinates
this.radius = radius
this.type = type
this.keyWord = keyWord
}
constructor(coordinates: List<Double>, radius: Int, type: String) {
this.coordinates = coordinates
this.radius = radius
this.type = type
}
}

View File

@@ -0,0 +1,17 @@
package com.mogo.module.tanlu.model;
/**
* @author lixiaopeng
* @description
* @since 2020-01-09
*/
public class NaviLatLng {
public Start start;
public End end;
NaviLatLng(Start start, End end) {
this.start = start;
this.end = end;
}
}

View File

@@ -0,0 +1,55 @@
package com.mogo.module.tanlu.model;
import java.io.Serializable;
/**
* @author lixiaopeng
* @description
* @since 2020-01-09
*/
public class NaviLatLngInfo implements Serializable {
public String FromPoiLatitude = "";
public String FromPoiLongitude = "";
public String ToPoiLatitude = "";
public String ToPoiLongitude= "";
public Start fromStart() {
return new Start(Double.parseDouble(FromPoiLatitude), Double.parseDouble(FromPoiLongitude));
}
public End toEnd() {
return new End(Double.parseDouble(ToPoiLatitude), Double.parseDouble(ToPoiLongitude));
}
public String getFromPoiLatitude() {
return FromPoiLatitude;
}
public void setFromPoiLatitude(String fromPoiLatitude) {
FromPoiLatitude = fromPoiLatitude;
}
public String getFromPoiLongitude() {
return FromPoiLongitude;
}
public void setFromPoiLongitude(String fromPoiLongitude) {
FromPoiLongitude = fromPoiLongitude;
}
public String getToPoiLatitude() {
return ToPoiLatitude;
}
public void setToPoiLatitude(String toPoiLatitude) {
ToPoiLatitude = toPoiLatitude;
}
public String getToPoiLongitude() {
return ToPoiLongitude;
}
public void setToPoiLongitude(String toPoiLongitude) {
ToPoiLongitude = toPoiLongitude;
}
}

View File

@@ -0,0 +1,19 @@
package com.mogo.module.tanlu.model
import java.io.Serializable
fun NaviLatLngInfo.fromStart(): Start {
return Start(FromPoiLatitude.toDouble(), FromPoiLongitude.toDouble())
}
fun NaviLatLngInfo.toEnd(): End {
return End(ToPoiLatitude.toDouble(), ToPoiLongitude.toDouble())
}
class NaviLatLngInfo1 : Serializable {
var FromPoiLatitude: String = ""
var FromPoiLongitude: String = ""
var ToPoiLatitude: String = ""
var ToPoiLongitude: String = ""
}

View File

@@ -0,0 +1,36 @@
package com.mogo.module.tanlu.model;
import com.mogo.commons.data.BaseData;
import java.util.List;
/**
* @author lixiaopeng
* @description 导航沿途数据
* @since 2020-02-03
*/
public class NaviResult extends BaseData {
private Result result;
public Result getResult() {
return result;
}
public void setResult(Result result) {
this.result = result;
}
public static class Result {
private List<Information> informations;
public List<Information> getInformations() {
return informations;
}
public void setInformations(List<Information> informations) {
this.informations = informations;
}
}
}

Some files were not shown because too many files have changed in this diff Show More