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 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 cls) { + openActivity(cls, null); + } + + public void openActivity(Class 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 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 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