diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index c7a463ad78..5be0f1a92d 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -46,6 +46,9 @@
+
+
+
diff --git a/app/build.gradle b/app/build.gradle
index 10558b4e0e..5fbe086d08 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -153,8 +153,6 @@ dependencies {
debugImplementation rootProject.ext.dependencies.debugleakcanary
releaseImplementation rootProject.ext.dependencies.releaseleakcanary
- implementation rootProject.ext.dependencies.callchatprovider
- implementation rootProject.ext.dependencies.callchat
implementation rootProject.ext.dependencies.mogologlib
compileOnly rootProject.ext.dependencies.adasapi
@@ -186,6 +184,10 @@ dependencies {
implementation rootProject.ext.dependencies.moduleleftpanelnoop
implementation rootProject.ext.dependencies.crashreportupgrade
implementation rootProject.ext.dependencies.crashreportbugly
+ implementation rootProject.ext.dependencies.callchat
+ implementation rootProject.ext.dependencies.callchatprovider
+
+
} else {
implementation project(':foudations:mogo-aicloud-services-sdk')
implementation project(':foudations:mogo-commons')
@@ -204,6 +206,10 @@ dependencies {
implementation project(':modules:mogo-module-apps')
implementation project(":modules:mogo-module-push-base")
implementation project(":modules:mogo-module-push")
+ implementation project(':modules:mogo-module-carchatting')
+ implementation project(':modules:mogo-module-carchattingprovider')
+
+
implementation project(':test:crashreport-upgrade')
implementation project(':test:crashreport-bugly')
diff --git a/config.gradle b/config.gradle
index 5b7c5050cc..2b18fc52b3 100644
--- a/config.gradle
+++ b/config.gradle
@@ -83,6 +83,7 @@ ext {
material : 'com.google.android.material:material:1.4.0',
indicator : 'com.github.zhpanvip:viewpagerindicator:1.0.4',
+ strategy : 'com.zhidaoauto.mic:strategy:1.0.6',
// modules
moduletanlu : "com.mogo.module:module-tanlu:${MOGO_MODULE_TANLU_VERSION}",
@@ -107,6 +108,7 @@ ext {
mogoserviceapi : "com.mogo.service:mogo-service-api:${MOGO_SERVICE_API_VERSION}",
moduleapps : "com.mogo.module:module-apps:${MOGO_MODULE_APPS_VERSION}",
moduleextensions : "com.mogo.module:module-extensions:${MOGO_MODULE_EXTENSIONS_VERSION}",
+ chat : "com.mogo.module.carchatout:module-chat:${CHAT_VERSION}",
callchat : "com.mogo.module.carchatout:module-carchatting:${CARCHATTING_VERSION}",
callchatprovider : "com.mogo.module.carchatout:module-carchatting-provider:${CARCHATTINGPROVIDER_VERSION}",
@@ -196,6 +198,7 @@ ext {
androidxroomktx : "androidx.room:room-ktx:2.2.3",
// rxjava2 with room
roomRxjava : 'androidx.room:room-rxjava2:2.2.3',
+ circleimageview : "de.hdodenhof:circleimageview:3.0.1",
//
mogomodulewidgets : "com.mogo.module:module-widgets:${MOGO_MODULE_WIDGETS_VERSION}",
diff --git a/core/function-impl/mogo-core-function-check/build.gradle b/core/function-impl/mogo-core-function-check/build.gradle
index 631b47c01f..9e514cfcb5 100644
--- a/core/function-impl/mogo-core-function-check/build.gradle
+++ b/core/function-impl/mogo-core-function-check/build.gradle
@@ -44,7 +44,6 @@ dependencies {
implementation rootProject.ext.dependencies.androidxrecyclerview
implementation rootProject.ext.dependencies.androidxconstraintlayout
implementation rootProject.ext.dependencies.arouter
- implementation rootProject.ext.dependencies.callchatprovider
implementation rootProject.ext.dependencies.coroutinesandroid
implementation rootProject.ext.dependencies.coroutinescore
implementation rootProject.ext.dependencies.rxandroid
@@ -56,12 +55,15 @@ dependencies {
if (Boolean.valueOf(RELEASE)) {
implementation rootProject.ext.dependencies.mogocommons
implementation rootProject.ext.dependencies.mogoserviceapi
+ implementation rootProject.ext.dependencies.callchatprovider
+
} else {
implementation project(":foudations:mogo-commons")
implementation project(':services:mogo-service-api')
implementation project(':modules:mogo-module-common')
implementation project(':modules:mogo-module-service')
+ implementation project(':modules:mogo-module-carchattingprovider')
implementation project(':core:mogo-core-utils')
implementation project(':core:mogo-core-data')
diff --git a/gradle.properties b/gradle.properties
index 6b252a7e4b..8356e2b970 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -156,6 +156,7 @@ MOGO_OCH_TAXI_VERSION=2.0.58
# mogoAiCloud sdk services
MOGO_AICLOUD_SERVICES_SDK_VERSION=2.0.58
######## 外部依赖引用
+CHAT_VERSION=1.8.0
# 车聊聊
CARCHATTING_VERSION=2.3.5
# 车聊聊接口
@@ -182,7 +183,7 @@ MOGO_TRAFFICLIVE_VERSION=1.1.46
# 定位服务
MOGO_LOCATION_VERSION=1.1.46
# 自研地图
-MAP_SDK_VERSION=1.0.1-vr-1.1.6
+MAP_SDK_VERSION=V2.0.0
#################架构升级新的版本号
MOGO_CORE_FUNCTION_HMI_VERSION=1.0.0
## 产品库必备配置,产品库自动对versionCode和versionName版本进行升级
diff --git a/modules/mogo-module-carchatting/.gitignore b/modules/mogo-module-carchatting/.gitignore
new file mode 100644
index 0000000000..796b96d1c4
--- /dev/null
+++ b/modules/mogo-module-carchatting/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/modules/mogo-module-carchatting/build.gradle b/modules/mogo-module-carchatting/build.gradle
new file mode 100644
index 0000000000..57a5610c2b
--- /dev/null
+++ b/modules/mogo-module-carchatting/build.gradle
@@ -0,0 +1,92 @@
+plugins {
+ id 'com.android.library'
+ id 'kotlin-android'
+ id 'kotlin-android-extensions'
+ id 'kotlin-kapt'
+ id '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'
+ //ARouter apt 参数
+ kapt {
+ useBuildCache = false
+ arguments {
+ arg("AROUTER_MODULE_NAME", project.getName())
+ }
+ }
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ zipAlignEnabled false
+ consumerProguardFiles 'consumer-rules.pro'
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ sourceSets {
+ main {
+ java.srcDirs = ['src/main/java', 'src/main/aidl']
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ compileOnly rootProject.ext.dependencies.kotlinstdlibjdk7
+ compileOnly rootProject.ext.dependencies.androidxccorektx
+ implementation rootProject.ext.dependencies.androidxrecyclerview
+ compileOnly rootProject.ext.dependencies.coroutinescore
+ compileOnly rootProject.ext.dependencies.coroutinesandroid
+ compileOnly rootProject.ext.dependencies.androidxappcompat
+ compileOnly rootProject.ext.dependencies.androidxconstraintlayout
+ compileOnly rootProject.ext.dependencies.gson
+
+ implementation rootProject.ext.dependencies.arouter
+ kapt rootProject.ext.dependencies.aroutercompiler
+
+ implementation rootProject.ext.dependencies.circleimageview
+ implementation rootProject.ext.dependencies.mogowebsocket
+
+ if (Boolean.valueOf(RELEASE)) {
+ compileOnly rootProject.ext.dependencies.callchatprovider
+ 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
+
+ implementation rootProject.ext.dependencies.chat
+ } else {
+ compileOnly project(':modules:mogo-module-carchattingprovider')
+
+ api project(":libraries:mogo-map")
+ api project(":foudations:mogo-utils")
+ api project(":foudations:mogo-commons")
+ api project(':services:mogo-service-api')
+ implementation project(':modules:mogo-module-common')
+
+ implementation project(':modules:mogo-module-chat')
+
+ implementation project(':core:mogo-core-data')
+
+ }
+}
+apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
diff --git a/modules/mogo-module-carchatting/consumer-rules.pro b/modules/mogo-module-carchatting/consumer-rules.pro
new file mode 100644
index 0000000000..256ab340f9
--- /dev/null
+++ b/modules/mogo-module-carchatting/consumer-rules.pro
@@ -0,0 +1,33 @@
+# 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.carchatting.bean.*{*;}
+-keep class com.mogo.module.carchatting.card.CallChatProvider.*{*;}
+-keep class com.mogo.module.carchatting.card.CallChatConstant.*{*;}
+-keep class com.mogo.module.carchatting.biz.IBizCallChat.*{*;}
+-keep class com.mogo.module.carchatting.invoke.CarsChattingProvider.*{*;}
+-keep class com.mogo.module.carchatting.net.HttpApi.*{*;}
+-keep class com.mogo.module.carchatting.net.HttpConstant.*{*;}
+-keep class com.mogo.module.carchatting.util.AnalyticsUtil.*{*;}
+-keep class com.mogo.module.carchatting.util.DateUtilKt.*{*;}
+-keep class com.mogo.module.carchatting.view.*{*;}
+-keep class com.mogo.module.carchatting.voice.*{*;}
diff --git a/modules/mogo-module-carchatting/gradle.properties b/modules/mogo-module-carchatting/gradle.properties
new file mode 100644
index 0000000000..d1ea9ff74d
--- /dev/null
+++ b/modules/mogo-module-carchatting/gradle.properties
@@ -0,0 +1,3 @@
+GROUP=com.mogo.module.carchatout
+POM_ARTIFACT_ID=module-carchatting
+VERSION_CODE=1
\ No newline at end of file
diff --git a/modules/mogo-module-carchatting/proguard-rules.pro b/modules/mogo-module-carchatting/proguard-rules.pro
new file mode 100644
index 0000000000..73cc6045c4
--- /dev/null
+++ b/modules/mogo-module-carchatting/proguard-rules.pro
@@ -0,0 +1,58 @@
+# 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
+
+#kotlin
+-dontwarn kotlin.*
+-dontwarn kotlin.**
+-keep class kotlin.* { *; }
+-keepclassmembernames class kotlinx.*{
+ volatile ;
+}
+-keepclassmembernames class kotlin.*{
+ volatile ;
+}
+-keep class kotlin.Metadata { *; }
+-keepclassmembers class **$WhenMappings {
+ ;
+}
+-keepclassmembers class kotlin.Metadata {
+ public ;
+}
+-keepclassmembers class kotlin.Metadata { *; }
+-keep @kotlin.Metadata class *
+-keepclasseswithmembers @kotlin.Metadata class * { *; }
+
+#-----CallChating-----
+#AIDL
+-keep class com.zhidao.imdemo.*
+-keep class com.zhidao.imdemo.IMCallBack.*{*;}
+-keep class com.zhidao.imdemo.IMCallRequest.*{*;}
+-keep class com.mogo.module.carchatting.biz.IMCallManager.*{*;}
+
+#Bean
+-keep class com.mogo.module.carchatting.bean.*
+-keep class com.mogo.module.carchatting.bean.ResponseInfo.*{*;}
+-keep class com.mogo.module.carchatting.bean.UserInfo{*;}
+-keep class com.mogo.module.carchatting.card.*
+-keep class com.mogo.module.carchatting.card.CallChatConstant.MODULE_NAME.*
+-keep class com.mogo.module.carchatting.card.CallChatConstant.PROVIDER.*
+-keep class com.mogo.module.carchatting.card.CallChatConstant.PATH.*
\ No newline at end of file
diff --git a/modules/mogo-module-carchatting/src/main/AndroidManifest.xml b/modules/mogo-module-carchatting/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..c7222743b9
--- /dev/null
+++ b/modules/mogo-module-carchatting/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
diff --git a/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/adapter/VehicleTeamAdapter.java b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/adapter/VehicleTeamAdapter.java
new file mode 100644
index 0000000000..46fded9b7b
--- /dev/null
+++ b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/adapter/VehicleTeamAdapter.java
@@ -0,0 +1,103 @@
+package com.mogo.module.carchatting.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.bumptech.glide.request.RequestOptions;
+import com.mogo.chat.model.bean.TeammateInfo;
+import com.mogo.commons.AbsMogoApplication;
+import com.mogo.module.carchatting.R;
+import com.mogo.module.common.glide.SkinAbleBitmapTarget;
+import com.mogo.utils.glide.GlideApp;
+
+import java.util.List;
+
+import de.hdodenhof.circleimageview.CircleImageView;
+
+/**
+ * created by wujifei on 2020/11/16 16:30
+ * describe:车队人员适配器
+ */
+public class VehicleTeamAdapter extends RecyclerView.Adapter {
+ private Context mContext;
+ private List teammates;
+
+ public VehicleTeamAdapter(Context mContext, List teammates) {
+ this.mContext = mContext;
+ this.teammates = teammates;
+ }
+
+ public void setTeammates(List teammates) {
+ this.teammates = teammates;
+ }
+
+ @NonNull
+ @Override
+ public VehicleTeamViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ return new VehicleTeamViewHolder(LayoutInflater.from(mContext).inflate(R.layout.module_car_chatting_launcher_teammate_item, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull VehicleTeamViewHolder holder, int position) {
+ TeammateInfo teammateInfo = teammates.get(position);
+ RequestOptions requestOptions = new RequestOptions().circleCrop()
+ .placeholder(R.mipmap.module_carchatting_default_head_img)
+ .error(R.mipmap.module_carchatting_default_head_img);
+ GlideApp.with(AbsMogoApplication.getApp().getApplicationContext()).asBitmap()
+ .load(teammateInfo.getHeadImgUrl())
+ .placeholder(R.mipmap.module_carchatting_default_head_img).circleCrop()
+ .into(new SkinAbleBitmapTarget(holder.moduleCarchattingCivHead, requestOptions));
+ holder.moduleCarchattingTvNickname.setText(teammateInfo.getNickName() == null ? "蘑菇车主" : teammateInfo.getNickName());
+ if (teammateInfo.getVehicleTeamLeader()) {
+ holder.moduleCarchattingTvIdentity.setText("队长");
+ holder.moduleCarchattingTvIdentity.setBackgroundResource(R.drawable.module_carchatting_team_teammate_leader_bg);
+ holder.moduleCarchattingTvIdentity.setTextColor(mContext.getResources().getColor(R.color.module_carchatting_team_leader));
+ } else {
+ holder.moduleCarchattingTvIdentity.setText("队员");
+ holder.moduleCarchattingTvIdentity.setBackgroundResource(R.drawable.module_carchatting_team_teammate_follower_bg);
+ }
+
+ holder.itemView.setOnClickListener(view -> {
+ if (mClickListener != null) {
+ mClickListener.onItemClickListener(position, teammateInfo);
+ }
+ });
+
+ }
+
+ @Override
+ public int getItemCount() {
+ return teammates == null ? 0 : teammates.size();
+ }
+
+
+ static class VehicleTeamViewHolder extends RecyclerView.ViewHolder {
+ private TextView moduleCarchattingTvIdentity;
+ private CircleImageView moduleCarchattingCivHead;
+ private TextView moduleCarchattingTvNickname;
+
+
+ public VehicleTeamViewHolder(@NonNull View itemView) {
+ super(itemView);
+ moduleCarchattingTvIdentity = (TextView) itemView.findViewById(R.id.module_carchatting_tv_identity);
+ moduleCarchattingCivHead = (CircleImageView) itemView.findViewById(R.id.module_carchatting_civ_head);
+ moduleCarchattingTvNickname = (TextView) itemView.findViewById(R.id.module_carchatting_tv_nickname);
+ }
+ }
+
+ private VehicleTeamItemClickListener mClickListener;
+
+ public void setItemClickListener(VehicleTeamItemClickListener clickListener) {
+ this.mClickListener = clickListener;
+ }
+
+ public interface VehicleTeamItemClickListener {
+ void onItemClickListener(int position, TeammateInfo teammateInfo);
+ }
+}
\ No newline at end of file
diff --git a/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/anim_dsl/Anim.kt b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/anim_dsl/Anim.kt
new file mode 100644
index 0000000000..c6082347f8
--- /dev/null
+++ b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/anim_dsl/Anim.kt
@@ -0,0 +1,82 @@
+package com.mogo.module.carchatting.anim_dsl
+
+import android.animation.Animator
+import android.animation.AnimatorSet
+import android.animation.ValueAnimator
+import android.view.animation.Interpolator
+import android.view.animation.LinearInterpolator
+
+/**
+ * an Animation just like [ValueAnimator], but it could reverse itself without the limitation of API level
+ * [ValueAnimator.reverse] is only available to the API level over 26.
+ * so this class comes to help.
+ */
+abstract class Anim {
+ /**
+ * the real Animator which is about to run
+ */
+ abstract var animator: Animator
+ var builder: AnimatorSet.Builder? = null
+ /**
+ * the duration of Animator
+ */
+ var duration
+ get() = 300L
+ set(value) {
+ animator.duration = value
+ }
+ /**
+ * the interpolator of Animator
+ */
+ var interpolator
+ get() = LinearInterpolator() as Interpolator
+ set(value) {
+ animator.interpolator = value
+ }
+ /**
+ * start delay of Animator
+ */
+ var delay
+ get() = 0L
+ set(value) {
+ animator.startDelay = value
+ }
+
+ /**
+ * the callbacks describe the status of animation
+ */
+ var onRepeat: ((Animator) -> Unit)? = null
+ var onEnd: ((Animator) -> Unit)? = null
+ var onCancel: ((Animator) -> Unit)? = null
+ var onStart: ((Animator) -> Unit)? = null
+
+ /**
+ * reverse the value of [ValueAnimator]
+ */
+ abstract fun reverse()
+
+ /**
+ * to the beginning of animation
+ */
+ abstract fun toBeginning()
+
+ internal fun addListener() {
+ animator.addListener(object : Animator.AnimatorListener {
+ override fun onAnimationRepeat(animation: Animator?) {
+ animation?.let { onRepeat?.invoke(it) }
+ }
+
+ override fun onAnimationEnd(animation: Animator?) {
+ animation?.let { onEnd?.invoke(it) }
+ }
+
+ override fun onAnimationCancel(animation: Animator?) {
+ animation?.let { onCancel?.invoke(it) }
+ }
+
+ override fun onAnimationStart(animation: Animator?) {
+ animation?.let { onStart?.invoke(it) }
+ }
+ })
+ }
+}
\ No newline at end of file
diff --git a/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/anim_dsl/AnimSet.kt b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/anim_dsl/AnimSet.kt
new file mode 100644
index 0000000000..f2c8aea74f
--- /dev/null
+++ b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/anim_dsl/AnimSet.kt
@@ -0,0 +1,155 @@
+package com.mogo.module.carchatting.anim_dsl
+
+import android.animation.Animator
+import android.animation.AnimatorSet
+
+/**
+ * a Container for [Anim] just like [AnimatorSet], but it could reverse itself without API level limitation.
+ * In addition, it is easy to build mush shorter and readable animation code like the following:
+ *
+ * animSet {
+ * anim {
+ * values = floatArrayOf(1.0f, 1.4f)
+ * action = { value -> tv.scaleX = (value as Float) }
+ * } with anim {
+ * values = floatArrayOf(0f, -200f)
+ * action = { value -> tv.translationY = (value as Float) }
+ * }
+ * duration = 200L
+ * }
+ *
+ * if you want to run animation with several properties on one Object,
+ * using [ObjectAnim] is more efficient than [ValueAnim], like the following:
+ *
+ * animSet {
+ * objectAnim {
+ * target = tvTitle
+ * translationX = floatArrayOf(0f, 200f)
+ * alpha = floatArrayOf(1.0f, 0.3f)
+ * scaleX = floatArrayOf(1.0f, 1.3f)
+ * }
+ * duration = 100L
+ * }
+ *
+ */
+class AnimSet : Anim() {
+ override var animator: Animator = AnimatorSet()
+ private val animatorSet
+ get() = animator as AnimatorSet
+
+ private val anims by lazy { mutableListOf() }
+
+ /**
+ * whether animation is at start point
+ */
+ private var isAtStartPoint: Boolean = true
+ /**
+ * whether animation value has reversed
+ */
+ private var hasReverse: Boolean = false
+
+ /**
+ * it creates a single [ValueAnim]
+ * [with] and [before] is available to combine several [anim] to one complex animation set by chain-invocation style.
+ */
+ fun anim(animCreation: ValueAnim.() -> Unit): Anim = ValueAnim().apply(animCreation).also { it.addListener() }.also { anims.add(it) }
+
+ /**
+ * build an [ObjectAnim] with a much shorter and readable code by DSL
+ */
+ fun objectAnim(action: ObjectAnim.() -> Unit): Anim =
+ ObjectAnim().apply(action).also { it.setPropertyValueHolder() }.also { it.addListener() }.also { anims.add(it) }
+
+ /**
+ * start the [AnimSet]
+ */
+ fun start() {
+ if (animatorSet.isRunning) return
+ anims.takeIf { hasReverse }?.forEach { anim -> anim.reverse() }.also { hasReverse = false }
+ if (anims.size == 1) animatorSet.play(anims.first().animator)
+ if (isAtStartPoint) {
+ animatorSet.start()
+ isAtStartPoint = false
+ }
+ }
+
+ /**
+ * reverse the animation
+ */
+ override fun reverse() {
+ if (animatorSet.isRunning) return
+ anims.takeIf { !hasReverse }?.forEach { anim -> anim.reverse() }.also { hasReverse = true }
+ if (!isAtStartPoint) {
+ animatorSet.start()
+ isAtStartPoint = true
+ }
+
+ }
+
+ override fun toBeginning() {
+ anims.forEach { it.toBeginning() }
+ }
+
+ /**
+ * get the animation in the [AnimSet] by [index]
+ */
+ fun getAnim(index: Int) = anims.takeIf { index in 0 until anims.size }?.let { it[index] }
+
+ /**
+ * cancel the [AnimatorSet]
+ */
+ fun cancel() {
+ animatorSet.cancel()
+ }
+
+ /**
+ * if you want to play animations one after another, use [before] to link several [Anim],
+ * like the following:
+ *
+ * animSet {
+ * anim {
+ * value = floatArrayOf(1.0f, 1.4f)
+ * action = { value -> tv.scaleX = (value as Float) }
+ * } before anim {
+ * values = floatArrayOf(0f, -200f)
+ * action = { value -> btn.translationY = (value as Float) }
+ * }
+ * duration = 200L
+ * }
+ *
+ */
+ infix fun Anim.before(anim: Anim): Anim {
+ animatorSet.play(animator).before(anim.animator).let { this.builder = it }
+ return anim
+ }
+
+ /**
+ * if you want to play animations at the same time, use [with] to link several [Anim],
+ * like the following:
+ *
+ * animSet {
+ * play {
+ * value = floatArrayOf(1.0f, 1.4f)
+ * action = { value -> tv.scaleX = (value as Float) }
+ * } with anim {
+ * values = floatArrayOf(0f, -200f)
+ * action = { value -> btn.translationY = (value as Float) }
+ * }
+ * duration = 200L
+ * }
+ *
+ * if there are both [with] and [before] in one invocation chain, [with] has higher priority,
+ * for example: `a before b with c` means b and c will play at the same time and a plays before them
+ *
+ */
+ infix fun Anim.with(anim: Anim): Anim {
+ if (builder == null) builder = animatorSet.play(animator).with(anim.animator)
+ else builder?.with(anim.animator)
+ return anim
+ }
+}
+
+/**
+ * build a set of animation with a much shorter and readable code by DSL
+ */
+fun animSet(creation: AnimSet.() -> Unit) = AnimSet().apply { creation() }.also { it.addListener() }
diff --git a/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/anim_dsl/ObjectAnim.kt b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/anim_dsl/ObjectAnim.kt
new file mode 100644
index 0000000000..b33c4b9423
--- /dev/null
+++ b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/anim_dsl/ObjectAnim.kt
@@ -0,0 +1,219 @@
+package com.mogo.module.carchatting.anim_dsl
+
+import android.animation.Animator
+import android.animation.ObjectAnimator
+import android.animation.PropertyValuesHolder
+import android.animation.ValueAnimator
+import android.view.View
+
+/**
+ * An Animator just like [ObjectAnimator], but it could reverse itself without the limitation of API level.
+ * In addition, combing with [AnimSet], it is easy to build much more readable animation code. See at [AnimSet]
+ */
+class ObjectAnim : Anim() {
+ companion object {
+ private const val TRANSLATION_X = "translationX"
+ private const val TRANSLATION_Y = "translationY"
+ private const val SCALE_X = "scaleX"
+ private const val SCALE_Y = "scaleY"
+ private const val ALPHA = "alpha"
+ private const val ROTATION = "rotation"
+ private const val ROTATION_X = "rotationX"
+ private const val ROTATION_Y = "rotationY"
+ }
+
+ /**
+ * the [ObjectAnim] is about to run
+ */
+ override var animator: Animator = ObjectAnimator()
+ private val objectAnimator
+ get() = animator as ObjectAnimator
+
+ /**
+ * predefine properties for [android.view.View]
+ * add a set() for each property inorder to change it dynamically
+ */
+ var translationX: FloatArray? = null
+ set(value) {
+ field = value
+ translationX?.let { PropertyValuesHolder.ofFloat(TRANSLATION_X, *it) }?.let { property ->
+ valuesHolder[TRANSLATION_X] = property
+ objectAnimator.setValues(*valuesHolder.values.toTypedArray())
+ }
+ }
+ var translationY: FloatArray? = null
+ set(value) {
+ field = value
+ translationY?.let { PropertyValuesHolder.ofFloat(TRANSLATION_Y, *it) }?.let { property ->
+ valuesHolder[TRANSLATION_Y] = property
+ objectAnimator.setValues(*valuesHolder.values.toTypedArray())
+ }
+ }
+ var scaleX: FloatArray? = null
+ set(value) {
+ field = value
+ scaleX?.let { PropertyValuesHolder.ofFloat(SCALE_X, *it) }?.let { property ->
+ valuesHolder[SCALE_X] = property
+ objectAnimator.setValues(*valuesHolder.values.toTypedArray())
+ }
+ }
+ var scaleY: FloatArray? = null
+ set(value) {
+ field = value
+ scaleY?.let { PropertyValuesHolder.ofFloat(SCALE_Y, *it) }?.let { property ->
+ valuesHolder[SCALE_Y] = property
+ objectAnimator.setValues(*valuesHolder.values.toTypedArray())
+ }
+ }
+ var alpha: FloatArray? = null
+ set(value) {
+ field = value
+ alpha?.let { PropertyValuesHolder.ofFloat(ALPHA, *it) }?.let { property ->
+ valuesHolder[ALPHA] = property
+ objectAnimator.setValues(*valuesHolder.values.toTypedArray())
+ }
+ }
+ var rotation: FloatArray? = null
+ set(value) {
+ field = value
+ rotation?.let { PropertyValuesHolder.ofFloat(ROTATION, *it) }?.let { property ->
+ valuesHolder[ROTATION] = property
+ objectAnimator.setValues(*valuesHolder.values.toTypedArray())
+ }
+ }
+ var rotationX: FloatArray? = null
+ set(value) {
+ field = value
+ rotationX?.let { PropertyValuesHolder.ofFloat(ROTATION_X, *it) }?.let { property ->
+ valuesHolder[ROTATION_X] = property
+ objectAnimator.setValues(*valuesHolder.values.toTypedArray())
+ }
+ }
+ var rotationY: FloatArray? = null
+ set(value) {
+ field = value
+ rotationY?.let { PropertyValuesHolder.ofFloat(ROTATION_Y, *it) }?.let { property ->
+ valuesHolder[ROTATION_Y] = property
+ objectAnimator.setValues(*valuesHolder.values.toTypedArray())
+ }
+ }
+ /**
+ * the object to be animated which is needed for [ObjectAnimator]
+ */
+ var target: Any? = null
+ set(value) {
+ field = value
+ (animator as ObjectAnimator).target = value
+ }
+ /**
+ * the repeat times of [ObjectAnim]
+ * [ValueAnimator.INFINITE] means repeat forever
+ */
+ var repeatCount
+ get() = 0
+ set(value) {
+ objectAnimator.repeatCount = value
+ }
+
+ /**
+ * the repeat mode of [ObjectAnim]
+ * the available value is [ValueAnimator.RESTART] or [ValueAnimator.REVERSE]
+ */
+ var repeatMode
+ get() = ValueAnimator.RESTART
+ set(value) {
+ objectAnimator.repeatMode = value
+ }
+ /**
+ * a map of [PropertyValuesHolder] to describe what kind of animations to run
+ */
+ private val valuesHolder = mutableMapOf()
+
+ /**
+ * reverse the value of [ObjectAnimator]
+ */
+ override fun reverse() {
+ valuesHolder.forEach { valuesHolder ->
+ when (valuesHolder.key) {
+ TRANSLATION_X -> translationX?.let {
+ it.reverse()
+ this.valuesHolder[TRANSLATION_X]?.setFloatValues(*it)
+ }
+ TRANSLATION_Y -> translationY?.let {
+ it.reverse()
+ this.valuesHolder[TRANSLATION_Y]?.setFloatValues(*it)
+ }
+ SCALE_X -> scaleX?.let {
+ it.reverse()
+ this.valuesHolder[SCALE_X]?.setFloatValues(*it)
+ }
+ SCALE_Y -> scaleY?.let {
+ it.reverse()
+ this.valuesHolder[SCALE_Y]?.setFloatValues(*it)
+ }
+ ALPHA -> alpha?.let {
+ it.reverse()
+ this.valuesHolder[ALPHA]?.setFloatValues(*it)
+ }
+ ROTATION -> rotation?.let {
+ it.reverse()
+ this.valuesHolder[ROTATION]?.setFloatValues(*it)
+ }
+ ROTATION_X -> rotationX?.let {
+ it.reverse()
+ this.valuesHolder[ROTATION_X]?.setFloatValues(*it)
+ }
+ ROTATION_Y -> rotationY?.let {
+ it.reverse()
+ this.valuesHolder[ROTATION_Y]?.setFloatValues(*it)
+ }
+ }
+ }
+ }
+
+ override fun toBeginning() {
+ valuesHolder.forEach { valuesHolder ->
+ when (valuesHolder.key) {
+ TRANSLATION_X -> translationX?.let {
+ (target as? View)?.translationX = it.first()
+ }
+ TRANSLATION_Y -> translationY?.let {
+ (target as? View)?.translationY = it.first()
+ }
+ SCALE_X -> scaleX?.let {
+ (target as? View)?.scaleX = it.first()
+ }
+ SCALE_Y -> scaleY?.let {
+ (target as? View)?.scaleY = it.first()
+ }
+ ALPHA -> alpha?.let {
+ (target as? View)?.alpha = it.first()
+ }
+ ROTATION -> rotation?.let {
+ (target as? View)?.rotation = it.first()
+ }
+ ROTATION_X -> rotationX?.let {
+ (target as? View)?.rotationX = it.first()
+ }
+ ROTATION_Y -> rotationY?.let {
+ (target as? View)?.rotationY = it.first()
+ }
+ }
+ }
+ }
+
+ /**
+ * add available [PropertyValuesHolder] to the list
+ */
+ fun setPropertyValueHolder() {
+ translationX?.let { PropertyValuesHolder.ofFloat(TRANSLATION_X, *it) }?.let { valuesHolder[TRANSLATION_X] = it }
+ translationY?.let { PropertyValuesHolder.ofFloat(TRANSLATION_Y, *it) }?.let { valuesHolder[TRANSLATION_Y] = it }
+ scaleX?.let { PropertyValuesHolder.ofFloat(SCALE_X, *it) }?.let { valuesHolder[SCALE_X] = it }
+ scaleY?.let { PropertyValuesHolder.ofFloat(SCALE_Y, *it) }?.let { valuesHolder[SCALE_Y] = it }
+ alpha?.let { PropertyValuesHolder.ofFloat(ALPHA, *it) }?.let { valuesHolder[ALPHA] = it }
+ rotation?.let { PropertyValuesHolder.ofFloat(ROTATION, *it) }?.let { valuesHolder[ROTATION] = it }
+ rotationX?.let { PropertyValuesHolder.ofFloat(ROTATION_X, *it) }?.let { valuesHolder[ROTATION_X] = it }
+ rotationY?.let { PropertyValuesHolder.ofFloat(ROTATION_Y, *it) }?.let { valuesHolder[ROTATION_Y] = it }
+ objectAnimator.setValues(*valuesHolder.values.toTypedArray())
+ }
+}
diff --git a/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/anim_dsl/ValueAnim.kt b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/anim_dsl/ValueAnim.kt
new file mode 100644
index 0000000000..bdcb7345fb
--- /dev/null
+++ b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/anim_dsl/ValueAnim.kt
@@ -0,0 +1,84 @@
+package com.mogo.module.carchatting.anim_dsl
+
+import android.animation.Animator
+import android.animation.ValueAnimator
+
+/**
+ * An Animator just like [ValueAnimator], but it could reverse itself without the limitation of API level.
+ * In addition, combing with [AnimSet], it is easy to build much more readable animation code. See at [AnimSet]
+ */
+class ValueAnim : Anim() {
+ /**
+ * the [ValueAnimator] is about to run
+ */
+ override var animator: Animator = ValueAnimator()
+ private val valueAnimator
+ get() = animator as ValueAnimator
+
+ /**
+ * the animation value
+ */
+ var values: Any? = null
+ set(value) {
+ field = value
+ value?.let {
+ when (it) {
+ is FloatArray -> valueAnimator.setFloatValues(*it)
+ is IntArray -> valueAnimator.setIntValues(*it)
+ else -> throw IllegalArgumentException("unsupported value type")
+ }
+ }
+ }
+
+ /**
+ * [action] describe what to animate
+ */
+ var action: ((Any) -> Unit)? = null
+ set(value) {
+ field = value
+ valueAnimator.addUpdateListener { valueAnimator ->
+ valueAnimator.animatedValue.let { value?.invoke(it) }
+ }
+ }
+ /**
+ * the repeat times of [ValueAnim]
+ * [ValueAnimator.INFINITE] means repeat forever
+ */
+ var repeatCount
+ get() = 0
+ set(value) {
+ valueAnimator.repeatCount = value
+ }
+
+ /**
+ * the repeat mode of [ValueAnim]
+ * the available value is [ValueAnimator.RESTART] or [ValueAnimator.REVERSE]
+ */
+ var repeatMode
+ get() = ValueAnimator.RESTART
+ set(value) {
+ valueAnimator.repeatMode = value
+ }
+
+ /**
+ * reverse the value of [ValueAnimator]
+ */
+ override fun reverse() {
+ values?.let {
+ when (it) {
+ is FloatArray -> {
+ it.reverse()
+ valueAnimator.setFloatValues(*it)
+ }
+ is IntArray -> {
+ it.reverse()
+ valueAnimator.setIntValues(*it)
+ }
+ else -> throw IllegalArgumentException("unsupported type of value")
+ }
+ }
+ }
+
+ override fun toBeginning() {
+ }
+}
\ No newline at end of file
diff --git a/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/EnthusiasmIndex.kt b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/EnthusiasmIndex.kt
new file mode 100644
index 0000000000..6d02178e4b
--- /dev/null
+++ b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/EnthusiasmIndex.kt
@@ -0,0 +1,9 @@
+package com.mogo.module.carchatting.bean
+
+class EnthusiasmIndex(
+ val id: Int = 0, val sn: String? = null,
+ val score: Int = 0, val shareNum: Int = 0,
+ val likeNum: Int = 0, val notLikeNum: Int = 0,
+ val enthusiasmIndex: Double = 10.0,
+ val createTime: String? = null, val updateTime: String? = null
+)
\ No newline at end of file
diff --git a/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/ErrorInfo.kt b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/ErrorInfo.kt
new file mode 100644
index 0000000000..857b3552de
--- /dev/null
+++ b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/ErrorInfo.kt
@@ -0,0 +1,3 @@
+package com.mogo.module.carchatting.bean
+
+data class ErrorInfo(var errorCode: Int, var errorMsg: String)
\ No newline at end of file
diff --git a/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/ResponseInfo.kt b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/ResponseInfo.kt
new file mode 100644
index 0000000000..bd04247747
--- /dev/null
+++ b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/ResponseInfo.kt
@@ -0,0 +1,3 @@
+package com.mogo.module.carchatting.bean
+
+data class ResponseInfo(var code: Int, var msg: String)
\ No newline at end of file
diff --git a/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/Result.kt b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/Result.kt
new file mode 100644
index 0000000000..183b834903
--- /dev/null
+++ b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/Result.kt
@@ -0,0 +1,3 @@
+package com.mogo.module.carchatting.bean
+
+class Result(val enthusiasmIndex: EnthusiasmIndex)
\ No newline at end of file
diff --git a/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/UserInfo.kt b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/UserInfo.kt
new file mode 100644
index 0000000000..21656397b3
--- /dev/null
+++ b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/UserInfo.kt
@@ -0,0 +1,52 @@
+package com.mogo.module.carchatting.bean
+
+import android.text.TextUtils
+import com.mogo.chat.model.bean.Sns
+
+fun toUserInfo(sns: Sns): UserInfo {
+ return UserInfo(sns.sn,
+ sns.userId.toLong(),
+ sns.nickName ?: "",
+ sns.headImgUrl ?: "",
+ sns.cardIdSex ?: "",
+ sns.cardIdAge ?: "",
+ sns.carInfo ?: "",
+ sns.cityName ?: "",
+ sns.lat.toString(),
+ sns.lon.toString())
+}
+
+class UserInfo(
+ val sn: String,
+ val userId: Long,
+ userName: String? = "小蘑菇",
+ val userHead: String?,
+ val gender: String?,
+ val age: String?,
+ val carTypeName: String?,
+ val location: String?,
+ val lat: String,
+ val lon: String
+) {
+ var userName: String? = "小蘑菇"
+ set(value) {
+ field = if (TextUtils.isEmpty(value)) {
+ "小蘑菇"
+ } else {
+ value
+ }
+ }
+
+ init {
+ if (TextUtils.isEmpty(userName)) {
+ this.userName = "小蘑菇"
+ } else {
+ this.userName = userName
+ }
+ }
+
+ override fun toString(): String {
+ return "UserInfo(sn='$sn', userId=$userId, userHead='$userHead', gender='$gender', age='$age', carTypeName='$carTypeName', location='$location', userName='$userName', lat='$lat', lon='$lon')"
+ }
+
+}
\ No newline at end of file
diff --git a/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/VoiceWake.kt b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/VoiceWake.kt
new file mode 100644
index 0000000000..b30a936749
--- /dev/null
+++ b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/bean/VoiceWake.kt
@@ -0,0 +1,15 @@
+package com.mogo.module.carchatting.bean
+
+import com.google.gson.annotations.SerializedName
+
+fun VoiceWake.check():Boolean{
+ return obj.equals("车聊聊") && operation.equals("打开")
+}
+
+class VoiceWake {
+
+ @SerializedName("object")
+ var obj:String? = null
+
+ var operation:String? = null
+}
\ No newline at end of file
diff --git a/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/biz/CallChatCenter.kt b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/biz/CallChatCenter.kt
new file mode 100644
index 0000000000..82f2381bb5
--- /dev/null
+++ b/modules/mogo-module-carchatting/src/main/java/com/mogo/module/carchatting/biz/CallChatCenter.kt
@@ -0,0 +1,686 @@
+package com.mogo.module.carchatting.biz
+
+import android.content.Context
+import androidx.fragment.app.FragmentActivity
+import com.alibaba.android.arouter.launcher.ARouter
+import com.google.gson.Gson
+import com.mogo.chat.constant.CALL_TYPE_VEHICLE_TEAM
+import com.mogo.chat.model.bean.TeammateInfo
+import com.mogo.chat.service.IMService
+import com.mogo.chat.util.UserInfoHelper.currentCallType
+import com.mogo.cloud.passport.MoGoAiCloudClientConfig
+import com.mogo.eagle.core.data.constants.MogoServicePaths.PATH_SERVICE_APIS
+import com.mogo.module.carchatting.R
+import com.mogo.module.carchatting.bean.UserInfo
+import com.mogo.module.carchatting.card.CallChatConstant.Companion.MODULE_NAME
+import com.mogo.module.carchatting.util.*
+import com.mogo.module.carchatting.view.CallingWindowManager.Companion.callingWindowManager
+import com.mogo.module.carchatting.view.MapViewManager.Companion.mapViewManager
+import com.mogo.module.carchatting.view.TeamInvitationWindowManager.Companion.teamInvitationWindowManager
+import com.mogo.module.carchatting.view.UserWindowManager.Companion.userWindowManager
+import com.mogo.module.carchatting.view.VehicleTeamFragment
+import com.mogo.module.carchatting.voice.IVoiceCommandListener
+import com.mogo.module.carchatting.voice.IVoiceIntentListener
+import com.mogo.module.carchatting.voice.VoiceUtil
+import com.mogo.service.IMogoServiceApis
+import com.mogo.service.statusmanager.IMogoStatusChangedListener
+import com.mogo.service.statusmanager.StatusDescriptor
+import com.mogo.utils.TipToast
+import com.mogo.utils.logger.Logger
+import com.zhidao.carchattingprovider.MogoDriverInfo
+
+class CallChatCenter private constructor() : IBizCallChat.IBizCallBack, IVoiceCommandListener,
+ IVoiceIntentListener {
+
+ companion object {
+ const val TAG: String = "CallChatCenter"
+
+ val callChatCenter by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
+ CallChatCenter()
+ }
+ }
+
+ private var showCallWindowFromDefault = false
+ private var currentUserInfo: UserInfo? = null
+ private var teamMember: List? = null
+
+ private var serviceApi: IMogoServiceApis? = null
+ private var context: Context? = null
+ private val callChatManager: CallChatManager = CallChatManager(this)
+
+ private var callWindowStatusListener: ((Boolean) -> Unit)? = null
+ private var userWindowStatusListener: ((Boolean) -> Unit)? = null
+
+ private var flag: String? = null
+ private var containerId: Int? = null
+ private var activity: FragmentActivity? = null
+
+ fun init(mContext: Context) {
+ Logger.i(TAG, "init")
+ this.context = mContext
+ initServiceApi()
+ teamInvitationWindowManager.init(mContext)
+ callingWindowManager.init(mContext, serviceApi!!, {
+ match(MATCH_TYPE_MANUAL, 2)
+ }, {
+ cancelMatch(false)
+ }, {
+ showVehicleTeamFragment()
+ }, {
+ hangUp()
+ }, {
+// Logger.i(TAG, "click head to move caller position , currentUserInfo : $currentUserInfo")
+// MogoApisHandler.getInstance().apis.mapServiceApi.mapUIController
+// .moveToCenter(MogoLatLng(currentUserInfo?.lat?.toDouble()
+// ?: 0.0, currentUserInfo?.lon?.toDouble() ?: 0.0)) //todo 需要产品理出需求,兼容他车
+ })
+ VoiceUtil.registerAll(context!!, this, this)
+ syncInitStatus()
+ }
+
+ private fun initServiceApi() {
+ Logger.i(TAG, "initServiceApi Launch IMService")
+ IMService.launchService(context!!)
+ Logger.i(TAG, "initServiceApi IMogoServiceApis")
+ val mogoService = ARouter.getInstance().build(PATH_SERVICE_APIS).navigation()
+ if (mogoService is IMogoServiceApis) {
+ this.serviceApi = mogoService
+ }
+ serviceApi?.statusManagerApi?.registerStatusChangedListener(
+ MODULE_NAME,
+ StatusDescriptor.MAIN_PAGE_RESUME,
+ statusChangedListener
+ )
+ serviceApi?.statusManagerApi?.registerStatusChangedListener(
+ MODULE_NAME,
+ StatusDescriptor.VR_MODE,
+ statusChangedListener
+ )
+ }
+
+ private val statusChangedListener = IMogoStatusChangedListener { descriptor, status ->
+ Logger.i(TAG, "IMogoStatusChangedListener status : $status descriptor : $descriptor")
+ when (descriptor) {
+ StatusDescriptor.MAIN_PAGE_RESUME -> {
+ if (status) {
+ VoiceUtil.registerAll(context!!, this, this)
+ syncInitStatus()
+ Logger.i(TAG, "MAIN_PAGE_RESUME callType: $currentCallType , status : ${callChatManager.isCalling()}")
+ if (currentCallType == CALL_TYPE_VEHICLE_TEAM && callChatManager.isCalling()) {
+ callWindowShowCallBack()
+ callingWindowManager.showVehicleTeamView()
+ callingWindowManager.updateVehicleTeamHeadView(teamMember)
+ mapViewManager.updateTeamMarker(context!!, teamMember)
+ } else if (callChatManager.isInit()) {
+ callingWindowManager.showInitView()
+ } else {
+ syncCallViewStatus()
+ }
+ } else {
+ VoiceUtil.unregisterAll(context!!, this)
+ onPause()
+ }
+ }
+ StatusDescriptor.VR_MODE -> {
+ Logger.i(TAG, "VR_MODE callType: $currentCallType , status : ${callChatManager.isCalling()}")
+ updateCallingWindowInVRMode()
+ }
+ else -> {
+ //do nothing for now
+ }
+ }
+ }
+
+ //更新VRMode模式下打电话界面
+ private fun updateCallingWindowInVRMode() {
+ callingWindowManager.resetVRModeView()
+ if (!callingWindowManager.isCallingWindowShow()) {
+ return
+ }
+ if (currentCallType == CALL_TYPE_VEHICLE_TEAM && callChatManager.isCalling()) {
+ callWindowHideCallBack()
+ callingWindowManager.hideVehicleTeamView()
+ callWindowShowCallBack()
+ callingWindowManager.showVehicleTeamView()
+ callingWindowManager.updateVehicleTeamHeadView(teamMember)
+ mapViewManager.updateTeamMarker(context!!, teamMember)
+ } else {
+ callingWindowManager.hideCallingView()
+ callWindowHideCallBack()
+ syncCallViewStatus()
+ }
+ }
+
+ fun invokeCall(userData: String) {
+ Logger.d(TAG, "其他模块来请求打电话给某人: $userData")
+ if (showCallWindowFromDefault) {
+ toast(R.string.module_car_chat_can_not_call)
+ return
+ }
+ showCallWindowFromDefault = true
+ handleCallInvokeData(userData)
+ }
+
+ fun registerCallWindowStatusListener(callWindowStatusListener: ((Boolean) -> Unit)) {
+ this.callWindowStatusListener = callWindowStatusListener
+ }
+
+ fun unRegisterCallWindowStatusListener() {
+ this.callWindowStatusListener = null
+ }
+
+ fun registerUserWindowStatusListener(userWindowStatusListener: ((Boolean) -> Unit)) {
+ this.userWindowStatusListener = userWindowStatusListener
+ }
+
+ fun unRegisterUserWindowStatusListener() {
+ this.userWindowStatusListener = null
+ }
+
+ fun showUserWindow(mogoDriverInfo: MogoDriverInfo) {
+ userWindowManager.showUserView(mogoDriverInfo) {
+ userWindowStatusListener?.invoke(it)
+ }
+ }
+
+ fun hideUserWindow(onError: ((String) -> Unit)? = null, onFinish: (() -> Unit)? = null) {
+ if (userWindowManager.isCallingWindowShow()) {
+ userWindowManager.hideUserView()
+ } else {
+ onError?.invoke("user window already hide, please don't repeat call")
+ }
+ onFinish?.invoke()
+ }
+
+ fun updateUserCallStatus(status: ((Boolean) -> Unit)) {
+ val callStatus = callChatManager.canCall() && !showCallWindowFromDefault
+ status.invoke(callStatus)
+ }
+
+ fun getUserEnthusiasmIndex(sn: String) {
+ callChatManager.getEnthusiasmIndex(sn, { enthusiasmIndex ->
+ userWindowManager.updateUserEnthusiasmIndex(enthusiasmIndex)
+ }, { errorMsg ->
+ Logger.i(TAG, "获取用户热心指数失败 msg : $errorMsg")
+ })
+ }
+
+ fun getUserInfo(sn: String) {
+ callChatManager.getUserInfo(sn, {
+ val userInfoMap = Gson().fromJson