diff --git a/app/functions/abiFilters.gradle b/app/functions/abiFilters.gradle
index 231565ac78..50a3b96168 100644
--- a/app/functions/abiFilters.gradle
+++ b/app/functions/abiFilters.gradle
@@ -64,6 +64,15 @@ project.android.productFlavors {
}
}
}
+ // f系列-分体机
+ phone {
+ externalNativeBuild {
+ ndk {
+ // 设置支持的SO库架构
+ abiFilters "arm64-v8a"
+ }
+ }
+ }
// f系列-分体机-高德
f8Amap {
externalNativeBuild {
@@ -73,4 +82,13 @@ project.android.productFlavors {
}
}
}
+ // 比亚迪
+ bydauto {
+ externalNativeBuild {
+ ndk {
+ // 设置支持的SO库架构
+ abiFilters "armeabi-v7a"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/functions/aicloudservices.gradle b/app/functions/aicloudservices.gradle
index ec9b7405b6..b27edb241e 100644
--- a/app/functions/aicloudservices.gradle
+++ b/app/functions/aicloudservices.gradle
@@ -1,6 +1,8 @@
// 基础服务:仅比亚迪渠道用sdk方式实现,其他都基于apk基础服务
project.dependencies {
if (Boolean.valueOf(RELEASE)) {
+ bydautoImplementation rootProject.ext.dependencies.mogoaicloudservicesdk
+ phoneImplementation rootProject.ext.dependencies.mogoaicloudservicesdk
f8xxImplementation rootProject.ext.dependencies.mogoaicloudserviceapk
f80xImplementation rootProject.ext.dependencies.mogoaicloudserviceapk
@@ -12,6 +14,8 @@ project.dependencies {
fPadLenovoOchTaxiImplementation rootProject.ext.dependencies.mogoaicloudservicesdk
fPadLenovoOchBusImplementation rootProject.ext.dependencies.mogoaicloudservicesdk
} else {
+ bydautoImplementation project(':foudations:mogo-aicloud-services-sdk')
+ phoneImplementation project(':foudations:mogo-aicloud-services-sdk')
f8xxImplementation project(':foudations:mogo-aicloud-services-apk')
f80xImplementation project(':foudations:mogo-aicloud-services-apk')
diff --git a/app/functions/basedmap.gradle b/app/functions/basedmap.gradle
index ce84589c38..4ad704ff3e 100644
--- a/app/functions/basedmap.gradle
+++ b/app/functions/basedmap.gradle
@@ -6,12 +6,15 @@ project.dependencies {
f80xImplementation rootProject.ext.dependencies.mapcustom
fochtaxiImplementation rootProject.ext.dependencies.mapcustom
fochbusImplementation rootProject.ext.dependencies.mapcustom
+ phoneImplementation rootProject.ext.dependencies.mapcustom
fPadLenovoImplementation rootProject.ext.dependencies.mapcustom
fPadLenovoOchTaxiImplementation rootProject.ext.dependencies.mapcustom
fPadLenovoOchBusImplementation rootProject.ext.dependencies.mapcustom
f8AmapImplementation rootProject.ext.dependencies.mapamap
+ bydautoImplementation rootProject.ext.dependencies.mapamap
+
} else {
f8xxImplementation project(':libraries:map-custom')
f80xImplementation project(':libraries:map-custom')
@@ -22,6 +25,10 @@ project.dependencies {
fPadLenovoOchTaxiImplementation project(':libraries:map-custom')
fPadLenovoOchBusImplementation project(':libraries:map-custom')
+ phoneImplementation project(':libraries:map-custom')
+
f8AmapImplementation project(':libraries:map-amap')
+ bydautoImplementation project(':libraries:map-amap')
+
}
}
\ No newline at end of file
diff --git a/app/functions/baseservices.gradle b/app/functions/baseservices.gradle
index 2eaa297774..23d545639c 100644
--- a/app/functions/baseservices.gradle
+++ b/app/functions/baseservices.gradle
@@ -2,6 +2,9 @@
project.dependencies {
if (Boolean.valueOf(RELEASE)) {
+ bydautoImplementation rootProject.ext.dependencies.mogobaseservicesdk
+ phoneImplementation rootProject.ext.dependencies.mogobaseservicesdk
+
f8xxImplementation rootProject.ext.dependencies.mogobaseserviceapk
f80xImplementation rootProject.ext.dependencies.mogobaseserviceapk
f8AmapImplementation rootProject.ext.dependencies.mogobaseserviceapk
@@ -12,6 +15,9 @@ project.dependencies {
fPadLenovoOchTaxiImplementation rootProject.ext.dependencies.mogobaseserviceapk
fPadLenovoOchBusImplementation rootProject.ext.dependencies.mogobaseserviceapk
} else {
+ bydautoImplementation project(':foudations:mogo-base-services-sdk')
+ phoneImplementation project(':foudations:mogo-base-services-sdk')
+
f8xxImplementation project(':foudations:mogo-base-services-apk')
f80xImplementation project(':foudations:mogo-base-services-apk')
f8AmapImplementation project(':foudations:mogo-base-services-apk')
diff --git a/app/functions/bizguide.gradle b/app/functions/bizguide.gradle
index 12d0075d49..6b621b0750 100644
--- a/app/functions/bizguide.gradle
+++ b/app/functions/bizguide.gradle
@@ -2,6 +2,8 @@
project.dependencies {
if (Boolean.valueOf(RELEASE)) {
+ bydautoImplementation rootProject.ext.dependencies.mogomoduleguide
+ phoneImplementation rootProject.ext.dependencies.mogomoduleguide
f8xxImplementation rootProject.ext.dependencies.mogomoduleguide
f80xImplementation rootProject.ext.dependencies.mogomoduleguide
f8AmapImplementation rootProject.ext.dependencies.mogomoduleguide
@@ -13,6 +15,8 @@ project.dependencies {
fPadLenovoOchTaxiImplementation rootProject.ext.dependencies.mogomoduleguide
fPadLenovoOchBusImplementation rootProject.ext.dependencies.mogomoduleguide
} else {
+ bydautoImplementation project(':modules:mogo-module-guide')
+ phoneImplementation project(':modules:mogo-module-guide')
f8xxImplementation project(':modules:mogo-module-guide')
f80xImplementation project(':modules:mogo-module-guide')
diff --git a/app/functions/leftpanel.gradle b/app/functions/leftpanel.gradle
index 15a7509e9b..c8e07a3939 100644
--- a/app/functions/leftpanel.gradle
+++ b/app/functions/leftpanel.gradle
@@ -2,6 +2,9 @@
project.dependencies {
if (Boolean.valueOf(RELEASE)) {
+ bydautoImplementation rootProject.ext.dependencies.moduleleftpanel
+ phoneImplementation rootProject.ext.dependencies.moduleleftpanelnoop
+
f8xxImplementation rootProject.ext.dependencies.moduleleftpanelnoop
f80xImplementation rootProject.ext.dependencies.moduleleftpanelnoop
f8AmapImplementation rootProject.ext.dependencies.moduleleftpanelnoop
@@ -14,6 +17,9 @@ project.dependencies {
fPadLenovoOchBusImplementation rootProject.ext.dependencies.moduleleftpanelnoop
} else {
+ bydautoImplementation project(':modules:mogo-module-left-panel')
+ phoneImplementation project(':modules:mogo-module-left-panel-noop')
+
f8xxImplementation project(':modules:mogo-module-left-panel-noop')
f80xImplementation project(':modules:mogo-module-left-panel-noop')
f8AmapImplementation project(':modules:mogo-module-left-panel-noop')
diff --git a/app/functions/mediaui.gradle b/app/functions/mediaui.gradle
new file mode 100644
index 0000000000..fab92e7f71
--- /dev/null
+++ b/app/functions/mediaui.gradle
@@ -0,0 +1,9 @@
+// 音乐播放模块
+
+project.dependencies {
+ if (Boolean.valueOf(RELEASE)) {
+ launcherImplementation rootProject.ext.dependencies.modulemedia
+ } else {
+ launcherImplementation project(':modules:mogo-module-media')
+ }
+}
\ No newline at end of file
diff --git a/app/functions/och.gradle b/app/functions/och.gradle
index 8738eeab06..255ba426d5 100644
--- a/app/functions/och.gradle
+++ b/app/functions/och.gradle
@@ -1,6 +1,9 @@
// 网约车服务:仅小巴车、出租车渠道用
project.dependencies {
if (Boolean.valueOf(RELEASE)) {
+ bydautoImplementation rootProject.ext.dependencies.mogoochnoop
+ phoneImplementation rootProject.ext.dependencies.mogoochnoop
+
f8xxImplementation rootProject.ext.dependencies.mogoochnoop
f80xImplementation rootProject.ext.dependencies.mogoochnoop
f8AmapImplementation rootProject.ext.dependencies.mogoochnoop
@@ -12,6 +15,9 @@ project.dependencies {
fPadLenovoOchTaxiImplementation rootProject.ext.dependencies.mogoochtaxi
fPadLenovoOchBusImplementation rootProject.ext.dependencies.mogoochbus
} else {
+ bydautoImplementation project(':OCH:mogo-och-noop')
+ phoneImplementation project(':OCH:mogo-och-noop')
+
f8xxImplementation project(':OCH:mogo-och-noop')
f80xImplementation project(':OCH:mogo-och-noop')
f8AmapImplementation project(':OCH:mogo-och-noop')
diff --git a/app/functions/perform.gradle b/app/functions/perform.gradle
index a1ebcec77c..97017f2a5f 100644
--- a/app/functions/perform.gradle
+++ b/app/functions/perform.gradle
@@ -3,10 +3,14 @@
project.dependencies {
if (Boolean.valueOf(RELEASE)) {
launcherImplementation rootProject.ext.dependencies.modulemainlauncher
+ independentImplementation rootProject.ext.dependencies.modulemainindependent
+
// 仅launcher需要引入该模块
launcherImplementation rootProject.ext.dependencies.moduleapps
} else {
launcherImplementation project(':main-extensions:mogo-module-main-launcher')
+ independentImplementation project(':main-extensions:mogo-module-main-independent')
+
// 仅launcher需要引入该模块
launcherImplementation project(':modules:mogo-module-apps')
}
diff --git a/app/functions/skin.gradle b/app/functions/skin.gradle
index 44b5d83421..4c2f5725e7 100644
--- a/app/functions/skin.gradle
+++ b/app/functions/skin.gradle
@@ -1,5 +1,8 @@
project.dependencies {
if (Boolean.valueOf(RELEASE)) {
+ bydautoImplementation rootProject.ext.dependencies.skinsupportnoop
+ phoneImplementation rootProject.ext.dependencies.skinsupportimpl
+
f8xxImplementation rootProject.ext.dependencies.skinsupportimpl
f80xImplementation rootProject.ext.dependencies.skinsupportimpl
f8AmapImplementation rootProject.ext.dependencies.skinsupportimpl
@@ -11,6 +14,9 @@ project.dependencies {
fPadLenovoOchTaxiImplementation rootProject.ext.dependencies.skinsupportimpl
fPadLenovoOchBusImplementation rootProject.ext.dependencies.skinsupportimpl
+
+ phoneImplementation rootProject.ext.dependencies.skinsupportlight
+
f8xxImplementation rootProject.ext.dependencies.skinsupportlight
f80xImplementation rootProject.ext.dependencies.skinsupportlight
f8AmapImplementation rootProject.ext.dependencies.skinsupportlight
@@ -22,6 +28,10 @@ project.dependencies {
fPadLenovoOchTaxiImplementation rootProject.ext.dependencies.skinsupportlight
fPadLenovoOchBusImplementation rootProject.ext.dependencies.skinsupportlight
} else {
+
+ bydautoImplementation project(':skin:mogo-skin-support-noop')
+ phoneImplementation project(':skin:mogo-skin-support-impl')
+
f8xxImplementation project(':skin:mogo-skin-support-impl')
f80xImplementation project(':skin:mogo-skin-support-impl')
f8AmapImplementation project(':skin:mogo-skin-support-impl')
@@ -33,6 +43,9 @@ project.dependencies {
fPadLenovoOchTaxiImplementation project(':skin:mogo-skin-support-impl')
fPadLenovoOchBusImplementation project(':skin:mogo-skin-support-impl')
+
+ phoneImplementation project(':skin:mogo-skin-light')
+
f8xxImplementation project(':skin:mogo-skin-light')
f80xImplementation project(':skin:mogo-skin-light')
f8AmapImplementation project(':skin:mogo-skin-light')
@@ -43,5 +56,6 @@ project.dependencies {
fPadLenovoImplementation project(':skin:mogo-skin-light')
fPadLenovoOchTaxiImplementation project(':skin:mogo-skin-light')
fPadLenovoOchBusImplementation project(':skin:mogo-skin-light')
+
}
}
\ No newline at end of file
diff --git a/app/functions/socketpush.gradle b/app/functions/socketpush.gradle
index e3e7833d1b..b42be11b59 100644
--- a/app/functions/socketpush.gradle
+++ b/app/functions/socketpush.gradle
@@ -4,8 +4,10 @@ project.dependencies {
if (Boolean.valueOf(RELEASE)) {
implementation rootProject.ext.dependencies.modulepushbase
launcherImplementation rootProject.ext.dependencies.modulepush
+ independentImplementation rootProject.ext.dependencies.modulepushnoop
} else {
implementation project(":modules:mogo-module-push-base")
launcherImplementation project(":modules:mogo-module-push")
+ independentImplementation project(":modules:mogo-module-push-noop")
}
}
\ No newline at end of file
diff --git a/app/functions/tts.gradle b/app/functions/tts.gradle
index 8c7b00177e..bc6ed75bd7 100644
--- a/app/functions/tts.gradle
+++ b/app/functions/tts.gradle
@@ -1,5 +1,8 @@
project.dependencies {
if (Boolean.valueOf(RELEASE)) {
+ bydautoImplementation rootProject.ext.dependencies.ttsdi
+ phoneImplementation rootProject.ext.dependencies.ttszhi
+
f8xxImplementation rootProject.ext.dependencies.ttszhi
f80xImplementation rootProject.ext.dependencies.ttszhi
f8AmapImplementation rootProject.ext.dependencies.ttszhi
@@ -11,6 +14,9 @@ project.dependencies {
fPadLenovoOchTaxiImplementation rootProject.ext.dependencies.ttspad
fPadLenovoOchBusImplementation rootProject.ext.dependencies.ttspad
} else {
+ bydautoImplementation project(':tts:tts-di')
+ phoneImplementation project(':tts:tts-zhi')
+
f8xxImplementation project(':tts:tts-zhi')
f80xImplementation project(':tts:tts-zhi')
f8AmapImplementation project(':tts:tts-zhi')
diff --git a/app/productFlavors/bydauto.gradle b/app/productFlavors/bydauto.gradle
new file mode 100644
index 0000000000..d0b1dc91e3
--- /dev/null
+++ b/app/productFlavors/bydauto.gradle
@@ -0,0 +1,37 @@
+project.android.productFlavors {
+ // 比亚迪
+ bydauto {
+ minSdkVersion rootProject.ext.android.minSdkVersion
+ targetSdkVersion rootProject.ext.android.targetSdkVersion
+ // 应用包名
+ applicationId rootProject.ext.android.bydautoIndependentApplicationId
+ dimension "product"
+ buildConfigField 'boolean', 'AI_ASSIST_ACTIVE_STAUTS', 'false'
+ // 车机类型,主要用于区分自研车机还是别人家的车机,其他车机,比亚迪定为1
+ buildConfigField 'int', 'CAR_MACHINE_TYPE', '1'
+ buildConfigField 'boolean', 'ROAD_EVENT_ANIMATED', 'true'
+ manifestPlaceholders = [AMAP_API_VALUE: rootProject.ext.android.bydautoIndependentApiValue, CHANNEL_VALUE: "bydauto"]
+ // 是否使用高德sdk自定义导航
+ buildConfigField 'boolean', 'USE_CUSTOM_NAVI', 'true'
+ // 是否支持换肤
+ buildConfigField 'boolean', 'IS_SKIN_SUPPORTED', 'false'
+ // 是否支持查询导航目的地车友
+ buildConfigField 'boolean', 'IS_SUPPORTED_SEARCH_DESTINATION_ONLINE_CAR_LIST', 'false'
+ // 是否支持桌面卡片刷新
+ buildConfigField 'boolean', 'IS_SUPPORT_LAUNCHER_CARD_REFRESH_STRATEGY', 'false'
+ // 是否基于地图
+ buildConfigField 'boolean', 'IS_MAP_BASED', 'true'
+ // 是否加载引导模块
+ buildConfigField 'boolean', 'IS_NEED_LOAD_GUIDE_MODULE', 'true'
+ // 分享时是否隐藏 adas
+ buildConfigField 'boolean', 'IS_NEED_HIDE_ADAS_WHEN_SHARE', 'false'
+ // 是否需要实时上报坐标
+ buildConfigField 'boolean', 'IS_NEED_UPLOAD_COORDINATES_IN_TIME', 'false'
+ // 是否需要使用工控机的rtk定位
+ buildConfigField 'boolean', 'IS_USE_ADAS_RTK_LOCATION_INFO', 'false'
+ // 是否需要悬浮窗权限申请
+ buildConfigField 'boolean', 'IS_NEED_REQUEST_FLOAT_PERMISSION', 'true'
+ // GPS数据提供源: 0-Android系统,1-工控机,2-OBU
+ buildConfigField 'int', 'GPS_PROVIDER', "1"
+ }
+}
\ No newline at end of file
diff --git a/app/productFlavors/phone.gradle b/app/productFlavors/phone.gradle
new file mode 100644
index 0000000000..7694872acc
--- /dev/null
+++ b/app/productFlavors/phone.gradle
@@ -0,0 +1,35 @@
+project.android.productFlavors {
+ // f系列-分体机
+ phone {
+ // 应用包名
+ applicationId rootProject.ext.android.fLauncherApplicationId
+ dimension "product"
+ buildConfigField 'boolean', 'AI_ASSIST_ACTIVE_STAUTS', 'false'
+ // 车机类型,主要用于区分自研车机还是别人家的车机,自研车机类型为0
+ buildConfigField 'int', 'CAR_MACHINE_TYPE', '1'
+ buildConfigField 'boolean', 'ROAD_EVENT_ANIMATED', 'true'
+ manifestPlaceholders = [AMAP_API_VALUE: rootProject.ext.android.fLauncherAmapApiValue, CHANNEL_VALUE: "phone"]
+ // 是否使用高德sdk自定义导航
+ buildConfigField 'boolean', 'USE_CUSTOM_NAVI', 'false'
+ // 是否支持换肤
+ buildConfigField 'boolean', 'IS_SKIN_SUPPORTED', 'true'
+ // 是否支持查询导航目的地车友
+ buildConfigField 'boolean', 'IS_SUPPORTED_SEARCH_DESTINATION_ONLINE_CAR_LIST', 'true'
+ // 是否支持桌面卡片刷新
+ buildConfigField 'boolean', 'IS_SUPPORT_LAUNCHER_CARD_REFRESH_STRATEGY', 'false'
+ // 是否基于地图
+ buildConfigField 'boolean', 'IS_MAP_BASED', 'true'
+ // 是否加载引导模块
+ buildConfigField 'boolean', 'IS_NEED_LOAD_GUIDE_MODULE', 'true'
+ // 分享时是否隐藏 adas
+ buildConfigField 'boolean', 'IS_NEED_HIDE_ADAS_WHEN_SHARE', 'false'
+ // 是否需要实时上报坐标
+ buildConfigField 'boolean', 'IS_NEED_UPLOAD_COORDINATES_IN_TIME', 'true'
+ // 是否需要使用工控机的rtk定位
+ buildConfigField 'boolean', 'IS_USE_ADAS_RTK_LOCATION_INFO', 'true'
+ // 是否需要悬浮窗权限申请
+ buildConfigField 'boolean', 'IS_NEED_REQUEST_FLOAT_PERMISSION', 'true'
+ // GPS数据提供源: 0-Android系统,1-工控机,2-OBU
+ buildConfigField 'int', 'GPS_PROVIDER', "1"
+ }
+}
\ No newline at end of file
diff --git a/app/regroup.gradle b/app/regroup.gradle
index 8a57cf2e62..01bff408c2 100644
--- a/app/regroup.gradle
+++ b/app/regroup.gradle
@@ -2,12 +2,21 @@
afterEvaluate {
+ def independent = ["bydauto", "phone"]
def launcher = ["f80x", "f8xx", "f8amap", "fochtaxi", "fochbus", "fPadLenovo", "fPadLenovoOchTaxi", "fPadLenovoOchBus"]
it.getTasks().iterator().forEachRemaining {
def task = it
def taskName = task.name
if (taskName.startsWith("assemble")
+ && taskName.contains("Independent")
+ && (taskName.endsWith("Debug") || taskName.endsWith("Release"))) {
+ independent.forEach {
+ if (taskName.toLowerCase().contains(it)) {
+ task.group = "assembleIndependent"
+ }
+ }
+ } else if (taskName.startsWith("assemble")
&& taskName.contains("Launcher")
&& (taskName.endsWith("Debug") || taskName.endsWith("Release"))) {
launcher.forEach {
@@ -15,6 +24,14 @@ afterEvaluate {
task.group = "assembleLauncher"
}
}
+ } else if (taskName.startsWith("install")
+ && taskName.contains("Independent")
+ && (taskName.endsWith("Debug") || taskName.endsWith("Release"))) {
+ independent.forEach {
+ if (taskName.toLowerCase().contains(it)) {
+ task.group = "installIndependent"
+ }
+ }
} else if (taskName.startsWith("install")
&& taskName.contains("Launcher")
&& (taskName.endsWith("Debug") || taskName.endsWith("Release"))) {
diff --git a/app/src/e8xx/AndroidManifest.xml b/app/src/e8xx/AndroidManifest.xml
new file mode 100644
index 0000000000..01afff1292
--- /dev/null
+++ b/app/src/e8xx/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/em4/AndroidManifest.xml b/app/src/em4/AndroidManifest.xml
new file mode 100644
index 0000000000..d755054676
--- /dev/null
+++ b/app/src/em4/AndroidManifest.xml
@@ -0,0 +1,6 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/launcher/AndroidManifest.xml b/app/src/launcher/AndroidManifest.xml
new file mode 100644
index 0000000000..cdf501d602
--- /dev/null
+++ b/app/src/launcher/AndroidManifest.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/config.gradle b/config.gradle
index c01d2707b5..d1934ad6e9 100644
--- a/config.gradle
+++ b/config.gradle
@@ -102,6 +102,7 @@ ext {
modulecommon : "com.mogo.module:module-common:${MOGO_MODULE_COMMON_VERSION}",
modulemain : "com.mogo.module:module-main:${MOGO_MODULE_MAIN_VERSION}",
modulemainlauncher : "com.mogo.module:module-main-launcher:${MOGO_MODULE_MAIN_LAUNCHER_VERSION}",
+ modulemainindependent : "com.mogo.module:module-main-independent:${MOGO_MODULE_MAIN_INDEPENDENT_VERSION}",
modulemap : "com.mogo.module:module-map:${MOGO_MODULE_MAP_VERSION}",
moduleservice : "com.mogo.module:module-service:${MOGO_MODULE_SERVICE_VERSION}",
mogoservice : "com.mogo.service:mogo-service:${MOGO_SERVICE_VERSION}",
@@ -117,6 +118,7 @@ ext {
moduleV2x : "com.mogo.module:module-v2x:${MOGO_MODULE_V2X_VERSION}",
moduleSmallMap : "com.mogo.module:module-small-map:${MOGO_MODULES_SMALL_MAP}",
moduleADAS : "com.mogo.module:mogo-module-adas:${MOGO_MODULES_ADAS}",
+ modulemedia : "com.mogo.module:module-media:${MOGO_MODULE_MEDIA_VERSION}",
modulesearch : "com.mogo.module:module-search:${MOGO_MODULE_SEARCH_VERSION}",
// push
modulepush : "com.mogo.module:module-push:${MOGO_MODULE_PUSH_VERSION}",
diff --git a/foudations/httpdns-tencent/.gitignore b/foudations/httpdns-tencent/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/foudations/httpdns-tencent/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/foudations/httpdns-tencent/build.gradle b/foudations/httpdns-tencent/build.gradle
new file mode 100644
index 0000000000..48df740363
--- /dev/null
+++ b/foudations/httpdns-tencent/build.gradle
@@ -0,0 +1,46 @@
+apply plugin: 'com.android.library'
+
+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
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: "libs", include: ["*.jar"])
+ implementation "com.mogo.tencent.httpdns:android-httpdns:+@aar"
+ implementation rootProject.ext.dependencies.arouter
+ annotationProcessor rootProject.ext.dependencies.aroutercompiler
+
+ if (Boolean.valueOf(RELEASE)) {
+ implementation rootProject.ext.dependencies.httpdnsbase
+ implementation rootProject.ext.dependencies.mogocommons
+ } else {
+ implementation project(':foudations:httpdns-base')
+ implementation project(':foudations:mogo-commons')
+ }
+}
+
+apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
\ No newline at end of file
diff --git a/foudations/httpdns-tencent/consumer-rules.pro b/foudations/httpdns-tencent/consumer-rules.pro
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/foudations/httpdns-tencent/gradle.properties b/foudations/httpdns-tencent/gradle.properties
new file mode 100644
index 0000000000..32c09bbf9b
--- /dev/null
+++ b/foudations/httpdns-tencent/gradle.properties
@@ -0,0 +1,3 @@
+GROUP=com.mogo.httpdns
+POM_ARTIFACT_ID=httpdns-tencent
+VERSION_CODE=1
\ No newline at end of file
diff --git a/foudations/httpdns-tencent/proguard-rules.pro b/foudations/httpdns-tencent/proguard-rules.pro
new file mode 100644
index 0000000000..481bb43481
--- /dev/null
+++ b/foudations/httpdns-tencent/proguard-rules.pro
@@ -0,0 +1,21 @@
+# 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
\ No newline at end of file
diff --git a/foudations/httpdns-tencent/src/main/AndroidManifest.xml b/foudations/httpdns-tencent/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..a30884aeb4
--- /dev/null
+++ b/foudations/httpdns-tencent/src/main/AndroidManifest.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/foudations/httpdns-tencent/src/main/java/com/mogo/httpdns/tencent/HttpDnsIpsCache.java b/foudations/httpdns-tencent/src/main/java/com/mogo/httpdns/tencent/HttpDnsIpsCache.java
new file mode 100644
index 0000000000..7e9e310346
--- /dev/null
+++ b/foudations/httpdns-tencent/src/main/java/com/mogo/httpdns/tencent/HttpDnsIpsCache.java
@@ -0,0 +1,170 @@
+package com.mogo.httpdns.tencent;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.text.TextUtils;
+
+import com.mogo.utils.ThreadPoolService;
+import com.mogo.utils.logger.Logger;
+import com.tencent.msdk.dns.MSDKDnsResolver;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author congtaowang
+ * @since 2020/11/18
+ *
+ * 描述
+ */
+class HttpDnsIpsCache {
+
+ private static final String TAG = "HttpDnsIpsCache";
+
+ // 缓存过期时间
+ public static final long INTERVAL_CACHE = 60 * 60 * 1000;
+
+ // 刷新缓存时间
+ public static final long TTL = ( long ) ( INTERVAL_CACHE * 0.75 );
+
+ // 使用dns新域名
+ public static final int MSG_DNS_FLUSH = 6000000;
+ // ttl
+ public static final int MSG_DNS_TTL = 6000001;
+
+ private final static Map< String, String > sCaches = new ConcurrentHashMap<>();
+ private final static Map< String, String > sTTLCaches = new ConcurrentHashMap<>();
+
+ private final static Map< String, IHttpDnsTtlCallback > sTtlCallbacks = new ConcurrentHashMap<>();
+
+ private final static Handler sHandler = new Handler( Looper.getMainLooper() ) {
+ @Override
+ public void handleMessage( Message msg ) {
+ super.handleMessage( msg );
+ if ( msg.what == MSG_DNS_FLUSH ) {
+ flushNewDnsCache();
+ postTtlCallback();
+ loopDnsParse();
+ } else if ( msg.what == MSG_DNS_TTL ) {
+ parseHosts();
+ }
+ }
+ };
+
+ /**
+ * 将 ttl 消息回调
+ */
+ static void postTtlCallback() {
+ if ( sTtlCallbacks.isEmpty() ) {
+ return;
+ }
+ Collection callbacks = sTtlCallbacks.values();
+ if (callbacks.isEmpty()) {
+ return;
+ }
+ for ( IHttpDnsTtlCallback callback : callbacks ) {
+ if ( callback == null ) {
+ continue;
+ }
+ try {
+ callback.onTtl();
+ } catch ( Exception e ) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * 缓存域名
+ *
+ * @param host
+ * @param ip
+ */
+ static void cache( String host, String ip ) {
+ sCaches.put( host, ip );
+ }
+
+ /**
+ * 获取缓存中的域名
+ *
+ * @param host
+ * @return
+ */
+ static String getHttpDnsIps( String host ) {
+ return sCaches.get( host );
+ }
+
+ /**
+ * 使用新的 dns 缓存
+ */
+ static void flushNewDnsCache() {
+ sCaches.clear();
+ sCaches.putAll( sTTLCaches );
+ }
+
+ /**
+ * ttl 到达后,刷新一遍 dns 域名
+ */
+ static void loopDnsParse() {
+ Logger.d( TAG, "使用新的dns列表" );
+ sHandler.sendEmptyMessageDelayed( MSG_DNS_FLUSH, INTERVAL_CACHE );
+ sHandler.sendEmptyMessageDelayed( MSG_DNS_TTL, TTL );
+ }
+
+ /**
+ * ttl 到期,刷新域名
+ */
+ static void parseHosts() {
+ Logger.d( TAG, "ttl 过期,刷新dns列表" );
+ ThreadPoolService.execute( new Runnable() {
+ @Override
+ public void run() {
+ Set< String > hostSet = sCaches.keySet();
+ if ( hostSet.isEmpty() ) {
+ return;
+ }
+ for ( String host : hostSet ) {
+ String newIp = parseHostFromHttpDns( host );
+ if ( TextUtils.isEmpty( newIp ) ) {
+ continue;
+ }
+ sTTLCaches.put( host, newIp );
+ }
+ }
+ } );
+ }
+
+ /**
+ * 使用腾讯服务解析域名
+ *
+ * @param host
+ * @return
+ */
+ static String parseHostFromHttpDns( String host ) {
+ String ips = MSDKDnsResolver.getInstance().getAddrByName( host );
+ String[] ipArr = ips.split( ";" );
+ if ( 0 == ipArr.length ) {
+ return null;
+ }
+ for ( String ip : ipArr ) {
+ if ( TextUtils.isEmpty( ip ) || TextUtils.equals( "0", ip ) ) {
+ continue;
+ }
+ Logger.d( TAG, "parse: %s - %s", host, ip );
+ return ip;
+ }
+ return null;
+ }
+
+
+ static void addHttpDnsTtlCallback( String host, IHttpDnsTtlCallback callback ) {
+ sTtlCallbacks.put( host, callback );
+ }
+
+ static void removeHttpDnsTtlCallback( String host ) {
+ sTtlCallbacks.remove( host );
+ }
+}
diff --git a/foudations/httpdns-tencent/src/main/java/com/mogo/httpdns/tencent/IHttpDnsTtlCallback.java b/foudations/httpdns-tencent/src/main/java/com/mogo/httpdns/tencent/IHttpDnsTtlCallback.java
new file mode 100644
index 0000000000..3e1ca6f6e8
--- /dev/null
+++ b/foudations/httpdns-tencent/src/main/java/com/mogo/httpdns/tencent/IHttpDnsTtlCallback.java
@@ -0,0 +1,6 @@
+package com.mogo.httpdns.tencent;
+
+public class IHttpDnsTtlCallback {
+ public void onTtl() {
+ }
+}
diff --git a/foudations/httpdns-tencent/src/main/java/com/mogo/httpdns/tencent/TencentHttpDns.java b/foudations/httpdns-tencent/src/main/java/com/mogo/httpdns/tencent/TencentHttpDns.java
new file mode 100644
index 0000000000..f516f0c448
--- /dev/null
+++ b/foudations/httpdns-tencent/src/main/java/com/mogo/httpdns/tencent/TencentHttpDns.java
@@ -0,0 +1,127 @@
+package com.mogo.httpdns.tencent;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import androidx.annotation.Keep;
+
+import com.alibaba.android.arouter.facade.annotation.Route;
+import com.mogo.cloud.httpdns.listener.OnAddressChangedListener;
+import com.mogo.commons.debug.DebugConfig;
+import com.mogo.httpdns.HttpDnsConst;
+import com.mogo.httpdns.IHttpDnsCallback;
+import com.mogo.httpdns.IMogoHttpDns;
+import com.mogo.utils.logger.Logger;
+import com.mogo.utils.network.HttpDns;
+import com.tencent.msdk.dns.MSDKDnsResolver;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static com.mogo.httpdns.HttpDnsConst.HTTP_DNS_ADDRESS_TYPE_IM;
+import static com.mogo.httpdns.HttpDnsConst.HTTP_DNS_ADDRESS_TYPE_WS;
+
+
+@Route( path = HttpDnsConst.PATH )
+public class TencentHttpDns implements IMogoHttpDns, HttpDns {
+
+ private static volatile boolean sInited = false;
+
+ private static final String TAG = "TencentHttpDns";
+
+ @Override
+ public List< InetAddress > lookup( String hostname ) throws UnknownHostException {
+ Logger.d( TAG, "需要dns解析" );
+ String cacheIp = getCacheOrParseIpIfNecessary( hostname );
+ if ( TextUtils.isEmpty( cacheIp ) ) {
+ return Collections.emptyList();
+ }
+
+ return Arrays.asList( InetAddress.getAllByName( cacheIp ) );
+ }
+
+ @Override
+ public String getCachedHttpDnsIps( String host,int type ) {
+ String ip = HttpDnsIpsCache.getHttpDnsIps(host);
+ if (ip == null) {
+ return null;
+ } else {
+ return tailPort(ip, type);
+ }
+ }
+
+ private String getCacheOrParseIpIfNecessary( String host ) {
+ String cacheIp = HttpDnsIpsCache.getHttpDnsIps( host );
+ if ( TextUtils.isEmpty( cacheIp ) ) {
+ cacheIp = HttpDnsIpsCache.parseHostFromHttpDns( host );
+ if ( !TextUtils.isEmpty( cacheIp ) ) {
+ HttpDnsIpsCache.cache( host, cacheIp );
+ }
+ }
+ return cacheIp;
+ }
+
+ @Override
+ public void getHttpDnsIp( String host,int type, boolean useCache, IHttpDnsCallback callback ) {
+ String cacheIp;
+ if ( useCache ) {
+ cacheIp = getCacheOrParseIpIfNecessary( host );
+ } else {
+ cacheIp = HttpDnsIpsCache.parseHostFromHttpDns( host );
+ if ( !TextUtils.isEmpty( cacheIp ) ) {
+ HttpDnsIpsCache.cache( host, cacheIp );
+ }
+ }
+ if ( !TextUtils.isEmpty( cacheIp ) ) {
+ if ( callback != null ) {
+ callback.onParsed( tailPort(cacheIp,type) );
+ return;
+ }
+ }
+ if ( callback != null ) {
+ callback.onParsed( null );
+ }
+ }
+
+ @Override
+ public String syncGetHttpDns(String host, int type, boolean useCache) {
+ return null;
+ }
+
+ @Override
+ public void addressChangedListener(OnAddressChangedListener listener) {
+
+ }
+
+ @Keep
+ @Override
+ public void init( Context context ) {
+ if ( sInited ) {
+ return;
+ }
+ MSDKDnsResolver.getInstance().init( context.getApplicationContext(),
+ "0I00093F244N42WU",
+ "2742",
+ "7Pplkaua",
+ DebugConfig.isDebug(),
+ 1_000
+ );
+ MSDKDnsResolver.getInstance().WGSetDnsOpenId( "1AE58PG9444E3G9L" );
+ HttpDnsIpsCache.loopDnsParse();
+ sInited = true;
+ }
+
+ private String tailPort(String ip, int type) {
+ switch (type) {
+ case HTTP_DNS_ADDRESS_TYPE_WS:
+ return ip + ":4004";
+ case HTTP_DNS_ADDRESS_TYPE_IM:
+ return ip + ":4002";
+ default:
+ return ip;
+ }
+ }
+}
diff --git a/foudations/mogo-base-services-apk/.gitignore b/foudations/mogo-base-services-apk/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/foudations/mogo-base-services-apk/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/foudations/mogo-base-services-apk/README.md b/foudations/mogo-base-services-apk/README.md
new file mode 100644
index 0000000000..b6ee9eafae
--- /dev/null
+++ b/foudations/mogo-base-services-apk/README.md
@@ -0,0 +1,7 @@
+## 基实现功能
+
+基础服务apk实现对应功能:位置上报、长连接、passport
+
+位置上报:com.zhidao.locationinfo
+长链:com.zhidao.socketservice
+passport:
\ No newline at end of file
diff --git a/foudations/mogo-base-services-apk/build.gradle b/foudations/mogo-base-services-apk/build.gradle
new file mode 100644
index 0000000000..943521aac6
--- /dev/null
+++ b/foudations/mogo-base-services-apk/build.gradle
@@ -0,0 +1,51 @@
+apply plugin: 'com.android.library'
+
+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"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: "libs", include: ["*.jar"])
+ implementation rootProject.ext.dependencies.arouter
+
+ api rootProject.ext.dependencies.socketsdk
+ api rootProject.ext.dependencies.socketsdkconnsvrprotoco
+ api rootProject.ext.dependencies.socketsdkprotobufjava
+ implementation rootProject.ext.dependencies.accountsdk
+
+ if (Boolean.valueOf(RELEASE)) {
+ implementation rootProject.ext.dependencies.mogoutils
+ implementation rootProject.ext.dependencies.mogocommons
+ implementation rootProject.ext.dependencies.mogoserviceapi
+ } else {
+ implementation project(":foudations:mogo-utils")
+ implementation project(":foudations:mogo-commons")
+ implementation project(":services:mogo-service-api")
+ }
+
+}
+
+apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
\ No newline at end of file
diff --git a/foudations/mogo-base-services-apk/consumer-rules.pro b/foudations/mogo-base-services-apk/consumer-rules.pro
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/foudations/mogo-base-services-apk/gradle.properties b/foudations/mogo-base-services-apk/gradle.properties
new file mode 100644
index 0000000000..aae1d6638c
--- /dev/null
+++ b/foudations/mogo-base-services-apk/gradle.properties
@@ -0,0 +1,3 @@
+GROUP=com.mogo.base
+POM_ARTIFACT_ID=services-apk
+VERSION_CODE=1
diff --git a/foudations/mogo-base-services-apk/proguard-rules.pro b/foudations/mogo-base-services-apk/proguard-rules.pro
new file mode 100644
index 0000000000..481bb43481
--- /dev/null
+++ b/foudations/mogo-base-services-apk/proguard-rules.pro
@@ -0,0 +1,21 @@
+# 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
\ No newline at end of file
diff --git a/foudations/mogo-base-services-apk/src/main/AndroidManifest.xml b/foudations/mogo-base-services-apk/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..a82c409551
--- /dev/null
+++ b/foudations/mogo-base-services-apk/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+ /
+
\ No newline at end of file
diff --git a/foudations/mogo-base-services-apk/src/main/java/com/mogo/base/services/locationinfo/MogoLocationInfoServices.java b/foudations/mogo-base-services-apk/src/main/java/com/mogo/base/services/locationinfo/MogoLocationInfoServices.java
new file mode 100644
index 0000000000..5a6c31d624
--- /dev/null
+++ b/foudations/mogo-base-services-apk/src/main/java/com/mogo/base/services/locationinfo/MogoLocationInfoServices.java
@@ -0,0 +1,63 @@
+package com.mogo.base.services.locationinfo;
+
+import android.content.Context;
+
+import androidx.annotation.Keep;
+
+import com.mogo.map.location.MogoLocation;
+import com.mogo.service.locationinfo.IMogoLocationInfoService;
+import com.mogo.utils.logger.Logger;
+
+public
+/**
+ * @author congtaowang
+ * @since 2020/7/16
+ *
+ * 位置服务
+ */
+@Keep
+class MogoLocationInfoServices implements IMogoLocationInfoService {
+
+ private static final String TAG = "MogoLocationInfoServices-apk";
+
+ private static volatile MogoLocationInfoServices sInstance;
+
+ private MogoLocationInfoServices() {
+ }
+
+ @Keep
+ public static MogoLocationInfoServices getInstance() {
+ if ( sInstance == null ) {
+ synchronized ( MogoLocationInfoServices.class ) {
+ if ( sInstance == null ) {
+ sInstance = new MogoLocationInfoServices();
+ }
+ }
+ }
+ return sInstance;
+ }
+
+ public synchronized void release() {
+ sInstance = null;
+ }
+
+ @Override
+ public void provideLocation( MogoLocation location ) {
+ Logger.d( TAG, "apk - provideLocation" );
+ }
+
+ @Override
+ public void start() {
+ Logger.d( TAG, "apk - start" );
+ }
+
+ @Override
+ public void stop() {
+ Logger.d( TAG, "apk - stop" );
+ }
+
+ @Override
+ public void init( Context context ) {
+ Logger.d( TAG, "apk - init" );
+ }
+}
diff --git a/foudations/mogo-base-services-apk/src/main/java/com/mogo/base/services/passport/PassportManager.java b/foudations/mogo-base-services-apk/src/main/java/com/mogo/base/services/passport/PassportManager.java
new file mode 100644
index 0000000000..624c97c390
--- /dev/null
+++ b/foudations/mogo-base-services-apk/src/main/java/com/mogo/base/services/passport/PassportManager.java
@@ -0,0 +1,100 @@
+package com.mogo.base.services.passport;
+
+import android.content.Context;
+
+import androidx.annotation.Keep;
+
+import com.mogo.commons.debug.DebugConfig;
+import com.mogo.commons.storage.SpStorage;
+import com.mogo.service.passport.IMogoPassportManager;
+import com.mogo.service.passport.IMogoTicketCallback;
+import com.mogo.utils.logger.Logger;
+import com.zhidao.account.sdk.AccountClientManager;
+import com.zhidao.account.sdk.BusinessType;
+import com.zhidao.account.sdk.Environment;
+import com.zhidao.account.sdk.callback.TicketInfoCallback;
+import com.zhidao.account.sdk.network.NetEnvironManager;
+
+public
+/**
+ * @author congtaowang
+ * @since 2020/7/16
+ *
+ * 描述
+ */
+@Keep
+class PassportManager implements IMogoPassportManager {
+
+ private static final String TAG = "PassportManager-apk";
+
+ private static volatile PassportManager sInstance;
+
+ private PassportManager() {
+ }
+
+ @Keep
+ public static PassportManager getInstance() {
+ if ( sInstance == null ) {
+ synchronized ( PassportManager.class ) {
+ if ( sInstance == null ) {
+ sInstance = new PassportManager();
+ }
+ }
+ }
+ return sInstance;
+ }
+
+ public synchronized void release() {
+ sInstance = null;
+ }
+
+ @Override
+ public void requestTicket( final IMogoTicketCallback callback ) {
+ getTicket( new TicketInfoCallback() {
+ @Override
+ public void onSuccess( String ticket ) {
+ Logger.d( TAG, "success" );
+ SpStorage.setTicket( ticket );
+ if ( callback != null ) {
+ callback.onTicketGot( ticket );
+ }
+ }
+
+ @Override
+ public void onFailure( int code, String msg ) {
+ Logger.d( TAG, "fail code= %s, msg=%s", code, msg );
+ if ( callback != null ) {
+ callback.onError( code, msg );
+ }
+ }
+ } );
+ }
+
+ private static void getTicket( TicketInfoCallback callback ) {
+ AccountClientManager.getTicket( callback );
+ }
+
+ @Override
+ public void init( Context context ) {
+ AccountClientManager.init( context.getApplicationContext(), getNetEnvironment(), BusinessType.toc_login, "os2.0-launcher" );
+ }
+
+ private Environment getNetEnvironment() {
+ int mode = DebugConfig.getNetMode();
+ if ( mode == DebugConfig.NET_MODE_DEMO ) {
+ // 演示环境用 qa 的
+ mode = DebugConfig.NET_MODE_QA;
+ }
+ switch ( mode ) {
+ case DebugConfig.NET_MODE_DEV:
+ return Environment.dev;
+ case DebugConfig.NET_MODE_DEMO:
+ case DebugConfig.NET_MODE_QA:
+ return Environment.qa;
+ case DebugConfig.NET_MODE_RELEASE:
+ default:
+ return Environment.release;
+
+ }
+ }
+}
diff --git a/foudations/mogo-base-services-apk/src/main/java/com/mogo/base/services/socket/SocketManager.java b/foudations/mogo-base-services-apk/src/main/java/com/mogo/base/services/socket/SocketManager.java
new file mode 100644
index 0000000000..a89c7c6b7c
--- /dev/null
+++ b/foudations/mogo-base-services-apk/src/main/java/com/mogo/base/services/socket/SocketManager.java
@@ -0,0 +1,227 @@
+package com.mogo.base.services.socket;
+
+import android.content.Context;
+
+import androidx.annotation.Keep;
+
+import com.google.protobuf.ByteString;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.mogo.service.connection.IMogoMsgAckListener;
+import com.mogo.service.connection.IMogoOnMessageListener;
+import com.mogo.service.connection.IMogoSocketManager;
+import com.mogo.service.connection.MsgBody;
+import com.mogo.utils.logger.Logger;
+import com.mogo.utils.network.utils.GsonUtil;
+import com.zhidao.ptech.connsvr.commom.protocol.MogoCommon;
+import com.zhidao.ptech.connsvr.protocol.MogoConnsvr;
+import com.zhidao.socketsdk.manager.OnSocketAckCallback;
+import com.zhidao.socketsdk.manager.OnSocketReceiveCallback;
+import com.zhidao.socketsdk.manager.SocketConnManager;
+import com.zhidao.socketsdk.manager.SocketConnManagerImpl;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author congtaowang
+ * @since 2019-12-31
+ *
+ * 长链实现:基于 netty
+ */
+@Keep
+public class SocketManager implements IMogoSocketManager, OnSocketReceiveCallback, OnSocketAckCallback {
+
+ private static final String TAG = "SocketManager-apk";
+
+ public static final int MSG_PRODUCT_LINE = MogoCommon.Product.mogoBussiness_VALUE;
+ private static final int MSG_HEADER_TYPE = MogoConnsvr.MsgType.mogoMsgTypeDispatchSvrNoRspReq_VALUE;
+
+ private static volatile SocketManager sInstance;
+
+ private SocketManager( Context context ) {
+ mSocketConnManager = SocketConnManagerImpl.getInstance( context );
+ mSocketConnManager.addSocketMessageCallback( this );
+ mSocketConnManager.addSocketAckCallback( this );
+ }
+
+ @Keep
+ public static SocketManager getInstance( Context context ) {
+ if ( sInstance == null ) {
+ synchronized ( SocketManager.class ) {
+ if ( sInstance == null ) {
+ sInstance = new SocketManager( context );
+ }
+ }
+ }
+ return sInstance;
+ }
+
+ /**
+ * 管理消息分发
+ *
+ * key - msgType
+ */
+ private Map< Integer, List< IMogoOnMessageListener > > mListeners = new ConcurrentHashMap<>();
+
+ /**
+ * 管理消息回执
+ *
+ * key - msgId
+ */
+ private Map< Long, IMogoMsgAckListener > mAckListeners = new ConcurrentHashMap<>();
+
+
+ private SocketConnManager mSocketConnManager;
+ public static final int MAX_CAP = 64; //保证充足的容量应对非常延时的推送
+ private ArrayList< Long > mReceivedMsgId = new ArrayList<>( MAX_CAP );
+ private int mCurrentIndex = 0;
+
+ @Override
+ public void init( Context context, String appId ) {
+ if ( mSocketConnManager != null ) {
+ mSocketConnManager.init( appId );
+ }
+ }
+
+ @Override
+ public void onMessageReceived( byte[] content ) {
+ onMessageReceived( content, 0);
+ }
+
+ public void onMessageReceived( byte[] content, long msgId ) {
+ try {
+ MogoConnsvr.Payload payload = MogoConnsvr.Payload.parseFrom( content );
+ int msgType = payload.getMsgType();
+ Logger.d( TAG, "received msg type = " + msgType );
+ List< IMogoOnMessageListener > listeners = mListeners.get( msgType );
+ if ( listeners != null && !listeners.isEmpty() ) {
+ Iterator< IMogoOnMessageListener > iterator = listeners.iterator();
+ if ( msgId != 0 ) { //兼容老版本
+ if ( mReceivedMsgId.contains( msgId ) ) { // 避免消息重发
+ return;
+ }
+ cacheLastReceivedMsgId( msgId );
+ }
+ Object object = null;
+ while ( iterator.hasNext() ) {
+ IMogoOnMessageListener listener = iterator.next();
+ if ( object == null ) {
+ object = GsonUtil.objectFromJson( payload.getPayload().toStringUtf8(), listener.target() );
+ }
+ if ( listener != null ) {
+ Logger.d( TAG, "received msgId = %s, content = %s", msgId, payload.getPayload().toStringUtf8() );
+ listener.onMsgReceived( object );
+ }
+ }
+ }
+ } catch ( InvalidProtocolBufferException e ) {
+ Logger.e( TAG, e, "parse msg error." );
+ }
+ }
+
+ private void cacheLastReceivedMsgId( long msgId ) {
+ if ( msgId == 0 ) {
+ return;
+ }
+ synchronized ( this ){
+ mReceivedMsgId.add( mCurrentIndex % MAX_CAP, msgId );
+ mCurrentIndex++;
+ }
+ }
+
+ @Override
+ public void onAck( byte[] headerBytes, byte[] payloadBytes ) {
+ try {
+ MogoConnsvr.Header header = MogoConnsvr.Header.parseFrom( headerBytes );
+ int msgType = header.getMsgType();
+ String appId = header.getAppId();
+ int productLine = header.getProductLine();
+ long msgId = header.getMsgId();
+ IMogoMsgAckListener listener = mAckListeners.remove( msgId );
+ if ( listener != null ) {
+ listener.onAck( msgId );
+ }
+ } catch ( InvalidProtocolBufferException e ) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void registerOnMessageListener( int msgType, IMogoOnMessageListener listener ) {
+ if ( mListeners.containsKey( msgType ) ) {
+ Logger.w( TAG, "msgType %d is exist.", msgType );
+ }
+ if ( !mListeners.containsKey( msgType ) ) {
+ mListeners.put( msgType, new ArrayList< IMogoOnMessageListener >() );
+ }
+ mListeners.get( msgType ).add( listener );
+ }
+
+ @Override
+ public void unregisterOnMessageListener( int msgType ) {
+ mListeners.remove( msgType );
+ }
+
+ @Override
+ public void unregisterOnMessageListener( int msgType, IMogoOnMessageListener listener ) {
+ if ( listener == null ) {
+ return;
+ }
+ if ( !mListeners.containsKey( msgType ) ) {
+ return;
+ }
+ List< IMogoOnMessageListener > listeners = mListeners.get( msgType );
+ if ( listeners != null && listeners.contains( listener ) ) {
+ listeners.remove( listener );
+ }
+ }
+
+ @Override
+ public void sendMsg( MsgBody body, IMogoMsgAckListener listener ) {
+ Logger.d( TAG, "sendMsg." );
+ if ( mSocketConnManager != null ) {
+ if ( mSocketConnManager.isConnected() ) {
+ Logger.d( TAG, "isConnected." );
+ final byte[] pb = convertToPBBytes( body.getMsgType(), objectToBytes( body.getContent() ) );
+ mSocketConnManager.sendPayload(
+ MSG_PRODUCT_LINE,
+ pb,
+ MSG_HEADER_TYPE,
+ body.isAck(),
+ body.getMsgId()
+ );
+ mAckListeners.put( body.getMsgId(), listener );
+ } else {
+ Logger.e( TAG, "sendMsg error, connect is lost." );
+ }
+ } else {
+ Logger.e( TAG, "sendMsg error, client is null." );
+ }
+ }
+
+ public byte[] objectToBytes( Object obj ) {
+ String jsonStr = GsonUtil.jsonFromObject( obj );
+ return jsonStr.getBytes();
+ }
+
+ private byte[] convertToPBBytes( int msgType, byte[] payloadBytes ) {
+ MogoConnsvr.Payload payloadData = MogoConnsvr.Payload.newBuilder()
+ .setMsgType( msgType )
+ .setPayload( ByteString.copyFrom( payloadBytes ) ).build();
+ return payloadData.toByteArray();
+ }
+
+ public synchronized void release() {
+ mListeners.clear();
+ mListeners = null;
+ sInstance = null;
+ }
+
+
+ @Override
+ public void init( Context context ) {
+ }
+}
diff --git a/foudations/mogo-base-services-sdk/.gitignore b/foudations/mogo-base-services-sdk/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/foudations/mogo-base-services-sdk/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/foudations/mogo-base-services-sdk/README.md b/foudations/mogo-base-services-sdk/README.md
new file mode 100644
index 0000000000..d5fa09de5b
--- /dev/null
+++ b/foudations/mogo-base-services-sdk/README.md
@@ -0,0 +1,3 @@
+## sdk实现功能
+
+脱离基础服务apk实现对应功能:位置上报、长连接、passport
\ No newline at end of file
diff --git a/foudations/mogo-base-services-sdk/build.gradle b/foudations/mogo-base-services-sdk/build.gradle
new file mode 100644
index 0000000000..cec1ce1ece
--- /dev/null
+++ b/foudations/mogo-base-services-sdk/build.gradle
@@ -0,0 +1,53 @@
+apply plugin: 'com.android.library'
+
+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"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: "libs", include: ["*.jar"])
+ implementation rootProject.ext.dependencies.arouter
+ // 上报位置
+ implementation 'com.zhidao.locupload:loc-upload-sdk:1.1.7'
+ // 长链
+ implementation 'com.zhidao.socket:built-in-socket:1.0.17'
+ // passport
+ implementation 'com.zhidao.tcloginsdk:tclogin:1.1.3'
+
+ annotationProcessor 'com.elegant.spi:compiler:1.0.3'
+
+
+ if (Boolean.valueOf(RELEASE)) {
+ implementation rootProject.ext.dependencies.mogoutils
+ implementation rootProject.ext.dependencies.mogocommons
+ implementation rootProject.ext.dependencies.mogoserviceapi
+ } else {
+ implementation project(":foudations:mogo-utils")
+ implementation project(":foudations:mogo-commons")
+ implementation project(":services:mogo-service-api")
+ }
+}
+
+apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
\ No newline at end of file
diff --git a/foudations/mogo-base-services-sdk/consumer-rules.pro b/foudations/mogo-base-services-sdk/consumer-rules.pro
new file mode 100644
index 0000000000..e4c27a022e
--- /dev/null
+++ b/foudations/mogo-base-services-sdk/consumer-rules.pro
@@ -0,0 +1,2 @@
+#-----MogoBaseServiceSdk-----
+-keep class com.mogo.base.services.locationinfo.MogoLocationSource.*{*;}
\ No newline at end of file
diff --git a/foudations/mogo-base-services-sdk/gradle.properties b/foudations/mogo-base-services-sdk/gradle.properties
new file mode 100644
index 0000000000..ce31a0de78
--- /dev/null
+++ b/foudations/mogo-base-services-sdk/gradle.properties
@@ -0,0 +1,3 @@
+GROUP=com.mogo.base
+POM_ARTIFACT_ID=services-sdk
+VERSION_CODE=1
\ No newline at end of file
diff --git a/foudations/mogo-base-services-sdk/proguard-rules.pro b/foudations/mogo-base-services-sdk/proguard-rules.pro
new file mode 100644
index 0000000000..ba8f820823
--- /dev/null
+++ b/foudations/mogo-base-services-sdk/proguard-rules.pro
@@ -0,0 +1,24 @@
+# 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
+
+#-----MogoBaseServiceSdk-----
+-keep class com.mogo.base.services.locationinfo.MogoLocationSource.*{*;}
\ No newline at end of file
diff --git a/foudations/mogo-base-services-sdk/src/main/AndroidManifest.xml b/foudations/mogo-base-services-sdk/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..d7ee25b198
--- /dev/null
+++ b/foudations/mogo-base-services-sdk/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+ /
+
\ No newline at end of file
diff --git a/foudations/mogo-base-services-sdk/src/main/java/com/mogo/base/services/BaseServicesConstants.java b/foudations/mogo-base-services-sdk/src/main/java/com/mogo/base/services/BaseServicesConstants.java
new file mode 100644
index 0000000000..927c8ef250
--- /dev/null
+++ b/foudations/mogo-base-services-sdk/src/main/java/com/mogo/base/services/BaseServicesConstants.java
@@ -0,0 +1,19 @@
+package com.mogo.base.services;
+
+import androidx.annotation.Keep;
+
+public abstract
+/*
+ * @author congtaowang
+ * @since 2020/7/23
+ *
+ * 描述
+ */
+class BaseServicesConstants {
+
+ /**
+ * 建立长链的通道ID
+ */
+ @Keep
+ public static final String SOCKET_CHANNEL_ID = "dataCrawler";
+}
diff --git a/foudations/mogo-base-services-sdk/src/main/java/com/mogo/base/services/locationinfo/MogoLocationInfoServices.java b/foudations/mogo-base-services-sdk/src/main/java/com/mogo/base/services/locationinfo/MogoLocationInfoServices.java
new file mode 100644
index 0000000000..a8310e6ad9
--- /dev/null
+++ b/foudations/mogo-base-services-sdk/src/main/java/com/mogo/base/services/locationinfo/MogoLocationInfoServices.java
@@ -0,0 +1,79 @@
+package com.mogo.base.services.locationinfo;
+
+import android.content.Context;
+
+import androidx.annotation.Keep;
+
+import com.mogo.commons.debug.DebugConfig;
+import com.mogo.map.location.MogoLocation;
+import com.mogo.service.locationinfo.IMogoLocationInfoService;
+import com.mogo.utils.logger.Logger;
+import com.zhidao.locupload.LocUploadConfig;
+import com.zhidao.locupload.LocUploadManager;
+
+public
+/*
+ * @author congtaowang
+ * @since 2020/7/16
+ *
+ * 位置服务
+ */
+@Keep
+class MogoLocationInfoServices implements IMogoLocationInfoService {
+
+ private static final String TAG = "MogoLocationInfoServices-sdk";
+
+ private static volatile MogoLocationInfoServices sInstance;
+ private MogoLocation mLocation;
+
+ private MogoLocationInfoServices() {
+ }
+
+ @Keep
+ public static MogoLocationInfoServices getInstance() {
+ if ( sInstance == null ) {
+ synchronized ( MogoLocationInfoServices.class ) {
+ if ( sInstance == null ) {
+ sInstance = new MogoLocationInfoServices();
+ }
+ }
+ }
+ return sInstance;
+ }
+
+ public synchronized void release() {
+ sInstance = null;
+ }
+
+ @Override
+ public void provideLocation( MogoLocation location ) {
+ mLocation = location;
+ Logger.d( TAG, "sdk - provideLocation" );
+ }
+
+ public MogoLocation getLocation() {
+ return mLocation;
+ }
+
+ @Override
+ public void start() {
+ LocUploadManager.getInstance().startUpload();
+ Logger.d( TAG, "sdk - start" );
+ }
+
+ @Override
+ public void stop() {
+ LocUploadManager.getInstance().stopUpload();
+ Logger.d( TAG, "sdk - stop" );
+ }
+
+ @Override
+ public void init( Context context ) {
+ LocUploadConfig.instance().
+ setAppId( DebugConfig.getSocketAppId() ).
+ setContext( context.getApplicationContext() ).
+ setLoggable( DebugConfig.isDebug() ).
+ setLocInterval( 2000L );
+ Logger.d( TAG, "sdk - init" );
+ }
+}
diff --git a/foudations/mogo-base-services-sdk/src/main/java/com/mogo/base/services/locationinfo/MogoLocationSource.java b/foudations/mogo-base-services-sdk/src/main/java/com/mogo/base/services/locationinfo/MogoLocationSource.java
new file mode 100644
index 0000000000..844abb4a98
--- /dev/null
+++ b/foudations/mogo-base-services-sdk/src/main/java/com/mogo/base/services/locationinfo/MogoLocationSource.java
@@ -0,0 +1,133 @@
+package com.mogo.base.services.locationinfo;
+
+import com.elegant.spi.annotations.Service;
+import com.zhidao.locupload.location.LocationServiceProvider;
+
+public
+/**
+ * @author congtaowang
+ * @since 2020/7/16
+ *
+ * 描述
+ */
+@Service( value = LocationServiceProvider.class )
+class MogoLocationSource extends LocationServiceProvider {
+
+ @Override
+ public float getBearing() {
+ if ( MogoLocationInfoServices.getInstance().getLocation() != null ) {
+ return MogoLocationInfoServices.getInstance().getLocation().getBearing();
+ }
+ return 0;
+ }
+
+ @Override
+ public float getAccuracy() {
+ if ( MogoLocationInfoServices.getInstance().getLocation() != null ) {
+ return MogoLocationInfoServices.getInstance().getLocation().getAccuracy();
+ }
+ return 0;
+ }
+
+ @Override
+ public String getProvider() {
+ if ( MogoLocationInfoServices.getInstance().getLocation() != null ) {
+ return MogoLocationInfoServices.getInstance().getLocation().getProvider();
+ }
+ return null;
+ }
+
+ @Override
+ public float getSpeed() {
+ if ( MogoLocationInfoServices.getInstance().getLocation() != null ) {
+ return MogoLocationInfoServices.getInstance().getLocation().getSpeed();
+ }
+ return 0;
+ }
+
+ @Override
+ public double getAltitude() {
+ if ( MogoLocationInfoServices.getInstance().getLocation() != null ) {
+ return MogoLocationInfoServices.getInstance().getLocation().getAltitude();
+ }
+ return 0;
+ }
+
+ @Override
+ public String getAdCode() {
+ if ( MogoLocationInfoServices.getInstance().getLocation() != null ) {
+ return MogoLocationInfoServices.getInstance().getLocation().getAdCode();
+ }
+ return null;
+ }
+
+ @Override
+ public int getLocType() {
+ if ( MogoLocationInfoServices.getInstance().getLocation() != null ) {
+ return MogoLocationInfoServices.getInstance().getLocation().getLocType();
+ }
+ return 0;
+ }
+
+ @Override
+ public double getLatitude() {
+ if ( MogoLocationInfoServices.getInstance().getLocation() != null ) {
+ return MogoLocationInfoServices.getInstance().getLocation().getLatitude();
+ }
+ return 0;
+ }
+
+ @Override
+ public double getLongitude() {
+ if ( MogoLocationInfoServices.getInstance().getLocation() != null ) {
+ return MogoLocationInfoServices.getInstance().getLocation().getLongitude();
+ }
+ return 0;
+ }
+
+ @Override
+ public long getTime() {
+ if ( MogoLocationInfoServices.getInstance().getLocation() != null ) {
+ return MogoLocationInfoServices.getInstance().getLocation().getTime();
+ }
+ return 0;
+ }
+
+ @Override
+ public String getCityCode() {
+ if ( MogoLocationInfoServices.getInstance().getLocation() != null ) {
+ return MogoLocationInfoServices.getInstance().getLocation().getCityCode();
+ }
+ return null;
+ }
+
+ @Override
+ public String getCityName() {
+ if ( MogoLocationInfoServices.getInstance().getLocation() != null ) {
+ return MogoLocationInfoServices.getInstance().getLocation().getCityName();
+ }
+ return null;
+ }
+
+ @Override
+ public int getGpsAccuracyStatus() {
+ if ( MogoLocationInfoServices.getInstance().getLocation() != null ) {
+ return MogoLocationInfoServices.getInstance().getLocation().getGpsAccuracyStatus();
+ }
+ return 0;
+ }
+
+ @Override
+ public int getSatellites() {
+ if ( MogoLocationInfoServices.getInstance().getLocation() != null ) {
+ return MogoLocationInfoServices.getInstance().getLocation().getSatellite();
+ }
+ return 0;
+ }
+
+ @Override
+ public int getCarStatus() {
+ // 常开状态
+ return 1;
+ }
+}
diff --git a/foudations/mogo-base-services-sdk/src/main/java/com/mogo/base/services/passport/PassportManager.java b/foudations/mogo-base-services-sdk/src/main/java/com/mogo/base/services/passport/PassportManager.java
new file mode 100644
index 0000000000..183e633722
--- /dev/null
+++ b/foudations/mogo-base-services-sdk/src/main/java/com/mogo/base/services/passport/PassportManager.java
@@ -0,0 +1,119 @@
+package com.mogo.base.services.passport;
+
+import android.content.Context;
+
+import androidx.annotation.Keep;
+
+import com.mogo.commons.debug.DebugConfig;
+import com.mogo.commons.storage.SpStorage;
+import com.mogo.service.passport.IMogoPassportManager;
+import com.mogo.service.passport.IMogoTicketCallback;
+import com.mogo.utils.logger.Logger;
+import com.zhidao.accountsdk.manager.CarPadClientManagerImpl;
+import com.zhidao.accountsdk.manager.TicketInfoCallback;
+import com.zhidao.tcloginsdk.LoginManager;
+import com.zhidao.tcloginsdk.model.TokenData;
+import com.zhidao.tcloginsdk.network.LoginCallback;
+
+public
+/*
+ * @author congtaowang
+ * @since 2020/7/16
+ *
+ * 描述
+ */
+@Keep
+class PassportManager implements IMogoPassportManager {
+
+ private static final String TAG = "PassportManager-sdk";
+ private Context mContext;
+
+ private static volatile PassportManager sInstance;
+
+ private PassportManager() {
+ }
+
+ @Keep
+ public static PassportManager getInstance() {
+ if ( sInstance == null ) {
+ synchronized ( PassportManager.class ) {
+ if ( sInstance == null ) {
+ sInstance = new PassportManager();
+ }
+ }
+ }
+ return sInstance;
+ }
+
+ public synchronized void release() {
+ sInstance = null;
+ }
+
+ @Override
+ public void requestTicket( final IMogoTicketCallback callback ) {
+ LoginManager.getInstance( mContext ).login( DebugConfig.getCarMachineType() != DebugConfig.CAR_MACHINE_TYPE_SELF_INNOVATE, DebugConfig.getProductFlavor(), new LoginCallback() {
+ @Override
+ public void onSuccess( TokenData.TokenResult result ) {
+ if ( callback != null ) {
+ callback.onLoginSuccess( result.token, result.sn );
+ }
+ getTicket( new TicketInfoCallback() {
+ @Override
+ public void onSuccess( String ticket ) {
+ Logger.d( TAG, "success" );
+ SpStorage.setTicket( ticket );
+ if ( callback != null ) {
+ callback.onTicketGot( ticket );
+ }
+ }
+
+ @Override
+ public void onFailure( int code ) {
+ Logger.d( TAG, "fail: code = %s", code );
+ if ( callback != null ) {
+ callback.onError( code, "getTicket error." );
+ }
+ }
+ } );
+ }
+
+ @Override
+ public void onFailure( int code, String msg ) {
+ Logger.d( TAG, "onFailure: code = %s, msg = %s", code, msg );
+ if ( callback != null ) {
+ callback.onError( code, "login: " + msg );
+ }
+ }
+ } );
+
+ }
+
+ private void getTicket( TicketInfoCallback callback ) {
+ CarPadClientManagerImpl.getInstance( mContext ).getTicket( "os2.0-launcher", new TicketInfoCallback() {
+ @Override
+ public void onSuccess( String ticket ) {
+ if ( callback != null ) {
+ callback.onSuccess( ticket );
+ }
+ }
+
+ @Override
+ public void onFailure( int code ) {
+ if ( callback != null ) {
+ callback.onFailure( code );
+ }
+ }
+ } );
+ }
+
+ @Override
+ public void init( Context context ) {
+ mContext = context;
+ int mode = DebugConfig.getNetMode();
+ if ( mode == DebugConfig.NET_MODE_DEMO ) {
+ // 演示环境用 qa 的
+ mode = DebugConfig.NET_MODE_QA;
+ }
+ LoginManager.getInstance( context ).setNetEnviron( mode );
+ }
+}
diff --git a/foudations/mogo-base-services-sdk/src/main/java/com/mogo/base/services/socket/SocketManager.java b/foudations/mogo-base-services-sdk/src/main/java/com/mogo/base/services/socket/SocketManager.java
new file mode 100644
index 0000000000..6fdb1699cc
--- /dev/null
+++ b/foudations/mogo-base-services-sdk/src/main/java/com/mogo/base/services/socket/SocketManager.java
@@ -0,0 +1,231 @@
+package com.mogo.base.services.socket;
+
+import android.content.Context;
+
+import androidx.annotation.Keep;
+import androidx.annotation.NonNull;
+
+import com.google.protobuf.ByteString;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.mogo.base.services.BaseServicesConstants;
+import com.mogo.commons.debug.DebugConfig;
+import com.mogo.commons.network.Utils;
+import com.mogo.service.connection.IMogoMsgAckListener;
+import com.mogo.service.connection.IMogoOnMessageListener;
+import com.mogo.service.connection.IMogoSocketManager;
+import com.mogo.service.connection.MsgBody;
+import com.mogo.utils.logger.Logger;
+import com.mogo.utils.network.utils.GsonUtil;
+import com.zhidao.locupload.Platform;
+import com.zhidao.ptech.connsvr.protocol.MogoConnsvr;
+import com.zhidao.socket.Callback;
+import com.zhidao.socket.CallbackManager;
+import com.zhidao.socket.Environment;
+import com.zhidao.socket.SocketClient;
+import com.zhidao.socket.SocketConfig;
+import com.zhidao.socket.utils.RequestUtil;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public
+/**
+ * @author congtaowang
+ * @since 2020/7/16
+ *
+ * 长链
+ */
+@Keep
+class SocketManager implements IMogoSocketManager, Callback {
+
+ private static final String TAG = "SocketManager-sdk";
+
+ private static volatile SocketManager sInstance;
+ private String mAppId;
+
+ public SocketManager( Context context ) {
+ CallbackManager.getInstance().register( this );
+ }
+
+ @Keep
+ public static SocketManager getInstance( Context context ) {
+ if ( sInstance == null ) {
+ synchronized ( SocketManager.class ) {
+ if ( sInstance == null ) {
+ sInstance = new SocketManager( context );
+ }
+ }
+ }
+ return sInstance;
+ }
+
+ /**
+ * 管理消息分发
+ *
+ * key - msgType
+ */
+ private Map< Integer, List< IMogoOnMessageListener > > mListeners = new ConcurrentHashMap<>();
+
+ /**
+ * 管理消息回执
+ *
+ * key - msgId
+ */
+ private Map< Long, IMogoMsgAckListener > mAckListeners = new ConcurrentHashMap<>();
+
+
+ public static final int MAX_CAP = 64; //保证充足的容量应对非常延时的推送
+ private ArrayList< Long > mReceivedMsgId = new ArrayList<>( MAX_CAP );
+ private int mCurrentIndex = 0;
+
+ @Override
+ public void init( Context context, String appId ) {
+ mAppId = appId;
+ SocketConfig.instance()
+ .setAppContext( context.getApplicationContext() )
+ .setEnvironment( getEnvironment() )
+ .setClient( Platform.getClient( Platform.car ) )
+ .setChannelId( BaseServicesConstants.SOCKET_CHANNEL_ID )
+ .setOpenAnalytics( true )
+ .setSn( MoGoAiCloudClientConfig.getInstance().getSn() )
+ .setDebug( DebugConfig.isDebug() );
+ SocketClient.getInstance().start( context );
+ }
+
+ private Environment getEnvironment() {
+ switch ( DebugConfig.getNetMode() ) {
+ case 1:
+ return Environment.dev;
+ case 2:
+ case 4:
+ return Environment.qa;
+ case 3:
+ default:
+ return Environment.release;
+ }
+ }
+
+ @Override
+ public void update( @NonNull CallbackManager manager, @NonNull byte[] content, String appId, long msgId ) {
+ try {
+ MogoConnsvr.Payload payload = MogoConnsvr.Payload.parseFrom( content );
+ int msgType = payload.getMsgType();
+ Logger.d( TAG, "received msg type = %d", msgType );
+ List< IMogoOnMessageListener > listeners = mListeners.get( msgType );
+ if ( listeners != null && !listeners.isEmpty() ) {
+ Iterator< IMogoOnMessageListener > iterator = listeners.iterator();
+ if ( msgId != 0 ) { //兼容老版本
+ if ( mReceivedMsgId.contains( msgId ) ) { // 避免消息重发
+ return;
+ }
+ cacheLastReceivedMsgId( msgId );
+ }
+ Object object = null;
+ while ( iterator.hasNext() ) {
+ IMogoOnMessageListener listener = iterator.next();
+ if ( object == null ) {
+ object = GsonUtil.objectFromJson( payload.getPayload().toStringUtf8(), listener.target() );
+ }
+ if ( listener != null ) {
+ Logger.d( TAG, "received msgId = %s, content = %s", msgId, payload.getPayload().toStringUtf8() );
+ listener.onMsgReceived( object );
+ }
+ }
+ }
+ } catch ( InvalidProtocolBufferException e ) {
+ Logger.e( TAG, e, "parse msg error." );
+ }
+ }
+
+ @Override
+ public void onAck( @NonNull CallbackManager manager, @NonNull byte[] headerBytes, byte[] content ) {
+ try {
+ MogoConnsvr.Header header = MogoConnsvr.Header.parseFrom( headerBytes );
+ int msgType = header.getMsgType();
+ String appId = header.getAppId();
+ int productLine = header.getProductLine();
+ long msgId = header.getMsgId();
+ IMogoMsgAckListener listener = mAckListeners.remove( msgId );
+ if ( listener != null ) {
+ listener.onAck( msgId );
+ }
+ Logger.d( TAG, "send message success: msgType = %d, appId = %s, productLine = %d", msgType, appId, productLine );
+ } catch ( InvalidProtocolBufferException e ) {
+ e.printStackTrace();
+ }
+ }
+
+ private void cacheLastReceivedMsgId( long msgId ) {
+ if ( msgId == 0 ) {
+ return;
+ }
+ synchronized ( this ) {
+ mReceivedMsgId.add( mCurrentIndex % MAX_CAP, msgId );
+ mCurrentIndex++;
+ }
+ }
+
+ @Override
+ public void registerOnMessageListener( int msgType, IMogoOnMessageListener listener ) {
+ if ( mListeners.containsKey( msgType ) ) {
+ Logger.w( TAG, "msgType %d is exist.", msgType );
+ }
+ if ( !mListeners.containsKey( msgType ) ) {
+ mListeners.put( msgType, new ArrayList<>() );
+ }
+ mListeners.get( msgType ).add( listener );
+ }
+
+ @Override
+ public void unregisterOnMessageListener( int msgType ) {
+ mListeners.remove( msgType );
+ }
+
+ @Override
+ public void unregisterOnMessageListener( int msgType, IMogoOnMessageListener listener ) {
+ if ( listener == null ) {
+ return;
+ }
+ if ( !mListeners.containsKey( msgType ) ) {
+ return;
+ }
+ List< IMogoOnMessageListener > listeners = mListeners.get( msgType );
+ if ( listeners != null && listeners.contains( listener ) ) {
+ listeners.remove( listener );
+ }
+ }
+
+ @Override
+ public void sendMsg( MsgBody body, IMogoMsgAckListener listener ) {
+ Logger.d( TAG, "sendMsg." );
+ final byte[] pb = convertToPBBytes( body.getMsgType(), objectToBytes( body.getContent() ) );
+ RequestUtil.sendPayloadData( mAppId, 2, pb, 1, true, System.currentTimeMillis() );
+ }
+
+ public byte[] objectToBytes( Object obj ) {
+ String jsonStr = GsonUtil.jsonFromObject( obj );
+ return jsonStr.getBytes();
+ }
+
+ private byte[] convertToPBBytes( int msgType, byte[] payloadBytes ) {
+ MogoConnsvr.Payload payloadData = MogoConnsvr.Payload.newBuilder()
+ .setMsgType( msgType )
+ .setPayload( ByteString.copyFrom( payloadBytes ) ).build();
+ return payloadData.toByteArray();
+ }
+
+ public synchronized void release() {
+ mListeners.clear();
+ mListeners = null;
+ sInstance = null;
+ }
+
+
+ @Override
+ public void init( Context context ) {
+ }
+
+}
diff --git a/modules/mogo-module-guide/.gitignore b/modules/mogo-module-guide/.gitignore
new file mode 100644
index 0000000000..796b96d1c4
--- /dev/null
+++ b/modules/mogo-module-guide/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/modules/mogo-module-guide/build.gradle b/modules/mogo-module-guide/build.gradle
new file mode 100644
index 0000000000..5c13d19f76
--- /dev/null
+++ b/modules/mogo-module-guide/build.gradle
@@ -0,0 +1,70 @@
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+apply plugin: 'com.alibaba.arouter'
+apply plugin: 'kotlin-kapt'
+
+android {
+ compileSdkVersion rootProject.ext.android.compileSdkVersion
+
+ 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
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation rootProject.ext.dependencies.kotlinstdlibjdk7
+ implementation rootProject.ext.dependencies.androidxccorektx
+ implementation rootProject.ext.dependencies.coroutinescore
+ implementation rootProject.ext.dependencies.coroutinesandroid
+ implementation rootProject.ext.dependencies.androidxappcompat
+ implementation rootProject.ext.dependencies.androidxconstraintlayout
+ implementation rootProject.ext.dependencies.androidxviewpager2
+ implementation rootProject.ext.dependencies.arouter
+ kapt rootProject.ext.dependencies.aroutercompiler
+ implementation rootProject.ext.dependencies.indicator
+
+ if (Boolean.valueOf(RELEASE)) {
+ implementation rootProject.ext.dependencies.mogoutils
+ implementation rootProject.ext.dependencies.mogocommons
+ implementation rootProject.ext.dependencies.mogoserviceapi
+ implementation rootProject.ext.dependencies.mogomoduleauth
+ implementation rootProject.ext.dependencies.modulecommon
+ } else {
+ implementation project(":foudations:mogo-utils")
+ implementation project(":foudations:mogo-commons")
+ implementation project(':services:mogo-service-api')
+ implementation project(':modules:mogo-module-authorize')
+ implementation project(":modules:mogo-module-common")
+ }
+}
+
+apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
\ No newline at end of file
diff --git a/modules/mogo-module-guide/consumer-rules.pro b/modules/mogo-module-guide/consumer-rules.pro
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/modules/mogo-module-guide/gradle.properties b/modules/mogo-module-guide/gradle.properties
new file mode 100644
index 0000000000..d5a467b651
--- /dev/null
+++ b/modules/mogo-module-guide/gradle.properties
@@ -0,0 +1,3 @@
+GROUP=com.mogo.module
+POM_ARTIFACT_ID=module-guide
+VERSION_CODE=1
diff --git a/modules/mogo-module-guide/proguard-rules.pro b/modules/mogo-module-guide/proguard-rules.pro
new file mode 100644
index 0000000000..f1b424510d
--- /dev/null
+++ b/modules/mogo-module-guide/proguard-rules.pro
@@ -0,0 +1,21 @@
+# 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
diff --git a/modules/mogo-module-guide/src/androidTest/java/com/mogo/module/guide/agreement/ExampleInstrumentedTest.kt b/modules/mogo-module-guide/src/androidTest/java/com/mogo/module/guide/agreement/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000000..1b82ddd479
--- /dev/null
+++ b/modules/mogo-module-guide/src/androidTest/java/com/mogo/module/guide/agreement/ExampleInstrumentedTest.kt
@@ -0,0 +1,2 @@
+package com.mogo.module.guide.agreement
+
diff --git a/modules/mogo-module-guide/src/main/AndroidManifest.xml b/modules/mogo-module-guide/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..f00166428d
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/AndroidManifest.xml
@@ -0,0 +1 @@
+
diff --git a/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/GuideBizManager.kt b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/GuideBizManager.kt
new file mode 100644
index 0000000000..6e6f4ac846
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/GuideBizManager.kt
@@ -0,0 +1,65 @@
+package com.mogo.module.guide
+
+import com.alibaba.android.arouter.launcher.ARouter
+import com.mogo.module.authorize.authprovider.invoke.AuthorizeConstant
+import com.mogo.module.authorize.authprovider.invoke.AuthorizeInvokerConstant.Companion.AUTHORIZE_TYPE_LAUNCHER_MAIN
+import com.mogo.module.authorize.authprovider.module.IMogoAuthorizeModuleManager
+import com.mogo.module.guide.GuideConstant.Companion.PATH_GUIDE_MODULE_NAME
+import com.mogo.module.guide.fragment.GuideFragment
+import com.mogo.module.guide.util.SharedPreferenceUtil.hasGuide
+import com.mogo.module.guide.util.SharedPreferenceUtil.setGuideFinish
+import com.mogo.module.guide.util.SharedPreferenceUtil.setGuideRecord
+import com.mogo.service.IMogoServiceApis
+import com.mogo.service.MogoServicePaths
+import com.mogo.service.fragmentmanager.FragmentDescriptor
+import com.mogo.utils.UiThreadHandler
+import com.mogo.utils.logger.Logger
+
+object GuideBizManager {
+
+ private var serviceApi: IMogoServiceApis? = null
+
+ fun init() {
+ Logger.d("GuideBizManager", "init===================================")
+ initService()
+ addGuideFragmentToStack()
+ }
+
+ private fun initService() {
+ val mogoService = ARouter.getInstance().build(MogoServicePaths.PATH_SERVICE_APIS).navigation()
+ if (mogoService is IMogoServiceApis && serviceApi == null) {
+ serviceApi = mogoService
+ serviceApi?.adasControllerApi?.closeADAS()
+ }
+ }
+
+ private fun addGuideFragmentToStack() {
+ if (!hasGuide()) {
+ serviceApi?.let {
+ val builderWrapper = FragmentDescriptor.Builder().fragment(GuideFragment())
+ .tag(PATH_GUIDE_MODULE_NAME).build()
+ it.fragmentManagerApi.push(builderWrapper)
+ }
+ }
+ }
+
+ fun removeGuideFragmentToStack() {
+ Logger.d("GuideBizManager", "removeGuideFragmentToStack")
+ setGuideFinish()
+ setGuideRecord()
+ serviceApi?.fragmentManagerApi?.pop()
+ serviceApi?.adasControllerApi?.showADAS()
+ }
+
+ fun invokeAuthorize() {
+ UiThreadHandler.postDelayed({
+ val authorizeInvoke = ARouter.getInstance().build(AuthorizeConstant.PROVIDER_MODULE).navigation()
+ if (authorizeInvoke is IMogoAuthorizeModuleManager) {
+ if (authorizeInvoke.needAuthorize(AUTHORIZE_TYPE_LAUNCHER_MAIN)) {
+ authorizeInvoke.invokeAuthorizeForShow()
+ }
+ }
+ }, 3000L)
+
+ }
+}
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/GuideConstant.kt b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/GuideConstant.kt
new file mode 100644
index 0000000000..4e2c54c706
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/GuideConstant.kt
@@ -0,0 +1,16 @@
+package com.mogo.module.guide
+
+class GuideConstant {
+
+ companion object {
+ /**
+ * 展示用户引导模块地址
+ */
+ const val PATH_GUIDE_FRAGMENT = "/guide/showFragment"
+
+ /**
+ * provider模块实例名称(暂时仅有卡片用到)
+ */
+ const val PATH_GUIDE_MODULE_NAME = "GUIDE_MODULE_NAME"
+ }
+}
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/MogoGuideProvider.kt b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/MogoGuideProvider.kt
new file mode 100644
index 0000000000..d1a00f893e
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/MogoGuideProvider.kt
@@ -0,0 +1,68 @@
+package com.mogo.module.guide
+
+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.guide.GuideConstant.Companion.PATH_GUIDE_FRAGMENT
+import com.mogo.module.guide.GuideConstant.Companion.PATH_GUIDE_MODULE_NAME
+import com.mogo.service.module.IMogoModuleProvider
+import com.mogo.service.module.ModuleType
+import com.mogo.utils.logger.Logger
+
+@Route(path = PATH_GUIDE_FRAGMENT)
+class MogoGuideProvider : IMogoModuleProvider {
+
+ /**
+ * 卡片用到
+ */
+ override fun createFragment(context: Context?, data: Bundle?): Fragment? {
+ return null
+ }
+
+ override fun createView(context: Context?): View? {
+ return null
+ }
+
+ override fun getModuleName(): String {
+ return PATH_GUIDE_MODULE_NAME
+ }
+
+ override fun getMapListener(): IMogoMapListener? {
+ return null
+ }
+
+ override fun getType(): Int {
+ return ModuleType.TYPE_SERVICE
+ }
+
+ override fun getNaviListener(): IMogoNaviListener? {
+ return null
+ }
+
+ override fun getLocationListener(): IMogoLocationListener? {
+ return null
+ }
+
+ override fun getMarkerClickListener(): IMogoMarkerClickListener? {
+ return null
+ }
+
+ override fun init(context: Context?) {
+ Logger.d("MogoGuideProvider", "init====")
+ GuideBizManager.init()
+ }
+
+ override fun getAppPackage(): String? {
+ return null
+ }
+
+ override fun getAppName(): String? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/fragment/GuideAdapter.kt b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/fragment/GuideAdapter.kt
new file mode 100644
index 0000000000..af3660c13e
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/fragment/GuideAdapter.kt
@@ -0,0 +1,35 @@
+package com.mogo.module.guide.fragment
+
+import androidx.fragment.app.Fragment
+import androidx.viewpager2.adapter.FragmentStateAdapter
+import com.mogo.module.guide.guide.*
+
+class GuideAdapter(fragmentActivity: GuideFragment) : FragmentStateAdapter(fragmentActivity) {
+
+ override fun getItemCount(): Int {
+ return guideList.size
+ }
+
+ override fun createFragment(position: Int): Fragment {
+ return guideList[position]
+ }
+
+ private val guideList: MutableList = mutableListOf()
+
+ companion object {
+ const val GUIDE_PAGE_ONE = 0
+ const val GUIDE_PAGE_TWO = 1
+ const val GUIDE_PAGE_THREE = 2
+ const val GUIDE_PAGE_FOUR = 3
+ const val GUIDE_PAGE_FIVE = 4
+ }
+
+ init {
+ guideList.add(GUIDE_PAGE_ONE, GuideStageOneFragment(fragmentActivity))
+ guideList.add(GUIDE_PAGE_TWO, GuideStageTwoFragment(fragmentActivity))
+ guideList.add(GUIDE_PAGE_THREE, GuideStageThreeFragment(fragmentActivity))
+ guideList.add(GUIDE_PAGE_FOUR, GuideStageFourFragment(fragmentActivity))
+ guideList.add(GUIDE_PAGE_FIVE, GuideStageFiveFragment(fragmentActivity))
+ }
+
+}
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/fragment/GuideConstract.kt b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/fragment/GuideConstract.kt
new file mode 100644
index 0000000000..22c574452a
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/fragment/GuideConstract.kt
@@ -0,0 +1,14 @@
+package com.mogo.module.guide.fragment
+
+import com.mogo.commons.mvp.IView
+
+class GuideConstract {
+
+ interface View:IView{
+
+ }
+
+ interface Biz{
+
+ }
+}
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/fragment/GuideFragment.kt b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/fragment/GuideFragment.kt
new file mode 100644
index 0000000000..127c0fcfe3
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/fragment/GuideFragment.kt
@@ -0,0 +1,138 @@
+package com.mogo.module.guide.fragment
+
+import android.view.View
+import androidx.recyclerview.widget.RecyclerView
+import com.mogo.commons.mvp.MvpFragment
+import com.mogo.commons.voice.IMogoVoiceCmdCallBack
+import com.mogo.module.guide.GuideBizManager
+import com.mogo.module.guide.R
+import com.mogo.module.guide.util.AnalyticsUtil
+import com.mogo.module.guide.util.AnalyticsUtil.INVOKE_TRACK_PASS_TIME
+import com.mogo.module.guide.util.AnalyticsUtil.INVOKE_TRACK_PLAY_PASS_ID
+import com.mogo.module.guide.util.AnalyticsUtil.INVOKE_TRACK_PLAY_TIME
+import com.mogo.module.guide.util.breakOffSpeak
+import com.mogo.module.guide.util.speak
+import com.mogo.utils.logger.Logger
+import com.zhpan.indicator.enums.IndicatorSlideMode
+import com.zhpan.indicator.enums.IndicatorStyle
+import kotlinx.android.synthetic.main.module_guide_fragment.*
+import kotlinx.android.synthetic.main.module_guide_item_include.*
+
+class GuideFragment : MvpFragment(), GuideConstract.View {
+
+ companion object {
+ const val TAG = "GuideFragment"
+ }
+
+ private var duringTime: Long = 0L
+ private var recordCount = 0
+
+ override fun getLayoutId(): Int {
+ return R.layout.module_guide_fragment
+ }
+
+ override fun createPresenter(): GuidePresenter {
+ return GuidePresenter(this)
+ }
+
+ private var adapter: GuideAdapter? = null
+
+ override fun initViews() {
+ Logger.d(TAG, "init Views")
+ duringTime = System.currentTimeMillis()
+ adapter = GuideAdapter(this)
+ moduleGuideViewPager.adapter = adapter
+ (moduleGuideViewPager.getChildAt(0) as RecyclerView).layoutManager!!.isItemPrefetchEnabled = false
+ @Suppress("DEPRECATION")
+ moduleGuideIndicator.setSliderColor(context!!.resources.getColor(R.color.module_guide_indicator_dark), context!!.resources.getColor(R.color.module_guide_indicator_white))
+ .setSliderWidth(context!!.resources.getDimension(R.dimen.dp_22))
+ .setSlideMode(IndicatorSlideMode.NORMAL)
+ .setIndicatorStyle(IndicatorStyle.CIRCLE)
+ .setupWithViewPager(moduleGuideViewPager)
+ visibleRight()
+ module_guide_page_left.setOnClickListener {
+ moveToBack()
+ }
+ module_guide_page_right.setOnClickListener {
+ moveToNext()
+ }
+ module_guide_tv_next_step.setOnClickListener {
+ if( (moduleGuideViewPager.currentItem + 1) == adapter!!.itemCount){
+ closeGuideFragment()
+ }else{
+ moveToNext()
+ }
+ }
+ }
+
+ fun visibleLeft() {
+ module_guide_page_left.visibility = View.VISIBLE
+ }
+
+ fun invisibleLeft() {
+ module_guide_page_left.visibility = View.GONE
+ }
+
+ fun visibleRight() {
+ module_guide_page_right.visibility = View.VISIBLE
+ module_guide_tv_next_step.text = context!!.resources.getString(R.string.module_guide_item_next_step)
+ }
+
+ fun invisibleRight() {
+ module_guide_page_right.visibility = View.GONE
+ module_guide_tv_next_step.text = context!!.resources.getString(R.string.module_guide_finish)
+ }
+
+ fun moveToNext() {
+ val count = adapter?.itemCount
+ if (moduleGuideViewPager.currentItem != count) {
+ moduleGuideViewPager.currentItem = moduleGuideViewPager.currentItem + 1
+ }
+ }
+
+ private fun moveToBack() {
+ val count = adapter?.itemCount
+ val backCount = moduleGuideViewPager.currentItem - 1
+ if (moduleGuideViewPager.currentItem != count) {
+ moduleGuideViewPager.currentItem = backCount
+ }
+ }
+
+ fun closeGuideFragment() {
+ recordCount = moduleGuideViewPager.currentItem + 1
+ destroy()
+ }
+
+ private fun track() {
+ val recordTime = System.currentTimeMillis() - duringTime
+ AnalyticsUtil.track(INVOKE_TRACK_PLAY_PASS_ID,
+ hashMapOf(INVOKE_TRACK_PASS_TIME to recordCount
+ , INVOKE_TRACK_PLAY_TIME to recordTime))
+ Logger.d(TAG, "closeGuideFragment -> recordTime : $recordTime , recordCount : $recordCount")
+ }
+
+ private fun destroy() {
+ GuideBizManager.removeGuideFragmentToStack()
+ }
+
+ private fun invokeAuthorize() {
+ GuideBizManager.invokeAuthorize()
+ }
+
+ override fun onDestroyView() {
+ closeGuideFragment()
+ super.onDestroyView()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ track()
+ breakOffSpeak(context!!)
+ speak(context!!, context!!.resources.getString(R.string.module_guide_voice_page_end), object : IMogoVoiceCmdCallBack {
+ override fun onTTSEnd(ttsId: String?, tts: String?) {
+
+ }
+ })
+ invokeAuthorize()
+ }
+}
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/fragment/GuidePresenter.kt b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/fragment/GuidePresenter.kt
new file mode 100644
index 0000000000..09000d16f4
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/fragment/GuidePresenter.kt
@@ -0,0 +1,18 @@
+package com.mogo.module.guide.fragment
+
+import androidx.lifecycle.LifecycleOwner
+import com.mogo.commons.mvp.Presenter
+
+class GuidePresenter : Presenter, GuideConstract.Biz {
+
+ constructor(view: GuideConstract.View) : super(view)
+
+ companion object{
+ const val TAG = "GuidePresenter"
+ }
+
+ override fun onCreate(owner: LifecycleOwner) {
+ super.onCreate(owner)
+
+ }
+}
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/guide/GuideStageFiveFragment.kt b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/guide/GuideStageFiveFragment.kt
new file mode 100644
index 0000000000..64b3a4d15e
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/guide/GuideStageFiveFragment.kt
@@ -0,0 +1,57 @@
+package com.mogo.module.guide.guide
+
+import com.mogo.commons.debug.DebugConfig
+import com.mogo.commons.mvp.IView
+import com.mogo.commons.mvp.MvpFragment
+import com.mogo.commons.mvp.Presenter
+import com.mogo.commons.voice.IMogoVoiceCmdCallBack
+import com.mogo.module.guide.R
+import com.mogo.module.guide.fragment.GuideFragment
+import com.mogo.module.guide.util.breakOffSpeak
+import com.mogo.module.guide.util.speak
+import kotlinx.android.synthetic.main.module_guide_item_stage_five.*
+import kotlinx.android.synthetic.main.module_guide_item_stage_four.*
+
+class GuideStageFiveFragment : MvpFragment> {
+
+ private var containerFragment: GuideFragment? = null
+
+ constructor(containerFragment: GuideFragment) {
+ this.containerFragment = containerFragment
+ }
+
+ override fun getLayoutId(): Int {
+ return R.layout.module_guide_item_stage_five
+ }
+
+ override fun createPresenter(): Presenter {
+ return GuideLocationPresenter(this)
+ }
+
+ override fun initViews() {
+ if(!DebugConfig.isLauncher()){
+ @Suppress("DEPRECATION")
+ moduleGuidePageFive.background = context!!.resources!!.getDrawable(R.mipmap.module_guide_item_stage_five)
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ containerFragment?.invisibleRight()
+ breakOffSpeak(context!!)
+ speak(context!!, context!!.resources.getString(R.string.module_guide_voice_page_five), object : IMogoVoiceCmdCallBack {
+ override fun onSpeakEnd(speakText: String?) {
+ if(!isVisible){
+ return
+ }
+ containerFragment?.closeGuideFragment()
+ }
+ })
+ }
+
+ class GuideLocationPresenter : Presenter {
+
+ constructor(view: IView?) : super(view)
+ }
+
+}
diff --git a/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/guide/GuideStageFourFragment.kt b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/guide/GuideStageFourFragment.kt
new file mode 100644
index 0000000000..0b703259fb
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/guide/GuideStageFourFragment.kt
@@ -0,0 +1,58 @@
+package com.mogo.module.guide.guide
+
+import com.mogo.commons.debug.DebugConfig
+import com.mogo.commons.mvp.IView
+import com.mogo.commons.mvp.MvpFragment
+import com.mogo.commons.mvp.Presenter
+import com.mogo.commons.voice.IMogoVoiceCmdCallBack
+import com.mogo.module.guide.R
+import com.mogo.module.guide.fragment.GuideFragment
+import com.mogo.module.guide.util.breakOffSpeak
+import com.mogo.module.guide.util.speak
+import kotlinx.android.synthetic.main.module_guide_item_stage_four.*
+import kotlinx.android.synthetic.main.module_guide_item_stage_three.*
+
+class GuideStageFourFragment : MvpFragment> {
+
+ private var containerFragment: GuideFragment? = null
+
+ constructor(containerFragment: GuideFragment) {
+ this.containerFragment = containerFragment
+ }
+
+ override fun getLayoutId(): Int {
+ return R.layout.module_guide_item_stage_four
+ }
+
+ override fun createPresenter(): Presenter {
+ return GuideNavigationPresenter(this)
+ }
+
+ override fun initViews() {
+ if(!DebugConfig.isLauncher()){
+ @Suppress("DEPRECATION")
+ moduleGuidePageFour.background = context!!.resources!!.getDrawable(R.mipmap.module_guide_item_stage_four)
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ containerFragment?.visibleLeft()
+ containerFragment?.visibleRight()
+ breakOffSpeak(context!!)
+ speak(context!!, context!!.resources.getString(R.string.module_guide_voice_page_four), object : IMogoVoiceCmdCallBack {
+ override fun onSpeakEnd(speakText: String?) {
+ if(!isVisible){
+ return
+ }
+ containerFragment?.moveToNext()
+ }
+ })
+ }
+
+ class GuideNavigationPresenter : Presenter {
+
+ constructor(view: IView?) : super(view)
+ }
+
+}
diff --git a/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/guide/GuideStageOneFragment.kt b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/guide/GuideStageOneFragment.kt
new file mode 100644
index 0000000000..6844e29fc7
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/guide/GuideStageOneFragment.kt
@@ -0,0 +1,57 @@
+package com.mogo.module.guide.guide
+
+import com.mogo.commons.debug.DebugConfig
+import com.mogo.commons.mvp.IView
+import com.mogo.commons.mvp.MvpFragment
+import com.mogo.commons.mvp.Presenter
+import com.mogo.commons.voice.IMogoVoiceCmdCallBack
+import com.mogo.module.guide.R
+import com.mogo.module.guide.fragment.GuideFragment
+import com.mogo.module.guide.util.breakOffSpeak
+import com.mogo.module.guide.util.speak
+import kotlinx.android.synthetic.main.module_guide_item_stage_one.*
+
+
+class GuideStageOneFragment : MvpFragment> {
+
+ private var containerFragment: GuideFragment? = null
+
+ constructor(containerFragment: GuideFragment) {
+ this.containerFragment = containerFragment
+ }
+
+ override fun getLayoutId(): Int {
+ return R.layout.module_guide_item_stage_one
+ }
+
+ override fun createPresenter(): Presenter {
+ return GuideStartPresenter(this)
+ }
+
+ override fun initViews() {
+ containerFragment?.visibleRight()
+ if(!DebugConfig.isLauncher()){
+ @Suppress("DEPRECATION")
+ moduleGuidePageOne.background = context!!.resources!!.getDrawable(R.mipmap.module_guide_item_stage_one)
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ containerFragment?.invisibleLeft()
+ breakOffSpeak(context!!)
+ speak(context!!, context!!.resources.getString(R.string.module_guide_voice_page_one), object : IMogoVoiceCmdCallBack {
+ override fun onSpeakEnd(speakText: String?) {
+ if (!isVisible) {
+ return
+ }
+ containerFragment?.moveToNext()
+ }
+ })
+ }
+
+ class GuideStartPresenter : Presenter {
+
+ constructor(view: IView?) : super(view)
+ }
+}
diff --git a/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/guide/GuideStageThreeFragment.kt b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/guide/GuideStageThreeFragment.kt
new file mode 100644
index 0000000000..88238ecc21
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/guide/GuideStageThreeFragment.kt
@@ -0,0 +1,58 @@
+package com.mogo.module.guide.guide
+
+import com.mogo.commons.debug.DebugConfig
+import com.mogo.commons.mvp.IView
+import com.mogo.commons.mvp.MvpFragment
+import com.mogo.commons.mvp.Presenter
+import com.mogo.commons.voice.IMogoVoiceCmdCallBack
+import com.mogo.module.guide.R
+import com.mogo.module.guide.fragment.GuideFragment
+import com.mogo.module.guide.util.breakOffSpeak
+import com.mogo.module.guide.util.speak
+import kotlinx.android.synthetic.main.module_guide_item_stage_three.*
+import kotlinx.android.synthetic.main.module_guide_item_stage_two.*
+
+class GuideStageThreeFragment : MvpFragment> {
+
+ private var containerFragment: GuideFragment? = null
+
+ constructor(containerFragment: GuideFragment) {
+ this.containerFragment = containerFragment
+ }
+
+ override fun getLayoutId(): Int {
+ return R.layout.module_guide_item_stage_three
+ }
+
+ override fun createPresenter(): Presenter {
+ return GuideOnLineCarPresenter(this)
+ }
+
+ override fun initViews() {
+ if(!DebugConfig.isLauncher()){
+ @Suppress("DEPRECATION")
+ moduleGuidePageThree.background = context!!.resources!!.getDrawable(R.mipmap.module_guide_item_stage_three)
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ containerFragment?.visibleLeft()
+ containerFragment?.visibleRight()
+ breakOffSpeak(context!!)
+ speak(context!!, context!!.resources.getString(R.string.module_guide_voice_page_three), object : IMogoVoiceCmdCallBack {
+ override fun onSpeakEnd(speakText: String?) {
+ if(!isVisible){
+ return
+ }
+ containerFragment?.moveToNext()
+ }
+ })
+ }
+
+ class GuideOnLineCarPresenter : Presenter {
+
+ constructor(view: IView?) : super(view)
+ }
+
+}
diff --git a/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/guide/GuideStageTwoFragment.kt b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/guide/GuideStageTwoFragment.kt
new file mode 100644
index 0000000000..37e7a8d29a
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/guide/GuideStageTwoFragment.kt
@@ -0,0 +1,58 @@
+package com.mogo.module.guide.guide
+
+import com.mogo.commons.debug.DebugConfig
+import com.mogo.commons.mvp.IView
+import com.mogo.commons.mvp.MvpFragment
+import com.mogo.commons.mvp.Presenter
+import com.mogo.commons.voice.IMogoVoiceCmdCallBack
+import com.mogo.module.guide.R
+import com.mogo.module.guide.fragment.GuideFragment
+import com.mogo.module.guide.util.breakOffSpeak
+import com.mogo.module.guide.util.speak
+import kotlinx.android.synthetic.main.module_guide_item_stage_one.*
+import kotlinx.android.synthetic.main.module_guide_item_stage_two.*
+
+class GuideStageTwoFragment : MvpFragment> {
+
+ private var containerFragment: GuideFragment? = null
+
+ constructor(containerFragment: GuideFragment) {
+ this.containerFragment = containerFragment
+ }
+
+ override fun getLayoutId(): Int {
+ return R.layout.module_guide_item_stage_two
+ }
+
+ override fun createPresenter(): Presenter {
+ return GuideCardPresenter(this)
+ }
+
+ override fun initViews() {
+ if(!DebugConfig.isLauncher()){
+ @Suppress("DEPRECATION")
+ moduleGuidePageTwo.background = context!!.resources!!.getDrawable(R.mipmap.module_guide_item_stage_two)
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ containerFragment?.visibleLeft()
+ containerFragment?.visibleRight()
+ breakOffSpeak(context!!)
+ speak(context!!, context!!.resources.getString(R.string.module_guide_voice_page_two), object : IMogoVoiceCmdCallBack {
+ override fun onSpeakEnd(speakText: String?) {
+ if(!isVisible){
+ return
+ }
+ containerFragment?.moveToNext()
+ }
+ })
+ }
+
+ class GuideCardPresenter : Presenter {
+
+ constructor(view: IView?) : super(view)
+ }
+
+}
diff --git a/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/util/AnalyticsUtil.kt b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/util/AnalyticsUtil.kt
new file mode 100644
index 0000000000..c5b94fcb41
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/util/AnalyticsUtil.kt
@@ -0,0 +1,25 @@
+package com.mogo.module.guide.util
+
+import com.alibaba.android.arouter.launcher.ARouter
+import com.mogo.service.IMogoServiceApis
+import com.mogo.service.MogoServicePaths
+import com.mogo.service.analytics.IMogoAnalytics
+
+object AnalyticsUtil {
+
+ const val INVOKE_TRACK_PLAY_PASS_ID = "v2x_play_pass"
+ const val INVOKE_TRACK_PASS_TIME = "pass_time"
+ const val INVOKE_TRACK_PLAY_TIME = "play_time"
+
+ private var trackRouter: IMogoAnalytics? = null
+
+ fun track(eventType: String, data: MutableMap? = hashMapOf()) {
+ if (trackRouter == null) {
+ val arouter = ARouter.getInstance().build(MogoServicePaths.PATH_SERVICE_APIS).navigation()
+ if (arouter is IMogoServiceApis) {
+ trackRouter = arouter.analyticsApi
+ }
+ }
+ trackRouter!!.track(eventType, data)
+ }
+}
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/util/SharedPreferenceUtil.kt b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/util/SharedPreferenceUtil.kt
new file mode 100644
index 0000000000..ee0b39edb3
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/util/SharedPreferenceUtil.kt
@@ -0,0 +1,22 @@
+package com.mogo.module.guide.util
+
+import com.mogo.commons.AbsMogoApplication
+import com.mogo.module.common.utils.SPConst.getSPGuideRecord
+import com.mogo.module.common.utils.SPConst.getSpGuide
+import com.mogo.utils.storage.SharedPrefsMgr
+
+object SharedPreferenceUtil {
+
+ fun hasGuide(): Boolean {
+ return SharedPrefsMgr.getInstance(AbsMogoApplication.getApp()).getBoolean(getSpGuide(), false)
+ }
+
+ fun setGuideFinish() {
+ SharedPrefsMgr.getInstance(AbsMogoApplication.getApp()).putBoolean(getSpGuide(), true)
+ }
+
+ fun setGuideRecord() {
+ SharedPrefsMgr.getInstance(AbsMogoApplication.getApp()).putLong(getSPGuideRecord(), System.currentTimeMillis())
+ }
+
+}
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/util/VoiceUtil.kt b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/util/VoiceUtil.kt
new file mode 100644
index 0000000000..b4d728f82e
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/java/com/mogo/module/guide/util/VoiceUtil.kt
@@ -0,0 +1,14 @@
+package com.mogo.module.guide.util
+
+import android.content.Context
+import com.mogo.commons.voice.AIAssist
+import com.mogo.commons.voice.IMogoVoiceCmdCallBack
+import com.mogo.commons.voice.VoicePreemptType
+
+fun speak(context: Context, text: String, callBack: IMogoVoiceCmdCallBack?) {
+ AIAssist.getInstance(context).speakTTSVoice(text, VoicePreemptType.PREEMPT_TYPE_IMMEADIATELY, callBack)
+}
+
+fun breakOffSpeak(context: Context){
+ AIAssist.getInstance(context).breakOffSpeak()
+}
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/res/drawable/module_guide_blue_corner.xml b/modules/mogo-module-guide/src/main/res/drawable/module_guide_blue_corner.xml
new file mode 100644
index 0000000000..c21deebfbf
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/res/drawable/module_guide_blue_corner.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/res/layout/module_guide_fragment.xml b/modules/mogo-module-guide/src/main/res/layout/module_guide_fragment.xml
new file mode 100644
index 0000000000..c0ab9b03e5
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/res/layout/module_guide_fragment.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/res/layout/module_guide_item_include.xml b/modules/mogo-module-guide/src/main/res/layout/module_guide_item_include.xml
new file mode 100644
index 0000000000..c170a9db8c
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/res/layout/module_guide_item_include.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/res/layout/module_guide_item_stage_five.xml b/modules/mogo-module-guide/src/main/res/layout/module_guide_item_stage_five.xml
new file mode 100644
index 0000000000..a7842257a8
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/res/layout/module_guide_item_stage_five.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/res/layout/module_guide_item_stage_four.xml b/modules/mogo-module-guide/src/main/res/layout/module_guide_item_stage_four.xml
new file mode 100644
index 0000000000..a0a61c5541
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/res/layout/module_guide_item_stage_four.xml
@@ -0,0 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/res/layout/module_guide_item_stage_one.xml b/modules/mogo-module-guide/src/main/res/layout/module_guide_item_stage_one.xml
new file mode 100644
index 0000000000..217f6c1c9c
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/res/layout/module_guide_item_stage_one.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/res/layout/module_guide_item_stage_three.xml b/modules/mogo-module-guide/src/main/res/layout/module_guide_item_stage_three.xml
new file mode 100644
index 0000000000..7721a4fde7
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/res/layout/module_guide_item_stage_three.xml
@@ -0,0 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/res/layout/module_guide_item_stage_two.xml b/modules/mogo-module-guide/src/main/res/layout/module_guide_item_stage_two.xml
new file mode 100644
index 0000000000..4c79d09447
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/res/layout/module_guide_item_stage_two.xml
@@ -0,0 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_item_stage_five.png b/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_item_stage_five.png
new file mode 100644
index 0000000000..fcd22618a3
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_item_stage_five.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_item_stage_four.png b/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_item_stage_four.png
new file mode 100644
index 0000000000..d6fc96f989
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_item_stage_four.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_item_stage_one.png b/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_item_stage_one.png
new file mode 100644
index 0000000000..2690abb302
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_item_stage_one.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_item_stage_three.png b/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_item_stage_three.png
new file mode 100644
index 0000000000..b849869d20
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_item_stage_three.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_item_stage_two.png b/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_item_stage_two.png
new file mode 100644
index 0000000000..dc2840a228
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_item_stage_two.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_left_page.png b/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_left_page.png
new file mode 100644
index 0000000000..da94ba4a48
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_left_page.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_right_page.png b/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_right_page.png
new file mode 100644
index 0000000000..f25becf47a
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-ldpi/module_guide_right_page.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_item_stage_five_launcher.png b/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_item_stage_five_launcher.png
new file mode 100644
index 0000000000..e027bb55bb
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_item_stage_five_launcher.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_item_stage_four_launcher.png b/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_item_stage_four_launcher.png
new file mode 100644
index 0000000000..e7be0d312e
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_item_stage_four_launcher.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_item_stage_one_launcher.png b/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_item_stage_one_launcher.png
new file mode 100644
index 0000000000..14cd567ad0
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_item_stage_one_launcher.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_item_stage_three_launcher.png b/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_item_stage_three_launcher.png
new file mode 100644
index 0000000000..94fdf82256
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_item_stage_three_launcher.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_item_stage_two_launcher.png b/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_item_stage_two_launcher.png
new file mode 100644
index 0000000000..8b8861a012
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_item_stage_two_launcher.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_left_page.png b/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_left_page.png
new file mode 100644
index 0000000000..a79e3d796c
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_left_page.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_right_page.png b/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_right_page.png
new file mode 100644
index 0000000000..07fed27927
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-mdpi/module_guide_right_page.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_item_stage_five_launcher.png b/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_item_stage_five_launcher.png
new file mode 100644
index 0000000000..61a3e015dc
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_item_stage_five_launcher.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_item_stage_four_launcher.png b/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_item_stage_four_launcher.png
new file mode 100644
index 0000000000..7153f0b341
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_item_stage_four_launcher.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_item_stage_one_launcher.png b/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_item_stage_one_launcher.png
new file mode 100644
index 0000000000..46a01e4a7a
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_item_stage_one_launcher.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_item_stage_three_launcher.png b/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_item_stage_three_launcher.png
new file mode 100644
index 0000000000..9e27ccecaa
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_item_stage_three_launcher.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_item_stage_two_launcher.png b/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_item_stage_two_launcher.png
new file mode 100644
index 0000000000..6a29d13093
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_item_stage_two_launcher.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_left_page.png b/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_left_page.png
new file mode 100644
index 0000000000..98ca2cb6df
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_left_page.png differ
diff --git a/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_right_page.png b/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_right_page.png
new file mode 100644
index 0000000000..f476cfc2dc
Binary files /dev/null and b/modules/mogo-module-guide/src/main/res/mipmap-xhdpi/module_guide_right_page.png differ
diff --git a/modules/mogo-module-guide/src/main/res/values-xhdpi-v4/dimens.xml b/modules/mogo-module-guide/src/main/res/values-xhdpi-v4/dimens.xml
new file mode 100644
index 0000000000..d56caf71d6
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/res/values-xhdpi-v4/dimens.xml
@@ -0,0 +1,1054 @@
+
+
+
+
+
+ -60px
+ -30px
+ -20px
+ -12px
+ -10px
+ -8px
+ -5px
+ -2px
+ -1px
+ 0px
+ 0.1px
+ 0.5px
+ 1px
+ 1.5px
+ 2px
+ 2.5px
+ 3px
+ 3.5px
+ 4px
+ 4.5px
+ 5px
+ 6px
+ 7px
+ 7.5px
+ 8px
+ 9px
+ 10px
+ 11px
+ 12px
+ 13px
+ 14px
+ 15px
+ 16px
+ 17px
+ 18px
+ 19px
+ 20px
+ 21px
+ 22px
+ 23px
+ 24px
+ 25px
+ 26px
+ 27px
+ 28px
+ 29px
+ 30px
+ 31px
+ 32px
+ 33px
+ 34px
+ 35px
+ 36px
+ 37px
+ 38px
+ 39px
+ 40px
+ 41px
+ 42px
+ 43px
+ 44px
+ 45px
+ 46px
+ 47px
+ 48px
+ 49px
+ 50px
+ 51px
+ 52px
+ 53px
+ 54px
+ 55px
+ 56px
+ 57px
+ 58px
+ 59px
+ 60px
+ 61px
+ 62px
+ 63px
+ 64px
+ 65px
+ 66px
+ 67px
+ 68px
+ 69px
+ 70px
+ 71px
+ 72px
+ 73px
+ 74px
+ 75px
+ 76px
+ 77px
+ 78px
+ 79px
+ 80px
+ 81px
+ 82px
+ 83px
+ 84px
+ 85px
+ 86px
+ 87px
+ 88px
+ 89px
+ 90px
+ 91px
+ 92px
+ 93px
+ 94px
+ 95px
+ 96px
+ 97px
+ 98px
+ 99px
+ 100px
+ 101px
+ 102px
+ 103px
+ 104px
+ 104.5px
+ 105px
+ 106px
+ 107px
+ 108px
+ 109px
+ 110px
+ 111px
+ 112px
+ 113px
+ 114px
+ 115px
+ 116px
+ 117px
+ 118px
+ 119px
+ 120px
+ 121px
+ 122px
+ 123px
+ 124px
+ 125px
+ 126px
+ 127px
+ 128px
+ 129px
+ 130px
+ 131px
+ 132px
+ 133px
+ 134px
+ 134.5px
+ 135px
+ 136px
+ 137px
+ 138px
+ 139px
+ 140px
+ 141px
+ 142px
+ 143px
+ 144px
+ 145px
+ 146px
+ 147px
+ 148px
+ 149px
+ 150px
+ 151px
+ 152px
+ 153px
+ 154px
+ 155px
+ 156px
+ 157px
+ 158px
+ 159px
+ 160px
+ 161px
+ 162px
+ 163px
+ 164px
+ 165px
+ 166px
+ 167px
+ 168px
+ 169px
+ 170px
+ 171px
+ 172px
+ 173px
+ 174px
+ 175px
+ 176px
+ 177px
+ 178px
+ 179px
+ 180px
+ 181px
+ 182px
+ 183px
+ 184px
+ 185px
+ 186px
+ 187px
+ 188px
+ 189px
+ 190px
+ 191px
+ 191.25px
+ 192px
+ 193px
+ 194px
+ 195px
+ 196px
+ 197px
+ 198px
+ 199px
+ 200px
+ 201px
+ 202px
+ 203px
+ 204px
+ 205px
+ 206px
+ 207px
+ 208px
+ 209px
+ 210px
+ 211px
+ 212px
+ 213px
+ 214px
+ 215px
+ 216px
+ 217px
+ 218px
+ 219px
+ 220px
+ 221px
+ 222px
+ 223px
+ 224px
+ 225px
+ 226px
+ 227px
+ 228px
+ 229px
+ 230px
+ 231px
+ 232px
+ 233px
+ 234px
+ 235px
+ 236px
+ 237px
+ 238px
+ 239px
+ 240px
+ 241px
+ 242px
+ 243px
+ 244px
+ 245px
+ 246px
+ 247px
+ 248px
+ 249px
+ 250px
+ 251px
+ 252px
+ 253px
+ 254px
+ 255px
+ 256px
+ 257px
+ 258px
+ 259px
+ 260px
+ 261px
+ 262px
+ 263px
+ 264px
+ 265px
+ 266px
+ 267px
+ 268px
+ 269px
+ 270px
+ 271px
+ 272px
+ 273px
+ 274px
+ 275px
+ 276px
+ 277px
+ 278px
+ 279px
+ 280px
+ 281px
+ 282px
+ 283px
+ 284px
+ 285px
+ 286px
+ 287px
+ 288px
+ 289px
+ 290px
+ 291px
+ 292px
+ 293px
+ 294px
+ 295px
+ 296px
+ 297px
+ 298px
+ 299px
+ 300px
+ 301px
+ 302px
+ 303px
+ 304px
+ 305px
+ 306px
+ 307px
+ 308px
+ 309px
+ 310px
+ 311px
+ 312px
+ 313px
+ 314px
+ 315px
+ 316px
+ 317px
+ 318px
+ 319px
+ 320px
+ 321px
+ 322px
+ 323px
+ 324px
+ 325px
+ 326px
+ 327px
+ 328px
+ 329px
+ 330px
+ 331px
+ 332px
+ 333px
+ 334px
+ 335px
+ 336px
+ 337px
+ 338px
+ 339px
+ 340px
+ 341px
+ 342px
+ 343px
+ 344px
+ 345px
+ 346px
+ 347px
+ 348px
+ 349px
+ 350px
+ 351px
+ 352px
+ 353px
+ 354px
+ 355px
+ 356px
+ 357px
+ 358px
+ 359px
+ 366px
+ 367px
+ 368px
+ 369px
+ 370px
+ 371px
+ 372px
+ 373px
+ 374px
+ 375px
+ 376px
+ 377px
+ 378px
+ 379px
+ 380px
+ 381px
+ 382px
+ 383px
+ 384px
+ 385px
+ 386px
+ 387px
+ 388px
+ 389px
+ 390px
+ 391px
+ 392px
+ 393px
+ 394px
+ 395px
+ 396px
+ 397px
+ 398px
+ 399px
+ 400px
+ 401px
+ 402px
+ 403px
+ 404px
+ 405px
+ 406px
+ 407px
+ 408px
+ 409px
+ 410px
+ 411px
+ 412px
+ 413px
+ 414px
+ 415px
+ 416px
+ 417px
+ 418px
+ 419px
+ 420px
+ 421px
+ 422px
+ 423px
+ 424px
+ 425px
+ 426px
+ 427px
+ 428px
+ 429px
+ 430px
+ 431px
+ 432px
+ 433px
+ 434px
+ 435px
+ 436px
+ 437px
+ 438px
+ 439px
+ 440px
+ 441px
+ 442px
+ 443px
+ 444px
+ 445px
+ 446px
+ 447px
+ 448px
+ 449px
+ 450px
+ 451px
+ 452px
+ 453px
+ 454px
+ 455px
+ 456px
+ 457px
+ 458px
+ 459px
+ 460px
+ 461px
+ 462px
+ 463px
+ 464px
+ 465px
+ 466px
+ 467px
+ 468px
+ 469px
+ 470px
+ 471px
+ 472px
+ 473px
+ 474px
+ 475px
+ 476px
+ 477px
+ 478px
+ 479px
+ 480px
+ 481px
+ 482px
+ 483px
+ 484px
+ 485px
+ 486px
+ 487px
+ 488px
+ 489px
+ 490px
+ 491px
+ 492px
+ 493px
+ 494px
+ 495px
+ 496px
+ 497px
+ 498px
+ 499px
+ 500px
+ 501px
+ 502px
+ 503px
+ 504px
+ 505px
+ 506px
+ 507px
+ 508px
+ 509px
+ 510px
+ 511px
+ 512px
+ 513px
+ 514px
+ 515px
+ 516px
+ 517px
+ 518px
+ 519px
+ 520px
+ 521px
+ 522px
+ 523px
+ 524px
+ 525px
+ 526px
+ 527px
+ 528px
+ 529px
+ 530px
+ 531px
+ 532px
+ 533px
+ 534px
+ 535px
+ 536px
+ 537px
+ 538px
+ 539px
+ 540px
+ 541px
+ 542px
+ 543px
+ 544px
+ 545px
+ 546px
+ 547px
+ 548px
+ 549px
+ 550px
+ 551px
+ 552px
+ 553px
+ 554px
+ 555px
+ 556px
+ 557px
+ 558px
+ 559px
+ 560px
+ 561px
+ 562px
+ 563px
+ 564px
+ 565px
+ 566px
+ 567px
+ 568px
+ 569px
+ 570px
+ 571px
+ 572px
+ 573px
+ 574px
+ 575px
+ 576px
+ 577px
+ 578px
+ 579px
+ 580px
+ 581px
+ 582px
+ 583px
+ 584px
+ 585px
+ 586px
+ 587px
+ 588px
+ 589px
+ 590px
+ 591px
+ 592px
+ 593px
+ 594px
+ 595px
+ 596px
+ 597px
+ 598px
+ 599px
+ 600px
+ 601px
+ 602px
+ 603px
+ 604px
+ 605px
+ 606px
+ 607px
+ 608px
+ 609px
+ 610px
+ 611px
+ 612px
+ 613px
+ 614px
+ 615px
+ 616px
+ 617px
+ 618px
+ 619px
+ 620px
+ 621px
+ 622px
+ 623px
+ 624px
+ 625px
+ 626px
+ 627px
+ 628px
+ 629px
+ 630px
+ 631px
+ 632px
+ 633px
+ 634px
+ 635px
+ 636px
+ 637px
+ 638px
+ 639px
+ 640px
+ 641px
+ 642px
+ 643px
+ 644px
+ 645px
+ 646px
+ 647px
+ 648px
+ 649px
+ 650px
+ 651px
+ 652px
+ 653px
+ 654px
+ 655px
+ 656px
+ 657px
+ 658px
+ 659px
+ 660px
+ 661px
+ 662px
+ 663px
+ 664px
+ 665px
+ 666px
+ 667px
+ 668px
+ 669px
+ 670px
+ 671px
+ 672px
+ 673px
+ 674px
+ 675px
+ 676px
+ 677px
+ 678px
+ 679px
+ 680px
+ 681px
+ 682px
+ 683px
+ 684px
+ 685px
+ 686px
+ 687px
+ 688px
+ 689px
+ 690px
+ 691px
+ 692px
+ 693px
+ 694px
+ 695px
+ 696px
+ 697px
+ 698px
+ 699px
+ 700px
+ 701px
+ 702px
+ 703px
+ 704px
+ 705px
+ 706px
+ 707px
+ 708px
+ 709px
+ 710px
+ 711px
+ 712px
+ 713px
+ 714px
+ 715px
+ 716px
+ 717px
+ 718px
+ 719px
+ 720px
+ 721px
+ 722px
+ 723px
+ 724px
+ 725px
+ 726px
+ 727px
+ 728px
+ 729px
+ 730px
+ 731px
+ 732px
+ 733px
+ 734px
+ 735px
+ 736px
+ 737px
+ 738px
+ 739px
+ 740px
+ 741px
+ 742px
+ 743px
+ 744px
+ 745px
+ 746px
+ 747px
+ 748px
+ 749px
+ 750px
+ 751px
+ 752px
+ 753px
+ 754px
+ 755px
+ 756px
+ 757px
+ 758px
+ 759px
+ 760px
+ 761px
+ 762px
+ 763px
+ 764px
+ 765px
+ 766px
+ 767px
+ 768px
+ 769px
+ 770px
+ 771px
+ 772px
+ 773px
+ 774px
+ 775px
+ 776px
+ 777px
+ 778px
+ 779px
+ 780px
+ 781px
+ 782px
+ 783px
+ 784px
+ 785px
+ 786px
+ 787px
+ 788px
+ 789px
+ 790px
+ 791px
+ 792px
+ 793px
+ 794px
+ 795px
+ 796px
+ 797px
+ 798px
+ 799px
+ 800px
+ 801px
+ 802px
+ 803px
+ 804px
+ 805px
+ 806px
+ 807px
+ 808px
+ 809px
+ 810px
+ 811px
+ 812px
+ 813px
+ 814px
+ 815px
+ 816px
+ 817px
+ 818px
+ 819px
+ 820px
+ 821px
+ 822px
+ 823px
+ 824px
+ 825px
+ 826px
+ 827px
+ 828px
+ 829px
+ 830px
+ 831px
+ 832px
+ 833px
+ 834px
+ 835px
+ 836px
+ 837px
+ 838px
+ 839px
+ 840px
+ 841px
+ 842px
+ 843px
+ 844px
+ 845px
+ 846px
+ 847px
+ 848px
+ 849px
+ 850px
+ 851px
+ 852px
+ 853px
+ 854px
+ 855px
+ 856px
+ 857px
+ 858px
+ 859px
+ 860px
+ 861px
+ 862px
+ 863px
+ 864px
+ 865px
+ 866px
+ 867px
+ 868px
+ 869px
+ 870px
+ 871px
+ 872px
+ 873px
+ 874px
+ 875px
+ 876px
+ 877px
+ 878px
+ 879px
+ 880px
+ 881px
+ 882px
+ 883px
+ 884px
+ 885px
+ 886px
+ 887px
+ 888px
+ 889px
+ 890px
+ 891px
+ 892px
+ 893px
+ 894px
+ 895px
+ 896px
+ 897px
+ 898px
+ 899px
+ 900px
+ 901px
+ 902px
+ 903px
+ 904px
+ 905px
+ 906px
+ 907px
+ 908px
+ 909px
+ 910px
+ 911px
+ 912px
+ 913px
+ 914px
+ 915px
+ 916px
+ 917px
+ 918px
+ 919px
+ 920px
+ 921px
+ 922px
+ 923px
+ 924px
+ 925px
+ 926px
+ 927px
+ 928px
+ 929px
+ 930px
+ 931px
+ 932px
+ 933px
+ 934px
+ 935px
+ 936px
+ 937px
+ 938px
+ 939px
+ 940px
+ 941px
+ 942px
+ 943px
+ 944px
+ 945px
+ 946px
+ 947px
+ 948px
+ 949px
+ 950px
+ 951px
+ 952px
+ 953px
+ 954px
+ 955px
+ 956px
+ 957px
+ 958px
+ 959px
+ 960px
+ 961px
+ 962px
+ 963px
+ 964px
+ 965px
+ 966px
+ 967px
+ 968px
+ 969px
+ 970px
+ 971px
+ 972px
+ 973px
+ 974px
+ 975px
+ 976px
+ 977px
+ 978px
+ 979px
+ 980px
+ 981px
+ 982px
+ 983px
+ 984px
+ 985px
+ 986px
+ 987px
+ 988px
+ 989px
+ 990px
+ 991px
+ 992px
+ 993px
+ 994px
+ 995px
+ 996px
+ 997px
+ 998px
+ 999px
+ 1300px
+
+
+
+
+ 6px
+ 7px
+ 8px
+ 9px
+ 10px
+ 11px
+ 12px
+ 13px
+ 14px
+ 15px
+ 16px
+ 17px
+ 18px
+ 19px
+ 20px
+ 21px
+ 22px
+ 23px
+ 24px
+ 25px
+ 28px
+ 30px
+ 32px
+ 34px
+ 36px
+ 38px
+ 40px
+ 42px
+ 48px
+
+
diff --git a/modules/mogo-module-guide/src/main/res/values/color.xml b/modules/mogo-module-guide/src/main/res/values/color.xml
new file mode 100644
index 0000000000..5405f26c5a
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/res/values/color.xml
@@ -0,0 +1,6 @@
+
+
+ #3B91FF
+ #33ffffff
+ #ffffff
+
\ No newline at end of file
diff --git a/modules/mogo-module-guide/src/main/res/values/dimens.xml b/modules/mogo-module-guide/src/main/res/values/dimens.xml
new file mode 100644
index 0000000000..86faec4c01
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/res/values/dimens.xml
@@ -0,0 +1,1046 @@
+
+
+ -32.8125px
+ -16.4062px
+ -10.9375px
+ -6.5625px
+ -5.4688px
+ -4.3750px
+ -2.7344px
+ -1.0938px
+ -0.5469px
+ 0.0000px
+ 0.0547px
+ 0.2734px
+ 0.5469px
+ 0.8203px
+ 1.0938px
+ 1.3672px
+ 1.6406px
+ 1.9141px
+ 2.1875px
+ 2.4609px
+ 2.7344px
+ 3.2812px
+ 3.8281px
+ 4.1016px
+ 4.3750px
+ 4.9219px
+ 5.4688px
+ 6.0156px
+ 6.5625px
+ 7.1094px
+ 7.6562px
+ 8.2031px
+ 8.7500px
+ 9.2969px
+ 9.8438px
+ 10.3906px
+ 10.9375px
+ 11.4844px
+ 12.0312px
+ 12.5781px
+ 13.1250px
+ 13.6719px
+ 14.2188px
+ 14.7656px
+ 15.3125px
+ 15.8594px
+ 16.4062px
+ 16.9531px
+ 17.5000px
+ 18.0469px
+ 18.5938px
+ 19.1406px
+ 19.6875px
+ 20.2344px
+ 20.7812px
+ 21.3281px
+ 21.8750px
+ 22.4219px
+ 22.9688px
+ 23.5156px
+ 24.0625px
+ 24.6094px
+ 25.1562px
+ 25.7031px
+ 26.2500px
+ 26.7969px
+ 27.3438px
+ 27.8906px
+ 28.4375px
+ 28.9844px
+ 29.5312px
+ 30.0781px
+ 30.6250px
+ 31.1719px
+ 31.7188px
+ 32.2656px
+ 32.8125px
+ 33.3594px
+ 33.9062px
+ 34.4531px
+ 35.0000px
+ 35.5469px
+ 36.0938px
+ 36.6406px
+ 37.1875px
+ 37.7344px
+ 38.2812px
+ 38.8281px
+ 39.3750px
+ 39.9219px
+ 40.4688px
+ 41.0156px
+ 41.5625px
+ 42.1094px
+ 42.6562px
+ 43.2031px
+ 43.7500px
+ 44.2969px
+ 44.8438px
+ 45.3906px
+ 45.9375px
+ 46.4844px
+ 47.0312px
+ 47.5781px
+ 48.1250px
+ 48.6719px
+ 49.2188px
+ 49.7656px
+ 50.3125px
+ 50.8594px
+ 51.4062px
+ 51.9531px
+ 52.5000px
+ 53.0469px
+ 53.5938px
+ 54.1406px
+ 54.6875px
+ 55.2344px
+ 55.7812px
+ 56.3281px
+ 56.8750px
+ 57.1484px
+ 57.4219px
+ 57.9688px
+ 58.5156px
+ 59.0625px
+ 59.6094px
+ 60.1562px
+ 60.7031px
+ 61.2500px
+ 61.7969px
+ 62.3438px
+ 62.8906px
+ 63.4375px
+ 63.9844px
+ 64.5312px
+ 65.0781px
+ 65.6250px
+ 66.1719px
+ 66.7188px
+ 67.2656px
+ 67.8125px
+ 68.3594px
+ 68.9062px
+ 69.4531px
+ 70.0000px
+ 70.5469px
+ 71.0938px
+ 71.6406px
+ 72.1875px
+ 72.7344px
+ 73.2812px
+ 73.5547px
+ 73.8281px
+ 74.3750px
+ 74.9219px
+ 75.4688px
+ 76.0156px
+ 76.5625px
+ 77.1094px
+ 77.6562px
+ 78.2031px
+ 78.7500px
+ 79.2969px
+ 79.8438px
+ 80.3906px
+ 80.9375px
+ 81.4844px
+ 82.0312px
+ 82.5781px
+ 83.1250px
+ 83.6719px
+ 84.2188px
+ 84.7656px
+ 85.3125px
+ 85.8594px
+ 86.4062px
+ 86.9531px
+ 87.5000px
+ 88.0469px
+ 88.5938px
+ 89.1406px
+ 89.6875px
+ 90.2344px
+ 90.7812px
+ 91.3281px
+ 91.8750px
+ 92.4219px
+ 92.9688px
+ 93.5156px
+ 94.0625px
+ 94.6094px
+ 95.1562px
+ 95.7031px
+ 96.2500px
+ 96.7969px
+ 97.3438px
+ 97.8906px
+ 98.4375px
+ 98.9844px
+ 99.5312px
+ 100.0781px
+ 100.6250px
+ 101.1719px
+ 101.7188px
+ 102.2656px
+ 102.8125px
+ 103.3594px
+ 103.9062px
+ 104.4531px
+ 104.5898px
+ 105.0000px
+ 105.5469px
+ 106.0938px
+ 106.6406px
+ 107.1875px
+ 107.7344px
+ 108.2812px
+ 108.8281px
+ 109.3750px
+ 109.9219px
+ 110.4688px
+ 111.0156px
+ 111.5625px
+ 112.1094px
+ 112.6562px
+ 113.2031px
+ 113.7500px
+ 114.2969px
+ 114.8438px
+ 115.3906px
+ 115.9375px
+ 116.4844px
+ 117.0312px
+ 117.5781px
+ 118.1250px
+ 118.6719px
+ 119.2188px
+ 119.7656px
+ 120.3125px
+ 120.8594px
+ 121.4062px
+ 121.9531px
+ 122.5000px
+ 123.0469px
+ 123.5938px
+ 124.1406px
+ 124.6875px
+ 125.2344px
+ 125.7812px
+ 126.3281px
+ 126.8750px
+ 127.4219px
+ 127.9688px
+ 128.5156px
+ 129.0625px
+ 129.6094px
+ 130.1562px
+ 130.7031px
+ 131.2500px
+ 131.7969px
+ 132.3438px
+ 132.8906px
+ 133.4375px
+ 133.9844px
+ 134.5312px
+ 135.0781px
+ 135.6250px
+ 136.1719px
+ 136.7188px
+ 137.2656px
+ 137.8125px
+ 138.3594px
+ 138.9062px
+ 139.4531px
+ 140.0000px
+ 140.5469px
+ 141.0938px
+ 141.6406px
+ 142.1875px
+ 142.7344px
+ 143.2812px
+ 143.8281px
+ 144.3750px
+ 144.9219px
+ 145.4688px
+ 146.0156px
+ 146.5625px
+ 147.1094px
+ 147.6562px
+ 148.2031px
+ 148.7500px
+ 149.2969px
+ 149.8438px
+ 150.3906px
+ 150.9375px
+ 151.4844px
+ 152.0312px
+ 152.5781px
+ 153.1250px
+ 153.6719px
+ 154.2188px
+ 154.7656px
+ 155.3125px
+ 155.8594px
+ 156.4062px
+ 156.9531px
+ 157.5000px
+ 158.0469px
+ 158.5938px
+ 159.1406px
+ 159.6875px
+ 160.2344px
+ 160.7812px
+ 161.3281px
+ 161.8750px
+ 162.4219px
+ 162.9688px
+ 163.5156px
+ 164.0625px
+ 164.6094px
+ 165.1562px
+ 165.7031px
+ 166.2500px
+ 166.7969px
+ 167.3438px
+ 167.8906px
+ 168.4375px
+ 168.9844px
+ 169.5312px
+ 170.0781px
+ 170.6250px
+ 171.1719px
+ 171.7188px
+ 172.2656px
+ 172.8125px
+ 173.3594px
+ 173.9062px
+ 174.4531px
+ 175.0000px
+ 175.5469px
+ 176.0938px
+ 176.6406px
+ 177.1875px
+ 177.7344px
+ 178.2812px
+ 178.8281px
+ 179.3750px
+ 179.9219px
+ 180.4688px
+ 181.0156px
+ 181.5625px
+ 182.1094px
+ 182.6562px
+ 183.2031px
+ 183.7500px
+ 184.2969px
+ 184.8438px
+ 185.3906px
+ 185.9375px
+ 186.4844px
+ 187.0312px
+ 187.5781px
+ 188.1250px
+ 188.6719px
+ 189.2188px
+ 189.7656px
+ 190.3125px
+ 190.8594px
+ 191.4062px
+ 191.9531px
+ 192.5000px
+ 193.0469px
+ 193.5938px
+ 194.1406px
+ 194.6875px
+ 195.2344px
+ 195.7812px
+ 196.3281px
+ 200.1562px
+ 200.7031px
+ 201.2500px
+ 201.7969px
+ 202.3438px
+ 202.8906px
+ 203.4375px
+ 203.9844px
+ 204.5312px
+ 205.0781px
+ 205.6250px
+ 206.1719px
+ 206.7188px
+ 207.2656px
+ 207.8125px
+ 208.3594px
+ 208.9062px
+ 209.4531px
+ 210.0000px
+ 210.5469px
+ 211.0938px
+ 211.6406px
+ 212.1875px
+ 212.7344px
+ 213.2812px
+ 213.8281px
+ 214.3750px
+ 214.9219px
+ 215.4688px
+ 216.0156px
+ 216.5625px
+ 217.1094px
+ 217.6562px
+ 218.2031px
+ 218.7500px
+ 219.2969px
+ 219.8438px
+ 220.3906px
+ 220.9375px
+ 221.4844px
+ 222.0312px
+ 222.5781px
+ 223.1250px
+ 223.6719px
+ 224.2188px
+ 224.7656px
+ 225.3125px
+ 225.8594px
+ 226.4062px
+ 226.9531px
+ 227.5000px
+ 228.0469px
+ 228.5938px
+ 229.1406px
+ 229.6875px
+ 230.2344px
+ 230.7812px
+ 231.3281px
+ 231.8750px
+ 232.4219px
+ 232.9688px
+ 233.5156px
+ 234.0625px
+ 234.6094px
+ 235.1562px
+ 235.7031px
+ 236.2500px
+ 236.7969px
+ 237.3438px
+ 237.8906px
+ 238.4375px
+ 238.9844px
+ 239.5312px
+ 240.0781px
+ 240.6250px
+ 241.1719px
+ 241.7188px
+ 242.2656px
+ 242.8125px
+ 243.3594px
+ 243.9062px
+ 244.4531px
+ 245.0000px
+ 245.5469px
+ 246.0938px
+ 246.6406px
+ 247.1875px
+ 247.7344px
+ 248.2812px
+ 248.8281px
+ 249.3750px
+ 249.9219px
+ 250.4688px
+ 251.0156px
+ 251.5625px
+ 252.1094px
+ 252.6562px
+ 253.2031px
+ 253.7500px
+ 254.2969px
+ 254.8438px
+ 255.3906px
+ 255.9375px
+ 256.4844px
+ 257.0312px
+ 257.5781px
+ 258.1250px
+ 258.6719px
+ 259.2188px
+ 259.7656px
+ 260.3125px
+ 260.8594px
+ 261.4062px
+ 261.9531px
+ 262.5000px
+ 263.0469px
+ 263.5938px
+ 264.1406px
+ 264.6875px
+ 265.2344px
+ 265.7812px
+ 266.3281px
+ 266.8750px
+ 267.4219px
+ 267.9688px
+ 268.5156px
+ 269.0625px
+ 269.6094px
+ 270.1562px
+ 270.7031px
+ 271.2500px
+ 271.7969px
+ 272.3438px
+ 272.8906px
+ 273.4375px
+ 273.9844px
+ 274.5312px
+ 275.0781px
+ 275.6250px
+ 276.1719px
+ 276.7188px
+ 277.2656px
+ 277.8125px
+ 278.3594px
+ 278.9062px
+ 279.4531px
+ 280.0000px
+ 280.5469px
+ 281.0938px
+ 281.6406px
+ 282.1875px
+ 282.7344px
+ 283.2812px
+ 283.8281px
+ 284.3750px
+ 284.9219px
+ 285.4688px
+ 286.0156px
+ 286.5625px
+ 287.1094px
+ 287.6562px
+ 288.2031px
+ 288.7500px
+ 289.2969px
+ 289.8438px
+ 290.3906px
+ 290.9375px
+ 291.4844px
+ 292.0312px
+ 292.5781px
+ 293.1250px
+ 293.6719px
+ 294.2188px
+ 294.7656px
+ 295.3125px
+ 295.8594px
+ 296.4062px
+ 296.9531px
+ 297.5000px
+ 298.0469px
+ 298.5938px
+ 299.1406px
+ 299.6875px
+ 300.2344px
+ 300.7812px
+ 301.3281px
+ 301.8750px
+ 302.4219px
+ 302.9688px
+ 303.5156px
+ 304.0625px
+ 304.6094px
+ 305.1562px
+ 305.7031px
+ 306.2500px
+ 306.7969px
+ 307.3438px
+ 307.8906px
+ 308.4375px
+ 308.9844px
+ 309.5312px
+ 310.0781px
+ 310.6250px
+ 311.1719px
+ 311.7188px
+ 312.2656px
+ 312.8125px
+ 313.3594px
+ 313.9062px
+ 314.4531px
+ 315.0000px
+ 315.5469px
+ 316.0938px
+ 316.6406px
+ 317.1875px
+ 317.7344px
+ 318.2812px
+ 318.8281px
+ 319.3750px
+ 319.9219px
+ 320.4688px
+ 321.0156px
+ 321.5625px
+ 322.1094px
+ 322.6562px
+ 323.2031px
+ 323.7500px
+ 324.2969px
+ 324.8438px
+ 325.3906px
+ 325.9375px
+ 326.4844px
+ 327.0312px
+ 327.5781px
+ 328.1250px
+ 328.6719px
+ 329.2188px
+ 329.7656px
+ 330.3125px
+ 330.8594px
+ 331.4062px
+ 331.9531px
+ 332.5000px
+ 333.0469px
+ 333.5938px
+ 334.1406px
+ 334.6875px
+ 335.2344px
+ 335.7812px
+ 336.3281px
+ 336.8750px
+ 337.4219px
+ 337.9688px
+ 338.5156px
+ 339.0625px
+ 339.6094px
+ 340.1562px
+ 340.7031px
+ 341.2500px
+ 341.7969px
+ 342.3438px
+ 342.8906px
+ 343.4375px
+ 343.9844px
+ 344.5312px
+ 345.0781px
+ 345.6250px
+ 346.1719px
+ 346.7188px
+ 347.2656px
+ 347.8125px
+ 348.3594px
+ 348.9062px
+ 349.4531px
+ 350.0000px
+ 350.5469px
+ 351.0938px
+ 351.6406px
+ 352.1875px
+ 352.7344px
+ 353.2812px
+ 353.8281px
+ 354.3750px
+ 354.9219px
+ 355.4688px
+ 356.0156px
+ 356.5625px
+ 357.1094px
+ 357.6562px
+ 358.2031px
+ 358.7500px
+ 359.2969px
+ 359.8438px
+ 360.3906px
+ 360.9375px
+ 361.4844px
+ 362.0312px
+ 362.5781px
+ 363.1250px
+ 363.6719px
+ 364.2188px
+ 364.7656px
+ 365.3125px
+ 365.8594px
+ 366.4062px
+ 366.9531px
+ 367.5000px
+ 368.0469px
+ 368.5938px
+ 369.1406px
+ 369.6875px
+ 370.2344px
+ 370.7812px
+ 371.3281px
+ 371.8750px
+ 372.4219px
+ 372.9688px
+ 373.5156px
+ 374.0625px
+ 374.6094px
+ 375.1562px
+ 375.7031px
+ 376.2500px
+ 376.7969px
+ 377.3438px
+ 377.8906px
+ 378.4375px
+ 378.9844px
+ 379.5312px
+ 380.0781px
+ 380.6250px
+ 381.1719px
+ 381.7188px
+ 382.2656px
+ 382.8125px
+ 383.3594px
+ 383.9062px
+ 384.4531px
+ 385.0000px
+ 385.5469px
+ 386.0938px
+ 386.6406px
+ 387.1875px
+ 387.7344px
+ 388.2812px
+ 388.8281px
+ 389.3750px
+ 389.9219px
+ 390.4688px
+ 391.0156px
+ 391.5625px
+ 392.1094px
+ 392.6562px
+ 393.2031px
+ 393.7500px
+ 394.2969px
+ 394.8438px
+ 395.3906px
+ 395.9375px
+ 396.4844px
+ 397.0312px
+ 397.5781px
+ 398.1250px
+ 398.6719px
+ 399.2188px
+ 399.7656px
+ 400.3125px
+ 400.8594px
+ 401.4062px
+ 401.9531px
+ 402.5000px
+ 403.0469px
+ 403.5938px
+ 404.1406px
+ 404.6875px
+ 405.2344px
+ 405.7812px
+ 406.3281px
+ 406.8750px
+ 407.4219px
+ 407.9688px
+ 408.5156px
+ 409.0625px
+ 409.6094px
+ 410.1562px
+ 410.7031px
+ 411.2500px
+ 411.7969px
+ 412.3438px
+ 412.8906px
+ 413.4375px
+ 413.9844px
+ 414.5312px
+ 415.0781px
+ 415.6250px
+ 416.1719px
+ 416.7188px
+ 417.2656px
+ 417.8125px
+ 418.3594px
+ 418.9062px
+ 419.4531px
+ 420.0000px
+ 420.5469px
+ 421.0938px
+ 421.6406px
+ 422.1875px
+ 422.7344px
+ 423.2812px
+ 423.8281px
+ 424.3750px
+ 424.9219px
+ 425.4688px
+ 426.0156px
+ 426.5625px
+ 427.1094px
+ 427.6562px
+ 428.2031px
+ 428.7500px
+ 429.2969px
+ 429.8438px
+ 430.3906px
+ 430.9375px
+ 431.4844px
+ 432.0312px
+ 432.5781px
+ 433.1250px
+ 433.6719px
+ 434.2188px
+ 434.7656px
+ 435.3125px
+ 435.8594px
+ 436.4062px
+ 436.9531px
+ 437.5000px
+ 438.0469px
+ 438.5938px
+ 439.1406px
+ 439.6875px
+ 440.2344px
+ 440.7812px
+ 441.3281px
+ 441.8750px
+ 442.4219px
+ 442.9688px
+ 443.5156px
+ 444.0625px
+ 444.6094px
+ 445.1562px
+ 445.7031px
+ 446.2500px
+ 446.7969px
+ 447.3438px
+ 447.8906px
+ 448.4375px
+ 448.9844px
+ 449.5312px
+ 450.0781px
+ 450.6250px
+ 451.1719px
+ 451.7188px
+ 452.2656px
+ 452.8125px
+ 453.3594px
+ 453.9062px
+ 454.4531px
+ 455.0000px
+ 455.5469px
+ 456.0938px
+ 456.6406px
+ 457.1875px
+ 457.7344px
+ 458.2812px
+ 458.8281px
+ 459.3750px
+ 459.9219px
+ 460.4688px
+ 461.0156px
+ 461.5625px
+ 462.1094px
+ 462.6562px
+ 463.2031px
+ 463.7500px
+ 464.2969px
+ 464.8438px
+ 465.3906px
+ 465.9375px
+ 466.4844px
+ 467.0312px
+ 467.5781px
+ 468.1250px
+ 468.6719px
+ 469.2188px
+ 469.7656px
+ 470.3125px
+ 470.8594px
+ 471.4062px
+ 471.9531px
+ 472.5000px
+ 473.0469px
+ 473.5938px
+ 474.1406px
+ 474.6875px
+ 475.2344px
+ 475.7812px
+ 476.3281px
+ 476.8750px
+ 477.4219px
+ 477.9688px
+ 478.5156px
+ 479.0625px
+ 479.6094px
+ 480.1562px
+ 480.7031px
+ 481.2500px
+ 481.7969px
+ 482.3438px
+ 482.8906px
+ 483.4375px
+ 483.9844px
+ 484.5312px
+ 485.0781px
+ 485.6250px
+ 486.1719px
+ 486.7188px
+ 487.2656px
+ 487.8125px
+ 488.3594px
+ 488.9062px
+ 489.4531px
+ 490.0000px
+ 490.5469px
+ 491.0938px
+ 491.6406px
+ 492.1875px
+ 492.7344px
+ 493.2812px
+ 493.8281px
+ 494.3750px
+ 494.9219px
+ 495.4688px
+ 496.0156px
+ 496.5625px
+ 497.1094px
+ 497.6562px
+ 498.2031px
+ 498.7500px
+ 499.2969px
+ 499.8438px
+ 500.3906px
+ 500.9375px
+ 501.4844px
+ 502.0312px
+ 502.5781px
+ 503.1250px
+ 503.6719px
+ 504.2188px
+ 504.7656px
+ 505.3125px
+ 505.8594px
+ 506.4062px
+ 506.9531px
+ 507.5000px
+ 508.0469px
+ 508.5938px
+ 509.1406px
+ 509.6875px
+ 510.2344px
+ 510.7812px
+ 511.3281px
+ 511.8750px
+ 512.4219px
+ 512.9688px
+ 513.5156px
+ 514.0625px
+ 514.6094px
+ 515.1562px
+ 515.7031px
+ 516.2500px
+ 516.7969px
+ 517.3438px
+ 517.8906px
+ 518.4375px
+ 518.9844px
+ 519.5312px
+ 520.0781px
+ 520.6250px
+ 521.1719px
+ 521.7188px
+ 522.2656px
+ 522.8125px
+ 523.3594px
+ 523.9062px
+ 524.4531px
+ 525.0000px
+ 525.5469px
+ 526.0938px
+ 526.6406px
+ 527.1875px
+ 527.7344px
+ 528.2812px
+ 528.8281px
+ 529.3750px
+ 529.9219px
+ 530.4688px
+ 531.0156px
+ 531.5625px
+ 532.1094px
+ 532.6562px
+ 533.2031px
+ 533.7500px
+ 534.2969px
+ 534.8438px
+ 535.3906px
+ 535.9375px
+ 536.4844px
+ 537.0312px
+ 537.5781px
+ 538.1250px
+ 538.6719px
+ 539.2188px
+ 539.7656px
+ 540.3125px
+ 540.8594px
+ 541.4062px
+ 541.9531px
+ 542.5000px
+ 543.0469px
+ 543.5938px
+ 544.1406px
+ 544.6875px
+ 545.2344px
+ 545.7812px
+ 546.3281px
+ 710.9375px
+ 3.2812px
+ 3.8281px
+ 4.3750px
+ 4.9219px
+ 5.4688px
+ 6.0156px
+ 6.5625px
+ 7.1094px
+ 7.6562px
+ 8.2031px
+ 8.7500px
+ 9.2969px
+ 9.8438px
+ 10.3906px
+ 10.9375px
+ 11.4844px
+ 12.0312px
+ 12.5781px
+ 13.1250px
+ 13.6719px
+ 15.3125px
+ 16.4062px
+ 17.5000px
+ 18.5938px
+ 19.6875px
+ 20.7812px
+ 21.8750px
+ 22.9688px
+ 26.2500px
+
diff --git a/modules/mogo-module-guide/src/main/res/values/strings.xml b/modules/mogo-module-guide/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..6ce77e8b38
--- /dev/null
+++ b/modules/mogo-module-guide/src/main/res/values/strings.xml
@@ -0,0 +1,14 @@
+
+ mogo-module-guide-agreement
+ 左滑了解更多
+ 进入首页
+ 下一步
+ 结束
+
+ 欢迎使用’蘑菇车联‘,您下次可以直接对我说,打开’蘑菇车联‘来直接进入应用,点击左下方按钮进行摄像头设置
+ 左边是道路事件的播报,点击右边地图上的事件标示可以查看事件详情,或者直接唤醒小智说,中关村附近堵不堵,来查询目的地周围路况
+ 这里是道路信息显示,点击后可查看事件详情
+ 这里是事件汇总,您可以查看您参与的事件和您的分享记录
+ 更多设置,在左上角的设置功能中,点击右下角的分享,可以把路况分享给其他车友,或者直接唤醒小智说,上报路况
+ 我们希望让您的出行更加安全高效,更多功能等着你去发现,快去体验体验吧
+
diff --git a/modules/mogo-module-guide/src/test/java/com/mogo/module/guide/agreement/ExampleUnitTest.kt b/modules/mogo-module-guide/src/test/java/com/mogo/module/guide/agreement/ExampleUnitTest.kt
new file mode 100644
index 0000000000..7570d3781c
--- /dev/null
+++ b/modules/mogo-module-guide/src/test/java/com/mogo/module/guide/agreement/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.mogo.module.guide.agreement
+
+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)
+ }
+}
diff --git a/modules/mogo-module-media/.gitignore b/modules/mogo-module-media/.gitignore
new file mode 100644
index 0000000000..426a199cc8
--- /dev/null
+++ b/modules/mogo-module-media/.gitignore
@@ -0,0 +1,14 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
\ No newline at end of file
diff --git a/modules/mogo-module-media/build.gradle b/modules/mogo-module-media/build.gradle
new file mode 100644
index 0000000000..e378c9aa3f
--- /dev/null
+++ b/modules/mogo-module-media/build.gradle
@@ -0,0 +1,73 @@
+apply plugin: 'com.android.library'
+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
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.aar'])
+
+ annotationProcessor rootProject.ext.dependencies.aroutercompiler
+ implementation rootProject.ext.dependencies.arouter
+ implementation rootProject.ext.dependencies.rxandroid
+ implementation rootProject.ext.dependencies.androidxappcompat
+ implementation rootProject.ext.dependencies.androidxconstraintlayout
+
+ // 爱趣听sdk上传到了公司的maven,用来规避RELEASE时ClassDefNotFound异常,后续若爱趣听有新的sdk也需要上传maven
+ implementation "com.mogo.tencent.wecarflow:mogo-wecarflow:+@aar"
+ implementation "com.mogo.kwmusic:mogo-kwmusic:+"
+
+ implementation rootProject.ext.dependencies.callchatprovider
+
+ if (Boolean.valueOf(RELEASE)) {
+ implementation rootProject.ext.dependencies.mogomap
+ implementation rootProject.ext.dependencies.mogoutils
+ implementation rootProject.ext.dependencies.mogocommons
+ implementation rootProject.ext.dependencies.mogoserviceapi
+ implementation rootProject.ext.dependencies.mogoservice
+ implementation rootProject.ext.dependencies.moduleservice
+ implementation rootProject.ext.dependencies.modulecommon
+ implementation rootProject.ext.dependencies.mogomoduleauth
+ } else {
+ implementation project(":libraries:mogo-map")
+ implementation project(":foudations:mogo-utils")
+ implementation project(":foudations:mogo-commons")
+ implementation project(':services:mogo-service-api')
+ implementation project(':services:mogo-service')
+ implementation project(':modules:mogo-module-common')
+ implementation project(':modules:mogo-module-service')
+ implementation project(':modules:mogo-module-authorize')
+ }
+}
+
+apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
\ No newline at end of file
diff --git a/modules/mogo-module-media/consumer-rules.pro b/modules/mogo-module-media/consumer-rules.pro
new file mode 100644
index 0000000000..f1ea2b90d5
--- /dev/null
+++ b/modules/mogo-module-media/consumer-rules.pro
@@ -0,0 +1,11 @@
+#-----MediaModule-----
+-dontwarn com.mogo.module.media.**
+-keep class com.mogo.module.media.api.* { *; }
+-keep class com.mogo.module.media.constants.* { *; }
+-keep class com.mogo.module.media.model.** { *; }
+-keep class com.mogo.module.media.view.* { *; }
+-keep class com.mogo.module.media.widget.** { *; }
+-keep class com.mogo.module.media.receiver.* { *; }
+-keep class com.mogo.module.media.utils.OnBitmapToLocalListener
+-keep class com.mogo.module.media.utils.OnCompressListener
+-keep class com.mogo.module.media.MediaConstants{*;}
\ No newline at end of file
diff --git a/modules/mogo-module-media/gradle.properties b/modules/mogo-module-media/gradle.properties
new file mode 100644
index 0000000000..8ff91031eb
--- /dev/null
+++ b/modules/mogo-module-media/gradle.properties
@@ -0,0 +1,3 @@
+GROUP=com.mogo.module
+POM_ARTIFACT_ID=module-media
+VERSION_CODE=1
diff --git a/modules/mogo-module-media/proguard-rules.pro b/modules/mogo-module-media/proguard-rules.pro
new file mode 100644
index 0000000000..0d676ccbbf
--- /dev/null
+++ b/modules/mogo-module-media/proguard-rules.pro
@@ -0,0 +1,35 @@
+# 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
+
+#-----MediaModule-----
+-dontwarn com.mogo.module.media.**
+-keep class com.mogo.module.media.listener.** { *; }
+-keep class com.mogo.module.media.model.** { *; }
+-keep class com.mogo.module.media.view.** { *; }
+-keep class com.mogo.module.media.widget.** { *; }
+-keep class com.mogo.module.media.api.** { *; }
+-keep class com.mogo.module.media.constants.** { *; }
+-keep class com.mogo.module.media.presenter.** { *; }
+-keep class com.mogo.module.media.receiver.** { *; }
+-keep class com.mogo.module.media.utils.OnBitmapToLocalListener
+-keep class com.mogo.module.media.utils.OnCompressListener
+-keep class com.mogo.module.media.MediaConstants
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/androidTest/java/com/mogo/module/media/ExampleInstrumentedTest.java b/modules/mogo-module-media/src/androidTest/java/com/mogo/module/media/ExampleInstrumentedTest.java
new file mode 100644
index 0000000000..2ac6fb5988
--- /dev/null
+++ b/modules/mogo-module-media/src/androidTest/java/com/mogo/module/media/ExampleInstrumentedTest.java
@@ -0,0 +1,27 @@
+package com.mogo.module.media;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ assertEquals("com.mogo.module.media", appContext.getPackageName());
+ }
+}
diff --git a/modules/mogo-module-media/src/main/AndroidManifest.xml b/modules/mogo-module-media/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..4292dc7f05
--- /dev/null
+++ b/modules/mogo-module-media/src/main/AndroidManifest.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/assets/13646-rugby-loader.json b/modules/mogo-module-media/src/main/assets/13646-rugby-loader.json
new file mode 100644
index 0000000000..70c3b84438
--- /dev/null
+++ b/modules/mogo-module-media/src/main/assets/13646-rugby-loader.json
@@ -0,0 +1 @@
+{"v":"5.5.9","fr":30,"ip":0,"op":17,"w":500,"h":500,"nm":"Base Ball","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 17","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.166,"y":0},"t":23,"s":[295.125,240.875,0],"to":[0,0,0],"ti":[0,0,0]},{"t":37,"s":[287.625,240.875,0]}],"ix":2},"a":{"a":0,"k":[37.625,-9.125,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[35.375,-9.125],[39.875,-9.125]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.313725490196,0.313725490196,0.313725490196,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.956862804936,0.63137254902,0.564705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":23,"s":[100]},{"t":33,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":29,"s":[100]},{"t":38,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":4,"nm":"Trim Paths 2","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":23,"op":36,"st":23,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 16","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.115,"y":0},"t":26,"s":[299.938,258.875,0],"to":[0,0,0],"ti":[0,0,0]},{"t":40,"s":[287.438,258.875,0]}],"ix":2},"a":{"a":0,"k":[35.938,8.875,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[30.625,8.875],[41.25,8.875]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.313725490196,0.313725490196,0.313725490196,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.956862804936,0.63137254902,0.564705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":26,"s":[100]},{"t":36,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":32,"s":[100]},{"t":41,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":4,"nm":"Trim Paths 2","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":26,"op":39,"st":26,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 15","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.115,"y":0},"t":23,"s":[300.188,275.812,0],"to":[0,0,0],"ti":[0,0,0]},{"t":36,"s":[282.688,275.812,0]}],"ix":2},"a":{"a":0,"k":[32.688,25.812,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[44.25,25.625],[48.75,25.625]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.313725490196,0.313725490196,0.313725490196,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.956862804936,0.63137254902,0.564705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":23,"s":[100]},{"t":33,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":28,"s":[100]},{"t":34,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":4,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[16.625,26],[34.875,26]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.313725490196,0.313725490196,0.313725490196,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.956862804936,0.63137254902,0.564705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":27,"s":[100]},{"t":37,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":33,"s":[100]},{"t":43,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":4,"nm":"Trim Paths 2","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":23,"op":35,"st":23,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 9","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.166,"y":0},"t":2,"s":[295.125,240.875,0],"to":[0,0,0],"ti":[0,0,0]},{"t":16,"s":[287.625,240.875,0]}],"ix":2},"a":{"a":0,"k":[37.625,-9.125,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[35.375,-9.125],[39.875,-9.125]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.313725490196,0.313725490196,0.313725490196,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.956862804936,0.63137254902,0.564705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":2,"s":[100]},{"t":12,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":8,"s":[100]},{"t":17,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":4,"nm":"Trim Paths 2","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":2,"op":15,"st":2,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Shape Layer 8","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.115,"y":0},"t":5,"s":[299.938,258.875,0],"to":[0,0,0],"ti":[0,0,0]},{"t":19,"s":[287.438,258.875,0]}],"ix":2},"a":{"a":0,"k":[35.938,8.875,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[30.625,8.875],[41.25,8.875]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.313725490196,0.313725490196,0.313725490196,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.956862804936,0.63137254902,0.564705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":5,"s":[100]},{"t":15,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":11,"s":[100]},{"t":20,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":4,"nm":"Trim Paths 2","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":5,"op":18,"st":5,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Shape Layer 7","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.115,"y":0},"t":2,"s":[300.188,275.812,0],"to":[0,0,0],"ti":[0,0,0]},{"t":15,"s":[282.688,275.812,0]}],"ix":2},"a":{"a":0,"k":[32.688,25.812,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[44.25,25.625],[48.75,25.625]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.313725490196,0.313725490196,0.313725490196,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.956862804936,0.63137254902,0.564705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":2,"s":[100]},{"t":12,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":7,"s":[100]},{"t":13,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":4,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[16.625,26],[34.875,26]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.313725490196,0.313725490196,0.313725490196,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.956862804936,0.63137254902,0.564705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":6,"s":[100]},{"t":16,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.211],"y":[0]},"t":12,"s":[100]},{"t":22,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":4,"nm":"Trim Paths 2","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":2,"op":14,"st":2,"bm":0}]},{"id":"comp_1","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 6","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-6.969,-6.062,0],"ix":2},"a":{"a":0,"k":[-19.656,6.062,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-23.812,1.562],[-15.5,10.562]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.313725490196,0.313725490196,0.313725490196,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.956862804936,0.63137254902,0.564705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":61,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 5","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-13.406,-0.188,0],"ix":2},"a":{"a":0,"k":[-19.656,6.062,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-23.812,1.562],[-15.5,10.562]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.313725490196,0.313725490196,0.313725490196,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.956862804936,0.63137254902,0.564705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":61,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 4","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-19.656,6.062,0],"ix":2},"a":{"a":0,"k":[-19.656,6.062,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-23.812,1.562],[-15.5,10.562]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.313725490196,0.313725490196,0.313725490196,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.956862804936,0.63137254902,0.564705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":61,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[264.625,274.625,0],"to":[0,0,0],"ti":[0,0,0]},{"t":17,"s":[210.875,222.125,0]}],"ix":2,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle');"},"a":{"a":0,"k":[-13.625,0.125,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-23.75,10],[-3.5,-9.75]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.313725490196,0.313725490196,0.313725490196,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.956862804936,0.63137254902,0.564705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":61,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Effect","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":0,"k":[147,147,100],"ix":6}},"ao":0,"w":500,"h":500,"ip":0,"op":61,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 11","parent":4,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-12.821,-0.393,0],"ix":2},"a":{"a":0,"k":[-12.821,-0.393,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[17.75,-18.75],[0,0],[-17.058,18.196]],"o":[[0,0],[-18.717,19.772],[0,0],[18.75,-20]],"v":[[17.75,-31],[-29.75,-17],[-43.5,31.5],[4.25,15.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.315119485294,0.315119485294,0.315119485294,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":61,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":0,"nm":"Centre Part","parent":4,"tt":1,"refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-5.301,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":500,"h":500,"ip":0,"op":61,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 1","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-12.821,-0.393,0],"ix":2},"a":{"a":0,"k":[-12.821,-0.393,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[23.5,-23],[0,0],[-20.5,21.75]],"o":[[0,0],[-21.485,21.028],[0,0],[20.5,-21.75]],"v":[[17.75,-31],[-31.25,-18.25],[-43.5,31.5],[6.5,16.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.315119485294,0.315119485294,0.315119485294,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":94,"ix":2},"o":{"a":0,"k":142,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":61,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Shape Layer 10","parent":4,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-12.821,-0.393,0],"ix":2},"a":{"a":0,"k":[-12.821,-0.393,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[18.544,-17.965],[0,0],[-17.058,18.196]],"o":[[0,0],[-19.25,18.648],[0,0],[18.75,-20]],"v":[[17.75,-31],[-32.25,-17.75],[-43.5,31.5],[4.25,15.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.315119485294,0.315119485294,0.315119485294,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":61,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"color","parent":4,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-46.534,"ix":10},"p":{"a":0,"k":[-13.142,-0.536,0],"ix":2},"a":{"a":0,"k":[-12.892,-0.786,0],"ix":1},"s":{"a":0,"k":[83.074,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[65.681,75.156],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.956862804936,0.63137254902,0.564705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-12.892,-0.786],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":61,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Shape Layer 12","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[231.153,249.422,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":8.5,"s":[231.153,253.097,0],"to":[0,0,0],"ti":[0,0,0]},{"t":17,"s":[231.153,249.422,0]}],"ix":2},"a":{"a":0,"k":[-12.821,-0.393,0],"ix":1},"s":{"a":0,"k":[147,147,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[23.5,-23],[0,0],[-20.5,21.75]],"o":[[0,0],[-21.485,21.028],[0,0],[20.5,-21.75]],"v":[[17.75,-31],[-31.25,-18.25],[-43.5,31.5],[6.5,16.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":94,"ix":2},"o":{"a":0,"k":142,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":61,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/assets/images/img_0.png b/modules/mogo-module-media/src/main/assets/images/img_0.png
new file mode 100644
index 0000000000..34b602b89f
Binary files /dev/null and b/modules/mogo-module-media/src/main/assets/images/img_0.png differ
diff --git a/modules/mogo-module-media/src/main/assets/images/img_1.png b/modules/mogo-module-media/src/main/assets/images/img_1.png
new file mode 100644
index 0000000000..c7f4766de9
Binary files /dev/null and b/modules/mogo-module-media/src/main/assets/images/img_1.png differ
diff --git a/modules/mogo-module-media/src/main/assets/traffic_active_animator.json b/modules/mogo-module-media/src/main/assets/traffic_active_animator.json
new file mode 100644
index 0000000000..753c8125f1
--- /dev/null
+++ b/modules/mogo-module-media/src/main/assets/traffic_active_animator.json
@@ -0,0 +1 @@
+{"v":"5.5.9","fr":25,"ip":0,"op":40,"w":600,"h":600,"nm":"合成 2","ddd":0,"assets":[{"id":"image_0","w":249,"h":420,"u":"images/","p":"img_0.png","e":0},{"id":"image_1","w":606,"h":396,"u":"images/","p":"img_1.png","e":0},{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"tick2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[0],"e":[99]},{"t":22}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[473.856,259.731,0],"ix":2},"a":{"a":0,"k":[27.375,-11.375,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":20,"s":[0,0,100],"e":[80,80,100]},{"t":22}],"ix":6,"x":"var $bm_rt;\nvar amp, freq, decay, n, n, t, t, v;\namp = 0.1;\nfreq = 1;\ndecay = 4;\n$bm_rt = n = 0;\nif (numKeys > 0) {\n $bm_rt = n = nearestKey(time).index;\n if (key(n).time > time) {\n n--;\n }\n}\nif (n == 0) {\n $bm_rt = t = 0;\n} else {\n $bm_rt = t = $bm_sub(time, key(n).time);\n}\nif (n > 0) {\n v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10)));\n $bm_rt = $bm_sum(value, $bm_div($bm_mul($bm_mul(v, amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))));\n} else {\n $bm_rt = value;\n}"}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-36,-15.5],[-21,-0.75],[1.75,-22.25]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":8,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[45,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"形状 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":20,"op":770,"st":20,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":" Round 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[474.319,259.882,0],"ix":2},"a":{"a":0,"k":[-9,-4,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":22,"s":[50,50,100],"e":[70,70,100]},{"t":25}],"ix":6,"x":"var $bm_rt;\nvar amp, freq, decay, n, n, t, t, v;\namp = 0.1;\nfreq = 1;\ndecay = 4;\n$bm_rt = n = 0;\nif (numKeys > 0) {\n $bm_rt = n = nearestKey(time).index;\n if (key(n).time > time) {\n n--;\n }\n}\nif (n == 0) {\n $bm_rt = t = 0;\n} else {\n $bm_rt = t = $bm_sub(time, key(n).time);\n}\nif (n > 0) {\n v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10)));\n $bm_rt = $bm_sum(value, $bm_div($bm_mul($bm_mul(v, amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))));\n} else {\n $bm_rt = value;\n}"}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[90,90],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[0.600000023842,0.600000023842,0.600000023842,1],"e":[0.196078434587,0.772549033165,1,1]},{"t":22}],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[100],"e":[50]},{"t":22}],"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-9.264,-4.264],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":20,"op":770,"st":20,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":" Round 8","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[2],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":9.899,"s":[100],"e":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[0],"e":[1]},{"t":749}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[474.519,259.894,0],"ix":2},"a":{"a":0,"k":[-9,-4,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[50,50,100],"e":[159,159,100]},{"t":20}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[70,70],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.162408118154,0.778977397844,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-9.264,-4.264],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":" Round 9","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[2],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":18.899,"s":[100],"e":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":29,"s":[0],"e":[1]},{"t":758}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[474.519,259.894,0],"ix":2},"a":{"a":0,"k":[-9,-4,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":9,"s":[50,50,100],"e":[159,159,100]},{"t":29}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[70,70],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.162408118154,0.778977397844,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-9.264,-4.264],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":9,"op":29,"st":9,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":" Round 7","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":15,"s":[2],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":24.899,"s":[100],"e":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":35,"s":[0],"e":[1]},{"t":764}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[474.519,259.894,0],"ix":2},"a":{"a":0,"k":[-9,-4,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":15,"s":[50,50,100],"e":[159,159,100]},{"t":35}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[70,70],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.162408118154,0.778977397844,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-9.264,-4.264],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":15,"op":35,"st":15,"bm":0},{"ddd":0,"ind":6,"ty":2,"nm":"手机.png","cl":"png","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[472,302,0],"ix":2},"a":{"a":0,"k":[124.5,210,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":750,"st":0,"bm":0}]},{"id":"comp_1","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"line 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[281,380.5,0],"ix":2},"a":{"a":0,"k":[-25.5,-79.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[34,-174.5],[74,-174.5]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.162408118154,0.778977397844,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-163.061,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"形状 2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"st","c":{"a":0,"k":[0.162408118154,0.778977397844,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[73.195,-73.461],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"形状 1","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[100],"e":[7]},{"t":24}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[100],"e":[7]},{"t":28}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":20,"op":30,"st":20,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"line 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[281,380.5,0],"ix":2},"a":{"a":0,"k":[-25.5,-79.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[34,-174.5],[74,-174.5]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.162408118154,0.778977397844,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"形状 2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"st","c":{"a":0,"k":[0.162408118154,0.778977397844,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[73.195,-73.461],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"形状 1","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":21,"s":[7],"e":[100]},{"t":25}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":21,"s":[7],"e":[100]},{"t":29}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":20,"op":30,"st":20,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"line 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[281,380.5,0],"ix":2},"a":{"a":0,"k":[-25.5,-79.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-7],[0,0]],"o":[[0,7],[0,0]],"v":[[-25,-107],[-25,-80]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.162408118154,0.778977397844,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"形状 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":21,"s":[7],"e":[100]},{"t":25}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":21,"s":[7],"e":[100]},{"t":29}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":20,"op":30,"st":20,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"line","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[281,208.5,0],"ix":2},"a":{"a":0,"k":[-25.5,-106.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-7],[0,0]],"o":[[0,7],[0,0]],"v":[[-25,-107],[-25,-80]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.162408118154,0.778977397844,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"形状 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":21,"s":[100],"e":[0]},{"t":24.5}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":21,"s":[100],"e":[0]},{"t":28}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":20,"op":30,"st":20,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"tick1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[283.556,288.743,0],"ix":2},"a":{"a":0,"k":[27.375,-11.375,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":10,"s":[100,100,100],"e":[50,50,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":15,"s":[50,50,100],"e":[100,100,100]},{"t":18}],"ix":6,"x":"var $bm_rt;\nvar amp, freq, decay, n, n, t, t, v;\namp = 0.1;\nfreq = 1;\ndecay = 4;\n$bm_rt = n = 0;\nif (numKeys > 0) {\n $bm_rt = n = nearestKey(time).index;\n if (key(n).time > time) {\n n--;\n }\n}\nif (n == 0) {\n $bm_rt = t = 0;\n} else {\n $bm_rt = t = $bm_sub(time, key(n).time);\n}\nif (n > 0) {\n v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10)));\n $bm_rt = $bm_sum(value, $bm_div($bm_mul($bm_mul(v, amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))));\n} else {\n $bm_rt = value;\n}"}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-36,-15.5],[-21,-0.75],[1.75,-22.25]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[45,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"形状 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":16,"s":[0],"e":[100]},{"t":24}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":750,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":" Round 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[284.319,288.882,0],"ix":2},"a":{"a":0,"k":[-9,-4,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":10,"s":[100,100,100],"e":[80,80,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":15,"s":[80,80,100],"e":[100,100,100]},{"t":18}],"ix":6,"x":"var $bm_rt;\nvar amp, freq, decay, n, n, t, t, v;\namp = 0.1;\nfreq = 1;\ndecay = 4;\n$bm_rt = n = 0;\nif (numKeys > 0) {\n $bm_rt = n = nearestKey(time).index;\n if (key(n).time > time) {\n n--;\n }\n}\nif (n == 0) {\n $bm_rt = t = 0;\n} else {\n $bm_rt = t = $bm_sub(time, key(n).time);\n}\nif (n > 0) {\n v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10)));\n $bm_rt = $bm_sum(value, $bm_div($bm_mul($bm_mul(v, amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))));\n} else {\n $bm_rt = value;\n}"}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[90,90],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0.600000023842,0.600000023842,0.600000023842,1],"e":[0.196078431373,0.772549019608,1,1]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0.196078431373,0.772549019608,1,1],"e":[0.196078434587,0.772549033165,1,1]},{"t":22}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-9.264,-4.264],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":750,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"手机","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.517],"y":[0.999]},"o":{"x":[0.652],"y":[0.016]},"t":0,"s":[22],"e":[287.899]},{"t":25}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.99],"y":[1]},"o":{"x":[0.01],"y":[0]},"t":0,"s":[300],"e":[300]},{"t":25}],"ix":4}},"a":{"a":0,"k":[300,300,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":600,"h":600,"ip":0,"op":40,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"bule tick","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,300,0],"ix":2},"a":{"a":0,"k":[300,300,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":600,"h":600,"ip":0,"op":40,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":2,"nm":"车机.png","cl":"png","refId":"image_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[302,310,0],"ix":2},"a":{"a":0,"k":[303,198,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":40,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"形状图层 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[294.742,298.636,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[600,606.881],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[5.258,4.805],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":750,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/MediaCardViewFragment.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/MediaCardViewFragment.java
new file mode 100644
index 0000000000..2d7e5713f4
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/MediaCardViewFragment.java
@@ -0,0 +1,2003 @@
+package com.mogo.module.media;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import com.bumptech.glide.load.engine.DiskCacheStrategy;
+import com.bumptech.glide.request.RequestOptions;
+import com.bumptech.glide.request.target.SimpleTarget;
+import com.bumptech.glide.request.transition.Transition;
+import com.mogo.commons.mvp.MvpFragment;
+import com.mogo.commons.voice.AIAssist;
+import com.mogo.commons.voice.IMogoVoiceCmdCallBack;
+import com.mogo.map.MogoLatLng;
+import com.mogo.map.location.IMogoLocationListener;
+import com.mogo.map.location.MogoLocation;
+import com.mogo.map.marker.IMogoMarker;
+import com.mogo.map.marker.IMogoMarkerClickListener;
+import com.mogo.module.authorize.authprovider.invoke.AuthorizeInvokerConstant;
+import com.mogo.module.authorize.authprovider.module.IMogoAcquireAuthorizeListener;
+import com.mogo.module.common.entity.MarkerLocation;
+import com.mogo.module.common.entity.MarkerShareMusic;
+import com.mogo.module.common.entity.MarkerShowEntity;
+import com.mogo.module.common.entity.MarkerUserInfo;
+import com.mogo.module.media.constants.EventConstants;
+import com.mogo.module.media.constants.LeTingFieldConstants;
+import com.mogo.module.media.constants.QQMusicFieldConstants;
+import com.mogo.module.media.constants.VoiceConstants;
+import com.mogo.module.media.dialog.MediaShareDialogFragment;
+import com.mogo.module.media.listener.NoDoubleClickListener;
+import com.mogo.module.media.model.LanRenInsertData;
+import com.mogo.module.media.model.LeTingNewsData;
+import com.mogo.module.media.model.MediaInfoData;
+import com.mogo.module.media.model.ShareLikeData;
+import com.mogo.module.media.model.ShareMediaJsonData;
+import com.mogo.module.media.presenter.MediaPresenter;
+import com.mogo.module.media.receiver.MediaSpeechReceiver;
+import com.mogo.module.media.utils.FastBlurUtil;
+import com.mogo.module.media.utils.MediaAnalyticsUtils;
+import com.mogo.module.media.utils.MusicControlBroadCast;
+import com.mogo.module.media.utils.StorageManager;
+import com.mogo.module.media.utils.TimeUtils;
+import com.mogo.module.media.utils.Utils;
+import com.mogo.module.media.view.MediaView;
+import com.mogo.module.media.widget.AnimCircleImageView;
+import com.mogo.module.media.widget.NoScrollSeekBar;
+import com.mogo.module.media.widget.RoundedImageView;
+import com.mogo.module.media.widget.ScrollingTextView;
+import com.mogo.module.media.widget.surfaceview.FrameTextureView;
+import com.mogo.service.intent.IMogoIntentListener;
+import com.mogo.service.module.IMogoModuleLifecycle;
+import com.mogo.service.statusmanager.IMogoStatusChangedListener;
+import com.mogo.service.statusmanager.StatusDescriptor;
+import com.mogo.utils.ActivityLifecycleManager;
+import com.mogo.utils.ThreadPoolService;
+import com.mogo.utils.TipToast;
+import com.mogo.utils.UiThreadHandler;
+import com.mogo.utils.glide.GlideApp;
+import com.mogo.utils.logger.Logger;
+import com.mogo.utils.network.utils.GsonUtil;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * 音乐卡片Fragment
+ */
+public class MediaCardViewFragment extends MvpFragment implements
+ MediaView, IMogoMarkerClickListener,
+ IMogoModuleLifecycle,
+ IMogoLocationListener, View.OnClickListener, MediaShareDialogFragment.Callback {
+
+ public static final String TAG = MediaCardViewFragment.class.getName();
+ public static boolean isMediaResume = false;
+ private Context mContext;
+
+ private ImageView mShareImageView;
+ private ImageView mFullScreenImageView;
+
+ private LinearLayout mShaerBackView;
+
+ private RelativeLayout mUserShareBackView;
+ private ImageView mShareUserHeardImageView;
+ private ScrollingTextView mShareUserNameTextView;
+ private ImageView mShareLikeImageView;
+ private TextView mShareLikeNumTextView;
+
+ private RoundedImageView mShareSongImageView;
+ private ScrollingTextView mShareSongNameTextView;
+ private ScrollingTextView mShareSingerNameTextView;
+
+ private LinearLayout mNoShareBackView;
+ private ImageView mNoShareSongImageView;
+ private ScrollingTextView mNoShareSongNameTextView;
+ private ScrollingTextView mNoShareSingerNameTextView; //章节
+
+ private ImageView mLastMusicImageView;
+ private ImageView mMusicPlay;
+ private ImageView mNextMusicImageView;
+
+ private TextView mLeftTimeTextView;
+ private TextView mRightTimeTextView;
+ private NoScrollSeekBar mProgressBar;
+ private FrameTextureView mAnimalSurfaceView;
+ private View mBlurAbove;
+
+ private MediaCardViewFragment.MediaStateReceiver mediaStateReceiver;
+ private MediaCardViewFragment.MediaProcessReceiver mediaProcessReceiver;
+ private MediaCardViewFragment.PlayingMusicReceiver playingMusicReceiver;
+ private MediaCardViewFragment.MediaNewsPayInfo mediaNewsPayInfo;
+ private MediaCardViewFragment.MediaCenterReceiver mediaCenterReceiver;
+ private MediaSpeechShareReceiver mediaCanShareReceiver;
+ private MediaInfoData mMediaInfoData;
+ private int mShowPlayState;
+
+ private View mWindowView;
+ private IMogoMarker mLastClickedMarker;
+ private AnimCircleImageView mCircleImg;
+ private TextView mScrollText;
+ private ImageView mWindowPlayPause;
+ private ImageView mWindowPlayNext;
+ private MediaShareDialogFragment mShareDilogFragment;
+ private MediaMogoVoiceListener mMediaVoiceListener;
+ private TextView mWindowCurrTime;
+ private TextView mWindowMaxTime;
+ private SeekBar mWindowProgress;
+ private ImageView mBlurBg;
+ private ShareLikeData.ShareLikeDataResult mLikeDataResult;
+ private NoDoubleClickListener mNoDoubleClickListener;
+
+ //是否提醒用户主动显示未分享
+ private boolean mShowSharePush = false;
+ private boolean mCardCenter = false;
+ private boolean mHasAddWindow = false;
+ private String mOldLoadUrl = "";
+ private boolean mTwoChange = false;
+ private boolean isFirstPlay = false;
+ private boolean mFragmentResume = false;
+ private ArrayList mLastAdasMarker = new ArrayList<>();
+
+ private Runnable mRunnable = new Runnable() {
+ @Override
+ public void run() {
+ MusicControlBroadCast.sendGetMusicPlayStateBroadcast();
+ }
+ };
+ private MediaMogoStatusManager mMogoStatusChangeListener;
+ private boolean mAdasShow = false;
+ private boolean mAuthorShow = false;
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ this.mContext = context;
+ }
+
+ @Override
+ protected int getLayoutId() {
+ return R.layout.module_media_card_fragment_view;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ getViewLifecycleOwner().getLifecycle().addObserver(mPresenter);
+ mMediaVoiceListener = new MediaMogoVoiceListener();
+ mMogoStatusChangeListener = new MediaMogoStatusManager();
+ registerMediaReceiver();
+ if (ServiceMediaHandler.getMogoRegisterCenter() != null){
+ ServiceMediaHandler.getMogoRegisterCenter().registerMogoLocationListener(MediaConstants.MODULE_TYPE, this);
+ ServiceMediaHandler.getMogoRegisterCenter().registerMogoMarkerClickListener(MediaConstants.MODULE_TYPE, this);
+ ServiceMediaHandler.getMogoRegisterCenter().registerMogoModuleLifecycle(MediaConstants.MODULE_TYPE, this);
+ }
+
+ if (ServiceMediaHandler.getMogoVoiceManager() != null){
+ ServiceMediaHandler.getMogoVoiceManager().registerIntentListener("com.zhidao.music.friend.query" ,mMediaVoiceListener);
+ ServiceMediaHandler.getMogoVoiceManager().registerIntentListener("com.zhidao.music.user.query" ,mMediaVoiceListener);
+ }
+
+ if (ServiceMediaHandler.getIMogoStatusManager() != null){
+ ServiceMediaHandler.getIMogoStatusManager().registerStatusChangedListener(MediaConstants.MODULE_TYPE,StatusDescriptor.ADAS_UI,mMogoStatusChangeListener);
+ }
+ ServiceMediaHandler.getMogoAuthorizeModuleManager().registerAuthorizeListener( AuthorizeInvokerConstant.AUTHORIZE_TYPE_LAUNCHER_SHARE_MUSIC, new IMogoAcquireAuthorizeListener() {
+ @Override
+ public void authorizeSuccess() {
+ if (mAuthorShow){
+ if (mPresenter != null){
+ if (mCardCenter && mMediaInfoData != null && !mMediaInfoData.isLocalMedia() && (mMediaInfoData.getType() == 1 || mMediaInfoData.getType() == 2 || mMediaInfoData.getType() == 3)) {
+ mPresenter.shareMusic(mMediaInfoData,false);
+ }else{
+ TipToast.shortTip("当前音频不可分享");
+ AIAssist.getInstance(getActivity()).speakTTSVoice("当前音频不可分享",null);
+ }
+ }
+ }else{
+ showShareDialog();
+ }
+
+ }
+
+ @Override
+ public void authorizeFailed(String s) {
+ //TipToast.shortTip("授权失败");
+ }
+
+ @Override
+ public void forbiddenVoiceWhenAuthorize(String s) {
+ Logger.d(TAG,"forbiddenVoiceWhenAuthorize");
+ }
+ });
+
+ // registerNoWakeUpShareCmd();
+ if (mPresenter != null ) {
+ mPresenter.getShouldShare();
+ }
+ }
+
+ @Override
+ protected void initViews() {
+
+ mAnimalSurfaceView = findViewById(R.id.media_animal_surface_view);
+ mAnimalSurfaceView.setVisibility(View.GONE);
+ mAnimalSurfaceView.setBitmapIds(Arrays.asList(Utils.getIconArray()));
+ mAnimalSurfaceView.setDuration(15000);
+ mAnimalSurfaceView.setRepeatTimes(FrameTextureView.INFINITE);
+
+ mShareImageView = findViewById(R.id.share_id);
+ mShareImageView.setVisibility(View.GONE);
+ mFullScreenImageView = findViewById(R.id.full_screen_id);
+ mFullScreenImageView.setVisibility(View.GONE);
+ mShaerBackView = findViewById(R.id.share_back_id);
+
+ mUserShareBackView = findViewById(R.id.share_user_back_id);
+
+ mShareUserHeardImageView = findViewById(R.id.share_user_heardImage);
+ mShareUserNameTextView = findViewById(R.id.share_user_name);
+ mShareLikeImageView = findViewById(R.id.like_id);
+ mShareLikeNumTextView = findViewById(R.id.like_num_id);
+
+ mShareSongImageView = findViewById(R.id.share_medial_image_id);
+ mShareSongNameTextView = findViewById(R.id.share_medial_song_name_id);
+ mShareSingerNameTextView = findViewById(R.id.share_medial_singer_name_id);
+
+ mNoShareBackView = findViewById(R.id.no_share_back_id);
+ mNoShareSongImageView = findViewById(R.id.no_share_medial_image_id);
+ mNoShareSongNameTextView = findViewById(R.id.no_share_medial_song_name_id);
+ mNoShareSingerNameTextView = findViewById(R.id.no_share_medial_singer_name_id);
+
+ mLastMusicImageView = findViewById(R.id.last_music);
+ mMusicPlay = findViewById(R.id.play_pause_music);
+ mNextMusicImageView = findViewById(R.id.next_music);
+
+ mLeftTimeTextView = findViewById(R.id.left_time_progress);
+ mRightTimeTextView = findViewById(R.id.right_all_time_progress);
+ mProgressBar = findViewById(R.id.music_progress_bar);
+ mBlurBg = findViewById(R.id.media_blur_img);
+ mBlurAbove = findViewById(R.id.media_blur_img_above);
+ mBlurAbove.setVisibility(View.VISIBLE);
+
+ mNoDoubleClickListener = new NoDoubleClickListener() {
+ @Override
+ public void onClicks(View view) {
+ if (view == mShareImageView) {
+ boolean tneedAuthor = ServiceMediaHandler.getMogoAuthorizeModuleManager().needAuthorize(AuthorizeInvokerConstant.AUTHORIZE_TYPE_LAUNCHER_SHARE_MUSIC);
+ Logger.d(TAG,"是否授权 "+tneedAuthor);
+ if (tneedAuthor){//需要授权
+ closeAdasEvent();
+ mAuthorShow = false;
+ ServiceMediaHandler.getMogoAuthorizeModuleManager().invokeAuthorization(AuthorizeInvokerConstant.AUTHORIZE_TYPE_LAUNCHER_SHARE_MUSIC);
+ }else{
+ mAuthorShow = false;
+ showShareDialog();
+ }
+
+ try {
+ if (mMediaInfoData != null){
+ HashMap hashMap = new HashMap<>();
+ hashMap.put("type",1);
+ String trackId = "";
+ if (mMediaInfoData.getType() == 1){
+ trackId = EventConstants.EVENT_QQ_OPEN_SHARE_DIALOG_SHOW;
+ }else if (mMediaInfoData.getType() == 2){
+ trackId = EventConstants.EVENT_BOOK_OPEN_SHARE_DIALOG_SHOW;
+ }else if (mMediaInfoData.getType() == 3){
+ trackId = EventConstants.EVENT_NEWS_OPEN_SHARE_DIALOG_SHOW;
+ }
+ MediaAnalyticsUtils.track(trackId,hashMap);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } else if (view == mLastMusicImageView) {
+ if (mMediaInfoData != null) {
+ MusicControlBroadCast.commandPre(mMediaInfoData.getType());
+ HashMap hashMap = new HashMap<>();
+ hashMap.put("type", 3);
+ if (mMediaInfoData.getType() == 1){
+ MediaAnalyticsUtils.track(EventConstants.EVENT_QQ_LAST_PLAY,hashMap);
+ }else if (mMediaInfoData.getType() == 2){
+ MediaAnalyticsUtils.track(EventConstants.EVENT_BOOK_LAST_PLAY,hashMap);
+ }else if (mMediaInfoData.getType() == 3){
+ MediaAnalyticsUtils.track(EventConstants.EVENT_NEWS_LAST_PLAY,hashMap);
+ }
+ }else{
+ MusicControlBroadCast.commandPlayPause(1,2);
+ }
+ } else if (view == mMusicPlay) {
+ if (isFirstPlay){
+ if (mMediaInfoData != null){
+ MusicControlBroadCast.listeningSendData(mMediaInfoData);
+ }
+ }
+ if (mMediaInfoData != null) {
+ MusicControlBroadCast.commandPlayPause(mMediaInfoData.getType(),mMediaInfoData.getPlayState());
+ HashMap hashMap = new HashMap<>();
+ hashMap.put("type", 3);
+ int playstate = mMediaInfoData.getPlayState();
+ if (mMediaInfoData.getType() == 1){
+ MediaAnalyticsUtils.track(playstate == 1 ?EventConstants.EVENT_QQ_MUSIC_PAUSE:EventConstants.EVENT_QQ_MUSIC_START,hashMap);
+ }else if (mMediaInfoData.getType() == 2){
+ MediaAnalyticsUtils.track(playstate == 1 ?EventConstants.EVENT_BOOK_MUSIC_PAUSE:EventConstants.EVENT_BOOK_MUSIC_START,hashMap);
+ }else if (mMediaInfoData.getType() == 3){
+ MediaAnalyticsUtils.track(playstate == 1 ?EventConstants.EVENT_NEWS_MUSIC_PAUSE:EventConstants.EVENT_NEWS_MUSIC_START,hashMap);
+ }
+ }else{
+ MusicControlBroadCast.qqPlayQQMusic();
+ }
+
+ } else if (view == mNextMusicImageView) {
+ if (mMediaInfoData != null) {
+ MusicControlBroadCast.commandNext(mMediaInfoData.getType());
+ HashMap hashMap = new HashMap<>();
+ hashMap.put("type", 3);
+ if (mMediaInfoData.getType() == 1){
+ MediaAnalyticsUtils.track(EventConstants.EVENT_QQ_Next_PLAY,hashMap);
+ }else if (mMediaInfoData.getType() == 2){
+ MediaAnalyticsUtils.track(EventConstants.EVENT_BOOK_Next_PLAY,hashMap);
+ }else if (mMediaInfoData.getType() == 3){
+ MediaAnalyticsUtils.track(EventConstants.EVENT_NEWS_Next_PLAY,hashMap);
+ }
+ }else{
+ MusicControlBroadCast.commandPlayPause(1,2);
+ }
+ }else if (view == mShareLikeImageView){
+ if (mPresenter != null && mLikeDataResult != null && !mLikeDataResult.checkLiked){
+ mPresenter.likeShare(mLikeDataResult);
+ }else{
+ ifNeedRefreshMediaCard(true);
+ }
+ }
+ }
+ };
+
+ mShareImageView.setOnClickListener(mNoDoubleClickListener);
+ mFullScreenImageView.setOnClickListener(this);
+ mShareLikeImageView.setOnClickListener(mNoDoubleClickListener);
+ mLastMusicImageView.setOnClickListener(mNoDoubleClickListener);
+ mMusicPlay.setOnClickListener(mNoDoubleClickListener);
+ mNextMusicImageView.setOnClickListener(mNoDoubleClickListener);
+
+ MediaInfoData sMediaInfoData = MusicControlBroadCast.getHisMedia();
+ mMediaInfoData = sMediaInfoData;
+ if (mMediaInfoData != null ){
+ if (mRightTimeTextView != null){
+ mRightTimeTextView.setText(Utils.calculateTime(mMediaInfoData.getMaxTime()));
+ }
+
+ if (mLeftTimeTextView != null){
+ mLeftTimeTextView.setText("00:00");
+ }
+ }
+
+ if (mMediaInfoData != null && !mHasAddWindow){
+ addWindowView();
+ }
+
+ ifNeedRefreshMediaCard(true);
+ mFullScreenImageView.setVisibility(View.VISIBLE);
+ //发送消息 如果在播放就会返回状态进行更新
+ UiThreadHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ MusicControlBroadCast.sendGetMusicPlayStateBroadcast();
+ }
+ },300);
+
+ isFirstPlay = true;
+ }
+
+
+ @Override
+ protected MediaPresenter createPresenter() {
+ return new MediaPresenter(this);
+ }
+
+ @Override
+ public void showSharePush(boolean show) {
+ mShowSharePush = show;
+ }
+
+ @Override
+ public void loadNearShareMusicSuccess(List list) {
+ if (list == null || list.size() < 1) return;
+ addNewMarker(list);
+ }
+
+ @Override
+ public void loadFriendShareMusicSuccess(List list) {
+ if (list == null || list.size() < 1) return;
+ addNewMarker(list);
+ }
+
+ @Override
+ public void loadShareLikeDataResultSuccess(ShareLikeData.ShareLikeDataResult likeDataResult,String mediaId) {
+
+ if (mediaId == null){
+ return;
+ }
+ if (mMediaInfoData == null){
+ mShareLikeImageView.setImageResource(R.drawable.module_media_no_heart);
+ return;
+ }
+
+ if (TextUtils.equals(mediaId,mMediaInfoData.getMediaId())){
+ mLikeDataResult = likeDataResult;
+ int likeNum = mLikeDataResult.likedCount;
+ mShareLikeNumTextView.setText(likeNum > 99 ? "99+":likeNum+"");
+ if (likeDataResult.checkLiked){
+ mShareLikeImageView.setImageResource(R.drawable.module_media_have_heart);
+ if (likeDataResult.likedCount <= 0){
+ mLikeDataResult.likedCount = 1;
+ mShareLikeNumTextView.setText("1");
+ }
+ }else {
+ mShareLikeImageView.setImageResource(R.drawable.module_media_no_heart);
+ }
+ }
+ }
+
+ @Override
+ public void likeShareSuccess() {
+ if (mLikeDataResult != null){
+ int likeNum = mLikeDataResult.likedCount+1;
+
+ mShareLikeNumTextView.setText(likeNum > 99 ? "99+":likeNum+"");
+ mLikeDataResult.likedCount = mLikeDataResult.likedCount + 1;
+ mLikeDataResult.checkLiked = true;
+ mShareLikeImageView.setImageResource(R.drawable.module_media_have_heart);
+ if (mLikeDataResult.likedCount <= 0){
+ mLikeDataResult.likedCount = 1;
+ mShareLikeNumTextView.setText("1");
+ }
+ }else{
+ mShareLikeImageView.setImageResource(R.drawable.module_media_no_heart);
+ }
+
+ }
+
+ @Override
+ public boolean onMarkerClicked(IMogoMarker marker) {
+ clickMarkerOper(marker);
+ return false;
+ }
+
+ private void clickMarkerOper(IMogoMarker marker) {
+ Logger.d(TAG,"clickMarkerOper");
+ try {
+ if (marker != null && !marker.isDestroyed()) {
+ MarkerShowEntity markerShowEntity = (MarkerShowEntity) marker.getObject();
+
+ if (markerShowEntity != null && markerShowEntity.getBindObj() != null && markerShowEntity.getBindObj() instanceof MarkerShareMusic){
+ MarkerShareMusic markerShareMusic = (MarkerShareMusic) markerShowEntity.getBindObj();
+ if (markerShareMusic != null){
+ if (mMediaInfoData != null && mMediaInfoData.getMediaId().equals(markerShareMusic.getMediaId())){
+ if (mMediaInfoData.getPlayState() != 1){
+ MusicControlBroadCast.commandPlayPause(mMediaInfoData.getType(),mMediaInfoData.getPlayState());
+ }
+ return;
+ }
+ MusicControlBroadCast.clickMarkerSendData(markerShareMusic);
+ }
+ }
+
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onPerform() {
+ if (mMediaInfoData != null && mWindowView != null) {
+ mWindowView.setVisibility(View.GONE);
+ if (mCircleImg != null && mCircleImg.isRotationing()) {
+ mCircleImg.stopAnim();
+ }
+ }
+
+ if (mMediaInfoData != null && mMediaInfoData.getPlayState() == 1 && mNoShareBackView.getVisibility() == View.VISIBLE){
+ if (mAnimalSurfaceView != null){
+ mAnimalSurfaceView.setVisibility(View.VISIBLE);
+ if (mFragmentResume)mAnimalSurfaceView.start(true);
+ }
+ }
+ mCardCenter = true;
+ }
+
+ @Override
+ public void onDisable() {
+ if (mMediaInfoData != null && mWindowView != null) {
+ if (mMediaInfoData.getType() == 1 || mMediaInfoData.getType() == 2 || mMediaInfoData.getType() == 3){
+ mWindowView.setVisibility(View.VISIBLE);
+ if (mCircleImg != null && mMediaInfoData.getPlayState() == 1 && mFragmentResume) {
+ mCircleImg.startAnim();
+ }
+ }
+ }
+ if (mAnimalSurfaceView != null && mAnimalSurfaceView.getVisibility() == View.VISIBLE){
+ mAnimalSurfaceView.setVisibility(View.GONE);
+ mAnimalSurfaceView.pause();
+ }
+
+ mCardCenter = false;
+ }
+
+ @Override
+ public void accOn() {
+ if (mPresenter != null && !TimeUtils.isSameData(System.currentTimeMillis() + "", StorageManager.getShowPushShareTime())) {
+ mPresenter.getShouldShare();
+ }
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (view == mFullScreenImageView) {
+ if (mMediaInfoData != null) {
+ MusicControlBroadCast.openMediaApp(mMediaInfoData.getType());
+ } else {
+ MusicControlBroadCast.openMediaApp(1);
+ }
+ }
+ }
+
+ private synchronized void showShareDialog() {
+ closeAdasEvent();
+
+ if (mShareDilogFragment != null && mShareDilogFragment.getDialog() != null && mShareDilogFragment.getDialog().isShowing()) {
+ destroyShareDialogFragment();
+ }else{
+ mShareDilogFragment = null;
+ }
+
+ if (mCardCenter && mMediaInfoData != null && !mMediaInfoData.isLocalMedia() && (mMediaInfoData.getType() == 1 || mMediaInfoData.getType() == 2 || mMediaInfoData.getType() == 3)) {
+ destroyShareDialogFragment();
+ mShareDilogFragment = MediaShareDialogFragment.newInstance(mMediaInfoData,false);
+ mShareDilogFragment.show(getChildFragmentManager(), "MediaShareDialogFragment");
+ }else{
+ TipToast.shortTip("当前音频不可分享");
+ AIAssist.getInstance(getActivity()).speakTTSVoice("当前音频不可分享",null);
+ }
+ }
+
+ private void closeAdasEvent() {
+// if (ServiceMediaHandler.getIMogoStatusManager().isADASShow() || mAdasShow){
+// ServiceMediaHandler.getMogoADASController().closeADAS();
+// Logger.d(TAG,"====关闭辅助驾驶=========");
+// }
+ }
+
+ /**
+ * 关闭分享,免唤醒
+ */
+ private void destroyShareDialogFragment() {
+ if (mShareDilogFragment != null && mShareDilogFragment.getDialog() != null
+ && mShareDilogFragment.getDialog().isShowing()) {
+ mShareDilogFragment.dismissAllowingStateLoss();
+ mShareDilogFragment = null;
+ }else{
+ mShareDilogFragment = null;
+ }
+ }
+
+ private void addWindowView() {
+ if (ServiceMediaHandler.getMogoWindowManager() == null){
+ return ;
+ }
+
+ if (!mHasAddWindow) {
+ mHasAddWindow = true;
+ mWindowView = LayoutInflater.from(mContext).inflate(R.layout.module_media_music_window_alert_layout, null);
+ if (mCardCenter){
+ mWindowView.setVisibility(View.GONE);
+ } else{
+ mWindowView.setVisibility(View.VISIBLE);
+ }
+// if (ServiceMediaHandler.getIMogoStatusManager().isADASShow() || mAdasShow){
+//// if (){
+////
+//// }
+// }else {
+// mWindowView.setVisibility(View.GONE);
+// }
+ mCircleImg = mWindowView.findViewById(R.id.window_circle_img);
+ mScrollText = mWindowView.findViewById(R.id.window_scroll_txt);
+ mWindowPlayPause = mWindowView.findViewById(R.id.window_play_pause);
+ mWindowPlayNext = mWindowView.findViewById(R.id.window_music_next);
+ mWindowCurrTime = mWindowView.findViewById(R.id.window_current_time);
+ mWindowMaxTime = mWindowView.findViewById(R.id.window_max_time);
+ mWindowProgress = mWindowView.findViewById(R.id.window_progress_bar);
+ if (mWindowPlayPause != null){
+ mWindowPlayPause.setImageResource(R.drawable.module_media_window_pop_pause);
+ }
+ int yPos = getContext().getResources().getDimensionPixelOffset(R.dimen.module_media_music_state_location);
+ int xPos = getContext().getResources().getDimensionPixelOffset(R.dimen.module_media_music_state_location_x);
+ ServiceMediaHandler.getMogoWindowManager().addView( mWindowView, xPos, yPos, false);
+ updateWindowUI(true);
+ mWindowView.setOnClickListener(new NoDoubleClickListener() {
+ @Override
+ public void onClicks(View view) {
+ if (mMediaInfoData != null) {
+ MusicControlBroadCast.openMediaApp(mMediaInfoData.getType());
+ } else {
+ MusicControlBroadCast.openMediaApp(1);
+ }
+ }
+ });
+
+ mWindowPlayPause.setOnClickListener(new NoDoubleClickListener() {
+ @Override
+ public void onClicks(View view) {
+ if (isFirstPlay){
+ if (mMediaInfoData != null){
+// if (ServiceMediaHandler.getIMogoStatusManager() != null && ServiceMediaHandler.getIMogoStatusManager().isADASShow()){
+// ServiceMediaHandler.getMogoADASController().closeADAS();
+// }
+ MusicControlBroadCast.listeningSendData(mMediaInfoData);
+ }
+ }else{
+ if (mMediaInfoData != null) {
+// if (ServiceMediaHandler.getIMogoStatusManager() != null && ServiceMediaHandler.getIMogoStatusManager().isADASShow()){
+// ServiceMediaHandler.getMogoADASController().closeADAS();
+// }
+ MusicControlBroadCast.commandPlayPause(mMediaInfoData.getType(),mMediaInfoData.getPlayState());
+ }
+ }
+ }
+ });
+
+ mWindowPlayNext.setOnClickListener(new NoDoubleClickListener() {
+ @Override
+ public void onClicks(View view) {
+ if (mMediaInfoData != null) {
+// if (ServiceMediaHandler.getIMogoStatusManager() != null && ServiceMediaHandler.getIMogoStatusManager().isADASShow()){
+// ServiceMediaHandler.getMogoADASController().closeADAS();
+// }
+ MusicControlBroadCast.commandNext(mMediaInfoData.getType());
+ }
+ }
+ });
+ }
+ }
+
+ private void updateWindowUI(){
+ updateWindowUI(false);
+ }
+
+ private void updateWindowUI(boolean first) {
+ if (mWindowView == null || mMediaInfoData == null) return;
+ if (mMediaInfoData != null) {
+ if (mCardCenter){
+ mWindowView.setVisibility(View.GONE);
+ }else{
+ if (mMediaInfoData.getType() == 1 || mMediaInfoData.getType() == 2 || mMediaInfoData.getType() == 3){
+ mWindowView.setVisibility(View.VISIBLE);
+ }
+ }
+ }else{
+ mWindowView.setVisibility(View.GONE);
+ }
+
+ if (mScrollText != null){
+ mScrollText.setText(mMediaInfoData.getMediaName());
+ }
+
+ if (first || mMediaInfoData.getPlayState() == 1 || mMediaInfoData.getPlayState() == 2) {
+ if (mWindowMaxTime != null) mWindowMaxTime.setText(Utils.calculateTime((int) mMediaInfoData.getMaxTime()));
+ if (mWindowCurrTime != null) mWindowCurrTime.setText(Utils.calculateTime((int) mMediaInfoData.getCurTime()));
+ }
+
+ if (mCircleImg != null){
+ com.bumptech.glide.request.RequestOptions options = new com.bumptech.glide.request.RequestOptions()
+ .placeholder(R.drawable.module_media_share_default_icon);
+ GlideApp.with(mContext).applyDefaultRequestOptions(options).load(mMediaInfoData.getMediaImg()).into(mCircleImg);
+ }
+
+ }
+
+ private void ifNeedRefreshMediaCard(boolean change) {
+ if (mMediaInfoData == null) {
+ return;
+ }
+
+ Logger.d(TAG,"ifNeedRefreshMediaCard "+change);
+ if (mMediaInfoData != null && change){
+ String bimgUrl = mMediaInfoData.getMediaImg();
+ if (!TextUtils.isEmpty(bimgUrl)) {
+ if(!mOldLoadUrl.equals(bimgUrl)){
+ mOldLoadUrl = bimgUrl;
+ GlideApp.with(mContext)
+ .asBitmap()
+ .load(bimgUrl)
+ .into(new SimpleTarget() {
+ @Override
+ public void onResourceReady( Bitmap resource, Transition super Bitmap> transition) {
+
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ if (resource != null) {
+ Bitmap newBitmap = FastBlurUtil.toBlur(resource, 10);
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mBlurBg.setImageBitmap(newBitmap);
+ mBlurAbove.setVisibility(View.VISIBLE);
+ }
+ });
+ }
+ }
+ }).start();
+ }
+
+ @Override
+ public void onLoadStarted(Drawable placeholder) {
+ super.onLoadStarted(placeholder);
+ }
+
+ @Override
+ public void onLoadFailed(Drawable errorDrawable) {
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mBlurBg.setImageResource(R.drawable.module_media_no_img_default_icon);
+ mBlurAbove.setVisibility(View.GONE);
+ }
+ });
+ }
+ });
+ }
+ }
+ }
+
+ MarkerShareMusic shareMediaMarkerInfo1 = null;
+ if (mMediaInfoData != null && (mMediaInfoData.getPlayState() == 1)){
+ ArrayList mtShareMusicList = new ArrayList<>();
+ if (ServiceMediaHandler.getMarkerManager() != null){
+ List< IMogoMarker > mogoMarkersList = ServiceMediaHandler.getMarkerManager().getMarkers(MediaConstants.MODULE_TYPE);
+ if (mogoMarkersList != null){
+ try {
+ for (IMogoMarker mogoMarker:mogoMarkersList){
+ if (mogoMarker != null && mogoMarker.getObject() != null && !mogoMarker.isDestroyed()){
+ MarkerShowEntity markerShowEntity = (MarkerShowEntity) mogoMarker.getObject();
+ if ( markerShowEntity.getBindObj()!= null){
+ MarkerShareMusic markerShareMusic = (MarkerShareMusic) markerShowEntity.getBindObj();
+ if (markerShareMusic != null){
+ mtShareMusicList.add(markerShareMusic);
+ }
+ }
+ }
+
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ for (MarkerShareMusic shareMediaMarkerInfo : mtShareMusicList) {
+ if (!TextUtils.isEmpty(mMediaInfoData.getMediaId()) && TextUtils.equals(shareMediaMarkerInfo.getMediaId(), mMediaInfoData.getMediaId())) {
+ shareMediaMarkerInfo1 = shareMediaMarkerInfo;
+ break;
+ }
+ }
+ }
+
+ if (shareMediaMarkerInfo1 == null) {
+ //这里显示没有分享的样式
+ mShaerBackView.setVisibility(View.GONE);
+ mNoShareBackView.setVisibility(View.VISIBLE);
+ mShareSongNameTextView.setText("");
+ mShareSingerNameTextView.setText("");
+ mShareUserNameTextView.setText("");
+ String imgUrl = mMediaInfoData.getMediaImg();
+ RequestOptions requestOptions = new RequestOptions()
+ .placeholder(R.drawable.module_media_share_default_icon)
+ .dontAnimate()
+ .diskCacheStrategy(DiskCacheStrategy.RESOURCE);
+ GlideApp.with(mContext).applyDefaultRequestOptions(requestOptions).load(imgUrl != null ? imgUrl : "").into(mNoShareSongImageView);
+ mNoShareSongNameTextView.setText(mMediaInfoData.getMediaName());
+ mNoShareSingerNameTextView.setText(mMediaInfoData.getMediaSinger());
+
+ if (mAnimalSurfaceView != null && mCardCenter && mMediaInfoData.getPlayState() == 1){
+ mAnimalSurfaceView.setVisibility(View.VISIBLE);
+ if (mFragmentResume)mAnimalSurfaceView.start(true);
+ }else{
+ if (mAnimalSurfaceView != null){
+ mAnimalSurfaceView.setVisibility(View.GONE);
+ mAnimalSurfaceView.pause();
+ }
+ }
+ } else {
+ //这里显示有分享的样式 并且请求点赞个数
+ mShaerBackView.setVisibility(View.VISIBLE);
+ mNoShareBackView.setVisibility(View.GONE);
+ if (mAnimalSurfaceView != null){
+ mAnimalSurfaceView.setVisibility(View.GONE);
+ mAnimalSurfaceView.pause();
+ }
+
+ mNoShareSongNameTextView.setText("");
+ mNoShareSingerNameTextView.setText("");
+
+ if (mMediaInfoData != null){
+ String musicImg = mMediaInfoData.getMediaImg();
+ RequestOptions musicImgRequestOptions = new RequestOptions()
+ .placeholder(R.drawable.module_media_share_default_rect_icon)
+ .dontAnimate()
+ .diskCacheStrategy(DiskCacheStrategy.RESOURCE);
+ GlideApp.with(getContext()).applyDefaultRequestOptions(musicImgRequestOptions).load(musicImg != null ? musicImg : "").into(mShareSongImageView);
+ mShareSongNameTextView.setText(mMediaInfoData.getMediaName());
+ mShareSingerNameTextView.setText(mMediaInfoData.getMediaSinger());
+ }
+
+ MarkerUserInfo markerUserInfo = shareMediaMarkerInfo1.getUserInfo();
+ if (markerUserInfo != null){
+ String userImg = markerUserInfo.getUserHead();
+ RequestOptions requestOptions = new RequestOptions()
+ .placeholder(R.drawable.module_media_head_default_img)
+ .dontAnimate()
+ .diskCacheStrategy(DiskCacheStrategy.RESOURCE);
+ GlideApp.with(mContext).applyDefaultRequestOptions(requestOptions).load(userImg != null ? userImg : "").into(mShareUserHeardImageView);
+ mShareUserNameTextView.setText(shareMediaMarkerInfo1.getUserInfo().getUserName());
+
+ // mShareLikeNumTextView.setText(mLikeDataResult != null ? mLikeDataResult.likedCount+"":shareMediaMarkerInfo1.getLikeNumber()+"");
+ }
+
+ if (mPresenter != null && change){
+ mPresenter.selectByPrimaryKey(shareMediaMarkerInfo1.getId(),mMediaInfoData.getMediaId());
+ }
+ }
+
+ if (mMediaInfoData.isLocalMedia()) {
+ //不能分项
+ mShareImageView.setVisibility(View.GONE);
+ } else {
+ //可以分享
+ mShareImageView.setVisibility(View.VISIBLE);
+ }
+
+ }
+
+ private class PlayingMusicReceiver extends BroadcastReceiver{
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ try {
+ if (intent != null){
+ String mediaStr = intent.getStringExtra("mediaData");
+ if (!TextUtils.isEmpty(mediaStr)){
+ MediaInfoData data = (MediaInfoData) GsonUtil.arrayFromJson(mediaStr, MediaInfoData.class);
+ if (data != null){
+ MusicControlBroadCast.listeningSendData(data);
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private class MediaCenterReceiver extends BroadcastReceiver{
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ try {
+ if (intent != null){
+ cardToCenter();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private class MediaSpeechShareReceiver extends BroadcastReceiver{
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent != null){
+ String cmdStr = intent.getStringExtra("command");
+ Logger.d(TAG,"MediaSpeechShareReceiver"+cmdStr);
+ if (cmdStr.equals("com.zhidao.multiMedia.share.allow")){
+ //告诉小智语音,是否可以分享
+ String typeStr = "音乐";
+ try {
+ String typeJson = intent.getExtras().getString("data");
+ ShareMediaJsonData data = GsonUtil.objectFromJson(typeJson, ShareMediaJsonData.class);
+ if (data != null) typeStr = data.type;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ if (typeStr == null) typeStr = "音乐";
+
+ int type = 1;
+ if (typeStr.equals("音乐")){
+ type = 1;
+ }else if (typeStr.equals("书籍")){
+ type = 2;
+ }else if (typeStr.equals("新闻")){
+ type = 3;
+ }else{
+ type = 1;
+ }
+ boolean canShare = false;
+ String why = "没有可分享音频";
+ int cannotType = 2;
+ if (mFragmentResume && mCardCenter && mMediaInfoData != null && !mMediaInfoData.isLocalMedia() && mMediaInfoData.getType() == type){
+ canShare = true;
+ }else{
+ canShare = false;
+ }
+
+ if (!mCardCenter){
+ why = "媒体卡片不在C位";
+ cannotType = 1;
+ canShare = false;
+ }
+
+ boolean tneedAuthor = ServiceMediaHandler.getMogoAuthorizeModuleManager().needAuthorize(AuthorizeInvokerConstant.AUTHORIZE_TYPE_LAUNCHER_SHARE_MUSIC);
+ Logger.d(TAG,"是否授权 "+tneedAuthor+" resume "+mFragmentResume);
+
+ if (!canShare){
+ MusicControlBroadCast.ifCanShare(false,tneedAuthor,cannotType,why);
+ return;
+ }
+
+ if (tneedAuthor){//需要授权
+ if (mMediaInfoData != null) {
+ mShowPlayState = mMediaInfoData.getPlayState();
+ if (mShowPlayState == 1) {
+ MusicControlBroadCast.commandPlayPause(mMediaInfoData.getType(),mMediaInfoData.getPlayState());
+ }
+ }
+ mAuthorShow = true;
+ closeAdasEvent();
+ ServiceMediaHandler.getMogoAuthorizeModuleManager().invokeAuthorization(AuthorizeInvokerConstant.AUTHORIZE_TYPE_LAUNCHER_SHARE_MUSIC);
+ cannotType = 2;
+ canShare = false;
+ }
+
+ MusicControlBroadCast.ifCanShare(canShare,!tneedAuthor,cannotType,why);
+ if (canShare){
+ showShareDialog();
+ }
+ }
+ }
+
+ }
+ }
+
+ /**
+ * 音频播放状态改变广播监听
+ */
+ private class MediaStateReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ //用于请求点赞数
+ boolean change = false;
+ boolean cancleChoose = false;
+ String ttMid = "";
+ if (intent != null) {
+ int type = intent.getIntExtra("type", -1);
+ int playState = intent.getIntExtra(QQMusicFieldConstants.playState, 0);
+ Logger.d("MediaStateReceiver", "===MediaStateReceiver==playState=="+playState+" type= "+type);
+ if (playState == 1) {
+ isFirstPlay = false;
+ if (mMusicPlay != null){
+ mMusicPlay.setImageResource(R.drawable.module_media_suspend);
+ }
+
+ if (mWindowPlayPause != null){
+ mWindowPlayPause.setImageResource(R.drawable.module_media_window_pop_play);
+ }
+
+ if (mCircleImg != null){
+ if (!mCardCenter && mFragmentResume){
+ mCircleImg.startAnim();
+ }else{
+ mCircleImg.stopAnim();
+ }
+ }
+
+ } else {
+ if (mMusicPlay != null){
+ mMusicPlay.setImageResource(R.drawable.module_media_play);
+ }
+
+ if (mWindowPlayPause != null){
+ mWindowPlayPause.setImageResource(R.drawable.module_media_window_pop_pause);
+ }
+ if (mAnimalSurfaceView != null){
+ mAnimalSurfaceView.setVisibility(View.GONE);
+ mAnimalSurfaceView.pause();
+ }
+
+ if (mCircleImg != null) mCircleImg.stopAnim();
+
+ if (type == 1 || type == 2 || type ==3){
+ UiThreadHandler.removeCallbacks(mRunnable);
+ UiThreadHandler.postDelayed(mRunnable,3000);
+ }
+
+ }
+
+ if (playState == 1 || playState == 2){
+ if (type == 1) {//qq音乐
+
+ int maxTime = intent.getIntExtra(QQMusicFieldConstants.maxTime, 0);
+ int curTime = intent.getIntExtra(QQMusicFieldConstants.curTime, 0);
+ String mediaName = intent.getStringExtra(QQMusicFieldConstants.mediaName);
+ String mediaUrl = intent.getStringExtra(QQMusicFieldConstants.mediaUrl);
+ String mediaSinger = intent.getStringExtra(QQMusicFieldConstants.mediaSinger);
+ String mediaImgUrl = intent.getStringExtra(QQMusicFieldConstants.mediaImgUrl);
+ String mediaType = intent.getStringExtra(QQMusicFieldConstants.mediaType);
+ String mediaMid = intent.getStringExtra(QQMusicFieldConstants.mediaMid);
+ int mediaPLayMode = intent.getIntExtra(QQMusicFieldConstants.mediaPlayMode, -1);
+ boolean isLocalMedia = intent.getBooleanExtra(QQMusicFieldConstants.isLocalMedia, false);
+
+ if (playState == 1 || playState == 2) {
+ mRightTimeTextView.setText(Utils.calculateTime(maxTime * 1000));
+ // mLeftTimeTextView.setText(Utils.calculateTime(curTime * 1000));
+ if (playState == 1){
+ if (mMediaInfoData == null){
+ change = true;
+ ttMid = "";
+ }else{
+ ttMid = mMediaInfoData.getMediaId();
+ }
+ if (mMediaInfoData != null && mMediaInfoData.getMediaId() != null && !mMediaInfoData.getMediaId().equals(mediaMid)) {
+ change = true;
+ }
+ }
+ }
+
+ if (mMediaInfoData == null) {
+ mMediaInfoData = new MediaInfoData();
+ }
+ mMediaInfoData.setType(type);
+ mMediaInfoData.setPlayState(playState);
+ mMediaInfoData.setMaxTime(maxTime * 1000);
+ mMediaInfoData.setCurTime(curTime * 1000);
+ mMediaInfoData.setMediaName(mediaName);
+ mMediaInfoData.setMediaUrl(mediaUrl);
+ mMediaInfoData.setMediaId(mediaMid);
+ mMediaInfoData.setMediaImg(mediaImgUrl);
+ mMediaInfoData.setMediaSinger(mediaSinger);
+ mMediaInfoData.setMediaPlayMode(mediaPLayMode);
+ mMediaInfoData.setLocalMedia(isLocalMedia);
+ mMediaInfoData.setMediaType(mediaType);
+ mMediaInfoData.setBookInfo("");
+
+ if (playState == 1 && mShowSharePush && mCardCenter) {
+ //播放分享推荐消息
+ showSharePushVoice();
+ }
+
+ } else if (type == 2) {//懒人听书
+
+ int maxTime = intent.getIntExtra(LeTingFieldConstants.maxTime, 0);
+ int curTime = intent.getIntExtra(LeTingFieldConstants.curTime, 0);
+
+ String mediaName = intent.getStringExtra(LeTingFieldConstants.mediaName);//章节数
+ String bookInfoStr = intent.getStringExtra(LeTingFieldConstants.bookInfo);
+ LanRenInsertData lanRenInsertData = GsonUtil.objectFromJson(bookInfoStr, LanRenInsertData.class);
+
+ String bookName = ""; // 书名 需要从bookinfo里面取
+ String cover = ""; //封面 bookinfo中取
+ String bookid = "";
+
+ try {
+ if (lanRenInsertData != null){
+ bookName = lanRenInsertData.getName(); // 书名 需要从bookinfo里面取
+ cover = lanRenInsertData.getCover(); //封面 bookinfo中取
+ bookid = lanRenInsertData.getBookId() + "";
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+
+ if (playState == 1 || playState == 2){
+ mRightTimeTextView.setText(Utils.calculateTime(maxTime));
+ // mLeftTimeTextView.setText(Utils.calculateTime(curTime));
+ if (playState == 1 || playState == 2){
+ if (mMediaInfoData == null){
+ change = true;
+ ttMid = "";
+ }else{
+ ttMid = mMediaInfoData.getMediaId();
+ }
+ if (mMediaInfoData != null && mMediaInfoData.getMediaId() != null && !mMediaInfoData.getMediaId().equals(bookid)) {
+ change = true;
+ }
+ }
+
+ }
+
+ if (mMediaInfoData == null) {
+ mMediaInfoData = new MediaInfoData();
+ }
+ mMediaInfoData.setType(type);
+ mMediaInfoData.setPlayState(playState);
+ mMediaInfoData.setMaxTime(maxTime);
+ mMediaInfoData.setCurTime(curTime);
+ if (!TextUtils.isEmpty(bookName)){
+ mMediaInfoData.setMediaName(bookName); //bookName 或者mediaName
+ }else if (!TextUtils.isEmpty(mediaName)){
+ mMediaInfoData.setMediaName(mediaName); //bookName 或者mediaName
+ }
+ mMediaInfoData.setMediaSinger(mediaName); //章节数
+ mMediaInfoData.setMediaImg(cover); //书籍封面
+ mMediaInfoData.setMediaId(bookid);//书籍的bookid int
+ mMediaInfoData.setBookInfo(bookInfoStr);
+ mMediaInfoData.setMediaUrl("");
+ mMediaInfoData.setLocalMedia(false);
+ mMediaInfoData.setMediaType("");
+
+ } else if (type == 3) {//乐听头条
+ int maxTime = intent.getIntExtra(LeTingFieldConstants.maxTime, 0);
+ int curTime = intent.getIntExtra(LeTingFieldConstants.curTime, 0);
+ String mediaName = intent.getStringExtra(LeTingFieldConstants.mediaName); //新闻title
+ String artist = intent.getStringExtra(LeTingFieldConstants.artist); //新闻来源,赋值给singer mediaSinger
+ String cover = intent.getStringExtra(LeTingFieldConstants.cover); //封面
+ String bookInfo = intent.getStringExtra("news");//新闻实体
+ String bookid = "";
+ try {
+ if (!TextUtils.isEmpty(bookInfo)){
+ LeTingNewsData leTingNewsData = GsonUtil.objectFromJson(bookInfo, LeTingNewsData.class);
+ if (leTingNewsData != null){
+ mediaName = leTingNewsData.getTitle();
+ artist = leTingNewsData.getSource();
+ cover = leTingNewsData.getImage();
+ bookid = leTingNewsData.getSid();
+ }
+
+ if (mediaName == null) mediaName = "";
+ if (artist == null) artist = "";
+ if (cover == null) cover = "";
+ if (bookid == null) bookid = "";
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+
+ if (playState == 1 || playState == 2){
+ mRightTimeTextView.setText(Utils.calculateTime(maxTime));
+ if (mMediaInfoData == null){
+ change = true;
+ ttMid = "";
+ }else{
+ ttMid = mMediaInfoData.getMediaId();
+ }
+ if (mMediaInfoData != null && mMediaInfoData.getMediaId() != null && !mMediaInfoData.getMediaId().equals(bookid)) {
+ change = true;
+ }
+ }
+
+ mMediaInfoData.setType(type);
+ mMediaInfoData.setPlayState(playState);
+ mMediaInfoData.setMaxTime(maxTime);
+ mMediaInfoData.setCurTime(curTime);
+ mMediaInfoData.setMediaName(mediaName); //新闻标题
+ mMediaInfoData.setMediaSinger(artist); //新闻来源
+ mMediaInfoData.setMediaImg(cover); //新闻封面
+
+ mMediaInfoData.setMediaId(bookid);//新闻的sid
+ mMediaInfoData.setBookInfo(bookInfo);
+ mMediaInfoData.setMediaUrl("");
+ mMediaInfoData.setLocalMedia(false);
+ mMediaInfoData.setMediaType("");
+
+ }
+
+ try {
+ if (mMediaInfoData != null && (type == 1 || type == 2)){
+ ThreadPoolService.execute(new Runnable() {
+ @Override
+ public void run() {
+ String tmData = GsonUtil.jsonFromObject(mMediaInfoData);
+ StorageManager.setLastListenMediaMusic(tmData);
+ Logger.d(TAG,"save"+tmData != null ? tmData:"");
+ }
+ });
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ if (change) {
+ changePlayMusic(mMediaInfoData);
+ }
+
+ //播放另外一个时去掉选中状态
+ if (!ttMid.equals(mMediaInfoData.getMediaId())){
+ cancleChoose = true;
+ }
+ if (cancleChoose && mMediaInfoData != null && (playState == 1 || playState == 2)){
+ if (ServiceMediaHandler.getMarkerManager() != null){
+ List< IMogoMarker > mogoMarkersList = ServiceMediaHandler.getMarkerManager().getMarkers(MediaConstants.MODULE_TYPE);
+ try {
+ if ( mogoMarkersList != null && mogoMarkersList.size() > 0){
+ for (IMogoMarker mogoMarker : mogoMarkersList){
+ if (mogoMarker != null && !mogoMarker.isDestroyed()){
+ if (mogoMarker.getObject() != null && mogoMarker.getObject() instanceof MarkerShowEntity){
+ MarkerShowEntity markerShowEntity = (MarkerShowEntity) mogoMarker.getObject();
+ if (markerShowEntity.getBindObj() != null && markerShowEntity.getBindObj() instanceof MarkerShareMusic){
+ MarkerShareMusic markerShareMusic = (MarkerShareMusic) markerShowEntity.getBindObj();
+ if (markerShowEntity.isChecked() && !markerShareMusic.getMediaId().equals(mMediaInfoData.getMediaId())){
+// MapMarkerManager.getInstance().closeMarkerSelect(mogoMarker);
+ break;
+ }
+ }
+
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ if (playState == 1 || playState == 2){
+ if (mTwoChange){
+ change = true;
+ mTwoChange = false;
+ }
+ if (change) {
+ mLikeDataResult = null;
+ if (mShareLikeImageView != null)mShareLikeImageView.setImageResource(R.drawable.module_media_no_heart);
+ }
+
+ Logger.d(TAG,"onreceive state change = "+change+" mediaid= "+mMediaInfoData.getMediaId());
+ ifNeedRefreshMediaCard(change);
+ }
+
+ //pop window 弹窗
+ if (mMediaInfoData != null && !TextUtils.isEmpty(mMediaInfoData.getMediaName()) && !TextUtils.isEmpty(mMediaInfoData.getMediaSinger())){
+ if (mFullScreenImageView != null && mFullScreenImageView.getVisibility() == View.GONE){
+ mFullScreenImageView.setVisibility(View.VISIBLE);
+ }
+ if (!mHasAddWindow){
+ addWindowView();
+ }else{
+ if (playState == 1 || playState == 2){
+ updateWindowUI();
+ }
+ }
+ }
+
+ }
+
+ if (playState == 1) {
+ mPresenter.startedMusic(mMediaInfoData);
+ } else {
+ if (mMediaInfoData != null){
+ mMediaInfoData.setPlayState(playState);
+ }
+ mPresenter.stopMusic();
+ }
+
+ }
+ }
+
+ }
+
+ /**
+ * 音频进度改变广播接收者
+ */
+ private class MediaProcessReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent != null) {
+ int curTime = intent.getIntExtra("curTime", -1);
+ Logger.d("MediaProcessReceiver", "===MediaProcessReceiver===="+curTime);
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (mMediaInfoData != null) {
+ if (mLeftTimeTextView != null) {
+ mLeftTimeTextView.setText(Utils.calculateTime(curTime));
+ }
+
+ if (mWindowCurrTime !=null){
+ mWindowCurrTime.setText(Utils.calculateTime(curTime));
+ }
+
+ try {
+ if (mProgressBar != null) {
+ int progress = (int) ((curTime * 1.0f * 100) / (mMediaInfoData.getMaxTime() * 1.0f));
+ mProgressBar.setProgress(progress);
+ if (mWindowProgress != null){
+ mWindowProgress.setProgress(progress);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+ }
+ });
+ }
+ }
+
+ }
+
+ /**
+ * 获取新闻是否付费
+ * com.zhidao.mediacenter.ltnewsPayInfo
+ */
+ private class MediaNewsPayInfo extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent != null) {
+ boolean playinfo = intent.getBooleanExtra("payinfo", false);
+ boolean appActive = ActivityLifecycleManager.getInstance().isAppActive();
+ appActive = isMediaResume;
+ String category = MediaSpeechReceiver.mCategoryStr;
+ MediaSpeechReceiver.mCategoryStr = "";
+ Logger.d(TAG," MediaNewsPayInfo "+"news "+category == null?"":category+" "+appActive);
+ if (playinfo){
+ if (TextUtils.isEmpty(category)){
+ //打开新闻
+ //播放某一类型新闻
+ if (appActive){
+ MusicControlBroadCast.sendPlayTypeNews("推荐");
+ cardToCenter();
+ }else{
+ MusicControlBroadCast.sendPlayTypeNewsOpenApp("推荐");
+ }
+ }else{
+ //播放某一类型新闻
+ if (appActive){
+ MusicControlBroadCast.sendPlayTypeNews(category);
+ cardToCenter();
+ }else{
+ MusicControlBroadCast.sendPlayTypeNewsOpenApp(category);
+ }
+ }
+ }else{
+ MusicControlBroadCast.openMediaApp(3);
+ }
+ }
+ }
+
+ }
+
+ private void registerMediaReceiver() {
+ mediaStateReceiver = new MediaCardViewFragment.MediaStateReceiver();
+ IntentFilter filterone = new IntentFilter();
+ filterone.addAction("com.zhidao.action.MEDIA_LRTS");
+ filterone.addAction("com.zhidao.action.MEDIA_LT_NEWS");
+ filterone.addAction("com.qq.music.status.change");
+ getContext().registerReceiver(mediaStateReceiver, filterone);
+
+ mediaProcessReceiver = new MediaCardViewFragment.MediaProcessReceiver();
+ IntentFilter filtertwo = new IntentFilter();
+ filtertwo.addAction("com.zhidao.action.MEDIA_PROGRESS");
+ getContext().registerReceiver(mediaProcessReceiver, filtertwo);
+
+ playingMusicReceiver = new PlayingMusicReceiver();
+ IntentFilter filterthree = new IntentFilter();
+ filterthree.addAction("com.mogo.launcher.media.listening");
+ getContext().registerReceiver(playingMusicReceiver, filterthree);
+
+ mediaNewsPayInfo = new MediaNewsPayInfo();
+ IntentFilter filterFour = new IntentFilter();
+ filterFour.addAction("com.zhidao.mediacenter.ltnewsPayInfo");
+ getContext().registerReceiver(mediaNewsPayInfo, filterFour);
+
+ mediaCenterReceiver = new MediaCenterReceiver();
+ IntentFilter filterFive = new IntentFilter();
+ filterFive.addAction("com.mogo.launcher.media.card.center");
+ getContext().registerReceiver(mediaCenterReceiver, filterFive);
+
+ //分享语音回调 -> 需要参数,分享的类型(音乐,书籍,新闻)
+ mediaCanShareReceiver = new MediaSpeechShareReceiver();
+ IntentFilter filterSix = new IntentFilter();
+ filterSix.addAction("com.zhidao.speech.awake.notify");//分享的询问
+ getContext().registerReceiver(mediaCanShareReceiver, filterSix);
+ }
+
+ private void unRegisterMediaReceiver() {
+ getContext().unregisterReceiver(mediaProcessReceiver);
+ getContext().unregisterReceiver(mediaStateReceiver);
+ getContext().unregisterReceiver(playingMusicReceiver);
+ getContext().unregisterReceiver(mediaNewsPayInfo);
+ getContext().unregisterReceiver(mediaCenterReceiver);
+ getContext().unregisterReceiver(mediaCanShareReceiver);
+ }
+
+ /**
+ * qq 音乐和懒人听书切换了不同的音频,不包括新闻
+ */
+ private void changePlayMusic(MediaInfoData data) {
+
+ }
+
+ private class MediaMogoStatusManager implements IMogoStatusChangedListener{
+
+ @Override
+ public void onStatusChanged(StatusDescriptor descriptor, boolean isTrue) {
+ Logger.d(TAG,"==onStatusChanged== "+isTrue);
+ mAdasShow = isTrue;
+ if (!isTrue && mLastAdasMarker != null && mLastAdasMarker.size() > 0){
+
+ try {
+ for (MarkerShareMusic markerShareMusic:mLastAdasMarker){
+ if (markerShareMusic != null && !TextUtils.isEmpty(markerShareMusic.getMediaId())){
+ drawMarkerShareMusicMarker(markerShareMusic);
+ }
+ }
+
+ drawMarkerAndBounds(mLastAdasMarker);
+
+ UiThreadHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ ifNeedRefreshMediaCard(true);
+ }
+ },500);
+
+ mLastAdasMarker.clear();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private class MediaMogoVoiceListener implements IMogoIntentListener {
+
+ @Override
+ public void onIntentReceived(String action, Intent intent) {
+ //此处接收注册的需要唤醒的指令
+ if (!TextUtils.isEmpty(action)){
+ if (action.equals( "com.zhidao.music.friend.query")){
+ //播放好友的歌
+ if (mPresenter != null){
+ mPresenter.getFriendMusic();
+ }
+ }else if (action.equals("com.zhidao.music.user.query")){
+ //播放附近的人的歌
+ if (mPresenter != null){
+ mPresenter.getNearShareMusic();
+ }
+ }else if (action.equals("com.mogo.launcher.media.share.dialog.close")){
+ //关闭分享
+ destroyShareDialogFragment();
+ }
+ }
+ }
+ }
+
+ /**
+ * 注册免唤醒 分享命令
+ */
+ private void registerNoWakeUpShareCmd() {
+ shareNoWakeUpCmd();
+ }
+
+ private void shareNoWakeUpCmd() {
+ AIAssist.getInstance(getActivity())
+ .registerUnWakeupCommand(
+ VoiceConstants.COMMAND_NO_WAKEUP_SHARE_MUSIC_CMD
+ , VoiceConstants.COMMAND_NO_WAKEUP_MUSIC_SHARE, new IMogoVoiceCmdCallBack() {
+ @Override
+ public void onCmdSelected(String cmd) {
+ if (mCardCenter && VoiceConstants.COMMAND_NO_WAKEUP_SHARE_MUSIC_CMD.equals(cmd)) {
+
+ if (mMediaInfoData != null && mMediaInfoData.getType() == 1){
+ showShareDialogEvent();
+ showShareDialog();
+ }else{
+ if (mMediaInfoData != null){
+ AIAssist.getInstance(getActivity()).speakTTSVoice("当前音频不可分享",null);
+ }else{
+ AIAssist.getInstance(getActivity()).speakTTSVoice("当前没有音频可分享",null);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onSpeakEnd(String speakText) {
+
+ }
+
+ @Override
+ public void onSpeakSelectTimeOut(String speakText) {
+
+ }
+
+ @Override
+ public void onCmdAction(String speakText) {
+
+ }
+
+ @Override
+ public void onCmdCancel(String speakText) {
+
+ }
+ });
+
+ AIAssist.getInstance(getActivity())
+ .registerUnWakeupCommand(
+ VoiceConstants.COMMAND_NO_WAKEUP_SHARE_BOOK_CMD
+ , VoiceConstants.COMMAND_NO_WAKEUP_BOOK_SHARE, new IMogoVoiceCmdCallBack() {
+ @Override
+ public void onCmdSelected(String cmd) {
+ if (mCardCenter && VoiceConstants.COMMAND_NO_WAKEUP_SHARE_BOOK_CMD.equals(cmd)) {
+ if (mMediaInfoData != null && mMediaInfoData.getType() == 2){
+ showShareDialog();
+ showShareDialogEvent();
+ }else{
+ if (mMediaInfoData != null){
+ AIAssist.getInstance(getActivity()).speakTTSVoice("当前音频不可分享",null);
+ }else{
+ AIAssist.getInstance(getActivity()).speakTTSVoice("当前没有音频可分享",null);
+ }
+ }
+
+ }
+ }
+
+ @Override
+ public void onSpeakEnd(String speakText) {
+
+ }
+
+ @Override
+ public void onSpeakSelectTimeOut(String speakText) {
+
+ }
+
+ @Override
+ public void onCmdAction(String speakText) {
+ }
+
+ @Override
+ public void onCmdCancel(String speakText) {
+ }
+ });
+
+ AIAssist.getInstance(getActivity())
+ .registerUnWakeupCommand(
+ VoiceConstants.COMMAND_NO_WAKEUP_SHARE_BOOK_MUSIC_CMD
+ , VoiceConstants.COMMAND_NO_WAKEUP_BOOK_MUSIC_SHARE, new IMogoVoiceCmdCallBack() {
+ @Override
+ public void onCmdSelected(String cmd) {
+ if (!isShareDialogShowing()){
+ if (mCardCenter && VoiceConstants.COMMAND_NO_WAKEUP_SHARE_BOOK_MUSIC_CMD.equals(cmd)) {
+ if (mMediaInfoData != null){
+ showShareDialog();
+ showShareDialogEvent();
+ }else{
+ if (mMediaInfoData != null){
+ AIAssist.getInstance(getActivity()).speakTTSVoice("当前音频不可分享",null);
+ }else{
+ AIAssist.getInstance(getActivity()).speakTTSVoice("当前没有音频可分享",null);
+ }
+ }
+
+ }
+ }
+ }
+
+ @Override
+ public void onSpeakEnd(String speakText) {
+
+ }
+
+ @Override
+ public void onSpeakSelectTimeOut(String speakText) {
+
+ }
+
+ @Override
+ public void onCmdAction(String speakText) {
+ }
+
+ @Override
+ public void onCmdCancel(String speakText) {
+ }
+ });
+
+ AIAssist.getInstance(getActivity())
+ .registerUnWakeupCommand(
+ VoiceConstants.COMMAND_NO_WAKEUP_SHARE_NEWS_CMD
+ , VoiceConstants.COMMAND_NO_WAKEUP_NEWS_SHARE, new IMogoVoiceCmdCallBack() {
+ @Override
+ public void onCmdSelected(String cmd) {
+ if (!isShareDialogShowing()){
+ if (mCardCenter && VoiceConstants.COMMAND_NO_WAKEUP_SHARE_NEWS_CMD.equals(cmd)) {
+ if (mMediaInfoData != null){
+ showShareDialog();
+ showShareDialogEvent();
+ }else{
+ if (mMediaInfoData != null){
+ AIAssist.getInstance(getActivity()).speakTTSVoice("当前音频不可分享",null);
+ }else{
+ AIAssist.getInstance(getActivity()).speakTTSVoice("当前没有音频可分享",null);
+ }
+ }
+
+ }
+ }
+ }
+
+ @Override
+ public void onSpeakEnd(String speakText) {
+
+ }
+
+ @Override
+ public void onSpeakSelectTimeOut(String speakText) {
+
+ }
+
+ @Override
+ public void onCmdAction(String speakText) {
+ }
+
+ @Override
+ public void onCmdCancel(String speakText) {
+ }
+ });
+ }
+
+ private void showShareDialogEvent() {
+ try {
+ if (mMediaInfoData != null){
+ HashMap hashMap = new HashMap<>();
+ hashMap.put("type",2);
+ String trackId = "";
+ if (mMediaInfoData.getType() == 1){
+ trackId = EventConstants.EVENT_QQ_OPEN_SHARE_DIALOG_SHOW;
+ }else if (mMediaInfoData.getType() == 2){
+ trackId = EventConstants.EVENT_BOOK_OPEN_SHARE_DIALOG_SHOW;
+ }else if (mMediaInfoData.getType() == 3){
+ trackId = EventConstants.EVENT_NEWS_OPEN_SHARE_DIALOG_SHOW;
+ }
+ MediaAnalyticsUtils.track(trackId,hashMap);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 播放push share 语音
+ */
+ private void showSharePushVoice() {
+ mShowSharePush = false;
+ AIAssist.getInstance(getActivity()).speakQAndACmd(VoiceConstants.COMMAND_SHARE_MUSIC_PUSH_MESSAGE
+ , VoiceConstants.COMMAND_SHARE_MUSIC_PUSH_MESSAGE_OK, VoiceConstants.COMMAND_SHARE_MUSIC_PUSH_MESSAGE_CANCEL
+ , new IMogoVoiceCmdCallBack() {
+
+ @Override
+ public void onSpeakEnd(String speakText) {
+ Logger.d(TAG,"showSharePushVoice"+"speakEnd"+speakText);
+ }
+
+ @Override
+ public void onSpeakSelectTimeOut(String speakText) {
+
+ }
+
+ @Override
+ public void onCmdAction(String speakText) {
+ //弹出分享框
+ boolean needAuthor = ServiceMediaHandler.getMogoAuthorizeModuleManager().needAuthorize(AuthorizeInvokerConstant.AUTHORIZE_TYPE_LAUNCHER_SHARE_MUSIC);
+ Logger.d(TAG,"是否授权 "+needAuthor);
+ if (needAuthor){//需要授权
+ mAuthorShow = true;
+ closeAdasEvent();
+ ServiceMediaHandler.getMogoAuthorizeModuleManager().invokeAuthorization(AuthorizeInvokerConstant.AUTHORIZE_TYPE_LAUNCHER_SHARE_MUSIC);
+ }else{
+ mAuthorShow = false;
+ showShareDialog();
+ }
+
+ if (mMediaInfoData != null){
+ HashMap hashMap = new HashMap<>();
+ hashMap.put("type",2);
+ String trackId = "";
+ if (mMediaInfoData.getType() == 1){
+ trackId = EventConstants.EVENT_QQ_OPEN_SHARE_DIALOG_SHOW;
+ }else if (mMediaInfoData.getType() == 2){
+ trackId = EventConstants.EVENT_BOOK_OPEN_SHARE_DIALOG_SHOW;
+ }else if (mMediaInfoData.getType() == 3){
+ trackId = EventConstants.EVENT_NEWS_OPEN_SHARE_DIALOG_SHOW;
+ }
+ MediaAnalyticsUtils.track(trackId,hashMap);
+ }
+ }
+
+ @Override
+ public void onCmdCancel(String speakText) {
+
+ }
+
+ @Override
+ public void onCmdSelected(String cmd) {
+
+ }
+ });
+ }
+
+ /**
+ * 删除所有自己卡片的点
+ */
+ private void removeAllMyTypeMarker() {
+ ServiceMediaHandler.getMarkerManager().removeMarkers(MediaConstants.MODULE_TYPE);
+ }
+
+ private void addNewMarker(List shareMusic) {
+ if (ServiceMediaHandler.getIMogoStatusManager().isADASShow() || mAdasShow){
+ ServiceMediaHandler.getMogoADASController().closeADAS();
+ }
+ try {
+ removeAllMyTypeMarker();
+
+ UiThreadHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (shareMusic != null) {
+ for (MarkerShareMusic markerShareMusic : shareMusic) {
+ drawMarkerShareMusicMarker(markerShareMusic);
+ }
+
+ if (!mCardCenter){
+ ServiceMediaHandler.getMogoCardManager().switch2(MediaConstants.MODULE_TYPE);
+ }else{
+ ServiceMediaHandler.getMogoCardManager().switch2(MediaConstants.MODULE_TYPE);
+ }
+
+ ServiceMediaHandler.getMapUIController().changeZoom(16);
+
+ try {
+ drawMarkerAndBounds((ArrayList) shareMusic);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ Logger.d(TAG,"switch2 cardtype music");
+
+ }
+
+ if (shareMusic != null && shareMusic.size() > 0){
+ MusicControlBroadCast.addQQMusicShareListPlayList((ArrayList) shareMusic);
+ }
+ }
+ }, 1000);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onShareDialogShow() {
+ if (mMediaInfoData != null) {
+ mShowPlayState = mMediaInfoData.getPlayState();
+ if (mShowPlayState == 1) {
+ MusicControlBroadCast.commandPlayPause(mMediaInfoData.getType(),mMediaInfoData.getPlayState());
+ }
+ }
+ }
+
+ @Override
+ public void onShareDialogDismiss(boolean success,MarkerShareMusic markerShareMusic) {
+ shareSuccessResult(success, markerShareMusic);
+ }
+
+ @Override
+ public void shareSuccessResult(boolean success, MarkerShareMusic markerShareMusic) {
+ if (success) {
+ mTwoChange = true;
+ mShowSharePush = false;
+ }
+ if (mShowPlayState == 1) {
+ MusicControlBroadCast.commandPlayPause(mMediaInfoData.getType(),mMediaInfoData.getPlayState());
+ }
+
+ UiThreadHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ ifNeedRefreshMediaCard(true);
+ }
+ },500);
+
+ try {
+ if (success && markerShareMusic != null && !TextUtils.isEmpty(markerShareMusic.getMediaId())){
+ if (ServiceMediaHandler.getIMogoStatusManager().isADASShow() || mAdasShow){
+ mLastAdasMarker.add(markerShareMusic);
+ }else{
+ drawMarkerShareMusicMarker(markerShareMusic);
+ }
+
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void drawMarkerShareMusicMarker(MarkerShareMusic markerShareMusic) {
+ MarkerLocation markerLocation = markerShareMusic.getLocation();
+ MarkerShowEntity markerShowEntity = new MarkerShowEntity();
+ markerShowEntity.setBindObj(markerShareMusic);
+ markerShowEntity.setMarkerLocation(markerLocation);
+ markerShowEntity.setMarkerType(markerShareMusic.getType());
+ markerShowEntity.setTextContent(markerShareMusic.getMediaName());
+ markerShowEntity.setIconUrl(markerShareMusic.getMediaImg());
+
+ ServiceMediaHandler.getMarkerService().drawMarker( markerShowEntity );
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mFragmentResume = false;
+ isMediaResume = false;
+ if (mMediaInfoData != null && mWindowView != null ) {
+ if (mMediaInfoData.getType() == 1 || mMediaInfoData.getType() == 2 || mMediaInfoData.getType() == 3){
+ if (mCircleImg != null && mCircleImg.isRotationing()) {
+ mCircleImg.stopAnim();
+ }
+ }
+ }
+ if (mAnimalSurfaceView != null && mAnimalSurfaceView.getVisibility() == View.VISIBLE){
+ mAnimalSurfaceView.pause();
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mFragmentResume = true;
+ isMediaResume = true;
+ if (mMediaInfoData != null && mWindowView != null && !mCardCenter) {
+ if (mMediaInfoData.getType() == 1 || mMediaInfoData.getType() == 2 || mMediaInfoData.getType() == 3){
+ if (mCircleImg != null && mMediaInfoData.getPlayState() == 1) {
+ mCircleImg.startAnim();
+ }
+ }
+ }
+ if (mMediaInfoData != null && mMediaInfoData.getPlayState() == 1 && mCardCenter && mAnimalSurfaceView != null && mAnimalSurfaceView.getVisibility() == View.VISIBLE ){
+ mAnimalSurfaceView.start(true);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ try {
+ UiThreadHandler.removeCallbacks(mRunnable);
+ mRunnable = null;
+ mLastMusicImageView.setOnClickListener(null);
+ mMusicPlay.setOnClickListener(null);
+ mNextMusicImageView.setOnClickListener(null);
+ mShareImageView.setOnClickListener(null);
+ mShareLikeImageView.setOnClickListener(null);
+ ServiceMediaHandler.getIMogoStatusManager().unregisterStatusChangedListener(MediaConstants.MODULE_TYPE,StatusDescriptor.ADAS_UI,mMogoStatusChangeListener);
+ ServiceMediaHandler.getMogoAuthorizeModuleManager().unregisterAuthorizeListener(AuthorizeInvokerConstant.AUTHORIZE_TYPE_LAUNCHER_SHARE_MUSIC);
+
+ if (mAnimalSurfaceView != null){
+ mAnimalSurfaceView.destroy();
+ mAnimalSurfaceView = null;
+ }
+ unRegisterMediaReceiver();
+ destroyShareDialogFragment();
+ if (mCircleImg != null && mCircleImg.isRotationing()) {
+ mCircleImg.stopAnim();
+ }
+
+ if (ServiceMediaHandler.getMogoWindowManager() != null){
+ ServiceMediaHandler.getMogoWindowManager().removeView(mWindowView);
+ }
+
+ if (ServiceMediaHandler.getMogoRegisterCenter() != null){
+ ServiceMediaHandler.getMogoRegisterCenter().unregisterMogoLocationListener(MediaConstants.MODULE_TYPE);
+ ServiceMediaHandler.getMogoRegisterCenter().unregisterMogoMapListener(MediaConstants.MODULE_TYPE);
+ ServiceMediaHandler.getMogoRegisterCenter().unregisterMogoMarkerClickListener(MediaConstants.MODULE_TYPE);
+ ServiceMediaHandler.getMogoRegisterCenter().unregisterMogoModuleLifecycle(MediaConstants.MODULE_TYPE);
+ }
+
+ if (ServiceMediaHandler.getMogoVoiceManager() != null){
+ ServiceMediaHandler.getMogoVoiceManager().unregisterIntentListener("com.zhidao.music.friend.query" ,mMediaVoiceListener);
+ ServiceMediaHandler.getMogoVoiceManager().unregisterIntentListener("com.zhidao.music.user.query" ,mMediaVoiceListener);
+ }
+
+ AIAssist.getInstance(getActivity()).unregisterUnWakeupCommand( VoiceConstants.COMMAND_NO_WAKEUP_SHARE_MUSIC_CMD);
+ AIAssist.getInstance(getActivity()).unregisterUnWakeupCommand( VoiceConstants.COMMAND_NO_WAKEUP_SHARE_BOOK_CMD);
+ AIAssist.getInstance(getActivity()).unregisterUnWakeupCommand( VoiceConstants.COMMAND_NO_WAKEUP_SHARE_NEWS_CMD);
+ AIAssist.getInstance(getActivity()).unregisterUnWakeupCommand( VoiceConstants.COMMAND_NO_WAKEUP_SHARE_BOOK_MUSIC_CMD);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 定位发生改变
+ *
+ * @param location 新定位点
+ */
+ @Override
+ public void onLocationChanged(MogoLocation location) {
+ if (location != null) {
+ // Logger.d("onLocationChanged", location.getLatitude() + " " + location.getLongitude());
+ }
+ }
+
+ public String getPackageName(){
+ if (mPresenter == null){
+ return "";
+ }else{
+ return mPresenter.getPackageName(mMediaInfoData);
+ }
+ }
+
+ public String getAppName(){
+ if (mPresenter == null){
+ return "";
+ }else{
+ return mPresenter.getAppName(mMediaInfoData);
+ }
+ }
+
+ public boolean isShareDialogShowing(){
+ if (mShareDilogFragment != null && mShareDilogFragment.getDialog() != null && mShareDilogFragment.getDialog().isShowing()) {
+ return true;
+ }else{
+ return false;
+ }
+ }
+
+ private void cardToCenter(){
+ ServiceMediaHandler.getMogoCardManager().switch2(MediaConstants.MODULE_TYPE);
+ }
+
+ private void drawMarkerAndBounds(ArrayList musicList){
+ final MogoLocation location = ServiceMediaHandler.getLocationClient().getLastKnowLocation();
+ if (location != null && musicList != null && musicList.size() > 0) {
+ MogoLatLng ownLatLng = new MogoLatLng(location.getLatitude(), location.getLongitude());
+ List locationList = new ArrayList<>();
+ for (int i = 1; i < musicList.size() && i < 6; i++) {
+ MarkerShareMusic mark = musicList.get(i);
+ MogoLatLng markLocation = new MogoLatLng(mark.getLocation().getLat(), mark.getLocation().getLon());
+ locationList.add(markLocation);
+ }
+ Rect rect = new Rect(
+ (int) getContext().getResources().getDimension(R.dimen.module_media_draw_rect_map_left),
+ (int) getContext().getResources().getDimension(R.dimen.module_media_draw_rect_map_top),
+ (int) getContext().getResources().getDimension(R.dimen.module_media_draw_rect_map_right),
+ (int) getContext().getResources().getDimension(R.dimen.module_media_draw_rect_map_bottom));
+ ServiceMediaHandler.getMapUIController().showBounds(MediaConstants.MODULE_TYPE, ownLatLng, locationList, rect, true);
+
+ }
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/MediaCardViewProvider.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/MediaCardViewProvider.java
new file mode 100644
index 0000000000..c4fdd84162
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/MediaCardViewProvider.java
@@ -0,0 +1,99 @@
+package com.mogo.module.media;
+
+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.media.window.MediaWindow2;
+import com.mogo.service.module.IMogoModuleLifecycle;
+import com.mogo.service.module.IMogoModuleProvider;
+import com.mogo.service.module.ModuleType;
+
+@Route( path = MediaConstants.TAG )
+public class MediaCardViewProvider implements IMogoModuleProvider {
+
+ private static final String TAG = "MediaCardViewProvider";
+ private MediaWindow2 mediaWindow2;
+
+ @Override
+ public Fragment createFragment( Context context, Bundle data ) {
+// fragment = new MediaCardViewFragment();
+// fragment.setArguments( data );
+// Logger.i( TAG, "createFragment" );
+ return null;
+ }
+
+ @Override
+ public void init( Context context ) {
+ ServiceMediaHandler.init( context );
+ mediaWindow2 = new MediaWindow2();
+ mediaWindow2.initMedia(context);
+ }
+
+ @Override
+ public String getModuleName() {
+ return MediaConstants.MODULE_TYPE;
+ }
+
+ @Override
+ public View createView( Context context ) {
+ // don't
+ return null;
+ }
+
+ @Override
+ public int getType() {
+ return ModuleType.TYPE_CARD_FRAGMENT;
+ }
+
+ @Override
+ public IMogoNaviListener getNaviListener() {
+ return null;
+ }
+
+
+ @Override
+ public IMogoModuleLifecycle getCardLifecycle() {
+ return null;
+ }
+
+ @Override
+ public IMogoMapListener getMapListener() {
+ return null;
+ }
+
+ @Override
+ public IMogoLocationListener getLocationListener() {
+ return null;
+ }
+
+ @Override
+ public IMogoMarkerClickListener getMarkerClickListener() {
+ return null;
+ }
+
+ @Override
+ public String getAppPackage() {
+ return "";
+ }
+
+ @Override
+ public String getAppName() {
+ return "";
+ }
+
+ @Override
+ public void onDestroy() {
+ if ( mediaWindow2 != null ) {
+ mediaWindow2.onDestroy();
+ }
+ mediaWindow2 = null;
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/MediaConstants.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/MediaConstants.java
new file mode 100644
index 0000000000..108ea4d744
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/MediaConstants.java
@@ -0,0 +1,9 @@
+package com.mogo.module.media;
+
+/**
+ * 卡片类型 name
+ */
+public class MediaConstants {
+ public static final String TAG = "/media/ui";
+ public static final String MODULE_TYPE = "CARD_TYPE_SHARE_MUSIC";
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/ServiceMediaHandler.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/ServiceMediaHandler.java
new file mode 100644
index 0000000000..b6da495fdc
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/ServiceMediaHandler.java
@@ -0,0 +1,206 @@
+package com.mogo.module.media;
+
+import android.content.Context;
+
+import com.alibaba.android.arouter.launcher.ARouter;
+import com.mogo.commons.AbsMogoApplication;
+import com.mogo.commons.debug.DebugConfig;
+import com.mogo.map.location.IMogoLocationClient;
+import com.mogo.map.marker.IMogoMarkerManager;
+import com.mogo.map.navi.IMogoNavi;
+import com.mogo.map.uicontroller.IMogoMapUIController;
+import com.mogo.module.authorize.authprovider.invoke.AuthorizeConstant;
+import com.mogo.module.authorize.authprovider.module.IMogoAuthorizeModuleManager;
+import com.mogo.service.MogoServicePaths;
+import com.mogo.service.adas.IMogoADASController;
+import com.mogo.service.analytics.IMogoAnalytics;
+import com.mogo.service.cardmanager.IMogoCardManager;
+import com.mogo.service.datamanager.IMogoDataManager;
+import com.mogo.service.imageloader.IMogoImageloader;
+import com.mogo.service.impl.MogoServiceApis;
+import com.mogo.service.intent.IMogoIntentManager;
+import com.mogo.service.map.IMogoMapService;
+import com.mogo.service.module.IMogoActionManager;
+import com.mogo.service.module.IMogoMarkerService;
+import com.mogo.service.module.IMogoRegisterCenter;
+import com.mogo.service.network.IMogoNetwork;
+import com.mogo.service.statusmanager.IMogoStatusManager;
+import com.mogo.service.windowview.IMogoWindowManager;
+import com.zhidao.carchattingprovider.ICarsChattingProvider;
+
+/**
+ *
+ * 持有服务接口实例
+ */
+public class ServiceMediaHandler {
+
+ private static MogoServiceApis mApis;
+ private static IMogoMapService mMapService;
+ private static IMogoLocationClient mLocationClient;
+ private static IMogoMarkerManager mMarkerManager;
+ private static IMogoMapUIController mMapUIController;
+ private static IMogoImageloader mImageloader;
+ private static IMogoNetwork mMogoNetWorkService;
+ private static IMogoWindowManager mMogoWindowManager;
+ private static IMogoCardManager mMogoCardManager;
+ private static IMogoAnalytics mMogoAnalytis;
+ private static IMogoRegisterCenter mMogoRegisterCenter;
+ private static IMogoIntentManager mMogoVoiceManager;
+ private static IMogoStatusManager mIMogoStatusManager;
+ private static IMogoNavi mMogoNavi;
+ private static IMogoDataManager mMogoDataManager;
+ private static IMogoActionManager mMogoActionManager;
+ private static IMogoADASController mMogoADASController;
+ private static IMogoAuthorizeModuleManager mMogoAuthorizeModuleManager;
+ private static IMogoMarkerService sMarkerService;
+
+ private static ICarsChattingProvider sCarsChattingProvider;
+
+ public static void init(Context context) {
+ mApis = (MogoServiceApis) ARouter.getInstance().build(MogoServicePaths.PATH_SERVICE_APIS).navigation(context);
+ mMapService = mApis.getMapServiceApi();
+ mImageloader = mApis.getImageLoaderApi();
+ mLocationClient = mMapService.getLocationClient(context);
+ mMarkerManager = mMapService.getMarkerManager(context);
+ mMapUIController = mMapService.getMapUIController();//zoomTo
+ mMogoNetWorkService = mApis.getNetworkApi();
+ mMogoWindowManager = mApis.getWindowManagerApi();
+ mMogoCardManager = mApis.getCardManagerApi();
+ mMogoAnalytis = mApis.getAnalyticsApi();
+ mMogoRegisterCenter = mApis.getRegisterCenterApi();
+ mMogoVoiceManager = mApis.getIntentManagerApi();
+ mIMogoStatusManager = mApis.getStatusManagerApi();
+ mMogoNavi = mMapService.getNavi( context );
+ mMogoDataManager = mApis.getDataManagerApi();
+ mMogoActionManager = mApis.getActionManagerApi();
+ mMogoADASController = mApis.getAdasControllerApi();
+ mMogoAuthorizeModuleManager = (IMogoAuthorizeModuleManager) ARouter.getInstance().build(AuthorizeConstant.PROVIDER_MODULE).navigation(context);
+ sMarkerService = mApis.getMarkerService();
+
+ sCarsChattingProvider = ARouter.getInstance().navigation( ICarsChattingProvider.class );
+ }
+
+ public static IMogoADASController getMogoADASController(){
+ isApisNull(mMogoADASController);
+ return mMogoADASController;
+ }
+
+ public static IMogoMapService getMapService() {
+ isApisNull(mMapService);
+ return mMapService;
+ }
+
+ public static IMogoLocationClient getLocationClient() {
+ isApisNull(mLocationClient);
+ return mLocationClient;
+ }
+
+ public static IMogoMarkerManager getMarkerManager() {
+ isApisNull(mMarkerManager);
+ return mMarkerManager;
+ }
+
+ public static IMogoMapUIController getMapUIController() {
+ isApisNull(mMapUIController);
+ return mMapUIController;
+ }
+
+ public static IMogoImageloader getImageloader() {
+ isApisNull(mImageloader);
+ return mImageloader;
+ }
+
+ public static IMogoNetwork getMogoNetWorkService(){
+ isApisNull(mMogoNetWorkService);
+ return mMogoNetWorkService;
+ }
+
+ public static IMogoWindowManager getMogoWindowManager() {
+ isApisNull(mMogoWindowManager);
+ return mMogoWindowManager;
+ }
+
+ public static IMogoCardManager getMogoCardManager() {
+ isApisNull(mMogoCardManager);
+ return mMogoCardManager;
+ }
+
+ public static IMogoAnalytics getMogoAnalytis() {
+ isApisNull(mMogoAnalytis);
+ return mMogoAnalytis;
+ }
+
+ /**
+ * 1 2 3 dev qa release
+ * @return
+ */
+ public static int getCurrentEvent(){
+ return DebugConfig.getNetMode();
+ }
+
+ public static IMogoRegisterCenter getMogoRegisterCenter(){
+ isApisNull(mMogoRegisterCenter);
+ return mMogoRegisterCenter;
+ }
+
+ public static IMogoIntentManager getMogoVoiceManager(){
+ isApisNull(mMogoVoiceManager);
+ return mMogoVoiceManager;
+ }
+
+ public static IMogoStatusManager getIMogoStatusManager(){
+ isApisNull(mIMogoStatusManager);
+ return mIMogoStatusManager;
+ }
+
+ public static IMogoNavi getMogoNavi(){
+ isApisNull(mMogoNavi);
+ return mMogoNavi;}
+
+ public static IMogoDataManager getMogoDataManager(){
+ isApisNull(mMogoDataManager);
+ return mMogoDataManager;
+ }
+
+ public static MogoServiceApis getApis() {
+ return mApis;
+ }
+
+ /**
+ * 这个注册的第一个参数是模块名称,目的是只给当前显示的卡片分发事件
+ * @return
+ */
+ public static IMogoActionManager getMogoctionManager(){
+ isApisNull(mMogoActionManager);
+ return mMogoActionManager;
+ }
+
+ public static IMogoAuthorizeModuleManager getMogoAuthorizeModuleManager(){
+ isApisNull(mMogoAuthorizeModuleManager);
+ return mMogoAuthorizeModuleManager;
+ }
+
+ public static boolean isObjStaticNull(Object object){
+ if (mApis == null || object == null){
+ return true;
+ }
+ return false;
+ }
+
+ public static IMogoMarkerService getMarkerService() {
+ isApisNull(sMarkerService);
+ return sMarkerService;
+ }
+
+ public static ICarsChattingProvider getCarsChattingApis() {
+ isApisNull( sCarsChattingProvider );
+ return sCarsChattingProvider;
+ }
+
+ public static void isApisNull( Object object){
+ if (isObjStaticNull(object)){
+ init(AbsMogoApplication.getApp());
+ }
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/api/MediaDztService.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/api/MediaDztService.java
new file mode 100644
index 0000000000..0adfc59051
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/api/MediaDztService.java
@@ -0,0 +1,79 @@
+package com.mogo.module.media.api;
+
+import com.mogo.commons.data.BaseData;
+import com.mogo.module.common.entity.MarkerResponse;
+import com.mogo.module.media.model.ShareLikeData;
+import com.mogo.module.media.model.ShareMediaMarkerInfoData;
+import com.mogo.module.media.model.ShareSuccessResult;
+import com.mogo.module.media.model.ShowShareData;
+
+import java.util.Map;
+
+import io.reactivex.Observable;
+import okhttp3.RequestBody;
+import retrofit2.http.Body;
+import retrofit2.http.FieldMap;
+import retrofit2.http.FormUrlEncoded;
+import retrofit2.http.GET;
+import retrofit2.http.Header;
+import retrofit2.http.Headers;
+import retrofit2.http.POST;
+import retrofit2.http.QueryMap;
+import retrofit2.http.Url;
+
+public interface MediaDztService {
+
+ /**
+ * 查询音频分享信息
+ */
+ @GET("/sunflower/os/music/car/v1/selectByPrimaryKey")
+ Observable selectByPrimaryKey(@QueryMap Map params);
+
+ /**
+ * 分享音乐
+ */
+ @Headers({"Content-type:application/json;charset=UTF-8"})
+ @POST
+ Observable shareMusic(@Url String url, @Body RequestBody body);
+
+ /**
+ * 好友分享的歌
+ */
+ @GET("/sunflower/os/music/car/v1/getFriendsMusic")
+ Observable getFriendShareMusic(@QueryMap Map params);
+
+ /**
+ * 是否需要触发分享
+ */
+ @GET("/sunflower/os/music/car/v1/checkShare")
+ Observable getShouldPushShare(@QueryMap Map params);
+
+ /**
+ * 开始音乐
+ */
+ @FormUrlEncoded
+ @POST("/yycp-launcherSnapshot/mediaShare/mediaStart")
+ Observable startedMusic(@FieldMap Map params );
+
+ /**
+ * 停止音乐
+ */
+ @FormUrlEncoded
+ @POST("/yycp-launcherSnapshot/mediaShare/mediaPause")
+ Observable stopMusic(@FieldMap Map params );
+
+ /**
+ * 点赞分享
+ */
+ @Headers({"Content-type:application/json;charset=UTF-8"})
+ @POST
+ Observable likeShare(@Url String url, @Body RequestBody body);
+
+ /**
+ * 获取附近分享的歌,传入一个type,单独拉取模块的markerdata
+ */
+ @FormUrlEncoded
+ @POST("/yycp-launcherSnapshot/launcherSnapshot/querySnapshotSync")
+ Observable getNearShareMusic(@FieldMap Map params );
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/BaseUrlConstants.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/BaseUrlConstants.java
new file mode 100644
index 0000000000..42f21c56a1
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/BaseUrlConstants.java
@@ -0,0 +1,12 @@
+package com.mogo.module.media.constants;
+
+public interface BaseUrlConstants {
+ String DEV_BASE_URL = "http://dzt-dev.zhidaohulian.com";
+ String QA_BASE_URL = "http://dzt-test.zhidaozhixing.com";
+ String SHOW_BASE_URL = "http://dzt-show.zhidaozhixing.com";
+ String RELEASE_BASE_URL = "http://dzt.zhidaohulian.com";
+
+
+ String SHARE_MUSIC_URL = "/sunflower/os/music/car/v1/osMusiceShare";
+ String SHARE_MUSIC_LIKE_URL = "/sunflower/os/music/car/v1/likedShareMusic";
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/Constants.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/Constants.java
new file mode 100644
index 0000000000..28eb9095d5
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/Constants.java
@@ -0,0 +1,18 @@
+package com.mogo.module.media.constants;
+
+public interface Constants {
+
+ int ONE_KB = 1024;
+ int ONE_MB = ONE_KB * 1024;
+
+ int SIZE_DEFAULT = 2048;
+ int SIZE_LIMIT = 2048;
+
+ String IMAGE_COMPRESS_PATH = "image/compress/";
+
+ //storage
+ String SHOW_SHARE_PUSH_TIME = "show_share_push_time";
+ //his music
+ String LAST_TIME_LISTEN_MEDIA_MUSIC = "last_time_listen_media_music";
+ String MEDIA_UNIQUE_NAME = "media_unique_name";
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/EventConstants.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/EventConstants.java
new file mode 100644
index 0000000000..46cfaef99a
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/EventConstants.java
@@ -0,0 +1,28 @@
+package com.mogo.module.media.constants;
+
+public interface EventConstants {
+ String EVENT_QQ_OPEN_SHARE_DIALOG_SHOW = "card_QQMusic_pop";//打开分享弹窗 type 1、click,2、小智语音
+ String EVENT_QQ_SHARE_DIALOG_OK = "card_QQMusic_affirm";//弹窗内选择“确认”
+ String EVENT_QQ_SHARE_DIALOG_CANCLE = "card_QQMusic_close";//弹窗内选择“取消”
+ String EVENT_QQ_MUSIC_START = "QQMusicBegin";// 音乐开始 type 1、click,2、小智语音,3、卡片
+ String EVENT_QQ_MUSIC_PAUSE = "QQMusicSuspend";// 音乐暂停 type 1、click,2、小智语音,3、卡片
+ String EVENT_QQ_LAST_PLAY = "QQMusicTheLast";//qq音乐上一章 type 1、click,2、小智语音,3、卡片
+ String EVENT_QQ_Next_PLAY = "QQMusicNext";//qq音乐下一章 type 1、click,2、小智语音,3、卡片
+
+ String EVENT_BOOK_OPEN_SHARE_DIALOG_SHOW = "card_Book_pop";//打开分享弹窗 type 1、click,2、小智语音
+ String EVENT_BOOK_SHARE_DIALOG_OK = "card_Book_affirm";//弹窗内选择“确认”
+ String EVENT_BOOK_SHARE_DIALOG_CANCLE = "card_Book_close";//弹窗内选择“取消”
+ String EVENT_BOOK_MUSIC_START = "BookBegin";// 书开始 type 1、click,2、小智语音,3、卡片
+ String EVENT_BOOK_MUSIC_PAUSE = "BookSuspend";// 书暂停 type 1、click,2、小智语音,3、卡片
+ String EVENT_BOOK_LAST_PLAY = "BookTheLast";//懒人听书上一章 type 1、click,2、小智语音,3、卡片
+ String EVENT_BOOK_Next_PLAY = "BookNext";//懒人听书下一章 type 1、click,2、小智语音,3、卡片
+
+ String EVENT_NEWS_OPEN_SHARE_DIALOG_SHOW = "card_News_pop";//打开分享弹窗 type 1、click,2、小智语音
+ String EVENT_NEWS_SHARE_DIALOG_OK = "card_News_affirm";//弹窗内选择“确认”
+ String EVENT_NEWS_SHARE_DIALOG_CANCLE = "card_News_close";//弹窗内选择“取消”
+ String EVENT_NEWS_MUSIC_START = "NewsBegin";// 新闻开始 type 1、click,2、小智语音,3、卡片
+ String EVENT_NEWS_MUSIC_PAUSE = "NewsSuspend";// 新闻暂停 type 1、click,2、小智语音,3、卡片
+ String EVENT_NEWS_LAST_PLAY = "NewsTheLast";//新闻上一章 type 1、click,2、小智语音,3、卡片
+ String EVENT_NEWS_Next_PLAY = "NewsNext";//新闻下一章 type 1、click,2、小智语音,3、卡片
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/LeTingFieldConstants.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/LeTingFieldConstants.java
new file mode 100644
index 0000000000..68ecba4a7e
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/LeTingFieldConstants.java
@@ -0,0 +1,13 @@
+package com.mogo.module.media.constants;
+
+public interface LeTingFieldConstants {
+ String curTime = "curTime";//当前播放时长
+ String maxTime = "maxTime";//书籍总时长
+ String type = "type";//2 为书籍听书,3 为新闻 1 qq音乐
+ String mediaName = "mediaName";//新书标题,新闻标题
+ String artist = "artist";//新书来源,新闻来源
+ String cover = "cover";//作者封面,封面
+ String bookName = "bookName";//书籍名
+ String playState = "playState";//1 播放 2 缓冲 0 暂停/停止 -1 播放错误
+ String bookInfo = "bookInfo";//书本实例
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/MusicConstant.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/MusicConstant.java
new file mode 100644
index 0000000000..e26222ae1f
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/MusicConstant.java
@@ -0,0 +1,13 @@
+package com.mogo.module.media.constants;
+
+/**
+ * 音频相关常量
+ *
+ * @author tongchenfei
+ */
+public class MusicConstant {
+ public static final int PLAY_STATE_PLAYING = 1;
+ public static final int PLAY_STATE_BUFF = 2;
+ public static final int PLAY_STATE_PAUSE_OR_STOP = 0;
+ public static final int PLAY_STATE_ERROR = -1;
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/QQMusicFieldConstants.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/QQMusicFieldConstants.java
new file mode 100644
index 0000000000..8c6c8915ef
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/QQMusicFieldConstants.java
@@ -0,0 +1,18 @@
+package com.mogo.module.media.constants;
+
+public interface QQMusicFieldConstants {
+ String curTime = "curTime";//当前播放时长
+ String maxTime = "maxTime";//书籍总时长
+ String type = "type";//2 为书籍听书,3 为新闻,1 为qq音乐
+ String mediaName = "mediaName";//歌曲名
+ String playState = "playState";//1 播放 2 缓冲 0 暂停/停止 -1 播放错误
+ String mediaUrl = "mediaUrl";//音乐url
+ String mediaSinger = "mediaSinger";//歌手名
+ String mediaImgUrl = "mediaImgUrl";//封面
+ String mediaType = "mediaType";//歌曲类别
+ String mediaMid = "mediaMid";//song mid
+ String isLocalMedia = "isLocalMedia";//是否是本地歌曲
+ String mediaPlayMode = "mediaPlayMode";//播放模式
+ String mediaAlbumName = "mediaAlbumName";//专辑名
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/VoiceConstants.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/VoiceConstants.java
new file mode 100644
index 0000000000..ee00d72ce0
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/constants/VoiceConstants.java
@@ -0,0 +1,50 @@
+package com.mogo.module.media.constants;
+
+public interface VoiceConstants {
+ String SHARE_QQ_MUSIC = "确认分享该歌曲,你可对我说确认或取消";
+ String SHARE_LANREN_MUSIC = "确认分享本书,你可对我说确认或取消";
+ String SHARE_LETINGNES_MUSIC = "确认分享新闻,你可对我说确认或取消";
+ String COMMAND_SHARE_MUSIC_PUSH_MESSAGE ="可把歌曲,书籍,新闻分享给附近的车友,语音回复分享即可分享";
+ String[] COMMAND_SHARE_MUSIC_PUSH_MESSAGE_OK = {"分享"};
+ String[] COMMAND_SHARE_MUSIC_PUSH_MESSAGE_CANCEL = { "不分享"};
+
+ String[] COMMAND_NO_WAKEUP_MUSIC_SHARE = {"分享歌曲","分享音乐","分享这首歌","帮我分享一下这个歌","把这首歌分享一下"};
+ String COMMAND_NO_WAKEUP_SHARE_MUSIC_CMD = "media_card_music_no_wake_share";
+
+ String[] COMMAND_NO_WAKEUP_BOOK_SHARE = {"分享书","分享这本书","帮我分享一下这本书","把这本书分享一下"};
+ String COMMAND_NO_WAKEUP_SHARE_BOOK_CMD = "media_card_book_no_wake_share";
+
+ String[] COMMAND_NO_WAKEUP_NEWS_SHARE = {"分享新闻","分享这条新闻","把这条新闻分享一下","帮我分享一下这条新闻"};
+ String COMMAND_NO_WAKEUP_SHARE_NEWS_CMD = "media_card_news_no_wake_share";
+
+ String[] COMMAND_NO_WAKEUP_BOOK_MUSIC_SHARE = {"分享"};
+ String COMMAND_NO_WAKEUP_SHARE_BOOK_MUSIC_CMD = "media_card_book_music_no_wake_share";
+
+ String[] COMMAND_SHARE_MUSIC_OK = {"确认", "是","分享"};
+ String[] COMMAND_NO_SHARE_MUSIC_CANCEL = {"取消", "不分享"};
+
+ String[] COMMAND_OPEN_MUSIC = {"**打开**音乐**","打开音乐","帮我打开一下音乐好不好","打开一下音乐好不好","帮我打开音乐","打开音乐谢谢"};
+ String COMMAND_OPEN_MUSIC_CMD = "media_card_open_music";
+
+ String[] COMMAND_CLOSE_MUSIC = {"**关闭**音乐**","关闭音乐","退出音乐","帮我关闭一下音乐好不好","关闭一下音乐好不好","帮我关闭音乐","关闭那个音乐","关闭音乐谢谢"};
+ String COMMAND_CLOSE_MUSIC_CMD = "media_card_close_music";
+
+ String[] COMMAND_NEAR_MUSIC = {"附近的歌","附近的人听的歌","附近的人听的音乐","周围的人听的歌","周围的人听的音乐"};
+ String COMMAND_NEAR_MUSIC_CMD = "media_card_near_music";
+
+ String[] COMMAND_FRIEND_MUSIC = {"好友听的歌","好友听的音乐","播放好友的歌","放好友的歌","听好友的歌","播放好友的音乐","放好友的音乐","听好友的音乐"};
+ String COMMAND_FRIEND_MUSIC_CMD = "media_card_friend_music";
+
+ String[] COMMAND_QUERY_MUSIC_NAME = {"这歌是什么","这歌叫啥","这首歌叫什么名字","歌名是什么","这首歌的名字","这首音乐叫什么","这个歌是啥"};
+ String COMMAND_QUERY_MUSIC_NAME_CMD = "media_card_query_music_name";
+
+ String[] COMMAND_QUERY_MUSIC_SINGER = {"这首歌是谁唱的","这歌谁唱的","这首歌的歌手","这首歌的歌手是谁","查一下这首歌的歌手"};
+ String COMMAND_QUERY_MUSIC_SINGERME_CMD = "media_card_query_music_singer";
+
+ String[] COMMAND_SHARE_DIALOG_TIMEOUT_CLOSE = {"关闭","取消","关闭分享","取消分享","关闭弹窗","取消弹窗","不分享"};
+ String COMMAND_SHARE_DIALOG_TIMEOUT_CLOSE_COMMAND = "share_dialog_timeout_close_command";
+
+ String[] COMMAND_SHARE_DIALOG_TIMEOUT_OK = {"确认","确定","分享","确认分享","确定分享"};
+ String COMMAND_SHARE_DIALOG_TIMEOUT_OK_COMMAND = "share_dialog_timeout_confirm_command";
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/dialog/BaseDialogFragment.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/dialog/BaseDialogFragment.java
new file mode 100644
index 0000000000..f899862699
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/dialog/BaseDialogFragment.java
@@ -0,0 +1,121 @@
+package com.mogo.module.media.dialog;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.DialogFragment;
+
+import com.mogo.utils.TipToast;
+
+
+public abstract class BaseDialogFragment extends DialogFragment {
+ protected Bundle mBundle;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mBundle = savedInstanceState == null ? getArguments() : savedInstanceState;
+ if (mBundle == null) {
+ mBundle = new Bundle();
+ }
+ }
+
+ @Override
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ if (mBundle != null) {
+ outState.putAll(mBundle);
+ }
+ super.onSaveInstanceState(outState);
+ }
+
+ public void openActivity(Class extends Activity> cls) {
+ openActivity(cls, null);
+ }
+
+ public void openActivity(Class extends Activity> cls, Bundle bundle) {
+ Intent intent = new Intent();
+ if (bundle != null) {
+ intent.putExtras(bundle);
+ }
+ intent.setClass(getActivity(), cls);
+ startActivity(intent);
+ }
+
+ public void openActivity(String url, Bundle bundle) {
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ if (bundle != null) {
+ intent.putExtras(bundle);
+ }
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ startActivity(intent);
+ }
+
+ public void openActivityForResult(Class extends Activity> cls, Bundle bundle, int requestCode) {
+ Intent intent = new Intent();
+ if (bundle != null) {
+ intent.putExtras(bundle);
+ }
+ intent.setClass(getActivity(), cls);
+ startActivityForResult(intent, requestCode);
+ }
+
+ public void backForResult(int resultCode, Bundle bundle) {
+ Intent intent = new Intent();
+ if (bundle != null) {
+ intent.putExtras(bundle);
+ }
+ getActivity().setResult(resultCode, intent);
+ getActivity().finish();
+ }
+
+ public void backToActivity(Class extends Activity> cls, Bundle bundle) {
+ Intent intent = new Intent();
+ if (bundle != null) {
+ intent.putExtras(bundle);
+ }
+ intent.setClass(getActivity(), cls);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ startActivity(intent);
+ }
+
+ @Override
+ public Context getContext() {
+ return super.getContext();
+ }
+
+ public boolean isVisibleToUser() {
+ return isResumed();
+ }
+
+
+ public void showToast(CharSequence toast) {
+ TipToast.shortTip(toast.toString());
+ }
+ public void showInputMethod(View view) {
+ if (getContext() == null) return;
+ InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ if (imm != null) {
+ imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
+ }
+ }
+
+ public void hideInputMethod(View view) {
+ if (getContext() == null) return;
+ InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ if (imm != null) {
+ imm.hideSoftInputFromWindow(view.getWindowToken(),InputMethodManager.HIDE_NOT_ALWAYS);
+ }
+ }
+}
+
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/dialog/CustomDialog.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/dialog/CustomDialog.java
new file mode 100644
index 0000000000..2e11fbdbe2
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/dialog/CustomDialog.java
@@ -0,0 +1,229 @@
+package com.mogo.module.media.dialog;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+
+import com.mogo.module.media.R;
+
+public class CustomDialog extends Dialog {
+ TextView txtOk;
+ TextView txtCancel;
+ TextView txtTitle;
+ TextView txtContent;
+ TextView txtSubContent;
+
+ private int mContentSize = 0;
+ private int mContentColor = 0;
+ private int mBtnSize = 0;
+
+ private int mSubContentSize = 0;
+ private int mContentLeftPadding = 0;
+
+ private View.OnClickListener onOkListener, onCancelListener;
+
+ private String title, subContent, okText, cancelText;
+ private CharSequence content;
+ private boolean isAutoDismissDialog = true;
+
+ private int contentGravity = Gravity.CENTER;
+ private int subContentGravity = Gravity.LEFT;
+
+ private boolean isContentClickSpanEnable = false;
+
+ public CustomDialog(@NonNull Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.module_media_dialog_cutom_layout);
+
+ initView();
+
+ if (TextUtils.isEmpty(title)) {
+ txtTitle.setVisibility(View.GONE);
+ } else {
+ txtTitle.setText(title);
+ txtTitle.setVisibility(View.VISIBLE);
+ }
+
+ if (mContentSize > 0){
+ txtContent.setTextSize(TypedValue.COMPLEX_UNIT_PX,mContentSize);
+ }
+
+ if (mSubContentSize > 0){
+ txtSubContent.setTextSize(TypedValue.COMPLEX_UNIT_PX,mSubContentSize);
+ }
+
+ if (mContentColor > 0){
+ txtContent.setTextColor(mContentColor);
+ }
+
+ if (mContentLeftPadding > 0){
+ txtContent.setPadding(mContentLeftPadding,0,mContentLeftPadding,0);
+ }
+
+ if ( content instanceof String) {
+ content = ( (String) content ).replace( "\\n", "\n" );
+ }
+
+ txtContent.setText(content);
+ if (TextUtils.isEmpty(subContent)) {
+ txtSubContent.setVisibility(View.GONE);
+ } else {
+ txtSubContent.setVisibility(View.VISIBLE);
+ txtSubContent.setText(subContent);
+ }
+
+ txtSubContent.setGravity(subContentGravity);
+
+ if (mBtnSize > 0){
+ txtOk.setTextSize(TypedValue.COMPLEX_UNIT_PX,mBtnSize);
+ txtCancel.setTextSize(TypedValue.COMPLEX_UNIT_PX,mBtnSize);
+ }
+
+ if (!TextUtils.isEmpty(okText)) {
+ txtOk.setVisibility(View.VISIBLE);
+ txtOk.setText(okText);
+ } else {
+ txtOk.setVisibility(View.GONE);
+ }
+ if (!TextUtils.isEmpty(cancelText)) {
+ txtCancel.setVisibility(View.VISIBLE);
+ txtCancel.setText(cancelText);
+ } else {
+ txtCancel.setVisibility(View.GONE);
+ }
+
+ txtOk.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (isAutoDismissDialog) {
+ dismiss();
+ }
+ if (onOkListener != null) {
+ onOkListener.onClick(v);
+ }
+ }
+ });
+ txtCancel.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (isAutoDismissDialog) {
+ dismiss();
+ }
+ if (onCancelListener != null) {
+ onCancelListener.onClick(v);
+ }
+ }
+ });
+
+ txtContent.setGravity( contentGravity );
+
+ if ( isContentClickSpanEnable ) {
+ txtContent.setMovementMethod( LinkMovementMethod.getInstance() );
+ }
+
+ }
+
+ private void initView() {
+ txtOk = findViewById(R.id.txt_ok);
+ txtCancel = findViewById(R.id.txt_cancel);
+ txtTitle = findViewById(R.id.txt_title);
+ txtContent = findViewById(R.id.txt_content);
+ txtSubContent = findViewById(R.id.txt_sub_content);
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public void setContent(CharSequence content) {
+ this.content = content;
+ }
+
+ public void setSubContent(String subContent) {
+ this.subContent = subContent;
+ }
+
+ public void setContentGravity(int gravity) {
+ contentGravity = gravity;
+ }
+
+ public void hiddenBtnCancel() {
+ txtCancel.setVisibility(View.GONE);
+ }
+
+ public void setOnOkClickListener(String okText, View.OnClickListener onOkClickListener) {
+ this.okText = okText;
+ this.onOkListener = onOkClickListener;
+ }
+
+ public void setOnOkClickListener(View.OnClickListener onOkClickListener) {
+ setOnOkClickListener("确定", onOkClickListener);
+ }
+
+ public void setOnCancelListener(String cancelText, View.OnClickListener onCancelListener) {
+ this.cancelText = cancelText;
+ this.onCancelListener = onCancelListener;
+ }
+
+ public void setOnCancelListener(View.OnClickListener onCancelListener) {
+ setOnCancelListener("取消", onCancelListener);
+ }
+
+ public void setAutoDismissDialog(boolean autoDismissDialog) {
+ isAutoDismissDialog = autoDismissDialog;
+ }
+
+ public void setBtnTextSize(int size){
+ mBtnSize = size;
+ }
+
+ public void setContentTextSize(int size){
+ mContentSize = size;
+ }
+
+ public void setSubContentTextSize(int size){
+ mSubContentSize = size;
+ }
+
+ public void setContentColor(int color){
+ mContentColor = color;
+ }
+
+ public int getContentGravity() {
+ return contentGravity;
+ }
+
+ public int getSubContentGravity() {
+ return subContentGravity;
+ }
+
+ public void setSubContentGravity(int subContentGravity) {
+ this.subContentGravity = subContentGravity;
+ }
+
+ public void setContentClickSpanEnable(boolean contentClickSpanEnable ) {
+ isContentClickSpanEnable = contentClickSpanEnable;
+ }
+
+ public int getContentLeftPadding() {
+ return mContentLeftPadding;
+ }
+
+ public void setContentLeftPadding(int mContentLeftPadding) {
+ this.mContentLeftPadding = mContentLeftPadding;
+ }
+}
+
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/dialog/MediaShareDialogFragment.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/dialog/MediaShareDialogFragment.java
new file mode 100644
index 0000000000..9dbfd499fe
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/dialog/MediaShareDialogFragment.java
@@ -0,0 +1,445 @@
+package com.mogo.module.media.dialog;
+
+import android.app.Dialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.mogo.commons.network.ParamsProvider;
+import com.mogo.commons.network.ParamsUtil;
+import com.mogo.commons.network.SubscribeImpl;
+import com.mogo.commons.voice.AIAssist;
+import com.mogo.commons.voice.IMogoVoiceCmdCallBack;
+import com.mogo.map.location.MogoLocation;
+import com.mogo.module.common.entity.MarkerShareMusic;
+import com.mogo.module.media.MediaConstants;
+import com.mogo.module.media.R;
+import com.mogo.module.media.ServiceMediaHandler;
+import com.mogo.module.media.api.MediaDztService;
+import com.mogo.module.media.constants.BaseUrlConstants;
+import com.mogo.module.media.constants.EventConstants;
+import com.mogo.module.media.constants.VoiceConstants;
+import com.mogo.module.media.listener.MogoVoiceCmdCallBackImp;
+import com.mogo.module.media.model.MediaInfoData;
+import com.mogo.module.media.model.ShareSuccessResult;
+import com.mogo.module.media.utils.BaseUrlManager;
+import com.mogo.module.media.utils.MediaAnalyticsUtils;
+import com.mogo.module.media.utils.ToastHelper;
+import com.mogo.module.media.widget.RoundedImageView;
+import com.mogo.utils.TipToast;
+import com.mogo.utils.glide.GlideApp;
+import com.mogo.utils.logger.Logger;
+import com.mogo.utils.network.RequestOptions;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.schedulers.Schedulers;
+
+/**
+ * media 分享dialog
+ */
+public class MediaShareDialogFragment extends BaseDialogFragment {
+
+ private Disposable mDisposable;
+ private Context context;
+ private Callback callback;
+ private RoundedImageView mMediaImg;
+ private TextView mMediaName;
+ private TextView mMediaSinger;
+ private TextView mOk;
+ private TextView mCancel;
+ private TextView mDialogContent;
+ private MediaInfoData mMediaInfoData;
+ private VoiceCallBack voiceCallBack = new VoiceCallBack();
+ private boolean shareSuccess = false;
+ private MarkerShareMusic markerShareMusic;
+ private boolean navi = false;
+ private ShareOkReceiver mShareOkReceiver;
+
+ public interface Callback {
+ void onShareDialogShow();
+
+ void onShareDialogDismiss(boolean success,MarkerShareMusic markerShareMusic);
+ }
+
+ public static final String TAG = "MediaShareDialogFragment";
+
+ public static MediaShareDialogFragment newInstance(MediaInfoData data,boolean navi) {
+ Bundle args = new Bundle();
+ args.putSerializable("data", data);
+ args.putBoolean("navi",navi);
+ MediaShareDialogFragment fragment = new MediaShareDialogFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ this.context = context;
+ if (getParentFragment() instanceof Callback) {
+ callback = ((Callback) getParentFragment());
+ } else if (context instanceof Callback) {
+ callback = ((Callback) context);
+ }
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ final Dialog dialog = getDialog();
+ if (dialog != null) {
+ dialog.setCanceledOnTouchOutside(false);
+ dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ if (dialog.getWindow() != null) {
+ dialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
+ }
+ }
+
+ return inflater.inflate(R.layout.module_media_share_fragment_view, null);
+ }
+
+ @Override
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ if (callback != null) {
+ callback.onShareDialogShow();
+ }
+ try {
+ mMediaInfoData = (MediaInfoData) getArguments().getSerializable("data");
+ navi = getArguments().getBoolean("navi");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ initViews();
+ registerMediaReceiver();
+ registerCloseNoWakeUp();
+ }
+
+ private class VoiceCallBack implements IMogoVoiceCmdCallBack {
+ @Override
+ public void onCmdSelected(String cmd) {
+
+ }
+
+ @Override
+ public void onCmdAction(String speakText) {
+ //确认
+ shareMusic(mMediaInfoData,false);
+ Logger.d("MediaShareDialogFragment","qa onCmdAction"+speakText);
+ }
+
+ @Override
+ public void onCmdCancel(String speakText) {
+ //取消
+ dissMisDialog(false);
+ Logger.d("MediaShareDialogFragment","qa onCmdCancel");
+ }
+
+ @Override
+ public void onSpeakEnd(String speakText) {
+ Logger.d("MediaShareDialogFragment","qa onSpeakEnd");
+ }
+
+ @Override
+ public void onSpeakSelectTimeOut(String speakText) {
+ if (!navi) registerCloseNoWakeUp();
+ Logger.d("MediaShareDialogFragment","qa onSpeakSelectTimeOut");
+ }
+ }
+
+ private void registerMediaReceiver() {
+ mShareOkReceiver = new ShareOkReceiver();
+ IntentFilter filterone = new IntentFilter();
+ filterone.addAction("com.zhidao.speech.awake.notify");
+ getContext().registerReceiver(mShareOkReceiver, filterone);
+ }
+
+ private void unRegisterMediaReceiver() {
+ try {
+ getContext().unregisterReceiver(mShareOkReceiver);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private class ShareOkReceiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ try {
+ if (intent != null){
+ String cmdStr = intent.getStringExtra("command");
+ if(cmdStr.equals("com.zhidao.multiMedia.share.comfirm")){
+ shareMusic(mMediaInfoData,false);
+ }else if (cmdStr.equals("com.zhidao.multiMedia.share.cancel")){
+ dissMisDialog(false);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void registerCloseNoWakeUp() {
+ AIAssist.getInstance(getActivity()).registerUnWakeupCommand(VoiceConstants.COMMAND_SHARE_DIALOG_TIMEOUT_CLOSE_COMMAND
+ , VoiceConstants.COMMAND_SHARE_DIALOG_TIMEOUT_CLOSE
+ ,new MogoVoiceCmdCallBackImp(){
+ @Override
+ public void onCmdSelected(String cmd) {
+ super.onCmdSelected(cmd);
+ if (cmd.equals(VoiceConstants.COMMAND_SHARE_DIALOG_TIMEOUT_CLOSE_COMMAND)){
+ dismissAllowingStateLoss();
+ }
+ Logger.d("MediaShareDialogFragment","registerUnWakeupCommand onCmdSelected");
+ }
+
+ @Override
+ public void onSpeakEnd(String speakText) {
+ super.onSpeakEnd(speakText);
+ Logger.d("MediaShareDialogFragment","registerUnWakeupCommand onSpeakEnd"+speakText);
+ }
+
+ @Override
+ public void onSpeakSelectTimeOut(String speakText) {
+ super.onSpeakSelectTimeOut(speakText);
+ Logger.d("MediaShareDialogFragment","registerUnWakeupCommand onSpeakSelectTimeOut");
+ }
+ });
+
+ AIAssist.getInstance(getActivity()).registerUnWakeupCommand(VoiceConstants.COMMAND_SHARE_DIALOG_TIMEOUT_OK_COMMAND
+ , VoiceConstants.COMMAND_SHARE_DIALOG_TIMEOUT_OK
+ ,new MogoVoiceCmdCallBackImp(){
+ @Override
+ public void onCmdSelected(String cmd) {
+ super.onCmdSelected(cmd);
+ if (cmd.equals(VoiceConstants.COMMAND_SHARE_DIALOG_TIMEOUT_OK_COMMAND)){
+ shareMusic(mMediaInfoData,false);
+ }
+ }
+
+ @Override
+ public void onSpeakEnd(String speakText) {
+ super.onSpeakEnd(speakText);
+ }
+
+ @Override
+ public void onSpeakSelectTimeOut(String speakText) {
+ super.onSpeakSelectTimeOut(speakText);
+ }
+ });
+
+
+ }
+
+ private void initViews() {
+ mMediaImg = getView().findViewById(R.id.media_img);
+ mMediaName = getView().findViewById(R.id.media_name);
+ mMediaSinger = getView().findViewById(R.id.media_singer);
+ mOk = getView().findViewById(R.id.txt_ok);
+ mCancel = getView().findViewById(R.id.txt_cancle);
+ mDialogContent = getView().findViewById(R.id.media_dialog_content);
+ mCancel.setOnClickListener(view -> {
+ dissMisDialog(true);
+ });
+
+ mOk.setOnClickListener(view -> {
+ shareMusic(mMediaInfoData,true);
+ });
+
+ if (mMediaInfoData != null) {
+ if (mMediaInfoData.getMediaImg() != null) {
+ com.bumptech.glide.request.RequestOptions options = new com.bumptech.glide.request.RequestOptions()
+ .placeholder(R.drawable.module_media_share_default_rect_icon);
+ GlideApp.with(getActivity()).applyDefaultRequestOptions(options).load(mMediaInfoData.getMediaImg()).into(mMediaImg);
+ }
+
+ if (mMediaInfoData.getMediaName() != null) {
+ mMediaName.setText(mMediaInfoData.getMediaName());
+ }
+
+ if (mMediaInfoData.getMediaSinger() != null) {
+ mMediaSinger.setText(mMediaInfoData.getMediaSinger());
+ }
+
+ if (mMediaInfoData.getType() == 1) {
+ mDialogContent.setText(context.getResources().getString(R.string.module_media_share_qq_music));
+ } else if (mMediaInfoData.getType() == 2){
+ mDialogContent.setText(context.getResources().getString(R.string.module_media_share_lan_ren));
+ } else if (mMediaInfoData.getType() == 3){
+ mDialogContent.setText(context.getResources().getString(R.string.module_media_share_le_ting_news));
+ }
+ }
+ }
+
+ private void dissMisDialog(boolean click) {
+ dismissAllowingStateLoss();
+ try {
+ if (mMediaInfoData != null){
+ HashMap hashMap = new HashMap<>();
+ hashMap.put("type",click ?1:2);
+ String trackId = "";
+ if (mMediaInfoData.getType() == 1){
+ trackId = EventConstants.EVENT_QQ_SHARE_DIALOG_CANCLE;
+ }else if (mMediaInfoData.getType() == 2){
+ trackId = EventConstants.EVENT_BOOK_SHARE_DIALOG_CANCLE;
+ }else if (mMediaInfoData.getType() == 3){
+ trackId = EventConstants.EVENT_NEWS_SHARE_DIALOG_CANCLE;
+ }
+ MediaAnalyticsUtils.track(trackId ,hashMap);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ super.onDismiss(dialog);
+ try {
+
+ unRegisterMediaReceiver();
+
+ AIAssist.getInstance(getActivity()).unregisterUnWakeupCommand(VoiceConstants.COMMAND_SHARE_DIALOG_TIMEOUT_CLOSE_COMMAND);
+ AIAssist.getInstance(getActivity()).unregisterUnWakeupCommand(VoiceConstants.COMMAND_SHARE_DIALOG_TIMEOUT_OK_COMMAND);
+
+ if (mDisposable != null && !mDisposable.isDisposed()) {
+ mDisposable.dispose();
+ }
+ if (callback != null) {
+ callback.onShareDialogDismiss(shareSuccess,markerShareMusic);
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void shareMusic(MediaInfoData mCurrentMusic,boolean click) {
+ if (mCurrentMusic == null) return;
+ markerShareMusic = new MarkerShareMusic();
+ try {
+ if (mMediaInfoData != null){
+ HashMap hashMap = new HashMap<>();
+ hashMap.put("type",click ? 1:2);
+ String trackId = "";
+ if (mMediaInfoData.getType() == 1){
+ trackId = EventConstants.EVENT_QQ_SHARE_DIALOG_OK;
+ }else if (mMediaInfoData.getType() == 2){
+ trackId = EventConstants.EVENT_BOOK_SHARE_DIALOG_OK;
+ }else if (mMediaInfoData.getType() == 3){
+ trackId = EventConstants.EVENT_NEWS_SHARE_DIALOG_OK;
+ }
+ MediaAnalyticsUtils.track(trackId ,hashMap);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ final Map businessParams = new HashMap<>();
+ final MogoLocation location = ServiceMediaHandler.getLocationClient().getLastKnowLocation();
+ if (location != null) {
+ businessParams.put("address", location.getAddress());
+ }
+
+ businessParams.put("bookInfo", mCurrentMusic.getBookInfo());
+ businessParams.put("mediaDuration", mCurrentMusic.getMaxTime() + "");
+ businessParams.put("mediaId", mCurrentMusic.getMediaId());
+ businessParams.put("mediaImg", mCurrentMusic.getMediaImg());
+ businessParams.put("mediaName", mCurrentMusic.getMediaName());
+ businessParams.put("mediaSinger", mCurrentMusic.getMediaSinger());
+ businessParams.put("mediaType", mCurrentMusic.getMediaType());
+ businessParams.put("mediaUrl", mCurrentMusic.getMediaUrl());
+ businessParams.put("shareType", mCurrentMusic.getType());
+
+ ParamsProvider.Builder builder = new ParamsProvider.Builder(getContext());
+ if (location != null) {
+ builder.append("lat", location.getLatitude());
+ builder.append("lng", location.getLongitude());
+ }else{
+ TipToast.shortTip("分享失败,定位出错请重试!");
+ shareSuccess = false;
+ dismissAllowingStateLoss();
+ return;
+ }
+ final Map params = builder
+ .append(businessParams)
+ .build();
+ Observable observable = ServiceMediaHandler.getMogoNetWorkService().create(MediaDztService.class, BaseUrlManager.getDztBaseUrl())
+ .shareMusic(ParamsUtil.toQueryUrl(BaseUrlManager.getDztBaseUrl() + BaseUrlConstants.SHARE_MUSIC_URL, params, businessParams), ParamsUtil.convert(businessParams));
+ observable
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new SubscribeImpl(RequestOptions.create(getContext())) {
+ @Override
+ public void onSubscribe(Disposable d) {
+ mDisposable = d;
+ }
+
+ @Override
+ public void onSuccess(ShareSuccessResult resultData) {
+ try {
+ ToastHelper.showShortSuccess(getContext(), getContext().getResources().getString(R.string.module_media_share_success));
+ if (!navi) AIAssist.getInstance(getActivity()).speakTTSVoice(getContext().getResources().getString(R.string.module_media_share_success),null);
+ shareSuccess = true;
+ if (resultData != null && resultData.result != null){
+ markerShareMusic = resultData.result;
+ markerShareMusic.setType(MediaConstants.MODULE_TYPE);
+ }
+ dismissAllowingStateLoss();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ super.onError(e);
+ try {
+ ToastHelper.showShortError(getContext(), getContext().getResources().getString(R.string.module_media_share_fail));
+ TipToast.shortTip("分享失败");
+ if (!navi)AIAssist.getInstance(getActivity()).speakTTSVoice(getContext().getResources().getString(R.string.module_media_share_fail),null);
+ dismissAllowingStateLoss();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onError(String message, int code) {
+ super.onError(message, code);
+ try {
+ ToastHelper.showShortError(getContext(), getContext().getResources().getString(R.string.module_media_share_fail));
+ TipToast.shortTip(!TextUtils.isEmpty(message)?message:"分享失败");
+ if (!navi)AIAssist.getInstance(getActivity()).speakTTSVoice(!TextUtils.isEmpty(message)?message:"分享失败",null);
+ dismissAllowingStateLoss();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ );
+
+ }
+
+}
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/listener/MogoVoiceCmdCallBackImp.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/listener/MogoVoiceCmdCallBackImp.java
new file mode 100644
index 0000000000..958debea23
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/listener/MogoVoiceCmdCallBackImp.java
@@ -0,0 +1,30 @@
+package com.mogo.module.media.listener;
+
+import com.mogo.commons.voice.IMogoVoiceCmdCallBack;
+
+public abstract class MogoVoiceCmdCallBackImp implements IMogoVoiceCmdCallBack {
+ @Override
+ public void onCmdSelected(String cmd) {
+
+ }
+
+ @Override
+ public void onCmdAction(String speakText) {
+
+ }
+
+ @Override
+ public void onCmdCancel(String speakText) {
+
+ }
+
+ @Override
+ public void onSpeakEnd(String speakText) {
+
+ }
+
+ @Override
+ public void onSpeakSelectTimeOut(String speakText) {
+
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/listener/NoDoubleClickListener.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/listener/NoDoubleClickListener.java
new file mode 100644
index 0000000000..006165855c
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/listener/NoDoubleClickListener.java
@@ -0,0 +1,24 @@
+package com.mogo.module.media.listener;
+
+import android.view.View;
+
+public abstract class NoDoubleClickListener implements View.OnClickListener {
+
+ public static final int MIN_CLICK_DELAY_TIME = 700;
+
+ private long lastClickTime = 0;
+
+ @Override
+
+ public void onClick(View v) {
+ long currentTime = System.currentTimeMillis();
+ if ((currentTime - lastClickTime) > MIN_CLICK_DELAY_TIME) {
+ lastClickTime = currentTime;
+ onClicks(v);
+ }
+
+ }
+
+ public abstract void onClicks(View view);
+}
+
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/LanRenInsertData.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/LanRenInsertData.java
new file mode 100644
index 0000000000..507bcf0754
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/LanRenInsertData.java
@@ -0,0 +1,100 @@
+package com.mogo.module.media.model;
+
+import java.io.Serializable;
+
+public class LanRenInsertData implements Serializable {
+
+ /**
+ * announcer : 动之以情
+ * auth : 耗子扛大刀
+ * bookId : 28862
+ * cover : http://bookpic.lrts.me/b8d33429fa0840578207c1685e8fa22a_180x254.jpg
+ * desc : 传说中的兵之王者,神秘莫测的杀手之王,带着仇恨与疑惑进入都市寻找仇敌!
+ * isCollect : false
+ * name : 特种军医在都市
+ * sections : 447
+ * typeName : 都市传说
+ */
+
+ private String announcer;
+ private String auth;
+ private int bookId;
+ private String cover;
+ private String desc;
+ private boolean isCollect;
+ private String name;
+ private int sections;
+ private String typeName;
+
+ public String getAnnouncer() {
+ return announcer;
+ }
+
+ public void setAnnouncer(String announcer) {
+ this.announcer = announcer;
+ }
+
+ public String getAuth() {
+ return auth;
+ }
+
+ public void setAuth(String auth) {
+ this.auth = auth;
+ }
+
+ public int getBookId() {
+ return bookId;
+ }
+
+ public void setBookId(int bookId) {
+ this.bookId = bookId;
+ }
+
+ public String getCover() {
+ return cover;
+ }
+
+ public void setCover(String cover) {
+ this.cover = cover;
+ }
+
+ public String getDesc() {
+ return desc;
+ }
+
+ public void setDesc(String desc) {
+ this.desc = desc;
+ }
+
+ public boolean isIsCollect() {
+ return isCollect;
+ }
+
+ public void setIsCollect(boolean isCollect) {
+ this.isCollect = isCollect;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getSections() {
+ return sections;
+ }
+
+ public void setSections(int sections) {
+ this.sections = sections;
+ }
+
+ public String getTypeName() {
+ return typeName;
+ }
+
+ public void setTypeName(String typeName) {
+ this.typeName = typeName;
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/LeTingNewsData.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/LeTingNewsData.java
new file mode 100644
index 0000000000..68bc3046ba
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/LeTingNewsData.java
@@ -0,0 +1,130 @@
+package com.mogo.module.media.model;
+
+import java.io.Serializable;
+
+public class LeTingNewsData implements Serializable {
+
+ /**
+ * catalog_id : channel_recommend
+ * catalog_name : 推荐
+ * title : 内蒙古:妈妈去武汉打“怪兽”
+ * hms : 02:20
+ * image : https://image.leting.io/a066db4d5c615605e79c3235d9f54669.jpg
+ * sid : Pfzgptk29ZG86N0JStE5l-1srtNmDnAwBBLMCm-2l7QvQAP7vq0G_Jlm6YM8z9kHb97sJVd5mJ_2zW5EWtahbQ==
+ * source : 北京您早
+ * source_icon : https://image.leting.io/a77d7b23030e49007c148a563c386dbe.jpg
+ * pub_time : 0
+ * updated_at : 0
+ * duration : 140
+ * hot : 0
+ */
+
+ private String catalog_id;
+ private String catalog_name;
+ private String title;
+ private String hms;
+ private String image;
+ private String sid;
+ private String source;
+ private String source_icon;
+ private int pub_time;
+ private int updated_at;
+ private int duration;
+ private int hot;
+
+ public String getCatalog_id() {
+ return catalog_id;
+ }
+
+ public void setCatalog_id(String catalog_id) {
+ this.catalog_id = catalog_id;
+ }
+
+ public String getCatalog_name() {
+ return catalog_name;
+ }
+
+ public void setCatalog_name(String catalog_name) {
+ this.catalog_name = catalog_name;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getHms() {
+ return hms;
+ }
+
+ public void setHms(String hms) {
+ this.hms = hms;
+ }
+
+ public String getImage() {
+ return image;
+ }
+
+ public void setImage(String image) {
+ this.image = image;
+ }
+
+ public String getSid() {
+ return sid;
+ }
+
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+
+ public String getSource() {
+ return source;
+ }
+
+ public void setSource(String source) {
+ this.source = source;
+ }
+
+ public String getSource_icon() {
+ return source_icon;
+ }
+
+ public void setSource_icon(String source_icon) {
+ this.source_icon = source_icon;
+ }
+
+ public int getPub_time() {
+ return pub_time;
+ }
+
+ public void setPub_time(int pub_time) {
+ this.pub_time = pub_time;
+ }
+
+ public int getUpdated_at() {
+ return updated_at;
+ }
+
+ public void setUpdated_at(int updated_at) {
+ this.updated_at = updated_at;
+ }
+
+ public int getDuration() {
+ return duration;
+ }
+
+ public void setDuration(int duration) {
+ this.duration = duration;
+ }
+
+ public int getHot() {
+ return hot;
+ }
+
+ public void setHot(int hot) {
+ this.hot = hot;
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/MediaInfoData.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/MediaInfoData.java
new file mode 100644
index 0000000000..a0ddf0f210
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/MediaInfoData.java
@@ -0,0 +1,156 @@
+package com.mogo.module.media.model;
+
+import com.mogo.module.media.constants.MusicConstant;
+
+import java.io.Serializable;
+
+public class MediaInfoData implements Serializable {
+
+ //QQ音乐,懒人听书,乐听头条 2 为书籍听书,3 为新闻,1 为qq音乐
+ private int type;
+
+ private String mediaId;//qq音乐id,书的bookId
+ //qq音乐url 懒人听书为“”
+ private String mediaUrl;
+
+ //歌曲名 ,当前播放书名,新闻标题内容
+ private String mediaName;
+
+ //演唱歌手,当前章节,新闻来源
+ private String mediaSinger;
+
+ //歌曲封面,书籍封面,新闻预览图
+ private String mediaImg;
+
+ //音乐类别,类似经典 ,流行只有qq特有
+ private String mediaType;
+
+ private int maxTime;//音频总时长
+
+ private String bookInfo;//懒人听书json串
+
+ //当前播放时长,可以不加,播放进度单独独立出来
+ private int curTime;
+
+ //是否是本地音频,只有qq音乐
+ private boolean isLocalMedia;//本地
+
+ //播放模式,顺序,单曲循环,随机
+ private int mediaPlayMode;
+
+ //1 播放 2 缓冲 0 暂停/停止 -1 播放错误
+ private int playState;
+
+ public String getMediaId() {
+ return mediaId;
+ }
+
+ public void setMediaId(String mediaId) {
+ this.mediaId = mediaId;
+ }
+
+ public String getMediaUrl() {
+ return mediaUrl;
+ }
+
+ public void setMediaUrl(String mediaUrl) {
+ this.mediaUrl = mediaUrl;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public void setType(int type) {
+ this.type = type;
+ }
+
+ public int getPlayState() {
+ return playState;
+ }
+
+ public void setPlayState(int playState) {
+ this.playState = playState;
+ }
+
+ public String getMediaName() {
+ return mediaName;
+ }
+
+ public void setMediaName(String mediaName) {
+ this.mediaName = mediaName;
+ }
+
+ public String getMediaSinger() {
+ return mediaSinger;
+ }
+
+ public void setMediaSinger(String mediaSinger) {
+ this.mediaSinger = mediaSinger;
+ }
+
+ public String getMediaImg() {
+ return mediaImg;
+ }
+
+ public void setMediaImg(String mediaImg) {
+ this.mediaImg = mediaImg;
+ }
+
+ public int getMaxTime() {
+ return maxTime;
+ }
+
+ public void setMaxTime(int maxTime) {
+ this.maxTime = maxTime;
+ }
+
+ public int getCurTime() {
+ return curTime;
+ }
+
+ public void setCurTime(int curTime) {
+ this.curTime = curTime;
+ }
+
+ public String getMediaType() {
+ return mediaType;
+ }
+
+ public void setMediaType(String mediaType) {
+ this.mediaType = mediaType;
+ }
+
+ public boolean isLocalMedia() {
+ return isLocalMedia;
+ }
+
+ public void setLocalMedia(boolean localMedia) {
+ isLocalMedia = localMedia;
+ }
+
+ public int getMediaPlayMode() {
+ return mediaPlayMode;
+ }
+
+ public void setMediaPlayMode(int mediaPlayMode) {
+ this.mediaPlayMode = mediaPlayMode;
+ }
+
+ public String getBookInfo() {
+ return bookInfo;
+ }
+
+ public void setBookInfo(String bookInfo) {
+ this.bookInfo = bookInfo;
+ }
+
+ @Override
+ public String toString() {
+ return "MediaInfoData{" +
+ "mediaName='" + mediaName + '\'' +
+ ", mediaImg='" + mediaImg + '\'' +
+ ", playState=" + playState +
+ '}';
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/MediaInfoDataEvent.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/MediaInfoDataEvent.java
new file mode 100644
index 0000000000..3849d03d76
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/MediaInfoDataEvent.java
@@ -0,0 +1,7 @@
+package com.mogo.module.media.model;
+
+import java.io.Serializable;
+
+public class MediaInfoDataEvent implements Serializable {
+ public MediaInfoData data;
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/MediaProcessEvent.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/MediaProcessEvent.java
new file mode 100644
index 0000000000..64c3419e97
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/MediaProcessEvent.java
@@ -0,0 +1,7 @@
+package com.mogo.module.media.model;
+
+import java.io.Serializable;
+
+public class MediaProcessEvent implements Serializable {
+ public int process;
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/NearShareRequestParameter.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/NearShareRequestParameter.java
new file mode 100644
index 0000000000..18c7a6767c
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/NearShareRequestParameter.java
@@ -0,0 +1,76 @@
+package com.mogo.module.media.model;
+
+import java.util.List;
+
+public class NearShareRequestParameter {
+
+ /**
+ * location : {"lat":31,"lon":116}
+ * radius : 1000
+ * dataType : ["CARD_TYPE_CARS_CHATTING","CARD_TYPE_ROAD_CODITION"]
+ * limit : 100
+ */
+
+ private LocationBean location;
+ private int radius;
+ private int limit;
+ private List dataType;
+
+ public LocationBean getLocation() {
+ return location;
+ }
+
+ public void setLocation(LocationBean location) {
+ this.location = location;
+ }
+
+ public int getRadius() {
+ return radius;
+ }
+
+ public void setRadius(int radius) {
+ this.radius = radius;
+ }
+
+ public int getLimit() {
+ return limit;
+ }
+
+ public void setLimit(int limit) {
+ this.limit = limit;
+ }
+
+ public List getDataType() {
+ return dataType;
+ }
+
+ public void setDataType(List dataType) {
+ this.dataType = dataType;
+ }
+
+ public static class LocationBean {
+ /**
+ * lat : 31.0
+ * lon : 116.0
+ */
+
+ private double lat;
+ private double lon;
+
+ public double getLat() {
+ return lat;
+ }
+
+ public void setLat(double lat) {
+ this.lat = lat;
+ }
+
+ public double getLon() {
+ return lon;
+ }
+
+ public void setLon(double lon) {
+ this.lon = lon;
+ }
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/QQMediaListData.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/QQMediaListData.java
new file mode 100644
index 0000000000..916ba6da1e
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/QQMediaListData.java
@@ -0,0 +1,58 @@
+package com.mogo.module.media.model;
+
+import java.io.Serializable;
+
+public class QQMediaListData implements Serializable {
+ //唯一区分歌曲
+ private String mediaUrl;
+
+ //歌曲名 ,当前播放书名,新闻标题内容
+ private String mediaName;
+
+ //演唱歌手,当前章节,新闻来源
+ private String mediaSinger;
+
+ private String mediaImgUrl;
+
+ private String mediaMid;
+
+ public String getMediaMid() {
+ return mediaMid;
+ }
+
+ public void setMediaMid(String mediaMid) {
+ this.mediaMid = mediaMid;
+ }
+
+ public String getMediaUrl() {
+ return mediaUrl;
+ }
+
+ public void setMediaUrl(String mediaUrl) {
+ this.mediaUrl = mediaUrl;
+ }
+
+ public String getMediaName() {
+ return mediaName;
+ }
+
+ public void setMediaName(String mediaName) {
+ this.mediaName = mediaName;
+ }
+
+ public String getMediaSinger() {
+ return mediaSinger;
+ }
+
+ public void setMediaSinger(String mediaSinger) {
+ this.mediaSinger = mediaSinger;
+ }
+
+ public String getMediaImgUrl() {
+ return mediaImgUrl;
+ }
+
+ public void setMediaImgUrl(String mediaImgUrl) {
+ this.mediaImgUrl = mediaImgUrl;
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/ShareLikeData.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/ShareLikeData.java
new file mode 100644
index 0000000000..f6018c6241
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/ShareLikeData.java
@@ -0,0 +1,20 @@
+package com.mogo.module.media.model;
+
+import com.mogo.commons.data.BaseData;
+
+public class ShareLikeData extends BaseData {
+
+ public ShareLikeDataResult result;
+
+ public static class ShareLikeDataResult{
+
+ public boolean checkLiked;
+ public int likedCount;
+ public String mediaId;
+ public String mediaUrl;
+ public int type; //1真是数据 2虚拟数据
+ public long userId;
+ public String userImg;
+ public String userName;
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/ShareMediaJsonData.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/ShareMediaJsonData.java
new file mode 100644
index 0000000000..3f70002032
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/ShareMediaJsonData.java
@@ -0,0 +1,15 @@
+package com.mogo.module.media.model;
+
+import java.io.Serializable;
+
+public class ShareMediaJsonData implements Serializable {
+ public String type;
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/ShareMediaMarkerInfoData.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/ShareMediaMarkerInfoData.java
new file mode 100644
index 0000000000..68351b20a4
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/ShareMediaMarkerInfoData.java
@@ -0,0 +1,47 @@
+package com.mogo.module.media.model;
+
+import com.mogo.commons.data.BaseData;
+import com.mogo.module.common.entity.MarkerShareMusic;
+
+import java.util.ArrayList;
+
+/**
+ MarkerShareMusic 结构说明:
+ * bookInfo : 懒人听书实体json串
+ * id : 100
+ * likeNumber : 99
+ * location : {"address":"北京市朝阳区三里屯街道108号","angle":"36.5","lat":"39.989368","lon":"116.480888"}
+ * mediaId : 音乐id
+ * mediaImg : 歌曲封面img url
+ * mediaName : 歌曲名
+ * mediaSinger : 歌手名
+ * mediaUrl : 歌曲url
+ * shareContentText : 分享的文字
+ * shareType : 1
+ * type : 卡片类型
+ * userInfo : {"age":"00后","gender":"男|女|无(也可以0|1|2根据实际库存返回即可)","sn":"018209312809312","userHead":"https://www.baidu.com/img/baidu_jgylogo3.png","userId":1,"userName":"用户昵称"}
+ */
+public class ShareMediaMarkerInfoData extends BaseData {
+
+ public ShareMediaMarkerInfoDataResult result;
+
+ public ShareMediaMarkerInfoDataResult getResult() {
+ return result;
+ }
+
+ public void setResult(ShareMediaMarkerInfoDataResult result) {
+ this.result = result;
+ }
+
+ public static class ShareMediaMarkerInfoDataResult{
+ public ArrayList shareMusic;
+
+ public ArrayList getShareMusic() {
+ return shareMusic;
+ }
+
+ public void setShareMusic(ArrayList shareMusic) {
+ this.shareMusic = shareMusic;
+ }
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/ShareSuccessResult.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/ShareSuccessResult.java
new file mode 100644
index 0000000000..9ad4338644
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/ShareSuccessResult.java
@@ -0,0 +1,16 @@
+package com.mogo.module.media.model;
+
+import com.mogo.commons.data.BaseData;
+import com.mogo.module.common.entity.MarkerShareMusic;
+
+public class ShareSuccessResult extends BaseData {
+ public MarkerShareMusic result;
+
+ public MarkerShareMusic getResult() {
+ return result;
+ }
+
+ public void setResult(MarkerShareMusic result) {
+ this.result = result;
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/ShowShareData.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/ShowShareData.java
new file mode 100644
index 0000000000..675299d556
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/ShowShareData.java
@@ -0,0 +1,27 @@
+package com.mogo.module.media.model;
+
+import com.mogo.commons.data.BaseData;
+
+public class ShowShareData extends BaseData {
+ public ShowShareResult result;
+
+ public ShowShareResult getResult() {
+ return result;
+ }
+
+ public void setResult(ShowShareResult result) {
+ this.result = result;
+ }
+
+ public static class ShowShareResult{
+ public boolean check;
+
+ public boolean isCheck() {
+ return check;
+ }
+
+ public void setCheck(boolean check) {
+ this.check = check;
+ }
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/url/UrlData.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/url/UrlData.java
new file mode 100644
index 0000000000..1143beba8a
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/model/url/UrlData.java
@@ -0,0 +1,29 @@
+package com.mogo.module.media.model.url;
+
+import java.io.Serializable;
+
+public class UrlData implements Serializable {
+ private String dztUrl;
+ private String apiUrl;
+
+ public UrlData(String dztUrl, String apiUrl) {
+ this.dztUrl = dztUrl;
+ this.apiUrl = apiUrl;
+ }
+
+ public String getDztUrl() {
+ return dztUrl;
+ }
+
+ public void setDztUrl(String dztUrl) {
+ this.dztUrl = dztUrl;
+ }
+
+ public String getApiUrl() {
+ return apiUrl;
+ }
+
+ public void setApiUrl(String apiUrl) {
+ this.apiUrl = apiUrl;
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/BaseMediaPresenter.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/BaseMediaPresenter.java
new file mode 100644
index 0000000000..9816d684a2
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/BaseMediaPresenter.java
@@ -0,0 +1,58 @@
+package com.mogo.module.media.presenter;
+
+import android.content.Context;
+
+import com.mogo.commons.mvp.IView;
+import com.mogo.commons.mvp.Presenter;
+import com.mogo.module.media.model.MediaInfoData;
+
+/**
+ * 媒体播放presenter基类,目前没有整合到原MediaPresenter中,原来的qq音乐,喜马拉雅和懒人听书下掉了
+ *
+ * @author tongchenfei
+ */
+public abstract class BaseMediaPresenter extends Presenter {
+ public BaseMediaPresenter(V view) {
+ super(view);
+ }
+
+ /**
+ * 初始化
+ *
+ * @param context 上下文
+ */
+ public abstract void init(Context context);
+
+ /**
+ * 播放音乐
+ * @param mediaInfoData 待播放音乐信息
+ */
+ public abstract void play(MediaInfoData mediaInfoData);
+
+ /**
+ * 暂停播放
+ * @param mediaInfoData 待暂停音乐信息
+ */
+ public abstract void pause(MediaInfoData mediaInfoData);
+
+ /**
+ * 停止播放
+ * @param mediaInfoData 待停止播放音乐信息
+ */
+ public abstract void stop(MediaInfoData mediaInfoData);
+
+ /**
+ * 上一首
+ */
+ public abstract void pre();
+
+ /**
+ * 下一首
+ */
+ public abstract void next();
+
+ /**
+ * 打开对应的应用
+ */
+ public abstract void openApp();
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/KwPresenter.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/KwPresenter.java
new file mode 100644
index 0000000000..6d40bafb55
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/KwPresenter.java
@@ -0,0 +1,259 @@
+package com.mogo.module.media.presenter;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import com.mogo.module.common.MogoApisHandler;
+import com.mogo.module.media.MediaConstants;
+import com.mogo.module.media.constants.MusicConstant;
+import com.mogo.module.media.model.MediaInfoData;
+import com.mogo.module.media.view.IMusicView;
+import com.mogo.service.IMogoServiceApis;
+import com.mogo.service.statusmanager.IMogoStatusChangedListener;
+import com.mogo.service.statusmanager.StatusDescriptor;
+
+import cn.kuwo.autosdk.api.KWAPI;
+import cn.kuwo.autosdk.api.OnGetSongImgUrlListener;
+import cn.kuwo.autosdk.api.PlayState;
+import cn.kuwo.autosdk.api.PlayerStatus;
+import cn.kuwo.base.bean.Music;
+
+/**
+ * 适配酷我的presenter
+ *
+ * @author tongchenfei
+ */
+public class KwPresenter extends BaseMediaPresenter {
+ private static final String TAG = "KwPresenter";
+ private KWAPI kwapi;
+ private boolean isBind = false;
+
+ private MediaInfoData currentMedia = new MediaInfoData();
+
+ public KwPresenter(IMusicView view) {
+ super(view);
+ }
+
+ @Override
+ public void init(Context context) {
+ kwapi = KWAPI.createKWAPI(context, "auto");
+
+ kwapi.registerConnectedListener(b -> {
+ Log.d(TAG, "onConnected: " + b);
+ Log.d(TAG, "onConnected: " + b);
+ isBind = b;
+ if (!isBind) {
+ mView.onMusicStopped();
+ }else{
+ PlayerStatus currentState = kwapi.getPlayerStatus();
+ Log.d(TAG, "check current status: " + currentState);
+ Log.d(TAG, "check current status: " + currentState);
+ if(currentState == PlayerStatus.BUFFERING||currentState == PlayerStatus.PLAYING){
+ currentMedia.setPlayState(MusicConstant.PLAY_STATE_PLAYING);
+ kwapi.getSongPicUrl(kwapi.getNowPlayingMusic(), onGetSongImgUrlListener);
+ startTrackTrackProgress();
+ mView.onMusicPlaying();
+ }
+ }
+ });
+
+ kwapi.registerExitListener(() -> {
+ Log.d(TAG, "onExit===");
+ Log.d(TAG, "onExit===");
+ mView.onAppExit();
+ });
+
+ kwapi.registerPlayerStatusListener((playerStatus, music) -> {
+ if ( music == null ) {
+ return;
+ }
+ Log.d(TAG, "onPlayerStatusListener: " + playerStatus + " music: " + music.name);
+ switch (playerStatus) {
+ case BUFFERING:
+ if (currentMedia.getMediaName() == null || !currentMedia.getMediaName().equals(music.name)) {
+ // 说明是切了新歌,需要及时同步一下状态
+ currentMedia.setPlayState(MusicConstant.PLAY_STATE_PLAYING);
+ currentMedia.setMediaName(music.name);
+ currentMedia.setMediaImg("");
+ mView.onMediaInfoChanged(currentMedia);
+ mView.onMusicPlaying();
+ }
+ kwapi.getSongPicUrl(music, onGetSongImgUrlListener);
+ break;
+ case PLAYING:
+ if (currentMedia.getMediaName() == null || !currentMedia.getMediaName().equals(music.name)) {
+ // 说明是切了新歌,需要及时同步一下状态
+ currentMedia.setPlayState(MusicConstant.PLAY_STATE_PLAYING);
+ currentMedia.setMediaName(music.name);
+ currentMedia.setMediaImg("");
+ mView.onMediaInfoChanged(currentMedia);
+ }
+ currentMedia.setPlayState(MusicConstant.PLAY_STATE_PLAYING);
+ kwapi.getSongPicUrl(music, onGetSongImgUrlListener);
+ startTrackTrackProgress();
+ mView.onMusicPlaying();
+ break;
+ case INIT:
+ case PAUSE:
+ case STOP:
+ currentMedia.setPlayState(MusicConstant.PLAY_STATE_PAUSE_OR_STOP);
+ stopTrackTrackProgress();
+ mView.onMusicPause();
+ break;
+ default:
+ break;
+ }
+ });
+
+ IMogoServiceApis serviceApis = MogoApisHandler.getInstance().getApis();
+
+ serviceApis.getStatusManagerApi().registerStatusChangedListener(MediaConstants.MODULE_TYPE, StatusDescriptor.MAIN_PAGE_RESUME, new IMogoStatusChangedListener() {
+ @Override
+ public void onStatusChanged(StatusDescriptor descriptor, boolean isTrue) {
+ if (isTrue) {
+ Log.d(TAG, "onResume, isBind: " + isBind);
+ Log.d(TAG, "onResume, isBind: " + isBind);
+ // 需要在resume时候判断绑定关系是否正常
+ if (!isBind) {
+ // 未绑定,需要重新绑定,同时第一次绑定初始化也是在此处
+ kwapi.bindAutoSdkService();
+ }else if(kwapi.isKuwoRunning()){
+ Music currentMusic = kwapi.getNowPlayingMusic();
+ if (currentMedia.getMediaName() == null && currentMusic != null) {
+ // 当前处于绑定状态,且有音乐信息,需判断是否正在播放,进行界面刷新
+ Log.d(TAG, "step1==" + currentMusic.name);
+ if (kwapi.getPlayerStatus() == PlayerStatus.BUFFERING || kwapi.getPlayerStatus() == PlayerStatus.PLAYING) {
+ Log.d(TAG, "当前可能正在播放音乐,需要更新=1=" + currentMusic.name);
+ currentMedia.setMediaName(currentMusic.name);
+ currentMedia.setPlayState(MusicConstant.PLAY_STATE_PLAYING);
+ mView.onMediaInfoChanged(currentMedia);
+ mView.onMusicPlaying();
+ kwapi.getSongPicUrl(currentMusic, onGetSongImgUrlListener);
+ } else if (kwapi.getPlayerStatus() == PlayerStatus.INIT) {
+ Log.d(TAG, "当前可能正在播放音乐,需要更新=3=" + currentMusic.name);
+ currentMedia.setMediaName(currentMusic.name);
+ currentMedia.setPlayState(MusicConstant.PLAY_STATE_PAUSE_OR_STOP);
+ mView.onMediaInfoChanged(currentMedia);
+ mView.onMusicStopped();
+ }
+ } else if (currentMedia.getMediaName() != null && currentMusic != null && !currentMedia.getMediaName().equals(currentMusic.name)) {
+ Log.d(TAG, "step2==media: " + currentMedia.getMediaName() + " " +
+ "musicName: " + currentMusic.name + " status: " + kwapi.getPlayerStatus());
+ if (kwapi.getPlayerStatus() == PlayerStatus.BUFFERING || kwapi.getPlayerStatus() == PlayerStatus.PLAYING) {
+ Log.d(TAG, "当前可能正在播放音乐,需要更新=2=" + currentMusic.name);
+ currentMedia.setMediaName(currentMusic.name);
+ currentMedia.setPlayState(MusicConstant.PLAY_STATE_PLAYING);
+ mView.onMediaInfoChanged(currentMedia);
+ mView.onMusicPlaying();
+ kwapi.getSongPicUrl(currentMusic, onGetSongImgUrlListener);
+ }else if (kwapi.getPlayerStatus() == PlayerStatus.INIT) {
+ Log.d(TAG, "当前可能正在播放音乐,需要更新=4=" + currentMusic.name);
+ currentMedia.setMediaName(currentMusic.name);
+ currentMedia.setPlayState(MusicConstant.PLAY_STATE_PAUSE_OR_STOP);
+ mView.onMediaInfoChanged(currentMedia);
+ mView.onMusicStopped();
+ }
+ }
+ }
+ }
+ }
+ });
+
+ kwapi.bindAutoSdkService();
+ }
+
+ @Override
+ public void play(MediaInfoData mediaInfoData) {
+ if (kwapi.isKuwoRunning()) {
+ kwapi.setPlayState(PlayState.STATE_PLAY);
+ } else {
+ kwapi.startAPP(true);
+ }
+ }
+
+ @Override
+ public void pause(MediaInfoData mediaInfoData) {
+ if (kwapi.isKuwoRunning()) {
+ kwapi.setPlayState(PlayState.STATE_PAUSE);
+ }else{
+ kwapi.startAPP(true);
+ }
+ }
+
+ @Override
+ public void stop(MediaInfoData mediaInfoData) {
+
+ }
+
+ @Override
+ public void pre() {
+ if (kwapi.isKuwoRunning()) {
+ kwapi.setPlayState(PlayState.STATE_PRE);
+ }
+ }
+
+ @Override
+ public void next() {
+ if (kwapi.isKuwoRunning()) {
+ kwapi.setPlayState(PlayState.STATE_NEXT);
+ }else{
+ kwapi.startAPP(true);
+ }
+ }
+
+ private Handler.Callback callback = new Handler.Callback() {
+ @Override
+ public boolean handleMessage(Message msg) {
+ if (isTrackingProgress) {
+ mView.onMusicProgress(kwapi.getCurrentPos(), kwapi.getCurrentMusicDuration());
+ msg.getTarget().sendEmptyMessageDelayed(MSG_TRACK_PROGRESS,
+ MSG_TRACK_PROGRESS_DELAY);
+ }
+ return false;
+ }
+ };
+ private Handler handler = new Handler(callback);
+ private static final int MSG_TRACK_PROGRESS = 1001;
+ private static final long MSG_TRACK_PROGRESS_DELAY = 1000;
+
+ private boolean isTrackingProgress = false;
+
+ private void startTrackTrackProgress() {
+ if(!isTrackingProgress) {
+ isTrackingProgress = true;
+ handler.sendEmptyMessageDelayed(MSG_TRACK_PROGRESS, MSG_TRACK_PROGRESS_DELAY);
+ }
+ }
+
+ private void stopTrackTrackProgress() {
+ if(isTrackingProgress) {
+ isTrackingProgress = false;
+ handler.removeMessages(MSG_TRACK_PROGRESS);
+ }
+ }
+
+ private OnGetSongImgUrlListener onGetSongImgUrlListener = new OnGetSongImgUrlListener() {
+ @Override
+ public void onGetSongImgUrlSucessed(Music music, String s) {
+ if(currentMedia.getPlayState() == MusicConstant.PLAY_STATE_PLAYING) {
+ currentMedia.setMediaName(music.name);
+ currentMedia.setMediaImg(s);
+ Log.d(TAG,
+ "onGetSongImgUrlSucessed: " + currentMedia);
+ handler.post(() -> mView.onMediaInfoChanged(currentMedia));
+ }
+ }
+
+ @Override
+ public void onGetSongImgUrlFailed(Music music, int i) {
+ Log.e(TAG, "onGetSongImgUrlFailed: " + i);
+ }
+ };
+
+ @Override
+ public void openApp(){
+ kwapi.startAPP(true);
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/MediaPresenter.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/MediaPresenter.java
new file mode 100644
index 0000000000..292d9e1b0c
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/MediaPresenter.java
@@ -0,0 +1,532 @@
+package com.mogo.module.media.presenter;
+
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+
+import com.mogo.commons.data.BaseData;
+import com.mogo.commons.mvp.Presenter;
+import com.mogo.commons.network.ParamsProvider;
+import com.mogo.commons.network.ParamsUtil;
+import com.mogo.commons.network.SubscribeImpl;
+import com.mogo.commons.voice.AIAssist;
+import com.mogo.map.location.MogoLocation;
+import com.mogo.module.common.entity.MarkerResponse;
+import com.mogo.module.common.entity.MarkerShareMusic;
+import com.mogo.module.media.MediaConstants;
+import com.mogo.module.media.R;
+import com.mogo.module.media.ServiceMediaHandler;
+import com.mogo.module.media.api.MediaDztService;
+import com.mogo.module.media.constants.BaseUrlConstants;
+import com.mogo.module.media.constants.EventConstants;
+import com.mogo.module.media.model.MediaInfoData;
+import com.mogo.module.media.model.NearShareRequestParameter;
+import com.mogo.module.media.model.ShareLikeData;
+import com.mogo.module.media.model.ShareMediaMarkerInfoData;
+import com.mogo.module.media.model.ShareSuccessResult;
+import com.mogo.module.media.model.ShowShareData;
+import com.mogo.module.media.utils.BaseUrlManager;
+import com.mogo.module.media.utils.MediaAnalyticsUtils;
+import com.mogo.module.media.utils.StorageManager;
+import com.mogo.module.media.utils.ToastHelper;
+import com.mogo.module.media.view.MediaView;
+import com.mogo.utils.TipToast;
+import com.mogo.utils.network.RequestOptions;
+import com.mogo.utils.network.utils.GsonUtil;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.functions.Consumer;
+import io.reactivex.schedulers.Schedulers;
+
+public class MediaPresenter extends Presenter {
+
+ private static final String TAG = "MediaPresenter";
+ private ArrayList mDisPosables;
+
+ public MediaPresenter(MediaView view) {
+ super(view);
+ }
+
+ @Override
+ public void onCreate(@NonNull LifecycleOwner owner) {
+ super.onCreate(owner);
+ }
+
+ public void getFriendMusic() {
+ final ParamsProvider.Builder builder = new ParamsProvider.Builder(getContext());
+ final MogoLocation location = ServiceMediaHandler.getLocationClient().getLastKnowLocation();
+ if (location != null) {
+ builder.append("address", location.getAddress());
+ builder.append("lat", location.getLatitude());
+ builder.append("lng", location.getLongitude());
+ }
+
+ Map parameters = builder.build();
+ Observable observable = ServiceMediaHandler.getMogoNetWorkService().
+ create(MediaDztService.class, BaseUrlManager.getDztBaseUrl()).getFriendShareMusic(parameters);
+ observable
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new SubscribeImpl(RequestOptions.create(getContext())) {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDispose(d);
+ }
+
+ @Override
+ public void onSuccess(ShareMediaMarkerInfoData resultData) {
+ if (resultData != null && resultData.getResult() != null
+ && resultData.getResult().getShareMusic() != null
+ && resultData.getResult().getShareMusic().size() > 0){
+ mView.loadFriendShareMusicSuccess(resultData.getResult().getShareMusic());
+ }else{
+ TipToast.shortTip("您的好友未分享过歌曲");
+ AIAssist.getInstance(mView.getContext()).speakTTSVoice("您的好友未分享过歌曲",null);
+ }
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ super.onError(e);
+ TipToast.shortTip("获取好友的歌失败");
+ }
+
+ @Override
+ public void onError(String message, int code) {
+ super.onError(message, code);
+ TipToast.shortTip("获取好友的歌失败");
+
+ }
+ }
+ );
+
+ }
+
+ /**
+ * 开始音乐播放的接口
+ * @param mCurrentMusic
+ */
+ public void startedMusic(MediaInfoData mCurrentMusic) {
+ if (mCurrentMusic == null)return;
+ final ParamsProvider.Builder builder = new ParamsProvider.Builder(getContext());
+ HashMap hashMap = new HashMap<>();
+ hashMap.put("mediaType", mCurrentMusic.getType());
+ hashMap.put("shareData", mCurrentMusic);
+ builder.append("data", GsonUtil.jsonFromObject(hashMap));
+ Map parameters = builder.build();
+ Observable observable = ServiceMediaHandler.getMogoNetWorkService().
+ create(MediaDztService.class, BaseUrlManager.getDztBaseUrl()).startedMusic(parameters);
+ observable
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new SubscribeImpl(RequestOptions.create(getContext())) {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDispose(d);
+ }
+
+ @Override
+ public void onSuccess(BaseData resultData) {
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ super.onError(e);
+
+ }
+
+ @Override
+ public void onError(String message, int code) {
+ super.onError(message, code);
+
+ }
+ }
+ );
+
+ }
+
+
+ /**
+ * 请求附近的
+ */
+ public void getNearShareMusic() {
+ final ParamsProvider.Builder builder = new ParamsProvider.Builder(getContext());
+ NearShareRequestParameter nearData = new NearShareRequestParameter();
+ NearShareRequestParameter.LocationBean locationBean = new NearShareRequestParameter.LocationBean();
+ final MogoLocation location = ServiceMediaHandler.getLocationClient().getLastKnowLocation();
+ if ( location != null ) {
+ locationBean.setLat(locationBean.getLat());
+ locationBean.setLon(locationBean.getLon());
+ }
+ nearData.setLocation(locationBean);
+ nearData.setLimit(10);
+ nearData.setRadius(2000);
+ ArrayList list = new ArrayList<>();
+ list.add(MediaConstants.MODULE_TYPE);
+ nearData.setDataType(list);
+ builder.append("data", GsonUtil.jsonFromObject(nearData));
+ Map parameters = builder.build();
+ Observable observable = ServiceMediaHandler.getMogoNetWorkService().
+ create(MediaDztService.class, BaseUrlManager.getDztBaseUrl()).getNearShareMusic(parameters);
+ Disposable disposable = observable
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(
+ new Consumer() {
+ @Override
+ public void accept(MarkerResponse markerResponse) throws Exception {
+ if (markerResponse != null && markerResponse.getCode() == 0
+ && markerResponse.getResult() != null
+ && markerResponse.getResult().getShareMusic() != null
+ && markerResponse.getResult().getShareMusic().size() > 0){
+ mView.loadNearShareMusicSuccess(markerResponse.getResult().getShareMusic());
+ }else{
+ AIAssist.getInstance(mView.getContext()).speakTTSVoice("当前暂无分享的歌曲",null);
+ }
+ }
+ },
+ new Consumer() {
+ @Override
+ public void accept(Throwable throwable) throws Exception {
+ TipToast.shortTip("获取附近的歌失败");
+ }
+ }
+ );
+
+ addDispose(disposable);
+ }
+
+ /**
+ * 停止音乐播放的接口
+ */
+ public void stopMusic() {
+ final ParamsProvider.Builder builder = new ParamsProvider.Builder(getContext());
+ Map parameters = builder.build();
+ Observable observable = ServiceMediaHandler.getMogoNetWorkService().
+ create(MediaDztService.class, BaseUrlManager.getDztBaseUrl()).stopMusic(parameters);
+ observable
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new SubscribeImpl(RequestOptions.create(getContext())) {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDispose(d);
+ }
+
+ @Override
+ public void onSuccess(BaseData resultData) {
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ super.onError(e);
+
+ }
+
+ @Override
+ public void onError(String message, int code) {
+ super.onError(message, code);
+
+ }
+ }
+ );
+
+ }
+
+ public void getShouldShare() {
+ final ParamsProvider.Builder builder = new ParamsProvider.Builder(getContext());
+ Map parameters = builder.build();
+ Observable observable = ServiceMediaHandler.getMogoNetWorkService().
+ create(MediaDztService.class, BaseUrlManager.getDztBaseUrl()).getShouldPushShare(parameters);
+ observable
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new SubscribeImpl(RequestOptions.create(getContext())) {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDispose(d);
+ }
+
+ @Override
+ public void onSuccess(ShowShareData resultData) {
+ //存储请求了触发分享的接口,每次accon一次
+ StorageManager.setShowPushShareTime(System.currentTimeMillis()+"");
+ if (resultData != null && resultData.result != null){
+ mView.showSharePush(resultData.result.check);
+ }
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ super.onError(e);
+
+ }
+
+ @Override
+ public void onError(String message, int code) {
+ super.onError(message, code);
+
+ }
+ }
+ );
+
+ }
+
+ public void selectByPrimaryKey(int id,String mediaId){
+ final ParamsProvider.Builder builder = new ParamsProvider.Builder(getContext());
+ builder.append("id",id);
+ Map parameters = builder.build();
+
+ Observable observable = ServiceMediaHandler.getMogoNetWorkService().
+ create(MediaDztService.class, BaseUrlManager.getDztBaseUrl()).selectByPrimaryKey(parameters);
+ observable
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new SubscribeImpl(RequestOptions.create(getContext())) {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDispose(d);
+ }
+
+ @Override
+ public void onSuccess(ShareLikeData resultData) {
+ //存储请求了触发分享的接口,每次accon一次
+ if (resultData == null){
+ return;
+ }
+ if (resultData.result == null){
+ return;
+ }
+ mView.loadShareLikeDataResultSuccess(resultData.result,mediaId);
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ super.onError(e);
+ TipToast.shortTip("加载点赞信息失败,请重试");
+ }
+
+ @Override
+ public void onError(String message, int code) {
+ super.onError(message, code);
+ TipToast.shortTip("加载点赞信息失败,请重试");
+ }
+ }
+ );
+
+ }
+
+ public void likeShare(ShareLikeData.ShareLikeDataResult likeDataResult){
+
+ final Map businessParams = new HashMap<>();
+ final MogoLocation location = ServiceMediaHandler.getLocationClient().getLastKnowLocation();
+
+ businessParams.put("musicId", likeDataResult.mediaId);
+ businessParams.put("musicUrl", likeDataResult.mediaUrl);
+ businessParams.put("userId", likeDataResult.userId);
+ businessParams.put("userType", likeDataResult.type);
+
+ ParamsProvider.Builder builder = new ParamsProvider.Builder(getContext());
+ if (location != null) {
+ builder.append("lat", location.getLatitude());
+ builder.append("lng", location.getLongitude());
+ }
+ final Map params = builder
+ .append(businessParams)
+ .build();
+
+
+ Observable observable = ServiceMediaHandler.getMogoNetWorkService().create(MediaDztService.class, BaseUrlManager.getDztBaseUrl())
+ .likeShare(ParamsUtil.toQueryUrl(BaseUrlManager.getDztBaseUrl() + BaseUrlConstants.SHARE_MUSIC_LIKE_URL, params, businessParams), ParamsUtil.convert(businessParams));
+ observable
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new SubscribeImpl(RequestOptions.create(getContext())) {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDispose(d);
+ }
+
+ @Override
+ public void onSuccess(BaseData resultData) {
+ mView.likeShareSuccess();
+ TipToast.shortTip("点赞成功");
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ super.onError(e);
+ TipToast.shortTip("点赞失败,请重试");
+ }
+
+ @Override
+ public void onError(String message, int code) {
+ super.onError(message, code);
+ TipToast.shortTip(message != null ?message:"点赞失败,请重试");
+ }
+ }
+ );
+
+
+ }
+
+ public void addDispose(Disposable subscription){
+ if (subscription != null){
+ if (mDisPosables == null) mDisPosables = new ArrayList<>();
+ mDisPosables.add(subscription);
+ }
+ }
+
+ public String getPackageName(MediaInfoData mMediaInfoData){
+ if (mMediaInfoData == null) return "";
+ if (mMediaInfoData.getType() == 1){
+ return "com.pvetec.musics";
+ }else if (mMediaInfoData.getType() == 2){
+ return "com.zhidao.lrts";
+ }else if (mMediaInfoData.getType() == 3){
+ return "com.zhidao.ltnews";
+ }else{
+ return "";
+ }
+ }
+
+ public String getAppName(MediaInfoData mMediaInfoData){
+ if (mMediaInfoData == null) return "";
+ if (mMediaInfoData.getType() == 1){
+ return "QQ音乐";
+ }else if (mMediaInfoData.getType() == 2){
+ return "懒人听书";
+ }else if (mMediaInfoData.getType() == 3){
+ return "乐听头条";
+ }else{
+ return "";
+ }
+ }
+
+ public void shareMusic(MediaInfoData mCurrentMusic,boolean click) {
+ if (mCurrentMusic == null) return;
+ try {
+ if (mCurrentMusic != null){
+ HashMap hashMap = new HashMap<>();
+ hashMap.put("type",click ? 1:2);
+ String trackId = "";
+ if (mCurrentMusic.getType() == 1){
+ trackId = EventConstants.EVENT_QQ_SHARE_DIALOG_OK;
+ }else if (mCurrentMusic.getType() == 2){
+ trackId = EventConstants.EVENT_BOOK_SHARE_DIALOG_OK;
+ }else if (mCurrentMusic.getType() == 3){
+ trackId = EventConstants.EVENT_NEWS_SHARE_DIALOG_OK;
+ }
+ MediaAnalyticsUtils.track(trackId ,hashMap);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ final Map businessParams = new HashMap<>();
+ final MogoLocation location = ServiceMediaHandler.getLocationClient().getLastKnowLocation();
+ if (location != null) {
+ businessParams.put("address", location.getAddress());
+ }
+
+ businessParams.put("bookInfo", mCurrentMusic.getBookInfo());
+ businessParams.put("mediaDuration", mCurrentMusic.getMaxTime() + "");
+ businessParams.put("mediaId", mCurrentMusic.getMediaId());
+ businessParams.put("mediaImg", mCurrentMusic.getMediaImg());
+ businessParams.put("mediaName", mCurrentMusic.getMediaName());
+ businessParams.put("mediaSinger", mCurrentMusic.getMediaSinger());
+ businessParams.put("mediaType", mCurrentMusic.getMediaType());
+ businessParams.put("mediaUrl", mCurrentMusic.getMediaUrl());
+ businessParams.put("shareType", mCurrentMusic.getType());
+
+ ParamsProvider.Builder builder = new ParamsProvider.Builder(getContext());
+ if (location != null) {
+ builder.append("lat", location.getLatitude());
+ builder.append("lng", location.getLongitude());
+ }else{
+ TipToast.shortTip("分享失败,定位出错请重试!");
+ return;
+ }
+ final Map params = builder
+ .append(businessParams)
+ .build();
+ Observable observable = ServiceMediaHandler.getMogoNetWorkService().create(MediaDztService.class, BaseUrlManager.getDztBaseUrl())
+ .shareMusic(ParamsUtil.toQueryUrl(BaseUrlManager.getDztBaseUrl() + BaseUrlConstants.SHARE_MUSIC_URL, params, businessParams), ParamsUtil.convert(businessParams));
+ observable
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new SubscribeImpl(com.mogo.utils.network.RequestOptions.create(getContext())) {
+ @Override
+ public void onSubscribe(Disposable d) {
+ super.onSubscribe(d);
+ addDispose(d);
+ }
+
+ @Override
+ public void onSuccess(ShareSuccessResult resultData) {
+ try {
+ ToastHelper.showShortSuccess(getContext(), getContext().getResources().getString(R.string.module_media_share_success));
+ AIAssist.getInstance(getContext()).speakTTSVoice(getContext().getResources().getString(R.string.module_media_share_success),null);
+ if (resultData != null && resultData.result != null){
+ MarkerShareMusic markerShareMusic = resultData.result;
+ markerShareMusic.setType(MediaConstants.MODULE_TYPE);
+ mView.shareSuccessResult(true,markerShareMusic);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ super.onError(e);
+ try {
+ ToastHelper.showShortError(getContext(), getContext().getResources().getString(R.string.module_media_share_fail));
+ TipToast.shortTip("分享失败");
+ AIAssist.getInstance(getContext()).speakTTSVoice(getContext().getResources().getString(R.string.module_media_share_fail),null);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onError(String message, int code) {
+ super.onError(message, code);
+ try {
+ ToastHelper.showShortError(getContext(), getContext().getResources().getString(R.string.module_media_share_fail));
+ TipToast.shortTip(!TextUtils.isEmpty(message)?message:"分享失败");
+ AIAssist.getInstance(getContext()).speakTTSVoice(!TextUtils.isEmpty(message)?message:"分享失败",null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ );
+
+ }
+
+ @Override
+ public void onDestroy(@NonNull LifecycleOwner owner) {
+ super.onDestroy(owner);
+ if (mDisPosables != null && !mDisPosables.isEmpty()) {
+ for (Disposable subscription : mDisPosables) {
+ if (subscription == null || subscription.isDisposed()) {
+ continue;
+ }
+ subscription.dispose();
+ }
+ mDisPosables.clear();
+ mDisPosables = null;
+ }
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/NoopPresenter.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/NoopPresenter.java
new file mode 100644
index 0000000000..4270a87d06
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/NoopPresenter.java
@@ -0,0 +1,52 @@
+package com.mogo.module.media.presenter;
+
+import android.content.Context;
+
+import com.mogo.module.media.model.MediaInfoData;
+import com.mogo.module.media.view.IMusicView;
+
+/**
+ * 空presenter实现,为了减少各种空判断
+ *
+ * @author tongchenfei
+ */
+public class NoopPresenter extends BaseMediaPresenter {
+ public NoopPresenter(IMusicView view) {
+ super(view);
+ }
+
+ @Override
+ public void init(Context context) {
+
+ }
+
+ @Override
+ public void play(MediaInfoData mediaInfoData) {
+
+ }
+
+ @Override
+ public void pause(MediaInfoData mediaInfoData) {
+
+ }
+
+ @Override
+ public void stop(MediaInfoData mediaInfoData) {
+
+ }
+
+ @Override
+ public void pre() {
+
+ }
+
+ @Override
+ public void next() {
+
+ }
+
+ @Override
+ public void openApp() {
+
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/PresenterFactory.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/PresenterFactory.java
new file mode 100644
index 0000000000..c5661387b7
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/PresenterFactory.java
@@ -0,0 +1,45 @@
+package com.mogo.module.media.presenter;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+
+import com.mogo.module.media.view.IMusicView;
+
+import java.util.List;
+
+/**
+ * Presenter简单工厂,根据包名判断选择哪个presenter
+ *
+ * @author tongchenfei
+ */
+public class PresenterFactory {
+ private static final String KW_PKG_NAME = "cn.kuwo.kwmusiccar";
+ private static final String WE_CAR_FLOW_PKG_NAME = "com.tencent.wecarflow";
+
+ /**
+ * 获取泛型是IMusicView的BaseMediaPresenter
+ *
+ * @param context 上下文,用来遍历机器上的包名
+ * @param view IMusicView,用来做view展示
+ * @return presenter
+ */
+ public static BaseMediaPresenter createMusicViewPresenter(Context context,
+ IMusicView view) {
+ BaseMediaPresenter result = null;
+ PackageManager pkm = context.getPackageManager();
+ List pkgInfoList = pkm.getInstalledPackages(0);
+ // 只做了两级优先级判断,比较简单
+ for (PackageInfo pkgInfo : pkgInfoList) {
+ if (pkgInfo.packageName.equals(KW_PKG_NAME)) {
+ result = new KwPresenter(view);
+ } else if (pkgInfo.packageName.equals(WE_CAR_FLOW_PKG_NAME) && result == null) {
+ result = new WeCarFlowPresenter(view);
+ }
+ }
+ if (result == null) {
+ result = new NoopPresenter(view);
+ }
+ return result;
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/WeCarFlowPresenter.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/WeCarFlowPresenter.java
new file mode 100644
index 0000000000..570964a4b2
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/presenter/WeCarFlowPresenter.java
@@ -0,0 +1,198 @@
+package com.mogo.module.media.presenter;
+
+import android.content.Context;
+
+import com.mogo.module.common.MogoApisHandler;
+import com.mogo.module.media.MediaConstants;
+import com.mogo.module.media.constants.MusicConstant;
+import com.mogo.module.media.model.MediaInfoData;
+import com.mogo.module.media.view.IMusicView;
+import com.mogo.service.IMogoServiceApis;
+import com.mogo.service.statusmanager.IMogoStatusChangedListener;
+import com.mogo.service.statusmanager.StatusDescriptor;
+import com.mogo.utils.logger.Logger;
+import com.tencent.wecarflow.flowoutside.sdk.BindListener;
+import com.tencent.wecarflow.flowoutside.sdk.FlowPlayControl;
+import com.tencent.wecarflow.flowoutside.sdk.MediaChangeListener;
+import com.tencent.wecarflow.flowoutside.sdk.MediaInfo;
+import com.tencent.wecarflow.flowoutside.sdk.PlayStateListener;
+import com.tencent.wecarflow.flowoutside.sdk.QueryCallback;
+
+/**
+ * 爱趣听presenter
+ *
+ * @author tongchenfei
+ */
+public class WeCarFlowPresenter extends BaseMediaPresenter {
+ private static final String TAG = "WeCarFlowPresenter";
+ public WeCarFlowPresenter(IMusicView view) {
+ super(view);
+ }
+
+ private Context context;
+
+ private MediaInfoData currentMedia;
+
+ private boolean isBind = true;
+ private IMogoServiceApis serviceApis;
+
+ private QueryCallback isPlayingCallback = new QueryCallback() {
+ @Override
+ public void onError(int i) {
+
+ }
+
+ @Override
+ public void onSuccess(Boolean aBoolean) {
+ currentMedia.setPlayState(aBoolean ? MusicConstant.PLAY_STATE_PLAYING :
+ MusicConstant.PLAY_STATE_PAUSE_OR_STOP);
+ if (mView != null) {
+ mView.onMediaInfoChanged(currentMedia);
+ }
+ }
+ };
+
+ private QueryCallback currentCallback = new QueryCallback() {
+ @Override
+ public void onError(int i) {
+
+ }
+
+ @Override
+ public void onSuccess(MediaInfo mediaInfo) {
+ currentMedia.setMediaName(mediaInfo.getMediaName());
+ currentMedia.setMediaImg(mediaInfo.getMediaImage());
+ if (mView != null) {
+ mView.onMediaInfoChanged(currentMedia);
+ }
+ }
+ };
+
+ @Override
+ public void init(Context context) {
+ this.context = context;
+ currentMedia = new MediaInfoData();
+
+ serviceApis = MogoApisHandler.getInstance().getApis();
+
+ serviceApis.getStatusManagerApi().registerStatusChangedListener(MediaConstants.MODULE_TYPE, StatusDescriptor.MAIN_PAGE_RESUME, new IMogoStatusChangedListener() {
+ @Override
+ public void onStatusChanged(StatusDescriptor descriptor, boolean isTrue) {
+ if (isTrue) {
+ Logger.d(TAG, "onResume, isBind: " + isBind);
+ // 需要在resume时候判断绑定关系是否正常
+ if (!isBind) {
+ // 未绑定,需要重新绑定,同时第一次绑定初始化也是在此处
+ FlowPlayControl.getInstance().bindPlayService(context);
+ }
+ }
+ }
+ });
+
+ FlowPlayControl.getInstance().addBindListener(new BindListener() {
+ @Override
+ public void onServiceConnected() {
+ Logger.d(TAG, "onServiceConnected===");
+ isBind = true;
+ FlowPlayControl.getInstance().queryPlaying(isPlayingCallback);
+ FlowPlayControl.getInstance().queryCurrent(currentCallback);
+ }
+
+ @Override
+ public void onServiceDisconnected() {
+ Logger.e(TAG, "onServiceDisconnected===");
+ isBind = false;
+ }
+
+ @Override
+ public void onBindDied() {
+ Logger.e(TAG, "onBindDied===");
+ isBind = false;
+ }
+ });
+
+ FlowPlayControl.getInstance().addMediaChangeListener(new MediaChangeListener() {
+ @Override
+ public void onMediaChange(MediaInfo mediaInfo) {
+ Logger.d(TAG, "onMediaChange: " + mediaInfo);
+ Logger.d(TAG, "onMediaChange, img: " + mediaInfo.getMediaImage());
+ currentMedia.setMediaName(mediaInfo.getMediaName());
+ currentMedia.setMediaImg(mediaInfo.getMediaImage());
+ mView.onMediaInfoChanged(currentMedia);
+ }
+
+ @Override
+ public void onFavorChange(boolean b) {
+
+ }
+ });
+
+ FlowPlayControl.getInstance().addPlayStateListener(new PlayStateListener() {
+ @Override
+ public void onStart() {
+ if (mView != null && currentMedia != null) {
+ currentMedia.setPlayState(MusicConstant.PLAY_STATE_PLAYING);
+ mView.onMusicPlaying();
+ mView.onMediaInfoChanged(currentMedia);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ if (mView != null && currentMedia != null) {
+ currentMedia.setPlayState(MusicConstant.PLAY_STATE_PAUSE_OR_STOP);
+ mView.onMusicPause();
+ mView.onMediaInfoChanged(currentMedia);
+ }
+ }
+
+ @Override
+ public void onStop() {
+ if (mView != null && currentMedia != null) {
+ currentMedia.setPlayState(MusicConstant.PLAY_STATE_PAUSE_OR_STOP);
+ mView.onMusicStopped();
+ mView.onMediaInfoChanged(currentMedia);
+ }
+ }
+
+ @Override
+ public void onProgress(String s, long current, long total) {
+ if (mView != null) {
+ mView.onMusicProgress(current, total);
+ }
+ }
+ });
+
+ FlowPlayControl.getInstance().bindPlayService(context);
+ }
+
+ @Override
+ public void play(MediaInfoData mediaInfoData) {
+ FlowPlayControl.getInstance().doPlay();
+ }
+
+ @Override
+ public void pause(MediaInfoData mediaInfoData) {
+ FlowPlayControl.getInstance().doPause();
+ }
+
+ @Override
+ public void stop(MediaInfoData mediaInfoData) {
+ FlowPlayControl.getInstance().doStop();
+ }
+
+ @Override
+ public void pre() {
+ FlowPlayControl.getInstance().doPre();
+ }
+
+ @Override
+ public void next() {
+ FlowPlayControl.getInstance().doNext();
+ }
+
+ @Override
+ public void openApp() {
+ FlowPlayControl.getInstance().startPlayActivity(context);
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/receiver/MediaProcessReceiver.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/receiver/MediaProcessReceiver.java
new file mode 100644
index 0000000000..d6202fe0d9
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/receiver/MediaProcessReceiver.java
@@ -0,0 +1,22 @@
+package com.mogo.module.media.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.mogo.module.media.model.MediaProcessEvent;
+
+public class MediaProcessReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ {
+ if (intent != null) {
+ int curTime = intent.getIntExtra("curTime", -1);
+ MediaProcessEvent event = new MediaProcessEvent();
+ event.process = curTime;
+ // EventBus.getDefault().post(event);
+ }
+ }
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/receiver/MediaSpeechReceiver.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/receiver/MediaSpeechReceiver.java
new file mode 100644
index 0000000000..fd35cc5bb6
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/receiver/MediaSpeechReceiver.java
@@ -0,0 +1,91 @@
+package com.mogo.module.media.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.mogo.module.media.MediaCardViewFragment;
+import com.mogo.module.media.utils.MusicControlBroadCast;
+import com.mogo.utils.ActivityLifecycleManager;
+import com.mogo.utils.UiThreadHandler;
+import com.mogo.utils.logger.Logger;
+import com.tencent.wecarflow.flowoutside.sdk.FlowPlayControl;
+
+import io.reactivex.processors.FlowableProcessor;
+
+/**
+ * 我要听{歌手/歌名}:
+ * 语音通知桌面广播: com.speech.adapter.send 参数:music_model
+ * 桌面通过该action转发给QQ音乐:com.txznet.adapter.send 参数 :music_model
+ *
+ * 播放音乐:
+ * 语音通知桌面广播:com.zhidao.speech.awake.notify 参数:command == com.ileja.music.playapp
+ *
+ * 懒人听书:我要听书、听书 com.zhidao.speech.awake.notify 参数:command:com.zhidao.book.play
+ * 乐听头条:播放新闻、我要听新闻、我要听{类型}新闻、听新闻action:com.zhidao.mediacenter.voiceltnews 参数:category
+ */
+public class MediaSpeechReceiver extends BroadcastReceiver {
+ public static String mCategoryStr = "";
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ {
+ if (intent != null) {
+ String cmdAction = intent.getAction();
+ boolean appActive = ActivityLifecycleManager.getInstance().isAppActive();
+ appActive = MediaCardViewFragment.isMediaResume;
+ Logger.d("MediaSpeechReceiver"," "+cmdAction+" "+appActive);
+ if (cmdAction.equals("com.speech.adapter.send")){
+ //我要听{歌手/歌名}
+ Logger.d("MediaSpeechReceiver"," "+"type qq ");
+ String musicModel = intent.getStringExtra("music_model");
+ FlowPlayControl.getInstance().semanticSearch(context, "launcher", musicModel);
+// if (appActive){
+// MusicControlBroadCast.playSomeBodyMusic(musicModel);
+// MusicControlBroadCast.mediaCenterBroadcast();
+// }else {
+// MusicControlBroadCast.playSomeBodyMusic(musicModel);
+// UiThreadHandler.postDelayed(new Runnable() {
+// @Override
+// public void run() {
+// MusicControlBroadCast.qqOpenQQMusic();
+// }
+// },300);
+// }
+ }else if (cmdAction.equals("com.zhidao.speech.awake.notify")){
+ //播放音乐
+ String musicCmd = intent.getStringExtra("command");
+ Logger.d("MediaSpeechReceiver"," "+"qq book"+musicCmd==null?"":musicCmd);
+ if (musicCmd.equals("com.ileja.music.playapp")){
+ //QQ音乐
+ FlowPlayControl.getInstance().doPlay();
+// if (appActive){
+// MusicControlBroadCast.qqPlayQQMusic();
+// MusicControlBroadCast.mediaCenterBroadcast();
+// }else{
+// MusicControlBroadCast.qqOpenQQMusic();
+// }
+ }else if (musicCmd.equals("com.zhidao.book.play")){
+ //懒人听书
+ if (appActive){
+ MusicControlBroadCast.controlLanRenPlayBack();
+ MusicControlBroadCast.mediaCenterBroadcast();
+ }else{
+ MusicControlBroadCast.openMediaApp(2);
+ }
+ }
+ }else if (cmdAction.equals("com.zhidao.mediacenter.voiceltnews")){
+ //新闻
+ try {
+ String category = intent.getStringExtra("category");
+ Logger.d("MediaSpeechReceiver"," "+"news "+category==null?"":category);
+ mCategoryStr = category;
+ MusicControlBroadCast.getNewsPayInfoState();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/receiver/MediaStateReceiver.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/receiver/MediaStateReceiver.java
new file mode 100644
index 0000000000..6d6bad8f7f
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/receiver/MediaStateReceiver.java
@@ -0,0 +1,135 @@
+package com.mogo.module.media.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
+import android.view.View;
+
+import com.mogo.module.media.constants.LeTingFieldConstants;
+import com.mogo.module.media.constants.QQMusicFieldConstants;
+import com.mogo.module.media.model.LanRenInsertData;
+import com.mogo.module.media.model.MediaInfoData;
+import com.mogo.module.media.model.MediaInfoDataEvent;
+import com.mogo.module.media.utils.StorageManager;
+import com.mogo.module.media.utils.Utils;
+import com.mogo.utils.DateTimeUtils;
+import com.mogo.utils.ThreadPoolService;
+import com.mogo.utils.network.utils.GsonUtil;
+
+public class MediaStateReceiver extends BroadcastReceiver {
+ //action:com.zhidao.action.MEDIA_LRTS
+ //action:com.zhidao.action.MEDIA_LT_NEWS
+ //action:com.qq.music.status.change
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ {
+ MediaInfoData mMediaInfoData = new MediaInfoData();
+ if (intent != null) {
+ int type = intent.getIntExtra("type", -1);
+ int playState = intent.getIntExtra(QQMusicFieldConstants.playState, 0);
+
+ if (type == 1) {//qq音乐
+
+ int maxTime = intent.getIntExtra(QQMusicFieldConstants.maxTime, 0);
+ int curTime = intent.getIntExtra(QQMusicFieldConstants.curTime, 0);
+ String mediaName = intent.getStringExtra(QQMusicFieldConstants.mediaName);
+ String mediaUrl = intent.getStringExtra(QQMusicFieldConstants.mediaUrl);
+ String mediaSinger = intent.getStringExtra(QQMusicFieldConstants.mediaSinger);
+ String mediaImgUrl = intent.getStringExtra(QQMusicFieldConstants.mediaImgUrl);
+ String mediaType = intent.getStringExtra(QQMusicFieldConstants.mediaType);
+ String mediaMid = intent.getStringExtra(QQMusicFieldConstants.mediaMid);
+ int mediaPLayMode = intent.getIntExtra(QQMusicFieldConstants.mediaPlayMode, -1);
+ boolean isLocalMedia = intent.getBooleanExtra(QQMusicFieldConstants.isLocalMedia, false);
+
+ mMediaInfoData.setType(type);
+ mMediaInfoData.setPlayState(playState);
+ mMediaInfoData.setMaxTime(maxTime * 1000);
+ mMediaInfoData.setCurTime(curTime * 1000);
+ mMediaInfoData.setMediaName(mediaName);
+ mMediaInfoData.setMediaUrl(mediaUrl);
+ mMediaInfoData.setMediaId(mediaMid);
+ mMediaInfoData.setMediaImg(mediaImgUrl);
+ mMediaInfoData.setMediaSinger(mediaSinger);
+ mMediaInfoData.setMediaPlayMode(mediaPLayMode);
+ mMediaInfoData.setLocalMedia(isLocalMedia);
+ mMediaInfoData.setMediaType(mediaType);
+
+ } else if (type == 2) {//懒人听书
+ int maxTime = intent.getIntExtra(LeTingFieldConstants.maxTime, 0);
+ int curTime = intent.getIntExtra(LeTingFieldConstants.curTime, 0);
+
+ String mediaName = intent.getStringExtra(LeTingFieldConstants.mediaName);//章节数
+ String bookInfoStr = intent.getStringExtra(LeTingFieldConstants.bookInfo);
+ LanRenInsertData lanRenInsertData = GsonUtil.objectFromJson(bookInfoStr, LanRenInsertData.class);
+
+ String bookName = ""; // 书名 需要从bookinfo里面取
+ String cover = ""; //封面 bookinfo中取
+ String bookid = "";
+
+ try {
+ if (lanRenInsertData != null) {
+ bookName = lanRenInsertData.getName(); // 书名 需要从bookinfo里面取
+ cover = lanRenInsertData.getCover(); //封面 bookinfo中取
+ bookid = lanRenInsertData.getBookId() + "";
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ mMediaInfoData.setType(type);
+ mMediaInfoData.setPlayState(playState);
+ mMediaInfoData.setMaxTime(maxTime);
+ mMediaInfoData.setCurTime(curTime);
+ mMediaInfoData.setMediaName(bookName); //bookName 或者mediaName
+ mMediaInfoData.setMediaSinger(mediaName); //章节数
+ mMediaInfoData.setMediaImg(cover); //书籍封面
+ mMediaInfoData.setMediaId(bookid);//书籍的bookid int
+ mMediaInfoData.setBookInfo(bookInfoStr);
+ mMediaInfoData.setMediaUrl("");
+ mMediaInfoData.setLocalMedia(false);
+ mMediaInfoData.setMediaType("");
+
+ } else if (type == 3) {//乐听头条
+ int maxTime = intent.getIntExtra(LeTingFieldConstants.maxTime, 0);
+ int curTime = intent.getIntExtra(LeTingFieldConstants.curTime, 0);
+ String mediaName = intent.getStringExtra(LeTingFieldConstants.mediaName); //新闻title
+ String artist = intent.getStringExtra(LeTingFieldConstants.artist); //新闻来源,赋值给singer mediaSinger
+ String cover = intent.getStringExtra(LeTingFieldConstants.cover); //封面
+
+ mMediaInfoData.setType(type);
+ mMediaInfoData.setPlayState(playState);
+ mMediaInfoData.setMaxTime(maxTime);
+ mMediaInfoData.setCurTime(curTime);
+ mMediaInfoData.setMediaName(mediaName); //新闻标题
+ mMediaInfoData.setMediaSinger(artist); //新闻来源
+ mMediaInfoData.setMediaImg(cover); //新闻封面
+
+ mMediaInfoData.setMediaId("");//书籍的bookid int
+ mMediaInfoData.setBookInfo("");
+ mMediaInfoData.setMediaUrl("");
+ mMediaInfoData.setLocalMedia(true);
+ mMediaInfoData.setMediaType("");
+ }
+
+ MediaInfoDataEvent event = new MediaInfoDataEvent();
+ event.data = mMediaInfoData;
+ // EventBus.getDefault().post(event);
+
+ /* try {
+ if (mMediaInfoData != null) {
+ ThreadPoolService.execute(new Runnable() {
+ @Override
+ public void run() {
+ StorageManager.setLastListenMediaMusic(GsonUtil.jsonFromObject(mMediaInfoData));
+ }
+ });
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }*/
+ }
+ }
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/BaseUrlManager.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/BaseUrlManager.java
new file mode 100644
index 0000000000..c4a87c9c4f
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/BaseUrlManager.java
@@ -0,0 +1,44 @@
+package com.mogo.module.media.utils;
+
+import com.mogo.module.media.ServiceMediaHandler;
+import com.mogo.module.media.constants.BaseUrlConstants;
+import com.mogo.module.media.model.url.UrlData;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class BaseUrlManager {
+
+ private static final List urlEntityList = new ArrayList<>();
+
+ static {
+ urlEntityList.add( getDevEntity() );
+ urlEntityList.add( getQaEntity() );
+ urlEntityList.add( getReleaseEntity() );
+ urlEntityList.add( getShowEntity() );
+ }
+
+ private static UrlData getShowEntity() {
+ return new UrlData(BaseUrlConstants.SHOW_BASE_URL,BaseUrlConstants.SHOW_BASE_URL);
+ }
+
+ private static UrlData getQaEntity() {
+ return new UrlData(BaseUrlConstants.QA_BASE_URL,BaseUrlConstants.QA_BASE_URL);
+ }
+
+ private static UrlData getDevEntity() {
+ return new UrlData(BaseUrlConstants.DEV_BASE_URL,BaseUrlConstants.DEV_BASE_URL);
+ }
+
+ private static UrlData getReleaseEntity() {
+ return new UrlData(BaseUrlConstants.RELEASE_BASE_URL,BaseUrlConstants.RELEASE_BASE_URL);
+ }
+
+ public static String getDztBaseUrl(){
+ return urlEntityList.get(ServiceMediaHandler.getCurrentEvent() - 1).getDztUrl();
+ }
+
+ public static String getApiBaseUrl(){
+ return urlEntityList.get(ServiceMediaHandler.getCurrentEvent() - 1).getApiUrl();
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/BitmapHelper.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/BitmapHelper.java
new file mode 100644
index 0000000000..89fd0ee6c0
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/BitmapHelper.java
@@ -0,0 +1,982 @@
+package com.mogo.module.media.utils;
+
+import android.annotation.SuppressLint;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.RectF;
+import android.media.ExifInterface;
+import android.media.MediaMetadataRetriever;
+import android.net.Uri;
+import android.opengl.GLES10;
+import android.os.Build;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
+import android.text.TextUtils;
+import android.util.Base64;
+import android.util.TypedValue;
+import android.view.View;
+import com.mogo.module.media.constants.Constants;
+import com.mogo.utils.logger.Logger;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+
+public class BitmapHelper {
+ private static final String TAG = "BitmapHelper";
+
+ /**
+ * 根据原图添加圆角
+ *
+ * @param source
+ * @return
+ */
+ public static Bitmap createRoundCornerImage(Bitmap source, float corner) {
+ final Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ Bitmap target = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(target);
+ RectF rect = new RectF(0, 0, source.getWidth(), source.getHeight());
+ canvas.drawRoundRect(rect, corner, corner, paint);
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
+ canvas.drawBitmap(source, 0, 0, paint);
+ return target;
+ }
+
+ public static byte[] bitmapToBytes(Bitmap bitmap) {
+ if (bitmap == null) {
+ return null;
+ }
+
+ ByteArrayOutputStream bos = null;
+ byte[] result = null;
+
+ try {
+ bos = new ByteArrayOutputStream();
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
+ result = bos.toByteArray();
+ } catch (Exception e) {
+ e.printStackTrace();
+ result = null;
+ } finally {
+ IOUtils.closeSilently(bos);
+ }
+
+ return result;
+ }
+
+ /**
+ * Use quality compression to compress bitmap's size to be smaller than a max size, and convert it to bytes thereafter.
+ * Note that this method will not report compressing ratio related data.
+ *
+ * @param bitmap data source
+ * @param maxSize unit in kb
+ * @return bytes after compressing bitmap to a size smaller than a specific max size.
+ */
+ public static byte[] bitmapToBytes(Bitmap bitmap, int maxSize) {
+ final long start = System.currentTimeMillis();
+
+ if (bitmap == null) {
+ return null;
+ }
+
+ final int maxSizeOfBytes = maxSize * Constants.ONE_KB;
+ ByteArrayOutputStream bos = null;
+ byte[] result = null;
+
+ try {
+ bos = new ByteArrayOutputStream();
+ int quality = 100;
+ int fullSize = 0;
+
+ do {
+ bos.reset();
+ bitmap.compress(Bitmap.CompressFormat.JPEG, quality, bos);
+ if (quality == 100) {
+ fullSize = bos.size();
+ }
+ Logger.i(TAG, "quality<---->size, " + quality + "<---->" + bos.size() / 1024);
+ }
+ while (bos.size() > maxSizeOfBytes && (quality -= (fullSize > Constants.ONE_MB) ? 10 : 5) >= 0);
+
+ result = bos.toByteArray();
+
+ final long end = System.currentTimeMillis();
+ Logger.i(TAG,
+ "bitmap to bytes costs " + (end - start) + "ms, \n" +
+ "bitmap full size is " + (fullSize / 1024) + "kb, \n" +
+ "bitmap final size is " + (bos.size() / 1024) + "kb, \n" +
+ "bitmap quality is " + quality);
+ } catch (Exception e) {
+ e.printStackTrace();
+ result = null;
+ } finally {
+ IOUtils.closeSilently(bos);
+ }
+
+ return result;
+ }
+
+ /**
+ * Use quality compression to compress bitmap to be smaller than a specific max size.
+ *
+ * @param bitmap data source
+ * @param maxSize a specific max size which's unit is kb.
+ * @return a compressed bitmap smaller than the max size.
+ */
+ public static void compressBitmap(Bitmap bitmap, int maxSize, final BitmapHelper.OnCompressListener listener) {
+ if (bitmap == null || bitmap.isRecycled() || listener == null) {
+ return;
+ }
+ listener.onBeforeCompress();
+ ByteArrayOutputStream bos = null;
+ Bitmap target = null;
+
+ try {
+ bos = new ByteArrayOutputStream();
+ int quality = 100;
+ int step = 5;
+ int fullSize = 0;
+
+ do {
+ bos.reset();
+ bitmap.compress(Bitmap.CompressFormat.JPEG, quality, bos);
+ if (quality == 100) {
+ fullSize = bos.size();
+ }
+ if (quality <= 10) {
+ step = 2;
+ }
+ }
+ while (bos.size() / 1024 > maxSize && (quality -= (fullSize > Constants.ONE_MB) ? 10 : step) > 0);
+
+ byte[] result = bos.toByteArray();
+ //target = bytesToBitmap(result);
+ listener.onCompressSuccess(result);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+// target = null;
+ listener.onCompressFailed("压缩失败");
+
+ } finally {
+ IOUtils.closeSilently(bos);
+ }
+
+ return;
+ }
+
+
+ public static Bitmap compressBitmap(Bitmap bitmap, int maxSize) {
+ if (bitmap == null) {
+ return null;
+ }
+
+ ByteArrayOutputStream bos = null;
+ Bitmap target = null;
+
+ try {
+ bos = new ByteArrayOutputStream();
+ int quality = 100;
+
+ do {
+ bos.reset();
+ bitmap.compress(Bitmap.CompressFormat.JPEG, quality, bos);
+ }
+ while (bos.size() / 1024 > maxSize && (quality -= 5) >= 0);
+
+ byte[] result = bos.toByteArray();
+ target = bytesToBitmap(result);
+ } catch (Exception e) {
+ e.printStackTrace();
+ target = null;
+ } finally {
+ IOUtils.closeSilently(bos);
+ }
+
+ return target;
+ }
+
+ public static byte[] compress(File bitmapFile, int maxSize) {
+ if (bitmapFile == null || !bitmapFile.exists()) {
+ return null;
+ }
+
+ Bitmap bitmap = BitmapFactory.decodeFile(bitmapFile.getAbsolutePath());
+ int degree = readPictureDegree( bitmapFile.getAbsolutePath() );
+ if ( degree != 0 ) {
+ Matrix matrix = new Matrix();
+ matrix.reset();
+ matrix.setRotate( degree );
+ bitmap = Bitmap.createBitmap(bitmap,0,0, bitmap.getWidth(), bitmap.getHeight(),matrix, true);
+ }
+
+ ByteArrayOutputStream bos = null;
+ byte[] target = null;
+
+ try {
+ bos = new ByteArrayOutputStream();
+ int quality = 100;
+
+ do {
+ bos.reset();
+ bitmap.compress(Bitmap.CompressFormat.JPEG, quality, bos);
+ }
+ while (bos.size() / 1024 > maxSize && (quality -= 5) >= 0);
+
+ target = bos.toByteArray();
+ } catch (Exception e) {
+ e.printStackTrace();
+ target = null;
+ } finally {
+ IOUtils.closeSilently(bos);
+ }
+
+ return target;
+ }
+
+ /**
+ * Decode an immutable bitmap from the specified byte array.
+ *
+ * @param b byte array of compressed image data
+ * @return an immutable bitmap or null in case of exception.
+ */
+ public static Bitmap bytesToBitmap(byte[] b) {
+ if (b != null && b.length != 0) {
+ return BitmapFactory.decodeByteArray(b, 0, b.length);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Decode an immutable bitmap from the specified byte array.
+ *
+ * @param b byte array of compressed image data
+ * @param options Options that control downsampling and whether the
+ * image should be completely decoded, or just is size returned.
+ * @return an immutable bitmap or null in case of exception.
+ */
+ public static Bitmap bytesToBitmap(byte[] b, BitmapFactory.Options options) {
+ if (b.length != 0) {
+ return BitmapFactory.decodeByteArray(b, 0, b.length, options);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Get max supported image size which will differ from different devices.
+ *
+ * @return max size related to the device.
+ */
+ public static int getMaxSupportedImageSize() {
+ int textureLimit = getMaxTextureSize();
+ if (textureLimit == 0) {
+ return Constants.SIZE_DEFAULT;
+ } else {
+ return Math.min(textureLimit, Constants.SIZE_LIMIT);
+ }
+ }
+
+ public static int getMaxTextureSize2() {
+ // The OpenGL texture size is the maximum size that can be drawn in an ImageView
+ int[] maxSize = new int[1];
+ GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize, 0);
+ return maxSize[0];
+ }
+
+ /**
+ * duplicated from
+ */
+ public static int computeSampleSize(InputStream is, boolean close) {
+ // Just decode image size into options
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+
+ try {
+ BitmapFactory.decodeStream(is, null, options);
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (close) IOUtils.closeSilently(is);
+ }
+
+ int srcWidth = options.outWidth;
+ int srcHeight = options.outHeight;
+
+ srcWidth = srcWidth % 2 == 1 ? srcWidth + 1 : srcWidth;
+ srcHeight = srcHeight % 2 == 1 ? srcHeight + 1 : srcHeight;
+
+ int longSide = Math.max(srcWidth, srcHeight);
+ int shortSide = Math.min(srcWidth, srcHeight);
+
+ float scale = ((float) shortSide / longSide);
+ if (scale <= 1 && scale > 0.5625) {
+ if (longSide < 1664) {
+ return 1;
+ } else if (longSide < 4990) {
+ return 2;
+ } else if (longSide > 4990 && longSide < 10240) {
+ return 4;
+ } else {
+ return longSide / 1280 == 0 ? 1 : longSide / 1280;
+ }
+ } else if (scale <= 0.5625 && scale > 0.5) {
+ return longSide / 1280 == 0 ? 1 : longSide / 1280;
+ } else {
+ return (int) Math.ceil(longSide / (1280.0 / scale));
+ }
+ }
+
+
+ /**
+ * Decode a bitmap's input stream to find a proper inSampleSize according to device's max supported size.
+ *
+ * @param is bitmap's data source
+ * @param close whether to close input stream after work is done.
+ * @return a proper inSampleSize
+ */
+ public static int findProperInSampleSize(InputStream is, boolean close) {
+ // Just decode image size into options
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+
+ try {
+ BitmapFactory.decodeStream(is, null, options);
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (close) IOUtils.closeSilently(is);
+ }
+
+ int maxSize = getMaxSupportedImageSize();
+ int sampleSize = 1;
+
+ while (options.outHeight / sampleSize > maxSize || options.outWidth / sampleSize > maxSize) {
+ sampleSize = sampleSize << 1;
+ }
+
+ Logger.i(TAG, "sample size is " + sampleSize);
+ return sampleSize;
+ }
+
+ /**
+ * Read a picture's degree from a file.
+ *
+ * @param file data source of a picture
+ * @return degrees range from 0 to 360
+ */
+ public static int readPictureDegree(File file) {
+ return readPictureDegree(file.getAbsolutePath());
+ }
+
+ /**
+ * Read a picture's degree from a file, we use {@link ExifInterface} instead of {@link android.media.ExifInterface}
+ * to avoid some unexpected bugs.
+ *
+ * @param filePath file's absolute path which we can read data source of a picture from.
+ * @return degrees range from 0 to 360
+ */
+ public static int readPictureDegree(String filePath) {
+ int degree = 0;
+
+ try {
+ ExifInterface exifInterface = new ExifInterface(filePath);
+ int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
+ switch (orientation) {
+ case ExifInterface.ORIENTATION_ROTATE_90:
+ degree = 90;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_180:
+ degree = 180;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_270:
+ degree = 270;
+ break;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ Logger.i(TAG, "ExifInterface, degree is " + degree);
+
+ return degree;
+ }
+
+ /**
+ * Rotate an bitmap to a specific angle.
+ *
+ * @param angle target angle
+ * @param bitmap data source
+ * @return Returns an immutable bitmap from subset of the source bitmap,
+ * transformed by the optional matrix. The new bitmap may be the
+ * same object as source, or a copy may have been made. It is
+ * initialized with the same density as the original bitmap.
+ *
+ * If the source bitmap is immutable and the requested subset is the
+ * same as the source bitmap itself, then the source bitmap is
+ * returned and no new bitmap is created.
+ */
+ public static Bitmap rotateBitmap(int angle, Bitmap bitmap) {
+ if (bitmap == null) {
+ return null;
+ }
+
+ try {
+ int width = bitmap.getWidth();
+ int height = bitmap.getHeight();
+ Matrix matrix = new Matrix();
+ matrix.preRotate(angle);
+ return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return bitmap;
+ }
+ }
+
+ /**
+ * Get picture's absolute path according to its uri.
+ *
+ * @param context context
+ * @param uri picture's uri
+ * @return absolute path of uri.
+ */
+ public static String getRealPathFromUri(Context context, Uri uri) {
+ int sdkVersion = Build.VERSION.SDK_INT;
+ if (sdkVersion >= 19) {
+ return getRealPathFromUriAboveApi19(context, uri);
+ } else {
+ return getRealPathFromUriBelowAPI19(context, uri);
+ }
+ }
+
+ /**
+ * Create a default {@link BitmapFactory.Options} .
+ * Note this options use rgb_565 and a proper inSampleSize in order to save memory.
+ *
+ * @param is data source of picture
+ * @param close whether to close data source
+ * @return options containing rgb_565 config and a proper inSampleSize.
+ */
+ public static BitmapFactory.Options newDefaultOptions(InputStream is, boolean close) {
+ final BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inPreferredConfig = Bitmap.Config.RGB_565;
+ options.inSampleSize = BitmapHelper.findProperInSampleSize(is, close);
+
+ return options;
+ }
+
+ /**
+ * Save picture to local file.
+ *
+ * @param bitmap data source
+ * @param file local file to store picture.
+ */
+ public static void savePicture(Bitmap bitmap, File file) {
+ final long start = System.currentTimeMillis();
+
+ if (bitmap == null || file == null) {
+ Logger.i(TAG, "保存失败, bitmap or file is null.");
+ return;
+ }
+ if (file.getParentFile() != null && !file.getParentFile().exists()) {
+ file.getParentFile().mkdirs();
+ }
+
+ try {
+ final FileOutputStream fos = new FileOutputStream(file);
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
+ fos.flush();
+ fos.close();
+
+ if (file.exists()) {
+ Logger.i(TAG, "保存成功");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ Logger.i(TAG, "saving picture costs " + (System.currentTimeMillis() - start) + "ms");
+ }
+
+ /**
+ * 适配api19以下(不包括api19),根据uri获取图片的绝对路径
+ *
+ * @param context 上下文对象
+ * @param uri 图片的Uri
+ * @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null
+ */
+ private static String getRealPathFromUriBelowAPI19(Context context, Uri uri) {
+ return getDataColumn(context, uri, null, null);
+ }
+
+ /**
+ * 适配api19及以上,根据uri获取图片的绝对路径
+ *
+ * @param context 上下文对象
+ * @param uri 图片的Uri
+ * @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null
+ */
+ @SuppressLint("NewApi")
+ private static String getRealPathFromUriAboveApi19(Context context, Uri uri) {
+ String filePath = null;
+
+ try {
+ // 如果是document类型的 uri, 则通过document id来进行处理
+ if (DocumentsContract.isDocumentUri(context, uri)) {
+ String documentId = DocumentsContract.getDocumentId(uri);
+ if (isMediaDocument(uri)) {
+ // 使用':'分割
+ String id = documentId.split(":")[1];
+ String selection = MediaStore.Images.Media._ID + "=?";
+ String[] selectionArgs = {id};
+ filePath = getDataColumn(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection, selectionArgs);
+ } else if (isDownloadsDocument(uri)) {
+ Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(documentId));
+ filePath = getDataColumn(context, contentUri, null, null);
+ }
+ } else if ("content".equalsIgnoreCase(uri.getScheme())) {
+ filePath = getDataColumn(context, uri, null, null);
+ } else if ("file".equals(uri.getScheme())) {
+ filePath = uri.getPath();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return filePath;
+ }
+
+ /**
+ * 获取数据库表中的 _data 列,即返回Uri对应的文件路径
+ */
+ private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
+ String path = null;
+ String[] projection = new String[]{MediaStore.Images.Media.DATA};
+ Cursor cursor = null;
+
+ try {
+ cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
+
+ if (cursor != null && cursor.moveToFirst()) {
+ int columnIndex = cursor.getColumnIndexOrThrow(projection[0]);
+ path = cursor.getString(columnIndex);
+ }
+ } catch (Exception e) {
+ if (cursor != null) {
+ cursor.close();
+ cursor = null;
+ }
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ cursor = null;
+ }
+ }
+
+ return path;
+ }
+
+ /**
+ * @param uri the Uri to check
+ * @return Whether the Uri authority is MediaProvider
+ */
+ private static boolean isMediaDocument(Uri uri) {
+ return "com.android.providers.media.documents".equals(uri.getAuthority());
+ }
+
+ /**
+ * @param uri the Uri to check
+ * @return Whether the Uri authority is DownloadsProvider
+ */
+ private static boolean isDownloadsDocument(Uri uri) {
+ return "com.android.providers.downloads.documents".equals(uri.getAuthority());
+ }
+
+ public static int getMaxTextureSize() {
+ try {
+ // Safe minimum default size
+ final int IMAGE_MAX_BITMAP_DIMENSION = Constants.SIZE_DEFAULT;
+
+ // Get EGL Display
+ EGL10 egl = (EGL10) EGLContext.getEGL();
+ EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+
+ // Initialise
+ int[] version = new int[2];
+ egl.eglInitialize(display, version);
+
+ // Query total number of configurations
+ int[] totalConfigurations = new int[1];
+ egl.eglGetConfigs(display, null, 0, totalConfigurations);
+
+ // Query actual list configurations
+ EGLConfig[] configurationsList = new EGLConfig[totalConfigurations[0]];
+ egl.eglGetConfigs(display, configurationsList, totalConfigurations[0], totalConfigurations);
+
+ int[] textureSize = new int[1];
+ int maximumTextureSize = 0;
+
+ // Iterate through all the configurations to located the maximum texture size
+ for (int i = 0; i < totalConfigurations[0]; i++) {
+ // Only need to check for width since opengl textures are always squared
+ egl.eglGetConfigAttrib(display, configurationsList[i], EGL10.EGL_MAX_PBUFFER_WIDTH, textureSize);
+
+ // Keep trackCustomEvent of the maximum texture size
+ if (maximumTextureSize < textureSize[0])
+ maximumTextureSize = textureSize[0];
+ }
+
+ // Release
+ egl.eglTerminate(display);
+
+ // Return largest texture size found, or default
+ return Math.max(maximumTextureSize, IMAGE_MAX_BITMAP_DIMENSION);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return 0;
+ }
+
+ /**
+ * 如需二次计算,请用 {@link #dip2pxF}
+ */
+ private static int dip2px(Context context, float dp) {
+ return (int) (convertUnitToPixel(context, TypedValue.COMPLEX_UNIT_DIP, dp) + 0.5f);
+ }
+
+ /**
+ * dip2px的返回float版
+ *
+ * @see #dip2px
+ */
+ private static float dip2pxF(Context context, float dp) {
+ return convertUnitToPixel(context, TypedValue.COMPLEX_UNIT_DIP, dp);
+ }
+
+ private static float px2dip(Context context, float px) {
+ final float scale = context.getResources().getDisplayMetrics().density;
+ return px / scale;
+ }
+
+ private static int px(Context context, float dp) {
+ return (int) (dip2px(context, dp) + 0.5f);
+ }
+
+ private static float convertUnitToPixel(Context context, int unit, float in) {
+ return TypedValue.applyDimension(unit, in, context.getResources().getDisplayMetrics());
+ }
+
+ private static int getScreenWidth(Context context) {
+ if (context == null) {
+ return 0;
+ }
+ return context.getResources().getDisplayMetrics().widthPixels;
+ }
+
+ private static int getScreenHeight(Context context) {
+ if (context == null) {
+ return 0;
+ }
+ return context.getResources().getDisplayMetrics().heightPixels;
+ }
+
+ public static String bitmapToBase64(Bitmap bitmap) {
+ String result = null;
+ try {
+ if (bitmap != null) {
+ result = Base64.encodeToString(bitmapToBytes(bitmap), Base64.DEFAULT);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ public static String bitmapArrayToBase64(byte[] data) {
+ String result = null;
+ try {
+ if (data != null) {
+ result = Base64.encodeToString(data, Base64.DEFAULT);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ public static Bitmap base64ToBitmap(String base64Data) {
+ byte[] bytes = Base64.decode(base64Data, Base64.DEFAULT);
+ return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
+ }
+
+ /**
+ * 在系统返回的intent中获取图片信息,并转化为uri
+ *
+ * @param data
+ * @return
+ */
+ public static Uri convertUri(Context context, Intent data) {
+ if (data == null || data.getData() == null) {
+ return null;
+ }
+ Uri localUri = data.getData();
+ String scheme = localUri.getScheme();
+ String imagePath = "";
+ if ("content".equals(scheme)) {
+ String[] filePathColumns = {MediaStore.Images.Media.DATA};
+ Cursor c = context.getContentResolver().query(localUri, filePathColumns, null, null, null);
+ if (c != null) {
+ try {
+ c.moveToFirst();
+ int columnIndex = c.getColumnIndex(filePathColumns[0]);
+ imagePath = c.getString(columnIndex);
+ c.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ c.close();
+ imagePath = "";
+ }
+ }
+ } else if ("file".equals(scheme)) {//小米4选择云相册中的图片是根据此方法获得路径
+ imagePath = localUri.getPath();
+ }
+ if (TextUtils.isEmpty(imagePath)) {
+ return localUri;
+ }
+ Uri uri = Uri.fromFile(new File(imagePath));
+ return uri != null ? uri : localUri;
+ }
+
+ public static Bitmap colorToBitmap(Context context,int colorResId) {// drawable 转换成bitmap
+ Bitmap.Config config = Bitmap.Config.ARGB_8888;// 取drawable的颜色格式
+ Bitmap bitmap = Bitmap.createBitmap(1, 1, config);// 建立对应bitmap
+ bitmap.eraseColor(context.getResources().getColor(colorResId));
+ return bitmap;
+ }
+
+ public static String getAlphaHexValue(float alpha) {
+ String color = Integer.toHexString((int) alpha * 255);
+ return TextUtils.isEmpty(color) ? color : color.toUpperCase();
+ }
+
+ /**
+ * 抓取本地视频缩略图(操作可能耗时,尽量异步进行)
+ *
+ * @param filePath
+ * @return
+ */
+ public static Bitmap getVideoThumbnail(String filePath) {
+ Bitmap b = null;
+ MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+ try {
+ retriever.setDataSource(filePath);
+ b = retriever.getFrameAtTime();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+
+ } finally {
+ try {
+ retriever.release();
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ }
+ }
+ return b;
+ }
+
+ public static BitmapFactory.Options getBitmapOptions(String path) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeFile(path, options);
+ return options;
+ }
+
+ public static int calculateInSampleSize(BitmapFactory.Options options, int targetWidth, int targetHeight) {
+ int height = options.outHeight;
+ int width = options.outWidth;
+ int size = 1;
+ if (height > targetHeight || width > targetWidth) {
+ int scaleHeight = Math.round((float) height / (float) targetHeight);
+ int scaleWidth = Math.round((float) width / (float) targetWidth);
+ size = scaleHeight > scaleWidth ? scaleHeight : scaleWidth;
+ }
+
+ return size;
+ }
+
+ public static Bitmap decodeScaleImage(String path, int targetWidth, int targetHeight) {
+ BitmapFactory.Options options = getBitmapOptions(path);
+ options.inSampleSize = calculateInSampleSize(options, targetWidth, targetHeight);
+ options.inJustDecodeBounds = false;
+ Bitmap bitmap = BitmapFactory.decodeFile(path, options);
+ int degree = readPictureDegree(path);
+ Bitmap rotateBitmap;
+ if (bitmap != null && degree != 0) {
+ rotateBitmap = rotateBitmap(degree, bitmap);
+ bitmap.recycle();
+ return rotateBitmap;
+ } else {
+ return bitmap;
+ }
+ }
+
+ public static Bitmap getImage(String fileName) {
+
+ FileInputStream stream = null;
+ try {
+ stream = new FileInputStream(fileName);
+ FileDescriptor fd = stream.getFD();
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inSampleSize = 1;
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeFileDescriptor(fd, null, options);
+ if (options.mCancel || options.outWidth == -1
+ || options.outHeight == -1) {
+ return null;
+ }
+
+ // 1.换算合适的图片缩放值,以减少对JVM太多的内存请求。
+ options.inSampleSize = calculateInSampleSize(options, options.outWidth,
+ options.outHeight);
+ options.inJustDecodeBounds = false;
+
+ options.inDither = false;
+ options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+
+ // 2. inPurgeable 设定为 true,可以让java系统, 在内存不足时先行回收部分的内存
+ options.inPurgeable = true;
+ // 与inPurgeable 一起使用
+ options.inInputShareable = true;
+
+ try {
+ // 4. inNativeAlloc 属性设置为true,可以不把使用的内存算到VM里
+ BitmapFactory.Options.class.getField("inNativeAlloc")
+ .setBoolean(options, true);
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ }
+ // 5. 使用decodeStream 解码,则利用NDK层中,利用nativeDecodeAsset()
+ // 进行解码,不用CreateBitmap
+ return BitmapFactory.decodeStream(stream, null, options);
+
+ } catch (IOException ex) {
+ Logger.e(TAG, "", ex);
+ } catch (OutOfMemoryError oom) {
+ Logger.e(TAG, "Unable to decode file " + fileName
+ + ". OutOfMemoryError.", oom);
+ } finally {
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ return null;
+ }
+
+
+ public static Bitmap convertViewToBitmap(View view) {
+ view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
+ view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
+
+ Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(bitmap);
+ c.drawColor(Color.WHITE);
+ view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
+ view.draw(c);
+ return bitmap;
+ }
+
+ public static boolean checkBitmapIsLegal(Bitmap bitmap) {
+ return bitmap != null && bitmap.getByteCount() > 0 && bitmap.getWidth() > 0 && bitmap.getHeight() > 0;
+ }
+
+ public static File saveToTempFile(Context context,byte[] bytes) {
+ if (bytes == null || bytes.length <= 0) {
+ return null;
+ }
+ String compressPath = FileUtils.getCachePath(context);
+ String md5 = Md5Utils.hexdigest(bytes);
+ File tempFile = new File(compressPath, md5 + ".temp");
+
+ if (!tempFile.exists()) {
+ tempFile.getParentFile().mkdirs();
+ } else if (tempFile.length() > 0) {
+ return tempFile;
+ }
+ FileOutputStream fileOutputStream = null;
+ try {
+ fileOutputStream = new FileOutputStream(tempFile);
+ fileOutputStream.write(bytes);
+ fileOutputStream.flush();
+ fileOutputStream.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return tempFile;
+ }
+
+ /**
+ * convert px to its equivalent sp
+ *
+ * 将px转换为sp
+ */
+ private static int px2sp(Context context, float pxValue) {
+ final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
+ return (int) (pxValue / fontScale + 0.5f);
+ }
+
+
+ /**
+ * convert sp to its equivalent px
+ *
+ * 将sp转换为px
+ */
+ public static int sp2px(Context context, float spValue) {
+ final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
+ return (int) (spValue * fontScale + 0.5f);
+ }
+
+ public interface OnCompressListener {
+
+ void onCompressSuccess( byte[] data );
+
+ void onCompressFailed( String msg );
+
+ void onBeforeCompress();
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/BlurImageUtils.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/BlurImageUtils.java
new file mode 100644
index 0000000000..8463ae5299
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/BlurImageUtils.java
@@ -0,0 +1,33 @@
+package com.mogo.module.media.utils;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicBlur;
+
+public class BlurImageUtils {
+ public static Bitmap rsBlur(Context context, Bitmap source, int radius){
+
+ Bitmap inputBmp = source;
+ RenderScript renderScript = RenderScript.create(context);
+
+ // Allocate memory for Renderscript to work with
+ final Allocation input = Allocation.createFromBitmap(renderScript,inputBmp);
+ final Allocation output = Allocation.createTyped(renderScript,input.getType());
+ // Load up an instance of the specific script that we want to use.
+ ScriptIntrinsicBlur scriptIntrinsicBlur = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript));
+ scriptIntrinsicBlur.setInput(input);
+ // Set the blur radius
+ scriptIntrinsicBlur.setRadius(radius);
+ // Start the ScriptIntrinisicBlur
+ scriptIntrinsicBlur.forEach(output);
+ // Copy the output to the blurred bitmap
+ output.copyTo(inputBmp);
+ renderScript.destroy();
+
+ return inputBmp;
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/FastBlurUtil.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/FastBlurUtil.java
new file mode 100644
index 0000000000..5de68b6240
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/FastBlurUtil.java
@@ -0,0 +1,330 @@
+package com.mogo.module.media.utils;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+
+/**
+ * Created by jay on 11/7/15.
+ */
+public class FastBlurUtil {
+ /**
+ * 根据imagepath获取bitmap
+ */
+ /**
+ * 得到本地或者网络上的bitmap url - 网络或者本地图片的绝对路径,比如:
+ * A.网络路径: url="http://blog.foreverlove.us/girl2.png" ;
+ * B.本地路径:url="file://mnt/sdcard/photo/image.png";
+ * C.支持的图片格式 ,png, jpg,bmp,gif等等
+ * @param url
+ * @return
+ */
+ public static int IO_BUFFER_SIZE = 2 * 1024;
+
+ public static Bitmap GetUrlBitmap(String url, int scaleRatio) {
+
+ int blurRadius = 8;//通常设置为8就行。
+ if (scaleRatio <= 0) {
+ scaleRatio = 10;
+ }
+
+
+ Bitmap originBitmap = null;
+ InputStream in = null;
+ BufferedOutputStream out = null;
+ try {
+ in = new BufferedInputStream(new URL(url).openStream(), IO_BUFFER_SIZE);
+ final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
+ out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
+ copy(in, out);
+ out.flush();
+ byte[] data = dataStream.toByteArray();
+ originBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
+
+ Bitmap scaledBitmap = Bitmap.createScaledBitmap(originBitmap,
+ originBitmap.getWidth() / scaleRatio,
+ originBitmap.getHeight() / scaleRatio,
+ false);
+ Bitmap blurBitmap = doBlur(scaledBitmap, blurRadius, true);
+ return blurBitmap;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private static void copy(InputStream in, OutputStream out)
+ throws IOException {
+ byte[] b = new byte[IO_BUFFER_SIZE];
+ int read;
+ while ((read = in.read(b)) != -1) {
+ out.write(b, 0, read);
+ }
+ }
+
+
+ // 把本地图片毛玻璃化
+ public static Bitmap toBlur(Bitmap originBitmap, int scaleRatio) {
+ // int scaleRatio = 10;
+ // 增大scaleRatio缩放比,使用一样更小的bitmap去虚化可以到更好的得模糊效果,而且有利于占用内存的减小;
+ int blurRadius = 6;//通常设置为8就行。
+ //增大blurRadius,可以得到更高程度的虚化,不过会导致CPU更加intensive
+
+ /* 其中前三个参数很明显,其中宽高我们可以选择为原图尺寸的1/10;
+ 第四个filter是指缩放的效果,filter为true则会得到一个边缘平滑的bitmap,
+ 反之,则会得到边缘锯齿、pixelrelated的bitmap。
+ 这里我们要对缩放的图片进行虚化,所以无所谓边缘效果,filter=false。*/
+ if (scaleRatio <= 0) {
+ scaleRatio = 10;
+ }
+ Bitmap scaledBitmap = Bitmap.createScaledBitmap(originBitmap,
+ originBitmap.getWidth() / scaleRatio,
+ originBitmap.getHeight() / scaleRatio,
+ false);
+ Bitmap blurBitmap = doBlur(scaledBitmap, blurRadius, true);
+ return blurBitmap;
+ }
+
+ public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) {
+
+ // Stack Blur v1.0 from
+ // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
+ //
+ // Java Author: Mario Klingemann
+ // http://incubator.quasimondo.com
+ // created Feburary 29, 2004
+ // Android port : Yahel Bouaziz
+ // http://www.kayenko.com
+ // ported april 5th, 2012
+
+ // This is a compromise between Gaussian Blur and Box blur
+ // It creates much better looking blurs than Box Blur, but is
+ // 7x faster than my Gaussian Blur implementation.
+ //
+ // I called it Stack Blur because this describes best how this
+ // filter works internally: it creates a kind of moving stack
+ // of colors whilst scanning through the image. Thereby it
+ // just has to add one new block of color to the right side
+ // of the stack and remove the leftmost color. The remaining
+ // colors on the topmost layer of the stack are either added on
+ // or reduced by one, depending on if they are on the right or
+ // on the left side of the stack.
+ //
+ // If you are using this algorithm in your code please add
+ // the following line:
+ //
+ // Stack Blur Algorithm by Mario Klingemann
+
+ Bitmap bitmap;
+ if (canReuseInBitmap) {
+ bitmap = sentBitmap;
+ } else {
+ bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
+ }
+
+ if (radius < 1) {
+ return (null);
+ }
+
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+
+ int[] pix = new int[w * h];
+ bitmap.getPixels(pix, 0, w, 0, 0, w, h);
+
+ int wm = w - 1;
+ int hm = h - 1;
+ int wh = w * h;
+ int div = radius + radius + 1;
+
+ int r[] = new int[wh];
+ int g[] = new int[wh];
+ int b[] = new int[wh];
+ int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
+ int vmin[] = new int[Math.max(w, h)];
+
+ int divsum = (div + 1) >> 1;
+ divsum *= divsum;
+ int dv[] = new int[256 * divsum];
+ for (i = 0; i < 256 * divsum; i++) {
+ dv[i] = (i / divsum);
+ }
+
+ yw = yi = 0;
+
+ int[][] stack = new int[div][3];
+ int stackpointer;
+ int stackstart;
+ int[] sir;
+ int rbs;
+ int r1 = radius + 1;
+ int routsum, goutsum, boutsum;
+ int rinsum, ginsum, binsum;
+
+ for (y = 0; y < h; y++) {
+ rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
+ for (i = -radius; i <= radius; i++) {
+ p = pix[yi + Math.min(wm, Math.max(i, 0))];
+ sir = stack[i + radius];
+ sir[0] = (p & 0xff0000) >> 16;
+ sir[1] = (p & 0x00ff00) >> 8;
+ sir[2] = (p & 0x0000ff);
+ rbs = r1 - Math.abs(i);
+ rsum += sir[0] * rbs;
+ gsum += sir[1] * rbs;
+ bsum += sir[2] * rbs;
+ if (i > 0) {
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+ } else {
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+ }
+ }
+ stackpointer = radius;
+
+ for (x = 0; x < w; x++) {
+
+ r[yi] = dv[rsum];
+ g[yi] = dv[gsum];
+ b[yi] = dv[bsum];
+
+ rsum -= routsum;
+ gsum -= goutsum;
+ bsum -= boutsum;
+
+ stackstart = stackpointer - radius + div;
+ sir = stack[stackstart % div];
+
+ routsum -= sir[0];
+ goutsum -= sir[1];
+ boutsum -= sir[2];
+
+ if (y == 0) {
+ vmin[x] = Math.min(x + radius + 1, wm);
+ }
+ p = pix[yw + vmin[x]];
+
+ sir[0] = (p & 0xff0000) >> 16;
+ sir[1] = (p & 0x00ff00) >> 8;
+ sir[2] = (p & 0x0000ff);
+
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+
+ rsum += rinsum;
+ gsum += ginsum;
+ bsum += binsum;
+
+ stackpointer = (stackpointer + 1) % div;
+ sir = stack[(stackpointer) % div];
+
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+
+ rinsum -= sir[0];
+ ginsum -= sir[1];
+ binsum -= sir[2];
+
+ yi++;
+ }
+ yw += w;
+ }
+ for (x = 0; x < w; x++) {
+ rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
+ yp = -radius * w;
+ for (i = -radius; i <= radius; i++) {
+ yi = Math.max(0, yp) + x;
+
+ sir = stack[i + radius];
+
+ sir[0] = r[yi];
+ sir[1] = g[yi];
+ sir[2] = b[yi];
+
+ rbs = r1 - Math.abs(i);
+
+ rsum += r[yi] * rbs;
+ gsum += g[yi] * rbs;
+ bsum += b[yi] * rbs;
+
+ if (i > 0) {
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+ } else {
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+ }
+
+ if (i < hm) {
+ yp += w;
+ }
+ }
+ yi = x;
+ stackpointer = radius;
+ for (y = 0; y < h; y++) {
+ // Preserve alpha channel: ( 0xff000000 & pix[yi] )
+ pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
+
+ rsum -= routsum;
+ gsum -= goutsum;
+ bsum -= boutsum;
+
+ stackstart = stackpointer - radius + div;
+ sir = stack[stackstart % div];
+
+ routsum -= sir[0];
+ goutsum -= sir[1];
+ boutsum -= sir[2];
+
+ if (x == 0) {
+ vmin[y] = Math.min(y + r1, hm) * w;
+ }
+ p = x + vmin[y];
+
+ sir[0] = r[p];
+ sir[1] = g[p];
+ sir[2] = b[p];
+
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+
+ rsum += rinsum;
+ gsum += ginsum;
+ bsum += binsum;
+
+ stackpointer = (stackpointer + 1) % div;
+ sir = stack[stackpointer];
+
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+
+ rinsum -= sir[0];
+ ginsum -= sir[1];
+ binsum -= sir[2];
+
+ yi += w;
+ }
+ }
+
+ bitmap.setPixels(pix, 0, w, 0, 0, w, h);
+
+ return (bitmap);
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/FileUtils.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/FileUtils.java
new file mode 100644
index 0000000000..8a06848283
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/FileUtils.java
@@ -0,0 +1,474 @@
+package com.mogo.module.media.utils;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.text.TextUtils;
+import android.util.Base64;
+
+import androidx.annotation.IntRange;
+import androidx.core.content.FileProvider;
+
+import com.mogo.module.media.constants.Constants;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.text.DecimalFormat;
+import java.util.Arrays;
+
+public class FileUtils {
+ private static final String[] IMAGE_SUPPORT_EXTS = {"png", "jpg", "jpeg", "bmp"};
+ private static final String[] VIDEO_SUPPORT_EXTS = {"mp4"};
+
+ public static String fileToBase64(File file) {
+ String base64 = null;
+ InputStream in = null;
+ try {
+ in = new FileInputStream(file);
+ byte[] bytes = new byte[in.available()];
+ int length = in.read(bytes);
+ base64 = Base64.encodeToString(bytes, 0, length, Base64.DEFAULT);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ IOUtils.closeSilently(in);
+ }
+ return base64;
+ }
+
+
+ /**
+ * 创建一个用于拍照图片输出路径的Uri (FileProvider)
+ */
+ public static Uri getUriForFile(Context context, File file) {
+ return FileProvider.getUriForFile(context, getFileProviderName(context), file);
+ }
+
+ public static String getFileProviderName(Context context) {
+ return context.getPackageName() + ".fileprovider";
+ }
+
+ /**
+ * 把Uri 解析出文件绝对路径
+ */
+ public static String parseOwnUri(Context context, Uri uri) {
+ if (uri == null || uri.getPath() == null) return null;
+ String path;
+ if (TextUtils.equals(uri.getAuthority(), getFileProviderName(context))) {
+ path = new File(uri.getPath()).getAbsolutePath();
+ } else {
+ path = uri.getPath();
+ }
+ return path;
+ }
+
+ public static void copy(final String from, final String to, final FileCopyListener listener) {
+
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+
+ File file = null;
+ try {
+ file = new File(from);
+ } catch (Exception e) {
+ if (listener != null) {
+ listener.onFail(e);
+ }
+ return;
+ }
+ if (!file.isFile()) {
+ if (listener != null) {
+ listener.onFail(new Exception(String.format("%s is not a file", from)));
+ return;
+ }
+ }
+ if (!file.exists()) {
+ if (listener != null) {
+ listener.onFail(new FileNotFoundException(String.format("%s is not exists.", from)));
+ return;
+ }
+ }
+
+ if (listener != null) {
+ listener.onStart();
+ }
+
+ long fileSize = file.length();
+ long process = 0;
+
+ try {
+ FileInputStream fis = new FileInputStream(file);
+
+ byte[] buff = new byte[1024];
+ int rc = 0;
+
+ File toFile = new File(to);
+ if (!toFile.getParentFile().exists()) {
+ toFile.getParentFile().mkdirs();
+ }
+
+ FileOutputStream fos = new FileOutputStream(toFile);
+
+ while ((rc = fis.read(buff, 0, 1024)) > 0) {
+ process += rc;
+ fos.write(buff, 0, rc);
+ if (listener != null) {
+ listener.onProcess(((int) (((float) process) * 100 / fileSize)));
+ }
+ }
+
+ fos.flush();
+ fos.close();
+ fis.close();
+
+ } catch (Exception e) {
+ if (listener != null) {
+ listener.onFail(e);
+ return;
+ }
+ }
+
+ if (listener != null) {
+ listener.onFinish(to);
+ }
+ }
+ }).start();
+ }
+
+ public static void copy(final InputStream is, final String to, final FileCopyListener listener) {
+
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+
+ if (listener != null) {
+ listener.onStart();
+ }
+
+ try {
+
+ long fileSize = is.available();
+ long process = 0;
+
+ byte[] buff = new byte[1024];
+ int rc = 0;
+
+ File toFile = new File(to);
+ if (!toFile.getParentFile().exists()) {
+ toFile.getParentFile().mkdirs();
+ }
+
+ FileOutputStream fos = new FileOutputStream(toFile);
+
+ while ((rc = is.read(buff, 0, 1024)) > 0) {
+ process += rc;
+ fos.write(buff, 0, rc);
+ if (listener != null) {
+ listener.onProcess(((int) (((float) process) * 100 / fileSize)));
+ }
+ }
+
+ fos.flush();
+ fos.close();
+ is.close();
+
+ } catch (Exception e) {
+ if (listener != null) {
+ listener.onFail(e);
+ return;
+ }
+ }
+
+ if (listener != null) {
+ listener.onFinish(to);
+ }
+ }
+ }).start();
+ }
+
+ public interface FileCopyListener {
+ void onStart();
+
+ void onFail(Exception e);
+
+ void onProcess(@IntRange(from = 0, to = 100) int process);
+
+ void onFinish(String toPath);
+ }
+
+ public static void createPath(String file) {
+ File f = new File(file);
+ if (f.exists()) {
+ return;
+ }
+ if (!f.getParentFile().exists()) {
+ f.getParentFile().mkdirs();
+ }
+ }
+
+ public static byte[] read(String file) {
+
+ File f = new File(file);
+ if (!f.exists() || f.length() == 0) {
+ return null;
+ }
+
+ try {
+ FileInputStream fis = new FileInputStream(f);
+ byte[] buffer = new byte[((int) f.length())];
+ fis.read(buffer);
+ IOUtils.closeSilently(fis);
+ return buffer;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public static String toBase64(byte[] buffer) {
+ if (buffer == null || buffer.length == 0) {
+ return null;
+ }
+ try {
+ return Base64.encodeToString(buffer, Base64.DEFAULT);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * 获取不带扩展名的文件名
+ *
+ * @param filePath
+ * @return
+ */
+ public static String getFileNameNoEx(String filePath) {
+ try {
+ if ((filePath != null) && (filePath.length() > 0)) {
+ int index = filePath.lastIndexOf("/") + 1;
+ int dot = filePath.lastIndexOf(".");
+ if ((dot > -1) && (dot < (filePath.length()))) {
+ if (index != -1 && index < filePath.length()) {
+ return filePath.substring(index, dot);
+ }
+ }
+ }
+ return filePath;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return filePath;
+ }
+
+ public static boolean isVideo(String path) {
+ String extName = FileUtils.getExtensionName(path);
+ if (TextUtils.isEmpty(extName)) {
+ return false;
+ }
+ return Arrays.asList(VIDEO_SUPPORT_EXTS).contains(extName.toLowerCase());
+ }
+
+ public static boolean isImage(String filePath) {
+ String extName = FileUtils.getExtensionName(filePath);
+ if (TextUtils.isEmpty(extName)) {
+ return false;
+ }
+ return Arrays.asList(IMAGE_SUPPORT_EXTS).contains(extName.toLowerCase());
+ }
+
+ public static boolean isExist(String path) {
+ if (TextUtils.isEmpty(path)) {
+ return false;
+ }
+ try {
+ File file = new File(path);
+ return file.exists() && file.isFile() && getFileSize(path) != 0;
+ } catch (Exception e) {
+ return false;
+ }
+
+ }
+
+ public static boolean isExist(File file) {
+ if (file == null) {
+ return false;
+ }
+ try {
+ return file.exists();
+ } catch (Exception e) {
+ return false;
+ }
+
+ }
+
+ public static boolean deleteFile(String path) {
+ try {
+ if (TextUtils.isEmpty(path)) {
+ return false;
+ }
+ File file = new File(path);
+ if (file.exists()) {
+ return file.delete();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ public static long getFileSize(String path) {
+ if (TextUtils.isEmpty(path)) {
+ return 0;
+ }
+ try {
+ return new File(path).length();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+
+ public static Uri getFileProviderUri(Context context, File file) {
+ Uri data;
+ // 判断版本大于等于7.0
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ data = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", file);
+ } else {
+ data = Uri.fromFile(file);
+ }
+ return data;
+ }
+
+ public static void saveBitmapToCache(Bitmap bitmap, String path, OnBitmapToLocalListener onBitmapToLocalListener) {
+ File file = new File(path);
+ if (!file.exists()) {
+ file.getParentFile().mkdirs();
+ }
+ FileOutputStream fileOutputStream = null;
+ try {
+ fileOutputStream = new FileOutputStream(path);
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
+ fileOutputStream.close();
+ if (onBitmapToLocalListener != null) {
+ onBitmapToLocalListener.saveSuccess(path);
+ }
+ } catch (Exception e) {
+ if (onBitmapToLocalListener != null) {
+ onBitmapToLocalListener.saveFailed();
+ }
+ e.printStackTrace();
+ }
+ }
+
+ public static File getDiskCacheDir(Context context, String uniqueName) {
+ String cachePath;
+ if (Environment.MEDIA_MOUNTED.equals(Environment
+ .getExternalStorageState()) && context.getExternalCacheDir() != null) {
+ cachePath = context.getExternalCacheDir().getPath();
+ } else {
+ cachePath = context.getCacheDir().getPath();
+ }
+ return new File(cachePath + File.separator + uniqueName);
+ }
+
+ public static String getCachePath(Context context) {
+ File targetFile = getDiskCacheDir(context, Constants.IMAGE_COMPRESS_PATH);
+ if (!targetFile.exists()) {
+ targetFile.mkdirs();
+ }
+ return targetFile.getAbsolutePath();
+ }
+
+ public static String formatFileSize(long size) {
+ DecimalFormat formatter = new DecimalFormat("####.00");
+ if (size < 1024) {
+ return size + "B";
+ } else if (size < 1024 * 1024L) {
+ float kbSize = size / 1024f;
+ return formatter.format(kbSize) + "KB";
+ } else if (size < 1024 * 1024 * 1024L) {
+ float mbSize = size / 1024f / 1024f;
+ return formatter.format(mbSize) + "MB";
+ } else if (size < 1024 * 1024 * 1024 * 1024L) {
+ float gbSize = size / 1024f / 1024f / 1024f;
+ return formatter.format(gbSize) + "GB";
+ } else {
+ return "0KB";
+ }
+ }
+
+ public static String getFileWithEx(String filePath) {
+ if (TextUtils.isEmpty(filePath)) {
+ return "";
+ }
+ int index = filePath.lastIndexOf("/");
+ try {
+ return filePath.substring(index + 1, filePath.length());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public static void writeToFile(String content, String logPath) {
+
+ if (TextUtils.isEmpty(logPath)) {
+ return;
+ }
+
+ String fileName = logPath + "/location.txt";//log日志名,使用时间命名,保证不重复
+ //如果父路径不存在
+ File file = new File(logPath);
+ if (!file.exists()) {
+ file.mkdirs();//创建父路径
+ }
+
+ FileOutputStream fos;//FileOutputStream会自动调用底层的close()方法,不用关闭
+ BufferedWriter bw = null;
+ try {
+ fos = new FileOutputStream(fileName, true);//这里的第二个参数代表追加还是覆盖,true为追加,flase为覆盖
+ bw = new BufferedWriter(new OutputStreamWriter(fos));
+ bw.write(content + "\n");
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (bw != null) {
+ bw.close();//关闭缓冲流
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ /**
+ * 获取文件扩展名
+ *
+ * @param filePath
+ * @return
+ */
+ public static String getExtensionName(String filePath) {
+ if ((filePath != null) && (filePath.length() > 0)) {
+ int dot = filePath.lastIndexOf('.');
+ if ((dot > -1) && (dot < (filePath.length() - 1))) {
+ return filePath.substring(dot + 1);
+ }
+ }
+ return filePath;
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/IOUtils.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/IOUtils.java
new file mode 100644
index 0000000000..4d7a17a7c2
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/IOUtils.java
@@ -0,0 +1,48 @@
+package com.mogo.module.media.utils;
+
+import androidx.annotation.Nullable;
+
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.InputStream;
+
+public class IOUtils {
+
+ public static byte[] inputToBytes(InputStream is) {
+ if(is == null){
+ return null;
+ }
+
+ ByteArrayOutputStream bos = null;
+ byte[] result = null;
+
+ try{
+ bos = new ByteArrayOutputStream();
+ byte[] buff = new byte[100];
+ int rc = 0;
+ while ((rc = is.read(buff, 0, 100)) > 0) {
+ bos.write(buff, 0, rc);
+ }
+
+ result = bos.toByteArray();
+ }catch (Exception e){
+ e.printStackTrace();
+ result = null;
+ }finally {
+ closeSilently(bos);
+ }
+
+ return result;
+ }
+
+ public static void closeSilently(@Nullable Closeable c) {
+ if (c == null) return;
+ try {
+ c.close();
+ c = null;
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/Md5Utils.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/Md5Utils.java
new file mode 100644
index 0000000000..9bfe577832
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/Md5Utils.java
@@ -0,0 +1,44 @@
+package com.mogo.module.media.utils;
+
+import java.security.MessageDigest;
+
+public class Md5Utils {
+
+ private static final char[] hexDigits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+ public static String hexdigest(String string) {
+ String s = null;
+
+ try {
+ s = hexdigest(string.getBytes());
+ } catch (Exception var3) {
+ var3.printStackTrace();
+ }
+
+ return s;
+ }
+
+ public static String hexdigest(byte[] bytes) {
+ String s = null;
+
+ try {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ md.update(bytes);
+ byte[] tmp = md.digest();
+ char[] str = new char[32];
+ int k = 0;
+
+ for(int i = 0; i < 16; ++i) {
+ byte byte0 = tmp[i];
+ str[k++] = hexDigits[byte0 >>> 4 & 15];
+ str[k++] = hexDigits[byte0 & 15];
+ }
+
+ s = new String(str);
+ } catch (Exception var8) {
+ var8.printStackTrace();
+ }
+
+ return s;
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/MediaAnalyticsUtils.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/MediaAnalyticsUtils.java
new file mode 100644
index 0000000000..25d6da3336
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/MediaAnalyticsUtils.java
@@ -0,0 +1,16 @@
+package com.mogo.module.media.utils;
+
+import com.mogo.module.media.ServiceMediaHandler;
+import com.mogo.utils.logger.Logger;
+
+import java.util.HashMap;
+
+public class MediaAnalyticsUtils {
+ /**
+ * 统一管理打点
+ */
+ public static void track(String id, HashMap map){
+ Logger.d("MediaAnalyticsUtils","addLogger "+id);
+ ServiceMediaHandler.getMogoAnalytis().track(id,map);
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/MusicControlBroadCast.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/MusicControlBroadCast.java
new file mode 100644
index 0000000000..6ec22f102e
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/MusicControlBroadCast.java
@@ -0,0 +1,515 @@
+package com.mogo.module.media.utils;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.text.TextUtils;
+
+import com.mogo.commons.AbsMogoApplication;
+import com.mogo.module.common.entity.MarkerShareMusic;
+import com.mogo.module.media.ServiceMediaHandler;
+import com.mogo.module.media.model.LanRenInsertData;
+import com.mogo.module.media.model.MediaInfoData;
+import com.mogo.module.media.model.QQMediaListData;
+import com.mogo.utils.UiThreadHandler;
+import com.mogo.utils.logger.Logger;
+import com.mogo.utils.network.utils.GsonUtil;
+
+import java.util.ArrayList;
+
+public class MusicControlBroadCast {
+
+ public static final String TAG = "MusicControlBroadCast";
+ public static boolean OPEN = false;
+ /**
+ *
+ * @param actionValue
+ */
+ public static void sendQQMusicControl(String actionValue) {
+ if (OPEN && ServiceMediaHandler.getMogoNavi().isNaviing())return;
+ Intent intent = new Intent("com.txznet.adapter.send");
+ intent.putExtra("action", actionValue);
+ intent.putExtra("source", "com.mogo.launcher");
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+ Logger.d(TAG,"sendQQMusicControl "+actionValue);
+ }
+
+ /**
+ * 打开qq音乐
+ */
+ public static void qqOpenQQMusic() {
+ sendQQMusicControl("music_open");
+ }
+
+ /**
+ * 关闭qq音乐
+ */
+ public static void qqCloseQQMusic() {
+ sendQQMusicControl("music_exit");
+ }
+
+ /**
+ * 暂停播放音乐
+ */
+ public static void qqPlayPauseQQMusic() {
+ sendQQMusicControl("music_play_or_pause");
+ }
+
+ /**
+ * 播放音乐
+ */
+
+ public static void qqPlayQQMusic() {
+ sendQQMusicControl("music_play");
+ }
+ /**
+ * 暂停音乐
+ */
+ public static void qqPauseQQMusic() {
+ sendQQMusicControl("music_pause");
+ }
+
+ /**
+ * 上一首音乐
+ */
+ public static void qqPreQQMusic() {
+ sendQQMusicControl("music_prev");
+ }
+
+ /**
+ * 下一首音乐
+ */
+ public static void qqNextQQMusic() {
+ sendQQMusicControl("music_next");
+ }
+
+ /**
+ * "music_sequential";//顺序播放
+ * "music_random";//随机播放
+ * "music_loopone";//单曲循环
+ * "music_loopall";//列表循环
+ * 修改qq 音乐播放模式
+ */
+ public static void qqChangePlayModeQQMusic(String playMode) {
+ sendQQMusicControl(playMode);
+ }
+
+ //乐听新闻 actionValue 101 102
+ public static void sendLeTingControl(int actionValue) {
+ Intent intent = new Intent("com.zhidao.ltnews.sendplayaudio");
+ intent.putExtra("controlstate", actionValue);
+ intent.putExtra("source", "com.mogo.launcher");
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+ Logger.d(TAG,"sendLeTingControl "+actionValue);
+ }
+
+ /**
+ * 关闭乐听头条
+ */
+ public static void newsCloseLeTing() {
+ sendLeTingControl(200);
+ }
+
+ /**
+ * 暂停播放乐听头条
+ */
+ public static void newsPlayPauseLeTing() {
+ sendLeTingControl(101);
+ }
+
+ /**
+ * 播放音乐乐听头条
+ */
+ public static void newsPlayLeTing() {
+ sendLeTingControl(100);
+ }
+
+ /**
+ * 暂停音乐乐听头条
+ */
+ public static void newsPauseLeTing() {
+ sendLeTingControl(101);
+ }
+
+ /**
+ * 上一首音乐乐听头条
+ */
+ public static void newsPreLeTing() {
+ sendLeTingControl(103);
+ }
+
+ /**
+ * 下一首音乐乐听头条
+ */
+ public static void newsNextLeTing() {
+ sendLeTingControl(102);
+ }
+
+
+ //懒人听书
+ public static void sendLanRenControl(int actionValue) {
+ Intent intent = new Intent("com.zhidao.lrts.sendplayaudio");
+ intent.putExtra("controlstate", actionValue);
+ intent.putExtra("source", "com.mogo.launcher");
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+ Logger.d(TAG,"sendLanRenControl "+actionValue);
+
+ }
+
+ /**
+ * 关闭懒人听书
+ */
+ public static void newsCloseLanRen() {
+ sendLanRenControl(200);
+ }
+
+ /**
+ * 暂停播放懒人听书
+ */
+ public static void newsPlayPauseLanRen() {
+ sendLanRenControl(101);
+ }
+
+ /**
+ * 播放音乐懒人听书
+ */
+ public static void newsPlayLanRen() {
+ sendLanRenControl(101);
+ }
+
+ /**
+ * 暂停音乐懒人听书
+ */
+ public static void newsPauseLanRen() {
+ sendLanRenControl(101);
+ }
+
+ /**
+ * 上一首音乐懒人听书
+ */
+ public static void newsPreLanRen() {
+ sendLanRenControl(103);
+ }
+
+ /**
+ * 下一首音乐懒人听书
+ */
+ public static void newsNextLanRen() {
+ sendLanRenControl(102);
+ }
+
+
+ /**
+ * qq 音乐添加进播放列表
+ */
+ public static void addQQMusicPlayList(ArrayList list) {
+ Intent intent = new Intent("com.txznet.adapter.send");
+ intent.putExtra("musicAddList", GsonUtil.jsonFromObject(list));
+ intent.putExtra("action","share_list");
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+ Logger.d(TAG,"addQQMusicPlayList ");
+ }
+
+ /**
+ * qq 音乐添加进播放列表
+ */
+ public static void addQQMusicShareListPlayList(ArrayList shareList) {
+ ArrayList list = new ArrayList<>();
+ for (MarkerShareMusic shareMusic:shareList){
+ if (shareMusic == null || shareMusic.getShareType() != 1)continue;
+ QQMediaListData data = new QQMediaListData();
+ data.setMediaImgUrl(shareMusic.getMediaImg() != null ? shareMusic.getMediaImg():"");
+ data.setMediaMid(shareMusic.getMediaId() != null ? shareMusic.getMediaId():"");
+ data.setMediaSinger(shareMusic.getMediaSinger() != null ? shareMusic.getMediaSinger():"");
+ data.setMediaName(shareMusic.getMediaName() != null ? shareMusic.getMediaName():"");
+ data.setMediaUrl(shareMusic.getMediaUrl() != null ? shareMusic.getMediaUrl() :"");
+ list.add(data);
+ }
+ String jsonaddList = "";
+ try {
+ jsonaddList = GsonUtil.jsonFromObject(list);
+ Intent intent = new Intent("com.txznet.adapter.send");
+ intent.putExtra("musicAddList", jsonaddList);
+ intent.putExtra("action","share_list");
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+ Logger.d(TAG,"addQQMusicShareListPlayList "+(list != null ?list.size():"null")+" "+jsonaddList);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 懒人听书进播放列表
+ */
+ public static void controlLanRenPlay(LanRenInsertData data) {
+ // Intent intent = new Intent("com.zhidao.lrts.sendplayaudio");
+ Intent intent = new Intent("com.zhidao.mediacenter.lrts");
+ intent.putExtra("bookinfo", GsonUtil.jsonFromObject(data));
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+ }
+
+ /**
+ * 懒人听书添加列表
+ * @param jsonStr
+ */
+ public static void controlLanRenPlay(String jsonStr){
+ Logger.d(TAG,"controlLanRenPlay "+jsonStr);
+ if (TextUtils.isEmpty(jsonStr))return;
+ //Intent intent = new Intent("com.zhidao.lrts.sendplayaudio");
+ Intent intent = new Intent("com.zhidao.mediacenter.lrts");
+ intent.putExtra("bookinfo", jsonStr);
+ intent.putExtra("acceptType", 1000);
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+
+ }
+
+ /**
+ * 懒人听书后台播放
+ * @param
+ */
+ public static void controlLanRenPlayBack(){
+ Intent intent = new Intent("com.zhidao.mediacenter.lrts");
+ intent.putExtra("acceptType", 1001);
+ intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+ }
+
+ /**
+ * 播放新闻,不需要打开app
+ * @param
+ */
+ public static void sendPlayNews(String jsonStr){
+ if (OPEN && ServiceMediaHandler.getMogoNavi().isNaviing())return;
+ Logger.d(TAG,"sendPlayNews "+jsonStr);
+ if (TextUtils.isEmpty(jsonStr))return;
+ Intent intent = new Intent("com.zhidao.mediacenter.ltnews");
+ intent.putExtra("news", jsonStr);
+ intent.putExtra("insertType", 1000);
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+ }
+
+ /**
+ * 获取付费情况
+ */
+ public static void getNewsPayInfoState(){
+ Intent intent = new Intent("com.zhidao.mediacenter.ltnews");
+ intent.putExtra("insertType", 1002);
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+ }
+
+ /**
+ * 播放类型新闻,不需要打开app
+ * @param
+ */
+ public static void sendPlayTypeNews(String category){
+ if (OPEN && ServiceMediaHandler.getMogoNavi().isNaviing())return;
+ Logger.d(TAG,"sendPlayNews "+category);
+ if (TextUtils.isEmpty(category))return;
+ Intent intent = new Intent("com.zhidao.mediacenter.ltnews");
+ intent.putExtra("category", category.replace("新闻",""));
+ intent.putExtra("insertType", 1001);
+ intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+ }
+
+ /**
+ * 播放类型新闻,需要打开app
+ * @param
+ */
+ public static void sendPlayTypeNewsOpenApp(String type){
+ if (TextUtils.isEmpty(type))return;
+ Logger.d(TAG,"sendPlayNews2 "+type);
+ Intent intent = new Intent();
+ intent.setAction("android.intent.action.VIEW");
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setData(Uri.parse("letingschema://playNews?category="+type.replace("新闻","")));
+ AbsMogoApplication.getApp().startActivity(intent);
+ }
+
+ //2 为书籍听书,3 为新闻,1 为qq音乐
+ public static void clickMarkerSendData(MarkerShareMusic markerShareMusic){
+ if (OPEN && ServiceMediaHandler.getMogoNavi().isNaviing())return;
+ if (markerShareMusic != null){
+ if (markerShareMusic.getShareType() == 1){
+ ArrayList list = new ArrayList<>();
+ QQMediaListData data = new QQMediaListData();
+ data.setMediaUrl(markerShareMusic.getMediaUrl());
+ data.setMediaName(markerShareMusic.getMediaName());
+ data.setMediaSinger(markerShareMusic.getMediaSinger());
+ data.setMediaMid(markerShareMusic.getMediaId());
+ data.setMediaImgUrl(markerShareMusic.getMediaImg());
+ list.add(data);
+ addQQMusicPlayList(list);
+ }else if (markerShareMusic.getShareType() == 2){
+ String bookJson = markerShareMusic.getBookInfo();
+ controlLanRenPlay(bookJson);
+ }else if (markerShareMusic.getShareType() == 3){
+ String bookJson = markerShareMusic.getBookInfo();
+ sendPlayNews(bookJson);
+ }
+
+ UiThreadHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ sendGetMusicPlayStateBroadcast();
+ }
+ }, 2000);
+
+ }
+ }
+
+ //2 为书籍听书,3 为新闻,1 为qq音乐
+ public static void listeningSendData(MediaInfoData markerShareMusic){
+ if (OPEN && ServiceMediaHandler.getMogoNavi().isNaviing())return;
+ if (markerShareMusic != null){
+ if (markerShareMusic.getType() == 1){
+ ArrayList list = new ArrayList<>();
+ QQMediaListData data = new QQMediaListData();
+ data.setMediaUrl(markerShareMusic.getMediaUrl());
+ data.setMediaName(markerShareMusic.getMediaName());
+ data.setMediaSinger(markerShareMusic.getMediaSinger());
+ data.setMediaMid(markerShareMusic.getMediaId());
+ data.setMediaImgUrl(markerShareMusic.getMediaImg());
+ list.add(data);
+ addQQMusicPlayList(list);
+ }else if (markerShareMusic.getType() == 2){
+ String bookJson = markerShareMusic.getBookInfo();
+ controlLanRenPlay(bookJson);
+ }else if (markerShareMusic.getType() == 3){
+ String newsJson = markerShareMusic.getBookInfo();
+ sendPlayNews(newsJson);
+ }
+
+ UiThreadHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ sendGetMusicPlayStateBroadcast();
+ }
+ }, 2000);
+ }
+ }
+
+ public static void commandPre(int type) {
+ if (OPEN && ServiceMediaHandler.getMogoNavi().isNaviing())return;
+ if (type == 1) {
+ qqPreQQMusic();
+ } else if (type == 2) {
+ newsPreLanRen();
+ } else if (type == 3) {
+ newsPreLeTing();
+ }
+ }
+
+ public static void commandNext(int type) {
+ if (OPEN && ServiceMediaHandler.getMogoNavi().isNaviing())return;
+ if (type == 1) {
+ qqNextQQMusic();
+ } else if (type == 2) {
+ newsNextLanRen();
+ } else if (type == 3) {
+ newsNextLeTing();
+ }
+ }
+
+ public static void commandPlayPause(int type,int play) {
+ if (OPEN && ServiceMediaHandler.getMogoNavi().isNaviing())return;
+ if (type == 1) {
+ if (play == 1){
+ qqPauseQQMusic();
+ }else{
+ qqPlayQQMusic();
+ }
+ } else if (type == 2) {
+ newsPlayPauseLanRen();
+ } else if (type == 3) {
+ newsPlayPauseLeTing();
+ }
+ }
+
+ public static void openMediaApp(int type) {
+ if (OPEN && ServiceMediaHandler.getMogoNavi().isNaviing())return;
+ if (type == 1) {
+ SkipToAppUtils.SkipToQQMusic();
+ } else if (type == 2) {
+ SkipToAppUtils.SkipToLrListen();
+ } else if (type == 3) {
+ SkipToAppUtils.SkipToLtNews();
+ }
+ }
+
+ public static void qqMusicSearch(){
+ Intent intent = new Intent("com.txznet.adapter.send");
+ intent.putExtra("music_model","{\"field\":1,\"text\":\"我要听周杰伦的歌\",\"title\":\"\",\"keywords\":[],\"artist\":[\"周杰伦\"],\"album\":\"\"}");
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+ }
+
+ public static void sendGetMusicPlayStateBroadcast(){
+ if (OPEN && ServiceMediaHandler.getMogoNavi().isNaviing())return;
+ Intent intent = new Intent("com.zhidao.mediacenter.getaudioinfo");
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+ Logger.d("MusicControlBroadCast===","sendGetMusicPlayStateBroadcast");
+ }
+
+ public static MediaInfoData getHisMedia() {
+ String lastMediaInfo = StorageManager.getLastListenMediaMusic();
+ if (!TextUtils.isEmpty(lastMediaInfo)){
+ MediaInfoData sMediaInfoData = GsonUtil.objectFromJson(lastMediaInfo, MediaInfoData.class);
+ if (sMediaInfoData != null){
+ sMediaInfoData.setPlayState(0);
+ return sMediaInfoData;
+ }
+ }
+
+ return null;
+
+ // 测试代码吧?
+// MediaInfoData mediaInfoData = new MediaInfoData();
+// mediaInfoData.setMediaId("001jiOrk2g389Y");
+// mediaInfoData.setBookInfo("");
+// mediaInfoData.setType(1);
+// mediaInfoData.setMediaName("恭喜发财 (广场舞)");
+// mediaInfoData.setMediaSinger("刘德华");
+// mediaInfoData.setMediaType("物流派");
+// mediaInfoData.setPlayState(0);
+// mediaInfoData.setLocalMedia(false);
+// mediaInfoData.setCurTime(0);
+// mediaInfoData.setMaxTime(410*1000);
+// mediaInfoData.setMediaUrl("http://isure.stream.qqmusic.qq.com/C200000s2wCd3pzdnA.m4a?guid=2000001271&vkey=8CE1A876F5079A6E4E9BCB8306252EF152F3D4F237B3BF4C1450B50BA7E065D3D55A0735FD2E957B129E83FF7D7D5D398479D53FE2171DF0&uin=&fromtag=50");
+// mediaInfoData.setMediaImg("http://music.qq.com/musicbox/img/uccpic_error.jpg");
+// return mediaInfoData;//刘德华的恭喜发财
+ }
+
+ /**
+ * 控制QQ音乐播放某人的歌
+ */
+ public static void playSomeBodyMusic(String musicModel){
+ Intent intent = new Intent("com.txznet.adapter.send");
+ intent.putExtra("music_model", musicModel);
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+ }
+
+ public static void mediaCenterBroadcast(){
+ Intent intent = new Intent("com.mogo.launcher.media.card.center");
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+ }
+
+
+ /**
+ * 发送是否可以分享
+ * @param canshare 是否可以分享 true 可以分享 false 不可分享
+ * @param auth 是否授权 1:已授权 0:未授权 isShare 1:有可分享数据, 0:无可分享数据
+ * @param notType 不能分享的类型 1 2 3
+ * @param notWhy 不能分享的原因 1 没有可以分享的音频 2 媒体卡片不再C位 3 未授权
+ */
+ public static void ifCanShare(boolean canshare,boolean auth,int notType,String notWhy){
+ Logger.d(TAG,"ifCanShare "+canshare);
+ Intent intent = new Intent("com.mogo.launcher.media.canshare");
+ intent.putExtra("isShare", canshare?"1":"0");
+ intent.putExtra("authResult", auth?"1":"0");
+ if (!canshare){
+ intent.putExtra("notType", notType);
+ intent.putExtra("notWhy", notWhy);
+ }
+
+ AbsMogoApplication.getApp().sendBroadcast(intent);
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/OnBitmapToLocalListener.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/OnBitmapToLocalListener.java
new file mode 100644
index 0000000000..9d72f24c1b
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/OnBitmapToLocalListener.java
@@ -0,0 +1,6 @@
+package com.mogo.module.media.utils;
+
+public interface OnBitmapToLocalListener {
+ void saveSuccess(String path);
+ void saveFailed();
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/OnCompressListener.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/OnCompressListener.java
new file mode 100644
index 0000000000..a9a8842e83
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/OnCompressListener.java
@@ -0,0 +1,9 @@
+package com.mogo.module.media.utils;
+
+public interface OnCompressListener {
+ void onCompressSuccess(byte[] data);
+
+ void onCompressFailed(String msg);
+
+ void onBeforeCompress();
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/SkipToAppUtils.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/SkipToAppUtils.java
new file mode 100644
index 0000000000..b709983534
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/SkipToAppUtils.java
@@ -0,0 +1,69 @@
+package com.mogo.module.media.utils;
+
+import android.content.ComponentName;
+import android.content.Intent;
+
+import com.mogo.commons.AbsMogoApplication;
+
+public class SkipToAppUtils {
+ /**
+ * 跳转到懒人听书
+ */
+ public static void SkipToLrListen() {
+ if (Utils.isActivityExits("com.zhidao.lrts",
+ "com.zhidao.lrts.main.MainActivity")){
+ try {
+ Intent intent = new Intent();
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ ComponentName comp = new ComponentName("com.zhidao.lrts",
+ "com.zhidao.lrts.main.MainActivity");
+ intent.setComponent(comp);
+ AbsMogoApplication.getApp().startActivity(intent);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ /**
+ * 跳转到乐听新闻
+ */
+ public static void SkipToLtNews() {
+ if (Utils.isActivityExits("com.zhidao.ltnews",
+ "com.zhidao.ltnews.main.MainActivity")){
+ try {
+ Intent intent = new Intent();
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ ComponentName comp = new ComponentName("com.zhidao.ltnews",
+ "com.zhidao.ltnews.main.MainActivity");
+ intent.setComponent(comp);
+ AbsMogoApplication.getApp().startActivity(intent);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ /**
+ * 跳转到QQ音乐
+ */
+ public static void SkipToQQMusic() {
+ if (Utils.isActivityExits("com.pvetec.musics",
+ "com.pvetec.musics.activity.MainActivity")){
+ try {
+ Intent intent = new Intent();
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ ComponentName comp = new ComponentName("com.pvetec.musics",
+ "com.pvetec.musics.activity.MainActivity");
+ intent.setComponent(comp);
+ AbsMogoApplication.getApp().startActivity(intent);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/StorageManager.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/StorageManager.java
new file mode 100644
index 0000000000..d6626621bf
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/StorageManager.java
@@ -0,0 +1,26 @@
+package com.mogo.module.media.utils;
+
+import com.mogo.commons.AbsMogoApplication;
+import com.mogo.module.media.constants.Constants;
+import com.mogo.utils.storage.SharedPrefsMgr;
+import com.mogo.utils.storage.lrucache.DiskCacheManager;
+
+public class StorageManager {
+
+ public static void setShowPushShareTime(String time){
+ SharedPrefsMgr.getInstance( AbsMogoApplication.getApp() ).putString(Constants.SHOW_SHARE_PUSH_TIME,time);
+ }
+
+ public static String getShowPushShareTime(){
+ return SharedPrefsMgr.getInstance( AbsMogoApplication.getApp() ).getString( Constants.SHOW_SHARE_PUSH_TIME);
+ }
+
+ public static String getLastListenMediaMusic(){
+ return new DiskCacheManager(AbsMogoApplication.getApp(), Constants.MEDIA_UNIQUE_NAME).getString(Constants.LAST_TIME_LISTEN_MEDIA_MUSIC);
+ }
+
+ public static void setLastListenMediaMusic(String json){
+ new DiskCacheManager(AbsMogoApplication.getApp(), Constants.MEDIA_UNIQUE_NAME).put(Constants.LAST_TIME_LISTEN_MEDIA_MUSIC, json);
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/TimeUtils.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/TimeUtils.java
new file mode 100644
index 0000000000..9c5e0817f5
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/TimeUtils.java
@@ -0,0 +1,65 @@
+package com.mogo.module.media.utils;
+
+import android.text.TextUtils;
+
+import com.mogo.utils.DateTimeUtils;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * Created by congtaowang on 2018/10/19.
+ */
+public class TimeUtils {
+
+ public static String parseYMD(long timestamp ) {
+ return parse( DateTimeUtils.yyyyMMdd, timestamp );
+ }
+
+ public static String parse(String pattern, long timestamp ) {
+ if ( TextUtils.isEmpty( pattern ) ) {
+ pattern = DateTimeUtils.yyyyMMdd;
+ }
+ try {
+ return new SimpleDateFormat( pattern ).format( new Date( timestamp ) );
+ } catch ( Exception e ) {
+ return "";
+ }
+ }
+
+ //两个时间戳是否是同一天
+ public static boolean isSameData(String currentTime, String lastTime) {
+ if (TextUtils.isEmpty(currentTime)) currentTime = "0";
+ if (TextUtils.isEmpty(lastTime)) lastTime = "0";
+ try {
+ Calendar nowCal = Calendar.getInstance();
+ Calendar dataCal = Calendar.getInstance();
+ SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ Long nowLong = new Long(currentTime);
+ Long dataLong = new Long(lastTime);
+ String data1 = df1.format(nowLong);
+ String data2 = df2.format(dataLong);
+ java.util.Date now = df1.parse(data1);
+ java.util.Date date = df2.parse(data2);
+ nowCal.setTime(now);
+ dataCal.setTime(date);
+ return isSameDay(nowCal, dataCal);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ public static boolean isSameDay(Calendar cal1, Calendar cal2) {
+ if(cal1 != null && cal2 != null) {
+ return cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA)
+ && cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR)
+ && cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR);
+ } else {
+ return false;
+ }
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/ToastHelper.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/ToastHelper.java
new file mode 100644
index 0000000000..301b76de57
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/ToastHelper.java
@@ -0,0 +1,98 @@
+
+package com.mogo.module.media.utils;
+
+import android.content.Context;
+import android.os.Handler;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.IdRes;
+import androidx.annotation.LayoutRes;
+
+import com.mogo.commons.AbsMogoApplication;
+import com.mogo.module.media.R;
+import com.mogo.utils.WindowUtils;
+
+public class ToastHelper {
+ private static View toastView;
+ private static ImageView imageView;
+ private static TextView textView;
+ private static Toast toast;
+
+ private ToastHelper() {
+ }
+
+ private static void createToast(Context context) {
+ toastView = LayoutInflater.from(context).inflate(R.layout.module_media_share_toast_view, (ViewGroup) null);
+ FrameLayout frameLayout = toastView.findViewById(R.id.module_media_toast_inner);
+ FrameLayout.LayoutParams vlp = new FrameLayout.LayoutParams(WindowUtils.getScreenWidth(context), WindowUtils.getScreenHeight(context));
+ frameLayout.setLayoutParams(vlp);
+ frameLayout.setPadding(0,0,0,WindowUtils.getStatusBarHeight(context));
+ imageView = (ImageView) toastView.findViewById(R.id.imgViewIcon);
+ textView = (TextView) toastView.findViewById(R.id.txtViewContent);
+ toast = new Toast(context);
+ toast.setView(toastView);
+ toast.setGravity(1, 0, 0);
+ }
+
+ public static void showShortSuccess(Context context, String msg) {
+ context = context.getApplicationContext();
+ if (toast == null) {
+ createToast(context);
+ }
+
+ imageView.setImageResource(R.drawable.module_media_share_success);
+ textView.setText(msg);
+ toast.setDuration(Toast.LENGTH_SHORT);
+ toast.show();
+ }
+
+ public static void showShortError(Context context, String msg) {
+ context = context.getApplicationContext();
+ if (toast == null) {
+ createToast(context);
+ }
+
+ imageView.setImageResource(R.drawable.module_media_share_fail);
+ textView.setText(msg);
+ toast.setDuration(Toast.LENGTH_SHORT);
+ toast.show();
+ }
+
+ public static void cancel() {
+ if (toast != null) {
+ if (AbsMogoApplication.getApp() != null) {
+ new Handler(AbsMogoApplication.getApp().getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ if (toast != null)
+ toast.cancel();
+ }
+ });
+ }
+ }
+ }
+
+ public static Toast customToast(Context context,
+ @LayoutRes int layout,
+ @IdRes int msgTextViewId,
+ int duration,
+ CharSequence message) {
+ Toast toast = new Toast(context);
+ final View view = LayoutInflater.from(context).inflate(layout, null);
+ TextView msgView = view.findViewById(msgTextViewId);
+ if (msgView != null) {
+ msgView.setText(message);
+ }
+ toast.setView(view);
+ toast.setDuration(duration);
+ toast.setGravity(Gravity.CENTER, 0, 0);
+ return toast;
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/Utils.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/Utils.java
new file mode 100644
index 0000000000..6918d3fa10
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/utils/Utils.java
@@ -0,0 +1,344 @@
+package com.mogo.module.media.utils;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Environment;
+import android.text.TextUtils;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+
+import com.mogo.commons.AbsMogoApplication;
+import com.mogo.module.media.R;
+import com.mogo.module.media.constants.Constants;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.List;
+
+public class Utils {
+
+ /**
+ * 将px值转换为dip或dp值,保证尺寸大小不变
+ */
+ public static int px2dip(Context context, float pxValue) {
+ final float scale = context.getResources().getDisplayMetrics().density;
+ return (int) (pxValue / scale + 0.5f);
+ }
+
+ /**
+ * 将dip或dp值转换为px值,保证尺寸大小不变
+ */
+ public static int dip2px(Context context, float dipValue) {
+ final float scale = context.getResources().getDisplayMetrics().density;
+ return (int) (dipValue * scale + 0.5f);
+ }
+
+ /**
+ * 将px值转换为sp值,保证文字大小不变
+ */
+ public static int px2sp(Context context, float pxValue) {
+ final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
+ return (int) (pxValue / fontScale + 0.5f);
+ }
+
+ /**
+ * 将sp值转换为px值,保证文字大小不变
+ */
+ public static int sp2px(Context context, float spValue) {
+ final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
+ return (int) (spValue * fontScale + 0.5f);
+ }
+
+ /**
+ * 验证手机格式
+ */
+ public static boolean isMobilePhone( String mobiles ) {
+ String telRegex = "[1]\\d{10}";
+ if ( TextUtils.isEmpty( mobiles ) ) return false;
+ else return mobiles.matches( telRegex );
+ }
+
+ public static boolean isVerifyCodeRight( String code ) {
+ if ( !TextUtils.isEmpty( code ) && code.trim().length() == 4 ) {
+ return true;
+ }
+ return false;
+ }
+
+ // 格式化用于拨打的电话号码
+ public static String formatPhoneNumber(String phoneNumber ) {
+ String StrTmp = "tel:" + phoneNumber.replace( "-", "" ).replace( " ", "" );
+ StrTmp = StrTmp.replace( "转", "p" );
+ return StrTmp;
+ }
+
+ /**
+ * 当前点击点是否在视图中
+ */
+ public static boolean isInsideView(MotionEvent event, View view ) {
+ if ( view != null && event != null ) {
+ float eventX = event.getRawX();
+ float eventY = event.getRawY();
+
+ int[] contentArray = new int[2];
+
+ Rect contentRect = new Rect();
+ view.getLocationOnScreen( contentArray );
+ view.getDrawingRect( contentRect );
+ contentRect.offsetTo( contentArray[0], contentArray[1] );
+
+ return contentRect.contains( ( int ) eventX, ( int ) eventY );
+ }
+
+ return false;
+ }
+
+ public static String getChannel(Context appContext ) {
+ String channel = "";
+ try {
+ final ApplicationInfo appInfo = appContext.getPackageManager().getApplicationInfo( appContext.getPackageName(), PackageManager.GET_META_DATA );
+ Bundle configBundle = appInfo.metaData;
+ if ( null != configBundle ) {
+ channel = configBundle.getString( "com.elegant.analytics.AnalyticsConfig.Channel", "" );
+ }
+ } catch ( final PackageManager.NameNotFoundException e ) {
+ e.printStackTrace();
+ }
+ return channel;
+ }
+
+ public static File getDiskCacheDir(Context context, String uniqueName ) {
+ String cachePath;
+ if ( Environment.MEDIA_MOUNTED.equals( Environment
+ .getExternalStorageState() ) && context.getExternalCacheDir() != null ) {
+ cachePath = context.getExternalCacheDir().getPath();
+ } else {
+ cachePath = context.getCacheDir().getPath();
+ }
+ return new File( cachePath + File.separator + uniqueName );
+ }
+
+ public static File saveBitmap(Bitmap source, String targetPath ) {
+ File file = new File( targetPath, System.currentTimeMillis() + ".jpg" );
+ if ( !file.getParentFile().exists() ) {
+ file.mkdirs();
+ }
+ try {
+ FileOutputStream fos = new FileOutputStream( file );
+ source.compress( Bitmap.CompressFormat.JPEG, 100, fos );
+ fos.flush();
+ fos.close();
+ } catch ( Exception e ) {
+ return null;
+ }
+ return file;
+ }
+
+ public static void showKeyBoard( Context context ) {
+ try {
+ InputMethodManager imm = (InputMethodManager) context.getSystemService( Context.INPUT_METHOD_SERVICE );
+ if ( imm != null ) {
+ imm.toggleSoftInput( 0, InputMethodManager.HIDE_NOT_ALWAYS );
+ }
+ } catch ( Exception e ) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void hiddenKeyBoard(Context context, EditText editText ) {
+ try {
+ InputMethodManager imm = (InputMethodManager) context.getSystemService( Context.INPUT_METHOD_SERVICE );
+ if ( imm != null ) {
+ imm.hideSoftInputFromWindow( editText.getWindowToken(), 0 );
+ }
+ } catch ( Exception e ) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 判断微信是否已安装
+ *
+ * @param context
+ * @return
+ */
+ public static boolean isWeichatAvailable( Context context ) {
+ final PackageManager packageManager = context.getPackageManager();// 获取packagemanager
+ List pinfo = packageManager.getInstalledPackages( 0 );// 获取所有已安装程序的包信息
+ if ( pinfo != null ) {
+ for ( int i = 0; i < pinfo.size(); i++ ) {
+ String pn = pinfo.get( i ).packageName;
+ if ( pn.equals( "com.tencent.mm" ) ) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * 判断qq是否已安装
+ *
+ * @param context
+ * @return
+ */
+ public static boolean isQQAvailable( Context context ) {
+ final PackageManager packageManager = context.getPackageManager();
+ List pinfo = packageManager.getInstalledPackages( 0 );
+ if ( pinfo != null ) {
+ for ( int i = 0; i < pinfo.size(); i++ ) {
+ String pn = pinfo.get( i ).packageName;
+ if ( pn.equals( "com.tencent.mobileqq" ) ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public static String getVersionName(Context context, String packageName ) {
+ try {
+ PackageManager packageManager = context.getPackageManager();
+ PackageInfo packInfo = packageManager.getPackageInfo( packageName, 0 );
+ return packInfo.versionName;
+ } catch ( Exception e ) {
+ return "";
+ }
+ }
+
+ public static int getVersionCode(Context context, String packageName ) {
+ try {
+ PackageManager packageManager = context.getPackageManager();
+ PackageInfo packInfo = packageManager.getPackageInfo( packageName, 0 );
+ return packInfo.versionCode;
+ } catch ( Exception e ) {
+ return 0;
+ }
+ }
+
+ public static boolean isActivityExits(String packageName,String classStr){
+ Intent intent = new Intent();
+ intent.setClassName(packageName, classStr);
+ ResolveInfo resolveInfo = AbsMogoApplication.getApp().getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ if(resolveInfo != null) {
+ return true;
+ }else{
+ return false;
+ }
+ }
+
+
+ //计算播放时间
+ public static String calculateTime(int duration) {
+ try {
+ String time = "";
+ long minute = duration / 60000;
+ long seconds = duration % 60000;
+ long second = Math.round((float) seconds / 1000);
+ if (minute < 10) {
+ time += "0";
+ }
+ time += minute + ":";
+ if (second < 10) {
+ time += "0";
+ }
+ time += second;
+ return time;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return "0:00";
+ }
+
+ public static Integer[] getIconArray(){
+ Integer[] iconArr = {
+ R.drawable.module_media_music_animal_icon1
+ ,R.drawable.module_media_music_animal_icon2
+ ,R.drawable.module_media_music_animal_icon3
+ ,R.drawable.module_media_music_animal_icon5
+ ,R.drawable.module_media_music_animal_icon4
+ ,R.drawable.module_media_music_animal_icon6
+ ,R.drawable.module_media_music_animal_icon7
+ ,R.drawable.module_media_music_animal_icon8
+ ,R.drawable.module_media_music_animal_icon9
+ ,R.drawable.module_media_music_animal_icon10
+ ,R.drawable.module_media_music_animal_icon11
+ ,R.drawable.module_media_music_animal_icon12
+ ,R.drawable.module_media_music_animal_icon13
+ ,R.drawable.module_media_music_animal_icon14
+ ,R.drawable.module_media_music_animal_icon15
+ ,R.drawable.module_media_music_animal_icon16
+ ,R.drawable.module_media_music_animal_icon17
+ ,R.drawable.module_media_music_animal_icon18
+ ,R.drawable.module_media_music_animal_icon19
+ ,R.drawable.module_media_music_animal_icon20
+ ,R.drawable.module_media_music_animal_icon21
+ ,R.drawable.module_media_music_animal_icon22
+ ,R.drawable.module_media_music_animal_icon23
+ ,R.drawable.module_media_music_animal_icon24
+ ,R.drawable.module_media_music_animal_icon25
+ ,R.drawable.module_media_music_animal_icon26
+ ,R.drawable.module_media_music_animal_icon27
+ ,R.drawable.module_media_music_animal_icon28
+ ,R.drawable.module_media_music_animal_icon29
+ ,R.drawable.module_media_music_animal_icon30
+ ,R.drawable.module_media_music_animal_icon31
+ ,R.drawable.module_media_music_animal_icon32
+ ,R.drawable.module_media_music_animal_icon33
+ ,R.drawable.module_media_music_animal_icon34
+ ,R.drawable.module_media_music_animal_icon35
+ ,R.drawable.module_media_music_animal_icon36
+ ,R.drawable.module_media_music_animal_icon37
+ ,R.drawable.module_media_music_animal_icon38
+ ,R.drawable.module_media_music_animal_icon39
+ ,R.drawable.module_media_music_animal_icon40
+ ,R.drawable.module_media_music_animal_icon41
+ ,R.drawable.module_media_music_animal_icon42
+ ,R.drawable.module_media_music_animal_icon43
+ ,R.drawable.module_media_music_animal_icon44
+ ,R.drawable.module_media_music_animal_icon45
+ ,R.drawable.module_media_music_animal_icon46
+ ,R.drawable.module_media_music_animal_icon47
+ ,R.drawable.module_media_music_animal_icon48
+ ,R.drawable.module_media_music_animal_icon49
+ ,R.drawable.module_media_music_animal_icon50
+ ,R.drawable.module_media_music_animal_icon51
+ ,R.drawable.module_media_music_animal_icon52
+ ,R.drawable.module_media_music_animal_icon53
+ ,R.drawable.module_media_music_animal_icon54
+ ,R.drawable.module_media_music_animal_icon55
+ ,R.drawable.module_media_music_animal_icon56
+ ,R.drawable.module_media_music_animal_icon57
+ ,R.drawable.module_media_music_animal_icon58
+ ,R.drawable.module_media_music_animal_icon59
+ ,R.drawable.module_media_music_animal_icon60
+ ,R.drawable.module_media_music_animal_icon61
+ ,R.drawable.module_media_music_animal_icon62
+ ,R.drawable.module_media_music_animal_icon63
+ ,R.drawable.module_media_music_animal_icon64
+ ,R.drawable.module_media_music_animal_icon65
+ ,R.drawable.module_media_music_animal_icon66
+ ,R.drawable.module_media_music_animal_icon67
+ ,R.drawable.module_media_music_animal_icon68
+ ,R.drawable.module_media_music_animal_icon69
+ ,R.drawable.module_media_music_animal_icon70
+ ,R.drawable.module_media_music_animal_icon71
+ ,R.drawable.module_media_music_animal_icon72
+ ,R.drawable.module_media_music_animal_icon73
+ ,R.drawable.module_media_music_animal_icon74
+ ,R.drawable.module_media_music_animal_icon75
+ };
+ return iconArr;
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/view/IMusicView.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/view/IMusicView.java
new file mode 100644
index 0000000000..bf6eee1611
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/view/IMusicView.java
@@ -0,0 +1,23 @@
+package com.mogo.module.media.view;
+
+import com.mogo.commons.mvp.IView;
+import com.mogo.module.media.model.MediaInfoData;
+
+/**
+ * 音频显示类的接口
+ *
+ * @author tongchenfei
+ */
+public interface IMusicView extends IView {
+ void onMediaInfoChanged(MediaInfoData mediaInfoData);
+
+ void onMusicPlaying();
+
+ void onMusicPause();
+
+ void onMusicStopped();
+
+ void onMusicProgress(long current,long total);
+
+ void onAppExit();
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/view/MediaView.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/view/MediaView.java
new file mode 100644
index 0000000000..17e35c5dff
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/view/MediaView.java
@@ -0,0 +1,21 @@
+package com.mogo.module.media.view;
+
+import com.mogo.commons.mvp.IView;
+import com.mogo.module.common.entity.MarkerShareMusic;
+import com.mogo.module.media.model.ShareLikeData;
+
+import java.util.List;
+
+public interface MediaView extends IView {
+ void showSharePush(boolean show);
+
+ void loadNearShareMusicSuccess(List list);
+
+ void loadFriendShareMusicSuccess(List list);
+
+ void loadShareLikeDataResultSuccess(ShareLikeData.ShareLikeDataResult likeDataResult, String mediaId);
+
+ void likeShareSuccess();
+
+ void shareSuccessResult(boolean success, MarkerShareMusic markerShareMusic);
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/AnimCircleImageView.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/AnimCircleImageView.java
new file mode 100644
index 0000000000..2cf0db96d9
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/AnimCircleImageView.java
@@ -0,0 +1,225 @@
+package com.mogo.module.media.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.NinePatchDrawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.ImageView;
+
+import com.mogo.module.common.utils.CarSeries;
+import com.mogo.skin.support.IMogoSkinCompatSupportable;
+import com.mogo.skin.support.helper.MogoSkinCompatHelperDelegate;
+import com.mogo.skin.support.helper.MogoSkinCompatImageHelperDelegate;
+
+@SuppressLint("AppCompatCustomView")
+public class AnimCircleImageView extends ImageView implements IMogoSkinCompatSupportable {
+ Drawable mDrawbleSrc;
+ Context context;
+ Bitmap mBitmapOut;
+ Bitmap output;
+ int defaultWidth;
+ int defaultHeight;
+ int diameter;
+ int radius;
+ PaintFlagsDrawFilter drawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);
+ Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
+
+ MogoSkinCompatImageHelperDelegate imageHelper;
+
+ int currentDegree;
+ int savedDegree;
+ boolean isRotateEnable;
+ boolean isRotating;
+// private int delayMilliseconds = 450;
+ private int delayMilliseconds = 2000;
+ private int mRotateAngleStep = 3;
+
+ public AnimCircleImageView(Context context) {
+ this(context, null);
+ }
+
+ public AnimCircleImageView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AnimCircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ imageHelper = new MogoSkinCompatImageHelperDelegate(this);
+ this.context = context;
+ init();
+ }
+
+ private void init() {
+ mDrawbleSrc = getDrawable();
+ isRotateEnable = false;
+ isRotating = false;
+ delayMilliseconds = CarSeries.isF8xxSeries() ? 10 : 450;
+ mRotateAngleStep = CarSeries.isF8xxSeries() ? 1 : 3;
+ }
+
+ @Override
+ public void setImageBitmap(Bitmap bm) {
+ super.setImageBitmap(bm);
+ mDrawbleSrc = getDrawable();
+ output = null;
+ }
+
+ @Override
+ public void setImageDrawable(Drawable drawable) {
+ super.setImageDrawable(drawable);
+ mDrawbleSrc = getDrawable();
+ output = null;
+ }
+
+ @Override
+ public void setImageResource(int resId) {
+ super.setImageResource(resId);
+// Log.d("AnimCircle", "setImageResource: " + MogoSkinCompatHelperDelegate.isSupport());
+ imageHelper.setImageResource(resId);
+ mDrawbleSrc = getDrawable();
+ output = null;
+ }
+
+ public void startAnim() {
+ Log.d("AnimCircle", "startAnim====" + isRotating);
+ if (isRotating){
+ return;
+ }
+ isRotateEnable = true;
+ isRotating = true;
+ currentDegree = savedDegree;
+ invalidate();
+ Log.d("AnimCircle", "invalidate==");
+ }
+
+ public void stopAnim() {
+ Log.d("AnimCircle", "stopAnim===");
+ removeCallbacks(loopInvalidate);
+ isRotating = false;
+ isRotateEnable = false;
+ savedDegree = currentDegree;
+ }
+
+ public boolean isRotationing(){
+ return isRotating;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+// Log.d("AnimCircle", "onDraw====");
+ try {
+ if (mDrawbleSrc == null) {
+ return;
+ }
+
+ if (getWidth() == 0 || getHeight() == 0) {
+ return;
+ }
+
+ if (mDrawbleSrc.getClass() == NinePatchDrawable.class) {
+ return;
+ }
+
+ if (output == null) {
+ defaultHeight = getHeight();
+ defaultWidth = getWidth();
+ diameter = (defaultHeight > defaultWidth ? defaultWidth : defaultHeight);
+ radius = diameter / 2;
+// mBitmapOut = getCuttedPicture(mDrawbleSrc);
+ mBitmapOut = ((BitmapDrawable) mDrawbleSrc).getBitmap();
+
+ Paint paint = new Paint();
+ Rect rect = new Rect(0, 0, mBitmapOut.getWidth(),
+ mBitmapOut.getHeight());
+
+ paint.setAntiAlias(true);
+ paint.setFilterBitmap(true);
+ paint.setDither(true);
+
+ output = Bitmap.createBitmap(mBitmapOut.getWidth(),
+ mBitmapOut.getHeight(), Bitmap.Config.ARGB_8888);
+ Canvas mTempCanvas = new Canvas(output);
+ mTempCanvas.drawARGB(0, 0, 0, 0);
+ mTempCanvas.drawCircle(mBitmapOut.getWidth() / 2,
+ mBitmapOut.getHeight() / 2, mBitmapOut.getWidth() / 2,
+ paint);
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
+ mTempCanvas.drawBitmap(mBitmapOut, rect, rect, paint);
+
+ }
+
+ if (isRotateEnable) {
+ currentDegree = (currentDegree + mRotateAngleStep) % 360;
+ canvas.save();
+ canvas.setDrawFilter(drawFilter);
+ canvas.rotate(currentDegree, defaultWidth / 2, defaultHeight / 2);
+ canvas.drawBitmap(output, defaultWidth / 2 - radius, defaultHeight / 2 - radius, mPaint);
+ canvas.restore();
+ if (isRotateEnable) {
+ removeCallbacks(loopInvalidate);
+ postDelayed(loopInvalidate, delayMilliseconds);
+// postInvalidateDelayed(delayMilliseconds);
+ }
+ } else {
+ canvas.save();
+ canvas.setDrawFilter(drawFilter);
+ canvas.rotate(currentDegree, defaultWidth / 2, defaultHeight / 2);
+ canvas.drawBitmap(output, defaultWidth / 2 - radius, defaultHeight / 2 - radius, mPaint);
+ canvas.restore();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ private Runnable loopInvalidate = this::invalidate;
+
+ private Bitmap getCuttedPicture(Drawable DrawbleSrc) {
+ Bitmap mBitmapOrigin = ((BitmapDrawable) DrawbleSrc).getBitmap();
+ int mWidth = mBitmapOrigin.getWidth();
+ int mHeight = mBitmapOrigin.getHeight();
+
+
+ float scale = Math.min((float) mWidth / (float) defaultWidth, (float) mHeight / (float) defaultHeight);
+ Bitmap mBitmapScaled = Bitmap.createScaledBitmap(mBitmapOrigin, (int) (mWidth / scale), (int) (mHeight / scale), false);
+ int x;
+ int y;
+
+ x = mBitmapScaled.getWidth() / 2 - radius;
+ y = mBitmapScaled.getHeight() / 2 - radius;
+
+ if (x < 0) {
+ x = 0;
+ }
+ if (y < 0) {
+ y = 0;
+ }
+ Bitmap mBitmapCropped = Bitmap.createBitmap(mBitmapScaled, x, y, diameter, diameter);
+ return mBitmapCropped;
+ }
+
+ public int getDelayMilliseconds() {
+ return delayMilliseconds;
+ }
+
+ public void setDelayMilliseconds(int delayMilliseconds) {
+ this.delayMilliseconds = delayMilliseconds;
+ }
+
+ @Override
+ public void applySkin() {
+ imageHelper.applySkin();
+ }
+}
+
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/AnimalJSurfaceView.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/AnimalJSurfaceView.java
new file mode 100644
index 0000000000..50af224904
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/AnimalJSurfaceView.java
@@ -0,0 +1,129 @@
+package com.mogo.module.media.widget;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+import com.mogo.utils.ThreadPoolService;
+
+public class AnimalJSurfaceView extends SurfaceView implements Runnable, SurfaceHolder.Callback {
+
+ private SurfaceHolder mHolder;
+
+ /**
+ * 动画是否执行中
+ */
+ private boolean bRunning = false;
+ /**
+ * 当前执行的第几帧
+ */
+ private int mCurrentPos;
+ /**
+ * 动画集合
+ */
+ private int[] mFrames;
+
+ public AnimalJSurfaceView(Context context) {
+ super(context);
+ init();
+ }
+
+ public AnimalJSurfaceView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public AnimalJSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init();
+ }
+
+ private void init() {
+ mHolder = getHolder();
+ mHolder.addCallback(this);
+ setZOrderOnTop(true);
+ mHolder.setFormat(PixelFormat.TRANSLUCENT);
+ }
+
+ public void setFrames(int[] frames) {
+ mFrames = frames;
+ }
+
+ public void startAnim() {
+ if (bRunning) {
+ return;
+ }
+ ThreadPoolService.execute(this);
+ bRunning = true;
+ }
+
+ public void stop() {
+ bRunning = false;
+ }
+
+ @Override
+ public void run() {
+ while (bRunning) {
+ drawBitmap();
+ mCurrentPos++;
+ try {
+ Thread.sleep(400);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+
+ private void drawBitmap() {
+ //获取画布并锁定
+ Canvas mCanvas = mHolder.lockCanvas();
+ if (mCanvas == null) {
+ return;
+ }else{
+ mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
+ }
+ //绘制透明色
+ mCanvas.drawColor(Color.parseColor("#00000000"));
+ Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), mFrames[mCurrentPos % mFrames.length]);
+
+ Paint paint = new Paint();
+ paint.setAlpha(70);
+ Rect mSrcRect = new Rect(0,
+ 0,
+ mBitmap.getWidth(),
+ mBitmap.getHeight()); // 图片绘制
+ Rect mDestRect = new Rect(0,
+ 0,
+ getWidth(),
+ getHeight());// 图片绘制位置
+
+ mCanvas.drawBitmap(mBitmap, mSrcRect, mDestRect, paint);
+ //解锁画布,并展示bitmap到surface
+ mHolder.unlockCanvasAndPost(mCanvas);
+ mBitmap.recycle();
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/CircleImageView.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/CircleImageView.java
new file mode 100644
index 0000000000..bbbe5316c4
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/CircleImageView.java
@@ -0,0 +1,87 @@
+package com.mogo.module.media.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.RectF;
+import android.graphics.Xfermode;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+import androidx.annotation.NonNull;
+
+@SuppressLint("AppCompatCustomView")
+public class CircleImageView extends ImageView {
+
+ private Paint mPaint;
+
+ private Xfermode mXfermode;
+
+ private boolean onceLoad = false;
+
+ private int mWidth;
+
+ private int mHeight;
+
+ private Bitmap mBitmap;
+
+ public CircleImageView(Context context) {
+ this(context, null);
+ }
+
+ public CircleImageView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ if (changed && !onceLoad) {
+ mPaint = new Paint();
+ mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
+ mPaint.setFilterBitmap(true);
+ mPaint.setXfermode(mXfermode);
+ mPaint.setAntiAlias(true);
+ mWidth = getWidth();
+ mHeight = getHeight();
+ if(mWidth <= 0 || mHeight <= 0){
+ return;
+ }
+ mBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(mBitmap);
+ RectF oval = new RectF(0, 0, mWidth, mHeight);
+ Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ canvas.drawOval(oval, paint);
+ onceLoad = true;
+ }
+
+ }
+
+ @Override
+ protected void onDraw(@NonNull Canvas canvas) {
+
+ Drawable image = getDrawable();
+ if(image==null || mWidth<=0 || mHeight<=0){
+ return;
+ }
+ int level = canvas.saveLayer(0, 0, mWidth, mHeight, null, Canvas.ALL_SAVE_FLAG);
+ image.setBounds(0, 0, mWidth, mHeight);
+ image.draw(canvas);
+ canvas.drawBitmap(mBitmap, 0, 0, mPaint);
+ canvas.restoreToCount(level);
+ //super.onDraw(canvas);
+
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/CircleImageView2.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/CircleImageView2.java
new file mode 100644
index 0000000000..dffbcfad90
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/CircleImageView2.java
@@ -0,0 +1,337 @@
+package com.mogo.module.media.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.ColorRes;
+import androidx.annotation.DrawableRes;
+
+import com.mogo.module.media.R;
+
+@SuppressLint("AppCompatCustomView")
+public class CircleImageView2 extends ImageView {
+
+ private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
+
+ private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
+ private static final int COLORDRAWABLE_DIMENSION = 2;
+
+ private static final int DEFAULT_BORDER_WIDTH = 0;
+ private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
+ private static final int DEFAULT_FILL_COLOR = Color.TRANSPARENT;
+ private static final boolean DEFAULT_BORDER_OVERLAY = false;
+
+ private final RectF mDrawableRect = new RectF();
+ private final RectF mBorderRect = new RectF();
+
+ private final Matrix mShaderMatrix = new Matrix();
+ private final Paint mBitmapPaint = new Paint();
+ private final Paint mBorderPaint = new Paint();
+ private final Paint mFillPaint = new Paint();
+
+ private int mBorderColor = DEFAULT_BORDER_COLOR;
+ private int mBorderWidth = DEFAULT_BORDER_WIDTH;
+ private int mFillColor = DEFAULT_FILL_COLOR;
+
+ private Bitmap mBitmap;
+ private BitmapShader mBitmapShader;
+ private int mBitmapWidth;
+ private int mBitmapHeight;
+
+ private float mDrawableRadius;
+ private float mBorderRadius;
+
+ private ColorFilter mColorFilter;
+
+ private boolean mReady;
+ private boolean mSetupPending;
+ private boolean mBorderOverlay;
+
+ public CircleImageView2(Context context) {
+ super(context);
+
+ init();
+ }
+
+ public CircleImageView2(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public CircleImageView2(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MediaCircleImageView2, defStyle, 0);
+
+ mBorderWidth = a.getDimensionPixelSize(R.styleable.MediaCircleImageView2_civ_border_width, DEFAULT_BORDER_WIDTH);
+ mBorderColor = a.getColor(R.styleable.MediaCircleImageView2_civ_border_color, DEFAULT_BORDER_COLOR);
+ mBorderOverlay = a.getBoolean(R.styleable.MediaCircleImageView2_civ_border_overlay, DEFAULT_BORDER_OVERLAY);
+ mFillColor = a.getColor(R.styleable.MediaCircleImageView2_civ_fill_color, DEFAULT_FILL_COLOR);
+
+ a.recycle();
+
+ init();
+ }
+
+ private void init() {
+ super.setScaleType(SCALE_TYPE);
+ mReady = true;
+
+ if (mSetupPending) {
+ setup();
+ mSetupPending = false;
+ }
+ }
+
+ @Override
+ public ScaleType getScaleType() {
+ return SCALE_TYPE;
+ }
+
+ @Override
+ public void setScaleType(ScaleType scaleType) {
+ if (scaleType != SCALE_TYPE) {
+ throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));
+ }
+ }
+
+ @Override
+ public void setAdjustViewBounds(boolean adjustViewBounds) {
+ if (adjustViewBounds) {
+ throw new IllegalArgumentException("adjustViewBounds not supported.");
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (mBitmap == null) {
+ return;
+ }
+
+ if (mFillColor != Color.TRANSPARENT) {
+ canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mDrawableRadius, mFillPaint);
+ }
+ canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mDrawableRadius, mBitmapPaint);
+ if (mBorderWidth != 0) {
+ canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mBorderRadius, mBorderPaint);
+ }
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ setup();
+ }
+
+ public int getBorderColor() {
+ return mBorderColor;
+ }
+
+ public void setBorderColor(@ColorInt int borderColor) {
+ if (borderColor == mBorderColor) {
+ return;
+ }
+
+ mBorderColor = borderColor;
+ mBorderPaint.setColor(mBorderColor);
+ invalidate();
+ }
+
+ public void setBorderColorResource(@ColorRes int borderColorRes) {
+ setBorderColor(getContext().getResources().getColor(borderColorRes));
+ }
+
+ public int getFillColor() {
+ return mFillColor;
+ }
+
+ public void setFillColor(@ColorInt int fillColor) {
+ if (fillColor == mFillColor) {
+ return;
+ }
+
+ mFillColor = fillColor;
+ mFillPaint.setColor(fillColor);
+ invalidate();
+ }
+
+ public void setFillColorResource(@ColorRes int fillColorRes) {
+ setFillColor(getContext().getResources().getColor(fillColorRes));
+ }
+
+ public int getBorderWidth() {
+ return mBorderWidth;
+ }
+
+ public void setBorderWidth(int borderWidth) {
+ if (borderWidth == mBorderWidth) {
+ return;
+ }
+
+ mBorderWidth = borderWidth;
+ setup();
+ }
+
+ public boolean isBorderOverlay() {
+ return mBorderOverlay;
+ }
+
+ public void setBorderOverlay(boolean borderOverlay) {
+ if (borderOverlay == mBorderOverlay) {
+ return;
+ }
+
+ mBorderOverlay = borderOverlay;
+ setup();
+ }
+
+ @Override
+ public void setImageBitmap(Bitmap bm) {
+ super.setImageBitmap(bm);
+ mBitmap = bm;
+ setup();
+ }
+
+ @Override
+ public void setImageDrawable(Drawable drawable) {
+ super.setImageDrawable(drawable);
+ mBitmap = getBitmapFromDrawable(drawable);
+ setup();
+ }
+
+ @Override
+ public void setImageResource(@DrawableRes int resId) {
+ super.setImageResource(resId);
+ mBitmap = getBitmapFromDrawable(getDrawable());
+ setup();
+ }
+
+ @Override
+ public void setImageURI(Uri uri) {
+ super.setImageURI(uri);
+ mBitmap = uri != null ? getBitmapFromDrawable(getDrawable()) : null;
+ setup();
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ if (cf == mColorFilter) {
+ return;
+ }
+
+ mColorFilter = cf;
+ mBitmapPaint.setColorFilter(mColorFilter);
+ invalidate();
+ }
+
+ private Bitmap getBitmapFromDrawable(Drawable drawable) {
+ if (drawable == null) {
+ return null;
+ }
+
+ if (drawable instanceof BitmapDrawable) {
+ return ((BitmapDrawable) drawable).getBitmap();
+ }
+
+ try {
+ Bitmap bitmap;
+
+ if (drawable instanceof ColorDrawable) {
+ bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
+ } else {
+ bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
+ }
+
+ Canvas canvas = new Canvas(bitmap);
+ drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ drawable.draw(canvas);
+ return bitmap;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private void setup() {
+ if (!mReady) {
+ mSetupPending = true;
+ return;
+ }
+
+ if (getWidth() == 0 && getHeight() == 0) {
+ return;
+ }
+
+ if (mBitmap == null) {
+ invalidate();
+ return;
+ }
+
+ mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
+
+ mBitmapPaint.setAntiAlias(true);
+ mBitmapPaint.setShader(mBitmapShader);
+
+ mBorderPaint.setStyle(Paint.Style.STROKE);
+ mBorderPaint.setAntiAlias(true);
+ mBorderPaint.setColor(mBorderColor);
+ mBorderPaint.setStrokeWidth(mBorderWidth);
+
+ mFillPaint.setStyle(Paint.Style.FILL);
+ mFillPaint.setAntiAlias(true);
+ mFillPaint.setColor(mFillColor);
+
+ mBitmapHeight = mBitmap.getHeight();
+ mBitmapWidth = mBitmap.getWidth();
+
+ mBorderRect.set(0, 0, getWidth(), getHeight());
+ mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f);
+
+ mDrawableRect.set(mBorderRect);
+ if (!mBorderOverlay) {
+ mDrawableRect.inset(mBorderWidth, mBorderWidth);
+ }
+ mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f);
+
+ updateShaderMatrix();
+ invalidate();
+ }
+
+ private void updateShaderMatrix() {
+ float scale;
+ float dx = 0;
+ float dy = 0;
+
+ mShaderMatrix.set(null);
+
+ if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
+ scale = mDrawableRect.height() / (float) mBitmapHeight;
+ dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
+ } else {
+ scale = mDrawableRect.width() / (float) mBitmapWidth;
+ dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
+ }
+
+ mShaderMatrix.setScale(scale, scale);
+ mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);
+
+ mBitmapShader.setLocalMatrix(mShaderMatrix);
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/CircleNumberProgress.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/CircleNumberProgress.java
new file mode 100644
index 0000000000..bfda00bc62
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/CircleNumberProgress.java
@@ -0,0 +1,185 @@
+package com.mogo.module.media.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.SweepGradient;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.mogo.module.media.R;
+import com.mogo.module.media.utils.Utils;
+
+/**
+ * @author lixiaopeng
+ * @description
+ * @since 2020/12/15
+ */
+public class CircleNumberProgress extends View {
+ /** 进度条画笔的宽度(dp) */
+ private int paintProgressWidth = 4;
+
+ /** 文字百分比的字体大小(sp) */
+ private int paintTextSize = 20;
+
+ /** 未完成进度条的颜色 */
+// private int paintUndoneColor = 0xffaaaaaa;
+ private int paintUndoneColor;
+
+ /** 已完成进度条的颜色 */
+// private int paintDoneColor = 0xff67aae4;
+ private int paintDoneColor;
+
+ /** 百分比文字的颜色 */
+ private int paintTextColor = 0xffff0077;
+
+ /** 设置进度条画笔的宽度(px) */
+ private int paintProgressWidthPx;
+
+ /** 文字画笔的尺寸(px) */
+ private int paintTextSizePx;
+ /** Context上下文环境 */
+ private Context context;
+
+ /** 调用者设置的进程 0 - 100 */
+ private int progress;
+
+ /** 画未完成进度圆弧的画笔 */
+ private Paint paintUndone = new Paint();
+
+ /** 画已经完成进度条的画笔 */
+ private Paint paintDone = new Paint();
+
+ /** 画文字的画笔 */
+// private Paint paintText = new Paint();
+
+ /** 包围进度条圆弧的矩形 */
+ private RectF rectF = new RectF();
+
+ /** 包围文字所在路径圆弧的矩形,比上一个矩形略小 */
+ private RectF rectF2 = new RectF();
+
+ /** 进度文字所在的路径 */
+ private Path path = new Path();
+
+ /** 文字所在路径圆弧的半径 */
+ private int radiusText;
+
+ /** 是否进行过了测量 */
+ private boolean isMeasured = false;
+
+ public CircleNumberProgress(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ this.context = context;
+ TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PercentageRing);
+ //中间圆的背景颜色 默认为浅紫色
+ paintUndoneColor = typedArray.getColor(R.styleable.PercentageRing_circleBackground, 0xffafb4db);
+ //外圆环的颜色 默认为深紫色
+// paintDoneColor = typedArray.getColor(R.styleable.PercentageRing_ringColor, Color.parseColor("#e6fffff"));
+
+ // 构造器中初始化数据
+ initData();
+ }
+
+ /** 初始化数据 */
+ private void initData() {
+
+ // 设置进度条画笔的宽度
+ paintProgressWidthPx = Utils.dip2px(context, paintProgressWidth);
+
+ // 设置文字画笔的尺寸(px)
+ paintTextSizePx = Utils.sp2px(context, paintTextSize);
+
+ // 未完成进度圆环的画笔的属性
+ paintUndone.setColor(paintUndoneColor);
+ paintUndone.setStrokeWidth(paintProgressWidthPx);
+ paintUndone.setAntiAlias(true);
+ paintUndone.setStyle(Paint.Style.STROKE);
+
+ // 已经完成进度条的画笔的属性
+// paintDone.setColor(paintDoneColor);
+ paintDone.setStrokeWidth(paintProgressWidthPx);
+ paintDone.setAntiAlias(true);
+ paintDone.setStyle(Paint.Style.STROKE);
+
+ float[] pos = {0f, 0.5f, 1.0f};
+ SweepGradient linearGradient = new SweepGradient((getMeasuredWidth() - 40)/2,(getMeasuredHeight() - 40)/2,
+ new int[]{Color.parseColor("#ffffff"), Color.parseColor("#B3ffffff"), Color.parseColor("#ffffff")}, pos);
+
+// SweepGradient linearGradient = new SweepGradient((getMeasuredWidth() -40)/2,(getMeasuredHeight() - 40)/2,new int[]{Color.GREEN, Color.RED, Color.YELLOW, Color.WHITE, Color.BLUE}, pos);
+ Matrix matrix = new Matrix();
+ matrix.setRotate(180, getMeasuredWidth()/2, getMeasuredHeight()/2);
+ linearGradient.setLocalMatrix(matrix);
+ paintDone.setShader(linearGradient);
+
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ if (!isMeasured) {
+ getWidthAndHeight();
+ isMeasured = true;
+ }
+ }
+
+ /** 得到视图等的高度宽度尺寸数据 */
+ private void getWidthAndHeight() {
+ // 得到自定义视图的高度
+ int viewHeight;
+
+ // 得到自定义视图的宽度
+ int viewWidth;
+
+ // 得到自定义视图的X轴中心点
+ int viewCenterX;
+
+ // 得到自定义视图的Y轴中心点
+ int viewCenterY;
+
+ viewHeight = getMeasuredHeight();
+ viewWidth = getMeasuredWidth();
+ viewCenterX = viewWidth / 2;
+ viewCenterY = viewHeight / 2;
+
+ // 取本View长宽较小者的一半为整个圆环部分(包括圆环和文字)最外侧的半径
+ int minLenth = viewHeight > viewWidth ? viewWidth / 2 : viewHeight / 2;
+
+ // 比较文字高度和圆环宽度,如果文字高度较大,那么文字将突破圆环,否则,圆环会把文字包裹在内部
+ Rect rect = new Rect();
+ int textHeight = rect.height();
+
+ // 得到圆环的中间半径(外径和内径平均值)
+ int radiusArc = minLenth - (paintProgressWidthPx > textHeight ? paintProgressWidthPx / 2 : textHeight / 2);
+ rectF.left = viewCenterX - radiusArc;
+ rectF.top = viewCenterY - radiusArc;
+ rectF.right = viewCenterX + radiusArc;
+ rectF.bottom = viewCenterY + radiusArc;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ // 画未完成进度的圆环
+ canvas.drawArc(rectF, 0, 360, false, paintUndone);
+
+ // 画已经完成进度的圆弧 从-90度开始,即从圆环顶部开始
+ canvas.drawArc(rectF, -90, progress / 100.0f * 360, false, paintDone);
+
+ }
+
+ /**
+ * @param progress 外部传进来的当前进度,强制重绘
+ */
+ public void setProgress(int progress) {
+ this.progress = progress;
+ invalidate();
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/Corner.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/Corner.java
new file mode 100644
index 0000000000..ef7115fa65
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/Corner.java
@@ -0,0 +1,16 @@
+package com.mogo.module.media.widget;
+import androidx.annotation.IntDef;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.SOURCE)
+@IntDef({
+ Corner.TOP_LEFT, Corner.TOP_RIGHT,
+ Corner.BOTTOM_LEFT, Corner.BOTTOM_RIGHT
+})
+public @interface Corner {
+ int TOP_LEFT = 0;
+ int TOP_RIGHT = 1;
+ int BOTTOM_RIGHT = 2;
+ int BOTTOM_LEFT = 3;
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/NoScrollSeekBar.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/NoScrollSeekBar.java
new file mode 100644
index 0000000000..d8f9186fbf
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/NoScrollSeekBar.java
@@ -0,0 +1,34 @@
+package com.mogo.module.media.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.SeekBar;
+
+@SuppressLint("AppCompatCustomView")
+public class NoScrollSeekBar extends SeekBar {
+
+ public NoScrollSeekBar(Context context) {
+ super(context);
+ }
+
+ public NoScrollSeekBar(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public NoScrollSeekBar(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+ /**
+ * onTouchEvent 是在 SeekBar 继承的抽象类 AbsSeekBar 里
+ * 你可以看下他们的继承关系
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ //原来是要将TouchEvent传递下去的,我们不让它传递下去就行了
+ //return super.onTouchEvent(event);
+
+ return false ;
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/PercentageRingView.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/PercentageRingView.java
new file mode 100755
index 0000000000..e21c7b9420
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/PercentageRingView.java
@@ -0,0 +1,174 @@
+package com.mogo.module.media.widget;
+
+import android.content.Context;
+import android.graphics.BlurMaskFilter;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.EmbossMaskFilter;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.graphics.SweepGradient;
+import android.util.AttributeSet;
+import android.view.View;
+
+
+/**
+ * 环形进度条
+ */
+public class PercentageRingView extends View {
+
+ private Paint pathPaint;
+ private Paint fillArcPaint;
+ // 设置光源的方向
+ private float[] direction = new float[]{1, 1, 1};
+ /**
+ * 透明
+ */
+ public static final int TRANSPARENT = 0x00000000;
+
+ /**
+ * 红色
+ */
+ public static final int RED = 0xffff0000;
+
+ // 设置环境光亮度
+ private float light = 0.4f;
+ //渐变数组
+ private int[] arcColors = new int[]{RED, TRANSPARENT};
+
+ // 选择要应用的反射等级
+ private float specular = 6;
+ private EmbossMaskFilter emboss;
+ private RectF oval;
+ private BlurMaskFilter mBlur;
+ // view重绘的标记
+ private boolean reset = false;
+ // 向 mask应用一定级别的模糊
+ private float blur = 3.5f;
+ private int arcradus = 30;
+ //初始化进度
+ private int progress = 0;
+ //设置进度最大值
+ private int max = 100;
+
+
+ public PercentageRingView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initPaint();
+ oval = new RectF();
+ emboss = new EmbossMaskFilter(direction, light, specular, blur);
+ mBlur = new BlurMaskFilter(20, BlurMaskFilter.Blur.NORMAL);
+ }
+
+ //初始化画笔操作
+ private void initPaint() {
+ //初始化画笔操作
+ pathPaint = new Paint();
+ // 设置是否抗锯齿
+ pathPaint.setAntiAlias(true);
+ // 帮助消除锯齿
+ pathPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
+ // 设置中空的样式
+ pathPaint.setStyle(Paint.Style.STROKE);
+ pathPaint.setDither(true);
+ pathPaint.setStrokeJoin(Paint.Join.ROUND);
+
+ fillArcPaint = new Paint();
+ // 设置是否抗锯齿
+ fillArcPaint.setAntiAlias(true);
+ // 帮助消除锯齿
+ fillArcPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
+ // 设置中空的样式
+ fillArcPaint.setStyle(Paint.Style.STROKE);
+ fillArcPaint.setDither(true);
+ fillArcPaint.setStrokeJoin(Paint.Join.ROUND);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ if (reset) {
+ canvas.drawColor(Color.TRANSPARENT);
+ reset = false;
+ }
+ drawcircle(canvas);
+
+ }
+
+ private void drawcircle(Canvas canvas) {
+ int height = getMeasuredWidth();
+ int width = getMeasuredWidth();
+ //半径 = 宽/2-圆环的宽度
+ int radius = width / 2 - arcradus;
+ int cx = width / 2;
+ int cy = height / 2;
+ pathPaint.setColor(Color.BLUE);
+ //绘制大圆
+ canvas.drawCircle(width / 2, height / 2, radius + arcradus
+ / 2 + 0.5f, pathPaint);
+ //绘制小圆
+ canvas.drawCircle(width / 2, height / 2, radius - arcradus
+ / 2 - 0.5f, pathPaint);
+
+ // 环形颜色填充
+ SweepGradient sweepGradient =
+ new SweepGradient(width / 2, height / 2, arcColors, null);
+ fillArcPaint.setShader(sweepGradient);
+ // 设置画笔为白色
+
+ // 模糊效果
+ fillArcPaint.setMaskFilter(mBlur);
+ // 设置线的类型,边是圆的
+ fillArcPaint.setStrokeCap(Paint.Cap.ROUND);
+
+ //设置圆弧的宽度
+ fillArcPaint.setStrokeWidth(arcradus + 1);
+ // 确定圆弧的绘制位置,也就是里面圆弧坐标和外面圆弧坐标
+ oval.set(width / 2 - radius, height / 2 - radius, width
+ / 2 + radius, height / 2 + radius);
+ // 画圆弧,第二个参数为:起始角度,第三个为跨的角度,第四个为true的时候是实心,false的时候为空心
+ canvas.drawArc(oval,
+ 0,
+ ((float) progress / max) * 360,
+ false,
+ fillArcPaint);
+ }
+
+ public int getProgress() {
+ return progress;
+ }
+
+ public void setProgress(int progress) {
+ this.progress = progress;
+ this.invalidate();
+ }
+
+ public int getMax() {
+ return max;
+ }
+
+ public void setMax(int max) {
+ this.max = max;
+ }
+
+ public int[] getArcColors() {
+ return arcColors;
+ }
+
+ public void setArcColors(int[] arcColors) {
+ this.arcColors = arcColors;
+// this.invalidate();
+ }
+
+ /**
+ * 描述:重置进度
+ *
+ * @throws
+ */
+ public void reset() {
+ reset = true;
+ this.progress = 0;
+ this.invalidate();
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/RoundedDrawable.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/RoundedDrawable.java
new file mode 100644
index 0000000000..a7e8d6b780
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/RoundedDrawable.java
@@ -0,0 +1,618 @@
+package com.mogo.module.media.widget;
+
+import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.util.Log;
+import android.widget.ImageView.ScaleType;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@SuppressWarnings("UnusedDeclaration")
+public class RoundedDrawable extends Drawable {
+
+ public static final String TAG = "RoundedDrawable";
+ public static final int DEFAULT_BORDER_COLOR = Color.BLACK;
+
+ private final RectF mBounds = new RectF();
+ private final RectF mDrawableRect = new RectF();
+ private final RectF mBitmapRect = new RectF();
+ private final Bitmap mBitmap;
+ private final Paint mBitmapPaint;
+ private final int mBitmapWidth;
+ private final int mBitmapHeight;
+ private final RectF mBorderRect = new RectF();
+ private final Paint mBorderPaint;
+ private final Matrix mShaderMatrix = new Matrix();
+ private final RectF mSquareCornersRect = new RectF();
+
+ private Shader.TileMode mTileModeX = Shader.TileMode.CLAMP;
+ private Shader.TileMode mTileModeY = Shader.TileMode.CLAMP;
+ private boolean mRebuildShader = true;
+
+ private float mCornerRadius = 0f;
+ // [ topLeft, topRight, bottomLeft, bottomRight ]
+ private final boolean[] mCornersRounded = new boolean[] { true, true, true, true };
+
+ private boolean mOval = false;
+ private float mBorderWidth = 0;
+ private ColorStateList mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);
+ private ScaleType mScaleType = ScaleType.FIT_CENTER;
+
+ public RoundedDrawable(Bitmap bitmap) {
+ mBitmap = bitmap;
+
+ mBitmapWidth = bitmap.getWidth();
+ mBitmapHeight = bitmap.getHeight();
+ mBitmapRect.set(0, 0, mBitmapWidth, mBitmapHeight);
+
+ mBitmapPaint = new Paint();
+ mBitmapPaint.setStyle(Paint.Style.FILL);
+ mBitmapPaint.setAntiAlias(true);
+
+ mBorderPaint = new Paint();
+ mBorderPaint.setStyle(Paint.Style.STROKE);
+ mBorderPaint.setAntiAlias(true);
+ mBorderPaint.setColor(mBorderColor.getColorForState(getState(), DEFAULT_BORDER_COLOR));
+ mBorderPaint.setStrokeWidth(mBorderWidth);
+ }
+
+ public static RoundedDrawable fromBitmap(Bitmap bitmap) {
+ if (bitmap != null) {
+ return new RoundedDrawable(bitmap);
+ } else {
+ return null;
+ }
+ }
+
+ public static Drawable fromDrawable(Drawable drawable) {
+ if (drawable != null) {
+ if (drawable instanceof RoundedDrawable) {
+ // just return if it's already a RoundedDrawable
+ return drawable;
+ } else if (drawable instanceof LayerDrawable) {
+ LayerDrawable ld = (LayerDrawable) drawable;
+ int num = ld.getNumberOfLayers();
+
+ // loop through layers to and change to RoundedDrawables if possible
+ for (int i = 0; i < num; i++) {
+ Drawable d = ld.getDrawable(i);
+ ld.setDrawableByLayerId(ld.getId(i), fromDrawable(d));
+ }
+ return ld;
+ }
+
+ // try to get a bitmap from the drawable and
+ Bitmap bm = drawableToBitmap(drawable);
+ if (bm != null) {
+ return new RoundedDrawable(bm);
+ }
+ }
+ return drawable;
+ }
+
+ public static Bitmap drawableToBitmap(Drawable drawable) {
+ if (drawable instanceof BitmapDrawable) {
+ return ((BitmapDrawable) drawable).getBitmap();
+ }
+
+ Bitmap bitmap;
+ int width = Math.max(drawable.getIntrinsicWidth(), 2);
+ int height = Math.max(drawable.getIntrinsicHeight(), 2);
+ try {
+ bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ drawable.draw(canvas);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ Log.w(TAG, "Failed to create bitmap from drawable!");
+ bitmap = null;
+ }
+
+ return bitmap;
+ }
+
+ public Bitmap getSourceBitmap() {
+ return mBitmap;
+ }
+
+ @Override
+ public boolean isStateful() {
+ return mBorderColor.isStateful();
+ }
+
+ @Override
+ protected boolean onStateChange(int[] state) {
+ int newColor = mBorderColor.getColorForState(state, 0);
+ if (mBorderPaint.getColor() != newColor) {
+ mBorderPaint.setColor(newColor);
+ return true;
+ } else {
+ return super.onStateChange(state);
+ }
+ }
+
+ private void updateShaderMatrix() {
+ float scale;
+ float dx;
+ float dy;
+
+ switch (mScaleType) {
+ case CENTER:
+ mBorderRect.set(mBounds);
+ mBorderRect.inset(mBorderWidth / 2, mBorderWidth / 2);
+
+ mShaderMatrix.reset();
+ mShaderMatrix.setTranslate((int) ((mBorderRect.width() - mBitmapWidth) * 0.5f + 0.5f),
+ (int) ((mBorderRect.height() - mBitmapHeight) * 0.5f + 0.5f));
+ break;
+
+ case CENTER_CROP:
+ mBorderRect.set(mBounds);
+ mBorderRect.inset(mBorderWidth / 2, mBorderWidth / 2);
+
+ mShaderMatrix.reset();
+
+ dx = 0;
+ dy = 0;
+
+ if (mBitmapWidth * mBorderRect.height() > mBorderRect.width() * mBitmapHeight) {
+ scale = mBorderRect.height() / (float) mBitmapHeight;
+ dx = (mBorderRect.width() - mBitmapWidth * scale) * 0.5f;
+ } else {
+ scale = mBorderRect.width() / (float) mBitmapWidth;
+ dy = (mBorderRect.height() - mBitmapHeight * scale) * 0.5f;
+ }
+
+ mShaderMatrix.setScale(scale, scale);
+ mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth / 2,
+ (int) (dy + 0.5f) + mBorderWidth / 2);
+ break;
+
+ case CENTER_INSIDE:
+ mShaderMatrix.reset();
+
+ if (mBitmapWidth <= mBounds.width() && mBitmapHeight <= mBounds.height()) {
+ scale = 1.0f;
+ } else {
+ scale = Math.min(mBounds.width() / (float) mBitmapWidth,
+ mBounds.height() / (float) mBitmapHeight);
+ }
+
+ dx = (int) ((mBounds.width() - mBitmapWidth * scale) * 0.5f + 0.5f);
+ dy = (int) ((mBounds.height() - mBitmapHeight * scale) * 0.5f + 0.5f);
+
+ mShaderMatrix.setScale(scale, scale);
+ mShaderMatrix.postTranslate(dx, dy);
+
+ mBorderRect.set(mBitmapRect);
+ mShaderMatrix.mapRect(mBorderRect);
+ mBorderRect.inset(mBorderWidth / 2, mBorderWidth / 2);
+ mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect, Matrix.ScaleToFit.FILL);
+ break;
+
+ default:
+ case FIT_CENTER:
+ mBorderRect.set(mBitmapRect);
+ mShaderMatrix.setRectToRect(mBitmapRect, mBounds, Matrix.ScaleToFit.CENTER);
+ mShaderMatrix.mapRect(mBorderRect);
+ mBorderRect.inset(mBorderWidth / 2, mBorderWidth / 2);
+ mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect, Matrix.ScaleToFit.FILL);
+ break;
+
+ case FIT_END:
+ mBorderRect.set(mBitmapRect);
+ mShaderMatrix.setRectToRect(mBitmapRect, mBounds, Matrix.ScaleToFit.END);
+ mShaderMatrix.mapRect(mBorderRect);
+ mBorderRect.inset(mBorderWidth / 2, mBorderWidth / 2);
+ mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect, Matrix.ScaleToFit.FILL);
+ break;
+
+ case FIT_START:
+ mBorderRect.set(mBitmapRect);
+ mShaderMatrix.setRectToRect(mBitmapRect, mBounds, Matrix.ScaleToFit.START);
+ mShaderMatrix.mapRect(mBorderRect);
+ mBorderRect.inset(mBorderWidth / 2, mBorderWidth / 2);
+ mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect, Matrix.ScaleToFit.FILL);
+ break;
+
+ case FIT_XY:
+ mBorderRect.set(mBounds);
+ mBorderRect.inset(mBorderWidth / 2, mBorderWidth / 2);
+ mShaderMatrix.reset();
+ mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect, Matrix.ScaleToFit.FILL);
+ break;
+ }
+
+ mDrawableRect.set(mBorderRect);
+ mRebuildShader = true;
+ }
+
+ @Override
+ protected void onBoundsChange(@NonNull Rect bounds) {
+ super.onBoundsChange(bounds);
+
+ mBounds.set(bounds);
+
+ updateShaderMatrix();
+ }
+
+ @Override
+ public void draw(@NonNull Canvas canvas) {
+ if (mRebuildShader) {
+ BitmapShader bitmapShader = new BitmapShader(mBitmap, mTileModeX, mTileModeY);
+ if (mTileModeX == Shader.TileMode.CLAMP && mTileModeY == Shader.TileMode.CLAMP) {
+ bitmapShader.setLocalMatrix(mShaderMatrix);
+ }
+ mBitmapPaint.setShader(bitmapShader);
+ mRebuildShader = false;
+ }
+
+ if (mOval) {
+ if (mBorderWidth > 0) {
+ canvas.drawOval(mDrawableRect, mBitmapPaint);
+ canvas.drawOval(mBorderRect, mBorderPaint);
+ } else {
+ canvas.drawOval(mDrawableRect, mBitmapPaint);
+ }
+ } else {
+ if (any(mCornersRounded)) {
+ float radius = mCornerRadius;
+ if (mBorderWidth > 0) {
+ canvas.drawRoundRect(mDrawableRect, radius, radius, mBitmapPaint);
+ canvas.drawRoundRect(mBorderRect, radius, radius, mBorderPaint);
+ redrawBitmapForSquareCorners(canvas);
+ redrawBorderForSquareCorners(canvas);
+ } else {
+ canvas.drawRoundRect(mDrawableRect, radius, radius, mBitmapPaint);
+ redrawBitmapForSquareCorners(canvas);
+ }
+ } else {
+ canvas.drawRect(mDrawableRect, mBitmapPaint);
+ if (mBorderWidth > 0) {
+ canvas.drawRect(mBorderRect, mBorderPaint);
+ }
+ }
+ }
+ }
+
+ private void redrawBitmapForSquareCorners(Canvas canvas) {
+ if (all(mCornersRounded)) {
+ // no square corners
+ return;
+ }
+
+ if (mCornerRadius == 0) {
+ return; // no round corners
+ }
+
+ float left = mDrawableRect.left;
+ float top = mDrawableRect.top;
+ float right = left + mDrawableRect.width();
+ float bottom = top + mDrawableRect.height();
+ float radius = mCornerRadius;
+
+ if (!mCornersRounded[Corner.TOP_LEFT]) {
+ mSquareCornersRect.set(left, top, left + radius, top + radius);
+ canvas.drawRect(mSquareCornersRect, mBitmapPaint);
+ }
+
+ if (!mCornersRounded[Corner.TOP_RIGHT]) {
+ mSquareCornersRect.set(right - radius, top, right, radius);
+ canvas.drawRect(mSquareCornersRect, mBitmapPaint);
+ }
+
+ if (!mCornersRounded[Corner.BOTTOM_RIGHT]) {
+ mSquareCornersRect.set(right - radius, bottom - radius, right, bottom);
+ canvas.drawRect(mSquareCornersRect, mBitmapPaint);
+ }
+
+ if (!mCornersRounded[Corner.BOTTOM_LEFT]) {
+ mSquareCornersRect.set(left, bottom - radius, left + radius, bottom);
+ canvas.drawRect(mSquareCornersRect, mBitmapPaint);
+ }
+ }
+
+ private void redrawBorderForSquareCorners(Canvas canvas) {
+ if (all(mCornersRounded)) {
+ // no square corners
+ return;
+ }
+
+ if (mCornerRadius == 0) {
+ return; // no round corners
+ }
+
+ float left = mDrawableRect.left;
+ float top = mDrawableRect.top;
+ float right = left + mDrawableRect.width();
+ float bottom = top + mDrawableRect.height();
+ float radius = mCornerRadius;
+ float offset = mBorderWidth / 2;
+
+ if (!mCornersRounded[Corner.TOP_LEFT]) {
+ canvas.drawLine(left - offset, top, left + radius, top, mBorderPaint);
+ canvas.drawLine(left, top - offset, left, top + radius, mBorderPaint);
+ }
+
+ if (!mCornersRounded[Corner.TOP_RIGHT]) {
+ canvas.drawLine(right - radius - offset, top, right, top, mBorderPaint);
+ canvas.drawLine(right, top - offset, right, top + radius, mBorderPaint);
+ }
+
+ if (!mCornersRounded[Corner.BOTTOM_RIGHT]) {
+ canvas.drawLine(right - radius - offset, bottom, right + offset, bottom, mBorderPaint);
+ canvas.drawLine(right, bottom - radius, right, bottom, mBorderPaint);
+ }
+
+ if (!mCornersRounded[Corner.BOTTOM_LEFT]) {
+ canvas.drawLine(left - offset, bottom, left + radius, bottom, mBorderPaint);
+ canvas.drawLine(left, bottom - radius, left, bottom, mBorderPaint);
+ }
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public int getAlpha() {
+ return mBitmapPaint.getAlpha();
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ mBitmapPaint.setAlpha(alpha);
+ invalidateSelf();
+ }
+
+ @Override
+ public ColorFilter getColorFilter() {
+ return mBitmapPaint.getColorFilter();
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ mBitmapPaint.setColorFilter(cf);
+ invalidateSelf();
+ }
+
+ @Override
+ public void setDither(boolean dither) {
+ mBitmapPaint.setDither(dither);
+ invalidateSelf();
+ }
+
+ @Override
+ public void setFilterBitmap(boolean filter) {
+ mBitmapPaint.setFilterBitmap(filter);
+ invalidateSelf();
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mBitmapWidth;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mBitmapHeight;
+ }
+
+ /**
+ * @return the corner radius.
+ */
+ public float getCornerRadius() {
+ return mCornerRadius;
+ }
+
+ /**
+ * @param corner the specific corner to get radius of.
+ * @return the corner radius of the specified corner.
+ */
+ public float getCornerRadius(@Corner int corner) {
+ return mCornersRounded[corner] ? mCornerRadius : 0f;
+ }
+
+ /**
+ * Sets all corners to the specified radius.
+ *
+ * @param radius the radius.
+ * @return the {@link RoundedDrawable} for chaining.
+ */
+ public RoundedDrawable setCornerRadius(float radius) {
+ setCornerRadius(radius, radius, radius, radius);
+ return this;
+ }
+
+ /**
+ * Sets the corner radius of one specific corner.
+ *
+ * @param corner the corner.
+ * @param radius the radius.
+ * @return the {@link RoundedDrawable} for chaining.
+ */
+ public RoundedDrawable setCornerRadius(@Corner int corner, float radius) {
+ if (radius != 0 && mCornerRadius != 0 && mCornerRadius != radius) {
+ throw new IllegalArgumentException("Multiple nonzero corner radii not yet supported.");
+ }
+
+ if (radius == 0) {
+ if (only(corner, mCornersRounded)) {
+ mCornerRadius = 0;
+ }
+ mCornersRounded[corner] = false;
+ } else {
+ if (mCornerRadius == 0) {
+ mCornerRadius = radius;
+ }
+ mCornersRounded[corner] = true;
+ }
+
+ return this;
+ }
+
+ /**
+ * Sets the corner radii of all the corners.
+ *
+ * @param topLeft top left corner radius.
+ * @param topRight top right corner radius
+ * @param bottomRight bototm right corner radius.
+ * @param bottomLeft bottom left corner radius.
+ * @return the {@link RoundedDrawable} for chaining.
+ */
+ public RoundedDrawable setCornerRadius(float topLeft, float topRight, float bottomRight,
+ float bottomLeft) {
+ Set radiusSet = new HashSet<>(4);
+ radiusSet.add(topLeft);
+ radiusSet.add(topRight);
+ radiusSet.add(bottomRight);
+ radiusSet.add(bottomLeft);
+
+ radiusSet.remove(0f);
+
+ if (radiusSet.size() > 1) {
+ throw new IllegalArgumentException("Multiple nonzero corner radii not yet supported.");
+ }
+
+ if (!radiusSet.isEmpty()) {
+ float radius = radiusSet.iterator().next();
+ if (Float.isInfinite(radius) || Float.isNaN(radius) || radius < 0) {
+ throw new IllegalArgumentException("Invalid radius value: " + radius);
+ }
+ mCornerRadius = radius;
+ } else {
+ mCornerRadius = 0f;
+ }
+
+ mCornersRounded[Corner.TOP_LEFT] = topLeft > 0;
+ mCornersRounded[Corner.TOP_RIGHT] = topRight > 0;
+ mCornersRounded[Corner.BOTTOM_RIGHT] = bottomRight > 0;
+ mCornersRounded[Corner.BOTTOM_LEFT] = bottomLeft > 0;
+ return this;
+ }
+
+ public float getBorderWidth() {
+ return mBorderWidth;
+ }
+
+ public RoundedDrawable setBorderWidth(float width) {
+ mBorderWidth = width;
+ mBorderPaint.setStrokeWidth(mBorderWidth);
+ return this;
+ }
+
+ public int getBorderColor() {
+ return mBorderColor.getDefaultColor();
+ }
+
+ public RoundedDrawable setBorderColor(@ColorInt int color) {
+ return setBorderColor(ColorStateList.valueOf(color));
+ }
+
+ public ColorStateList getBorderColors() {
+ return mBorderColor;
+ }
+
+ public RoundedDrawable setBorderColor(ColorStateList colors) {
+ mBorderColor = colors != null ? colors : ColorStateList.valueOf(0);
+ mBorderPaint.setColor(mBorderColor.getColorForState(getState(), DEFAULT_BORDER_COLOR));
+ return this;
+ }
+
+ public boolean isOval() {
+ return mOval;
+ }
+
+ public RoundedDrawable setOval(boolean oval) {
+ mOval = oval;
+ return this;
+ }
+
+ public ScaleType getScaleType() {
+ return mScaleType;
+ }
+
+ public RoundedDrawable setScaleType(ScaleType scaleType) {
+ if (scaleType == null) {
+ scaleType = ScaleType.FIT_CENTER;
+ }
+ if (mScaleType != scaleType) {
+ mScaleType = scaleType;
+ updateShaderMatrix();
+ }
+ return this;
+ }
+
+ public Shader.TileMode getTileModeX() {
+ return mTileModeX;
+ }
+
+ public RoundedDrawable setTileModeX(Shader.TileMode tileModeX) {
+ if (mTileModeX != tileModeX) {
+ mTileModeX = tileModeX;
+ mRebuildShader = true;
+ invalidateSelf();
+ }
+ return this;
+ }
+
+ public Shader.TileMode getTileModeY() {
+ return mTileModeY;
+ }
+
+ public RoundedDrawable setTileModeY(Shader.TileMode tileModeY) {
+ if (mTileModeY != tileModeY) {
+ mTileModeY = tileModeY;
+ mRebuildShader = true;
+ invalidateSelf();
+ }
+ return this;
+ }
+
+ private static boolean only(int index, boolean[] booleans) {
+ for (int i = 0, len = booleans.length; i < len; i++) {
+ if (booleans[i] != (i == index)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean any(boolean[] booleans) {
+ for (boolean b : booleans) {
+ if (b) { return true; }
+ }
+ return false;
+ }
+
+ private static boolean all(boolean[] booleans) {
+ for (boolean b : booleans) {
+ if (b) { return false; }
+ }
+ return true;
+ }
+
+ public Bitmap toBitmap() {
+ return drawableToBitmap(this);
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/RoundedImageView.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/RoundedImageView.java
new file mode 100644
index 0000000000..b552bea0bb
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/RoundedImageView.java
@@ -0,0 +1,595 @@
+package com.mogo.module.media.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.ColorFilter;
+import android.graphics.Shader;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.net.Uri;
+
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.ImageView;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.DimenRes;
+import androidx.annotation.DrawableRes;
+
+import com.mogo.module.media.R;
+
+@SuppressLint("AppCompatCustomView")
+public class RoundedImageView extends ImageView {
+
+ // Constants for tile mode attributes
+ private static final int TILE_MODE_UNDEFINED = -2;
+ private static final int TILE_MODE_CLAMP = 0;
+ private static final int TILE_MODE_REPEAT = 1;
+ private static final int TILE_MODE_MIRROR = 2;
+
+ public static final String TAG = "RoundedImageView";
+ public static final float DEFAULT_RADIUS = 0f;
+ public static final float DEFAULT_BORDER_WIDTH = 0f;
+ public static final Shader.TileMode DEFAULT_TILE_MODE = Shader.TileMode.CLAMP;
+ private static final ImageView.ScaleType[] SCALE_TYPES = {
+ ImageView.ScaleType.MATRIX,
+ ImageView.ScaleType.FIT_XY,
+ ImageView.ScaleType.FIT_START,
+ ImageView.ScaleType.FIT_CENTER,
+ ImageView.ScaleType.FIT_END,
+ ImageView.ScaleType.CENTER,
+ ImageView.ScaleType.CENTER_CROP,
+ ImageView.ScaleType.CENTER_INSIDE
+ };
+
+ private final float[] mCornerRadii =
+ new float[] { DEFAULT_RADIUS, DEFAULT_RADIUS, DEFAULT_RADIUS, DEFAULT_RADIUS };
+
+ private Drawable mBackgroundDrawable;
+ private ColorStateList mBorderColor =
+ ColorStateList.valueOf(RoundedDrawable.DEFAULT_BORDER_COLOR);
+ private float mBorderWidth = DEFAULT_BORDER_WIDTH;
+ private ColorFilter mColorFilter = null;
+ private boolean mColorMod = false;
+ private Drawable mDrawable;
+ private boolean mHasColorFilter = false;
+ private boolean mIsOval = false;
+ private boolean mMutateBackground = false;
+ private int mResource;
+ private int mBackgroundResource;
+ private ImageView.ScaleType mScaleType;
+ private Shader.TileMode mTileModeX = DEFAULT_TILE_MODE;
+ private Shader.TileMode mTileModeY = DEFAULT_TILE_MODE;
+
+ public RoundedImageView(Context context) {
+ super(context);
+ }
+
+ public RoundedImageView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public RoundedImageView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MediaRoundedImageView, defStyle, 0);
+
+ int index = a.getInt(R.styleable.MediaRoundedImageView_android_scaleType, -1);
+ if (index >= 0) {
+ setScaleType(SCALE_TYPES[index]);
+ } else {
+ // default scaletype to FIT_CENTER
+ setScaleType(ImageView.ScaleType.FIT_CENTER);
+ }
+
+ float cornerRadiusOverride =
+ a.getDimensionPixelSize(R.styleable.MediaRoundedImageView_riv_corner_radius, -1);
+
+ mCornerRadii[Corner.TOP_LEFT] =
+ a.getDimensionPixelSize(R.styleable.MediaRoundedImageView_riv_corner_radius_top_left, -1);
+ mCornerRadii[Corner.TOP_RIGHT] =
+ a.getDimensionPixelSize(R.styleable.MediaRoundedImageView_riv_corner_radius_top_right, -1);
+ mCornerRadii[Corner.BOTTOM_RIGHT] =
+ a.getDimensionPixelSize(R.styleable.MediaRoundedImageView_riv_corner_radius_bottom_right, -1);
+ mCornerRadii[Corner.BOTTOM_LEFT] =
+ a.getDimensionPixelSize(R.styleable.MediaRoundedImageView_riv_corner_radius_bottom_left, -1);
+
+ boolean any = false;
+ for (int i = 0, len = mCornerRadii.length; i < len; i++) {
+ if (mCornerRadii[i] < 0) {
+ mCornerRadii[i] = 0f;
+ } else {
+ any = true;
+ }
+ }
+
+ if (!any) {
+ if (cornerRadiusOverride < 0) {
+ cornerRadiusOverride = DEFAULT_RADIUS;
+ }
+ for (int i = 0, len = mCornerRadii.length; i < len; i++) {
+ mCornerRadii[i] = cornerRadiusOverride;
+ }
+ }
+
+ mBorderWidth = a.getDimensionPixelSize(R.styleable.MediaRoundedImageView_riv_border_width, -1);
+ if (mBorderWidth < 0) {
+ mBorderWidth = DEFAULT_BORDER_WIDTH;
+ }
+
+ mBorderColor = a.getColorStateList(R.styleable.MediaRoundedImageView_riv_border_color);
+ if (mBorderColor == null) {
+ mBorderColor = ColorStateList.valueOf(RoundedDrawable.DEFAULT_BORDER_COLOR);
+ }
+
+ mMutateBackground = a.getBoolean(R.styleable.MediaRoundedImageView_riv_mutate_background, false);
+ mIsOval = a.getBoolean(R.styleable.MediaRoundedImageView_riv_oval, false);
+
+ final int tileMode = a.getInt(R.styleable.MediaRoundedImageView_riv_tile_mode, TILE_MODE_UNDEFINED);
+ if (tileMode != TILE_MODE_UNDEFINED) {
+ setTileModeX(parseTileMode(tileMode));
+ setTileModeY(parseTileMode(tileMode));
+ }
+
+ final int tileModeX =
+ a.getInt(R.styleable.MediaRoundedImageView_riv_tile_mode_x, TILE_MODE_UNDEFINED);
+ if (tileModeX != TILE_MODE_UNDEFINED) {
+ setTileModeX(parseTileMode(tileModeX));
+ }
+
+ final int tileModeY =
+ a.getInt(R.styleable.MediaRoundedImageView_riv_tile_mode_y, TILE_MODE_UNDEFINED);
+ if (tileModeY != TILE_MODE_UNDEFINED) {
+ setTileModeY(parseTileMode(tileModeY));
+ }
+
+ updateDrawableAttrs();
+ updateBackgroundDrawableAttrs(true);
+
+ if (mMutateBackground) {
+ //noinspection deprecation
+ super.setBackgroundDrawable(mBackgroundDrawable);
+ }
+
+ a.recycle();
+ }
+
+ private static Shader.TileMode parseTileMode(int tileMode) {
+ switch (tileMode) {
+ case TILE_MODE_CLAMP:
+ return Shader.TileMode.CLAMP;
+ case TILE_MODE_REPEAT:
+ return Shader.TileMode.REPEAT;
+ case TILE_MODE_MIRROR:
+ return Shader.TileMode.MIRROR;
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ protected void drawableStateChanged() {
+ super.drawableStateChanged();
+ invalidate();
+ }
+
+ @Override
+ public ImageView.ScaleType getScaleType() {
+ return mScaleType;
+ }
+
+ @Override
+ public void setScaleType(ImageView.ScaleType scaleType) {
+ assert scaleType != null;
+
+ if (mScaleType != scaleType) {
+ mScaleType = scaleType;
+
+ switch (scaleType) {
+ case CENTER:
+ case CENTER_CROP:
+ case CENTER_INSIDE:
+ case FIT_CENTER:
+ case FIT_START:
+ case FIT_END:
+ case FIT_XY:
+ super.setScaleType(ImageView.ScaleType.FIT_XY);
+ break;
+ default:
+ super.setScaleType(scaleType);
+ break;
+ }
+
+ updateDrawableAttrs();
+ updateBackgroundDrawableAttrs(false);
+ invalidate();
+ }
+ }
+
+ @Override
+ public void setImageDrawable(Drawable drawable) {
+ mResource = 0;
+ mDrawable = RoundedDrawable.fromDrawable(drawable);
+ updateDrawableAttrs();
+ super.setImageDrawable(mDrawable);
+ }
+
+ @Override
+ public void setImageBitmap(Bitmap bm) {
+ mResource = 0;
+ mDrawable = RoundedDrawable.fromBitmap(bm);
+ updateDrawableAttrs();
+ super.setImageDrawable(mDrawable);
+ }
+
+ @Override
+ public void setImageResource(@DrawableRes int resId) {
+ if (mResource != resId) {
+ mResource = resId;
+ mDrawable = resolveResource();
+ updateDrawableAttrs();
+ super.setImageDrawable(mDrawable);
+ }
+ }
+
+ @Override
+ public void setImageURI(Uri uri) {
+ super.setImageURI(uri);
+ setImageDrawable(getDrawable());
+ }
+
+ private Drawable resolveResource() {
+ Resources rsrc = getResources();
+ if (rsrc == null) { return null; }
+
+ Drawable d = null;
+
+ if (mResource != 0) {
+ try {
+ d = rsrc.getDrawable(mResource);
+ } catch (Exception e) {
+ Log.w(TAG, "Unable to find resource: " + mResource, e);
+ // Don't try again.
+ mResource = 0;
+ }
+ }
+ return RoundedDrawable.fromDrawable(d);
+ }
+
+ @Override
+ public void setBackground(Drawable background) {
+ setBackgroundDrawable(background);
+ }
+
+ @Override
+ public void setBackgroundResource(@DrawableRes int resId) {
+ if (mBackgroundResource != resId) {
+ mBackgroundResource = resId;
+ mBackgroundDrawable = resolveBackgroundResource();
+ setBackgroundDrawable(mBackgroundDrawable);
+ }
+ }
+
+ @Override
+ public void setBackgroundColor(int color) {
+ mBackgroundDrawable = new ColorDrawable(color);
+ setBackgroundDrawable(mBackgroundDrawable);
+ }
+
+ private Drawable resolveBackgroundResource() {
+ Resources rsrc = getResources();
+ if (rsrc == null) { return null; }
+
+ Drawable d = null;
+
+ if (mBackgroundResource != 0) {
+ try {
+ d = rsrc.getDrawable(mBackgroundResource);
+ } catch (Exception e) {
+ Log.w(TAG, "Unable to find resource: " + mBackgroundResource, e);
+ // Don't try again.
+ mBackgroundResource = 0;
+ }
+ }
+ return RoundedDrawable.fromDrawable(d);
+ }
+
+ private void updateDrawableAttrs() {
+ updateAttrs(mDrawable, mScaleType);
+ }
+
+ private void updateBackgroundDrawableAttrs(boolean convert) {
+ if (mMutateBackground) {
+ if (convert) {
+ mBackgroundDrawable = RoundedDrawable.fromDrawable(mBackgroundDrawable);
+ }
+ updateAttrs(mBackgroundDrawable, ImageView.ScaleType.FIT_XY);
+ }
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ if (mColorFilter != cf) {
+ mColorFilter = cf;
+ mHasColorFilter = true;
+ mColorMod = true;
+ applyColorMod();
+ invalidate();
+ }
+ }
+
+ private void applyColorMod() {
+ // Only mutate and apply when modifications have occurred. This should
+ // not reset the mColorMod flag, since these filters need to be
+ // re-applied if the Drawable is changed.
+ if (mDrawable != null && mColorMod) {
+ mDrawable = mDrawable.mutate();
+ if (mHasColorFilter) {
+ mDrawable.setColorFilter(mColorFilter);
+ }
+ // TODO: support, eventually...
+ //mDrawable.setXfermode(mXfermode);
+ //mDrawable.setAlpha(mAlpha * mViewAlphaScale >> 8);
+ }
+ }
+
+ private void updateAttrs(Drawable drawable, ImageView.ScaleType scaleType) {
+ if (drawable == null) { return; }
+
+ if (drawable instanceof RoundedDrawable) {
+ ((RoundedDrawable) drawable)
+ .setScaleType(scaleType)
+ .setBorderWidth(mBorderWidth)
+ .setBorderColor(mBorderColor)
+ .setOval(mIsOval)
+ .setTileModeX(mTileModeX)
+ .setTileModeY(mTileModeY);
+
+ if (mCornerRadii != null) {
+ ((RoundedDrawable) drawable).setCornerRadius(
+ mCornerRadii[Corner.TOP_LEFT],
+ mCornerRadii[Corner.TOP_RIGHT],
+ mCornerRadii[Corner.BOTTOM_RIGHT],
+ mCornerRadii[Corner.BOTTOM_LEFT]);
+ }
+
+ applyColorMod();
+ } else if (drawable instanceof LayerDrawable) {
+ // loop through layers to and set drawable attrs
+ LayerDrawable ld = ((LayerDrawable) drawable);
+ for (int i = 0, layers = ld.getNumberOfLayers(); i < layers; i++) {
+ updateAttrs(ld.getDrawable(i), scaleType);
+ }
+ }
+ }
+
+ @Override
+ @Deprecated
+ public void setBackgroundDrawable(Drawable background) {
+ mBackgroundDrawable = background;
+ updateBackgroundDrawableAttrs(true);
+ //noinspection deprecation
+ super.setBackgroundDrawable(mBackgroundDrawable);
+ }
+
+ /**
+ * @return the largest corner radius.
+ */
+ public float getCornerRadius() {
+ return getMaxCornerRadius();
+ }
+
+ /**
+ * @return the largest corner radius.
+ */
+ public float getMaxCornerRadius() {
+ float maxRadius = 0;
+ for (float r : mCornerRadii) {
+ maxRadius = Math.max(r, maxRadius);
+ }
+ return maxRadius;
+ }
+
+ /**
+ * Get the corner radius of a specified corner.
+ *
+ * @param corner the corner.
+ * @return the radius.
+ */
+ public float getCornerRadius(@Corner int corner) {
+ return mCornerRadii[corner];
+ }
+
+ /**
+ * Set all the corner radii from a dimension resource id.
+ *
+ * @param resId dimension resource id of radii.
+ */
+ public void setCornerRadiusDimen(@DimenRes int resId) {
+ float radius = getResources().getDimension(resId);
+ setCornerRadius(radius, radius, radius, radius);
+ }
+
+ /**
+ * Set the corner radius of a specific corner from a dimension resource id.
+ *
+ * @param corner the corner to set.
+ * @param resId the dimension resource id of the corner radius.
+ */
+ public void setCornerRadiusDimen(@Corner int corner, @DimenRes int resId) {
+ setCornerRadius(corner, getResources().getDimensionPixelSize(resId));
+ }
+
+ /**
+ * Set the corner radii of all corners in px.
+ *
+ * @param radius the radius to set.
+ */
+ public void setCornerRadius(float radius) {
+ setCornerRadius(radius, radius, radius, radius);
+ }
+
+ /**
+ * Set the corner radius of a specific corner in px.
+ *
+ * @param corner the corner to set.
+ * @param radius the corner radius to set in px.
+ */
+ public void setCornerRadius(@Corner int corner, float radius) {
+ if (mCornerRadii[corner] == radius) {
+ return;
+ }
+ mCornerRadii[corner] = radius;
+
+ updateDrawableAttrs();
+ updateBackgroundDrawableAttrs(false);
+ invalidate();
+ }
+
+ /**
+ * Set the corner radii of each corner individually. Currently only one unique nonzero value is
+ * supported.
+ *
+ * @param topLeft radius of the top left corner in px.
+ * @param topRight radius of the top right corner in px.
+ * @param bottomRight radius of the bottom right corner in px.
+ * @param bottomLeft radius of the bottom left corner in px.
+ */
+ public void setCornerRadius(float topLeft, float topRight, float bottomLeft, float bottomRight) {
+ if (mCornerRadii[Corner.TOP_LEFT] == topLeft
+ && mCornerRadii[Corner.TOP_RIGHT] == topRight
+ && mCornerRadii[Corner.BOTTOM_RIGHT] == bottomRight
+ && mCornerRadii[Corner.BOTTOM_LEFT] == bottomLeft) {
+ return;
+ }
+
+ mCornerRadii[Corner.TOP_LEFT] = topLeft;
+ mCornerRadii[Corner.TOP_RIGHT] = topRight;
+ mCornerRadii[Corner.BOTTOM_LEFT] = bottomLeft;
+ mCornerRadii[Corner.BOTTOM_RIGHT] = bottomRight;
+
+ updateDrawableAttrs();
+ updateBackgroundDrawableAttrs(false);
+ invalidate();
+ }
+
+ public float getBorderWidth() {
+ return mBorderWidth;
+ }
+
+ public void setBorderWidth(@DimenRes int resId) {
+ setBorderWidth(getResources().getDimension(resId));
+ }
+
+ public void setBorderWidth(float width) {
+ if (mBorderWidth == width) { return; }
+
+ mBorderWidth = width;
+ updateDrawableAttrs();
+ updateBackgroundDrawableAttrs(false);
+ invalidate();
+ }
+
+ @ColorInt
+ public int getBorderColor() {
+ return mBorderColor.getDefaultColor();
+ }
+
+ public void setBorderColor(@ColorInt int color) {
+ setBorderColor(ColorStateList.valueOf(color));
+ }
+
+ public ColorStateList getBorderColors() {
+ return mBorderColor;
+ }
+
+ public void setBorderColor(ColorStateList colors) {
+ if (mBorderColor.equals(colors)) { return; }
+
+ mBorderColor =
+ (colors != null) ? colors : ColorStateList.valueOf(RoundedDrawable.DEFAULT_BORDER_COLOR);
+ updateDrawableAttrs();
+ updateBackgroundDrawableAttrs(false);
+ if (mBorderWidth > 0) {
+ invalidate();
+ }
+ }
+
+ /**
+ * Return true if this view should be oval and always set corner radii to half the height or
+ * width.
+ *
+ * @return if this {@link RoundedImageView} is set to oval.
+ */
+ public boolean isOval() {
+ return mIsOval;
+ }
+
+ /**
+ * Set if the drawable should ignore the corner radii set and always round the source to
+ * exactly half the height or width.
+ *
+ * @param oval if this {@link RoundedImageView} should be oval.
+ */
+ public void setOval(boolean oval) {
+ mIsOval = oval;
+ updateDrawableAttrs();
+ updateBackgroundDrawableAttrs(false);
+ invalidate();
+ }
+
+ public Shader.TileMode getTileModeX() {
+ return mTileModeX;
+ }
+
+ public void setTileModeX(Shader.TileMode tileModeX) {
+ if (this.mTileModeX == tileModeX) { return; }
+
+ this.mTileModeX = tileModeX;
+ updateDrawableAttrs();
+ updateBackgroundDrawableAttrs(false);
+ invalidate();
+ }
+
+ public Shader.TileMode getTileModeY() {
+ return mTileModeY;
+ }
+
+ public void setTileModeY(Shader.TileMode tileModeY) {
+ if (this.mTileModeY == tileModeY) { return; }
+
+ this.mTileModeY = tileModeY;
+ updateDrawableAttrs();
+ updateBackgroundDrawableAttrs(false);
+ invalidate();
+ }
+
+ /**
+ * If {@code true}, we will also round the background drawable according to the settings on this
+ * ImageView.
+ *
+ * @return whether the background is mutated.
+ */
+ public boolean mutatesBackground() {
+ return mMutateBackground;
+ }
+
+ /**
+ * Set whether the {@link RoundedImageView} should round the background drawable according to
+ * the settings in addition to the source drawable.
+ *
+ * @param mutate true if this view should mutate the background drawable.
+ */
+ public void mutateBackground(boolean mutate) {
+ if (mMutateBackground == mutate) { return; }
+
+ mMutateBackground = mutate;
+ updateBackgroundDrawableAttrs(true);
+ invalidate();
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/ScrollingTextView.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/ScrollingTextView.java
new file mode 100644
index 0000000000..0ab1abb4fc
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/ScrollingTextView.java
@@ -0,0 +1,39 @@
+package com.mogo.module.media.widget;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+
+import androidx.appcompat.widget.AppCompatTextView;
+
+public class ScrollingTextView extends AppCompatTextView {
+ public ScrollingTextView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public ScrollingTextView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ScrollingTextView(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
+ if (focused)
+ super.onFocusChanged(focused, direction, previouslyFocusedRect);
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean focused) {
+ if (focused)
+ super.onWindowFocusChanged(focused);
+ }
+
+ @Override
+ public boolean isFocused() {
+ return true;
+ }
+}
+
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/BaseSurfaceView.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/BaseSurfaceView.java
new file mode 100644
index 0000000000..fd9ddfd6f1
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/BaseSurfaceView.java
@@ -0,0 +1,181 @@
+package com.mogo.module.media.widget.surfaceview;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.PixelFormat;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+public abstract class BaseSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
+ public static final int DEFAULT_FRAME_DURATION_MILLISECOND = 50;
+
+ private HandlerThread handlerThread;
+ private SurfaceViewHandler handler;
+ protected int frameDuration = DEFAULT_FRAME_DURATION_MILLISECOND;
+ private Canvas canvas;
+ private boolean isAlive;
+ public boolean pause = false;
+
+ public BaseSurfaceView(Context context) {
+ super(context);
+ init();
+ }
+
+ public BaseSurfaceView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public BaseSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init();
+ }
+
+ protected int getFrameDuration() {
+ return frameDuration;
+ }
+
+ protected void setFrameDuration(int frameDuration) {
+ this.frameDuration = frameDuration;
+ }
+
+ protected void init() {
+ getHolder().addCallback(this);
+ setBackgroundTransparent();
+ }
+
+ private void setBackgroundTransparent() {
+ setZOrderOnTop(false);
+ setZOrderMediaOverlay(true);
+ getHolder().setFormat(PixelFormat.TRANSLUCENT);
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ isAlive = true;
+ startDrawThread();
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ stopDrawThread();
+ isAlive = false;
+ }
+
+ public void stopDrawThread() {
+ handlerThread.quit();
+ handler.removeCallbacksAndMessages(null);
+ handler = null;
+ }
+
+ public void startDrawThread() {
+ handlerThread = new HandlerThread("SurfaceViewThread");
+ handlerThread.start();
+ handler = new SurfaceViewHandler(handlerThread.getLooper());
+ handler.post(new DrawRunnable());
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ int originWidth = getMeasuredWidth();
+ int originHeight = getMeasuredHeight();
+ int width = widthMode == MeasureSpec.AT_MOST ? getDefaultWidth() : originWidth;
+ int height = heightMode == MeasureSpec.AT_MOST ? getDefaultHeight() : originHeight;
+ setMeasuredDimension(width, height);
+ Log.v("ttaylor", "BaseSurfaceView.onMeasure()" + " default Width=" + getDefaultWidth() + " default height=" + getDefaultHeight());
+ }
+
+ /**
+ * the width is used when wrap_content is set to layout_width
+ * the child knows how big it should be
+ *
+ * @return
+ */
+ protected abstract int getDefaultWidth();
+
+ /**
+ * the height is used when wrap_content is set to layout_height
+ * the child knows how big it should be
+ *
+ * @return
+ */
+ protected abstract int getDefaultHeight();
+
+
+ private class SurfaceViewHandler extends Handler {
+
+ public SurfaceViewHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ }
+ }
+
+ private class DrawRunnable implements Runnable {
+
+ @Override
+ public void run() {
+ if (!isAlive) {
+ return;
+ }
+ try {
+ canvas = getHolder().lockCanvas();
+ onFrameDraw(canvas);
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ getHolder().unlockCanvasAndPost(canvas);
+ onFrameDrawFinish();
+ }
+
+ // TODO: 2019-05-08 stop the drawing thread
+ if (handler != null && !pause){
+ handler.postDelayed(this, frameDuration);
+ }
+
+ }
+ }
+
+ public void setPause(boolean pause){
+ this.pause = pause;
+ }
+
+ public boolean getPause(){
+ return this.pause;
+ }
+
+ public void reStartDrawRunnable(){
+ if (handler != null){
+ handler.post(new DrawRunnable());
+ }
+ }
+
+ /**
+ * it is will be invoked after one frame is drawn
+ */
+ protected abstract void onFrameDrawFinish();
+
+ /**
+ * draw one frame to the surface by canvas
+ *
+ * @param canvas
+ */
+ protected abstract void onFrameDraw(Canvas canvas);
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/BaseTextureView.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/BaseTextureView.java
new file mode 100644
index 0000000000..2a722748a8
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/BaseTextureView.java
@@ -0,0 +1,182 @@
+package com.mogo.module.media.widget.surfaceview;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.SurfaceTexture;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.TextureView;
+
+public abstract class BaseTextureView extends TextureView implements TextureView.SurfaceTextureListener {
+ public static final int DEFAULT_FRAME_DURATION_MILLISECOND = 50;
+
+ private HandlerThread handlerThread;
+ private SurfaceViewHandler handler;
+ protected int frameDuration = DEFAULT_FRAME_DURATION_MILLISECOND;
+ private Canvas canvas;
+ private boolean isAlive;
+ public boolean pause = false;
+
+ public BaseTextureView(Context context) {
+ super(context);
+ init();
+ }
+
+ public BaseTextureView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public BaseTextureView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init();
+ }
+
+ protected int getFrameDuration() {
+ return frameDuration;
+ }
+
+ protected void setFrameDuration(int frameDuration) {
+ this.frameDuration = frameDuration;
+ }
+
+ protected void init() {
+ setOpaque(false);//设置背景透明,记住这里是[是否不透明]
+ setSurfaceTextureListener(this);//设置监听
+ }
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+ //当TextureView初始化时调用
+ isAlive = true;
+ startDrawThread();
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+ //当TextureView的大小改变时调用
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+ //当TextureView被销毁时调用
+ stopDrawThread();
+ isAlive = false;
+ return true;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+ //当TextureView更新时调用,也就是当我们调用unlockCanvasAndPost方法时
+ }
+
+ public void stopDrawThread() {
+ handlerThread.quit();
+ handler.removeCallbacksAndMessages(null);
+ handler = null;
+ }
+
+ public void startDrawThread() {
+ handlerThread = new HandlerThread("SurfaceViewThread");
+ handlerThread.start();
+ handler = new SurfaceViewHandler(handlerThread.getLooper());
+ handler.post(new DrawRunnable());
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ int originWidth = getMeasuredWidth();
+ int originHeight = getMeasuredHeight();
+ int width = widthMode == MeasureSpec.AT_MOST ? getDefaultWidth() : originWidth;
+ int height = heightMode == MeasureSpec.AT_MOST ? getDefaultHeight() : originHeight;
+ setMeasuredDimension(width, height);
+ Log.v("ttaylor", "BaseSurfaceView.onMeasure()" + " default Width=" + getDefaultWidth() + " default height=" + getDefaultHeight());
+ }
+
+ /**
+ * the width is used when wrap_content is set to layout_width
+ * the child knows how big it should be
+ *
+ * @return
+ */
+ protected abstract int getDefaultWidth();
+
+ /**
+ * the height is used when wrap_content is set to layout_height
+ * the child knows how big it should be
+ *
+ * @return
+ */
+ protected abstract int getDefaultHeight();
+
+
+ private class SurfaceViewHandler extends Handler {
+
+ public SurfaceViewHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ }
+ }
+
+ private class DrawRunnable implements Runnable {
+
+ @Override
+ public void run() {
+ if (!isAlive) {
+ return;
+ }
+ try {
+ canvas = lockCanvas();
+ onFrameDraw(canvas);
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ unlockCanvasAndPost(canvas);
+ onFrameDrawFinish();
+ }
+
+ if (handler != null && !pause){
+ handler.postDelayed(this, frameDuration);
+ }
+
+ }
+ }
+
+ public void setPause(boolean pause){
+ this.pause = pause;
+ }
+
+ public boolean getPause(){
+ return this.pause;
+ }
+
+ public void reStartDrawRunnable(){
+ pause = false;
+ if (handler != null){
+ handler.post(new DrawRunnable());
+ }
+ }
+
+ /**
+ * it is will be invoked after one frame is drawn
+ */
+ protected abstract void onFrameDrawFinish();
+
+ /**
+ * draw one frame to the surface by canvas
+ *
+ * @param canvas
+ */
+ protected abstract void onFrameDraw(Canvas canvas);
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/FrameSurfaceView.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/FrameSurfaceView.java
new file mode 100644
index 0000000000..d2dc94e252
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/FrameSurfaceView.java
@@ -0,0 +1,396 @@
+package com.mogo.module.media.widget.surfaceview;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.util.AttributeSet;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * a SurfaceView which draws bitmaps one after another like frame animation
+ */
+public class FrameSurfaceView extends BaseSurfaceView {
+ public static final int INVALID_INDEX = Integer.MAX_VALUE;
+ private int bufferSize = 3;
+ public static final String DECODE_THREAD_NAME = "DecodingThread";
+ public static final int INFINITE = -1;
+ //-1 means repeat infinitely
+ private int repeatTimes;
+ private int repeatedCount;
+
+ /**
+ * the resources of frame animation
+ */
+ private List bitmapIds = new ArrayList<>();
+ /**
+ * the index of bitmap resource which is decoding
+ */
+ private int bitmapIdIndex;
+ /**
+ * the index of frame which is drawing
+ */
+ private int frameIndex = INVALID_INDEX;
+ /**
+ * decoded bitmaps stores in this queue
+ * consumer is drawing thread, producer is decoding thread.
+ */
+ private LinkedBlockingQueue decodedBitmaps = new LinkedBlockingQueue(bufferSize);
+ /**
+ * bitmaps already drawn by canvas stores in this queue
+ * consumer is decoding thread, producer is drawing thread.
+ */
+ private LinkedBlockingQueue drawnBitmaps = new LinkedBlockingQueue(bufferSize);
+ /**
+ * the thread for decoding bitmaps
+ */
+ private HandlerThread decodeThread;
+ /**
+ * the Runnable describes how to decode one bitmap
+ */
+ private DecodeRunnable decodeRunnable;
+ /**
+ * this handler helps to decode bitmap one after another
+ */
+ private Handler handler;
+ private BitmapFactory.Options options;
+ private Paint paint = new Paint();
+ private Rect srcRect;
+ private Rect dstRect = new Rect();
+ private int defaultWidth;
+ private int defaultHeight;
+
+ public FrameSurfaceView(Context context) {
+ super(context);
+ }
+
+ public FrameSurfaceView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public FrameSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public void setRepeatTimes(int repeatTimes) {
+ this.repeatTimes = repeatTimes;
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ options = new BitmapFactory.Options();
+ options.inMutable = true;
+ decodeThread = new HandlerThread(DECODE_THREAD_NAME);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ dstRect.set(0, 0, getWidth(), getHeight());
+ }
+
+ @Override
+ protected int getDefaultWidth() {
+ return defaultWidth;
+ }
+
+ @Override
+ protected int getDefaultHeight() {
+ return defaultHeight;
+ }
+
+ @Override
+ protected void onFrameDrawFinish() {
+ }
+
+ /**
+ * set the duration of frame animation
+ *
+ * @param duration time in milliseconds
+ */
+ public void setDuration(int duration) {
+ int frameDuration = duration / bitmapIds.size();
+ setFrameDuration(frameDuration);
+ }
+
+ /**
+ * set the materials of frame animation which is an array of bitmap resource id
+ *
+ * @param bitmapIds an array of bitmap resource id
+ */
+ public void setBitmapIds(List bitmapIds) {
+ if (bitmapIds == null || bitmapIds.size() == 0) {
+ return;
+ }
+ this.bitmapIds = bitmapIds;
+ //by default, take the first bitmap's dimension into consideration
+ getBitmapDimension(bitmapIds.get(bitmapIdIndex));
+ preloadFrames();
+ decodeRunnable = new DecodeRunnable(bitmapIdIndex, bitmapIds, options);
+ }
+
+ private void getBitmapDimension(int bitmapId) {
+ final BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeResource(this.getResources(), bitmapId, options);
+ defaultWidth = options.outWidth;
+ defaultHeight = options.outHeight;
+ srcRect = new Rect(0, 0, defaultWidth, defaultHeight);
+ //we have to re-measure to make defaultWidth in use in onMeasure()
+ requestLayout();
+ }
+
+ /**
+ * load the first several frames of animation before it is started
+ */
+ private void preloadFrames() {
+ putDecodedBitmap(bitmapIds.get(bitmapIdIndex++), options, new LinkedBitmap());
+ putDecodedBitmap(bitmapIds.get(bitmapIdIndex++), options, new LinkedBitmap());
+ }
+
+ /**
+ * recycle the bitmap used by frame animation.
+ * Usually it should be invoked when the ui of frame animation is no longer visible
+ */
+ public void destroy() {
+ if (drawnBitmaps != null) {
+ drawnBitmaps.clear();
+ }
+ if (decodeThread != null) {
+ decodeThread.quit();
+ decodeThread = null;
+ }
+ if (handler != null) {
+ handler = null;
+ }
+ }
+
+ @Override
+ protected void onFrameDraw(Canvas canvas) {
+ clearCanvas(canvas);
+ if (!isStart()) {
+ return;
+ }
+ if (!isFinish()) {
+ drawOneFrame(canvas);
+ } else {
+ onFrameAnimationEnd();
+ if (repeatTimes != 0 && repeatTimes == INFINITE) {
+ start();
+ } else if (repeatedCount < repeatTimes) {
+ start();
+ repeatedCount++;
+ } else {
+ repeatedCount = 0;
+ }
+ }
+ }
+
+ /**
+ * draw a single frame which is a bitmap
+ *
+ * @param canvas
+ */
+ private void drawOneFrame(Canvas canvas) {
+ try {
+ LinkedBitmap linkedBitmap = getDecodedBitmap();
+ if (linkedBitmap != null) {
+ canvas.drawBitmap(linkedBitmap.bitmap, srcRect, dstRect, paint);
+ }
+ putDrawnBitmap(linkedBitmap);
+ frameIndex++;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * invoked when frame animation is done
+ */
+ private void onFrameAnimationEnd() {
+ reset();
+ }
+
+ /**
+ * reset the index of frame, preparing for the next frame animation
+ */
+ private void reset() {
+ frameIndex = INVALID_INDEX;
+ }
+
+ /**
+ * whether frame animation is finished
+ *
+ * @return true: animation is finished, false: animation is doing
+ */
+ private boolean isFinish() {
+ return frameIndex >= bitmapIds.size() - 1;
+ }
+
+ /**
+ * whether frame animation is started
+ *
+ * @return true: animation is started, false: animation is not started
+ */
+ private boolean isStart() {
+ return frameIndex != INVALID_INDEX;
+ }
+
+ /**
+ * start frame animation from the first frame
+ */
+ public void start() {
+ frameIndex = 0;
+ if (decodeThread == null) {
+ decodeThread = new HandlerThread(DECODE_THREAD_NAME);
+ }
+ if (!decodeThread.isAlive()) {
+ decodeThread.start();
+ }
+ if (handler == null) {
+ handler = new Handler(decodeThread.getLooper());
+ }
+ if (decodeRunnable != null) {
+ decodeRunnable.setIndex(0);
+ }
+ handler.post(decodeRunnable);
+ }
+
+ public void pause(){
+ setPause(true);
+ }
+
+ public void start(boolean restart){
+ if (restart){
+ if (frameIndex == INVALID_INDEX ){
+ start();
+ }else{
+ if (getPause()){
+ setPause(false);
+ reStartDrawRunnable();
+ }else{
+ start();
+ }
+ }
+ }else{
+ start();
+ }
+ }
+
+ /**
+ * clear out the drawing on canvas,preparing for the next frame
+ * * @param canvas
+ */
+ private void clearCanvas(Canvas canvas) {
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+ canvas.drawPaint(paint);
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
+ }
+
+ /**
+ * decode bitmap by BitmapFactory.decodeStream(), it is about twice faster than BitmapFactory.decodeResource()
+ *
+ * @param resId the bitmap resource
+ * @param options
+ * @return
+ */
+ private Bitmap decodeBitmap(int resId, BitmapFactory.Options options) {
+ options.inScaled = false;
+ InputStream inputStream = getResources().openRawResource(resId);
+ return BitmapFactory.decodeStream(inputStream, null, options);
+ }
+
+ private void putDecodedBitmapByReuse(int resId, BitmapFactory.Options options) {
+ LinkedBitmap linkedBitmap = getDrawnBitmap();
+ if (linkedBitmap == null) {
+ linkedBitmap = new LinkedBitmap();
+ }
+ options.inBitmap = linkedBitmap.bitmap;
+ putDecodedBitmap(resId, options, linkedBitmap);
+ }
+
+ private void putDecodedBitmap(int resId, BitmapFactory.Options options, LinkedBitmap linkedBitmap) {
+ Bitmap bitmap = decodeBitmap(resId, options);
+ linkedBitmap.bitmap = bitmap;
+ try {
+ decodedBitmaps.put(linkedBitmap);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void putDrawnBitmap(LinkedBitmap bitmap) {
+ if (bitmap == null)return;
+ drawnBitmaps.offer(bitmap);
+ }
+
+ /**
+ * get bitmap which already drawn by canvas
+ *
+ * @return
+ */
+ private LinkedBitmap getDrawnBitmap() {
+ LinkedBitmap bitmap = null;
+ try {
+ bitmap = drawnBitmaps.take();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ return bitmap;
+ }
+
+ /**
+ * get decoded bitmap in the decoded bitmap queue
+ * it might block due to new bitmap is not ready
+ *
+ * @return
+ */
+ private LinkedBitmap getDecodedBitmap() {
+ LinkedBitmap bitmap = null;
+ try {
+ bitmap = decodedBitmaps.take();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ return bitmap;
+ }
+
+ private class DecodeRunnable implements Runnable {
+
+ private int index;
+ private List bitmapIds;
+ private BitmapFactory.Options options;
+
+ public DecodeRunnable(int index, List bitmapIds, BitmapFactory.Options options) {
+ this.index = index;
+ this.bitmapIds = bitmapIds;
+ this.options = options;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ }
+
+ @Override
+ public void run() {
+ putDecodedBitmapByReuse(bitmapIds.get(index), options);
+ index++;
+ if (index < bitmapIds.size()) {
+ handler.post(this);
+ } else {
+ index = 0;
+ }
+ }
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/FrameTextureView.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/FrameTextureView.java
new file mode 100644
index 0000000000..9af3fda6fa
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/FrameTextureView.java
@@ -0,0 +1,386 @@
+package com.mogo.module.media.widget.surfaceview;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.util.AttributeSet;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * a SurfaceView which draws bitmaps one after another like frame animation
+ */
+public class FrameTextureView extends BaseTextureView {
+ public static final int INVALID_INDEX = Integer.MAX_VALUE;
+ private int bufferSize = 3;
+ public static final String DECODE_THREAD_NAME = "DecodingThread";
+ public static final int INFINITE = -1;
+ //-1 means repeat infinitely
+ private int repeatTimes;
+ private int repeatedCount;
+
+ /**
+ * the resources of frame animation
+ */
+ private List bitmapIds = new ArrayList<>();
+ /**
+ * the index of bitmap resource which is decoding
+ */
+ private int bitmapIdIndex;
+ /**
+ * the index of frame which is drawing
+ */
+ private int frameIndex = INVALID_INDEX;
+ /**
+ * decoded bitmaps stores in this queue
+ * consumer is drawing thread, producer is decoding thread.
+ */
+ private LinkedBlockingQueue decodedBitmaps = new LinkedBlockingQueue(bufferSize);
+ /**
+ * bitmaps already drawn by canvas stores in this queue
+ * consumer is decoding thread, producer is drawing thread.
+ */
+ private LinkedBlockingQueue drawnBitmaps = new LinkedBlockingQueue(bufferSize);
+ /**
+ * the thread for decoding bitmaps
+ */
+ private HandlerThread decodeThread;
+ /**
+ * the Runnable describes how to decode one bitmap
+ */
+ private DecodeRunnable decodeRunnable;
+ /**
+ * this handler helps to decode bitmap one after another
+ */
+ private Handler handler;
+ private BitmapFactory.Options options;
+ private Paint paint = new Paint();
+ private Rect srcRect;
+ private Rect dstRect = new Rect();
+ private int defaultWidth;
+ private int defaultHeight;
+
+ public FrameTextureView(Context context) {
+ super(context);
+ }
+
+ public FrameTextureView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public FrameTextureView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public void setRepeatTimes(int repeatTimes) {
+ this.repeatTimes = repeatTimes;
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ options = new BitmapFactory.Options();
+ options.inMutable = true;
+ decodeThread = new HandlerThread(DECODE_THREAD_NAME);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ dstRect.set(0, 0, getWidth(), getHeight());
+ }
+
+ @Override
+ protected int getDefaultWidth() {
+ return defaultWidth;
+ }
+
+ @Override
+ protected int getDefaultHeight() {
+ return defaultHeight;
+ }
+
+ @Override
+ protected void onFrameDrawFinish() {
+ }
+
+ /**
+ * set the duration of frame animation
+ *
+ * @param duration time in milliseconds
+ */
+ public void setDuration(int duration) {
+ int frameDuration = duration / bitmapIds.size();
+ setFrameDuration(frameDuration);
+ }
+
+ /**
+ * set the materials of frame animation which is an array of bitmap resource id
+ *
+ * @param bitmapIds an array of bitmap resource id
+ */
+ public void setBitmapIds(List bitmapIds) {
+ if (bitmapIds == null || bitmapIds.size() == 0) {
+ return;
+ }
+ this.bitmapIds = bitmapIds;
+ //by default, take the first bitmap's dimension into consideration
+ getBitmapDimension(bitmapIds.get(bitmapIdIndex));
+ preloadFrames();
+ decodeRunnable = new DecodeRunnable(bitmapIdIndex, bitmapIds, options);
+ }
+
+ private void getBitmapDimension(int bitmapId) {
+ final BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeResource(this.getResources(), bitmapId, options);
+ defaultWidth = options.outWidth;
+ defaultHeight = options.outHeight;
+ srcRect = new Rect(0, 0, defaultWidth, defaultHeight);
+ //we have to re-measure to make defaultWidth in use in onMeasure()
+ requestLayout();
+ }
+
+ /**
+ * load the first several frames of animation before it is started
+ */
+ private void preloadFrames() {
+ putDecodedBitmap(bitmapIds.get(bitmapIdIndex++), options, new LinkedBitmap());
+ putDecodedBitmap(bitmapIds.get(bitmapIdIndex++), options, new LinkedBitmap());
+ }
+
+ /**
+ * recycle the bitmap used by frame animation.
+ * Usually it should be invoked when the ui of frame animation is no longer visible
+ */
+ public void destroy() {
+ if (drawnBitmaps != null) {
+ drawnBitmaps.clear();
+ }
+ if (decodeThread != null) {
+ decodeThread.quit();
+ decodeThread = null;
+ }
+ if (handler != null) {
+ handler = null;
+ }
+ }
+
+ @Override
+ protected void onFrameDraw(Canvas canvas) {
+ clearCanvas(canvas);
+ if (!isStart()) {
+ return;
+ }
+ if (!isFinish()) {
+ drawOneFrame(canvas);
+ } else {
+ onFrameAnimationEnd();
+ if (repeatTimes != 0 && repeatTimes == INFINITE) {
+ start();
+ } else if (repeatedCount < repeatTimes) {
+ start();
+ repeatedCount++;
+ } else {
+ repeatedCount = 0;
+ }
+ }
+ }
+
+ /**
+ * draw a single frame which is a bitmap
+ *
+ * @param canvas
+ */
+ private void drawOneFrame(Canvas canvas) {
+ LinkedBitmap linkedBitmap = getDecodedBitmap();
+ if (linkedBitmap != null) {
+ canvas.drawBitmap(linkedBitmap.bitmap, srcRect, dstRect, paint);
+ }
+ putDrawnBitmap(linkedBitmap);
+ frameIndex++;
+ }
+
+ /**
+ * invoked when frame animation is done
+ */
+ private void onFrameAnimationEnd() {
+ reset();
+ }
+
+ /**
+ * reset the index of frame, preparing for the next frame animation
+ */
+ private void reset() {
+ frameIndex = INVALID_INDEX;
+ }
+
+ /**
+ * whether frame animation is finished
+ *
+ * @return true: animation is finished, false: animation is doing
+ */
+ private boolean isFinish() {
+ return frameIndex >= bitmapIds.size() - 1;
+ }
+
+ /**
+ * whether frame animation is started
+ *
+ * @return true: animation is started, false: animation is not started
+ */
+ private boolean isStart() {
+ return frameIndex != INVALID_INDEX;
+ }
+
+ /**
+ * start frame animation from the first frame
+ */
+ public void start() {
+ pause = false;
+ frameIndex = 0;
+ if (decodeThread == null) {
+ decodeThread = new HandlerThread(DECODE_THREAD_NAME);
+ }
+ if (!decodeThread.isAlive()) {
+ decodeThread.start();
+ }
+ if (handler == null) {
+ handler = new Handler(decodeThread.getLooper());
+ }
+ if (decodeRunnable != null) {
+ decodeRunnable.setIndex(0);
+ }
+ handler.post(decodeRunnable);
+ }
+
+ public void pause(){
+ setPause(true);
+ }
+
+ public void start(boolean restart){
+ if (restart){
+ if (!isStart() || !getPause()){
+ start();
+ }else{
+ reStartDrawRunnable();
+ }
+ }else{
+ start();
+ }
+ }
+
+ /**
+ * clear out the drawing on canvas,preparing for the next frame
+ * * @param canvas
+ */
+ private void clearCanvas(Canvas canvas) {
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+ canvas.drawPaint(paint);
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
+ }
+
+ /**
+ * decode bitmap by BitmapFactory.decodeStream(), it is about twice faster than BitmapFactory.decodeResource()
+ *
+ * @param resId the bitmap resource
+ * @param options
+ * @return
+ */
+ private Bitmap decodeBitmap(int resId, BitmapFactory.Options options) {
+ options.inScaled = false;
+ InputStream inputStream = getResources().openRawResource(resId);
+ return BitmapFactory.decodeStream(inputStream, null, options);
+ }
+
+ private void putDecodedBitmapByReuse(int resId, BitmapFactory.Options options) {
+ LinkedBitmap linkedBitmap = getDrawnBitmap();
+ if (linkedBitmap == null) {
+ linkedBitmap = new LinkedBitmap();
+ }
+ options.inBitmap = linkedBitmap.bitmap;
+ putDecodedBitmap(resId, options, linkedBitmap);
+ }
+
+ private void putDecodedBitmap(int resId, BitmapFactory.Options options, LinkedBitmap linkedBitmap) {
+ Bitmap bitmap = decodeBitmap(resId, options);
+ linkedBitmap.bitmap = bitmap;
+ try {
+ decodedBitmaps.put(linkedBitmap);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void putDrawnBitmap(LinkedBitmap bitmap) {
+ drawnBitmaps.offer(bitmap);
+ }
+
+ /**
+ * get bitmap which already drawn by canvas
+ *
+ * @return
+ */
+ private LinkedBitmap getDrawnBitmap() {
+ LinkedBitmap bitmap = null;
+ try {
+ bitmap = drawnBitmaps.take();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ return bitmap;
+ }
+
+ /**
+ * get decoded bitmap in the decoded bitmap queue
+ * it might block due to new bitmap is not ready
+ *
+ * @return
+ */
+ private LinkedBitmap getDecodedBitmap() {
+ LinkedBitmap bitmap = null;
+ try {
+ bitmap = decodedBitmaps.take();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ return bitmap;
+ }
+
+ private class DecodeRunnable implements Runnable {
+
+ private int index;
+ private List bitmapIds;
+ private BitmapFactory.Options options;
+
+ public DecodeRunnable(int index, List bitmapIds, BitmapFactory.Options options) {
+ this.index = index;
+ this.bitmapIds = bitmapIds;
+ this.options = options;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ }
+
+ @Override
+ public void run() {
+ putDecodedBitmapByReuse(bitmapIds.get(index), options);
+ index++;
+ if (index < bitmapIds.size()) {
+ handler.post(this);
+ } else {
+ index = 0;
+ }
+ }
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/LinkedBitmap.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/LinkedBitmap.java
new file mode 100644
index 0000000000..0b0f4c4491
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/LinkedBitmap.java
@@ -0,0 +1,9 @@
+package com.mogo.module.media.widget.surfaceview;
+
+import android.graphics.Bitmap;
+
+public class LinkedBitmap {
+ public Bitmap bitmap;
+ public LinkedBitmap next;
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/LinkedBlockingQueue.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/LinkedBlockingQueue.java
new file mode 100644
index 0000000000..dc8b26a1d1
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/LinkedBlockingQueue.java
@@ -0,0 +1,199 @@
+package com.mogo.module.media.widget.surfaceview;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class LinkedBlockingQueue {
+ /**
+ * Current number of elements
+ */
+ private final AtomicInteger count = new AtomicInteger();
+ /**
+ * Lock held by take, poll, etc
+ */
+ private final ReentrantLock takeLock = new ReentrantLock();
+
+ /**
+ * Wait queue for waiting takes
+ */
+ private final Condition notEmpty = takeLock.newCondition();
+
+ /**
+ * Lock held by put, offer, etc
+ */
+ private final ReentrantLock putLock = new ReentrantLock();
+
+ /**
+ * Wait queue for waiting puts
+ */
+ private final Condition notFull = putLock.newCondition();
+ /**
+ * The capacity bound, or Integer.MAX_VALUE if none
+ */
+ private final int capacity;
+ /**
+ * the first element in the queue
+ */
+ private LinkedBitmap head;
+ /**
+ * the last element int the queue
+ */
+ private LinkedBitmap tail;
+
+
+ public LinkedBlockingQueue(int capacity) {
+ if (capacity <= 0) throw new IllegalArgumentException();
+ this.capacity = capacity;
+ }
+
+ public void put(LinkedBitmap bitmap) throws InterruptedException {
+ if (bitmap == null) throw new NullPointerException();
+ // Note: convention in all put/take/etc is to preset local var
+ // holding count negative to indicate failure unless set.
+ int c = -1;
+ final ReentrantLock putLock = this.putLock;
+ final AtomicInteger count = this.count;
+ putLock.lockInterruptibly();
+ try {
+ /*
+ * Note that count is used in wait guard even though it is
+ * not protected by lock. This works because count can
+ * only decrease at this point (all other puts are shut
+ * out by lock), and we (or some other waiting put) are
+ * signalled if it ever changes from capacity. Similarly
+ * for all other uses of count in other wait guards.
+ */
+ while (count.get() == capacity) {
+ notFull.await();
+ }
+ enqueue(bitmap);
+ c = count.getAndIncrement();
+ if (c + 1 < capacity)
+ notFull.signal();
+ } finally {
+ putLock.unlock();
+ }
+ if (c == 0)
+ signalNotEmpty();
+ }
+
+ public boolean offer(LinkedBitmap bitmap) {
+ if (bitmap == null) throw new NullPointerException();
+ final AtomicInteger count = this.count;
+ if (count.get() == capacity)
+ return false;
+ int c = -1;
+ final ReentrantLock putLock = this.putLock;
+ putLock.lock();
+ try {
+ if (count.get() < capacity) {
+ enqueue(bitmap);
+ c = count.getAndIncrement();
+ if (c + 1 < capacity)
+ notFull.signal();
+ }
+ } finally {
+ putLock.unlock();
+ }
+ if (c == 0)
+ signalNotEmpty();
+ return c >= 0;
+ }
+
+ public LinkedBitmap take() throws InterruptedException {
+ LinkedBitmap x;
+ int c = -1;
+ final AtomicInteger count = this.count;
+ final ReentrantLock takeLock = this.takeLock;
+ takeLock.lockInterruptibly();
+ try {
+ while (count.get() == 0) {
+ notEmpty.await();
+ }
+ x = dequeue();
+ c = count.getAndDecrement();
+ if (c > 1)
+ notEmpty.signal();
+ } finally {
+ takeLock.unlock();
+ }
+ if (c == capacity)
+ signalNotFull();
+ return x;
+ }
+
+ /**
+ * insert element into the end of queue
+ *
+ * @param bitmap
+ */
+ private void enqueue(LinkedBitmap bitmap) {
+ if (head == null) {
+ head = bitmap;
+ tail = bitmap;
+ bitmap.next = null;
+ } else {
+ tail.next = bitmap;
+ bitmap.next = null;
+ }
+ }
+
+ /**
+ * get and remove the first element of the queue
+ *
+ * @return
+ */
+ private LinkedBitmap dequeue() {
+ LinkedBitmap p = head;
+ if (p == null) {
+ return null;
+ } else {
+ head = head.next;
+ }
+ return p;
+ }
+
+ /**
+ * Signals a waiting take. Called only from put/offer (which do not
+ * otherwise ordinarily lock takeLock.)
+ */
+ private void signalNotEmpty() {
+ final ReentrantLock takeLock = this.takeLock;
+ takeLock.lock();
+ try {
+ notEmpty.signal();
+ } finally {
+ takeLock.unlock();
+ }
+ }
+
+ /**
+ * Signals a waiting put. Called only from take/poll.
+ */
+ private void signalNotFull() {
+ final ReentrantLock putLock = this.putLock;
+ putLock.lock();
+ try {
+ notFull.signal();
+ } finally {
+ putLock.unlock();
+ }
+ }
+
+ /**
+ * recycle the bitmaps one by one
+ */
+ public void clear() {
+ LinkedBitmap p = head;
+ if (p == null) {
+ return;
+ }
+ while (p != null) {
+ if (p.bitmap != null) {
+ p.bitmap.recycle();
+ }
+ p.bitmap = null;
+ p = p.next;
+ }
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/MethodUtil.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/MethodUtil.java
new file mode 100644
index 0000000000..7ccb9dae6b
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/MethodUtil.java
@@ -0,0 +1,22 @@
+package com.mogo.module.media.widget.surfaceview;
+
+import android.os.SystemClock;
+import android.util.Log;
+
+public class MethodUtil {
+
+ /**
+ * calculate the time consumed by runnable invocation, print log in millisecond
+ *
+ * @param runnable
+ */
+ public static long time(Runnable runnable) {
+ long start = SystemClock.elapsedRealtime();
+ runnable.run();
+ long end = SystemClock.elapsedRealtime();
+ long span = end - start;
+ Log.v("ttaylor", "MethodUtil.time()" + " time span = " + span + " ms");
+ return span;
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/NumberUtil.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/NumberUtil.java
new file mode 100644
index 0000000000..a4e8fc0b7d
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/widget/surfaceview/NumberUtil.java
@@ -0,0 +1,32 @@
+package com.mogo.module.media.widget.surfaceview;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+public class NumberUtil {
+
+ private static long total;
+ private static int times;
+
+ private static String tag;
+
+ /**
+ * calculate the average of a series long number and print it
+ * @param tag
+ * @param l
+ */
+ public static void average(String tag, Long l) {
+ if (!TextUtils.isEmpty(tag) && !tag.equals(NumberUtil.tag)) {
+ reset();
+ NumberUtil.tag = tag;
+ }
+ times++;
+ total += l;
+ Log.v("ttaylor", "Average.average() " + NumberUtil.tag + " average = " + (total / times));
+ }
+
+ private static void reset() {
+ total = 0;
+ times = 0;
+ }
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/window/MediaWindow.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/window/MediaWindow.java
new file mode 100644
index 0000000000..2099f36f8f
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/window/MediaWindow.java
@@ -0,0 +1,662 @@
+package com.mogo.module.media.window;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import com.mogo.map.marker.IMogoMarker;
+import com.mogo.module.common.entity.MarkerShareMusic;
+import com.mogo.module.common.entity.MarkerShowEntity;
+import com.mogo.module.media.MediaConstants;
+import com.mogo.module.media.R;
+import com.mogo.module.media.ServiceMediaHandler;
+import com.mogo.module.media.constants.LeTingFieldConstants;
+import com.mogo.module.media.constants.QQMusicFieldConstants;
+import com.mogo.module.media.listener.NoDoubleClickListener;
+import com.mogo.module.media.model.LanRenInsertData;
+import com.mogo.module.media.model.LeTingNewsData;
+import com.mogo.module.media.model.MediaInfoData;
+import com.mogo.module.media.model.ShareLikeData;
+import com.mogo.module.media.presenter.MediaPresenter;
+import com.mogo.module.media.receiver.MediaSpeechReceiver;
+import com.mogo.module.media.utils.MusicControlBroadCast;
+import com.mogo.module.media.utils.StorageManager;
+import com.mogo.module.media.utils.Utils;
+import com.mogo.module.media.view.MediaView;
+import com.mogo.module.media.widget.AnimCircleImageView;
+import com.mogo.utils.ActivityLifecycleManager;
+import com.mogo.utils.ThreadPoolService;
+import com.mogo.utils.UiThreadHandler;
+import com.mogo.utils.glide.GlideApp;
+import com.mogo.utils.logger.Logger;
+import com.mogo.utils.network.utils.GsonUtil;
+
+import java.util.List;
+
+public class MediaWindow implements MediaView{
+
+ public static final String TAG = MediaWindow.class.getName();
+ private Context mContext;
+ private MediaPresenter mPresenter;
+
+ private MediaWindow.MediaStateReceiver mediaStateReceiver;
+ private MediaWindow.MediaProcessReceiver mediaProcessReceiver;
+ private MediaWindow.PlayingMusicReceiver playingMusicReceiver;
+ private MediaWindow.MediaNewsPayInfo mediaNewsPayInfo;
+ private MediaInfoData mMediaInfoData;
+
+ private View mWindowView;
+ private AnimCircleImageView mCircleImg;
+ private TextView mScrollText;
+ private ImageView mWindowPlayPause;
+ private ImageView mWindowPlayNext;
+ private TextView mWindowCurrTime;
+ private TextView mWindowMaxTime;
+ private SeekBar mWindowProgress;
+
+ private boolean mHasAddWindow = false;
+ private boolean mTwoChange = false;
+ private boolean isFirstPlay = false;
+
+ private Runnable mRunnable = MusicControlBroadCast::sendGetMusicPlayStateBroadcast;
+
+ public void initMedia(Context context){
+ mContext = context;
+ mPresenter = new MediaPresenter(this);
+ registerMediaReceiver();
+
+ MediaInfoData sMediaInfoData = MusicControlBroadCast.getHisMedia();
+ mMediaInfoData = sMediaInfoData;
+
+ if (mMediaInfoData != null && !mHasAddWindow){
+ addWindowView();
+ }
+
+ //发送消息 如果在播放就会返回状态进行更新
+ UiThreadHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ MusicControlBroadCast.sendGetMusicPlayStateBroadcast();
+ }
+ },300);
+
+ isFirstPlay = true;
+
+ }
+
+
+ private void addWindowView() {
+ if (ServiceMediaHandler.getMogoWindowManager() == null){
+ return ;
+ }
+
+ if (!mHasAddWindow) {
+ mHasAddWindow = true;
+ mWindowView = LayoutInflater.from(mContext).inflate(R.layout.module_media_music_window_alert_layout, null);
+ mWindowView.setVisibility(View.VISIBLE);
+ mCircleImg = mWindowView.findViewById(R.id.window_circle_img);
+ mScrollText = mWindowView.findViewById(R.id.window_scroll_txt);
+ mWindowPlayPause = mWindowView.findViewById(R.id.window_play_pause);
+ mWindowPlayNext = mWindowView.findViewById(R.id.window_music_next);
+ mWindowCurrTime = mWindowView.findViewById(R.id.window_current_time);
+ mWindowMaxTime = mWindowView.findViewById(R.id.window_max_time);
+ mWindowProgress = mWindowView.findViewById(R.id.window_progress_bar);
+ if (mWindowPlayPause != null){
+ mWindowPlayPause.setImageResource(R.drawable.module_media_window_pop_pause);
+ }
+ int yPos = getContext().getResources().getDimensionPixelOffset(R.dimen.module_media_music_state_location);
+ int xPos = getContext().getResources().getDimensionPixelOffset(R.dimen.module_media_music_state_location_x);
+ ServiceMediaHandler.getMogoWindowManager().addView( mWindowView, xPos, yPos, false);
+ updateWindowUI(true);
+ mWindowView.setOnClickListener(new NoDoubleClickListener() {
+ @Override
+ public void onClicks(View view) {
+ if (mMediaInfoData != null) {
+ MusicControlBroadCast.openMediaApp(mMediaInfoData.getType());
+ } else {
+ MusicControlBroadCast.openMediaApp(1);
+ }
+ }
+ });
+
+ mWindowPlayPause.setOnClickListener(new NoDoubleClickListener() {
+ @Override
+ public void onClicks(View view) {
+ if (isFirstPlay){
+ if (mMediaInfoData != null){
+ MusicControlBroadCast.listeningSendData(mMediaInfoData);
+ }
+ }else{
+ if (mMediaInfoData != null) {
+ MusicControlBroadCast.commandPlayPause(mMediaInfoData.getType(),mMediaInfoData.getPlayState());
+ }
+ }
+ }
+ });
+
+ mWindowPlayNext.setOnClickListener(new NoDoubleClickListener() {
+ @Override
+ public void onClicks(View view) {
+ if (mMediaInfoData != null) {
+ MusicControlBroadCast.commandNext(mMediaInfoData.getType());
+ }
+ }
+ });
+ }
+ }
+
+ private void updateWindowUI(){
+ updateWindowUI(false);
+ }
+
+ private void updateWindowUI(boolean first) {
+ if (mWindowView == null || mMediaInfoData == null){
+ return;
+ }
+ if (mMediaInfoData != null) {
+ if (mMediaInfoData.getType() == 1 || mMediaInfoData.getType() == 2 || mMediaInfoData.getType() == 3) {
+ mWindowView.setVisibility(View.VISIBLE);
+ }
+ } else {
+ mWindowView.setVisibility(View.GONE);
+ }
+
+ if (mScrollText != null){
+ mScrollText.setText(mMediaInfoData.getMediaName());
+ }
+
+ if (first || mMediaInfoData.getPlayState() == 1 || mMediaInfoData.getPlayState() == 2) {
+ if (mWindowMaxTime != null){
+ mWindowMaxTime.setText(Utils.calculateTime((int) mMediaInfoData.getMaxTime()));
+ }
+ if (mWindowCurrTime != null){
+ mWindowCurrTime.setText(Utils.calculateTime((int) mMediaInfoData.getCurTime()));
+ }
+ }
+
+ if (mCircleImg != null){
+ com.bumptech.glide.request.RequestOptions options = new com.bumptech.glide.request.RequestOptions()
+ .placeholder(R.drawable.module_media_share_default_icon);
+ GlideApp.with(mContext).applyDefaultRequestOptions(options).load(mMediaInfoData.getMediaImg()).into(mCircleImg);
+ }
+
+ }
+
+ @Override
+ public void showSharePush(boolean show) {
+
+ }
+
+ @Override
+ public void loadNearShareMusicSuccess(List list) {
+
+ }
+
+ @Override
+ public void loadFriendShareMusicSuccess(List list) {
+
+ }
+
+ @Override
+ public void loadShareLikeDataResultSuccess(ShareLikeData.ShareLikeDataResult likeDataResult, String mediaId) {
+
+ }
+
+ @Override
+ public void likeShareSuccess() {
+
+ }
+
+ @Override
+ public void shareSuccessResult(boolean success, MarkerShareMusic markerShareMusic) {
+
+ }
+
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+
+ private class PlayingMusicReceiver extends BroadcastReceiver{
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ try {
+ if (intent != null){
+ String mediaStr = intent.getStringExtra("mediaData");
+ if (!TextUtils.isEmpty(mediaStr)){
+ MediaInfoData data = (MediaInfoData) GsonUtil.arrayFromJson(mediaStr, MediaInfoData.class);
+ if (data != null){
+ MusicControlBroadCast.listeningSendData(data);
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * 音频播放状态改变广播监听
+ */
+ private class MediaStateReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ //用于请求点赞数
+ boolean change = false;
+ boolean cancleChoose = false;
+ String ttMid = "";
+ if (intent != null) {
+ int type = intent.getIntExtra("type", -1);
+ int playState = intent.getIntExtra(QQMusicFieldConstants.playState, 0);
+ Logger.d("MediaStateReceiver", "===MediaStateReceiver==playState=="+playState+" type= "+type);
+ if (playState == 1) {
+ isFirstPlay = false;
+
+ if (mWindowPlayPause != null){
+ mWindowPlayPause.setImageResource(R.drawable.module_media_window_pop_play);
+ }
+
+ if (mCircleImg != null){
+ mCircleImg.startAnim();
+ }
+
+ } else {
+ if (mWindowPlayPause != null){
+ mWindowPlayPause.setImageResource(R.drawable.module_media_window_pop_pause);
+ }
+
+
+ if (mCircleImg != null){
+ mCircleImg.stopAnim();
+ }
+
+ if (type == 1 || type == 2 || type ==3){
+ UiThreadHandler.removeCallbacks(mRunnable);
+ UiThreadHandler.postDelayed(mRunnable,3000);
+ }
+
+ }
+
+ if (playState == 1 || playState == 2){
+ if (type == 1) {//qq音乐
+
+ int maxTime = intent.getIntExtra(QQMusicFieldConstants.maxTime, 0);
+ int curTime = intent.getIntExtra(QQMusicFieldConstants.curTime, 0);
+ String mediaName = intent.getStringExtra(QQMusicFieldConstants.mediaName);
+ String mediaUrl = intent.getStringExtra(QQMusicFieldConstants.mediaUrl);
+ String mediaSinger = intent.getStringExtra(QQMusicFieldConstants.mediaSinger);
+ String mediaImgUrl = intent.getStringExtra(QQMusicFieldConstants.mediaImgUrl);
+ String mediaType = intent.getStringExtra(QQMusicFieldConstants.mediaType);
+ String mediaMid = intent.getStringExtra(QQMusicFieldConstants.mediaMid);
+ int mediaPLayMode = intent.getIntExtra(QQMusicFieldConstants.mediaPlayMode, -1);
+ boolean isLocalMedia = intent.getBooleanExtra(QQMusicFieldConstants.isLocalMedia, false);
+
+ if (playState == 1 || playState == 2) {
+ if (playState == 1){
+ if (mMediaInfoData == null){
+ change = true;
+ ttMid = "";
+ }else{
+ ttMid = mMediaInfoData.getMediaId();
+ }
+ if (mMediaInfoData != null && mMediaInfoData.getMediaId() != null && !mMediaInfoData.getMediaId().equals(mediaMid)) {
+ change = true;
+ }
+ }
+ }
+
+ if (mMediaInfoData == null) {
+ mMediaInfoData = new MediaInfoData();
+ }
+ mMediaInfoData.setType(type);
+ mMediaInfoData.setPlayState(playState);
+ mMediaInfoData.setMaxTime(maxTime * 1000);
+ mMediaInfoData.setCurTime(curTime * 1000);
+ mMediaInfoData.setMediaName(mediaName);
+ mMediaInfoData.setMediaUrl(mediaUrl);
+ mMediaInfoData.setMediaId(mediaMid);
+ mMediaInfoData.setMediaImg(mediaImgUrl);
+ mMediaInfoData.setMediaSinger(mediaSinger);
+ mMediaInfoData.setMediaPlayMode(mediaPLayMode);
+ mMediaInfoData.setLocalMedia(isLocalMedia);
+ mMediaInfoData.setMediaType(mediaType);
+ mMediaInfoData.setBookInfo("");
+
+ } else if (type == 2) {//懒人听书
+
+ int maxTime = intent.getIntExtra(LeTingFieldConstants.maxTime, 0);
+ int curTime = intent.getIntExtra(LeTingFieldConstants.curTime, 0);
+
+ String mediaName = intent.getStringExtra(LeTingFieldConstants.mediaName);//章节数
+ String bookInfoStr = intent.getStringExtra(LeTingFieldConstants.bookInfo);
+ LanRenInsertData lanRenInsertData = GsonUtil.objectFromJson(bookInfoStr, LanRenInsertData.class);
+
+ String bookName = ""; // 书名 需要从bookinfo里面取
+ String cover = ""; //封面 bookinfo中取
+ String bookid = "";
+
+ try {
+ if (lanRenInsertData != null){
+ bookName = lanRenInsertData.getName(); // 书名 需要从bookinfo里面取
+ cover = lanRenInsertData.getCover(); //封面 bookinfo中取
+ bookid = lanRenInsertData.getBookId() + "";
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+
+ if (playState == 1 || playState == 2){
+ if (playState == 1 || playState == 2){
+ if (mMediaInfoData == null){
+ change = true;
+ ttMid = "";
+ }else{
+ ttMid = mMediaInfoData.getMediaId();
+ }
+ if (mMediaInfoData != null && mMediaInfoData.getMediaId() != null && !mMediaInfoData.getMediaId().equals(bookid)) {
+ change = true;
+ }
+ }
+
+ }
+
+ if (mMediaInfoData == null) {
+ mMediaInfoData = new MediaInfoData();
+ }
+ mMediaInfoData.setType(type);
+ mMediaInfoData.setPlayState(playState);
+ mMediaInfoData.setMaxTime(maxTime);
+ mMediaInfoData.setCurTime(curTime);
+ if (!TextUtils.isEmpty(bookName)){
+ mMediaInfoData.setMediaName(bookName); //bookName 或者mediaName
+ }else if (!TextUtils.isEmpty(mediaName)){
+ mMediaInfoData.setMediaName(mediaName); //bookName 或者mediaName
+ }
+ mMediaInfoData.setMediaSinger(mediaName); //章节数
+ mMediaInfoData.setMediaImg(cover); //书籍封面
+ mMediaInfoData.setMediaId(bookid);//书籍的bookid int
+ mMediaInfoData.setBookInfo(bookInfoStr);
+ mMediaInfoData.setMediaUrl("");
+ mMediaInfoData.setLocalMedia(false);
+ mMediaInfoData.setMediaType("");
+
+ } else if (type == 3) {//乐听头条
+ int maxTime = intent.getIntExtra(LeTingFieldConstants.maxTime, 0);
+ int curTime = intent.getIntExtra(LeTingFieldConstants.curTime, 0);
+ String mediaName = intent.getStringExtra(LeTingFieldConstants.mediaName); //新闻title
+ String artist = intent.getStringExtra(LeTingFieldConstants.artist); //新闻来源,赋值给singer mediaSinger
+ String cover = intent.getStringExtra(LeTingFieldConstants.cover); //封面
+ String bookInfo = intent.getStringExtra("news");//新闻实体
+ String bookid = "";
+ try {
+ if (!TextUtils.isEmpty(bookInfo)){
+ LeTingNewsData leTingNewsData = GsonUtil.objectFromJson(bookInfo, LeTingNewsData.class);
+ if (leTingNewsData != null){
+ mediaName = leTingNewsData.getTitle();
+ artist = leTingNewsData.getSource();
+ cover = leTingNewsData.getImage();
+ bookid = leTingNewsData.getSid();
+ }
+
+ if (mediaName == null){
+ mediaName = "";
+ }
+ if (artist == null){
+ artist = "";
+ }
+ if (cover == null){
+ cover = "";
+ }
+ if (bookid == null){
+ bookid = "";
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+
+ if (playState == 1 || playState == 2){
+ if (mMediaInfoData == null){
+ change = true;
+ ttMid = "";
+ }else{
+ ttMid = mMediaInfoData.getMediaId();
+ }
+ if (mMediaInfoData != null && mMediaInfoData.getMediaId() != null && !mMediaInfoData.getMediaId().equals(bookid)) {
+ change = true;
+ }
+ }
+
+ mMediaInfoData.setType(type);
+ mMediaInfoData.setPlayState(playState);
+ mMediaInfoData.setMaxTime(maxTime);
+ mMediaInfoData.setCurTime(curTime);
+ mMediaInfoData.setMediaName(mediaName); //新闻标题
+ mMediaInfoData.setMediaSinger(artist); //新闻来源
+ mMediaInfoData.setMediaImg(cover); //新闻封面
+
+ mMediaInfoData.setMediaId(bookid);//新闻的sid
+ mMediaInfoData.setBookInfo(bookInfo);
+ mMediaInfoData.setMediaUrl("");
+ mMediaInfoData.setLocalMedia(false);
+ mMediaInfoData.setMediaType("");
+
+ }
+
+ try {
+ if (mMediaInfoData != null && (type == 1 || type == 2)){
+ ThreadPoolService.execute(new Runnable() {
+ @Override
+ public void run() {
+ String tmData = GsonUtil.jsonFromObject(mMediaInfoData);
+ StorageManager.setLastListenMediaMusic(tmData);
+ Logger.d(TAG,"save"+tmData != null ? tmData:"");
+ }
+ });
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ //播放另外一个时去掉选中状态
+ if (!ttMid.equals(mMediaInfoData.getMediaId())){
+ cancleChoose = true;
+ }
+ if (cancleChoose && mMediaInfoData != null && (playState == 1 || playState == 2)){
+ if (ServiceMediaHandler.getMarkerManager() != null){
+ List< IMogoMarker > mogoMarkersList = ServiceMediaHandler.getMarkerManager().getMarkers(MediaConstants.MODULE_TYPE);
+ try {
+ if ( mogoMarkersList != null && mogoMarkersList.size() > 0){
+ for (IMogoMarker mogoMarker : mogoMarkersList){
+ if (mogoMarker != null && !mogoMarker.isDestroyed()){
+ if (mogoMarker.getObject() != null && mogoMarker.getObject() instanceof MarkerShowEntity){
+ MarkerShowEntity markerShowEntity = (MarkerShowEntity) mogoMarker.getObject();
+ if (markerShowEntity.getBindObj() != null && markerShowEntity.getBindObj() instanceof MarkerShareMusic){
+ MarkerShareMusic markerShareMusic = (MarkerShareMusic) markerShowEntity.getBindObj();
+ if (markerShowEntity.isChecked() && !markerShareMusic.getMediaId().equals(mMediaInfoData.getMediaId())){
+// MapMarkerManager.getInstance().closeMarkerSelect(mogoMarker);
+ break;
+ }
+ }
+
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ if (playState == 1 || playState == 2){
+ if (mTwoChange){
+ change = true;
+ mTwoChange = false;
+ }
+
+
+ Logger.d(TAG,"onreceive state change = "+change+" mediaid= "+mMediaInfoData.getMediaId());
+// ifNeedRefreshMediaCard(change);
+ }
+
+ //pop window 弹窗
+ if (mMediaInfoData != null && !TextUtils.isEmpty(mMediaInfoData.getMediaName()) && !TextUtils.isEmpty(mMediaInfoData.getMediaSinger())){
+
+ if (!mHasAddWindow){
+ addWindowView();
+ }else{
+ if (playState == 1 || playState == 2){
+ updateWindowUI();
+ }
+ }
+ }
+
+ }
+
+ if (playState == 1) {
+ mPresenter.startedMusic(mMediaInfoData);
+ } else {
+ if (mMediaInfoData != null){
+ mMediaInfoData.setPlayState(playState);
+ }
+ mPresenter.stopMusic();
+ }
+
+ }
+ }
+
+ }
+
+ /**
+ * 音频进度改变广播接收者
+ */
+ private class MediaProcessReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent != null) {
+ int curTime = intent.getIntExtra("curTime", -1);
+ Logger.d("MediaProcessReceiver", "===MediaProcessReceiver===="+curTime);
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mMediaInfoData != null) {
+ if (mWindowCurrTime != null) {
+ mWindowCurrTime.setText(Utils.calculateTime(curTime));
+ }
+ try {
+ int progress = (int) ((curTime * 1.0f * 100) / (mMediaInfoData.getMaxTime() * 1.0f));
+ if (mWindowProgress != null) {
+ mWindowProgress.setProgress(progress);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+ }
+ });
+ }
+ }
+
+ }
+
+ /**
+ * 获取新闻是否付费
+ * com.zhidao.mediacenter.ltnewsPayInfo
+ */
+ private class MediaNewsPayInfo extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent != null) {
+ boolean playinfo = intent.getBooleanExtra("payinfo", false);
+ boolean appActive = ActivityLifecycleManager.getInstance().isAppActive();
+ String category = MediaSpeechReceiver.mCategoryStr;
+ MediaSpeechReceiver.mCategoryStr = "";
+ Logger.d(TAG," MediaNewsPayInfo "+"news "+category == null?"":category+" "+appActive);
+ if (playinfo){
+ if (TextUtils.isEmpty(category)){
+ //打开新闻
+ //播放某一类型新闻
+ if (appActive){
+ MusicControlBroadCast.sendPlayTypeNews("推荐");
+ }else{
+ MusicControlBroadCast.sendPlayTypeNewsOpenApp("推荐");
+ }
+ }else{
+ //播放某一类型新闻
+ if (appActive){
+ MusicControlBroadCast.sendPlayTypeNews(category);
+ }else{
+ MusicControlBroadCast.sendPlayTypeNewsOpenApp(category);
+ }
+ }
+ }else{
+ MusicControlBroadCast.openMediaApp(3);
+ }
+ }
+ }
+
+ }
+
+ private void registerMediaReceiver() {
+ mediaStateReceiver = new MediaWindow.MediaStateReceiver();
+ IntentFilter filterone = new IntentFilter();
+ filterone.addAction("com.zhidao.action.MEDIA_LRTS");
+ filterone.addAction("com.zhidao.action.MEDIA_LT_NEWS");
+ filterone.addAction("com.qq.music.status.change");
+ getContext().registerReceiver(mediaStateReceiver, filterone);
+
+ mediaProcessReceiver = new MediaWindow.MediaProcessReceiver();
+ IntentFilter filtertwo = new IntentFilter();
+ filtertwo.addAction("com.zhidao.action.MEDIA_PROGRESS");
+ getContext().registerReceiver(mediaProcessReceiver, filtertwo);
+
+ playingMusicReceiver = new PlayingMusicReceiver();
+ IntentFilter filterthree = new IntentFilter();
+ filterthree.addAction("com.mogo.launcher.media.listening");
+ getContext().registerReceiver(playingMusicReceiver, filterthree);
+
+ mediaNewsPayInfo = new MediaNewsPayInfo();
+ IntentFilter filterFour = new IntentFilter();
+ filterFour.addAction("com.zhidao.mediacenter.ltnewsPayInfo");
+ getContext().registerReceiver(mediaNewsPayInfo, filterFour);
+
+ }
+
+ private void unRegisterMediaReceiver() {
+ getContext().unregisterReceiver(mediaProcessReceiver);
+ getContext().unregisterReceiver(mediaStateReceiver);
+ getContext().unregisterReceiver(playingMusicReceiver);
+ getContext().unregisterReceiver(mediaNewsPayInfo);
+ }
+
+ private void destroy(){
+ try {
+ UiThreadHandler.removeCallbacks(mRunnable);
+ mRunnable = null;
+ unRegisterMediaReceiver();
+ if (mCircleImg != null && mCircleImg.isRotationing()) {
+ mCircleImg.stopAnim();
+ }
+
+ if (ServiceMediaHandler.getMogoWindowManager() != null){
+ ServiceMediaHandler.getMogoWindowManager().removeView(mWindowView);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/modules/mogo-module-media/src/main/java/com/mogo/module/media/window/MediaWindow2.java b/modules/mogo-module-media/src/main/java/com/mogo/module/media/window/MediaWindow2.java
new file mode 100644
index 0000000000..42f1aa3342
--- /dev/null
+++ b/modules/mogo-module-media/src/main/java/com/mogo/module/media/window/MediaWindow2.java
@@ -0,0 +1,508 @@
+package com.mogo.module.media.window;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import com.mogo.commons.debug.DebugConfig;
+import com.mogo.commons.voice.AIAssist;
+import com.mogo.commons.voice.IMogoVoiceCmdCallBack;
+import com.mogo.module.common.MogoApisHandler;
+import com.mogo.module.common.glide.SkinAbleBitmapTarget;
+import com.mogo.module.media.MediaConstants;
+import com.mogo.module.media.R;
+import com.mogo.module.media.ServiceMediaHandler;
+import com.mogo.module.media.constants.MusicConstant;
+import com.mogo.module.media.listener.NoDoubleClickListener;
+import com.mogo.module.media.model.MediaInfoData;
+import com.mogo.module.media.presenter.BaseMediaPresenter;
+import com.mogo.module.media.presenter.KwPresenter;
+import com.mogo.module.media.presenter.PresenterFactory;
+import com.mogo.module.media.utils.Utils;
+import com.mogo.module.media.view.IMusicView;
+import com.mogo.module.media.widget.AnimCircleImageView;
+import com.mogo.module.media.widget.CircleNumberProgress;
+import com.mogo.module.media.widget.PercentageRingView;
+import com.mogo.service.statusmanager.IMogoStatusChangedListener;
+import com.mogo.service.statusmanager.StatusDescriptor;
+import com.mogo.utils.WindowUtils;
+import com.mogo.utils.glide.GlideApp;
+import com.mogo.utils.logger.Logger;
+import com.tencent.wecarflow.flowoutside.sdk.FlowPlayControl;
+import com.zhidao.carchattingprovider.ICallChatResponse;
+import com.zhidao.carchattingprovider.ICallProviderResponse;
+
+/**
+ * 适配爱趣听和酷我的window,通过presenter区分
+ * 爱趣听使用{@link com.mogo.module.media.presenter.WeCarFlowPresenter}
+ * 酷我使用{@link KwPresenter}
+ *
+ * @author tongchenfei
+ */
+public class MediaWindow2 implements IMusicView , IMogoStatusChangedListener {
+
+ public static final String TAG = MediaWindow2.class.getName();
+ private Context mContext;
+ private BaseMediaPresenter mPresenter;
+
+ private MediaInfoData mMediaInfoData = new MediaInfoData();
+
+ private View mWindowView;
+ private AnimCircleImageView mCircleImg;
+ private TextView mScrollText;
+ private ImageView mWindowPlayPause;
+ private ImageView mWindowPlayNext;
+ private TextView mWindowCurrTime;
+ private TextView mWindowMaxTime;
+ private SeekBar mWindowProgress;
+
+ private boolean mHasAddWindow = false;
+ private boolean mTwoChange = false;
+ private boolean isFirstPlay = false;
+ private boolean mIsCallChatWindowVisible;
+
+ private ICallProviderResponse mCallProviderResponse;
+ private CircleNumberProgress mPercentageRingView;
+// private PercentageRingView mPercentageRingView;
+ private ImageView mPauseImage;
+ private AnimCircleImageView mAnimCircleImageView;
+
+
+ public void initMedia(Context context) {
+ mContext = context;
+ mPresenter = PresenterFactory.createMusicViewPresenter(context, this);
+ mPresenter.init(context);
+
+ if(DebugConfig.isLauncher()) {
+ AIAssist.getInstance(context).registerUnWakeupCommand("flow_we_car_stop", new String[]{"停止播放", "暂停播放"}, new IMogoVoiceCmdCallBack() {
+ @Override
+ public void onCmdSelected(String cmd) {
+ // 简单添加暂停播放全局免唤醒词
+ if ("flow_we_car_stop".equals(cmd)) {
+ FlowPlayControl.getInstance().doPause();
+ }
+ }
+ });
+ }
+
+ ServiceMediaHandler.getIMogoStatusManager().registerStatusChangedListener(MediaConstants.MODULE_TYPE, StatusDescriptor.ACC_STATUS, this);
+ ServiceMediaHandler.getIMogoStatusManager().registerStatusChangedListener(MediaConstants.MODULE_TYPE, StatusDescriptor.VR_MODE, this);
+
+ // 车聊聊才是王
+ mCallProviderResponse = new ICallChatResponse(){
+ @Override
+ public void callWindowStatus( boolean b ) {
+ Logger.d( TAG, "callWindowStatus: "+ b);
+ mIsCallChatWindowVisible = b;
+ if ( !mHasAddWindow || mWindowView == null ) {
+ return;
+ }
+ if ( mIsCallChatWindowVisible ) {
+ mWindowView.setVisibility(View.GONE );
+ } else {
+ mWindowView.setVisibility(View.VISIBLE);
+ }
+ }
+ };
+ if ( ServiceMediaHandler.getCarsChattingApis() != null ) {
+ ServiceMediaHandler.getCarsChattingApis().registerCallWindowStatusListener( MediaConstants.MODULE_TYPE, mContext, mCallProviderResponse);
+ }
+ isFirstPlay = true;
+ }
+
+ @Override
+ public void onStatusChanged( StatusDescriptor descriptor, boolean isTrue ) {
+ Log.d(TAG, " onStatusChanged ----- descriptor = " + descriptor);
+ if (descriptor == StatusDescriptor.ACC_STATUS&&!isTrue) {
+ ServiceMediaHandler.getMogoWindowManager().removeView(mWindowView);
+ mHasAddWindow = false;
+ }
+
+ if (descriptor == StatusDescriptor.VR_MODE) {
+ if (mWindowView == null) {
+ return;
+ }
+
+ ServiceMediaHandler.getMogoWindowManager().removeView(mWindowView);
+ mHasAddWindow = false;
+ addWindowView();
+ }
+ }
+
+ private void addWindowView() {
+ Log.d(TAG, "addWindowView===" + mHasAddWindow);
+ if (ServiceMediaHandler.getMogoWindowManager() == null) {
+ Log.d(TAG, "addWindowView return");
+ return;
+ }
+
+ if (!mHasAddWindow) {
+ mHasAddWindow = true;
+ if (MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode()) {
+ mWindowView =
+ LayoutInflater.from(mContext).inflate(R.layout.module_media_music_window_alert_layout_new, null);
+ mPercentageRingView = mWindowView.findViewById(R.id.window_circle_bg);
+ mAnimCircleImageView = mWindowView.findViewById(R.id.window_circle_img_new);
+ mPauseImage = mWindowView.findViewById(R.id.window_play_pause_new);
+
+// int[] arcColors = new int[]{
+// Color.parseColor("#1Affffff"),
+// Color.parseColor("#80ffffff"),
+// Color.parseColor("#BFffffff"),
+// Color.parseColor("#ffffff")
+// };
+//
+// mPercentageRingView.setArcColors(arcColors);
+
+ if (mPauseImage != null) {
+ mPauseImage.setImageResource(R.drawable.module_media_window_pop_pause_new);
+ }
+
+ int yPos =
+ getContext().getResources().getDimensionPixelOffset(R.dimen.module_media_music_state_location_new);
+ int xPos =
+ getContext().getResources().getDimensionPixelOffset(R.dimen.module_media_music_state_location_x_new);
+ int statusBarHeight = WindowUtils.getStatusBarHeight(mContext);
+ Logger.d(TAG,
+ "yPos: " + yPos + " xPos: " + xPos + " statusBarHeight: " + statusBarHeight);
+ Log.d(TAG, "addMediaWindoView");
+ FrameLayout.LayoutParams params =
+ new FrameLayout.LayoutParams((int) mContext.getResources().getDimension(R.dimen.module_media_pop_window_width_new), (int) mContext.getResources().getDimension(R.dimen.module_media_pop_window_height_new));
+ params.leftMargin = xPos;
+ params.topMargin = yPos;
+ ServiceMediaHandler.getMogoWindowManager().addView(mWindowView, params, false);
+ updateWindowUI(true);
+
+ mWindowView.setOnClickListener(new NoDoubleClickListener() {
+ @Override
+ public void onClicks(View view) {
+ mPresenter.openApp();
+ }
+ });
+
+ mPauseImage.setOnClickListener(new NoDoubleClickListener() {
+ @Override
+ public void onClicks(View view) {
+ if (mMediaInfoData != null) {
+ if (mMediaInfoData.getPlayState() == MusicConstant.PLAY_STATE_PAUSE_OR_STOP) {
+ mPresenter.play(mMediaInfoData);
+ } else {
+ // 没有做详细判断,不是暂停就是播放
+ mPresenter.pause(mMediaInfoData);
+ }
+ } else {
+ mPresenter.openApp();
+ }
+ }
+ });
+
+ if ( mIsCallChatWindowVisible ) {
+ Logger.d( TAG, "vr mWindowView.setVisibility: status = " + mIsCallChatWindowVisible );
+ mWindowView.setVisibility(View.GONE);
+ } else {
+ mWindowView.setVisibility(View.VISIBLE);
+ }
+ } else {
+ mWindowView =
+ LayoutInflater.from(mContext).inflate(R.layout.module_media_music_window_alert_layout, null);
+ mCircleImg = mWindowView.findViewById(R.id.window_circle_img);
+ mScrollText = mWindowView.findViewById(R.id.window_scroll_txt);
+ mWindowPlayPause = mWindowView.findViewById(R.id.window_play_pause);
+ mWindowPlayNext = mWindowView.findViewById(R.id.window_music_next);
+ mWindowCurrTime = mWindowView.findViewById(R.id.window_current_time);
+ mWindowMaxTime = mWindowView.findViewById(R.id.window_max_time);
+ mWindowProgress = mWindowView.findViewById(R.id.window_progress_bar);
+ if (mWindowPlayPause != null) {
+ mWindowPlayPause.setImageResource(R.drawable.module_media_window_pop_pause);
+ }
+ int yPos =
+ getContext().getResources().getDimensionPixelOffset(R.dimen.module_media_music_state_location);
+ int xPos =
+ getContext().getResources().getDimensionPixelOffset(R.dimen.module_media_music_state_location_x);
+ int statusBarHeight = WindowUtils.getStatusBarHeight(mContext);
+ Logger.d(TAG,
+ "yPos: " + yPos + " xPos: " + xPos + " statusBarHeight: " + statusBarHeight);
+ Log.d(TAG, "addMediaWindoView");
+ FrameLayout.LayoutParams params =
+ new FrameLayout.LayoutParams((int) mContext.getResources().getDimension(R.dimen.module_media_pop_window_width), (int) mContext.getResources().getDimension(R.dimen.module_media_pop_window_height));
+ params.leftMargin = xPos;
+ params.topMargin = yPos;
+ ServiceMediaHandler.getMogoWindowManager().addView(mWindowView, params, false);
+ updateWindowUI(true);
+ mWindowView.setOnClickListener(new NoDoubleClickListener() {
+ @Override
+ public void onClicks(View view) {
+ mPresenter.openApp();
+ }
+ });
+
+ mWindowPlayPause.setOnClickListener(new NoDoubleClickListener() {
+ @Override
+ public void onClicks(View view) {
+ if (mMediaInfoData != null) {
+ if (mMediaInfoData.getPlayState() == MusicConstant.PLAY_STATE_PAUSE_OR_STOP) {
+ mPresenter.play(mMediaInfoData);
+ } else {
+ // 没有做详细判断,不是暂停就是播放
+ mPresenter.pause(mMediaInfoData);
+ }
+ } else {
+ mPresenter.openApp();
+ }
+ }
+ });
+
+ mWindowPlayNext.setOnClickListener(new NoDoubleClickListener() {
+ @Override
+ public void onClicks(View view) {
+ if (mPresenter != null) {
+ mPresenter.next();
+ }
+ }
+ });
+
+ if ( mIsCallChatWindowVisible ) {
+ Logger.d( TAG, "mWindowView.setVisibility: status = " + mIsCallChatWindowVisible );
+ mWindowView.setVisibility(View.GONE);
+ } else {
+ mWindowView.setVisibility(View.VISIBLE);
+ }
+ }
+ }
+ }
+
+ private void updateWindowUI() {
+ updateWindowUI(false);
+ }
+
+ private void updateWindowUI(boolean first) {
+ if (mWindowView == null) {
+ return;
+ }
+ if (mMediaInfoData != null) {
+ if (mMediaInfoData.getType() == MusicConstant.PLAY_STATE_ERROR||isFirstPlay) {
+ mWindowView.setVisibility(View.GONE);
+ } else {
+ if ( mIsCallChatWindowVisible ) {
+ mWindowView.setVisibility(View.GONE );
+ } else {
+ mWindowView.setVisibility(View.VISIBLE);
+ }
+ }
+ } else {
+ mWindowView.setVisibility(View.GONE);
+ return;
+ }
+
+ if (MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode()) {
+ if (first || mMediaInfoData.getPlayState() == MusicConstant.PLAY_STATE_PLAYING || mMediaInfoData.getPlayState() == MusicConstant.PLAY_STATE_BUFF) {
+ if( mMediaInfoData.getPlayState() == MusicConstant.PLAY_STATE_PLAYING) {
+ // kw音乐做的容错
+ if (mPauseImage != null) {
+ mPauseImage.setImageResource(R.drawable.module_media_window_pop_play_new);
+ }
+ if (mAnimCircleImageView != null) {
+ mAnimCircleImageView.startAnim();
+ }
+ }
+ }
+
+ if (mAnimCircleImageView != null) {
+ if(mMediaInfoData!=null&&mMediaInfoData.getMediaImg()!=null&&!mMediaInfoData.getMediaImg().isEmpty()) {
+ int size =
+ mContext.getResources().getDimensionPixelSize(R.dimen.module_media_pop_window_anim_img_size_new);
+ Logger.d(TAG, "overload: " + size);
+ com.bumptech.glide.request.RequestOptions options =
+ new com.bumptech.glide.request.RequestOptions()
+ .placeholder(R.drawable.module_media_default_music_img).error(R.drawable.module_media_default_music_img).override(size, size);
+ GlideApp.with(mContext).asBitmap().apply(options).load(mMediaInfoData.getMediaImg()).into(new SkinAbleBitmapTarget(mAnimCircleImageView, options));
+// GlideApp.with(mContext).applyDefaultRequestOptions(options).load(mMediaInfoData.getMediaImg()).into(new SkinAbleBitmapTarget(mCircleImg, options));
+ }else{
+ Logger.e(TAG, "mMediaInfoData == null ");
+ mAnimCircleImageView.setImageResource(R.drawable.module_media_default_music_img_new);
+ }
+ }
+ } else {
+ if (mScrollText != null) {
+ mScrollText.setText(mMediaInfoData.getMediaName());
+ }
+
+ if (first || mMediaInfoData.getPlayState() == MusicConstant.PLAY_STATE_PLAYING || mMediaInfoData.getPlayState() == MusicConstant.PLAY_STATE_BUFF) {
+ if (mWindowMaxTime != null) {
+ mWindowMaxTime.setText(Utils.calculateTime((int) mMediaInfoData.getMaxTime()));
+ }
+ if (mWindowCurrTime != null) {
+ mWindowCurrTime.setText(Utils.calculateTime((int) mMediaInfoData.getCurTime()));
+ }
+
+ if( mMediaInfoData.getPlayState() == MusicConstant.PLAY_STATE_PLAYING) {
+ // kw音乐做的容错
+ if (mWindowPlayPause != null) {
+ mWindowPlayPause.setImageResource(R.drawable.module_media_window_pop_play);
+ }
+ if (mCircleImg != null) {
+ mCircleImg.startAnim();
+ }
+ }
+ }
+
+ if (mCircleImg != null) {
+ if(mMediaInfoData!=null&&mMediaInfoData.getMediaImg()!=null&&!mMediaInfoData.getMediaImg().isEmpty()) {
+ int size =
+ mContext.getResources().getDimensionPixelSize(R.dimen.module_media_pop_window_anim_img_size);
+ com.bumptech.glide.request.RequestOptions options =
+ new com.bumptech.glide.request.RequestOptions()
+ .placeholder(R.drawable.module_media_default_music_img).error(R.drawable.module_media_default_music_img).override(size, size);
+ GlideApp.with(mContext).asBitmap().apply(options).load(mMediaInfoData.getMediaImg()).into(new SkinAbleBitmapTarget(mCircleImg, options));
+// GlideApp.with(mContext).applyDefaultRequestOptions(options).load(mMediaInfoData.getMediaImg()).into(new SkinAbleBitmapTarget(mCircleImg, options));
+ }else{
+ mCircleImg.setImageResource(R.drawable.module_media_default_music_img);
+ }
+ }
+ }
+
+ }
+
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ public void onMusicPlaying() {
+ Logger.d(TAG, "onMusicPlaying===" + mMediaInfoData);
+ isFirstPlay = false;
+ updateWindowUI(false);
+ if (MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode()) {
+ if (mPauseImage != null) {
+ mPauseImage.setImageResource(R.drawable.module_media_window_pop_play_new);
+ }
+
+ if (mAnimCircleImageView != null) {
+ mAnimCircleImageView.startAnim();
+ }
+ } else {
+ if (mWindowPlayPause != null) {
+ mWindowPlayPause.setImageResource(R.drawable.module_media_window_pop_play);
+ }
+
+ if (mCircleImg != null) {
+ mCircleImg.startAnim();
+ }
+ }
+
+ MogoApisHandler.getInstance().getApis().getStatusManagerApi().setMediaPlayStatus(TAG, true);
+ }
+
+ @Override
+ public void onMusicPause() {
+ Logger.d(TAG, "onMusicPause: ===" + mMediaInfoData);
+ if (MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode()) {
+ if (mPauseImage != null) {
+ mPauseImage.setImageResource(R.drawable.module_media_window_pop_pause_new);
+ }
+
+ if (mAnimCircleImageView != null) {
+ mAnimCircleImageView.stopAnim();
+ }
+ } else {
+ if (mWindowPlayPause != null) {
+ mWindowPlayPause.setImageResource(R.drawable.module_media_window_pop_pause);
+ }
+
+ if (mAnimCircleImageView != null) {
+ mAnimCircleImageView.stopAnim();
+ }
+ }
+
+ MogoApisHandler.getInstance().getApis().getStatusManagerApi().setMediaPlayStatus(TAG,false);
+ }
+
+ @Override
+ public void onMusicStopped() {
+ Logger.d(TAG, "onMusicStopped===" + mMediaInfoData);
+ if (MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode()) {
+ if (mPauseImage != null) {
+ mPauseImage.setImageResource(R.drawable.module_media_window_pop_pause_new);
+ }
+
+ if (mAnimCircleImageView != null) {
+ mAnimCircleImageView.stopAnim();
+ }
+ } else {
+ if (mWindowPlayPause != null) {
+ mWindowPlayPause.setImageResource(R.drawable.module_media_window_pop_pause);
+ }
+
+ if (mCircleImg != null) {
+ mCircleImg.stopAnim();
+ }
+ }
+
+ MogoApisHandler.getInstance().getApis().getStatusManagerApi().setMediaPlayStatus(TAG,false);
+ }
+
+ @Override
+ public void onMediaInfoChanged(MediaInfoData mediaInfoData) {
+ Logger.d(TAG, "onMediaInfoChanged: " + mediaInfoData);
+ mMediaInfoData = mediaInfoData;
+ addWindowView();
+ updateWindowUI();
+ }
+
+ @Override
+ public void onMusicProgress(long current, long total) {
+// Logger.d(TAG, "onMusicProgress==current: " + current + " total: " + total);
+ if (MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode()) {
+ try {
+ int progress =
+ (int) ((current * 1.0f * 100) / (total * 1.0f));
+ if (mPercentageRingView != null) {
+ mPercentageRingView.setVisibility(View.VISIBLE);
+ mPercentageRingView.setProgress(progress);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } else {
+ if (mMediaInfoData != null) {
+ mMediaInfoData.setCurTime((int) current);
+ mMediaInfoData.setMaxTime((int) total);
+ }
+ if (mWindowCurrTime != null) {
+ mWindowCurrTime.setText(Utils.calculateTime((int) current));
+ mWindowMaxTime.setText(Utils.calculateTime((int) total));
+ }
+ try {
+ int progress =
+ (int) ((current * 1.0f * 100) / (total * 1.0f));
+ if (mWindowProgress != null) {
+ mWindowProgress.setProgress(progress);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void onAppExit() {
+ if ( mWindowView != null ) {
+ mWindowView.setVisibility(View.GONE);
+ }
+ }
+
+ public void onDestroy(){
+ Logger.d(TAG, "onDestroy");
+ if ( ServiceMediaHandler.getCarsChattingApis() != null ) {
+ ServiceMediaHandler.getCarsChattingApis().unRegisterCallWindowStatusListener( MediaConstants.MODULE_TYPE, mContext);
+ }
+ ServiceMediaHandler.getIMogoStatusManager().unregisterStatusChangedListener(MediaConstants.MODULE_TYPE, StatusDescriptor.ACC_STATUS,this);
+ }
+}
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/ic_search_choice_point.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/ic_search_choice_point.png
new file mode 100644
index 0000000000..8ca4538285
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/ic_search_choice_point.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/ic_search_poi_location.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/ic_search_poi_location.png
new file mode 100644
index 0000000000..25940d02c6
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/ic_search_poi_location.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/ic_search_unshadow.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/ic_search_unshadow.png
new file mode 100644
index 0000000000..cd32e7f85f
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/ic_search_unshadow.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_blur_default_icon.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_blur_default_icon.png
new file mode 100644
index 0000000000..30d5891d96
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_blur_default_icon.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_default_music_img.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_default_music_img.png
new file mode 100644
index 0000000000..d8de3c1ef3
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_default_music_img.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_full_screen.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_full_screen.png
new file mode 100644
index 0000000000..240f148149
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_full_screen.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_have_heart.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_have_heart.png
new file mode 100644
index 0000000000..f86d4f3fde
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_have_heart.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_head_default_img.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_head_default_img.png
new file mode 100644
index 0000000000..0597a02397
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_head_default_img.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_last_song.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_last_song.png
new file mode 100644
index 0000000000..eb4a4099a1
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_last_song.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_next_song.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_next_song.png
new file mode 100644
index 0000000000..dcb18e202f
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_next_song.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_no_heart.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_no_heart.png
new file mode 100644
index 0000000000..804057b9ca
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_no_heart.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_no_img_default_icon.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_no_img_default_icon.png
new file mode 100644
index 0000000000..04f4e5c139
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_no_img_default_icon.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_play.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_play.png
new file mode 100644
index 0000000000..1b16f5d635
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_play.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_default_icon.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_default_icon.png
new file mode 100644
index 0000000000..a6ab1c9620
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_default_icon.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_default_icon2.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_default_icon2.png
new file mode 100644
index 0000000000..2dbb8b6773
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_default_icon2.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_default_rect_icon.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_default_rect_icon.png
new file mode 100644
index 0000000000..fc0b6145b1
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_default_rect_icon.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_fail.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_fail.png
new file mode 100644
index 0000000000..e15649f868
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_fail.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_normal.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_normal.png
new file mode 100644
index 0000000000..2562454404
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_normal.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_success.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_success.png
new file mode 100644
index 0000000000..2508848c10
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_share_success.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_suspend.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_suspend.png
new file mode 100644
index 0000000000..88df36ee6d
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_suspend.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_window_alert_bg.9.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_window_alert_bg.9.png
new file mode 100644
index 0000000000..8e6032a5f1
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_window_alert_bg.9.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_window_pop_pause.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_window_pop_pause.png
new file mode 100644
index 0000000000..6d35054284
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_window_pop_pause.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_window_pop_play.png b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_window_pop_play.png
new file mode 100644
index 0000000000..61510381d0
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-ldpi/module_media_window_pop_play.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/ic_search_choice_point.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/ic_search_choice_point.png
new file mode 100644
index 0000000000..8ca4538285
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/ic_search_choice_point.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/ic_search_poi_location.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/ic_search_poi_location.png
new file mode 100644
index 0000000000..25940d02c6
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/ic_search_poi_location.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/ic_search_unshadow.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/ic_search_unshadow.png
new file mode 100644
index 0000000000..cd32e7f85f
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/ic_search_unshadow.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_blur_default_icon.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_blur_default_icon.png
new file mode 100644
index 0000000000..30d5891d96
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_blur_default_icon.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_default_music_img.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_default_music_img.png
new file mode 100644
index 0000000000..d8de3c1ef3
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_default_music_img.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_full_screen.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_full_screen.png
new file mode 100644
index 0000000000..240f148149
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_full_screen.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_have_heart.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_have_heart.png
new file mode 100644
index 0000000000..f86d4f3fde
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_have_heart.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_head_default_img.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_head_default_img.png
new file mode 100644
index 0000000000..0597a02397
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_head_default_img.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_last_song.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_last_song.png
new file mode 100644
index 0000000000..eb4a4099a1
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_last_song.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_next_song.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_next_song.png
new file mode 100644
index 0000000000..dcb18e202f
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_next_song.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_no_heart.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_no_heart.png
new file mode 100644
index 0000000000..804057b9ca
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_no_heart.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_no_img_default_icon.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_no_img_default_icon.png
new file mode 100644
index 0000000000..04f4e5c139
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_no_img_default_icon.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_play.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_play.png
new file mode 100644
index 0000000000..1b16f5d635
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_play.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_default_icon.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_default_icon.png
new file mode 100644
index 0000000000..a6ab1c9620
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_default_icon.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_default_icon2.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_default_icon2.png
new file mode 100644
index 0000000000..2dbb8b6773
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_default_icon2.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_default_rect_icon.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_default_rect_icon.png
new file mode 100644
index 0000000000..fc0b6145b1
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_default_rect_icon.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_fail.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_fail.png
new file mode 100644
index 0000000000..e15649f868
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_fail.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_normal.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_normal.png
new file mode 100644
index 0000000000..2562454404
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_normal.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_success.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_success.png
new file mode 100644
index 0000000000..2508848c10
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_share_success.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_suspend.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_suspend.png
new file mode 100644
index 0000000000..88df36ee6d
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_suspend.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_window_alert_bg.9.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_window_alert_bg.9.png
new file mode 100644
index 0000000000..8e6032a5f1
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_window_alert_bg.9.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_window_pop_pause.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_window_pop_pause.png
new file mode 100644
index 0000000000..6d35054284
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_window_pop_pause.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_window_pop_play.png b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_window_pop_play.png
new file mode 100644
index 0000000000..61510381d0
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-mdpi/module_media_window_pop_play.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/ic_search_choice_point.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/ic_search_choice_point.png
new file mode 100644
index 0000000000..9f75ac8e88
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/ic_search_choice_point.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/ic_search_poi_location.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/ic_search_poi_location.png
new file mode 100644
index 0000000000..484f80efd5
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/ic_search_poi_location.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_blur_default_icon.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_blur_default_icon.png
new file mode 100644
index 0000000000..7198c071db
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_blur_default_icon.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_default_music_img.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_default_music_img.png
new file mode 100644
index 0000000000..df81e5d06d
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_default_music_img.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_default_music_img_new.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_default_music_img_new.png
new file mode 100644
index 0000000000..fcc9015490
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_default_music_img_new.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_full_screen.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_full_screen.png
new file mode 100644
index 0000000000..bc14feee50
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_full_screen.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_full_screen_select.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_full_screen_select.png
new file mode 100644
index 0000000000..170785863b
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_full_screen_select.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_have_heart.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_have_heart.png
new file mode 100644
index 0000000000..d660105c2d
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_have_heart.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_head_default_img.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_head_default_img.png
new file mode 100644
index 0000000000..f2e5a03cab
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_head_default_img.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_icon_map_marker_music.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_icon_map_marker_music.png
new file mode 100644
index 0000000000..398912c0ea
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_icon_map_marker_music.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_last_song.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_last_song.png
new file mode 100644
index 0000000000..f3a0b6f28e
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_last_song.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_last_song_click.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_last_song_click.png
new file mode 100644
index 0000000000..80ec16e26f
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_last_song_click.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon1.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon1.png
new file mode 100644
index 0000000000..172a5934ae
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon1.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon10.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon10.png
new file mode 100644
index 0000000000..dc9589159b
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon10.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon11.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon11.png
new file mode 100644
index 0000000000..d913d05154
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon11.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon12.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon12.png
new file mode 100644
index 0000000000..35702bc1ab
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon12.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon13.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon13.png
new file mode 100644
index 0000000000..94faa2ac0e
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon13.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon14.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon14.png
new file mode 100644
index 0000000000..341e9ce7b9
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon14.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon15.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon15.png
new file mode 100644
index 0000000000..a271a09b42
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon15.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon16.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon16.png
new file mode 100644
index 0000000000..4ff5b09209
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon16.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon17.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon17.png
new file mode 100644
index 0000000000..1a96b0115a
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon17.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon18.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon18.png
new file mode 100644
index 0000000000..238f47d78c
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon18.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon19.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon19.png
new file mode 100644
index 0000000000..b45536a4d1
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon19.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon2.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon2.png
new file mode 100644
index 0000000000..775d44e934
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon2.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon20.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon20.png
new file mode 100644
index 0000000000..b70e929788
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon20.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon21.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon21.png
new file mode 100644
index 0000000000..b17ef58d95
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon21.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon22.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon22.png
new file mode 100644
index 0000000000..28a667b077
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon22.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon23.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon23.png
new file mode 100644
index 0000000000..8fb205f65c
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon23.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon24.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon24.png
new file mode 100644
index 0000000000..57216edd8b
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon24.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon25.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon25.png
new file mode 100644
index 0000000000..bf1db703d9
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon25.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon26.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon26.png
new file mode 100644
index 0000000000..ff783cb414
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon26.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon27.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon27.png
new file mode 100644
index 0000000000..b8c70103a6
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon27.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon28.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon28.png
new file mode 100644
index 0000000000..0b53d4e0cc
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon28.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon29.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon29.png
new file mode 100644
index 0000000000..35910fc41e
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon29.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon3.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon3.png
new file mode 100644
index 0000000000..f2aef2d862
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon3.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon30.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon30.png
new file mode 100644
index 0000000000..a8e76f4292
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon30.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon31.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon31.png
new file mode 100644
index 0000000000..2cfcb1239b
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon31.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon32.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon32.png
new file mode 100644
index 0000000000..8a7e0eab0c
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon32.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon33.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon33.png
new file mode 100644
index 0000000000..801817119d
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon33.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon34.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon34.png
new file mode 100644
index 0000000000..0775b3aae6
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon34.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon35.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon35.png
new file mode 100644
index 0000000000..d78c1ad2fc
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon35.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon36.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon36.png
new file mode 100644
index 0000000000..00c647affa
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon36.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon37.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon37.png
new file mode 100644
index 0000000000..72d9a66e36
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon37.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon38.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon38.png
new file mode 100644
index 0000000000..36525eec91
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon38.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon39.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon39.png
new file mode 100644
index 0000000000..1ef84eba37
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon39.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon4.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon4.png
new file mode 100644
index 0000000000..8180b14e9a
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon4.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon40.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon40.png
new file mode 100644
index 0000000000..14e67a0b5a
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon40.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon41.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon41.png
new file mode 100644
index 0000000000..bc95f9f96c
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon41.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon42.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon42.png
new file mode 100644
index 0000000000..ed0b6f76ce
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon42.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon43.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon43.png
new file mode 100644
index 0000000000..7e36135339
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon43.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon44.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon44.png
new file mode 100644
index 0000000000..eb86260b6d
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon44.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon45.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon45.png
new file mode 100644
index 0000000000..4d2423aacc
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon45.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon46.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon46.png
new file mode 100644
index 0000000000..ddf538ab6e
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon46.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon47.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon47.png
new file mode 100644
index 0000000000..04e325d6c0
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon47.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon48.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon48.png
new file mode 100644
index 0000000000..6b029f0a17
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon48.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon49.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon49.png
new file mode 100644
index 0000000000..e329da91b6
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon49.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon5.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon5.png
new file mode 100644
index 0000000000..4fda193c49
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon5.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon50.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon50.png
new file mode 100644
index 0000000000..d357202e6d
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon50.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon51.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon51.png
new file mode 100644
index 0000000000..d3c5a2d346
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon51.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon52.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon52.png
new file mode 100644
index 0000000000..ca7c4220a9
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon52.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon53.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon53.png
new file mode 100644
index 0000000000..f3ee370442
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon53.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon54.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon54.png
new file mode 100644
index 0000000000..c9a047e05e
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon54.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon55.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon55.png
new file mode 100644
index 0000000000..35d3b5a7c4
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon55.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon56.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon56.png
new file mode 100644
index 0000000000..44912aa767
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon56.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon57.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon57.png
new file mode 100644
index 0000000000..f87729a3fc
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon57.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon58.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon58.png
new file mode 100644
index 0000000000..b031cda549
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon58.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon59.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon59.png
new file mode 100644
index 0000000000..37241888fc
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon59.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon6.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon6.png
new file mode 100644
index 0000000000..74ff4016fc
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon6.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon60.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon60.png
new file mode 100644
index 0000000000..b8d636130d
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon60.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon61.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon61.png
new file mode 100644
index 0000000000..f37807f227
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon61.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon62.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon62.png
new file mode 100644
index 0000000000..8e91f014c8
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon62.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon63.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon63.png
new file mode 100644
index 0000000000..eb93bf536c
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon63.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon64.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon64.png
new file mode 100644
index 0000000000..5eee54dd42
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon64.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon65.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon65.png
new file mode 100644
index 0000000000..757cbb1047
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon65.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon66.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon66.png
new file mode 100644
index 0000000000..7ec3c175b6
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon66.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon67.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon67.png
new file mode 100644
index 0000000000..89547994eb
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon67.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon68.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon68.png
new file mode 100644
index 0000000000..41ba271e26
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon68.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon69.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon69.png
new file mode 100644
index 0000000000..2e9f59de0a
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon69.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon7.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon7.png
new file mode 100644
index 0000000000..86cfdf616c
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon7.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon70.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon70.png
new file mode 100644
index 0000000000..d9cc30556d
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon70.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon71.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon71.png
new file mode 100644
index 0000000000..b996b8de6b
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon71.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon72.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon72.png
new file mode 100644
index 0000000000..a93bb38648
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon72.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon73.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon73.png
new file mode 100644
index 0000000000..a3089c41eb
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon73.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon74.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon74.png
new file mode 100644
index 0000000000..a3d862aa22
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon74.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon75.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon75.png
new file mode 100644
index 0000000000..18e155874b
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon75.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon8.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon8.png
new file mode 100644
index 0000000000..946405b451
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon8.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon9.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon9.png
new file mode 100644
index 0000000000..43622cdd9c
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_music_animal_icon9.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_next_song.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_next_song.png
new file mode 100644
index 0000000000..a3898c5827
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_next_song.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_next_song_click.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_next_song_click.png
new file mode 100644
index 0000000000..6194927beb
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_next_song_click.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_no_heart.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_no_heart.png
new file mode 100644
index 0000000000..4c1d667884
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_no_heart.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_no_img_default_icon.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_no_img_default_icon.png
new file mode 100644
index 0000000000..d1978ce559
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_no_img_default_icon.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_play.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_play.png
new file mode 100644
index 0000000000..d46389d86e
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_play.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_click.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_click.png
new file mode 100644
index 0000000000..246b92c4a9
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_click.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_default_icon.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_default_icon.png
new file mode 100644
index 0000000000..bfaed8e0f5
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_default_icon.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_default_icon1.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_default_icon1.png
new file mode 100644
index 0000000000..38c4a43636
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_default_icon1.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_default_rect_icon.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_default_rect_icon.png
new file mode 100644
index 0000000000..51d4b92fe8
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_default_rect_icon.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_fail.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_fail.png
new file mode 100644
index 0000000000..b70bfed8c1
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_fail.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_normal.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_normal.png
new file mode 100644
index 0000000000..dcc359bf47
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_normal.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_success.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_success.png
new file mode 100644
index 0000000000..0005916564
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_share_success.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_suspend.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_suspend.png
new file mode 100644
index 0000000000..3dfa5da5c6
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_suspend.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_alert_bg.9.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_alert_bg.9.png
new file mode 100644
index 0000000000..96ddb81326
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_alert_bg.9.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_pop_next.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_pop_next.png
new file mode 100644
index 0000000000..d23e33246b
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_pop_next.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_pop_pause.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_pop_pause.png
new file mode 100644
index 0000000000..a908c23da5
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_pop_pause.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_pop_pause_new.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_pop_pause_new.png
new file mode 100644
index 0000000000..86f936f702
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_pop_pause_new.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_pop_play.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_pop_play.png
new file mode 100644
index 0000000000..ab6f5e4d7c
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_pop_play.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_pop_play_new.png b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_pop_play_new.png
new file mode 100644
index 0000000000..78e5680e91
Binary files /dev/null and b/modules/mogo-module-media/src/main/res/drawable-xhdpi/module_media_window_pop_play_new.png differ
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_bottom_revert_trianle_bg.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_bottom_revert_trianle_bg.xml
new file mode 100644
index 0000000000..19bc1f9d13
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_bottom_revert_trianle_bg.xml
@@ -0,0 +1,18 @@
+
+
+ -
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_card_back.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_card_back.xml
new file mode 100644
index 0000000000..71b9ee964e
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_card_back.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_card_tran_img_bg.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_card_tran_img_bg.xml
new file mode 100644
index 0000000000..fc072d2f97
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_card_tran_img_bg.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_circle_bg.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_circle_bg.xml
new file mode 100644
index 0000000000..4f0286a260
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_circle_bg.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_click_poi_bg_top.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_click_poi_bg_top.xml
new file mode 100644
index 0000000000..df19595e70
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_click_poi_bg_top.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_demo_selector.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_demo_selector.xml
new file mode 100644
index 0000000000..d17daeaa24
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_demo_selector.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_misic_progress_bar.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_misic_progress_bar.xml
new file mode 100644
index 0000000000..eb04bda3a3
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_misic_progress_bar.xml
@@ -0,0 +1,35 @@
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_next_bg_selector.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_next_bg_selector.xml
new file mode 100644
index 0000000000..3141e1a44a
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_next_bg_selector.xml
@@ -0,0 +1,14 @@
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_play_bg_selector.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_play_bg_selector.xml
new file mode 100644
index 0000000000..eafad48464
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_play_bg_selector.xml
@@ -0,0 +1,13 @@
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_progress_bg.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_progress_bg.xml
new file mode 100644
index 0000000000..11e0a400c7
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_progress_bg.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_progress_pop_bg.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_progress_pop_bg.xml
new file mode 100644
index 0000000000..a8e74c1033
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_progress_pop_bg.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_share_dialog_bg.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_share_dialog_bg.xml
new file mode 100644
index 0000000000..222dea52a8
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_share_dialog_bg.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_share_dialog_left_btn_bg.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_share_dialog_left_btn_bg.xml
new file mode 100644
index 0000000000..fad92a439a
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_share_dialog_left_btn_bg.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_share_dialog_right_btn_bg.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_share_dialog_right_btn_bg.xml
new file mode 100644
index 0000000000..111ff2af99
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_share_dialog_right_btn_bg.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_share_dialog_title_bg.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_share_dialog_title_bg.xml
new file mode 100644
index 0000000000..9037314b49
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_share_dialog_title_bg.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_share_toast_bg.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_share_toast_bg.xml
new file mode 100644
index 0000000000..c3ade0a821
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_share_toast_bg.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_user_share_music_back.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_user_share_music_back.xml
new file mode 100644
index 0000000000..42bde49ed3
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_user_share_music_back.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/drawable/module_media_window_progress_bar.xml b/modules/mogo-module-media/src/main/res/drawable/module_media_window_progress_bar.xml
new file mode 100644
index 0000000000..a62ffcda8f
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/drawable/module_media_window_progress_bar.xml
@@ -0,0 +1,32 @@
+
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/layout/module_media_bubble_marker.xml b/modules/mogo-module-media/src/main/res/layout/module_media_bubble_marker.xml
new file mode 100644
index 0000000000..0fc5b67336
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/layout/module_media_bubble_marker.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/layout/module_media_card_fragment_view.xml b/modules/mogo-module-media/src/main/res/layout/module_media_card_fragment_view.xml
new file mode 100644
index 0000000000..2223bb6dbf
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/layout/module_media_card_fragment_view.xml
@@ -0,0 +1,375 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/mogo-module-media/src/main/res/layout/module_media_dialog_cutom_layout.xml b/modules/mogo-module-media/src/main/res/layout/module_media_dialog_cutom_layout.xml
new file mode 100644
index 0000000000..e6aaae273c
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/layout/module_media_dialog_cutom_layout.xml
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/layout/module_media_music_window_alert_layout.xml b/modules/mogo-module-media/src/main/res/layout/module_media_music_window_alert_layout.xml
new file mode 100644
index 0000000000..7a0b082d3b
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/layout/module_media_music_window_alert_layout.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/mogo-module-media/src/main/res/layout/module_media_music_window_alert_layout_new.xml b/modules/mogo-module-media/src/main/res/layout/module_media_music_window_alert_layout_new.xml
new file mode 100644
index 0000000000..9002881140
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/layout/module_media_music_window_alert_layout_new.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/mogo-module-media/src/main/res/layout/module_media_share_fragment_view.xml b/modules/mogo-module-media/src/main/res/layout/module_media_share_fragment_view.xml
new file mode 100644
index 0000000000..6389fdef75
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/layout/module_media_share_fragment_view.xml
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/mogo-module-media/src/main/res/layout/module_media_share_toast_view.xml b/modules/mogo-module-media/src/main/res/layout/module_media_share_toast_view.xml
new file mode 100644
index 0000000000..73fc49ae04
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/layout/module_media_share_toast_view.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/mogo-module-media/src/main/res/values-xhdpi/colors.xml b/modules/mogo-module-media/src/main/res/values-xhdpi/colors.xml
new file mode 100644
index 0000000000..69b22338c6
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/values-xhdpi/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #008577
+ #00574B
+ #D81B60
+
diff --git a/modules/mogo-module-media/src/main/res/values-xhdpi/dimens.xml b/modules/mogo-module-media/src/main/res/values-xhdpi/dimens.xml
new file mode 100644
index 0000000000..75bfb5e9d1
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/values-xhdpi/dimens.xml
@@ -0,0 +1,129 @@
+
+
+ 872px
+ 1067px
+ 40px
+ 1760px
+
+ 660px
+ 660px
+ 20px
+ 23px
+ 67.5px
+ 67.5px
+ 67.5px
+ 10px
+ 23px
+ 116px
+ 30px
+ 145px
+ 20px
+ 30px
+ 90px
+ 90px
+ 21px
+ 24px
+ 23px
+ 26px
+ 30px
+ 16px
+ 68px
+ 68px
+ 23px
+ 35px
+ 56px
+ 56px
+ 126px
+ 3px
+ 116px
+ 116px
+ 22px
+ 37.5px
+ 28px
+
+
+
+ 790px
+ 525px
+ 55px
+ 61px
+ 20px
+ 136px
+ 20px
+ 136px
+ 34px
+ 40px
+ 30px
+ 34px
+ 40px
+ 60px
+ 96px
+ 130px
+ 4px
+ 6px
+
+ 600px
+ 140px
+ 116px
+ 116px
+ 112px
+ 30px
+ 80px
+ 101px
+ 60px
+ 115px
+ 230px
+ 14px
+ 35px
+ 24px
+ 56px
+ 40px
+ 8px
+ 16px
+ 16px
+ 500px
+ 350px
+ 20px
+ 120px
+ 36px
+ 20px
+
+ 660px
+ 660px
+ 20px
+ 22px
+ 22px
+ 348px
+ 348px
+ 226px
+ 226px
+ 36px
+ 28px
+ 4px
+ 2px
+ 11px
+ 22px
+ 21px
+ 4px
+ 6px
+ 2px
+
+ 15px
+ 78px
+ 107px
+ 53px
+ 2px
+ 64px
+ 6px
+ 12px
+ 6px
+ 8px
+ 180px
+
+ 60px
+ 750px
+ 120px
+ 270px
+ 30px
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/values-xhdpi/strings.xml b/modules/mogo-module-media/src/main/res/values-xhdpi/strings.xml
new file mode 100644
index 0000000000..952949198b
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/values-xhdpi/strings.xml
@@ -0,0 +1,3 @@
+
+ mogo-module-media
+
diff --git a/modules/mogo-module-media/src/main/res/values-xhdpi/styles.xml b/modules/mogo-module-media/src/main/res/values-xhdpi/styles.xml
new file mode 100644
index 0000000000..5885930df6
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/values-xhdpi/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/modules/mogo-module-media/src/main/res/values/attrs.xml b/modules/mogo-module-media/src/main/res/values/attrs.xml
new file mode 100644
index 0000000000..d8f98cf7bf
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/values/attrs.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/values/colors.xml b/modules/mogo-module-media/src/main/res/values/colors.xml
new file mode 100644
index 0000000000..7c39678a81
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/values/colors.xml
@@ -0,0 +1,9 @@
+
+
+ #fff
+ #7affffff
+ #444E6E
+ #f6ffffff
+ #1Affffff
+ #ffffff
+
diff --git a/modules/mogo-module-media/src/main/res/values/dimens.xml b/modules/mogo-module-media/src/main/res/values/dimens.xml
new file mode 100644
index 0000000000..d0351297ed
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/values/dimens.xml
@@ -0,0 +1,129 @@
+
+
+ 467px
+ 573px
+ 80px
+ 930px
+
+
+ 352px
+ 352px
+ 10.67px
+ 12px
+ 36px
+ 36px
+ 36px
+ 5px
+ 12px
+ 62px
+ 16px
+ 78px
+ 10.6px
+ 16px
+ 48px
+ 48px
+ 11px
+ 12px
+ 12px
+ 14px
+ 16px
+ 8px
+ 36px
+ 36px
+ 12px
+ 18px
+ 30px
+ 30px
+ 67.2px
+ 3px
+ 62px
+ 62px
+ 12px
+ 20px
+ 15px
+
+
+
+ 421px
+ 280px
+ 28px
+ 32.5px
+ 11.5px
+ 72.5px
+ 10.7px
+ 72.5px
+ 10px
+ 22px
+ 16px
+ 18px
+ 22px
+ 32px
+ 51px
+ 68px
+ 2px
+ 3.2px
+
+ 338px
+ 82px
+ 116px
+ 116px
+ 60px
+ 18px
+ 44px
+ 60px
+ 60px
+ 123px
+ 10px
+ 18px
+ 14px
+ 30px
+ 21px
+ 4px
+ 8px
+ 7px
+
+ 267px
+ 187px
+ 10px
+ 64px
+ 18px
+ 11px
+
+ 352px
+ 352px
+ 10.5px
+ 11px
+ 11.5px
+ 175px
+ 175px
+ 114px
+ 114px
+ 20px
+ 15px
+ 4px
+ 2px
+ 6px
+ 12px
+ 11px
+ 4px
+ 1px
+
+ 8px
+ 44px
+ 62px
+ 28px
+ 1px
+ 35px
+ 3.2px
+ 6.4px
+ 3px
+ 4px
+ 96px
+
+ 32px
+ 400px
+ 80px
+ 150px
+ 16px
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-media/src/main/res/values/strings.xml b/modules/mogo-module-media/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..913d27b8a0
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/values/strings.xml
@@ -0,0 +1,12 @@
+
+ mogo-module-media
+
+ 来自
+ 的分享
+ 是否确认分享此歌曲?
+ 是否确认分享此书?
+ 是否确认分享此新闻?
+ 分享成功
+ 分享失败
+
+
diff --git a/modules/mogo-module-media/src/main/res/values/styles.xml b/modules/mogo-module-media/src/main/res/values/styles.xml
new file mode 100644
index 0000000000..5885930df6
--- /dev/null
+++ b/modules/mogo-module-media/src/main/res/values/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/modules/mogo-module-media/src/test/java/com/mogo/module/media/ExampleUnitTest.java b/modules/mogo-module-media/src/test/java/com/mogo/module/media/ExampleUnitTest.java
new file mode 100644
index 0000000000..7a2aef7111
--- /dev/null
+++ b/modules/mogo-module-media/src/test/java/com/mogo/module/media/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.mogo.module.media;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/modules/mogo-module-splash-noop/.gitignore b/modules/mogo-module-splash-noop/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/modules/mogo-module-splash-noop/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/modules/mogo-module-splash-noop/build.gradle b/modules/mogo-module-splash-noop/build.gradle
new file mode 100644
index 0000000000..509929f10c
--- /dev/null
+++ b/modules/mogo-module-splash-noop/build.gradle
@@ -0,0 +1,58 @@
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlin-kapt'
+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")
+
+ javaCompileOptions {
+ annotationProcessorOptions {
+ arguments = [AROUTER_MODULE_NAME: project.getName()]
+ }
+ }
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles 'consumer-rules.pro'
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ compileOptions {
+ targetCompatibility 1.8
+ sourceCompatibility 1.8
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation rootProject.ext.dependencies.androidxccorektx
+ implementation rootProject.ext.dependencies.kotlinstdlibjdk7
+ implementation rootProject.ext.dependencies.androidxappcompat
+ implementation rootProject.ext.dependencies.androidxconstraintlayout
+ implementation rootProject.ext.dependencies.arouter
+ kapt rootProject.ext.dependencies.aroutercompiler
+ implementation rootProject.ext.dependencies.rxjava
+ implementation rootProject.ext.dependencies.rxandroid
+
+ if (Boolean.valueOf(RELEASE)) {
+ compileOnly rootProject.ext.dependencies.modulecommon
+ } else {
+ compileOnly project(':modules:mogo-module-common')
+ }
+}
+
+apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
diff --git a/modules/mogo-module-splash-noop/consumer-rules.pro b/modules/mogo-module-splash-noop/consumer-rules.pro
new file mode 100644
index 0000000000..3ef05240ac
--- /dev/null
+++ b/modules/mogo-module-splash-noop/consumer-rules.pro
@@ -0,0 +1 @@
+-keep class com.zhidao.mogo.module.splash.BydConst{*;}
\ No newline at end of file
diff --git a/modules/mogo-module-splash-noop/gradle.properties b/modules/mogo-module-splash-noop/gradle.properties
new file mode 100644
index 0000000000..33dc22af32
--- /dev/null
+++ b/modules/mogo-module-splash-noop/gradle.properties
@@ -0,0 +1,3 @@
+GROUP=com.mogo.module
+POM_ARTIFACT_ID=module-splash-noop
+VERSION_CODE=1
diff --git a/modules/mogo-module-splash-noop/proguard-rules.pro b/modules/mogo-module-splash-noop/proguard-rules.pro
new file mode 100644
index 0000000000..f5e721d80f
--- /dev/null
+++ b/modules/mogo-module-splash-noop/proguard-rules.pro
@@ -0,0 +1,23 @@
+# 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.mogo.module.splash.BydConst
\ No newline at end of file
diff --git a/modules/mogo-module-splash-noop/src/main/AndroidManifest.xml b/modules/mogo-module-splash-noop/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..2ace90a42d
--- /dev/null
+++ b/modules/mogo-module-splash-noop/src/main/AndroidManifest.xml
@@ -0,0 +1,3 @@
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-splash-noop/src/main/java/com/zhidao/mogo/module/splash/BydConst.kt b/modules/mogo-module-splash-noop/src/main/java/com/zhidao/mogo/module/splash/BydConst.kt
new file mode 100644
index 0000000000..74536ca572
--- /dev/null
+++ b/modules/mogo-module-splash-noop/src/main/java/com/zhidao/mogo/module/splash/BydConst.kt
@@ -0,0 +1,6 @@
+package com.zhidao.mogo.module.splash
+
+object BydConst {
+ const val MODULE_NAME = "MODULE_BYD"
+ const val PATH_NAME = "/carmachine/byd"
+}
\ No newline at end of file
diff --git a/modules/mogo-module-splash-noop/src/main/java/com/zhidao/mogo/module/splash/BydProvider.kt b/modules/mogo-module-splash-noop/src/main/java/com/zhidao/mogo/module/splash/BydProvider.kt
new file mode 100644
index 0000000000..9b134711e7
--- /dev/null
+++ b/modules/mogo-module-splash-noop/src/main/java/com/zhidao/mogo/module/splash/BydProvider.kt
@@ -0,0 +1,72 @@
+package com.zhidao.mogo.module.splash
+
+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.service.module.IMogoModuleLifecycle
+import com.mogo.service.module.IMogoModuleProvider
+import com.mogo.utils.logger.Logger
+import com.zhidao.mogo.module.splash.BydConst.MODULE_NAME
+import com.zhidao.mogo.module.splash.BydConst.PATH_NAME
+
+/**
+ * 比亚迪车机provider
+ *
+ * @author tongchenfei
+ */
+@Route(path = PATH_NAME)
+class BydProvider:IMogoModuleProvider {
+ override fun getNaviListener(): IMogoNaviListener? {
+ return null
+ }
+
+ override fun getLocationListener(): IMogoLocationListener? {
+ return null
+ }
+
+ override fun getType(): Int {
+ return 0
+ }
+
+ override fun getMarkerClickListener(): IMogoMarkerClickListener? {
+ return null
+ }
+
+ override fun init(context: Context?) {
+ Logger.d(MODULE_NAME, "比亚迪noop模块初始化===")
+ }
+
+ override fun getMapListener(): IMogoMapListener? {
+ return null
+ }
+
+ override fun getAppPackage(): String {
+ return ""
+ }
+
+ override fun createView(context: Context?): View? {
+ return null
+ }
+
+ override fun createFragment(context: Context?, data: Bundle?): Fragment? {
+ return null
+ }
+
+ override fun getModuleName(): String {
+ return MODULE_NAME
+ }
+
+ override fun getAppName(): String {
+ return ""
+ }
+
+ override fun getCardLifecycle(): IMogoModuleLifecycle? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/modules/mogo-module-splash/.gitignore b/modules/mogo-module-splash/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/modules/mogo-module-splash/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/modules/mogo-module-splash/build.gradle b/modules/mogo-module-splash/build.gradle
new file mode 100644
index 0000000000..509929f10c
--- /dev/null
+++ b/modules/mogo-module-splash/build.gradle
@@ -0,0 +1,58 @@
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlin-kapt'
+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")
+
+ javaCompileOptions {
+ annotationProcessorOptions {
+ arguments = [AROUTER_MODULE_NAME: project.getName()]
+ }
+ }
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles 'consumer-rules.pro'
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ compileOptions {
+ targetCompatibility 1.8
+ sourceCompatibility 1.8
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation rootProject.ext.dependencies.androidxccorektx
+ implementation rootProject.ext.dependencies.kotlinstdlibjdk7
+ implementation rootProject.ext.dependencies.androidxappcompat
+ implementation rootProject.ext.dependencies.androidxconstraintlayout
+ implementation rootProject.ext.dependencies.arouter
+ kapt rootProject.ext.dependencies.aroutercompiler
+ implementation rootProject.ext.dependencies.rxjava
+ implementation rootProject.ext.dependencies.rxandroid
+
+ if (Boolean.valueOf(RELEASE)) {
+ compileOnly rootProject.ext.dependencies.modulecommon
+ } else {
+ compileOnly project(':modules:mogo-module-common')
+ }
+}
+
+apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
diff --git a/modules/mogo-module-splash/consumer-rules.pro b/modules/mogo-module-splash/consumer-rules.pro
new file mode 100644
index 0000000000..633730835f
--- /dev/null
+++ b/modules/mogo-module-splash/consumer-rules.pro
@@ -0,0 +1,2 @@
+#-----ModuleSplash-----
+-keep class com.zhidao.mogo.module.splash.SplashConst{*;}
\ No newline at end of file
diff --git a/modules/mogo-module-splash/gradle.properties b/modules/mogo-module-splash/gradle.properties
new file mode 100644
index 0000000000..4c41034d70
--- /dev/null
+++ b/modules/mogo-module-splash/gradle.properties
@@ -0,0 +1,3 @@
+GROUP=com.mogo.module
+POM_ARTIFACT_ID=module-splash
+VERSION_CODE=1
diff --git a/modules/mogo-module-splash/proguard-rules.pro b/modules/mogo-module-splash/proguard-rules.pro
new file mode 100644
index 0000000000..f64d6a4170
--- /dev/null
+++ b/modules/mogo-module-splash/proguard-rules.pro
@@ -0,0 +1,24 @@
+# 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
+
+#-----ModuleSplash-----
+-keep class com.zhidao.mogo.module.splash.SplashConst.*{*;}
\ No newline at end of file
diff --git a/modules/mogo-module-splash/src/androidTest/java/com/zhidao/mogo/module/splash/ExampleInstrumentedTest.kt b/modules/mogo-module-splash/src/androidTest/java/com/zhidao/mogo/module/splash/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000000..b0d35cfd07
--- /dev/null
+++ b/modules/mogo-module-splash/src/androidTest/java/com/zhidao/mogo/module/splash/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.zhidao.mogo.module.splash
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.zhidao.mogo.module.byd.test", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/modules/mogo-module-splash/src/main/AndroidManifest.xml b/modules/mogo-module-splash/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..2ace90a42d
--- /dev/null
+++ b/modules/mogo-module-splash/src/main/AndroidManifest.xml
@@ -0,0 +1,3 @@
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-splash/src/main/java/com/zhidao/mogo/module/splash/SplashConst.kt b/modules/mogo-module-splash/src/main/java/com/zhidao/mogo/module/splash/SplashConst.kt
new file mode 100644
index 0000000000..a2ffcbd208
--- /dev/null
+++ b/modules/mogo-module-splash/src/main/java/com/zhidao/mogo/module/splash/SplashConst.kt
@@ -0,0 +1,6 @@
+package com.zhidao.mogo.module.splash
+
+object SplashConst {
+ const val MODULE_NAME = "MODULE_SPLASH"
+ const val PATH_NAME = "/splash/api"
+}
\ No newline at end of file
diff --git a/modules/mogo-module-splash/src/main/java/com/zhidao/mogo/module/splash/SplashProvider.kt b/modules/mogo-module-splash/src/main/java/com/zhidao/mogo/module/splash/SplashProvider.kt
new file mode 100644
index 0000000000..b3f4d9292d
--- /dev/null
+++ b/modules/mogo-module-splash/src/main/java/com/zhidao/mogo/module/splash/SplashProvider.kt
@@ -0,0 +1,78 @@
+@file:Suppress("DEPRECATION")
+
+package com.zhidao.mogo.module.splash
+
+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.commons.debug.DebugConfig
+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.service.module.IMogoModuleLifecycle
+import com.mogo.service.module.IMogoModuleProvider
+import com.mogo.utils.logger.Logger
+import com.zhidao.mogo.module.splash.SplashConst.MODULE_NAME
+import com.zhidao.mogo.module.splash.SplashConst.PATH_NAME
+import com.zhidao.mogo.module.splash.fragment.BydSplashFragment
+
+/**
+ * 比亚迪车机provider
+ *
+ * @author tongchenfei
+ */
+@Route(path = PATH_NAME)
+class SplashProvider : IMogoModuleProvider {
+ override fun getNaviListener(): IMogoNaviListener? {
+ return null
+ }
+
+ override fun getLocationListener(): IMogoLocationListener? {
+ return null
+ }
+
+ override fun getType(): Int {
+ return 0
+ }
+
+ override fun getMarkerClickListener(): IMogoMarkerClickListener? {
+ return null
+ }
+
+ override fun init(context: Context?) {
+ Logger.d(MODULE_NAME, "比亚迪模块初始化===")
+ }
+
+ override fun getMapListener(): IMogoMapListener? {
+ return null
+ }
+
+ override fun getAppPackage(): String {
+ return ""
+ }
+
+ override fun createView(context: Context?): View? {
+ return null
+ }
+
+ override fun createFragment(context: Context?, data: Bundle?): Fragment? = if (DebugConfig.getCarMachineType() == DebugConfig.CAR_MACHINE_TYPE_BYD) {
+ BydSplashFragment()
+ } else {
+ null
+ }
+
+ override fun getModuleName(): String {
+ return MODULE_NAME
+ }
+
+ override fun getAppName(): String {
+ return ""
+ }
+
+ override fun getCardLifecycle(): IMogoModuleLifecycle? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/modules/mogo-module-splash/src/main/java/com/zhidao/mogo/module/splash/fragment/BydSplashFragment.kt b/modules/mogo-module-splash/src/main/java/com/zhidao/mogo/module/splash/fragment/BydSplashFragment.kt
new file mode 100644
index 0000000000..1148d63378
--- /dev/null
+++ b/modules/mogo-module-splash/src/main/java/com/zhidao/mogo/module/splash/fragment/BydSplashFragment.kt
@@ -0,0 +1,55 @@
+package com.zhidao.mogo.module.splash.fragment
+
+import android.os.Handler
+import android.os.Message
+import com.mogo.commons.mvp.MvpFragment
+import com.zhidao.mogo.module.splash.R
+import com.zhidao.mogo.module.splash.presenter.BydSplashPresenter
+import kotlinx.android.synthetic.main.fragment_byd_splash.*
+
+const val DEFAULT_COUNT_DOWN_TIME = 5
+const val MSG_COUNT_DOWN = 1001
+const val DEFAULT_COUNT_DOWN_DELAY = 1000L
+class BydSplashFragment :MvpFragment(),Handler.Callback{
+ private val handler = Handler(this)
+ private var countDownTime = DEFAULT_COUNT_DOWN_TIME
+
+ override fun getLayoutId(): Int = R.layout.fragment_byd_splash
+
+ override fun initViews() {
+ startCountDown()
+ tvByd.setOnClickListener {
+ hideSplash()
+ }
+ }
+
+ override fun createPresenter(): BydSplashPresenter = BydSplashPresenter(this)
+
+ private fun startCountDown(){
+ handler.removeMessages(MSG_COUNT_DOWN)
+ countDownTime = DEFAULT_COUNT_DOWN_TIME
+ tvCountDown.text = countDownTime.toString()
+ handler.sendEmptyMessageDelayed(MSG_COUNT_DOWN, DEFAULT_COUNT_DOWN_DELAY)
+ }
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == MSG_COUNT_DOWN) {
+ tvCountDown?.also {
+ countDownTime--
+ if(countDownTime>0) {
+ it.text = countDownTime.toString()
+ handler.sendEmptyMessageDelayed(MSG_COUNT_DOWN, DEFAULT_COUNT_DOWN_DELAY)
+ }else{
+ hideSplash()
+ }
+ }
+ return true
+ }
+ return false
+ }
+
+ private fun hideSplash(){
+ handler.removeMessages(MSG_COUNT_DOWN)
+ activity!!.supportFragmentManager.beginTransaction().remove(this).commit()
+ }
+}
\ No newline at end of file
diff --git a/modules/mogo-module-splash/src/main/java/com/zhidao/mogo/module/splash/presenter/BydSplashPresenter.kt b/modules/mogo-module-splash/src/main/java/com/zhidao/mogo/module/splash/presenter/BydSplashPresenter.kt
new file mode 100644
index 0000000000..b16df959c7
--- /dev/null
+++ b/modules/mogo-module-splash/src/main/java/com/zhidao/mogo/module/splash/presenter/BydSplashPresenter.kt
@@ -0,0 +1,7 @@
+package com.zhidao.mogo.module.splash.presenter
+
+import com.mogo.commons.mvp.Presenter
+import com.zhidao.mogo.module.splash.fragment.BydSplashFragment
+
+class BydSplashPresenter(view: BydSplashFragment) : Presenter(view) {
+}
\ No newline at end of file
diff --git a/modules/mogo-module-splash/src/main/res/drawable-xhdpi-1920x1000/module_byd_splash.webp b/modules/mogo-module-splash/src/main/res/drawable-xhdpi-1920x1000/module_byd_splash.webp
new file mode 100644
index 0000000000..d39b3abe55
Binary files /dev/null and b/modules/mogo-module-splash/src/main/res/drawable-xhdpi-1920x1000/module_byd_splash.webp differ
diff --git a/modules/mogo-module-splash/src/main/res/drawable/byd_count_down_bg.xml b/modules/mogo-module-splash/src/main/res/drawable/byd_count_down_bg.xml
new file mode 100644
index 0000000000..83bc413969
--- /dev/null
+++ b/modules/mogo-module-splash/src/main/res/drawable/byd_count_down_bg.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-splash/src/main/res/drawable/byd_enter_btn_bg.xml b/modules/mogo-module-splash/src/main/res/drawable/byd_enter_btn_bg.xml
new file mode 100644
index 0000000000..e34b2f6181
--- /dev/null
+++ b/modules/mogo-module-splash/src/main/res/drawable/byd_enter_btn_bg.xml
@@ -0,0 +1,10 @@
+
+
+ -
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-splash/src/main/res/drawable/module_byd_splash.webp b/modules/mogo-module-splash/src/main/res/drawable/module_byd_splash.webp
new file mode 100644
index 0000000000..d39b3abe55
Binary files /dev/null and b/modules/mogo-module-splash/src/main/res/drawable/module_byd_splash.webp differ
diff --git a/modules/mogo-module-splash/src/main/res/layout/fragment_byd_splash.xml b/modules/mogo-module-splash/src/main/res/layout/fragment_byd_splash.xml
new file mode 100644
index 0000000000..bb79601719
--- /dev/null
+++ b/modules/mogo-module-splash/src/main/res/layout/fragment_byd_splash.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/mogo-module-splash/src/test/java/com/zhidao/mogo/module/splash/ExampleUnitTest.kt b/modules/mogo-module-splash/src/test/java/com/zhidao/mogo/module/splash/ExampleUnitTest.kt
new file mode 100644
index 0000000000..35aae2dff8
--- /dev/null
+++ b/modules/mogo-module-splash/src/test/java/com/zhidao/mogo/module/splash/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.zhidao.mogo.module.splash
+
+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)
+ }
+}
\ No newline at end of file