Compare commits

..

103 Commits

Author SHA1 Message Date
e58cc2c405 删除 .gradle/caches/build-cache-1 缓存目录 2023-03-24 10:12:49 +08:00
32de24bb09 delete gradlew clean 2023-03-21 16:20:57 +08:00
481a0b5257 add gradlew clean 2023-03-21 15:56:41 +08:00
dd99610310 测试打包时间 2023-03-21 15:24:55 +08:00
448ded444f 新建minio cache 2023-03-21 14:46:02 +08:00
171f1b8e4e 新建minio cache 2023-03-21 14:17:37 +08:00
449cf76cb2 新建minio cache 2023-03-21 14:04:03 +08:00
f204cf3dda 测试aliyun 内网docker build 2023-03-21 10:17:22 +08:00
aa36af2193 修改镜像为aliyun 地址 2023-03-21 09:50:38 +08:00
e7d15fd874 测试打包时间 2023-03-21 09:33:09 +08:00
3b4d7767ec 复制缓存 2023-03-20 17:59:51 +08:00
2b7faed871 复制缓存 2023-03-20 17:55:44 +08:00
bfbef33054 GIT_SUBMODULE_STRATEGY: recursive 2023-03-20 17:47:48 +08:00
e996eb72a7 开启cache 2023-03-20 17:42:44 +08:00
67a7b7b5ce test 2023-03-20 17:27:38 +08:00
07ad819a50 tar gradle-cache 2023-03-20 17:04:05 +08:00
c965bed2f8 tar gradle-cache 2023-03-20 16:57:20 +08:00
5db36ab0aa tar gradle-cache 2023-03-20 16:35:13 +08:00
c14b06c3b9 tar gradle-cache 2023-03-20 16:33:19 +08:00
4297d5af70 tar gradle-cache 2023-03-20 16:31:56 +08:00
e230e5a7b6 tar gradle-cache 2023-03-20 16:23:29 +08:00
6e0fcef261 tar gradle-cache 2023-03-20 15:54:06 +08:00
c037a2ff91 tar gradle-cache 2023-03-20 15:23:28 +08:00
e7dc16d234 tar gradle-cache 2023-03-20 14:34:19 +08:00
b22edbba69 change Dockerfile path 2023-03-20 14:18:18 +08:00
a953f282ab change Dockerfile path 2023-03-20 14:08:21 +08:00
211bc0cacb change Dockerfile path 2023-03-20 13:56:25 +08:00
798f1fe2fa 注释GIT_STRATEGY: none 2023-03-20 13:50:42 +08:00
d8755eb3bd 注释GIT_STRATEGY: none 2023-03-20 13:50:39 +08:00
b42ef259d4 注释android_build 2023-03-20 13:48:34 +08:00
b6f6007c66 change Dockerfile path 2023-03-20 13:47:54 +08:00
17de6d423d change docker build arg 2023-03-20 11:50:59 +08:00
1386bb727d change artifacts path 2023-03-20 11:04:19 +08:00
2a6bc205df add docker build 2023-03-20 10:37:10 +08:00
38fd0144a5 change images 2023-03-17 15:37:31 +08:00
85ef012911 ci:change docker images 2023-03-03 16:33:12 +08:00
c480a631cd ci:change docker images 2023-03-03 16:18:04 +08:00
bfd1dda9b3 ci:change docker images 2023-03-03 16:08:44 +08:00
ac53235a09 ci: KUBERNETES_CPU_LIMIT: 12 2023-02-27 18:07:39 +08:00
87c9d85b51 change org.gradle.jvmargs 2023-02-27 17:27:47 +08:00
8fd5c669d0 ci: KUBERNETES_CPU_LIMIT: 16 2023-02-27 16:09:31 +08:00
cd1c3052f8 ci:change tags pve-local-runner 2023-02-24 10:13:53 +08:00
80e0163235 fix: plugin 添加内部 nexus 源 2023-02-23 16:27:24 +08:00
9867241e3a ci:add KUBERNETES_CPU_LIMIT 2023-02-23 15:32:06 +08:00
92f4058dfc ci:add KUBERNETES_CPU_LIMIT 2023-02-23 14:59:05 +08:00
4bd414566f ci:change tags offline-test 2023-02-23 14:23:41 +08:00
a472eabf6d ci:change tags local-runner 2023-02-23 14:23:41 +08:00
38f780e514 change org.gradle.jvmargs 2023-02-23 14:23:41 +08:00
dc7cb2abe3 change jvmargs 2023-02-23 14:23:41 +08:00
bfdba625b8 change jvmargs 2023-02-23 14:23:41 +08:00
fe10ef135b ci:change tags pve-local-runner 2023-02-23 14:23:41 +08:00
f600197d89 ci:change tags 2023-02-23 14:23:41 +08:00
8362e7d9da ci:change docker image 2023-02-23 14:23:41 +08:00
d92cae7af8 ci:change docker image 2023-02-23 14:23:41 +08:00
c48b786178 change build.gradle 2023-02-23 14:23:41 +08:00
0818e64fe3 change maven url 2023-02-23 14:23:41 +08:00
5983832aa9 add maven url 2023-02-23 14:23:41 +08:00
c833a53bcc add maven url 2023-02-23 14:23:41 +08:00
ad1b5dada3 change kotlin_version 1.7.1 2023-02-23 14:23:41 +08:00
8cd64dd4bc ci:change docker image 2023-02-23 14:23:41 +08:00
fe37a3bd31 ci:change docker image 2023-02-23 14:23:41 +08:00
f3c33decaf change docker image 2023-02-23 14:23:41 +08:00
2a79755777 优化app的build.gradle 2023-02-23 14:23:41 +08:00
a3601fd25c 优化app的build.gradle 2023-02-23 14:23:41 +08:00
40c55dc66f 优化app的build.gradle 2023-02-23 14:23:41 +08:00
e22c3c06b9 change build.gradle 2023-02-23 14:23:41 +08:00
0f7b5055b4 test cache 2023-02-23 14:23:41 +08:00
15246bbf31 change before_script 2023-02-23 14:23:41 +08:00
92b6f1570a change cache 2023-02-23 14:23:41 +08:00
8c195e01d8 change cache 2023-02-23 14:23:41 +08:00
2a7077efab test cache 2023-02-23 14:23:40 +08:00
b6c1aa2323 test cache 2023-02-23 14:23:40 +08:00
bf3ceec277 修改jvm 2023-02-23 14:23:40 +08:00
48b668cf98 修改jvm 2023-02-23 14:23:40 +08:00
b492002c42 修改jvm 2023-02-23 14:23:40 +08:00
7261b6b512 修改gradle 版本 2023-02-23 14:23:40 +08:00
0c04cc3559 ci修改配置 2023-02-23 14:23:40 +08:00
4cf5102534 ci修改配置 2023-02-23 14:23:40 +08:00
b99353475b ci修改cache 2023-02-23 14:23:40 +08:00
f8b88b1b4e ci修改cache 2023-02-23 14:23:40 +08:00
228c938311 修改jvmargs 2023-02-23 14:23:40 +08:00
48cc6c97f9 ci修改cache 缓存目录 2023-02-23 14:23:40 +08:00
87cc042389 增大jvmargs 2023-02-23 14:23:40 +08:00
ab7a27c84b ci修改cache 缓存目录 2023-02-23 14:23:40 +08:00
708314e680 ci修改cache 缓存目录 2023-02-23 14:23:40 +08:00
59f0265cca ci修改cache 缓存目录 2023-02-23 14:23:40 +08:00
1630d24471 ci添加 build 缓存目录 2023-02-23 14:23:40 +08:00
117da57157 添加.gradle/caches 缓存 2023-02-23 14:23:40 +08:00
5c66937b48 test 2023-02-23 14:23:40 +08:00
c2179a665f 修改jvmargs堆大小 2023-02-23 14:23:40 +08:00
10178a2712 修改tags为online 集群来跑android_build 2023-02-23 14:23:40 +08:00
3ab8b6fc15 ci: 更正邮件镜像 2023-02-23 14:23:40 +08:00
dd8989fd6b ci: 更新 ci 配置文件 2023-02-23 14:23:40 +08:00
9bf4439c5b ci: 更新 ci 编译配置 2023-02-23 14:23:40 +08:00
9fd726d28b ci: 更新 ci 编译配置 2023-02-23 14:23:40 +08:00
fc382c9c98 ci: 更新 ci 编译配置 2023-02-23 14:23:40 +08:00
743339ffb4 ci: 更新 ci 编译配置 2023-02-23 14:23:40 +08:00
0d4dcacae1 ci: 更新 ci 编译配置 2023-02-23 14:23:40 +08:00
9d601e9a39 ci: 更新 ci 编译配置 2023-02-23 14:23:40 +08:00
b8d2826aae ci: 添加 ci 编译配置 2023-02-23 14:23:40 +08:00
0e11b03256 ci: 添加 ci 编译配置 2023-02-23 14:23:40 +08:00
ad1e6ce608 ci: 添加 ci 编译配置 2023-02-23 14:23:40 +08:00
b03cba15d4 ci: 添加 ci 编译配置 2023-02-23 14:23:40 +08:00
4285 changed files with 65099 additions and 182804 deletions

4
.gitignore vendored
View File

@ -9,6 +9,4 @@ build/
release-app/ release-app/
test-app/ test-app/
scripts/apk-channel/ scripts/apk-channel/
app/src/test/java/com/gh/gamecenter app/src/test/java/com/gh/gamecenter
app/src/main/assets-debug/
app/src/main/assets-release/

View File

@ -1,161 +1,43 @@
# commit_sha 文件记录上一次成功流水线的commit sha用于定时计划检测是否有新代码提交有就执行流水线没有就终止流水线
cache:
# 不同的分支采用不同的 cache防止分支之间相互影响
key: "${CI_COMMIT_REF_SLUG}_commit_sha"
paths:
- commit_sha
policy: pull
# 将打包&发送apk包邮件job 和代码分析job 并行执行
stages: stages:
- build&analyze - android-build
- oss-upload&send-email - docker-build
- ci_sonar_mail
# 阻止了 合并请求 或 push分支和标签的流水线。 最后的 when: always 规则运行所有其他流水线类型,包括定时计划流水线。
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
when: always
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: never
- when: always
before_script:
# 检查是否存在 commit_sha 文件
- if [ -f commit_sha ]; then cat commit_sha; else echo "0000000" > commit_sha; fi
- export BEFORE_COMMIT_SHA=$(cat commit_sha)
# 比较commit sha ,若与上一次成功流水线的commit sha 相同,则退出流水线
- if [ "$CI_COMMIT_SHA" == "$BEFORE_COMMIT_SHA" ] && [ "$CI_PIPELINE_SOURCE" != "web" ]; then exit 137; fi
# 使用 .post 阶段使作业在流水线的末尾运行。.post 始终是流水线的最后阶段。
change_commit:
tags:
- offline-test
stage: .post
# 此job 跳过拉取git代码
variables:
GIT_STRATEGY: none
script:
# 更新 commit_sha
- if [ "$CI_COMMIT_SHA" != "$BEFORE_COMMIT_SHA" ]; then echo $CI_COMMIT_SHA > commit_sha; fi
cache:
# 不同的分支采用不同的 cache防止分支之间相互影响
key: "${CI_COMMIT_REF_SLUG}_commit_sha"
paths:
- commit_sha
policy: pull-push
allow_failure:
exit_codes: 137
android_build: android_build:
tags: tags:
# - local-runner
- offline-test - offline-test
stage: build&analyze stage: android-build
image: hub.shanqu.cc/library/ci-android:jdk11-sdk31-33 image: hub.shanqu.cc/devops/ci-android:jdk11
resource_group: android_build variables:
KUBERNETES_CPU_LIMIT: "16"
GIT_SUBMODULE_STRATEGY: recursive
Apk_Path: "app/build/outputs/apk/**/release/*.apk"
script:
- export GRADLE_USER_HOME=./.gradle
- chmod +x ./gradlew
- ./scripts/jenkins_build.sh -c
- rm -rf ./.gradle/caches/build-cache-1
cache:
paths:
- .gradle
only:
- feature-ci
# 构建推送docker镜像
docker-build:
tags:
- offline-test
stage: docker-build
variables: variables:
GIT_SUBMODULE_STRATEGY: recursive GIT_SUBMODULE_STRATEGY: recursive
KUBERNETES_CPU_LIMIT: "10" image: hub.shanqu.cc/library/docker:latest
script: script:
- export GRADLE_USER_HOME=/home/gitlab-runner/ci-build-cache/$CI_PROJECT_PATH/.gradle - imageName=`echo $CI_PROJECT_PATH | sed 's#/#-#g'`
- chmod +x ./gradlew - docker build -t registry.cn-shenzhen.aliyuncs.com/ghzs/$imageName:latest .
- ./scripts/jenkins_build.sh $CI_COMMIT_REF_NAME $BEFORE_COMMIT_SHA $CI_COMMIT_SHA - docker push registry.cn-shenzhen.aliyuncs.com/ghzs/$imageName:latest
#设置打包后的产物用于job之间共享 cache:
artifacts: paths:
paths: - .gradle
- app/build/tmp/*.apk policy: pull
expire_in: 48 hrs # 指定附件上载后保存的时间24h默认永久在Gitlab保存
allow_failure:
exit_codes: 137
only: only:
- dev - feature-ci
- release
- pack/update_sentry_plugin_cache
# 代码检查
sonarqube_analysis:
tags:
- offline-test
stage: build&analyze
image: hub.shanqu.cc/library/sonar-scanner-cli:latest
dependencies: [] #禁止传递来的artifact
script:
## 获取项目的一级组和二级组和项目名作为projectKey例如projectKey=platform-backend-eci-monitor
- group=`echo $CI_PROJECT_PATH | sed 's#/#-#g'`
- sonar-scanner
-Dsonar.host.url=http://sonarqube-server.sonarqube:9000/
-Dsonar.login=be43de7264ce4c4766eb0c020373c3e74e6df257
-Dsonar.jacoco.reportPaths=target/jacoco.exec
-Dsonar.projectKey=$group
-Dsonar.projectName=$CI_PROJECT_PATH
-Dsonar.sourceEncoding=UTF-8
-Dsonar.exclusions=**/vendor/**,**/errcode/**
-Dsonar.gitlab.project_id=$CI_PROJECT_ID
-Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA
-Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME
-Dsonar.gitlab.ci_merge_request_iid=$CI_MERGE_REQUEST_IID
-Dsonar.gitlab.merge_request_discussion=true
-Dsonar.java.binaries=.
-Dsonar.branch.name=$CI_COMMIT_REF_NAME
allow_failure:
exit_codes: 137
only:
- dev
- release
## 发送简易检测结果报告
send_sonar_report:
tags:
- offline-test
stage: ci_sonar_mail
image: hub.shanqu.cc/library/docker:latest
# 此job 跳过拉取git代码
variables:
GIT_STRATEGY: none
script:
- group=`echo $CI_PROJECT_PATH | sed 's#/#-#g'`
- docker run -e PROJECTKEY=$group -e EMAIL=$GITLAB_USER_EMAIL -e BRANCH=$CI_COMMIT_REF_NAME --name send-email --rm hub.shanqu.cc/platform/send-sonar-report:latest
allow_failure:
exit_codes: 137
only:
- dev
- release
oss-upload&send-email:
tags:
- sysadm-devops
stage: oss-upload&send-email
image: hub.shanqu.cc/devops/android-apk-oss-upload:latest
id_tokens:
VAULT_ID_TOKEN:
aud: https://vault.shanqu.cc
variables:
GIT_STRATEGY: none
VAULT_ADDR: https://vault.shanqu.cc # 固定值
VAULT_SECRET_PATH: prod/devops/android-apk-oss-upload # 固定值
VAULT_ROLE: android-apk-oss-upload # 固定值
ENDPOINT: "tos-cn-guangzhou.ivolces.com" # 固定值
BUCKET: "sysadm-public" # 固定值
FILE_PATH: "app/build/tmp/" # APK 存放路径
Email_To_List: $EMAIL_TO_LIST # 邮件接受人列表
Email_Title: "光环助手 $CI_COMMIT_BRANCH" # 邮件标题
PIPELINE_ID: $CI_PIPELINE_ID # 流水线id
COMMIT_BRANCH: $CI_COMMIT_BRANCH # 提交分支
MAIL_MESSAGE: "[$CI_COMMIT_AUTHOR] $CI_COMMIT_MESSAGE"
needs:
- job: android_build
artifacts: true
script:
### 绑定上传参数 ###
- export OSS_PATH="release/dev/${CI_PROJECT_NAME}/$(date "+%Y/%m/%d")"
### 开启上传 ###
- /usr/local/bin/python /upload.py
### 发送邮件
- /usr/local/bin/python /ci-android-mail-jira-comment.py
only:
- dev
- release
- pack/update_sentry_plugin_cache

6
.gitmodules vendored
View File

@ -5,9 +5,9 @@
[submodule "vspace-bridge"] [submodule "vspace-bridge"]
path = vspace-bridge path = vspace-bridge
url = ../../../cwzs/android/vspace-bridge.git url = ../../../cwzs/android/vspace-bridge.git
[submodule "module_common/src/debug/assets/assistant-android-mock"]
path = module_common/src/debug/assets/assistant-android-mock
url = ../../../halo/android/assistant-android-mock.git
[submodule "ndownload"] [submodule "ndownload"]
path = ndownload path = ndownload
url = ../../../android/ndownload.git url = ../../../android/ndownload.git
[submodule "vasdk"]
path = vasdk
url = ../../../sdg/android/vasdk.git

View File

@ -1,5 +1,6 @@
FROM openjdk:11-jdk FROM openjdk:11-jdk
WORKDIR /project WORKDIR /project
ARG CI_PROJECT_PATH=default_value
SHELL ["/bin/bash", "-c"] SHELL ["/bin/bash", "-c"]
#配置SDK环境变量 #配置SDK环境变量
ENV ANDROID_SDK_ROOT /usr/lib/sdk ENV ANDROID_SDK_ROOT /usr/lib/sdk
@ -7,9 +8,11 @@ ENV ANDROID_HOME /usr/lib/sdk
ENV PATH $ANDROID_SDK_ROOT:$PATH ENV PATH $ANDROID_SDK_ROOT:$PATH
ENV PATH=$PATH:${ANDROID_HOME}/cmdline-tools/cmdline-tools/bin/ ENV PATH=$PATH:${ANDROID_HOME}/cmdline-tools/cmdline-tools/bin/
ENV GRADLE_USER_HOME /project/.gradle ENV GRADLE_USER_HOME /project/.gradle
RUN source ~/.bashrc RUN source ~/.bashrc
RUN sed -i "s@http://\(deb\|security\).debian.org@https://mirrors.aliyun.com@g" /etc/apt/sources.list \ RUN sed -i "s@http://\(deb\|security\).debian.org@https://mirrors.aliyun.com@g" /etc/apt/sources.list \
&& apt-get --quiet update --yes \ && apt-get --quiet update --yes \
&& apt-get --quiet install --yes lib32stdc++6 lib32z1 libncurses5 util-linux bash tzdata librdkafka-dev pkgconf \ && apt-get --quiet install --yes wget lib32stdc++6 lib32z1 libncurses5 \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
COPY .gradle /project/.gradle
COPY . /project

View File

@ -30,7 +30,14 @@
### git 版本管理 ### git 版本管理
本项目使用简化版的 git flow 来管理分支,细节请看 [光环安卓简单 git 规范](https://git.shanqu.cc/halo/android/assistant-android/-/wikis/%E5%85%89%E7%8E%AF%E5%AE%89%E5%8D%93%E7%AE%80%E5%8D%95-git-%E8%A7%84%E8%8C%83) 本项目使用简化版的 git flow 来管理分支,细节请看 [光环安卓简单 git 规范](https://git.ghzs.com/halo/android/assistant-android/-/wikis/%E5%85%89%E7%8E%AF%E5%AE%89%E5%8D%93%E7%AE%80%E5%8D%95-git-%E8%A7%84%E8%8C%83)
### API 环境配置
本项目使用 Build Variants 来切换 API 环境
* internal 为测试环境
* publish 为正式环境
### 图片资源配置 ### 图片资源配置
@ -44,4 +51,16 @@
### 混淆配置 ### 混淆配置
* 本项目使用了微信的 [AndResGuard](https://github.com/shwenzhang/AndResGuard) 作为资源混淆压缩方案,新增需要使用 `getIdentifier` 获取的资源文件时需要添加至白名单
* 本项目默认使用 R8 作为混淆工具,往 proguard-rules.txt 添加 proguard 新配置项时请检查可用性(如语法等) * 本项目默认使用 R8 作为混淆工具,往 proguard-rules.txt 添加 proguard 新配置项时请检查可用性(如语法等)
### APK打包配置
> 打内部测试包:`./scripts/test_build.sh`
> 打邮件测试包:`./scripts/jenkins_build.sh`
### TODO
* 把原有 EventBus 的消息 Type 统一到一个文件内
* 将实现细节从 View(Fragment、Activity) 剥离并以 MVVM 结构改造
* 重构 MainActivity

View File

@ -3,27 +3,18 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' // kotlin apply plugin: 'kotlin-android' // kotlin
apply plugin: 'kotlin-parcelize' apply plugin: 'kotlin-parcelize'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
apply plugin: 'AndResGuard'
import groovy.xml.XmlUtil import groovy.xml.XmlUtil
android { android {
String CONFIG_ID = ""
String FIRST_LAUNCH = ""
String SDK_VERSION = ""
String SDK_APP_ID = ""
String SDK_APP_NAME = ""
boolean USE_DEFAULT_CHANNEL_SDK = true
int ACTIVATE_REPORTING_RATIO = 100
buildFeatures { buildFeatures {
viewBinding true viewBinding true
dataBinding true dataBinding true
} }
compileOptions { compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
@ -74,41 +65,18 @@ android {
versionName rootProject.ext.versionName versionName rootProject.ext.versionName
applicationId rootProject.ext.applicationId applicationId rootProject.ext.applicationId
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-fresco.txt', rootProject.ext.va_proguard_rules proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-fresco.txt'
String CORE_EVENT_GAME_CATEGORY = "" /**
* All third-party appid/appkey
// 推广用的关键事件游戏类型 */
buildConfigField "String", "CORE_EVENT_GAME_CATEGORY", "\"${CORE_EVENT_GAME_CATEGORY}\""
// 推广用的配置 id
buildConfigField "String", "CONFIG_ID", "\"${CONFIG_ID}\""
// 推广用的 SDK 版本 (仅记录使用)
buildConfigField "String", "SDK_VERSION", "\"${SDK_VERSION}\""
buildConfigField "String", "SDK_APP_ID", "\"${SDK_APP_ID}\""
buildConfigField "String", "SDK_APP_NAME", "\"${SDK_APP_NAME}\""
buildConfigField "boolean", "USE_DEFAULT_CHANNEL_SDK", "${USE_DEFAULT_CHANNEL_SDK}"
// 首次启动的跳转配置
buildConfigField "String", "FIRST_LAUNCH", "\"${FIRST_LAUNCH}\""
buildConfigField "int", "ACTIVATE_REPORTING_RATIO", "${ACTIVATE_REPORTING_RATIO}"
// All third-party appid/appkey
buildConfigField "boolean", "IS_GAT_APP", "false"
buildConfigField "String", "API_HOST", "\"${API_HOST}\"" buildConfigField "String", "API_HOST", "\"${API_HOST}\""
buildConfigField "String", "NEW_API_HOST", "\"${NEW_API_HOST}\"" buildConfigField "String", "NEW_API_HOST", "\"${NEW_API_HOST}\""
buildConfigField "String", "LOG_HUB_PROJECT", "\"${LOG_HUB_PROJECT}\""
buildConfigField "String", "VAPI_HOST", "\"${VAPI_HOST}\"" buildConfigField "String", "VAPI_HOST", "\"${VAPI_HOST}\""
buildConfigField "String", "WGAME_CPM_BUSIAPPID", "\"${WGAME_CPM_BUSIAPPID}\""
buildConfigField "String", "WGAME_CPM_API_HOST", "\"${WGAME_CPM_API_HOST}\""
buildConfigField "String", "WECHAT_APPID", "\"${WECHAT_APPID}\"" buildConfigField "String", "WECHAT_APPID", "\"${WECHAT_APPID}\""
buildConfigField "String", "WECHAT_SECRET", "\"${WECHAT_SECRET}\"" buildConfigField "String", "WECHAT_SECRET", "\"${WECHAT_SECRET}\""
buildConfigField "String", "TENCENT_APPID", "\"${TENCENT_APPID}\"" buildConfigField "String", "TENCENT_APPID", "\"${TENCENT_APPID}\""
buildConfigField "String", "WEIBO_APPKEY", "\"${WEIBO_APPKEY}\"" buildConfigField "String", "WEIBO_APPKEY", "\"${WEIBO_APPKEY}\""
// 一体包的32位畅玩游戏助手包名
buildConfigField "String", "EXT_PACKAGE_NAME", "\"${rootProject.ext.EXT_PACKAGE_NAME}\""
} }
// gradle 2.2以上默认同时启用v1和v2优先用于Android N // gradle 2.2以上默认同时启用v1和v2优先用于Android N
@ -129,23 +97,6 @@ android {
} }
} }
packagingOptions {
// exclude 部分冗余的文件
exclude 'META-INF/gradle/incremental.annotation.processors'
exclude 'darwin/x86_64/liblz4-java.dylib'
exclude 'assets/libwbsafeedit_x86'
exclude 'assets/libwbsafeedit_x86_64'
exclude 'lib/armeabi-v7a/libRSSupport.so'
exclude 'lib/arm64-v8a/libRSSupport.so'
exclude 'lib/armeabi-v7a/librsjni.so'
exclude 'lib/arm64-v8a/librsjni.so'
resources.excludes += "com/j256/*"
resources.excludes += "org/apache/commons/codec/language/bm/*"
}
buildTypes { buildTypes {
debug { debug {
debuggable true debuggable true
@ -176,23 +127,14 @@ android {
variantFilter { variant -> variantFilter { variant ->
def names = variant.flavors*.name def names = variant.flavors*.name
def isDebugType = variant.buildType.name == "debug" def isDebugType = variant.buildType.name == "debug"
if ((names.contains("tea") || name.contains("kuaishou") || name.contains("gdt")) && isDebugType) { if ((names.contains("tea") || name.contains("kuaishou")) && isDebugType) {
setIgnore(true) setIgnore(true)
} }
} }
flavorDimensions("env", "region") flavorDimensions("env")
sourceSets { sourceSets {
debug {
assets.srcDirs += 'src/main/assets-debug'
}
release {
assets.srcDirs += 'src/main/assets-release'
}
publish { publish {
java.srcDirs = ['src/main/java', "src/default/java"] java.srcDirs = ['src/main/java', "src/default/java"]
} }
@ -205,22 +147,10 @@ android {
kuaishou { kuaishou {
java.srcDirs = ['src/main/java', 'src/kuaishou/java'] java.srcDirs = ['src/main/java', 'src/kuaishou/java']
} }
gdt {
java.srcDirs = ['src/main/java', 'src/gdt/java']
}
gat {
java.srcDirs = ['src/main/java', 'src/gat/java']
}
cn {
java.srcDirs = ['src/main/java', 'src/cn/java']
}
sm {
java.srcDirs = ['src/main/java', 'src/sm/java']
}
} }
productFlavors { productFlavors {
// internal 内部测试包使用的 flavor接口包含包括测试和正式环境 // internal test dev host
internal { internal {
dimension "env" dimension "env"
versionNameSuffix "-debug" versionNameSuffix "-debug"
@ -230,14 +160,9 @@ android {
buildConfigField "String", "DEV_VAPI_HOST", "\"${DEV_VAPI_HOST}\"" buildConfigField "String", "DEV_VAPI_HOST", "\"${DEV_VAPI_HOST}\""
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${DEV_QUICK_LOGIN_APPID}\"" buildConfigField "String", "QUICK_LOGIN_APPID", "\"${DEV_QUICK_LOGIN_APPID}\""
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${DEV_QUICK_LOGIN_APPKEY}\"" buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${DEV_QUICK_LOGIN_APPKEY}\""
buildConfigField "String", "DEV_CSJ_APPID", "\"${DEV_CSJ_APPID}\""
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}-debug\""
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}-debug")
} }
// publish 发布时候使用的 flavor接口仅包含正式环境 // publish release host
publish { publish {
dimension "env" dimension "env"
@ -246,11 +171,6 @@ android {
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\"" buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\"" buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\"" buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}")
} }
tea { tea {
@ -261,13 +181,8 @@ android {
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\"" buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\"" buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\"" buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
manifestPlaceholders.put("APPLOG_SCHEME", "rangersapplog.byAx6uYt".toLowerCase()) manifestPlaceholders.put("APPLOG_SCHEME", "rangersapplog.byAx6uYt".toLowerCase())
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}")
} }
kuaishou { kuaishou {
@ -278,60 +193,6 @@ android {
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\"" buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\"" buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\"" buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}")
}
gdt {
dimension "env"
buildConfigField "String", "DEV_API_HOST", "\"${API_HOST}\""
buildConfigField "String", "NEW_DEV_API_HOST", "\"${NEW_API_HOST}\""
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}")
}
sm {
dimension "env"
buildConfigField "String", "DEV_API_HOST", "\"${API_HOST}\""
buildConfigField "String", "NEW_DEV_API_HOST", "\"${NEW_API_HOST}\""
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}")
}
// 港澳台
gat {
dimension "region"
applicationId rootProject.ext.applicationIdGat
// 支持繁体
resConfigs "zh", "zh-rTW"
buildConfigField "boolean", "IS_GAT_APP", "true"
buildConfigField "String", "LOG_HUB_PROJECT", "\"${LOG_HUB_PROJECT_GAT}\""
buildConfigField "String", "API_HOST", "\"${API_HOST_GAT}\""
buildConfigField "String", "NEW_API_HOST", "\"${NEW_API_HOST_GAT}\""
}
cn {
dimension "region"
} }
} }
} }
@ -342,35 +203,21 @@ repositories {
} }
} }
// 删除不需要的 assets
android.applicationVariants.configureEach { variant ->
variant.mergeAssets.doLast {
def assetDir = variant.mergeAssetsProvider.get().outputDir.get()
def unwantedAssets = ['2011394667', 'gdt_plugin/gdtadv2.jar']
unwantedAssets.each { assetPath ->
def file = new File([assetDir, assetPath].join(File.separator))
if (file.exists()) {
file.delete()
}
}
}
}
dependencies { dependencies {
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs') implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
teaImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/tea/libs') teaImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/tea/libs')
kuaishouImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/kuaishou/libs') kuaishouImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/kuaishou/libs')
gdtImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/gdt/libs') testImplementation 'junit:junit:4.12'
smImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/sm/libs')
debugImplementation "com.squareup.leakcanary:leakcanary-android:${leakcanary}" debugImplementation "com.squareup.leakcanary:leakcanary-android:${leakcanary}"
debugImplementation "com.squareup.leakcanary:leakcanary-android-process:${leakcanary}" debugImplementation "com.squareup.leakcanary:leakcanary-android-process:${leakcanary}"
// debugImplementation "com.gu.android:toolargetool:${toolargetool}" // 需要使用调试时才启用 // debugImplementation "com.gu.android:toolargetool:${toolargetool}" // 需要使用调试时才启用
debugImplementation "com.github.nichbar:WhatTheStack:${whatTheStack}" debugImplementation "com.github.nichbar:WhatTheStack:${whatTheStack}"
debugImplementation "io.github.didi.dokit:dokitx:${dokit}"
implementation "androidx.multidex:multidex:${multiDex}" implementation "androidx.multidex:multidex:${multiDex}"
implementation "androidx.fragment:fragment-ktx:${fragment}" implementation "androidx.fragment:fragment-ktx:${fragment}"
@ -380,8 +227,9 @@ dependencies {
implementation "androidx.viewpager2:viewpager2:${viewpager2}" implementation "androidx.viewpager2:viewpager2:${viewpager2}"
kapt "androidx.room:room-compiler:${room}" kapt "androidx.room:room-compiler:${room}"
implementation "com.tencent.vasdolly:helper:${apkChannelPackage}" implementation "com.kyleduo.switchbutton:library:${switchButton}"
implementation "com.tencent.vasdolly:writer:${apkChannelPackage}"
implementation "com.leon.channel:helper:${apkChannelPackage}"
implementation "com.j256.ormlite:ormlite-android:${ormlite}" implementation "com.j256.ormlite:ormlite-android:${ormlite}"
implementation "com.j256.ormlite:ormlite-core:${ormlite}" implementation "com.j256.ormlite:ormlite-core:${ormlite}"
@ -402,14 +250,13 @@ dependencies {
exclude module: "gsyvideoplayer-androidvideocache" exclude module: "gsyvideoplayer-androidvideocache"
exclude group: "tv.danmaku.ijk.media" exclude group: "tv.danmaku.ijk.media"
}) })
implementation ("com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer-exo_player2:$gsyVideo") { implementation "com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer-exo_player2:$gsyVideo"
exclude group: 'com.google.android.exoplayer', module: 'extension-rtmp'
} // implementation "androidx.work:work-runtime:${workManager}"
implementation "com.llew.huawei:verifier:${verifier}" implementation "com.llew.huawei:verifier:${verifier}"
teaImplementation "com.bytedance.applog:RangersAppLog-Lite-cn:${bytedanceApplog}" teaImplementation "com.bytedance.applog:RangersAppLog-Lite-cn:${bytedanceApplog}"
teaImplementation "com.bytedance.ads:AppConvert:${bytedanceAppConvert}"
implementation "net.lingala.zip4j:zip4j:${zip4j}" implementation "net.lingala.zip4j:zip4j:${zip4j}"
@ -418,111 +265,41 @@ dependencies {
implementation "com.lg:easyfloat:${easyFloat}" implementation "com.lg:easyfloat:${easyFloat}"
implementation("com.lg:apksig:${apksig}") { implementation "io.github.florent37:shapeofview:${shapeOfView}"
exclude group: 'com.google.protobuf'
} implementation "com.lg:apksig:${apksig}"
implementation "com.lg:gid:${gid}" implementation "com.lg:gid:${gid}"
implementation "com.lg:shortcut:${shortcut}" compileOnly "com.github.axen1314.lancet:lancet-base:${lancet_version}"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:${desugarJdkLibs}"
kapt "com.alibaba:arouter-compiler:$arouterVersion" kapt "com.alibaba:arouter-compiler:$arouterVersion"
implementation project(':ndownload') implementation project(':ndownload')
implementation project(':vspace-bridge:vspace') implementation project(':vspace-bridge:vspace')
implementation(project(':feature:xapk-installer'))
implementation(project(':module_common')) { implementation (project(':module_common')) {
exclude group: 'androidx.swiperefreshlayout' exclude group: 'androidx.swiperefreshlayout'
} }
implementation(project(':module_login')) { implementation(project(':module_login')) {
exclude group: 'androidx.swiperefreshlayout' exclude group: 'androidx.swiperefreshlayout'
} }
implementation(project(':module_core_feature')) {
exclude group: 'androidx.swiperefreshlayout'
}
implementation(project(':module_setting')) { implementation(project(':module_setting')) {
exclude group: 'androidx.swiperefreshlayout' exclude group: 'androidx.swiperefreshlayout'
} }
// implementation(project(':module_setting_compose')) {
// implementation(project(':module_setting_compose')) { // exclude group: 'androidx.swiperefreshlayout'
// exclude group: 'androidx.swiperefreshlayout' // }
// } implementation(project(':module_core_feature')){
exclude group: 'androidx.swiperefreshlayout'
if (!gradle.ext.excludeOptionalModules || gradle.ext.enablePkg) {
implementation(project(':feature:pkg'))
} }
implementation(project(':module_feedback')) {
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableFeedback) { exclude group: 'androidx.swiperefreshlayout'
implementation(project(':feature:new_feedback')) {
exclude group: 'androidx.swiperefreshlayout'
}
} }
// 默认不接入光能模块,提高编译速度
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableMessage) { // debugImplementation(project(':module_energy')) {
implementation(project(':module_message')) { // exclude group: 'androidx.swiperefreshlayout'
exclude group: 'androidx.swiperefreshlayout' // }
}
}
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableOaid) {
implementation(project(':feature:oaid'))
}
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableFloatingWindow) {
implementation(project(':feature:floating-window'))
}
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableSensorData) {
implementation(project(':module_sensors_data')) {
exclude group: 'androidx.swiperefreshlayout'
}
}
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableCsjAd) {
implementation(project(':feature:csj_ad'))
}
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableQQGame) {
implementation(project(':feature:qq_game')) {
exclude group: 'androidx.swiperefreshlayout'
}
}
if (!gradle.ext.excludeOptionalModules || gradle.ext.enablePush) {
def pushProperty = findProperty('BUILD_PUSH_TYPE')
// 根据BUILD_PUSH_TYPE决定使用哪个推送SDK目前默认使用极光推送
def pushProject = (pushProperty == null || pushProperty == 'jg')
? project(':feature:jg_push') : project(':feature:acloud_push')
implementation(pushProject) {
exclude group: 'androidx.swiperefreshlayout'
}
}
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableSentry) {
implementation(project(':feature:sentry'))
}
implementation(project(':feature:media_select'))
implementation(project(":module_va_api"))
implementation(project(":va-archive-common"))
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableVa) {
implementation(project(":module_va_impl"))
}
debugImplementation "com.bytedance.tools.codelocator:codelocator-core:2.0.3"
internalImplementation(project(':module_internal_test'))
debugImplementation 'com.bytedance.android:shadowhook:1.0.9'
debugImplementation 'io.github.shiqos:wytrace:1.0.1'
} }
File propFile = file('sign.properties') File propFile = file('sign.properties')
if (propFile.exists()) { if (propFile.exists()) {
Properties props = new Properties() Properties props = new Properties()
@ -580,6 +357,101 @@ if (propFile.exists()) {
// }.each { t -> t.dependsOn generateMetaJson } // }.each { t -> t.dependsOn generateMetaJson }
//} //}
andResGuard {
mappingFile = null
use7zip = true
useSign = true
// 打开这个开关会keep住所有资源的原始路径只混淆资源的名字
keepRoot = false
// 设置这个值会把arsc name列混淆成相同的名字减少string常量池的大小
fixedResName = "arg"
// 打开这个开关会合并所有哈希值相同的资源,但请不要过度依赖这个功能去除去冗余资源
mergeDuplicatedRes = true
whiteList = [
"R.drawable.icon",
"R.drawable.ic_bar_back",
"R.drawable.toolbar_search_icon",
"R.drawable.bg_notification_answer_style_1",
"R.drawable.bg_notification_answer_style_2",
"R.drawable.bg_notification_article_style_1",
"R.drawable.bg_notification_article_style_2",
"R.drawable.bg_notification_feedback_style_1",
"R.drawable.bg_notification_feedback_style_2",
"R.drawable.bg_notification_gift_style_1",
"R.drawable.bg_notification_gift_style_2",
"R.drawable.bg_notification_login_style_1",
"R.drawable.bg_notification_login_style_2",
"R.drawable.bg_notification_question_style_1",
"R.drawable.bg_notification_question_style_2",
"R.drawable.bg_notification_rating_style_1",
"R.drawable.bg_notification_rating_style_2",
"R.drawable.bg_notification_reserve_game_style_1",
"R.drawable.bg_notification_reserve_game_style_2",
"R.drawable.bg_notification_video_style_1",
"R.drawable.bg_notification_video_style_2",
"R.drawable.ic_recommend_activity",
"R.drawable.ic_recommend_discount",
"R.drawable.ic_recommend_function",
"R.drawable.ic_recommend_gift",
"R.drawable.ic_recommend_role",
"R.drawable.download_button_normal_style",
"R.drawable.ic_selector_selected",
"R.drawable.ic_selector_default",
"R.id.download_speed",
"R.id.download_percentage",
"R.id.comment",
"R.id.vote",
"R.id.watermark_hint",
"R.id.watermark_sb",
"R.id.bottomShareIv",
"R.id.bottomShareTv",
"R.id.recommendStarPref",
"R.id.recommendStar",
"R.id.iv_vmode_badge",
"R.id.tv_vmode",
"R.id.iv_vmode",
"R.drawable.help_search_delete",
"R.drawable.suggest_type_normal",
"R.drawable.suggest_type_crash",
"R.drawable.suggest_type_game_question",
"R.drawable.suggest_type_game_collect",
"R.drawable.suggest_type_function_suggest",
"R.drawable.suggest_type_article_collect",
"R.drawable.suggest_type_copyright",
"R.drawable.news_comment_detail_read",
"R.drawable.news_comment_detail_comment",
"R.drawable.news_comment_detail_share",
"R.drawable.ic_libao",
"R.drawable.ic_link",
"R.drawable.concern_message_icon",
"R.drawable.reuse_blank_hint",
"R.drawable.ic_concern",
"R.drawable.concern_down",
"R.drawable.concern_up",
"R.drawable.ic_libao_more",
"R.drawable.ic_libao_delete",
"R.drawable.ic_dialog_close",
"R.drawable.occupy2",
"R.drawable.kc_checkbox_unselect",
"R.drawable.kc_checkbox_select",
"R.drawable.ic_type_unselect",
"R.drawable.ic_type_selected",
"R.drawable.suggest_add_pic_icon",
"R.drawable.icon_pic_add",
"R.drawable.ask_search_input_delete",
"R.drawable.suggest_pic_delete"
]
compressFilePattern = [
"*.png",
"*.jpg",
"*.jpeg",
"*.gif",
]
sevenzip {
artifact = 'io.github.leon406:SevenZip:1.2.22.5'
}
}
project.afterEvaluate { project.afterEvaluate {
def variants = null def variants = null
try { try {
@ -662,4 +534,4 @@ project.afterEvaluate {
} }
} }
} }
} }

View File

@ -20,13 +20,11 @@
-keep class com.gh.gamecenter.db.info.* {*;} -keep class com.gh.gamecenter.db.info.* {*;}
-keep class com.gh.gamecenter.entity.** {<fields>;} -keep class com.gh.gamecenter.entity.** {<fields>;}
-keep class com.gh.gamecenter.qa.entity.** {<fields>;} -keep class com.gh.gamecenter.qa.entity.** {<fields>;}
-keep class com.gh.download.DownloadDataSimpleEntity {<fields>;}
-keep class com.gh.gamecenter.floatingwindow.FloatingWindowEntity {<fields>;}
-keep class com.gh.gamecenter.BR -keep class com.gh.gamecenter.BR
-keep class com.gh.gamecenter.retrofit.* {*;} -keep class com.gh.gamecenter.retrofit.* {*;}
-keep class com.gh.gamecenter.eventbus.* {*;} -keep class com.gh.gamecenter.eventbus.* {*;}
-keep class com.gh.gamecenter.home.gamecollection.carousel.GameCollectionStackLayout {*;} -keep class com.gh.gamecenter.home.gamecollection.GameCollectionStackLayout {*;}
-keep class com.gh.gamecenter.home.gamecollection.carousel.GameCollectionStackAnimation {*;} -keep class com.gh.gamecenter.home.gamecollection.GameCollectionStackAnimation {*;}
# Prevent R8 from leaving Data object members always null # Prevent R8 from leaving Data object members always null
-keepclassmembers,allowobfuscation class * { -keepclassmembers,allowobfuscation class * {
@ -64,35 +62,11 @@
public <init>(android.content.Context, android.util.AttributeSet, int); public <init>(android.content.Context, android.util.AttributeSet, int);
} }
### RecyclerView.jumpToPositionForSmoothScroller
-keep class androidx.recyclerview.widget.RecyclerView {
void jumpToPositionForSmoothScroller(int);
}
### ViewBinding 反射相关
-keep class * implements androidx.viewbinding.ViewBinding {
public static *** inflate(android.view.LayoutInflater, android.view.ViewGroup, boolean);
}
### TEA ### TEA
-keep class com.gh.gamecenter.TeaHelper { *; } -keep class com.gh.gamecenter.TeaHelper { *; }
### EasyFloat ### EasyFloat
-keep class com.lzf.easyfloat.* {*;} -keep class com.lzf.easyfloat.* {*;}
### 广点通SDK ### dokit
-dontwarn com.qq.gdt.action.** -keep class com.didichuxing.** {*;}
-keep class com.qq.gdt.action.** {*;}
-keep public class com.tencent.turingfd.sdk.**
### 神马 SDK
-dontwarn com.gism.**
-keepclasseswithmembers class * {
native <methods>;
}
-keepclassmembernames class com.contrarywind.view.WheelView {
private int itemsVisible;
}

View File

@ -8,7 +8,7 @@ import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.PackageFlavorHelper import com.gh.gamecenter.common.utils.PackageFlavorHelper
import com.gh.gamecenter.core.provider.IFlavorProvider import com.gh.gamecenter.core.provider.IFlavorProvider
import com.gh.gamecenter.core.utils.SPUtils import com.gh.gamecenter.core.utils.SPUtils
import com.tencent.vasdolly.helper.ChannelReaderUtil import com.leon.channel.helper.ChannelReaderUtil
class FlavorProviderImp : IFlavorProvider { class FlavorProviderImp : IFlavorProvider {
override fun getChannelStr(application: Application): String { override fun getChannelStr(application: Application): String {
@ -26,15 +26,11 @@ class FlavorProviderImp : IFlavorProvider {
return channel return channel
} }
override fun init(application: Application, activity: Activity, activateRatio: Int) { override fun init(application: Application, activity: Activity) {
// do nothing // do nothing
} }
override fun logEvent(content: String) { override fun logEvent(content: String) {
// do nothing // do nothing
} }
override fun logCoreEvent() {
// do nothing
}
} }

View File

@ -1,47 +0,0 @@
package com.gh.gamecenter
import android.app.Application
import com.lightgame.utils.Utils
import com.qq.gdt.action.ActionParam
import com.qq.gdt.action.ActionType
import com.qq.gdt.action.GDTAction
import com.qq.gdt.action.PrivateController
import org.json.JSONObject
object GdtHelper {
private const val USER_ACTION_SET_ID = "1201041887"
private const val APP_SECRET_ID = "c29cc5c48cf540c43b4b97363bb09216"
private const val KS_USER_ACTION_SET_ID = "1201032128"
private const val KS_APP_SECRET_ID = "9bdbbb81d4e0bd333a2a581f9ee36986"
@JvmStatic
fun init(application: Application, channel: String) {
GDTAction.setPrivateController(object : PrivateController() {
override fun isCanUsePhoneState(): Boolean {
return false
}
})
if (channel == "KS_GDT_GHZS_MC01") {
GDTAction.init(application, KS_USER_ACTION_SET_ID, KS_APP_SECRET_ID, channel)
} else {
GDTAction.init(application, USER_ACTION_SET_ID, APP_SECRET_ID, channel)
}
GDTAction.start()
Utils.log("init GdtHelper")
}
@JvmStatic
fun logAction(type: String) {
when (type) {
"EVENT_ACTIVE" -> GDTAction.logAction(ActionType.START_APP)
"active_register" -> GDTAction.logAction(ActionType.REGISTER)
"EVENT_NEXTDAY_STAY" -> GDTAction.logAction(ActionType.START_APP, JSONObject().apply {
put(ActionParam.Key.LENGTH_OF_STAY, 1)
})
}
}
}

View File

@ -1,52 +0,0 @@
package com.gh.gamecenter.provider
import android.app.Activity
import android.app.Application
import android.text.TextUtils
import com.gh.gamecenter.GdtHelper
import com.gh.gamecenter.core.provider.IFlavorProvider
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.TimeUtils
import com.halo.assistant.HaloApp
import com.tencent.vasdolly.helper.ChannelReaderUtil
class FlavorProviderImp : IFlavorProvider {
override fun init(application: Application, activity: Activity, activateRatio: Int) {
GdtHelper.init(application, getChannelStr(application))
if (HaloApp.getInstance().isBrandNewInstall) {
logEvent("EVENT_ACTIVE")
SPUtils.setLong("TIME_OF_BRAND_NEW_INSTALL", System.currentTimeMillis() / 1000)
} else {
val shouldSendRetentionLogEvent =
SPUtils.getBoolean("SHOULD_SEND_RETENTION_EVENT", true)
val installTimeNotToday =
!TimeUtils.isToday(SPUtils.getLong("TIME_OF_BRAND_NEW_INSTALL", System.currentTimeMillis() / 1000))
if (shouldSendRetentionLogEvent && installTimeNotToday) {
logEvent("EVENT_NEXTDAY_STAY")
SPUtils.setBoolean("SHOULD_SEND_RETENTION_EVENT", false)
}
}
}
override fun getChannelStr(application: Application): String {
var channel = ChannelReaderUtil.getChannel(application)
if (channel == null || TextUtils.isEmpty(channel.trim())) {
channel = GDT_DEFAULT_CHANNEL
}
return channel
}
override fun logEvent(content: String) {
GdtHelper.logAction(content)
}
override fun logCoreEvent() {
// do nothing
}
companion object {
private const val GDT_DEFAULT_CHANNEL = "GDT_GHZS_01"
}
}

View File

@ -1,42 +0,0 @@
package com.gh.vspace
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.Keep
import com.gh.gamecenter.R
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.databinding.LayoutPersonalOtherItemBinding
import com.gh.vspace.installexternalgames.InstallExternalGameActivity
import com.lightgame.utils.Utils
import java.io.File
@Keep
class ExternalGameUsage : ITestCase {
private fun buttonTemplate(viewParent: ViewGroup, id: Int, fn: (LayoutPersonalOtherItemBinding) -> Unit) {
val context = viewParent.context
viewParent.findViewById<View>(id) ?: run {
val binding = LayoutPersonalOtherItemBinding.inflate(LayoutInflater.from(context)).apply {
root.id = id
fn(this)
}
viewParent.addView(binding.root, 0)
}
}
override fun addInstallExternalGameButton(viewParent: ViewGroup) {
val context = viewParent.context
buttonTemplate(viewParent, R.id.install_game_from_external) {
it.titleTv.text = context.getString(R.string.title_install_external_game)
it.iconIv.setImageResource(R.drawable.ic_personal_my_game)
it.root.setOnClickListener {
context.startActivity(
InstallExternalGameActivity.getIntent(context)
.apply { flags = flags or Intent.FLAG_ACTIVITY_NEW_TASK })
}
}
}
}

View File

@ -1,5 +0,0 @@
package com.gh.vspace.installexternalgames;
public class Constants {
public static final String TAG = "从SD卡安装";
}

View File

@ -1,52 +0,0 @@
package com.gh.vspace.installexternalgames
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.utils.toBinding
class ExternalGameAdapter(private val games: List<ExternalGameUiState>, private val onItemClickListener: OnItemClickListener) :
RecyclerView.Adapter<ExternalGameViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ExternalGameViewHolder {
return ExternalGameViewHolder(parent.toBinding())
}
override fun getItemCount(): Int {
return games.size
}
override fun onBindViewHolder(holder: ExternalGameViewHolder, position: Int) {
val item = games[position]
holder.apkInfo.text = item.externalGameEntity.let { item ->
"""
应用程序名:${item.appName}
版本号:${item.apkVersion}
包名: ${item.apkPackageName}
路径:${item.apkPath}
""".trimIndent()
}
holder.update.setOnClickListener {
onItemClickListener.onItemClick(item, OnItemClickListener.ClickType.CLICK_INSTALL)
}
holder.install.goneIf(item.isInstalled) {
holder.install.setOnClickListener {
onItemClickListener.onItemClick(item, OnItemClickListener.ClickType.CLICK_INSTALL)
}
}
holder.uninstall.goneIf(!item.isInstalled) {
holder.uninstall.setOnClickListener {
onItemClickListener.onItemClick(
item,
OnItemClickListener.ClickType.CLICK_UNINSTALL
)
}
}
holder.start.goneIf(!item.isInstalled) {
holder.start.setOnClickListener {
onItemClickListener.onItemClick(item, OnItemClickListener.ClickType.CLICK_START)
}
}
}
}

View File

@ -1,11 +0,0 @@
package com.gh.vspace.installexternalgames
data class ExternalGameEntity(
val cpuAbi: Set<String>,
val apkPath: String,
val apkFileName: String,
val appName: String,
val apkVersion: String,
val apkPackageName: String,
val lastModified: Long,
)

View File

@ -1,6 +0,0 @@
package com.gh.vspace.installexternalgames
data class ExternalGameUiState(
val externalGameEntity: ExternalGameEntity,
val isInstalled: Boolean
)

View File

@ -1,12 +0,0 @@
package com.gh.vspace.installexternalgames
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.databinding.LayoutExternalGameItemBinding
class ExternalGameViewHolder(binding: LayoutExternalGameItemBinding) : RecyclerView.ViewHolder(binding.root) {
val apkInfo = binding.apkFileInfo
val install = binding.btnInstall
val uninstall = binding.btnUninstall
val start = binding.btnStart
val update = binding.btnUpdate
}

View File

@ -1,14 +0,0 @@
package com.gh.vspace.installexternalgames
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.gh.gamecenter.common.base.activity.ToolBarActivity
class InstallExternalGameActivity : ToolBarActivity() {
companion object {
fun getIntent(context: Context): Intent {
return getTargetIntent(context, InstallExternalGameActivity::class.java, InstallExternalGameFragment::class.java, Bundle())
}
}
}

View File

@ -1,200 +0,0 @@
package com.gh.vspace.installexternalgames
import android.Manifest
import android.app.Dialog
import android.content.ComponentName
import android.content.pm.PackageManager
import android.os.Bundle
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.gh.common.util.DialogUtils
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
import com.gh.gamecenter.common.exposure.meta.MetaUtil
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.common.view.divider.HorizontalDividerItemDecoration
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.databinding.FragmentInstallExternalGamesBinding
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lg.vspace.VirtualAppManager
import com.lightgame.download.DownloadEntity
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
private val mViewModel: InstallExternalGameViewModel by lazy { viewModelProvider() }
private lateinit var mBinding: FragmentInstallExternalGamesBinding
private val games = mutableListOf<ExternalGameUiState>()
private var adapter = ExternalGameAdapter(games, this)
private var uninstallDisposable: Disposable? = null
override fun getLayoutId() = 0
override fun getInflatedLayout() =
FragmentInstallExternalGamesBinding.inflate(layoutInflater).apply { mBinding = this }.root
private lateinit var dialog: Dialog
private val requestPermissionLauncher = registerForActivityResult<String, Boolean>(
ActivityResultContracts.RequestPermission()
) { result ->
if (result == true) {
// grant
mViewModel.scanPaths()
} else {
// not grant
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setNavigationTitle(getString(com.gh.gamecenter.R.string.title_install_external_game))
initView()
mViewModel.gamesList.observe(this) {
if (dialog.isShowing) {
dialog.dismiss()
}
games.clear()
games.addAll(
it.map {
ExternalGameUiState(it, VHelper.isInstalled(it.apkPackageName))
}
)
adapter.notifyDataSetChanged()
}
requestStoragePermission()
}
private fun requestStoragePermission() {
when {
ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.READ_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED -> {
mViewModel.scanPaths()
}
shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE) -> {
requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
}
else -> {
requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
}
}
}
private fun initView() {
dialog = DialogUtils.showWaitDialog(requireContext(), "")
mBinding.externalGamesList.let {
it.adapter = adapter
it.layoutManager = LinearLayoutManager(requireContext())
val itemDecoration = HorizontalDividerItemDecoration.Builder(requireContext())
.size(2F.dip2px())
.color(com.gh.gamecenter.common.R.color.ui_divider.toColor(requireContext()))
.build()
if (it.itemDecorationCount != 0) {
it.removeItemDecorationAt(0)
}
it.addItemDecoration(itemDecoration)
}
}
override fun onDestroy() {
super.onDestroy()
if (dialog.isShowing) {
dialog.dismiss()
}
if (uninstallDisposable?.isDisposed != true) {
uninstallDisposable?.dispose()
}
}
override fun onItemClick(externalGameUiState: ExternalGameUiState, clickType: OnItemClickListener.ClickType) {
when (clickType) {
OnItemClickListener.ClickType.CLICK_INSTALL -> {
install(externalGameUiState)
}
OnItemClickListener.ClickType.CLICK_UNINSTALL -> {
uninstall(externalGameUiState)
}
OnItemClickListener.ClickType.CLICK_START -> {
start(externalGameUiState)
}
}
}
private fun install(externalGameUiState: ExternalGameUiState) {
VHelper.disableLaunchGameAfterInstallation()
VHelper.install(requireContext(), DownloadEntity().apply {
externalGameUiState.externalGameEntity.apply {
packageName = apkPackageName
path = apkPath
}
}, true)
VHelper.newCwValidateVspaceBeforeAction(
requireContext(),null,
) {
dialog.show()
}
}
private fun uninstall(externalGameUiState: ExternalGameUiState) {
dialog.show()
uninstallDisposable = Single.create<Void> {
VHelper.uninstall(externalGameUiState.externalGameEntity.apkPackageName)
}.subscribeOn(Schedulers.from(AppExecutor.lightWeightIoExecutor)).observeOn(AndroidSchedulers.mainThread())
.subscribe { t1, t2 ->
if (dialog.isShowing) {
dialog.dismiss()
}
}
}
private fun start(externalGameUiState: ExternalGameUiState) {
val intent = VirtualAppManager.get().getStartGameIntent(
externalGameUiState.externalGameEntity.apkPackageName,
"",
externalGameUiState.externalGameEntity.appName,
"",
MetaUtil.getBase64EncodedAndroidId(),
HaloApp.getInstance().gid,
com.gh.gamecenter.BuildConfig.VERSION_NAME,
HaloApp.getInstance().channel,
"",
"",
com.gh.gamecenter.BuildConfig.VA_VERSION_NAME,
HaloApp.getInstance().oaid
)
intent.setComponent(
ComponentName(
com.gh.gamecenter.BuildConfig.APPLICATION_ID,
VirtualAppManager.AIDL_SERVER_REMOTE_GUIDE_ACTIVITY
)
)
requireActivity().startActivity(intent)
}
}

View File

@ -1,64 +0,0 @@
package com.gh.vspace.installexternalgames
import android.app.Application
import android.content.pm.PackageManager
import android.os.Environment
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.gh.gamecenter.core.runOnIoThread
import com.gh.vspace.VHelper
import com.lg.vspace.helper.compat.NativeLibraryHelperCompat
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
class InstallExternalGameViewModel(application: Application) : AndroidViewModel(application) {
private val _gamesList = MutableLiveData<List<ExternalGameEntity>>(listOf())
val gamesList: LiveData<List<ExternalGameEntity>> = _gamesList
private val pkgManger = getApplication<Application>().packageManager
private var disposable: Disposable = VHelper.callSite.observeOn(AndroidSchedulers.mainThread()).subscribe {
scanPaths()
}
fun scanPaths() {
runOnIoThread {
_gamesList.postValue(Environment.getExternalStorageDirectory().walk().maxDepth(1)
.filter { it.isHidden.not() }
.filter { it.isFile }
.onEach {
Utils.log(Constants.TAG, "获得文件: ${it.name}")
}
.filter { it.extension == "apk" }
.map {
val packageInfo = pkgManger.getPackageArchiveInfo(
it.absolutePath,
PackageManager.GET_META_DATA or PackageManager.GET_ACTIVITIES
)
packageInfo?.let { packageInfo ->
val applicationInfo = packageInfo.applicationInfo
applicationInfo.publicSourceDir = it.absolutePath
applicationInfo.sourceDir = it.absolutePath
ExternalGameEntity(
cpuAbi = NativeLibraryHelperCompat.getPackageAbiList(it.absolutePath),
apkPath = it.absolutePath,
apkFileName = it.name,
apkPackageName = packageInfo.packageName,
apkVersion = packageInfo.versionName,
appName = pkgManger.getApplicationLabel(applicationInfo).toString(),
lastModified = it.lastModified()
)
}
}.filterNotNull()
.toList().sortedByDescending { it.lastModified }
)
}
}
override fun onCleared() {
super.onCleared()
disposable.dispose()
}
}

View File

@ -1,11 +0,0 @@
package com.gh.vspace.installexternalgames
interface OnItemClickListener {
enum class ClickType {
CLICK_INSTALL, CLICK_UNINSTALL, CLICK_START
}
fun onItemClick(externalGameUiState: ExternalGameUiState, clickType: ClickType)
}

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/external_games_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/apk_file_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
tools:text="文件名:\n路径" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_install"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_install"
android:visibility="gone"
tools:visibility="visible" />
<Button
android:id="@+id/btn_update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_update"
android:visibility="visible"
tools:visibility="visible" />
<Button
android:id="@+id/btn_uninstall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_uninstall"
android:visibility="gone"
tools:visibility="visible" />
<Button
android:id="@+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_start"
android:visibility="gone"
tools:visibility="visible" />
</LinearLayout>
</LinearLayout>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="title_install_external_game">從SD卡安裝</string>
<string name="text_install">安裝</string>
<string name="text_update">更新</string>
<string name="text_uninstall">卸載</string>
<string name="text_start">啟動</string>
</resources>

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="install_game_from_external" type="id" />
</resources>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="title_install_external_game">从SD卡安装</string>
<string name="text_install">安装</string>
<string name="text_update">更新</string>
<string name="text_uninstall">卸载</string>
<string name="text_start">启动</string>
</resources>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<!-- Trust user added CAs while debuggable only -->
<certificates src="user" />
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>

View File

@ -5,15 +5,15 @@ import com.kwai.monitor.log.TurboAgent
import com.kwai.monitor.log.TurboConfig import com.kwai.monitor.log.TurboConfig
object KuaishouHelper { object KuaishouHelper {
private val mAppId by lazy { BuildConfig.SDK_APP_ID.ifEmpty { "81537" } } private const val APP_ID = "80655"
private val mAppName by lazy { BuildConfig.SDK_APP_NAME.ifEmpty { "guanghuanzhushou_1" } } private const val APP_NAME = "guanghuanzhushou_1"
@JvmStatic @JvmStatic
fun init(context: Context, channel: String) { fun init(context: Context, channel: String) {
TurboAgent.init( TurboAgent.init(
TurboConfig.TurboConfigBuilder.create(context) TurboConfig.TurboConfigBuilder.create(context)
.setAppId(mAppId) .setAppId(APP_ID)
.setAppName(mAppName) .setAppName(APP_NAME)
.setAppChannel(channel) .setAppChannel(channel)
.build() .build()
) )

View File

@ -3,20 +3,16 @@ package com.gh.gamecenter.provider
import android.app.Activity import android.app.Activity
import android.app.Application import android.app.Application
import android.text.TextUtils import android.text.TextUtils
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.KuaishouHelper import com.gh.gamecenter.KuaishouHelper
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.provider.IFlavorProvider import com.gh.gamecenter.core.provider.IFlavorProvider
import com.gh.gamecenter.core.utils.SPUtils import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.TimeUtils import com.gh.gamecenter.core.utils.TimeUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.halo.assistant.HaloApp import com.halo.assistant.HaloApp
import com.kwai.monitor.payload.TurboHelper import com.leon.channel.helper.ChannelReaderUtil
import com.tencent.vasdolly.helper.ChannelReaderUtil
class FlavorProviderImp : IFlavorProvider { class FlavorProviderImp : IFlavorProvider {
override fun init(application: Application, activity: Activity, activateRatio: Int) { override fun init(application: Application, activity: Activity) {
KuaishouHelper.init(application, getChannelStr(application)) KuaishouHelper.init(application, getChannelStr(application))
if (HaloApp.getInstance().isBrandNewInstall) { if (HaloApp.getInstance().isBrandNewInstall) {
@ -35,11 +31,7 @@ class FlavorProviderImp : IFlavorProvider {
} }
override fun getChannelStr(application: Application): String { override fun getChannelStr(application: Application): String {
var channel = if (BuildConfig.USE_DEFAULT_CHANNEL_SDK) { var channel = ChannelReaderUtil.getChannel(application)
ChannelReaderUtil.getChannel(application)
} else {
TurboHelper.getChannel(application)
}
if (channel == null || TextUtils.isEmpty(channel.trim())) { if (channel == null || TextUtils.isEmpty(channel.trim())) {
channel = KUAISHOU_CHANNEL channel = KUAISHOU_CHANNEL
} }
@ -50,15 +42,6 @@ class FlavorProviderImp : IFlavorProvider {
KuaishouHelper.onEvent(content) KuaishouHelper.onEvent(content)
} }
override fun logCoreEvent() {
logEvent("EVENT_KEY_PATH_OPTIMIZATION")
if (BuildConfig.ACTIVATE_REPORTING_RATIO == 1) {
AppExecutor.uiExecutor.executeWithDelay({
ToastUtils.toast("关键行为 EVENT_KEY_PATH_OPTIMIZATION")
}, 500)
}
}
companion object { companion object {
private const val KUAISHOU_CHANNEL = "KS-GHZS-01" private const val KUAISHOU_CHANNEL = "KS-GHZS-01"
} }

Binary file not shown.

View File

@ -7,29 +7,10 @@
<package android:name="com.gh.gamecenter" /> <package android:name="com.gh.gamecenter" />
</queries> </queries>
<queries>
<package android:name="com.gh.toolmap" />
<intent>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="ghtoolmap"/>
</intent>
</queries>
<queries> <queries>
<package android:name="com.lg.vspace" /> <package android:name="com.lg.vspace" />
<package android:name="com.gh.gamecenter.addon" />
</queries> </queries>
<!-- 华为/荣耀角标 -->
<uses-permission android:name="com.huawei.android.launcher.permission.CHANGE_BADGE " />
<uses-permission android:name="com.hihonor.android.launcher.permission.CHANGE_BADGE" />
<!-- vivo角标 -->
<uses-permission android:name="com.vivo.notification.permission.BADGE_ICON" />
<uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<!-- 允许应用程序访问网络连接 --> <!-- 允许应用程序访问网络连接 -->
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<!-- 允许应用程序写入外部存储如SD卡上写文件 --> <!-- 允许应用程序写入外部存储如SD卡上写文件 -->
@ -50,7 +31,7 @@
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" /> <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<!-- 应用安装相关 --> <!-- 应用安装相关 -->
<uses-permission android:name="com.android.permission.GET_INSTALLED_APPS" /> <uses-permission android:name="com.android.permission.GET_INSTALLED_APPS" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<!-- 前台服务权限--> <!-- 前台服务权限-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
@ -65,11 +46,7 @@
<!-- 如果有视频相关的广告且使用textureView播放请务必添加否则黑屏 --> <!-- 如果有视频相关的广告且使用textureView播放请务必添加否则黑屏 -->
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- 悬浮窗 --> <uses-sdk tools:overrideLibrary="com.shuyu.gsyvideoplayer,
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-sdk tools:overrideLibrary="
com.shuyu.gsyvideoplayer,
com.shuyu.gsyvideoplayer.lib, com.shuyu.gsyvideoplayer.lib,
com.haroldadmin.whatthestack, com.haroldadmin.whatthestack,
com.shuyu.gsyvideoplayer.armv7a, com.shuyu.gsyvideoplayer.armv7a,
@ -99,40 +76,7 @@
androidx.compose.animation.core, androidx.compose.animation.core,
androidx.constraintlayout.compose, androidx.constraintlayout.compose,
androidx.compose.ui.test.manifest, androidx.compose.ui.test.manifest,
com.bytedance.sdk.openadsdk, androidx.compose.ui.tooling.preview"/>
com.bykv.vk.openvk,
com.bytedance.tools,
androidx.compose.ui.tooling.preview,
com.tencent.qqmini,
com.tencent.qqmini.minigame.external,
com.tencent.qqmini.minigame.opensdk,
com.tencent.qqmini.union.ad,
com.lg.vspace,
io.lg.va.common,
com.va.floating,
com.lg.cloud,
com.lg.archive,
com.lg.vclient,
com.va.realname,
com.lg.vspace.flavor,
com.lg.update,
com.lg.login,
com.lg.accelerator,
com.lody.virtual,
com.lg.core,
com.lg.ads,
com.lg.common,
com.lg.vspace.network,
com.lody.virtual.lib.res,
com.va.host,
com.lg.vspace.plugin.host,
com.lg.plugin.constant,
com.bytedance.tools.codelocator,
org.chickenhook.restrictionbypass,
com.lody.virtual.sandhook,
com.lg.vspace.common,
com.lg.vspace.archive.common,
com.wy.lib.wytrace" />
<!-- 去掉 SDK 一些流氓权限 --> <!-- 去掉 SDK 一些流氓权限 -->
<uses-permission <uses-permission
@ -147,18 +91,6 @@
android:name="android.permission.GET_TASKS" android:name="android.permission.GET_TASKS"
tools:node="remove" /> tools:node="remove" />
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION"
tools:node="remove" />
<uses-permission
android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
tools:node="remove" />
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"
tools:node="remove" />
<supports-screens <supports-screens
android:anyDensity="true" android:anyDensity="true"
android:largeScreens="true" android:largeScreens="true"
@ -173,17 +105,10 @@
android:icon="@mipmap/logo" android:icon="@mipmap/logo"
android:label="@string/app_name" android:label="@string/app_name"
android:largeHeap="true" android:largeHeap="true"
android:networkSecurityConfig="@xml/network_security_config"
android:preserveLegacyExternalStorage="true"
android:requestLegacyExternalStorage="true"
android:resizeableActivity="true" android:resizeableActivity="true"
android:theme="@style/AppCompatTheme.APP" android:theme="@style/AppCompatTheme.APP"
tools:replace="android:name,android:allowBackup" tools:replace="android:name,android:allowBackup"
tools:targetApi="r"> tools:targetApi="n">
<meta-data
android:name="EasyGoClient"
android:value="true" />
<meta-data <meta-data
android:name="io.sentry.auto-init" android:name="io.sentry.auto-init"
@ -194,10 +119,6 @@
android:name="io.sentry.breadcrumbs.system-events" android:name="io.sentry.breadcrumbs.system-events"
android:value="false" /> android:value="false" />
<meta-data android:name="module_version" android:value="${VA_VERSION_NAME}" />
<service android:name="com.gh.ndownload.NDownloadService" />
<activity <activity
android:name="com.gh.gamecenter.SplashScreenActivity" android:name="com.gh.gamecenter.SplashScreenActivity"
android:configChanges="keyboardHidden|orientation|screenSize" android:configChanges="keyboardHidden|orientation|screenSize"
@ -214,15 +135,10 @@
<activity <activity
android:name="com.gh.gamecenter.MainActivity" android:name="com.gh.gamecenter.MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden" android:configChanges="orientation|screenSize|keyboardHidden"
android:exported="true"
android:launchMode="singleTask" android:launchMode="singleTask"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:theme="@style/AppCompatTheme.APP" android:theme="@style/AppCompatTheme.APP"
android:windowSoftInputMode="stateAlwaysHidden|adjustResize"> android:windowSoftInputMode="stateAlwaysHidden|adjustResize" />
<intent-filter>
<action android:name="android.intent.action.VIEW" />
</intent-filter>
</activity>
<activity <activity
android:name="com.gh.gamecenter.DownloadManagerActivity" android:name="com.gh.gamecenter.DownloadManagerActivity"
@ -254,7 +170,7 @@
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity <activity
android:name="com.gh.gamecenter.newsdetail.NewsDetailActivity" android:name="com.gh.gamecenter.NewsDetailActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity <activity
@ -309,7 +225,7 @@
android:windowSoftInputMode="stateHidden" /> android:windowSoftInputMode="stateHidden" />
<activity <activity
android:name="com.gh.gamecenter.libao.LibaoDetailActivity" android:name="com.gh.gamecenter.LibaoDetailActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity <activity
@ -320,6 +236,10 @@
android:name="com.gh.gamecenter.CleanApkActivity" android:name="com.gh.gamecenter.CleanApkActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.SelectUserIconActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name="com.gh.gamecenter.CommentDetailActivity" android:name="com.gh.gamecenter.CommentDetailActivity"
android:screenOrientation="portrait" android:screenOrientation="portrait"
@ -337,13 +257,21 @@
<activity <activity
android:name="com.gh.gamecenter.VoteActivity" android:name="com.gh.gamecenter.VoteActivity"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:windowSoftInputMode="stateAlwaysHidden|adjustPan" /> android:windowSoftInputMode="stateAlwaysHidden|adjustResize" />
<activity <activity
android:name="com.gh.gamecenter.WeiBoShareActivity" android:name="com.gh.gamecenter.WeiBoShareActivity"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden" /> android:windowSoftInputMode="stateHidden" />
<activity
android:name=".category.CategoryDirectoryActivity"
android:screenOrientation="portrait" />
<activity
android:name=".category.CategoryListActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name="com.gh.gamecenter.UserInfoActivity" android:name="com.gh.gamecenter.UserInfoActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
@ -356,19 +284,51 @@
android:name="com.gh.gamecenter.CollectionActivity" android:name="com.gh.gamecenter.CollectionActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.MessageActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name="com.gh.gamecenter.UserInfoEditActivity" android:name="com.gh.gamecenter.UserInfoEditActivity"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden" /> android:windowSoftInputMode="stateHidden" />
<activity
android:name="com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.answer.edit.AnswerEditActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.ConcernInfoActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name="com.gh.gamecenter.InfoActivity" android:name="com.gh.gamecenter.InfoActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.MessageKeFuActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.MessageInviteActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.MessageVoteActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name=".qa.questions.invite.QuestionsInviteActivity" android:name=".qa.questions.invite.QuestionsInviteActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.myqa.MyAskActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name="com.gh.gamecenter.qa.questions.edit.QuestionEditActivity" android:name="com.gh.gamecenter.qa.questions.edit.QuestionEditActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
@ -406,6 +366,10 @@
android:name="com.gh.gamecenter.qa.article.edit.ArticleEditActivity" android:name="com.gh.gamecenter.qa.article.edit.ArticleEditActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.article.MyArticleActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name="com.gh.gamecenter.qa.article.draft.ArticleDraftActivity" android:name="com.gh.gamecenter.qa.article.draft.ArticleDraftActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
@ -444,6 +408,10 @@
android:name="com.gh.gamecenter.history.HistoryActivity" android:name="com.gh.gamecenter.history.HistoryActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.personalhome.rating.RatingActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name="com.gh.gamecenter.gamedetail.rating.logs.CommentLogsActivity" android:name="com.gh.gamecenter.gamedetail.rating.logs.CommentLogsActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
@ -465,6 +433,9 @@
android:name="com.gh.gamecenter.video.game.GameVideoActivity" android:name="com.gh.gamecenter.video.game.GameVideoActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.editor.LocalMediaActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name="com.gh.gamecenter.servers.GameServersActivity" android:name="com.gh.gamecenter.servers.GameServersActivity"
@ -497,19 +468,17 @@
android:configChanges="orientation|screenSize|keyboardHidden" android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:theme="@style/TransparentStatusBarAndNavigationBar" /> android:theme="@style/TransparentStatusBarAndNavigationBar" />
<activity
android:name=".gamedetail.myrating.MyRatingActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name="com.gh.gamecenter.gamedetail.fuli.kaifu.ServersCalendarActivity" android:name="com.gh.gamecenter.gamedetail.fuli.kaifu.ServersCalendarActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity <activity
android:name=".gamedetail.fuli.kaifu.ServersCalendarManagementActivity" android:name=".qa.answer.draft.AnswerDraftActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name=".gamedetail.fuli.kaifu.ServersSubscribedGameListActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name=".gamedetail.rating.RatingFoldActivity" android:name=".gamedetail.rating.RatingFoldActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
@ -521,6 +490,10 @@
android:name=".video.poster.PosterEditActivity" android:name=".video.poster.PosterEditActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name=".video.poster.PosterClipActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name=".forum.detail.ForumDetailActivity" android:name=".forum.detail.ForumDetailActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
@ -562,6 +535,14 @@
android:name=".simulatorgame.SimulatorManagementActivity" android:name=".simulatorgame.SimulatorManagementActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name=".catalog.CatalogActivity"
android:screenOrientation="portrait" />
<activity
android:name=".catalog.NewCatalogListActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name=".forum.search.ForumOrUserSearchActivity" android:name=".forum.search.ForumOrUserSearchActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
@ -582,6 +563,10 @@
android:name=".personal.DeliveryInfoActivity" android:name=".personal.DeliveryInfoActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name=".qa.editor.PreviewVideoActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name=".qa.video.publish.VideoPublishActivity" android:name=".qa.video.publish.VideoPublishActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
@ -614,10 +599,6 @@
android:name=".game.commoncollection.detail.CommonCollectionDetailActivity" android:name=".game.commoncollection.detail.CommonCollectionDetailActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name=".game.commoncollection.detail.CustomCommonCollectionDetailActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name=".gamecollection.detail.GameCollectionDetailActivity" android:name=".gamecollection.detail.GameCollectionDetailActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
@ -638,8 +619,8 @@
<!-- android:theme="@android:style/Theme.Translucent" />--> <!-- android:theme="@android:style/Theme.Translucent" />-->
<activity <activity
android:name="com.gh.gamecenter.SkipActivity"
android:exported="true" android:exported="true"
android:name="com.gh.gamecenter.SkipActivity"
android:theme="@style/Theme.AppCompat.Light.Fullscreen.Transparent"> android:theme="@style/Theme.AppCompat.Light.Fullscreen.Transparent">
<intent-filter> <intent-filter>
<data android:scheme="ghzhushou" /> <data android:scheme="ghzhushou" />
@ -658,19 +639,6 @@
</intent-filter> </intent-filter>
</activity> </activity>
<!-- 光环助手授权登陆页面 -->
<activity
android:name=".authorization.AuthorizationActivity"
android:exported="true"
android:launchMode="singleTask"
android:screenOrientation="portrait">
<intent-filter>
<data android:scheme="ghzhushou_authorization" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.VIEW" />
</intent-filter>
</activity>
<activity <activity
android:name="com.gh.gamecenter.teenagermode.TeenagerModeActivity" android:name="com.gh.gamecenter.teenagermode.TeenagerModeActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
@ -709,7 +677,7 @@
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity <activity
android:name="com.gh.gamecenter.toolbox.ToolBoxActivity" android:name="com.gh.gamecenter.toolbox.ToolBoxBlockActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity <activity
@ -762,52 +730,6 @@
android:name=".servers.gametest2.GameServerTestV2Activity" android:name=".servers.gametest2.GameServerTestV2Activity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.gamecollection.hotlist.GameCollectionHotListActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.minigame.qq.QGameHomeWrapperActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.minigame.MiniGameSearchActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.gamecollection.hotlist.GameCollectionListDetailActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.UserAuthActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.SplashAdActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.wrapper.ToolbarWrapperActivity"
android:screenOrientation="portrait" />
<activity
android:name=".forum.home.CommunityActivity"
android:screenOrientation="portrait" />
<activity
android:name=".forum.home.follow.FollowDynamicActivity"
android:theme="@style/Theme.Transparent" />
<activity
android:name=".forum.home.follow.AllFollowedActivity"
android:screenOrientation="portrait"
android:theme="@style/AppCompatTheme.APP" />
<activity
android:name=".search.SearchTabActivity"
android:configChanges="keyboardHidden"
android:screenOrientation="portrait"
android:theme="@style/AppCompatTheme.APP" />
<!-- <activity--> <!-- <activity-->
<!-- android:name="${applicationId}.douyinapi.DouYinEntryActivity"--> <!-- android:name="${applicationId}.douyinapi.DouYinEntryActivity"-->
@ -819,8 +741,7 @@
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}" android:authorities="${applicationId}"
android:exported="false" android:exported="false"
android:grantUriPermissions="true" android:grantUriPermissions="true">
tools:replace="android:authorities">
<meta-data <meta-data
android:name="android.support.FILE_PROVIDER_PATHS" android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" /> android:resource="@xml/provider_paths" />
@ -846,9 +767,9 @@
<service <service
android:name=".aidl.CommunicationService" android:name=".aidl.CommunicationService"
android:enabled="true" android:enabled="true"
android:exported="true"> android:exported="true" >
<intent-filter> <intent-filter>
<action android:name="com.gh.gamecenter.aidl.CommunicationService" /> <action android:name="com.gh.gamecenter.aidl.CommunicationService"/>
</intent-filter> </intent-filter>
</service> </service>
@ -864,10 +785,6 @@
<!-- tools:node="remove" />--> <!-- tools:node="remove" />-->
<!-- </provider>--> <!-- </provider>-->
<service android:name="com.gh.gamecenter.install.InstallService" />
<service android:name="com.gh.download.suspendwindow.DownloadSuspendWindowService" />
<receiver <receiver
android:name="com.gh.gamecenter.receiver.DownloadReceiver" android:name="com.gh.gamecenter.receiver.DownloadReceiver"
android:exported="false"> android:exported="false">
@ -883,11 +800,6 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<activity
android:name="com.gh.common.xapk.XapkInstallReceiver"
android:exported="false"
android:theme="@style/Theme.Transparent" />
<receiver <receiver
android:name="com.gh.gamecenter.receiver.ActivitySkipReceiver" android:name="com.gh.gamecenter.receiver.ActivitySkipReceiver"
android:exported="true"> android:exported="true">
@ -895,6 +807,40 @@
<action android:name="com.gh.gamecenter.ACTIVITYSKIP" /> <action android:name="com.gh.gamecenter.ACTIVITYSKIP" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<!-- 梦工厂配置 开始 -->
<!--<meta-data
android:name="MGC_APPID"
android:value="1001276" />
<provider
android:name="com.leto.game.base.provider.LetoFileProvider"
android:authorities="${applicationId}.leto.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/leto_file_path"
tools:replace="android:resource" />
</provider>-->
<!-- 梦工厂配置 结束 -->
<!-- 穿山甲配置 开始 -->
<!--<provider
android:name="com.bytedance.sdk.openadsdk.TTFileProvider"
android:authorities="${applicationId}.TTFileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
<provider
android:name="com.bytedance.sdk.openadsdk.multipro.TTMultiProvider"
android:authorities="${applicationId}.TTMultiProvider"
android:exported="false" />-->
<!-- 穿山甲配置 结束 -->
</application> </application>
</manifest> </manifest>

View File

@ -1,27 +0,0 @@
{
"easyGoVersion": "1.0",
"client": "com.gh.gamecenter",
"logicEntities": [
{
"head": {
"function": "magicwindow",
"required": "true"
},
"body": {
"mode":"1",
"activityPairs":[
{"from":"com.gh.gamecenter.MainActivity","to":"*"}
],
"defaultDualActivities": {
"mainPages": "com.gh.gamecenter.MainActivity"
},
"UX": {
"supportRotationUxCompat": "false",
"isDraggable": "true"
},
"transActivities":[
]
}
}
]
}

View File

@ -6,6 +6,8 @@
<link rel="stylesheet" type="text/css" href="normalize.css"> <link rel="stylesheet" type="text/css" href="normalize.css">
<link rel="stylesheet" type="text/css" href="style.css"> <link rel="stylesheet" type="text/css" href="style.css">
<link rel="stylesheet" type="text/css" href="video-js.min.css"> <link rel="stylesheet" type="text/css" href="video-js.min.css">
<!-- <link rel="stylesheet" href="https://static-web.ghzs.com/website-static/lib/video-js.min.css">--> <!--在web页面播放视频-->
<!--<link rel="stylesheet" type="text/css" href="https://resource.ghzs.com/css/halo_app.css">-->
</head> </head>
<body style="overflow-x: hidden; word-break: break-all;"> <body style="overflow-x: hidden; word-break: break-all;">
@ -13,5 +15,8 @@
<script type="text/javascript" src="zepto.min.js"></script> <script type="text/javascript" src="zepto.min.js"></script>
<script type="text/javascript" src="rich_editor.js"></script> <script type="text/javascript" src="rich_editor.js"></script>
<script type="text/javascript" src="video.min.js"></script> <script type="text/javascript" src="video.min.js"></script>
<!--<script src="https://static-web.ghzs.com/website-static/lib/video.min.js"></script>--> <!--在web页面播放视频-->
<!--<script type="text/javascript" src="content.js"></script>-->
<!--<script type="text/javascript" src="https://resource.ghzs.com/js/halo_app.js"></script>-->
</body> </body>
</html> </html>

View File

@ -0,0 +1 @@
{"v":"5.5.9","fr":60,"ip":0,"op":90,"w":1080,"h":202,"nm":"click","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"椭圆形","sr":1,"ks":{"o":{"a":0,"k":20,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[204,1455,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":[{"d":1,"ty":"el","s":{"a":0,"k":[24,24],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","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":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"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":"椭圆形","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"椭圆形","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":63,"s":[10]},{"t":70,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[204,1455,0],"ix":2},"a":{"a":0,"k":[0,0,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":39,"s":[100,100,100]},{"t":49,"s":[110,110,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[36,36],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","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":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"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":"椭圆形","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"圆环","refId":"comp_0","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.531],"y":[0]},"t":28,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":38,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.526],"y":[0]},"t":48,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.446],"y":[0]},"t":63,"s":[50]},{"t":82,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[125.951,79.658,0],"ix":2},"a":{"a":0,"k":[205.951,1458.658,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.601,0.601,0.333],"y":[0,0,0]},"t":28,"s":[50,50,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.528,0.528,0.333],"y":[0,0,0]},"t":38,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.526,0.526,0.333],"y":[0,0,0]},"t":48,"s":[120,120,100]},{"t":63,"s":[100,100,100]}],"ix":6}},"ao":0,"w":1080,"h":1920,"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"点击手","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.596],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.515],"y":[0]},"t":63,"s":[100]},{"t":83,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.507],"y":[0]},"t":10,"s":[6]},{"t":30,"s":[2]}],"ix":10},"p":{"a":0,"k":[178.982,123.325,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.489,0.489,0.333],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"t":30,"s":[90,90,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.33,-8.3],[3.89,0.27],[-4.4,-1.68],[-4.33,-0.67],[-4.08,9.32],[3.33,5.44],[3.39,4.6],[0.87,-3.7],[3.6,-0.86],[1.03,-0.21],[2.34,-0.53],[0.96,1.15],[4.22,5.48],[-1.18,-4.56]],"o":[[1.11,1.71],[-3.89,-0.27],[6.42,2.5],[4.33,0.66],[1.63,-5.32],[-3.34,-5.45],[-1.68,-2.1],[-0.71,3.14],[-3.43,0.95],[-0.57,0.08],[-3.86,1.12],[-3.23,-3.94],[-1.89,-2.28],[2.42,4.64]],"v":[[-5.387,9.698],[-10.717,8.498],[-12.327,15.628],[5.813,21.748],[23.313,11.778],[20.273,-1.202],[11.563,-13.962],[5.393,-12.362],[1.083,-13.722],[-2.087,-9.742],[-5.707,-11.752],[-8.777,-7.572],[-18.297,-20.542],[-23.827,-17.832]],"c":true},"ix":2},"nm":"路径 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":"填充 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":[300,300],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0}],"markers":[]}

View File

@ -0,0 +1 @@
{"v":"5.6.4","fr":25,"ip":0,"op":35,"w":1080,"h":214,"nm":"点赞","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"椭圆形 2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.588],"y":[0]},"t":17,"s":[15]},{"t":20,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[468.04,73.68,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.659,0.659,0.333],"y":[0,0,0]},"t":10,"s":[50,50,100]},{"t":19,"s":[150,150,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[24,24],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","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":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"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":"椭圆形","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":10,"op":1510,"st":10,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"椭圆形 3","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.588],"y":[0]},"t":27,"s":[15]},{"t":30,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[468.04,73.68,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.659,0.659,0.333],"y":[0,0,0]},"t":20,"s":[50,50,100]},{"t":28,"s":[140,140,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[24,24],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","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":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"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":"椭圆形","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":20,"op":1520,"st":20,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"路径备份 2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.602],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":5,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.663],"y":[0]},"t":24,"s":[100]},{"t":29,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[531.02,129.675,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.514,0.514,0.333],"y":[0,0,0]},"t":5,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.533,0.533,0.333],"y":[0,0,0]},"t":10,"s":[90,90,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.586,0.586,0.333],"y":[0,0,0]},"t":15,"s":[95,95,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.499,0.499,0.333],"y":[0,0,0]},"t":19,"s":[90,90,100]},{"t":24,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.33,-8.3],[3.89,0.27],[-4.4,-1.68],[-4.33,-0.67],[-4.08,9.32],[3.33,5.44],[3.39,4.6],[0.87,-3.7],[3.6,-0.86],[1.03,-0.21],[2.34,-0.53],[0.96,1.15],[4.22,5.48],[-1.18,-4.56]],"o":[[1.11,1.71],[-3.89,-0.27],[6.42,2.5],[4.33,0.66],[1.63,-5.32],[-3.34,-5.45],[-1.68,-2.1],[-0.71,3.14],[-3.43,0.95],[-0.57,0.08],[-3.86,1.12],[-3.23,-3.94],[-1.89,-2.28],[2.42,4.64]],"v":[[-5.387,9.698],[-10.717,8.498],[-12.327,15.628],[5.813,21.748],[23.313,11.778],[20.273,-1.202],[11.563,-13.962],[5.393,-12.362],[1.083,-13.722],[-2.087,-9.742],[-5.707,-11.752],[-8.777,-7.572],[-18.297,-20.542],[-23.827,-17.832]],"c":true},"ix":2},"nm":"路径 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":"填充 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":[300,300],"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":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1500,"st":0,"bm":0}],"markers":[]}

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"v":"5.9.1","fr":60,"ip":0,"op":60,"w":144,"h":144,"nm":"icon_change","ddd":0,"assets":[{"id":"comp_0","nm":"icon_change_detail","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"stroke1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[37.04,52.994,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.533,-0.143],[0.143,-0.533],[1.487,-1.304],[1.961,-0.258],[1.774,0.875],[0.709,0.661],[0,0],[0,0.445],[0,0],[-0.276,0],[0,0],[-0.013,0],[0,0],[0.315,-0.315],[0,0],[-0.682,-0.336],[-1.569,0.207],[-1.19,1.043],[-0.41,1.528]],"o":[[0.533,0.143],[-0.512,1.91],[-1.487,1.304],[-1.961,0.258],[-0.879,-0.433],[0,0],[-0.315,0.315],[0,0],[0,-0.276],[0,0],[0.013,0],[0,0],[0.445,0],[0,0],[0.555,0.508],[1.419,0.7],[1.569,-0.207],[1.19,-1.043],[0.143,-0.533]],"v":[[8.605,-4.301],[9.312,-3.076],[6.247,1.854],[0.958,4.25],[-4.77,3.304],[-7.163,1.652],[-8.493,2.982],[-9.347,2.628],[-9.347,-1.665],[-8.847,-2.165],[-8.161,-2.165],[-8.122,-2.165],[-4.554,-2.165],[-4.2,-1.311],[-5.748,0.237],[-3.885,1.51],[0.697,2.267],[4.928,0.35],[7.381,-3.594]],"c":true},"ix":2},"nm":"stroke1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,1,1,1,0.5,1,1,1,1,1,1,1,0,1,0.5,0.8,1,0.6],"ix":9}},"s":{"a":0,"k":[-5.347,-4.665],"ix":5},"e":{"a":0,"k":[8.653,-4.665],"ix":6},"t":1,"nm":"color1","mn":"ADBE Vector Graphic - G-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":[300,300],"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":"stroke1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"stroke2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[34.96,19.006,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.961,0.258],[-1.774,-0.875],[-0.709,-0.661],[0,0],[0,-0.445],[0,0],[0.276,0],[0,0],[0.012,0],[0,0],[-0.315,0.315],[0,0],[0.682,0.336],[1.569,-0.207],[1.19,-1.043],[0.41,-1.528],[0.533,0.143],[-0.143,0.533],[-1.487,1.304]],"o":[[1.961,-0.258],[0.879,0.433],[0,0],[0.315,-0.315],[0,0],[0,0.276],[0,0],[-0.012,0],[0,0],[-0.445,0],[0,0],[-0.555,-0.508],[-1.419,-0.7],[-1.569,0.207],[-1.19,1.043],[-0.143,0.533],[-0.533,-0.143],[0.512,-1.91],[1.487,-1.304]],"v":[[-0.958,-4.25],[4.77,-3.304],[7.163,-1.652],[8.493,-2.982],[9.347,-2.628],[9.347,1.665],[8.847,2.165],[8.16,2.165],[8.123,2.165],[4.554,2.165],[4.2,1.311],[5.748,-0.237],[3.885,-1.51],[-0.697,-2.267],[-4.928,-0.35],[-7.381,3.594],[-8.605,4.301],[-9.312,3.076],[-6.247,-1.854]],"c":true},"ix":2},"nm":"stroke2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,1,1,1,0.5,1,1,1,1,1,1,1,0,1,0.5,0.8,1,0.6],"ix":9}},"s":{"a":0,"k":[5.347,4.665],"ix":5},"e":{"a":0,"k":[-8.653,4.665],"ix":6},"t":1,"nm":"color2","mn":"ADBE Vector Graphic - G-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":[300,300],"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":"stroke2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"icon_change_detail","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":0,"s":[0]},{"t":36,"s":[360]}],"ix":10},"p":{"a":0,"k":[72,72,0],"ix":2,"l":2},"a":{"a":0,"k":[36,36,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":72,"h":72,"ip":0,"op":300,"st":0,"bm":0}],"markers":[]}

View File

@ -1 +0,0 @@
{"v":"5.9.1","fr":60,"ip":0,"op":60,"w":72,"h":72,"nm":"icon_title_change","ddd":0,"assets":[{"id":"comp_0","nm":"arrow","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"arrow_e_dark","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[29.25,30,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.701,0.456],[-1.627,-0.674],[-0.705,-0.667],[0,0],[-0.552,0],[0,-0.552],[0,0],[0.552,0],[0,0],[0.012,0],[0,0],[0,0.552],[-0.552,0],[0,0],[0.615,0.255],[1.276,-0.342],[0.804,-1.048],[0,-1.321],[-0.804,-1.048],[-1.276,-0.342],[-1.22,0.505],[-0.66,1.144],[-0.478,-0.276],[0.276,-0.478],[1.627,-0.674],[1.701,0.456],[1.072,1.397],[0,1.761],[-1.072,1.397]],"o":[[1.701,-0.456],[0.909,0.376],[0,0],[0,-0.552],[0.552,0],[0,0],[0,0.552],[0,0],[-0.012,0],[0,0],[-0.552,0],[0,-0.552],[0,0],[-0.493,-0.435],[-1.22,-0.505],[-1.276,0.342],[-0.804,1.048],[0,1.321],[0.804,1.048],[1.276,0.342],[1.22,-0.505],[0.276,-0.478],[0.478,0.276],[-0.881,1.525],[-1.627,0.674],[-1.701,-0.456],[-1.072,-1.397],[0,-1.761],[1.072,-1.397]],"v":[[-1.821,-7.727],[3.311,-7.391],[5.75,-5.809],[5.75,-6.5],[6.75,-7.5],[7.75,-6.5],[7.75,-3.5],[6.75,-2.5],[6.331,-2.5],[6.295,-2.5],[3.75,-2.5],[2.75,-3.5],[3.75,-4.5],[4.219,-4.5],[2.546,-5.543],[-1.303,-5.796],[-4.51,-3.653],[-5.75,0],[-4.51,3.653],[-1.303,5.796],[2.546,5.543],[5.446,3],[6.812,2.634],[7.178,4],[3.311,7.391],[-1.821,7.727],[-6.097,4.87],[-7.75,0],[-6.097,-4.87]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.158117651939,0.532358944416,0.878431379795,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":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"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":"arrow_e_dark","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"arrow","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":0,"s":[0]},{"t":36,"s":[360]}],"ix":10},"p":{"a":0,"k":[36,36,0],"ix":2,"l":2},"a":{"a":0,"k":[30,30,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":60,"h":60,"ip":0,"op":300,"st":0,"bm":0}],"markers":[]}

View File

@ -1 +0,0 @@
{"v":"5.9.1","fr":60,"ip":0,"op":60,"w":72,"h":72,"nm":"icon_title_change","ddd":0,"assets":[{"id":"comp_0","nm":"arrow","fr":60,"layers":[{"ddd":0,"ind":2,"ty":4,"nm":"arrow_e_light","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[29.25,30,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.701,0.456],[-1.627,-0.674],[-0.705,-0.667],[0,0],[-0.552,0],[0,-0.552],[0,0],[0.552,0],[0,0],[0.012,0],[0,0],[0,0.552],[-0.552,0],[0,0],[0.615,0.255],[1.276,-0.342],[0.804,-1.048],[0,-1.321],[-0.804,-1.048],[-1.276,-0.342],[-1.22,0.505],[-0.66,1.144],[-0.478,-0.276],[0.276,-0.478],[1.627,-0.674],[1.701,0.456],[1.072,1.397],[0,1.761],[-1.072,1.397]],"o":[[1.701,-0.456],[0.909,0.376],[0,0],[0,-0.552],[0.552,0],[0,0],[0,0.552],[0,0],[-0.012,0],[0,0],[-0.552,0],[0,-0.552],[0,0],[-0.493,-0.435],[-1.22,-0.505],[-1.276,0.342],[-0.804,1.048],[0,1.321],[0.804,1.048],[1.276,0.342],[1.22,-0.505],[0.276,-0.478],[0.478,0.276],[-0.881,1.525],[-1.627,0.674],[-1.701,-0.456],[-1.072,-1.397],[0,-1.761],[1.072,-1.397]],"v":[[-1.821,-7.727],[3.311,-7.391],[5.75,-5.809],[5.75,-6.5],[6.75,-7.5],[7.75,-6.5],[7.75,-3.5],[6.75,-2.5],[6.331,-2.5],[6.295,-2.5],[3.75,-2.5],[2.75,-3.5],[3.75,-4.5],[4.219,-4.5],[2.546,-5.543],[-1.303,-5.796],[-4.51,-3.653],[-5.75,0],[-4.51,3.653],[-1.303,5.796],[2.546,5.543],[5.446,3],[6.812,2.634],[7.178,4],[3.311,7.391],[-1.821,7.727],[-6.097,4.87],[-7.75,0],[-6.097,-4.87]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.141176477075,0.588235318661,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":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"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":"arrow_e_light","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"arrow","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":0,"s":[0]},{"t":36,"s":[360]}],"ix":10},"p":{"a":0,"k":[36,36,0],"ix":2,"l":2},"a":{"a":0,"k":[30,30,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":60,"h":60,"ip":0,"op":300,"st":0,"bm":0}],"markers":[]}

View File

@ -0,0 +1 @@
{"v":"5.5.9","fr":60,"ip":0,"op":120,"w":1080,"h":586,"nm":"上滑","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":2,"ty":4,"nm":"手","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.642],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.558],"y":[0]},"t":60,"s":[100]},{"t":71,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.479,"y":0},"t":3,"s":[611,475,0],"to":[0,-62.75,0],"ti":[0,62.75,0]},{"t":40,"s":[611,98.5,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[90,90,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-7.78,-12.06],[5.68,0.39],[-6.42,-2.45],[-6.32,-0.97],[-5.95,13.55],[4.87,7.91],[4.94,6.69],[1.26,-5.37],[5.25,-1.25],[1.5,-0.3],[3.4,-0.77],[1.4,1.68],[6.15,7.98],[-1.73,-6.64]],"o":[[1.62,2.49],[-5.68,-0.39],[9.37,3.63],[6.31,0.98],[2.39,-7.74],[-4.87,-7.92],[-2.45,-3.05],[-1.05,4.57],[-4.99,1.39],[-0.83,0.13],[-5.63,1.63],[-4.71,-5.72],[-2.75,-3.31],[3.52,6.76]],"v":[[-7.86,14.26],[-15.64,12.52],[-17.99,22.89],[8.47,31.78],[33.98,17.29],[29.55,-1.59],[16.85,-20.15],[7.86,-17.83],[1.56,-19.8],[-3.05,-14.02],[-8.33,-16.94],[-12.44,-11.045],[-26.761,-30.19],[-34.75,-25.78]],"c":true},"ix":2},"nm":"路径 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":"填充 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":[300,300],"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":"路径","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"矩形","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.715],"y":[0]},"t":57,"s":[100]},{"t":67,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[525,228.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.491,"y":0},"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[24.328,180.5],[-22,180.5],[-22,204.5],[24.328,204.5]],"c":true}]},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[24.328,-207.5],[-22,-207.5],[-22,204.5],[24.328,204.5]],"c":true}]}],"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"蒙版 1"}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[6,137],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,1,1,1,0.5,1,1,1,1,1,1,1,0,1,0.5,0.5,1,0],"ix":9}},"s":{"a":0,"k":[0,-68.5],"ix":5},"e":{"a":0,"k":[0,68.5],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-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":[300,300],"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":"矩形","np":2,"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":100,"ix":2},"o":{"a":0,"k":33,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":3,"op":123,"st":3,"bm":0}],"markers":[]}

View File

@ -0,0 +1 @@
{"v":"5.6.9","fr":30,"ip":0,"op":20,"w":66,"h":66,"nm":"bottom bar tab/论坛/选中/E","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"白-修正","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,33,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":4,"s":[80,80,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":9,"s":[110,110,100]},{"t":13,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":1,"y":0},"t":0,"s":[{"i":[[0,-0.66],[0,0],[1.38,0],[0,1.38],[0,0],[-0.66,0],[0,0]],"o":[[0,0],[0,1.38],[-1.38,0],[0,0],[0,-0.66],[0,0],[0.66,0]],"v":[[2.5,-1.3],[2.5,0],[0,2.5],[-2.5,0],[-2.5,-1.3],[-1.3,-2.5],[1.3,-2.5]],"c":true}]},{"i":{"x":0,"y":1},"o":{"x":0.333,"y":0},"t":4,"s":[{"i":[[0,-0.66],[0,0],[1.38,0],[0,1.38],[0,0],[-0.66,0],[0,0]],"o":[[0,0],[0,1.38],[-1.38,0],[0,0],[0,-0.66],[0,0],[0.66,0]],"v":[[2.5,-0.102],[2.5,0],[0,2.109],[-2.5,0],[-2.5,-0.102],[-1.3,-1.302],[1.3,-1.302]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":1,"y":0},"t":9,"s":[{"i":[[0,-0.66],[0,0],[1.38,0],[0,1.38],[0,0],[-0.66,0],[0,0]],"o":[[0,0],[0,1.38],[-1.38,0],[0,0],[0,-0.66],[0,0],[0.66,0]],"v":[[2.498,-1.845],[2.5,0],[0,2.734],[-2.5,0],[-2.502,-1.845],[-1.302,-3.045],[1.298,-3.045]],"c":true}]},{"t":13,"s":[{"i":[[0,-0.66],[0,0],[1.38,0],[0,1.38],[0,0],[-0.66,0],[0,0]],"o":[[0,0],[0,1.38],[-1.38,0],[0,0],[0,-0.66],[0,0],[0.66,0]],"v":[[2.5,-1.3],[2.5,0],[0,2.5],[-2.5,0],[-2.5,-1.3],[-1.3,-2.5],[1.3,-2.5]],"c":true}]}],"ix":2},"nm":"路径 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":"填充 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":[300,300],"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":"矩形","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":150,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"蓝","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,33.76,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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.8,0.42],[-3.44,-0.79],[-0.09,-1.71],[0,0],[0,0],[1.98,-0.1],[0,0],[0,0],[0,0],[0.62,0.57],[0,0],[0,0],[0,0],[0,0],[0,0],[0.2,1.89],[0,0],[0,0],[0,0]],"o":[[3.44,-0.79],[1.74,0.41],[0,0],[0,0],[0,2],[0,0],[0,0],[0,0],[-0.69,0.52],[0,0],[0,0],[0,0],[0,0],[0,0],[-1.94,0],[0,0],[0,0],[0,0],[0,-1.8]],"v":[[-6.39,-8.971],[6.39,-8.971],[9.49,-5.471],[9.5,-5.271],[9.5,3.249],[5.95,6.989],[5.75,6.999],[3.25,6.999],[0.3,9.209],[-1.95,9.089],[-2.06,8.969],[-2.17,8.849],[-2.21,8.779],[-3.4,6.999],[-5.75,6.999],[-9.48,3.639],[-9.49,3.449],[-9.5,3.249],[-9.5,-5.271]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.266,0.638,1,0.5,0.242,0.595,1,1,0.217,0.552,1],"ix":9}},"s":{"a":0,"k":[-9.5,-9.561],"ix":5},"e":{"a":0,"k":[9.5,9.561],"ix":6},"t":1,"nm":"color","mn":"ADBE Vector Graphic - G-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":[300,300],"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":"路径","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":150,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"预合成 1","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,33,0],"ix":2},"a":{"a":0,"k":[33,33,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":[100,100,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":4,"s":[70,70,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":9,"s":[110,110,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":13,"s":[90,90,100]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"w":66,"h":66,"ip":0,"op":20,"st":0,"bm":0}],"markers":[]}

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"v":"5.12.2","fr":60,"ip":0,"op":40,"w":66,"h":66,"nm":"icon_tab_my","ddd":0,"assets":[{"id":"comp_0","nm":"icon","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"highlight","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33.134,34.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":0.733},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,-0.004],[0.493,0],[0,0.004],[-0.493,0]],"o":[[0,0.004],[-0.493,0],[0,-0.004],[0.493,0]],"v":[[0.893,1.488],[0,1.496],[-0.893,1.488],[0,1.483]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0.267},"t":10,"s":[{"i":[[0,-1.018],[1.793,0],[0,1.018],[-1.793,0]],"o":[[0,1.018],[-1.793,0],[0,-1.018],[1.793,0]],"v":[[2.914,-0.344],[0,1.5],[-2.914,-0.344],[0,-1.5]],"c":true}]},{"i":{"x":0.333,"y":1},"o":{"x":0.667,"y":0},"t":18,"s":[{"i":[[0,-1.181],[1.407,0],[0,1.181],[-1.407,0]],"o":[[0,1.181],[-1.407,0],[0,-1.181],[1.407,0]],"v":[[2.226,-0.341],[0,1.74],[-2.211,-0.341],[0,-1.74]],"c":true}]},{"i":{"x":0.333,"y":1},"o":{"x":0.667,"y":0},"t":26,"s":[{"i":[[0,-0.905],[1.381,0],[0,0.905],[-1.381,0]],"o":[[0,0.905],[-1.381,0],[0,-0.905],[1.381,0]],"v":[[2.5,-0.306],[0,1.333],[-2.5,-0.306],[0,-1.333]],"c":true}]},{"t":32,"s":[{"i":[[0,-1.018],[1.381,0],[0,1.018],[-1.381,0]],"o":[[0,1.018],[-1.381,0],[0,-1.018],[1.381,0]],"v":[[2.5,-0.344],[0,1.5],[-2.5,-0.344],[0,-1.5]],"c":true}]}],"ix":2},"nm":"路径 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":"color","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":[300,300],"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":"椭圆形","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"body","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,34.204,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-3.866,0],[0,3.866],[3.866,0],[0,-3.866]],"o":[[3.866,0],[0,-3.866],[-3.866,0],[0,3.866]],"v":[[0,4.599],[7,-2.401],[0,-9.401],[-7,-2.401]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.207,0.359],[2.438,0],[1.189,-2.104],[-0.361,-0.204],[-0.204,0.361],[-1.915,0],[-0.932,-1.613],[-0.359,0.207]],"o":[[-1.198,-2.072],[-2.462,0],[-0.204,0.361],[0.361,0.204],[0.925,-1.638],[1.897,0],[0.207,0.359],[0.359,-0.207]],"v":[[5.848,8.225],[0,4.849],[-5.88,8.282],[-5.596,9.304],[-4.574,9.02],[0,6.349],[4.549,8.976],[5.574,9.25]],"c":true},"ix":2},"nm":"路径 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"合并路径 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.267,0.639,1,0.5,0.241,0.596,1,1,0.216,0.553,1],"ix":9}},"s":{"a":0,"k":[-3.812,-4.384],"ix":5},"e":{"a":0,"k":[6.345,8.129],"ix":6},"t":1,"nm":"color","mn":"ADBE Vector Graphic - G-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":[300,300],"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":"Union","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"ct":1,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"icon","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,33,0],"ix":2,"l":2},"a":{"a":0,"k":[33,33,0],"ix":1,"l":2},"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":[100,100,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":8,"s":[70,70,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":18,"s":[110,110,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":26,"s":[90,90,100]},{"t":32,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"w":66,"h":66,"ip":0,"op":60,"st":0,"bm":0}],"markers":[],"props":{}}

View File

@ -0,0 +1 @@
{"v":"5.5.9","fr":30,"ip":0,"op":20,"w":66,"h":66,"nm":"tab_video","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"形状图层 1","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.771],"y":[0]},"t":0,"s":[0]},{"t":5,"s":[100]}],"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[-3.742,6.835,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[30.937,31.042,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sr","sy":2,"d":1,"pt":{"a":0,"k":3,"ix":3},"p":{"a":0,"k":[0,0],"ix":4},"r":{"a":0,"k":0,"ix":5},"or":{"a":0,"k":29.286,"ix":7},"os":{"a":0,"k":75,"ix":9},"ix":1,"nm":"多边星形路径 1","mn":"ADBE Vector Shape - Star","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":13,"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":[-20.75,-13.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[102.743,88.578],"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.667],"y":[1]},"o":{"x":[0.657],"y":[0]},"t":0,"s":[0]},{"t":8,"s":[100]}],"ix":2},"o":{"a":0,"k":-115,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"路径 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,33.004,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.508,0.508,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.488,0.488,0.333],"y":[0,0,0]},"t":4,"s":[80,80,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.502,0.502,0.333],"y":[0,0,0]},"t":9,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.534,0.534,0.333],"y":[0,0,0]},"t":13,"s":[95,95,100]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[2.16,0.38],[3.22,-0.55],[0.38,-2.16],[-0.55,-3.22],[-2.16,-0.38],[-1.63,0],[-1.61,0.27],[-0.38,2.16],[0.55,3.22]],"o":[[-0.38,-2.16],[-3.22,-0.55],[-2.16,0.38],[-0.55,3.22],[0.38,2.16],[1.61,0.27],[1.63,0],[2.16,-0.38],[0.55,-3.22],[0,0]],"v":[[9.09,-4.86],[4.86,-9.09],[-4.86,-9.09],[-9.09,-4.86],[-9.09,4.86],[-4.86,9.09],[0,9.5],[4.86,9.09],[9.09,4.86],[9.09,-4.86]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.266,0.638,1,0.5,0.242,0.595,1,1,0.217,0.552,1],"ix":9}},"s":{"a":0,"k":[-5.174,-4.43],"ix":5},"e":{"a":0,"k":[8.612,8.214],"ix":6},"t":1,"nm":"Gradient Fill 3","mn":"ADBE Vector Graphic - G-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":[300,300],"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":"路径","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0}],"markers":[]}

File diff suppressed because one or more lines are too long

View File

@ -34,18 +34,18 @@ try {
var script = document.createElement("script") var script = document.createElement("script")
document.body.appendChild(script) document.body.appendChild(script)
if (isDebug) { if (isDebug) {
script.src = "https://dev-and-static.ghzs66.com/web/js/halo.js" + "?timestamp=" + Math.round(new Date().getTime() / 1000) script.src = "https://resource.ghzs.com/js/halo_app_test.js" + "?timestamp=" + Math.round(new Date().getTime() / 1000)
} else { } else {
script.src = "https://and-static.ghzs66.com/web/js/halo.js" + "?timestamp=" + Math.round(new Date().getTime() / 1000 / 1000) script.src = "https://resource.ghzs.com/js/halo.js" + "?timestamp=" + Math.round(new Date().getTime() / 1000 / 1000)
} }
var style = document.createElement("link") var style = document.createElement("link")
style.rel = "stylesheet" style.rel = "stylesheet"
style.type = "text/css" style.type = "text/css"
if (isDebug) { if (isDebug) {
style.href = "https://dev-and-static.ghzs66.com/web/css/halo.css" + "?timestamp=" + Math.round(new Date().getTime() / 1000) style.href = "https://resource.ghzs.com/css/halo_app_test.css" + "?timestamp=" + Math.round(new Date().getTime() / 1000)
} else { } else {
style.href = "https://and-static.ghzs66.com/web/css/halo.css" + "?timestamp=" + Math.round(new Date().getTime() / 1000 / 1000) style.href = "https://resource.ghzs.com/css/halo.css" + "?timestamp=" + Math.round(new Date().getTime() / 1000 / 1000)
} }
document.head.appendChild(style) document.head.appendChild(style)
@ -205,17 +205,14 @@ RE.setOutdent = function() {
RE.setJustifyLeft = function() { RE.setJustifyLeft = function() {
document.execCommand('justifyLeft', false, null); document.execCommand('justifyLeft', false, null);
RE.enabledEditingItems()
} }
RE.setJustifyCenter = function() { RE.setJustifyCenter = function() {
document.execCommand('justifyCenter', false, null); document.execCommand('justifyCenter', false, null);
RE.enabledEditingItems()
} }
RE.setJustifyRight = function() { RE.setJustifyRight = function() {
document.execCommand('justifyRight', false, null); document.execCommand('justifyRight', false, null);
RE.enabledEditingItems()
} }
RE.setBlockquote = function() { RE.setBlockquote = function() {
@ -230,16 +227,6 @@ RE.insertImage = function(url) {
RE.insertHTML(html); RE.insertHTML(html);
} }
// 设置分割线
RE.insertHorizontalRule = function() {
document.execCommand('insertHorizontalRule', false, null);
}
// 设置编辑器默认换行符
RE.setDefaultParagraphSeparator = function(separator) {
document.execCommand('defaultParagraphSeparator', false, separator);
}
// 替换成缩略图 // 替换成缩略图
RE.replaceTbImage = function(imgRuleFlag, gifRuleFlag) { RE.replaceTbImage = function(imgRuleFlag, gifRuleFlag) {
var imgs = document.getElementsByTagName("img"); var imgs = document.getElementsByTagName("img");
@ -587,10 +574,6 @@ document.addEventListener("selectionchange", function(e) {
RE.sendElementNameToNative() RE.sendElementNameToNative()
}); });
document.addEventListener("selectionchange", function(e) {
setTimeout(() => RE.enabledEditingItems(e), 10)
});
RE.recursion = function(dom) { RE.recursion = function(dom) {
var parenDom = dom.parentElement var parenDom = dom.parentElement
if (parenDom && parenDom instanceof Element && if (parenDom && parenDom instanceof Element &&
@ -633,6 +616,7 @@ RE.sendElementNameToNative = function() {
// android function to open link // android function to open link
function customLinkgo(self) { function customLinkgo(self) {
var datas = self.dataset.datas var datas = self.dataset.datas
// console.log(datas)
window.OnLinkClickListener.onClick(datas) window.OnLinkClickListener.onClick(datas)
} }

View File

@ -30,6 +30,7 @@ body {
} }
#editor { #editor {
display: table-cell;
outline: 0px solid transparent; outline: 0px solid transparent;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; background-position: center;

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,745 +0,0 @@
package com.gh.ad
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.SharedPreferences
import android.os.Message
import android.text.TextUtils
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
import androidx.fragment.app.Fragment
import com.alibaba.android.arouter.launcher.ARouter
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.common.exposure.ExposureManager
import com.gh.common.util.DirectUtils.directToLinkPage
import com.gh.common.util.LogUtils
import com.gh.common.util.NewFlatLogUtils.logOpenScreenAdSkip
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.MainActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.provider.ICsjAdProvider
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.TimeUtils.getToday
import com.gh.gamecenter.entity.AdConfig
import com.gh.gamecenter.entity.StartupAdEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent.Companion.createEvent
import com.gh.gamecenter.feature.exposure.ExposureType
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers
/**
* 广告实现代理类
*
* 由它来分发功能实现到具体的实现
*
* 以开屏广告为例有两种实现1. 自有的广告实现 2. 穿山甲的开屏广告实现
*/
object AdDelegateHelper {
private var mCsjAdImpl: ICsjAdProvider? = null
private val mAdConfigList: ArrayList<AdConfig> by lazy { arrayListOf() }
private var mSplashAd: AdConfig? = null
private var mDownloadManagerAd: AdConfig? = null
private val mGameSearchAdList: ArrayList<AdConfig> by lazy { arrayListOf() }
private var mVGameLaunchAd: AdConfig? = null
val vGameLaunchAd: AdConfig?
get() = mVGameLaunchAd
val splashAdDisplayInterval: Int
get() = mSplashAd?.ownerAd?.startAd?.displayInterval ?: 3
private const val AD_SDK_CSJ = "穿山甲"
const val AD_TYPE_SDK = "third_party_ads" // 第三方 SDK 广告
const val AD_TYPE_OWNER = "owner_ads" // 自有广告
private const val KEY_CACHE_CONFIG = "cache_config" // 放在 SP 里的广告缓存(避免接口加载问题)
private val mAdConfigSp: SharedPreferences by lazy {
HaloApp.getInstance().getSharedPreferences("AdConfig", Context.MODE_PRIVATE)
}
var isShowingSplashAd = false // 是否正在显示开屏广告
var gameSearchKeyword = ""
fun initAdSdk(context: Context) {
if (AdPluginDownloadHelper.isCsjPluginDownloaded()) {
initAdSdkInternal(context)
} else {
// 首次启动,为了不影响首页加载,延迟 3 秒再下载广告插件并初始化
AppExecutor.uiExecutor.executeWithDelay({
AdPluginDownloadHelper.downloadPluginIfNeeded(isCsj = true) {
initAdSdkInternal(context)
}
}, 3000L)
}
}
private fun initAdSdkInternal(context: Context) {
// 初始化穿山甲
if (mCsjAdImpl == null) {
mCsjAdImpl =
ARouter.getInstance().build(RouteConsts.provider.csjAd).navigation() as? ICsjAdProvider
val csjAppId = if (EnvHelper.isDevEnv) BuildConfig.DEV_CSJ_APPID else BuildConfig.CSJ_APPID
mCsjAdImpl?.initSDK(context, csjAppId, HaloApp.getInstance().oaid)
// 监听亮色/暗色模式切换
DarkModeUtils.registerModeChangeListener {
val topActivity = CurrentActivityHolder.getCurrentActivity() ?: return@registerModeChangeListener
updateThemeStatus(context, DarkModeUtils.isDarkModeOn(topActivity))
}
}
}
/**
* 请求接口获取广告相关配置
*/
@SuppressLint("CheckResult")
fun requestAdConfig(isFromRetry: Boolean, keyword: String = "", callback: (() -> Unit)? = null) {
// mAdConfigList 不为空不需要重试
if (isFromRetry && mAdConfigList.isNotEmpty()) {
return
}
val paramsMap = if (keyword.isNotEmpty()) mapOf("keyword" to keyword) else mapOf()
RetrofitManager.getInstance()
.newApi
.getAdConfig(paramsMap)
.subscribeOn(Schedulers.io())
.subscribe(object : BiResponse<List<AdConfig>>() {
override fun onSuccess(data: List<AdConfig>) {
gameSearchKeyword = keyword
handleAdConfig(data)
callback?.invoke()
// 缓存数据到 SP 供接口请求失败用
SPUtils.setString(mAdConfigSp, KEY_CACHE_CONFIG, data.toJson())
}
override fun onFailure(exception: Exception) {
super.onFailure(exception)
// 若接口请求失败时,从 SP 里获取上次缓存的数据
val cachedConfig: List<AdConfig>? = SPUtils.getString(mAdConfigSp, KEY_CACHE_CONFIG).toObject()
if (cachedConfig != null && mAdConfigList.isEmpty()) {
handleAdConfig(cachedConfig)
}
callback?.invoke()
}
})
}
/**
* 获取搜索页的广告列表
*/
fun getGameSearchAdList(): ArrayList<AdConfig> {
return mGameSearchAdList
}
/**
* 获取下载管理页的广告
*/
fun getDownloadManagerAd(): AdConfig? {
return mDownloadManagerAd
}
/**
* 处理广告配置
*/
fun handleAdConfig(configList: List<AdConfig>) {
mAdConfigList.clear()
mGameSearchAdList.clear()
mSplashAd = null
mDownloadManagerAd = null
mVGameLaunchAd = null
for (config in configList) {
mAdConfigList.add(config)
// 处理返回的数据
when (config.location) {
"halo_launch" -> {
config.ownerAd?.startAd?.let { it.id = config.ownerAd.id }
mSplashAd = config
}
"download_manager" -> mDownloadManagerAd = config
"game_search" -> config.let { mGameSearchAdList.add(it) }
"helper_launch" -> mVGameLaunchAd = config
}
}
}
/**
* 是否需要显示开屏广告
* @param isHotLaunch 是否为热启动
*/
fun shouldShowStartUpAd(isHotLaunch: Boolean): Boolean {
return mSplashAd != null
&& !isShowingSplashAd
&& (!isHotLaunch || shouldShowStartUpAdWhenHotLaunch())
&& !isMatchAdFreeRule(mSplashAd)
&& isMatchStartUpAdDisplayRule()
}
/**
* 热启动是否需要显示开屏广告(目前只展示第三方广告)
*/
private fun shouldShowStartUpAdWhenHotLaunch() = (mCsjAdImpl != null)
&& mSplashAd?.displayRule?.hotStartSplashAd?.type == AD_TYPE_SDK
&& mSplashAd?.hotStartThirdPartyAd != null
/**
* 是否需要显示下载管理广告
*/
fun shouldShowDownloadManagerAd(): Boolean {
return mDownloadManagerAd != null && !isMatchAdFreeRule(mDownloadManagerAd) && isMatchDownloadManagerAdDisplayRule()
}
fun shouldShowHelperLaunchAd(): Boolean {
return mVGameLaunchAd != null && !isMatchAdFreeRule(mVGameLaunchAd) && isMatchAdDisplayRule(mVGameLaunchAd, Constants.SP_LAST_HELPER_LAUNCH_AD_SHOW_TIME)
}
/**
* 是否需要显示游戏搜索广告
*/
fun shouldShowGameSearchAd(adConfig: AdConfig): Boolean {
return !isMatchAdFreeRule(adConfig) && isMatchGameSearchAdDisplayRule(adConfig)
}
/**
* 是否在免广告时长内
*/
private fun isMatchAdFreeRule(adConfig: AdConfig?): Boolean {
adConfig?.displayRule?.run {
if (adFreeDuration > 0) {
val ghInstalledDurationInHours = (System.currentTimeMillis() - PackageUtils.getInstalledTime(
HaloApp.getInstance(),
BuildConfig.APPLICATION_ID
)).toFloat() / 1000 / 3600
return ghInstalledDurationInHours < adFreeDuration
} else {
return false
}
}
return false
}
/**
* 是否大于开屏广告展示间隔时长
*/
private fun isMatchStartUpAdDisplayRule(): Boolean = isMatchAdDisplayRule(mSplashAd, Constants.SP_LAST_SPLASH_AD_SHOW_TIME)
/**
* 是否大于广告管理展示间隔时长
*/
private fun isMatchDownloadManagerAdDisplayRule(): Boolean = isMatchAdDisplayRule(mDownloadManagerAd, Constants.SP_LAST_DOWNLOAD_MANAGER_AD_SHOW_TIME)
private fun isMatchAdDisplayRule(adConfig: AdConfig?, spKey: String): Boolean {
adConfig?.displayRule?.run {
if (adDisplayInterval > 0) {
val lastShowTime = SPUtils.getLong(spKey, 0L)
val durationInMinutes = (System.currentTimeMillis() - lastShowTime).toFloat() / 1000 / 60
return durationInMinutes > adDisplayInterval
} else {
return true
}
}
return true
}
/**
* 是否大于游戏搜索展示间隔时长
*/
private fun isMatchGameSearchAdDisplayRule(adConfig: AdConfig?): Boolean {
adConfig?.displayRule?.run {
if (adDisplayInterval > 0) {
val lastShowTime = SPUtils.getLong(Constants.SP_LAST_GAME_SEARCH_AD_SHOW_TIME + adConfig.position, 0L)
val durationInMinutes = (System.currentTimeMillis() - lastShowTime).toFloat() / 1000 / 60
return durationInMinutes > adDisplayInterval
} else {
return true
}
}
return true
}
/**
* 更新主题样式
*/
private fun updateThemeStatus(context: Context, isDarkMode: Boolean) {
mCsjAdImpl?.updateThemeStatus(context, isDarkMode)
}
/**
* 请求开屏广告
*/
@JvmStatic
fun requestSplashAd(
activity: Activity,
adViewWidthInPx: Int,
adViewHeightInPx: Int,
adViewWidthInDp: Float,
adViewHeightInDp: Float,
startAdContainer: ViewGroup,
sdkStartAdContainer: ViewGroup,
sdkJumpBtn: TextView,
adsViewGroup: FrameLayout,
handler: BaseActivity.BaseHandler,
isHotLaunch: Boolean,
hideAction: () -> Unit
) {
val hideCallback = {
isShowingSplashAd = false
hideAction.invoke()
}
if (mSplashAd != null) {
when (if (isHotLaunch) mSplashAd!!.displayRule.hotStartSplashAd?.type else mSplashAd!!.displayRule.adSource) {
AD_TYPE_SDK -> {
isShowingSplashAd = true
requestThirdPartySplashAd(
activity,
adViewWidthInPx,
adViewHeightInPx,
adViewWidthInDp,
adViewHeightInDp,
startAdContainer,
sdkStartAdContainer,
sdkJumpBtn,
adsViewGroup,
handler,
isHotLaunch,
hideCallback
)
}
AD_TYPE_OWNER -> {
isShowingSplashAd = true
requestStandardSplashAd(
activity,
adViewWidthInPx,
adViewHeightInPx,
adViewWidthInDp,
adViewHeightInDp,
startAdContainer,
sdkStartAdContainer,
sdkJumpBtn,
adsViewGroup,
handler,
isHotLaunch,
hideCallback
)
}
}
} else {
hideCallback.invoke()
}
}
/**
* 获取第三方开屏广告
*/
private fun requestThirdPartySplashAd(
activity: Activity,
adViewWidthInPx: Int,
adViewHeightInPx: Int,
adViewWidthInDp: Float,
adViewHeightInDp: Float,
startAdContainer: ViewGroup,
sdkStartAdContainer: ViewGroup,
sdkJumpBtn: TextView,
adsViewGroup: FrameLayout,
handler: BaseActivity.BaseHandler,
isHotLaunch: Boolean,
hideCallback: () -> Unit
) {
// 第三方开屏广告回调,失败时根据接口配置选项决定是否显示自有开屏广告
val sdkSplashCallback: (isSuccess: Boolean) -> Unit = { isSuccess ->
if (isSuccess) {
hideCallback.invoke()
SPUtils.setLong(Constants.SP_LAST_SPLASH_AD_SHOW_TIME, System.currentTimeMillis())
} else {
if (mSplashAd?.displayRule?.adSource == AD_TYPE_SDK && mSplashAd?.displayRule?.onFailedAction == "show" && !isHotLaunch) {
sdkStartAdContainer.visibility = View.GONE
requestStandardSplashAd(
activity,
adViewWidthInPx,
adViewHeightInPx,
adViewWidthInDp,
adViewHeightInDp,
startAdContainer,
sdkStartAdContainer,
sdkJumpBtn,
adsViewGroup,
handler,
isHotLaunch,
hideCallback
)
} else {
hideCallback.invoke()
}
}
}
val thirdPartyAd = if (isHotLaunch) mSplashAd?.hotStartThirdPartyAd else mSplashAd?.thirdPartyAd
// 第三方广告的数据为空,按加载失败处理
if (mSplashAd == null || thirdPartyAd == null) {
sdkSplashCallback.invoke(false)
return
}
val timeout = if (isHotLaunch) {
((mSplashAd?.displayRule?.hotStartSplashAd?.timeout ?: 3.5F) * 1000).toInt()
} else {
((mSplashAd?.displayRule?.timeout ?: 3.5F) * 1000).toInt()
}
if (thirdPartyAd.sourceName == AD_SDK_CSJ) {
sdkStartAdContainer.visibility = View.VISIBLE
requestCsjSplashAd(
activity,
adViewWidthInPx,
adViewHeightInPx,
adViewWidthInDp,
adViewHeightInDp,
sdkStartAdContainer,
sdkJumpBtn,
timeout,
isHotLaunch,
sdkSplashCallback
)
}
}
/**
* 获取穿山甲的开屏广告
*/
private fun requestCsjSplashAd(
activity: Activity,
adViewWidthInPx: Int,
adViewHeightInPx: Int,
adViewWidthInDp: Float,
adViewHeightInDp: Float,
startAdContainer: ViewGroup,
sdkJumpBtn: TextView,
timeout: Int,
isHotLaunch: Boolean,
callback: (isSuccess: Boolean) -> Unit,
) {
val thirdPartyAd = if (isHotLaunch) mSplashAd?.hotStartThirdPartyAd else mSplashAd?.thirdPartyAd
if (mCsjAdImpl == null || thirdPartyAd == null) {
callback.invoke(false)
} else {
sdkJumpBtn.setOnClickListener {
callback.invoke(true)
if (activity is BaseActivity) {
activity.baseHandler.removeMessages(MainActivity.COUNTDOWN_SDK_AD)
}
}
val onAdShowAction = {
sdkJumpBtn.visibility = View.VISIBLE
if (activity is BaseActivity) {
activity.baseHandler.sendEmptyMessageDelayed(MainActivity.COUNTDOWN_SDK_AD, 1000)
}
SensorsBridge.trackEvent("ThirdPartyAdShow",
"ad_source", thirdPartyAd.sourceName,
"ad_id", thirdPartyAd.slotId,
"ad_format", mSplashAd?.typeChinese ?: "",
"ad_placement", "光环启动",
"launch_type", if (isHotLaunch) "热启动" else "冷启动",
"ad_space_id", mSplashAd?.id ?: "",
"ad_space_name", mSplashAd?.name ?: ""
)
}
val onAdClickAction = {
callback.invoke(true)
SensorsBridge.trackEvent("ThirdPartyAdClick",
"ad_source", thirdPartyAd.sourceName,
"ad_id", thirdPartyAd.slotId,
"ad_format", mSplashAd?.typeChinese ?: "",
"ad_placement", "光环启动",
"launch_type", if (isHotLaunch) "热启动" else "冷启动",
"ad_space_id", mSplashAd?.id ?: "",
"ad_space_name", mSplashAd?.name ?: ""
)
}
mCsjAdImpl?.requestSplashAd(
activity,
thirdPartyAd.slotId,
adViewWidthInPx,
adViewHeightInPx,
adViewWidthInDp,
adViewHeightInDp,
startAdContainer,
timeout,
onAdShowAction,
onAdClickAction,
callback,
)
}
}
/**
* 显示自有的开屏广告
*/
private fun requestStandardSplashAd(
activity: Activity,
adViewWidthInPx: Int,
adViewHeightInPx: Int,
adViewWidthInDp: Float,
adViewHeightInDp: Float,
startAdContainer: ViewGroup,
sdkStartAdContainer: ViewGroup,
sdkJumpBtn: TextView,
adsViewGroup: FrameLayout,
handler: BaseActivity.BaseHandler,
isHotLaunch: Boolean,
hideCallback: () -> Unit
) {
val splashAd = mSplashAd?.ownerAd?.startAd
val onEmptyCallback = {
if (mSplashAd?.displayRule?.adSource == AD_TYPE_OWNER && mSplashAd?.displayRule?.onFailedAction == "show" && mSplashAd?.thirdPartyAd != null) {
// 自有广告为空时,显示第三方广告
requestThirdPartySplashAd(
activity,
adViewWidthInPx,
adViewHeightInPx,
adViewWidthInDp,
adViewHeightInDp,
startAdContainer,
sdkStartAdContainer,
sdkJumpBtn,
adsViewGroup,
handler,
isHotLaunch,
hideCallback
)
} else {
hideCallback.invoke()
}
}
if (splashAd == null) {
onEmptyCallback.invoke()
return
}
if (!TextUtils.isEmpty(splashAd.img)) {
val showedTodayTimestamp = SPUtils.getString(Constants.SP_STARTUP_AD_TIMESTAMP, "") ?: ""
when (splashAd.rule) {
"each" -> showStandardSplashAd(splashAd, startAdContainer, handler, hideCallback)
"once" -> if (TextUtils.isEmpty(showedTodayTimestamp)
|| !showedTodayTimestamp.contains(splashAd.id)
) {
showStandardSplashAd(splashAd, startAdContainer, handler, hideCallback)
} else {
onEmptyCallback.invoke()
}
"everyday" -> {
val today = getToday()
if (TextUtils.isEmpty(showedTodayTimestamp)
|| !showedTodayTimestamp.contains(today)
|| !showedTodayTimestamp.contains(splashAd.id)
) {
showStandardSplashAd(splashAd, startAdContainer, handler, hideCallback)
} else {
onEmptyCallback.invoke()
}
}
else -> hideCallback.invoke()
}
SPUtils.setString(Constants.SP_STARTUP_AD_TIMESTAMP, splashAd.id + getToday())
} else {
hideCallback.invoke()
}
}
private fun showStandardSplashAd(
ad: StartupAdEntity,
startAdContainer: ViewGroup,
handler: BaseActivity.BaseHandler,
hideCallback: () -> Unit
) {
val jumpBtn = startAdContainer.findViewById<TextView>(R.id.jumpBtn)
val jumpDetailBtn: TextView = startAdContainer.findViewById(R.id.jumpDetailBtn)
val adImage: SimpleDraweeView = startAdContainer.findViewById(R.id.adImage)
val adVideo = startAdContainer.findViewById<SplashAdVideoView>(R.id.ad_video)
val icpContainer: View? = startAdContainer.findViewById(R.id.startAdIcpContainer)
startAdContainer.visibility = View.VISIBLE
icpContainer?.visibility = View.VISIBLE
jumpBtn.text = startAdContainer.context.getString(R.string.splash_jump, splashAdDisplayInterval)
jumpDetailBtn.text = ad.desc
jumpDetailBtn.setDrawableEnd(
AppCompatResources.getDrawable(
startAdContainer.context,
R.drawable.ic_startup_ad_arrow
), null, null
)
adImage.visibleIf(true)
ImageUtils.display(adImage, ad.img)
if (ad.isImageType) {
adVideo.visibleIf(false)
} else {
adVideo.visibleIf(true)
adVideo.startPlay(ad.video.url)
}
startAdContainer.setOnClickListener {
// 拦截点击事件传递
}
jumpBtn.setOnClickListener {
handler.removeMessages(MainActivity.COUNTDOWN_AD)
hideCallback.invoke()
val linkEntity = ad.jump
logOpenScreenAdSkip(
ad.id,
(if (linkEntity.text != null) linkEntity.text else "")!!,
(if (linkEntity.type != null) linkEntity.type else "")!!,
(if (linkEntity.link != null) linkEntity.link else "")!!
)
SensorsBridge.trackEvent(
"SplashAdOwnSkip",
"splash_ad_id",
ad.id,
"link_type",
linkEntity.type ?: "",
"link_id",
linkEntity.link ?: "",
"link_text",
linkEntity.text ?: ""
)
}
val sources: MutableList<ExposureSource> = ArrayList()
sources.add(ExposureSource("开屏广告", ad.id))
val event = createEvent(null, sources, null, ExposureType.EXPOSURE)
ExposureManager.log(event)
if (ad.button) {
jumpDetailBtn.setOnClickListener { v: View ->
val linkEntity = ad.jump
directToLinkPage(v.context, linkEntity, "(启动广告)", "", event)
SensorsBridge.trackEvent(
"SplashAdOwnClick",
"splash_ad_id",
ad.id,
"link_type",
linkEntity.type ?: "",
"link_id",
linkEntity.link ?: "",
"link_text",
linkEntity.text ?: ""
)
v.postDelayed({
handler.removeMessages(MainActivity.COUNTDOWN_AD)
hideCallback.invoke()
}, 1000)
}
jumpDetailBtn.visibility = View.VISIBLE
LogUtils.logStartAd("watch_start_ads", ad)
} else {
LogUtils.logStartAd("start_ads", ad)
}
SPUtils.setLong(Constants.SP_LAST_SPLASH_AD_SHOW_TIME, System.currentTimeMillis())
val msg = Message.obtain()
msg.what = MainActivity.COUNTDOWN_AD
msg.obj = ad
handler.sendMessageDelayed(msg, 1000)
}
/**
* 获取第三方信息流广告
*/
fun requestThirdPartyFlowAd(
fragment: Fragment,
slotId: String,
adContainerView: ViewGroup,
expressViewWidth: Float,
onAdShowAction: () -> Unit,
onAdClickAction: () -> Unit,
callback: (isSuccess: Boolean) -> Unit,
) {
mCsjAdImpl?.requestFlowAd(fragment, adContainerView, slotId, expressViewWidth, onAdShowAction, onAdClickAction, callback)
}
/**
* 获取第三方 Banner 广告
*/
fun requestThirdPartyBannerAd(
fragment: Fragment,
containerView: ViewGroup,
ad: AdConfig.ThirdPartyAd,
expressViewWidthInDp: Float,
onAdShowAction: () -> Unit,
onAdClickAction: () -> Unit,
callback: (isSuccess: Boolean) -> Unit
) {
val slotId = ad.slotId
val displayRatio: Float = if (ad.displaySize.isEmpty()) {
2F
} else {
val array = ad.displaySize.split("*")
if (array.size == 2) {
array[0].toFloat() / array[1].toFloat()
} else {
2F
}
}
val expressViewHeightInDp = expressViewWidthInDp / displayRatio
mCsjAdImpl?.requestBannerAd(
fragment,
containerView,
slotId,
expressViewWidthInDp,
expressViewHeightInDp,
onAdShowAction,
onAdClickAction,
callback
)
}
/**
* 获取第三方 全屏/插屏 广告
*/
fun requestFullScreenAd(
fragment: Fragment,
ad: AdConfig.ThirdPartyAd,
onAdShowAction: () -> Unit,
onAdClickAction: () -> Unit,
callback: (isSuccess: Boolean) -> Unit
) {
val slotId = ad.slotId
mCsjAdImpl?.requestFullScreenAd(
fragment,
slotId,
onAdShowAction,
onAdClickAction,
callback
)
}
/**
* 取消开屏广告
*/
fun cancelSplashAd(context: Context) {
mCsjAdImpl?.cancelSplashAd(context)
}
}

View File

@ -1,149 +0,0 @@
package com.gh.ad
import com.gh.download.simple.DownloadMessageHandler
import com.gh.download.simple.SimpleDownloadDatabase
import com.gh.download.simple.SimpleDownloadManager
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.PluginRedirectHelper
import com.gh.gamecenter.core.utils.SPUtils
import com.lg.download.DownloadError
import com.lg.download.DownloadStatus
import com.lg.download.httpclient.DefaultHttpClient
import com.lg.download.listener.InnerDownloadListener
import com.lg.ndownload.DownloadConfig
import com.lg.ndownload.DownloadConfigBuilder
import com.lg.ndownload.DownloadIoExecutor
import com.lightgame.utils.Utils
import java.lang.Exception
import java.net.URLConnection
object AdPluginDownloadHelper : InnerDownloadListener {
private const val CSJ_FILE_NAME = "2011394667"
private const val GDT_FILE_NAME = "gdt_plugin/gdtadv2.jar"
private const val CSJ_PLUGIN_URL = "https://and-static.ghzs66.com/android/static/2011394667"
private const val GDT_PLUGIN_URL = "https://and-static.ghzs66.com/android/static/gdtadv2.jar"
private var csjDownloadedCallback: (() -> Unit)? = null
/**
* 是否已经下载了广告插件
*/
fun isCsjPluginDownloaded(): Boolean {
return SPUtils.getBoolean(CSJ_FILE_NAME, false)
}
/**
* 下载广告插件并初始化 (初始化限定穿山甲)
*/
fun downloadPluginIfNeeded(isCsj: Boolean = false, isGdt: Boolean = false, csjCallback: (() -> Unit)? = null) {
val isCsjPluginDownloaded = SPUtils.getBoolean(CSJ_FILE_NAME, false)
val isGdtPluginDownloaded = SPUtils.getBoolean(GDT_FILE_NAME, false)
if (isCsj && isCsjPluginDownloaded) {
csjCallback?.invoke()
return
}
if (isGdt && isGdtPluginDownloaded) {
return
}
runOnIoThread {
csjDownloadedCallback = csjCallback
DownloadMessageHandler.init(SimpleDownloadDatabase.instance.downloadDao())
if (!isCsjPluginDownloaded && isCsj) {
val csjPluginConfig = DownloadConfigBuilder()
.setUniqueId(CSJ_FILE_NAME)
.setUrl(CSJ_PLUGIN_URL)
.setFileName(CSJ_FILE_NAME)
.setHttpClient(DefaultHttpClient())
.setDownloadThreadSize(2)
.setPathToStore(PluginRedirectHelper.getAssetDir())
.setDownloadExecutor(DownloadIoExecutor.getInstance())
.setDownloadListener(this).build()
SimpleDownloadManager.download(csjPluginConfig)
}
if (!isGdtPluginDownloaded && isGdt) {
val gdtPluginConfig = DownloadConfigBuilder()
.setUniqueId(GDT_FILE_NAME)
.setUrl(GDT_PLUGIN_URL)
.setFileName(GDT_FILE_NAME)
.setHttpClient(DefaultHttpClient())
.setDownloadThreadSize(2)
.setPathToStore(PluginRedirectHelper.getAssetDir())
.setDownloadExecutor(DownloadIoExecutor.getInstance())
.setDownloadListener(this).build()
SimpleDownloadManager.download(gdtPluginConfig)
}
}
}
override fun onError(id: String?, error: DownloadError?, exception: Exception?) {
Utils.log("下载广告插件失败 $id")
id?.let {
if (it == CSJ_FILE_NAME) {
csjDownloadedCallback = null
}
SimpleDownloadManager.cancel(it)
}
}
override fun onProgress(id: String?, progress: Float) {
Utils.log("下载广告插件进度 $id $progress")
}
override fun onProgressWithoutThrottle(id: String?, progress: Float) {
// do nothing
}
override fun onSizeReceived(id: String?, fileSize: Long) {
// do nothing
}
override fun onReadyToDownload(id: String?, actualThreadSize: Int) {
// do nothing
}
override fun onStatusChanged(id: String?, status: DownloadStatus?) {
// do nothing
}
override fun onDownloadComplete(id: String?, elapsedTime: Long) {
id?.let {
// id 即为插件名
SPUtils.setBoolean(it, true)
if (it == CSJ_FILE_NAME) {
csjDownloadedCallback?.invoke()
csjDownloadedCallback = null
}
}
}
override fun onSpeedChanged(id: String?, speed: Float) {
// do nothing
}
override fun onRedirectingUrl(
id: String?,
connection: URLConnection?,
config: DownloadConfig?
) {
// do nothing
}
override fun onRedirectedUrl(
id: String?,
connection: URLConnection?,
redirectedUrl: String?
) {
// do nothing
}
}

View File

@ -1,107 +0,0 @@
package com.gh.ad
import android.content.Context
import android.view.View
import android.view.ViewGroup
import android.view.ViewStub
import androidx.fragment.app.Fragment
import com.alibaba.android.arouter.facade.annotation.Route
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.provider.ILaunchAd
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.entity.AdConfig
@Route(path = RouteConsts.provider.vaAd, name = "畅玩启动页广告")
class LaunchAdImpl : ILaunchAd {
override fun init(context: Context?) {
}
override fun requestAd(fragment: Fragment, container: ViewGroup, maskView: View, topViewStub: ViewStub, bottomViewStub: ViewStub, adClickAction: () -> Unit): View {
if (AdDelegateHelper.shouldShowHelperLaunchAd()) {
val launchAd = AdDelegateHelper.vGameLaunchAd
val showThirdPartyAd = launchAd?.displayRule?.adSource == AdDelegateHelper.AD_TYPE_SDK
val thirdPartyAd = launchAd?.thirdPartyAd
if (showThirdPartyAd && thirdPartyAd != null) {
val onAdShowAction = {
SensorsBridge.trackEvent("ThirdPartyAdShow",
"ad_source", thirdPartyAd.sourceName,
"ad_id", thirdPartyAd.slotId,
"ad_format", launchAd.typeChinese,
"ad_placement", AD_PLACEMENT,
"ad_space_id", launchAd.id,
"ad_space_name", launchAd.name
)
}
val onAdClickAction = {
SensorsBridge.trackEvent("ThirdPartyAdClick",
"ad_source", thirdPartyAd.sourceName,
"ad_id", thirdPartyAd.slotId,
"ad_format", launchAd.typeChinese,
"ad_placement", AD_PLACEMENT,
"ad_space_id", launchAd.id,
"ad_space_name", launchAd.name
)
adClickAction.invoke()
}
if (launchAd.type == AdConfig.TYPE_BANNER) {
requestBannerAd(fragment, container, maskView, thirdPartyAd, onAdShowAction, onAdClickAction)
return topViewStub.inflate()
} else if (launchAd.type == AdConfig.TYPE_INTERSTITIAL) {
requestFullScreenAd(fragment, thirdPartyAd, onAdShowAction, onAdClickAction)
return bottomViewStub.inflate()
}
}
}
return bottomViewStub.inflate()
}
private fun requestBannerAd(
fragment: Fragment,
container: ViewGroup,
maskView: View,
thirdPartyAd: AdConfig.ThirdPartyAd,
onAdShowAction: () -> Unit,
onAdClickAction: () -> Unit,
) {
AdDelegateHelper.requestThirdPartyBannerAd(
fragment,
container,
thirdPartyAd,
DisplayUtils.getScreenWidthInDp(fragment.requireActivity()),
onAdShowAction,
onAdClickAction
) { isSuccess ->
maskView.goneIf(!isSuccess)
if (isSuccess) {
SPUtils.setLong(Constants.SP_LAST_HELPER_LAUNCH_AD_SHOW_TIME, System.currentTimeMillis())
}
}
}
private fun requestFullScreenAd(
fragment: Fragment,
thirdPartyAd: AdConfig.ThirdPartyAd,
onAdShowAction: () -> Unit,
onAdClickAction: () -> Unit
) {
AdDelegateHelper.requestFullScreenAd(
fragment,
thirdPartyAd,
onAdShowAction,
onAdClickAction
) { isSuccess ->
if (isSuccess) {
SPUtils.setLong(Constants.SP_LAST_HELPER_LAUNCH_AD_SHOW_TIME, System.currentTimeMillis())
}
}
}
companion object {
private const val AD_PLACEMENT = "畅玩启动"
}
}

View File

@ -1,78 +0,0 @@
package com.gh.ad
import android.app.Activity
import android.content.Context
import android.util.AttributeSet
import android.view.WindowManager
import com.gh.gamecenter.R
import com.gh.gamecenter.video.detail.CustomManager
import com.shuyu.gsyvideoplayer.utils.GSYVideoType
import com.shuyu.gsyvideoplayer.utils.GSYVideoType.SCREEN_TYPE_FULL
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
import com.shuyu.gsyvideoplayer.video.base.GSYVideoViewBridge
class SplashAdVideoView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) :
StandardGSYVideoPlayer(context, attrs) {
fun startPlay(url: String) {
GSYVideoType.setShowType(SCREEN_TYPE_FULL)
GSYVideoType.setRenderType(GSYVideoType.SUFRACE)
CustomManager.getCustomManager(getKey()).isNeedMute = true
setUp(url, true, "")
setNeedAutoAdaptation(false)
startPlayLogic()
}
override fun getGSYVideoManager(): GSYVideoViewBridge {
CustomManager.getCustomManager(getKey()).initContext(context.applicationContext)
return CustomManager.getCustomManager(getKey())
}
private fun getKey() = "splash_ad"
/**
* 覆盖父类方法,防止在是视频 Preparing 阶段封面图被隐藏,导致白屏
*/
override fun changeUiToPreparingShow() = Unit
override fun getLayoutId(): Int {
return R.layout.layout_splash_ad_video
}
override fun onAutoCompletion() {
setStateAndUi(CURRENT_STATE_AUTO_COMPLETE);
mSaveChangeViewTIme = 0
mCurrentPosition = 0
if (!mIfCurrentIsFullscreen) {
getGSYVideoManager().setLastListener(null)
}
mAudioManager.abandonAudioFocus(onAudioFocusChangeListener);
if (mContext is Activity) {
try {
(mContext as Activity).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
} catch (e: Exception) {
e.printStackTrace()
}
}
releaseNetWorkState()
if (mVideoAllCallBack != null && isCurrentMediaListener()) {
mVideoAllCallBack.onAutoComplete(mOriginUrl, mTitle, this)
}
mHadPlay = false
}
fun clearAll() {
GSYVideoType.setShowType(GSYVideoType.SCREEN_TYPE_DEFAULT)
GSYVideoType.setRenderType(GSYVideoType.TEXTURE)
release()
CustomManager.removeManager(getKey())
}
}

View File

@ -21,8 +21,6 @@ import com.gh.common.view.RichEditor
import com.gh.gamecenter.CropImageActivity import com.gh.gamecenter.CropImageActivity
import com.gh.gamecenter.R import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.activity.ToolBarActivity import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.entity.LocalVideoEntity
import com.gh.gamecenter.feature.selector.LocalMediaActivity
import com.gh.gamecenter.common.utils.* import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.AppExecutor import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.runOnIoThread import com.gh.gamecenter.core.runOnIoThread
@ -32,7 +30,6 @@ import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.qa.editor.* import com.gh.gamecenter.qa.editor.*
import com.gh.gamecenter.feature.entity.AnswerEntity import com.gh.gamecenter.feature.entity.AnswerEntity
import com.gh.gamecenter.feature.entity.ArticleEntity import com.gh.gamecenter.feature.entity.ArticleEntity
import com.gh.gamecenter.feature.selector.ChooseType
import com.gh.gamecenter.qa.entity.EditorInsertEntity import com.gh.gamecenter.qa.entity.EditorInsertEntity
import com.gh.gamecenter.video.poster.PosterEditActivity import com.gh.gamecenter.video.poster.PosterEditActivity
import com.gh.gamecenter.video.upload.UploadManager import com.gh.gamecenter.video.upload.UploadManager
@ -47,7 +44,7 @@ import org.json.JSONObject
import java.io.File import java.io.File
// TODO: 移动到module_bbs模块 // TODO: 移动到module_bbs模块
abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor() : ToolBarActivity(), abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> : ToolBarActivity(),
KeyboardHeightObserver, UploadVideoListener { KeyboardHeightObserver, UploadVideoListener {
lateinit var mRichEditor: RichEditor lateinit var mRichEditor: RichEditor
@ -60,16 +57,11 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
private lateinit var mEditorFontItalic: CheckableImageView private lateinit var mEditorFontItalic: CheckableImageView
private lateinit var mEditorFontStrikeThrough: CheckableImageView private lateinit var mEditorFontStrikeThrough: CheckableImageView
private lateinit var mEditorFontUnderline: CheckableImageView private lateinit var mEditorFontUnderline: CheckableImageView
private lateinit var mEditorParagraphDivider: CheckableImageView
private lateinit var mEditorParagraphH1: CheckableImageView private lateinit var mEditorParagraphH1: CheckableImageView
private lateinit var mEditorParagraphH2: CheckableImageView private lateinit var mEditorParagraphH2: CheckableImageView
private lateinit var mEditorParagraphH3: CheckableImageView private lateinit var mEditorParagraphH3: CheckableImageView
private lateinit var mEditorParagraphH4: CheckableImageView private lateinit var mEditorParagraphH4: CheckableImageView
private lateinit var mEditorParagraphQuote: CheckableImageView private lateinit var mEditorParagraphQuote: CheckableImageView
private lateinit var mEditorAlignLeft: CheckableImageView
private lateinit var mEditorAlignCenter: CheckableImageView
private lateinit var mEditorAlignRight: CheckableImageView
private lateinit var mEditorAlignContainer: View
private lateinit var mEditorFontContainer: View private lateinit var mEditorFontContainer: View
private lateinit var mEditorParagraphContainer: View private lateinit var mEditorParagraphContainer: View
private lateinit var mEditorLinkContainer: View private lateinit var mEditorLinkContainer: View
@ -105,7 +97,6 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
mRichEditor.insertCustomStyleLink(insertData) mRichEditor.insertCustomStyleLink(insertData)
} }
} }
INSERT_ARTICLE_CODE -> { INSERT_ARTICLE_CODE -> {
val article = val article =
data?.getParcelableExtra<ArticleEntity>(ArticleEntity::class.java.simpleName) data?.getParcelableExtra<ArticleEntity>(ArticleEntity::class.java.simpleName)
@ -115,7 +106,6 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
mRichEditor.insertCustomStyleLink(insertData) mRichEditor.insertCustomStyleLink(insertData)
} }
} }
INSERT_GAME_CODE -> { INSERT_GAME_CODE -> {
val game = data?.getParcelableExtra<GameEntity>(GameEntity::class.java.simpleName) val game = data?.getParcelableExtra<GameEntity>(GameEntity::class.java.simpleName)
if (game != null) { if (game != null) {
@ -124,7 +114,6 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
mRichEditor.insertCustomStyleLink(insertData) mRichEditor.insertCustomStyleLink(insertData)
} }
} }
INSERT_GAME_COLLECTION_CODE -> { INSERT_GAME_COLLECTION_CODE -> {
val gameCollectionEntity = val gameCollectionEntity =
data?.getParcelableExtra<GamesCollectionEntity>(GamesCollectionEntity::class.java.simpleName) data?.getParcelableExtra<GamesCollectionEntity>(GamesCollectionEntity::class.java.simpleName)
@ -134,11 +123,9 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
mRichEditor.insertCustomStyleLink(insertData) mRichEditor.insertCustomStyleLink(insertData)
} }
} }
REQUEST_CODE_IMAGE -> { REQUEST_CODE_IMAGE -> {
if (data != null) mViewModel.uploadPic(data) if (data != null) mViewModel.uploadPic(data)
} }
INSERT_MEDIA_VIDEO_CODE -> { INSERT_MEDIA_VIDEO_CODE -> {
val localVideoList = val localVideoList =
data?.getParcelableArrayListExtra<LocalVideoEntity>(LocalVideoEntity::class.java.name) data?.getParcelableArrayListExtra<LocalVideoEntity>(LocalVideoEntity::class.java.name)
@ -148,14 +135,12 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
uploadVideo(localVideoList) uploadVideo(localVideoList)
} }
} }
REQUEST_CODE_IMAGE_CROP -> { REQUEST_CODE_IMAGE_CROP -> {
val imagePath = data?.getStringExtra(CropImageActivity.RESULT_CLIP_PATH) val imagePath = data?.getStringExtra(CropImageActivity.RESULT_CLIP_PATH)
if (!imagePath.isNullOrEmpty()) { if (!imagePath.isNullOrEmpty()) {
mViewModel.uploadPoster(imagePath) mViewModel.uploadPoster(imagePath)
} }
} }
INSERT_VIDEO_CODE -> { INSERT_VIDEO_CODE -> {
val videoEntity = data?.getParcelableExtra<MyVideoEntity>(MyVideoEntity::class.java.simpleName) val videoEntity = data?.getParcelableExtra<MyVideoEntity>(MyVideoEntity::class.java.simpleName)
if (videoEntity != null) { if (videoEntity != null) {
@ -209,12 +194,7 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
mEditorParagraphH2 = findViewById(R.id.editor_paragraph_h2) mEditorParagraphH2 = findViewById(R.id.editor_paragraph_h2)
mEditorParagraphH3 = findViewById(R.id.editor_paragraph_h3) mEditorParagraphH3 = findViewById(R.id.editor_paragraph_h3)
mEditorParagraphH4 = findViewById(R.id.editor_paragraph_h4) mEditorParagraphH4 = findViewById(R.id.editor_paragraph_h4)
mEditorParagraphDivider = findViewById(R.id.editor_paragraph_divider)
mEditorParagraphQuote = findViewById(R.id.editor_paragraph_quote) mEditorParagraphQuote = findViewById(R.id.editor_paragraph_quote)
mEditorAlignLeft = findViewById(R.id.editor_align_left)
mEditorAlignCenter = findViewById(R.id.editor_align_center)
mEditorAlignRight = findViewById(R.id.editor_align_right)
mEditorAlignContainer = findViewById(R.id.editor_align_container)
mEditorFontContainer = findViewById(R.id.editor_font_container) mEditorFontContainer = findViewById(R.id.editor_font_container)
mEditorParagraphContainer = findViewById(R.id.editor_paragraph_container) mEditorParagraphContainer = findViewById(R.id.editor_paragraph_container)
mEditorLinkContainer = findViewById(R.id.editor_link_container) mEditorLinkContainer = findViewById(R.id.editor_link_container)
@ -236,7 +216,7 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
mKeyboardHeightProvider = KeyboardHeightProvider(this) mKeyboardHeightProvider = KeyboardHeightProvider(this)
mRichEditor.post { mKeyboardHeightProvider?.start() } mRichEditor.post { mKeyboardHeightProvider?.start() }
mRichEditor.enableForceDark(DarkModeUtils.isDarkModeOn(this)) mRichEditor.enableForceDark(DarkModeUtils.isDarkModeOn(this))
mRichEditor.setEditorBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(this)) mRichEditor.setEditorBackgroundColor(R.color.background_white.toColor(this))
mRichEditor.setEditorFontColor(if (mIsDarkModeOn) Color.parseColor("#C2C2C2") else Color.parseColor("#4A4A4A")) mRichEditor.setEditorFontColor(if (mIsDarkModeOn) Color.parseColor("#C2C2C2") else Color.parseColor("#4A4A4A"))
// 防止个别手机在Js里无法获取粘贴内容 // 防止个别手机在Js里无法获取粘贴内容
mRichEditor.addJavascriptInterface(OnPasteListener(), "onPasteListener") mRichEditor.addJavascriptInterface(OnPasteListener(), "onPasteListener")
@ -261,13 +241,6 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
mRichEditor.hasFocus() mRichEditor.hasFocus()
} else false } else false
} }
mRichEditor.setOnDecorationChangeListener { _, types ->
mEditorAlignLeft.isChecked = types.contains(RichEditor.Type.JUSTIFYLEFT)
mEditorAlignCenter.isChecked = types.contains(RichEditor.Type.JUSTIFYCENTER)
mEditorAlignRight.isChecked = types.contains(RichEditor.Type.JUSTIFYRIGHT)
}
mOriginalCb.setOnCheckedChangeListener { _, isChecked -> mOriginalCb.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) { if (isChecked) {
mOriginalTipsContainer.alpha = 0f mOriginalTipsContainer.alpha = 0f
@ -352,9 +325,6 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
MtaHelper.onEvent(mtaEventName(), "文字样式", "文字样式-下滑线") MtaHelper.onEvent(mtaEventName(), "文字样式", "文字样式-下滑线")
} }
} }
mEditorParagraphDivider.setOnClickListener {
mRichEditor.insertDivider()
}
mEditorParagraphH1.setOnClickListener { mEditorParagraphH1.setOnClickListener {
if (mEditorParagraphH1.isChecked) { if (mEditorParagraphH1.isChecked) {
mRichEditor.formatBlock() mRichEditor.formatBlock()
@ -400,27 +370,6 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
} }
mEditorParagraphQuote.isChecked = !mEditorParagraphQuote.isChecked mEditorParagraphQuote.isChecked = !mEditorParagraphQuote.isChecked
} }
mEditorAlignLeft.setOnClickListener {
if (!mEditorAlignLeft.isChecked) {
mRichEditor.setAlignLeft()
MtaHelper.onEvent(mtaEventName(), "文本对齐选项", "文本对齐选项-靠左")
mEditorAlignLeft.isChecked = !mEditorAlignLeft.isChecked
}
}
mEditorAlignCenter.setOnClickListener {
if (!mEditorAlignCenter.isChecked) {
mRichEditor.setAlignCenter()
MtaHelper.onEvent(mtaEventName(), "文本对齐选项", "文本对齐选项-靠中")
mEditorAlignCenter.isChecked = !mEditorAlignCenter.isChecked
}
}
mEditorAlignRight.setOnClickListener {
if (!mEditorAlignRight.isChecked) {
mRichEditor.setAlignRight()
MtaHelper.onEvent(mtaEventName(), "文本对齐选项", "文本对齐选项-靠右")
mEditorAlignRight.isChecked = !mEditorAlignRight.isChecked
}
}
findViewById<View>(R.id.editor_link_answer).setOnClickListener { findViewById<View>(R.id.editor_link_answer).setOnClickListener {
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-回答") MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-回答")
startActivityForResult( startActivityForResult(
@ -500,22 +449,25 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
return return
} }
try { try {
PermissionHelper.checkStoragePermissionBeforeAction(this) { PermissionHelper.checkStoragePermissionBeforeAction(this,
val maxChooseCount = if (videoCount + 3 <= MAX_MEDIA_COUNT) 3 else MAX_MEDIA_COUNT - videoCount object : EmptyCallback {
startActivityForResult( override fun onCallback() {
LocalMediaActivity.getIntent( val maxChooseCount = if (videoCount + 3 <= MAX_MEDIA_COUNT) 3 else MAX_MEDIA_COUNT - videoCount
this@BaseRichEditorActivity, startActivityForResult(
ChooseType.VIDEO, LocalMediaActivity.getIntent(
maxChooseCount, this@BaseRichEditorActivity,
if (mtaEventName() == "提问帖") "发提问帖" else "发帖子" LocalMediaActivity.ChooseType.VIDEO,
), INSERT_MEDIA_VIDEO_CODE maxChooseCount,
) if (mtaEventName() == "提问帖") "发提问帖" else "发帖子"
NewLogUtils.logChooseMedia( ), INSERT_MEDIA_VIDEO_CODE
"view_media", )
if (mtaEventName() == "提问帖") "提问帖" else "帖子", NewLogUtils.logChooseMedia(
"视频" "view_media",
) if (mtaEventName() == "提问帖") "提问帖" else "帖子",
} "视频"
)
}
})
} catch (e: Exception) { } catch (e: Exception) {
toast(R.string.media_image_hint) toast(R.string.media_image_hint)
e.printStackTrace() e.printStackTrace()
@ -530,16 +482,18 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
return return
} }
try { try {
PermissionHelper.checkStoragePermissionBeforeAction(this) { PermissionHelper.checkStoragePermissionBeforeAction(this, object : EmptyCallback {
val maxChooseCount = if (imageCount + 10 <= MAX_IMAGE_COUNT) 10 else MAX_IMAGE_COUNT - imageCount override fun onCallback() {
val intent = LocalMediaActivity.getIntent( val maxChooseCount = if (imageCount + 10 <= MAX_IMAGE_COUNT) 10 else MAX_IMAGE_COUNT - imageCount
this@BaseRichEditorActivity, val intent = LocalMediaActivity.getIntent(
ChooseType.IMAGE, this@BaseRichEditorActivity,
maxChooseCount, LocalMediaActivity.ChooseType.IMAGE,
if (mtaEventName() == "提问帖") "发提问帖" else "发帖子" maxChooseCount,
) if (mtaEventName() == "提问帖") "发提问帖" else "发帖子"
startActivityForResult(intent, REQUEST_CODE_IMAGE) )
} startActivityForResult(intent, REQUEST_CODE_IMAGE)
}
})
} catch (e: Exception) { } catch (e: Exception) {
toast(R.string.media_image_hint) toast(R.string.media_image_hint)
e.printStackTrace() e.printStackTrace()
@ -562,7 +516,6 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
mEditorFontContainer.visibility = if (mEditorFont.isChecked) View.VISIBLE else View.GONE mEditorFontContainer.visibility = if (mEditorFont.isChecked) View.VISIBLE else View.GONE
mEditorParagraphContainer.visibility = mEditorParagraphContainer.visibility =
if (mEditorFont.isChecked) View.VISIBLE else View.GONE if (mEditorFont.isChecked) View.VISIBLE else View.GONE
mEditorAlignContainer.visibility = if (mEditorFont.isChecked) View.VISIBLE else View.GONE
mEditorLinkContainer.visibility = View.GONE mEditorLinkContainer.visibility = View.GONE
mTagsContainer.visibility = View.GONE mTagsContainer.visibility = View.GONE
mIsExtendedKeyboardShow = mEditorFont.isChecked mIsExtendedKeyboardShow = mEditorFont.isChecked
@ -584,7 +537,6 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
if (mEditorLink.isChecked) View.VISIBLE else View.GONE if (mEditorLink.isChecked) View.VISIBLE else View.GONE
mEditorLinkContainer.visibility = if (mEditorLink.isChecked) View.VISIBLE else View.GONE mEditorLinkContainer.visibility = if (mEditorLink.isChecked) View.VISIBLE else View.GONE
mEditorFontContainer.visibility = View.GONE mEditorFontContainer.visibility = View.GONE
mEditorAlignContainer.visibility = View.GONE
mEditorParagraphContainer.visibility = View.GONE mEditorParagraphContainer.visibility = View.GONE
mTagsContainer.visibility = View.GONE mTagsContainer.visibility = View.GONE
mIsExtendedKeyboardShow = mEditorLink.isChecked mIsExtendedKeyboardShow = mEditorLink.isChecked
@ -800,9 +752,9 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
override fun onDarkModeChanged() { override fun onDarkModeChanged() {
super.onDarkModeChanged() super.onDarkModeChanged()
updateStatusBarColor(com.gh.gamecenter.common.R.color.ui_surface, com.gh.gamecenter.common.R.color.ui_surface) updateStatusBarColor(R.color.background_white, R.color.background_white)
mRichEditor.enableForceDark(DarkModeUtils.isDarkModeOn(this)) mRichEditor.enableForceDark(DarkModeUtils.isDarkModeOn(this))
mRichEditor.setEditorBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(this)) mRichEditor.setEditorBackgroundColor(R.color.background_white.toColor(this))
mRichEditor.setEditorFontColor(if (mIsDarkModeOn) Color.parseColor("#C2C2C2") else Color.parseColor("#4A4A4A")) mRichEditor.setEditorFontColor(if (mIsDarkModeOn) Color.parseColor("#C2C2C2") else Color.parseColor("#4A4A4A"))
} }
@ -824,7 +776,7 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
const val INSERT_VIDEO_CODE = 415 const val INSERT_VIDEO_CODE = 415
const val MAX_INPUT_TEXT_NUM = 10000 const val MAX_INPUT_TEXT_NUM = 10000
const val MAX_MEDIA_COUNT = 20 const val MAX_MEDIA_COUNT = 20
const val MAX_IMAGE_COUNT = 70 const val MAX_IMAGE_COUNT = 35
const val REQUEST_CODE_IMAGE = 120 const val REQUEST_CODE_IMAGE = 120
const val INSERT_MEDIA_VIDEO_CODE = 121 const val INSERT_MEDIA_VIDEO_CODE = 121

View File

@ -1,6 +1,5 @@
package com.gh.base package com.gh.base
import android.annotation.SuppressLint
import android.app.Application import android.app.Application
import android.content.Intent import android.content.Intent
import android.graphics.Bitmap import android.graphics.Bitmap
@ -10,16 +9,15 @@ import android.text.TextUtils
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
import com.gh.gamecenter.common.entity.ErrorEntity
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.Response import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.* import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.runOnUiThread import com.gh.gamecenter.core.runOnUiThread
import com.gh.gamecenter.core.utils.MD5Utils import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.core.utils.ToastUtils import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.entity.ForumDetailEntity import com.gh.gamecenter.common.entity.ErrorEntity
import com.gh.gamecenter.common.entity.LocalVideoEntity import com.gh.gamecenter.entity.LocalVideoEntity
import com.gh.gamecenter.entity.QuoteCountEntity import com.gh.gamecenter.entity.QuoteCountEntity
import com.gh.gamecenter.qa.BbsType import com.gh.gamecenter.qa.BbsType
import com.gh.gamecenter.retrofit.RetrofitManager import com.gh.gamecenter.retrofit.RetrofitManager
@ -30,21 +28,16 @@ import com.google.gson.JsonObject
import com.lightgame.utils.Utils import com.lightgame.utils.Utils
import com.zhihu.matisse.Matisse import com.zhihu.matisse.Matisse
import com.zhihu.matisse.internal.utils.PathUtils import com.zhihu.matisse.internal.utils.PathUtils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody import okhttp3.ResponseBody
import retrofit2.HttpException import retrofit2.HttpException
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.util.*
import kotlin.collections.LinkedHashMap
import kotlin.collections.set import kotlin.collections.set
// TODO: 移动到module_bbs模块 // TODO: 移动到module_bbs模块
abstract class BaseRichEditorViewModel(application: Application) : AndroidViewModel(application) { abstract class BaseRichEditorViewModel(application: Application) : AndroidViewModel(application) {
val mApi: ApiService = RetrofitManager.getInstance().api val mApi: ApiService = RetrofitManager.getInstance().api
val mNewApi: ApiService = RetrofitManager.getInstance().newApi
val processDialog = MediatorLiveData<WaitingDialogFragment.WaitingDialogData>() val processDialog = MediatorLiveData<WaitingDialogFragment.WaitingDialogData>()
val chooseImagesUpload = MutableLiveData<LinkedHashMap<String, String>>() val chooseImagesUpload = MutableLiveData<LinkedHashMap<String, String>>()
val chooseImagesUploadSuccess = MutableLiveData<LinkedHashMap<String, String>>() val chooseImagesUploadSuccess = MutableLiveData<LinkedHashMap<String, String>>()
@ -58,11 +51,10 @@ abstract class BaseRichEditorViewModel(application: Application) : AndroidViewMo
val TITLE_MIN_LENGTH = 6 val TITLE_MIN_LENGTH = 6
val MIN_TEXT_LENGTH = 6 val MIN_TEXT_LENGTH = 6
val MAX_TEXT_LENGTH = 10000 val MAX_TEXT_LENGTH = 10000
val FILE_HOST = "file:///"
var id = ""//视频标记 var id = ""//视频标记
var videoId = ""//更改封面视频id var videoId = ""//更改封面视频id
val quoteCountEntity = QuoteCountEntity()//数据上报用 val quoteCountEntity = QuoteCountEntity()//数据上报用
val sectionListLiveData = MutableLiveData<List<ForumDetailEntity.Section>>()
var isModerator = false
fun setUploadVideoListener(uploadVideoListener: UploadVideoListener) { fun setUploadVideoListener(uploadVideoListener: UploadVideoListener) {
this.mUploadVideoListener = uploadVideoListener this.mUploadVideoListener = uploadVideoListener
@ -83,7 +75,7 @@ abstract class BaseRichEditorViewModel(application: Application) : AndroidViewMo
val application: Application = getApplication() val application: Application = getApplication()
Utils.toast( Utils.toast(
getApplication(), getApplication(),
application.getString(com.gh.gamecenter.common.R.string.pic_max_hint, count) application.getString(R.string.pic_max_hint, count)
) )
continue continue
} }
@ -124,15 +116,8 @@ abstract class BaseRichEditorViewModel(application: Application) : AndroidViewMo
} }
val map = LinkedHashMap<String, String>() val map = LinkedHashMap<String, String>()
for (key in imageUrlMap.keys) { for (key in imageUrlMap.keys) {
// 文件格式为 HEIC 时,使用经 OSS 转码的图片作为预览图片 map[MD5Utils.getUrlMD5(key)] = FILE_HOST + key.decodeURI()
if (FileUtils.getFileMimeType(getApplication(), key.decodeURI())?.lowercase(Locale.CHINA)?.contains("heic") == true) { mapImages[TextUtils.htmlEncode(key).decodeURI()] = imageUrlMap[key] ?: ""
val transformedImgUrl = ImageUtils.getIdealImageUrl(imageUrlMap[key], 5000) ?: ""
map[MD5Utils.getUrlMD5(key)] = transformedImgUrl
mapImages[transformedImgUrl.decodeURI()] = imageUrlMap[key] ?: ""
} else {
map[MD5Utils.getUrlMD5(key)] = imageUrlMap[key] ?: ""
mapImages[TextUtils.htmlEncode(key).decodeURI()] = imageUrlMap[key] ?: ""
}
} }
chooseImagesUploadSuccess.value = map chooseImagesUploadSuccess.value = map
} }
@ -423,30 +408,6 @@ abstract class BaseRichEditorViewModel(application: Application) : AndroidViewMo
return true return true
} }
fun getForumSections(bbsId: String) {
mNewApi.getForumSections(bbsId)
.compose(observableToMain())
.subscribe(object : Response<List<ForumDetailEntity.Section>>() {
override fun onResponse(response: List<ForumDetailEntity.Section>?) {
response?.run {
sectionListLiveData.postValue(this)
}
}
})
}
@SuppressLint("CheckResult")
fun getModeratorsInfo(bbsId: String) {
mApi.getModeratorsInfo(bbsId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<JsonObject>() {
override fun onSuccess(data: JsonObject) {
isModerator = data["is_moderators"].asBoolean
}
})
}
private fun getVideoType(): String { private fun getVideoType(): String {
return when (type) { return when (type) {
BbsType.GAME_BBS.value -> { BbsType.GAME_BBS.value -> {

View File

@ -1,20 +1,18 @@
package com.gh.base package com.gh.base
import android.graphics.Typeface
import android.os.Bundle import android.os.Bundle
import android.text.TextUtils
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import com.gh.download.DownloadManager import com.gh.download.DownloadManager
import com.gh.gamecenter.DownloadManagerActivity import com.gh.gamecenter.DownloadManagerActivity
import com.gh.gamecenter.R import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.activity.ToolBarActivity import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.constant.Constants import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.viewModelProvider import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.SPUtils.getBoolean import com.gh.gamecenter.core.utils.SPUtils.getBoolean
import com.gh.gamecenter.entity.GameUpdateEntity import com.gh.gamecenter.entity.GameUpdateEntity
import com.gh.gamecenter.eventbus.EBDownloadStatus import com.gh.gamecenter.eventbus.EBDownloadStatus
@ -46,7 +44,7 @@ abstract class DownloadToolbarActivity : ToolBarActivity() {
override fun inflateMenu(res: Int) { override fun inflateMenu(res: Int) {
super.inflateMenu(res) super.inflateMenu(res)
if (!getBoolean(Constants.SP_TEENAGER_MODE) && showDownloadMenu()) { if (showDownloadMenu()) {
createDownloadMenu(res) createDownloadMenu(res)
} }
} }
@ -60,7 +58,6 @@ abstract class DownloadToolbarActivity : ToolBarActivity() {
} }
val downloadMenuView = mActionMenuView.menu.findItem(R.id.menu_download).actionView val downloadMenuView = mActionMenuView.menu.findItem(R.id.menu_download).actionView
mDownloadCountHint = downloadMenuView?.findViewById(R.id.menu_download_count_hint) mDownloadCountHint = downloadMenuView?.findViewById(R.id.menu_download_count_hint)
mDownloadCountHint?.typeface = Typeface.createFromAsset(assets, Constants.DIN_FONT_PATH)
} }
override fun onMenuItemClick(item: MenuItem?): Boolean { override fun onMenuItemClick(item: MenuItem?): Boolean {
@ -77,27 +74,19 @@ abstract class DownloadToolbarActivity : ToolBarActivity() {
if (mDownloadCountHint == null) return if (mDownloadCountHint == null) return
val count = DownloadManager.getInstance().getDownloadOrUpdateCount(updateList) val count = DownloadManager.getInstance().getDownloadOrUpdateCount(updateList)
if (count != null) { if (count != null) {
mDownloadCountHint?.visibility = View.VISIBLE mDownloadCountHint!!.visibility = View.VISIBLE
mDownloadCountHint?.text = count mDownloadCountHint!!.text = count
val params = mDownloadCountHint?.layoutParams val params = mDownloadCountHint!!.layoutParams
params?.width = if (count.isEmpty()) 6F.dip2px() else ConstraintLayout.LayoutParams.WRAP_CONTENT if (TextUtils.isEmpty(count)) {
params?.height = if (count.isEmpty()) 6F.dip2px() else 14F.dip2px() params.width = DisplayUtils.dip2px(6f)
(params as? ViewGroup.MarginLayoutParams)?.setMargins( params.height = DisplayUtils.dip2px(6f)
0, } else {
if (count.isEmpty()) 0 else (-4F).dip2px(), params.width = DisplayUtils.dip2px(12f)
if (count.isEmpty()) (-4F).dip2px() else (-8F).dip2px(), params.height = DisplayUtils.dip2px(12f)
0 }
) mDownloadCountHint!!.layoutParams = params
mDownloadCountHint?.setPadding(
if (count.isEmpty()) 0 else 4F.dip2px(),
0,
if (count.isEmpty()) 0 else 4F.dip2px(),
0
)
mDownloadCountHint?.minWidth = if (count.isEmpty()) 0 else 14F.dip2px()
mDownloadCountHint?.layoutParams = params
} else { } else {
mDownloadCountHint?.visibility = View.GONE mDownloadCountHint!!.visibility = View.GONE
} }
} }

View File

@ -4,30 +4,16 @@ import android.app.Activity
import android.app.Application import android.app.Application
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.alibaba.android.arouter.launcher.ARouter
import com.gh.ad.AdDelegateHelper
import com.gh.common.util.FloatingBackViewManager import com.gh.common.util.FloatingBackViewManager
import com.gh.common.xapk.XapkInstaller
import com.gh.download.DownloadManager import com.gh.download.DownloadManager
import com.gh.gamecenter.SingletonWebActivity import com.gh.gamecenter.SingletonWebActivity
import com.gh.gamecenter.SkipActivity
import com.gh.gamecenter.SplashAdActivity
import com.gh.gamecenter.SplashScreenActivity import com.gh.gamecenter.SplashScreenActivity
import com.gh.gamecenter.authorization.AuthorizationActivity
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.provider.IHelpAndFeedbackProvider
import com.gh.gamecenter.common.utils.PackageFlavorHelper import com.gh.gamecenter.common.utils.PackageFlavorHelper
import com.gh.gamecenter.core.provider.IPushProvider
import com.gh.gamecenter.login.view.LoginActivity
import com.gh.gamecenter.va.VCore
import com.gh.gamecenter.login.utils.QuickLoginHelper
import com.gh.vspace.VHelper import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp import com.halo.assistant.HaloApp
// TODO移动到对应的模块 // TODO移动到对应的模块
class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks { class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
private var isFromBackgroundToForeground = false // 是否后台回到前台
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
// do nothing // do nothing
@ -35,37 +21,16 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
override fun onActivityStarted(activity: Activity) { override fun onActivityStarted(activity: Activity) {
GlobalActivityManager.currentActivity = activity GlobalActivityManager.currentActivity = activity
GlobalActivityManager.activityCount ++
if (GlobalActivityManager.activityCount == 1 && isFromBackgroundToForeground) {
if (AdDelegateHelper.shouldShowStartUpAd(true)
&& !HaloApp.getInstance().isDisableSplashAdTemporarily
&& activity !is SplashScreenActivity
&& activity !is SkipActivity
&& activity !is AuthorizationActivity
&& activity !is SplashAdActivity
&& !isSuggestionActivity(activity)
) {
activity.startActivity(SplashAdActivity.getIntent(activity))
}
isFromBackgroundToForeground = false
}
if (GlobalActivityManager.activityCount == 1) {
// 清除桌面角标
if (activity !is SplashScreenActivity && activity !is AuthorizationActivity) {
val pushProvider = ARouter.getInstance().build(RouteConsts.provider.push).navigation() as? IPushProvider
pushProvider?.cleanBadgeNumber(activity.applicationContext)
}
}
if (QuickLoginHelper.isLoginAuthPage(activity)) {
QuickLoginHelper.addCustomViewToLoginAuthPage(activity)
}
} }
override fun onActivityResumed(activity: Activity) { override fun onActivityResumed(activity: Activity) {
// 判断是否需要显示或隐藏返回小浮窗 // 判断是否需要显示或隐藏返回小浮窗
if (FloatingBackViewManager.getType().isNotEmpty()) { if (FloatingBackViewManager.getType().isNotEmpty()) {
if (activity is SingletonWebActivity if ((activity::class.java.name == "EnergyCenterActivity")
&& FloatingBackViewManager.getType() == FloatingBackViewManager.TYPE_TASK
) {
FloatingBackViewManager.disableBackView()
} else if (activity is SingletonWebActivity
&& FloatingBackViewManager.getType() == FloatingBackViewManager.TYPE_ACTIVITY && FloatingBackViewManager.getType() == FloatingBackViewManager.TYPE_ACTIVITY
) { ) {
FloatingBackViewManager.disableBackView() FloatingBackViewManager.disableBackView()
@ -90,17 +55,9 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
DarkModeSwitchHelper.showDarkModeSwitchFloatingView(activity) DarkModeSwitchHelper.showDarkModeSwitchFloatingView(activity)
} }
if (activity is AppCompatActivity if (activity is AppCompatActivity && activity !is SplashScreenActivity) {
&& !VCore.getInstance().isLaunchActivity(activity)
&& activity !is LoginActivity
&& activity !is SplashScreenActivity
&& activity !is SkipActivity
&& activity !is AuthorizationActivity
) {
VHelper.showFeedbackDialogIfLastSuccessfulLaunchedGameExitUnexpectedly(activity) VHelper.showFeedbackDialogIfLastSuccessfulLaunchedGameExitUnexpectedly(activity)
} }
XapkInstaller.updateCurrentInstallStatus()
} }
override fun onActivityPaused(activity: Activity) { override fun onActivityPaused(activity: Activity) {
@ -111,8 +68,7 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
} }
override fun onActivityStopped(activity: Activity) { override fun onActivityStopped(activity: Activity) {
GlobalActivityManager.activityCount -- // do nothing
isFromBackgroundToForeground = GlobalActivityManager.activityCount <= 0
} }
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
@ -120,16 +76,7 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
} }
override fun onActivityDestroyed(activity: Activity) { override fun onActivityDestroyed(activity: Activity) {
if (QuickLoginHelper.isLoginAuthPage(activity)) { // do nothing
QuickLoginHelper.release()
}
}
private fun isSuggestionActivity(activity: Activity): Boolean {
val helpAndFeedbackProvider =
ARouter.getInstance().build(RouteConsts.provider.helpAndFeedback)
.navigation() as? IHelpAndFeedbackProvider
return helpAndFeedbackProvider?.isSuggestionActivity(activity) ?: false
} }
} }

View File

@ -0,0 +1,14 @@
package com.gh.base
import android.app.Activity
import java.lang.ref.WeakReference
object GlobalActivityManager {
private var mCurrentActivityWeakRef: WeakReference<Activity>? = null
var currentActivity: Activity?
get() = mCurrentActivityWeakRef?.get()
set(activity) {
mCurrentActivityWeakRef = WeakReference<Activity>(activity)
}
}

View File

@ -12,7 +12,6 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import com.alibaba.android.arouter.launcher.ARouter import com.alibaba.android.arouter.launcher.ARouter
import com.gh.common.exposure.ExposureManager
import com.gh.common.util.* import com.gh.common.util.*
import com.gh.common.util.LogUtils import com.gh.common.util.LogUtils
import com.gh.download.DownloadManager import com.gh.download.DownloadManager
@ -24,27 +23,19 @@ import com.gh.gamecenter.common.callback.BiCallback
import com.gh.gamecenter.common.constant.Constants import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.RouteConsts import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.entity.NotificationUgc import com.gh.gamecenter.common.entity.NotificationUgc
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.loghub.LoghubUtils import com.gh.gamecenter.common.loghub.LoghubUtils
import com.gh.gamecenter.common.provider.IHelpAndFeedbackProvider import com.gh.gamecenter.common.provider.IHelpAndFeedbackProvider
import com.gh.gamecenter.common.tracker.Tracker import com.gh.gamecenter.common.tracker.Tracker
import com.gh.gamecenter.common.utils.* import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.NewFlatLogUtils
import com.gh.gamecenter.common.view.dsbridge.CompletionHandler import com.gh.gamecenter.common.view.dsbridge.CompletionHandler
import com.gh.gamecenter.core.AppExecutor import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.provider.IPushProvider
import com.gh.gamecenter.core.runOnIoThread import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.runOnUiThread import com.gh.gamecenter.core.runOnUiThread
import com.gh.gamecenter.core.utils.CurrentActivityHolder import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.core.utils.DisplayUtils import com.gh.gamecenter.energy.EnergyBridge
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.entity.SensorsEvent
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.eventbus.EBPackage import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.entity.Badge import com.gh.gamecenter.feature.entity.Badge
import com.gh.gamecenter.feature.entity.GameEntity import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.login.user.LoginTag import com.gh.gamecenter.login.user.LoginTag
import com.gh.gamecenter.login.user.UserManager import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.login.user.UserRepository import com.gh.gamecenter.login.user.UserRepository
@ -59,46 +50,25 @@ import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus.* import com.lightgame.download.DownloadStatus.*
import com.lightgame.utils.Utils import com.lightgame.utils.Utils
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.json.JSONObject import org.json.JSONObject
import java.io.BufferedOutputStream import java.io.BufferedOutputStream
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.util.* import java.util.*
class DefaultJsApi( class DefaultJsApi(var context: Context, val entrance: String = "", private var mFragment: Fragment? = null) {
var context: Context,
val entrance: String = "",
private var mFragment: Fragment? = null,
private var mBbsId: String? = "",
private var mOriginUrl: String? = "",
private val mForumName: String? = "",
) {
companion object {
private const val SOURCE_ENTRANCE = "webView"
}
private var mLoginHandler: CompletionHandler<Any>? = null private var mLoginHandler: CompletionHandler<Any>? = null
private var mDownloadWatcher: DataWatcher? = null // 下载观察者 private var mDownloadWatcher: DataWatcher? = null
private var mDownloadUrlSet: HashSet<String>? = null // 下载的 url 集合 private var mDownloadUrlSet: HashSet<String>? = null
private var mDownloadHandler: CompletionHandler<Any>? = null // 下载信息回调 private var mDownloadHandler: CompletionHandler<Any>? = null
private var mExposureEvent: ExposureEvent? = null // 活动曝光实体
init { init {
if (mFragment != null) { if (mFragment != null) {
EventBus.getDefault().register(this)
autoUnregisterDownloadObserverIfNeeded(mFragment) autoUnregisterDownloadObserverIfNeeded(mFragment)
} }
} }
@JavascriptInterface
fun isEnableForceDark(msg: Any): Boolean {
return DarkModeUtils.isWebViewForceDarkEnabled
}
@JavascriptInterface @JavascriptInterface
fun isGhzs(msg: Any): String { fun isGhzs(msg: Any): String {
return "true" return "true"
@ -114,19 +84,6 @@ class DefaultJsApi(
// do nothing, mta is deprecated // do nothing, mta is deprecated
} }
@JavascriptInterface
fun logSensorsEvent(event: Any) {
val sensorsEvent = event.toString().toObject() ?: SensorsEvent()
val trackEvent = JSONObject()
tryCatchInRelease {
sensorsEvent.kv.split(",").forEach {
val kv = it.split(":")
trackEvent.put(kv[0], kv[1])
}
}
SensorsBridge.trackEvent(sensorsEvent.name, trackEvent)
}
@JavascriptInterface @JavascriptInterface
fun getUserInfo(msg: Any): String { fun getUserInfo(msg: Any): String {
return UserManager.getInstance().userInfoEntity?.toJson() ?: "" return UserManager.getInstance().userInfoEntity?.toJson() ?: ""
@ -139,7 +96,7 @@ class DefaultJsApi(
@JavascriptInterface @JavascriptInterface
fun login(msg: Any) { fun login(msg: Any) {
if (NetworkUtils.isQuickLoginEnabled(context)) { if (SPUtils.getBoolean(Constants.SP_HAS_GET_PHONE_INFO) || NetworkUtils.isOpenMobileData(context)) {
QuickLoginHelper.startLogin(context, "浏览器") QuickLoginHelper.startLogin(context, "浏览器")
} else { } else {
val intent = LoginActivity.getIntent(context, "浏览器") val intent = LoginActivity.getIntent(context, "浏览器")
@ -189,6 +146,7 @@ class DefaultJsApi(
WechatBindHelper.bindWechat(wechatLoginInfoMap, object : BiCallback<Boolean, Boolean> { WechatBindHelper.bindWechat(wechatLoginInfoMap, object : BiCallback<Boolean, Boolean> {
override fun onFirst(first: Boolean) { override fun onFirst(first: Boolean) {
EnergyBridge.postEnergyTask("bind_wechat")
handler.complete(true) handler.complete(true)
} }
@ -229,11 +187,11 @@ class DefaultJsApi(
runOnUiThread { runOnUiThread {
// 若畅玩列表中安装了,优先启动畅玩游戏 // 若畅玩列表中安装了,优先启动畅玩游戏
if (VHelper.isInstalled(packageName)) { if (VHelper.isInstalled(packageName)) {
VHelper.validateVSpaceBeforeAction(context, packageName, null) { if (!VHelper.showDialogIfVSpaceIsNeeded(context)) {
VHelper.launch(context, packageName) VHelper.launch(context, packageName)
} }
} else { } else {
PackageLauncher.launchApp(context, packageName = packageName) PackageUtils.launchApplicationByPackageName(context, packageName)
} }
} }
} }
@ -244,19 +202,12 @@ class DefaultJsApi(
val context = CurrentActivityHolder.getCurrentActivity() val context = CurrentActivityHolder.getCurrentActivity()
context?.startActivity( context?.startActivity(ImageViewerActivity.getIntent(context, imageEvent.imageList, imageEvent.position, "浏览器"))
ImageViewerActivity.getIntent(
context,
imageEvent.imageList,
imageEvent.position,
"浏览器"
)
)
} }
@JavascriptInterface @JavascriptInterface
fun isInstalled(event: Any): String { fun isInstalled(event: Any): String {
val localInstalledPackageList = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0) val localInstalledPackageList = PackageUtils.getAllPackageName(HaloApp.getInstance().application)
val packageNameList: ArrayList<String> = event.toString().toObject() ?: ArrayList() val packageNameList: ArrayList<String> = event.toString().toObject() ?: ArrayList()
for (packageName in packageNameList) { for (packageName in packageNameList) {
@ -290,31 +241,6 @@ class DefaultJsApi(
} }
} }
/**
* 是否为论坛详情的专区
*/
@JavascriptInterface
fun isForumZone(msg: Any): Boolean {
return !mBbsId.isNullOrEmpty()
}
/**
* 打开论坛搜索页
* 如果用户是从 webView跳转到论坛搜索页则sourceEntrance为空
*/
@JavascriptInterface
fun openForumSearch(msg: Any) {
runOnUiThread {
DirectUtils.directToForumOrUserSearch(
context,
mBbsId ?: "",
entrance.ifBlank { "内部网页" },
SOURCE_ENTRANCE,
mForumName ?: ""
)
}
}
@JavascriptInterface @JavascriptInterface
fun exitWebView(msg: Any) { fun exitWebView(msg: Any) {
runOnUiThread { (context as Activity).finish() } runOnUiThread { (context as Activity).finish() }
@ -323,6 +249,7 @@ class DefaultJsApi(
@JavascriptInterface @JavascriptInterface
fun updateRegulationTestStatus(msg: Any) { fun updateRegulationTestStatus(msg: Any) {
if (msg.toString().toLowerCase(Locale.getDefault()) == "pass") { if (msg.toString().toLowerCase(Locale.getDefault()) == "pass") {
EnergyBridge.postEnergyTask("finish_etiquette_exam")
SPUtils.setString(Constants.SP_REGULATION_TEST_PASS_STATUS, "pass") SPUtils.setString(Constants.SP_REGULATION_TEST_PASS_STATUS, "pass")
} }
} }
@ -338,17 +265,6 @@ class DefaultJsApi(
return HaloApp.getInstance().gid return HaloApp.getInstance().gid
} }
@JavascriptInterface
fun getOaid(msg: Any): String {
return HaloApp.getInstance().oaid
}
@JavascriptInterface
fun getPushId(): String {
val pushProvider = ARouter.getInstance().build(RouteConsts.provider.push).navigation() as? IPushProvider
return pushProvider?.getRegistrationId(HaloApp.getInstance()) ?: "unknown"
}
@JavascriptInterface @JavascriptInterface
fun showIncompatibleVersionDialog(msg: Any) { fun showIncompatibleVersionDialog(msg: Any) {
DialogHelper.showUpgradeDialog(context) DialogHelper.showUpgradeDialog(context)
@ -409,22 +325,22 @@ class DefaultJsApi(
@JavascriptInterface @JavascriptInterface
fun postWearBadgeTask(msg: Any) { fun postWearBadgeTask(msg: Any) {
// do nothing EnergyBridge.postEnergyTask("wear_badge")
} }
@JavascriptInterface @JavascriptInterface
fun startEnergyCenter(msg: Any) { fun startEnergyCenter(msg: Any) {
// do nothing context.startActivity(EnergyBridge.getEnergyCenterIntent(context))
} }
@JavascriptInterface @JavascriptInterface
fun startEnergyHouse(msg: Any) { fun startEnergyHouse(msg: Any) {
// do nothing context.startActivity(EnergyBridge.getEnergyHouseIntent(context, null))
} }
@JavascriptInterface @JavascriptInterface
fun showQaFeedbackDialog(msg: Any) { fun showQaFeedbackDialog(msg: Any) {
val mHelpAndFeedbackHelp = val mHelpAndFeedbackHelp =
ARouter.getInstance().build(RouteConsts.provider.helpAndFeedback).navigation() as? IHelpAndFeedbackProvider ARouter.getInstance().build(RouteConsts.provider.helpAndFeedback).navigation() as? IHelpAndFeedbackProvider
mHelpAndFeedbackHelp?.showQaFeedbackDialogFragment(context as AppCompatActivity, msg.toString()) mHelpAndFeedbackHelp?.showQaFeedbackDialogFragment(context as AppCompatActivity, msg.toString())
} }
@ -555,7 +471,7 @@ class DefaultJsApi(
@JavascriptInterface @JavascriptInterface
fun getInstallStatus(event: Any): String { fun getInstallStatus(event: Any): String {
val localInstalledPackageList = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0) val localInstalledPackageList = PackageUtils.getAllPackageName(HaloApp.getInstance().application)
val packageNameList: ArrayList<String> = event.toString().toObject() ?: ArrayList() val packageNameList: ArrayList<String> = event.toString().toObject() ?: ArrayList()
val installStatusMap: HashMap<String, Boolean> = hashMapOf() val installStatusMap: HashMap<String, Boolean> = hashMapOf()
@ -570,24 +486,13 @@ class DefaultJsApi(
@JavascriptInterface @JavascriptInterface
fun installDownloadedGame(event: Any) { fun installDownloadedGame(event: Any) {
val url = event.toString() val url = event.toString()
val vUrl = VHelper.getVUrl(url)
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(url, null) val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(url, null, false)
?: DownloadManager.getInstance().getDownloadEntitySnapshot(url, null) ?: DownloadManager.getInstance().getDownloadEntitySnapshot(vUrl, null, false)
NewFlatLogUtils.logGameInstall(
gameId = downloadEntity?.gameId ?: "",
gameName = downloadEntity?.name ?: "",
trigger = "主动安装"
)
SensorsBridge.trackInstallGameClick(
gameId = downloadEntity?.gameId ?: "",
gameName = downloadEntity?.name ?: "",
action = "主动安装"
)
downloadEntity?.let { downloadEntity?.let {
PackageInstaller.install(context, it, showUnzipToast = false, ignoreAsVGame = false) PackageInstaller.install(context, it, showUnzipToast = false)
} }
} }
@ -680,33 +585,6 @@ class DefaultJsApi(
} }
} }
@JavascriptInterface
fun logExposure(event: Any) {
val simpleExposureEvent = event.toString().toObject() ?: SimpleExposureEvent()
if (simpleExposureEvent.id.isNotEmpty()) {
val sourceKey = if (mOriginUrl?.contains(Constants.URL_QUERY_FROM_FLOATING_WINDOW) == true) {
"落地页"
} else {
"游戏活动"
}
val exposureSource = ExposureSource(sourceKey, "${simpleExposureEvent.title}+${simpleExposureEvent.id}")
mExposureEvent = ExposureEvent.createEvent(
gameEntity = null,
source = arrayListOf(exposureSource),
)
ExposureManager.log(mExposureEvent!!)
ExposureManager.commitSavedExposureEvents(true)
}
}
/**
* 获取 ExposureEvent可能为空
*/
fun getExposureEvent(): ExposureEvent? {
return mExposureEvent
}
private fun autoUnregisterDownloadObserverIfNeeded(fragment: Fragment?) { private fun autoUnregisterDownloadObserverIfNeeded(fragment: Fragment?) {
fragment?.parentFragmentManager?.registerFragmentLifecycleCallbacks( fragment?.parentFragmentManager?.registerFragmentLifecycleCallbacks(
object : FragmentManager.FragmentLifecycleCallbacks() { object : FragmentManager.FragmentLifecycleCallbacks() {
@ -718,8 +596,6 @@ class DefaultJsApi(
if (mDownloadWatcher != null) { if (mDownloadWatcher != null) {
DownloadManager.getInstance().removeObserver(mDownloadWatcher) DownloadManager.getInstance().removeObserver(mDownloadWatcher)
} }
EventBus.getDefault().unregister(this@DefaultJsApi)
} }
} }
@ -742,14 +618,6 @@ class DefaultJsApi(
) )
} }
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(status: EBDownloadStatus) {
// 将下载任务删除事件回调给网页
if (mDownloadHandler != null && "delete" == status.status) {
mDownloadHandler?.setProgressData(SimpleDownloadEntity(status.url, 0F, "UNKNOWN").toJson())
}
}
@Keep @Keep
internal class ImageEvent(var imageList: ArrayList<String> = arrayListOf(), var position: Int = 0) internal class ImageEvent(var imageList: ArrayList<String> = arrayListOf(), var position: Int = 0)
@ -759,9 +627,6 @@ class DefaultJsApi(
@Keep @Keep
internal class TextShareEvent(var text: String = "", var type: String = "") internal class TextShareEvent(var text: String = "", var type: String = "")
@Keep
internal class SimpleExposureEvent(var title: String = "", var id: String = "")
@Keep @Keep
internal class InviteFriendsEvent( internal class InviteFriendsEvent(
var type: String = "", var type: String = "",
@ -788,7 +653,6 @@ class DefaultJsApi(
var status: String = "" // DOWNLOADING, PAUSED, DOWNLOADED, ERROR, UNKNOWN var status: String = "" // DOWNLOADING, PAUSED, DOWNLOADED, ERROR, UNKNOWN
) { ) {
companion object { companion object {
fun fromDownloadEntity(downloadEntity: DownloadEntity): SimpleDownloadEntity { fun fromDownloadEntity(downloadEntity: DownloadEntity): SimpleDownloadEntity {
val status: String = when (downloadEntity.status) { val status: String = when (downloadEntity.status) {
add, add,

View File

@ -5,8 +5,9 @@ import android.content.Intent
import android.net.Uri import android.net.Uri
import android.text.TextUtils import android.text.TextUtils
import android.util.Base64 import android.util.Base64
import com.gh.common.util.CheckLoginUtils import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.common.util.DirectUtils import com.gh.gamecenter.common.constant.Constants
import com.gh.common.util.*
import com.gh.common.util.DirectUtils.directToFeedback import com.gh.common.util.DirectUtils.directToFeedback
import com.gh.common.util.DirectUtils.directToGameDetailVideoStreaming import com.gh.common.util.DirectUtils.directToGameDetailVideoStreaming
import com.gh.common.util.DirectUtils.directToGameServerCalendar import com.gh.common.util.DirectUtils.directToGameServerCalendar
@ -14,29 +15,23 @@ import com.gh.common.util.DirectUtils.directToGameVideo
import com.gh.common.util.DirectUtils.directToLegacyVideoDetail import com.gh.common.util.DirectUtils.directToLegacyVideoDetail
import com.gh.common.util.DirectUtils.directToLinkPage import com.gh.common.util.DirectUtils.directToLinkPage
import com.gh.common.util.DirectUtils.directToQa import com.gh.common.util.DirectUtils.directToQa
import com.gh.common.util.PackageUtils import com.gh.gamecenter.*
import com.gh.gamecenter.WebActivity import com.gh.gamecenter.core.utils.GsonUtils.gson
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.entity.CommunityEntity import com.gh.gamecenter.common.entity.CommunityEntity
import com.gh.gamecenter.common.entity.LinkEntity import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.entity.SimpleGameEntity
import com.gh.gamecenter.common.eventbus.EBReuse import com.gh.gamecenter.common.eventbus.EBReuse
import com.gh.gamecenter.common.entity.SimpleGameEntity
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.common.utils.DialogHelper import com.gh.gamecenter.common.utils.DialogHelper
import com.gh.gamecenter.common.utils.EnvHelper import com.gh.gamecenter.common.utils.EnvHelper
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.core.utils.GsonUtils.gson
import com.gh.gamecenter.core.utils.ToastUtils import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.entity.ActivityLabelEntity import com.gh.gamecenter.entity.*
import com.gh.gamecenter.entity.SubjectRecommendEntity import com.gh.gamecenter.eventbus.EBSkip
import com.gh.gamecenter.entity.VideoLinkEntity import com.gh.gamecenter.fragment.MainWrapperFragment
import com.gh.gamecenter.feature.entity.GameEntity import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.utils.PlatformUtils import com.gh.gamecenter.feature.utils.PlatformUtils
import com.gh.gamecenter.gamecollection.publish.GameCollectionEditActivity import com.gh.gamecenter.gamecollection.publish.GameCollectionEditActivity
import com.gh.gamecenter.libao.LibaoDetailActivity
import com.gh.gamecenter.newsdetail.NewsDetailActivity
import com.gh.gamecenter.qa.BbsType import com.gh.gamecenter.qa.BbsType
import com.gh.gamecenter.qa.video.publish.VideoPublishActivity import com.gh.gamecenter.qa.video.publish.VideoPublishActivity
import com.gh.gamecenter.subject.SubjectActivity import com.gh.gamecenter.subject.SubjectActivity
@ -48,23 +43,15 @@ import java.nio.charset.Charset
object DefaultUrlHandler { object DefaultUrlHandler {
@JvmStatic @JvmStatic
fun interceptUrl(context: Context, url: String, entrance: String, sourceEntrance: String = ""): Boolean { fun interceptUrl(context: Context, url: String, entrance: String): Boolean {
return interceptUrl(context, url, null, entrance, false, sourceEntrance) return interceptUrl(context, url, entrance, false)
} }
/** /**
* 检查并拦截部分内部处理的 url
* @param traceEvent 供一些页面用于登记曝光来源的实体
* @param bringAppToFront 是否需要在不匹配 host 的时候把 APP 调回到前台 (如微信调起) * @param bringAppToFront 是否需要在不匹配 host 的时候把 APP 调回到前台 (如微信调起)
*
* @return 是否已拦截处理
*/ */
@JvmStatic @JvmStatic
fun interceptUrl(context: Context, url: String, fun interceptUrl(context: Context, url: String, entrance: String, bringAppToFront: Boolean = false): Boolean {
traceEvent: ExposureEvent? = null,
entrance: String,
bringAppToFront: Boolean = false,
sourceEntrance: String = ""): Boolean {
val uri = Uri.parse(url) val uri = Uri.parse(url)
if ("ghzhushou" == uri.scheme) { if ("ghzhushou" == uri.scheme) {
Utils.log("url = $url") Utils.log("url = $url")
@ -88,7 +75,6 @@ object DefaultUrlHandler {
id = id, id = id,
tab = uri.getQueryParameter("to"), tab = uri.getQueryParameter("to"),
autoDownload = uri.getQueryParameter("auto_download") == "true", autoDownload = uri.getQueryParameter("auto_download") == "true",
traceEvent = traceEvent,
entrance = entrance entrance = entrance
) )
@ -97,7 +83,6 @@ object DefaultUrlHandler {
id, id,
uri.getQueryParameter("name"), uri.getQueryParameter("name"),
false, false,
null,
entrance entrance
) )
@ -133,7 +118,7 @@ object DefaultUrlHandler {
} }
} }
"question" -> DirectUtils.directToQuestionDetail(context, id, entrance, "文章链接", sourceEntrance) "question" -> DirectUtils.directToQuestionDetail(context, id, entrance, "文章链接")
"real_name" -> DirectUtils.directToRealName(context) "real_name" -> DirectUtils.directToRealName(context)
@ -176,7 +161,7 @@ object DefaultUrlHandler {
if ("articles" == type) { if ("articles" == type) {
DirectUtils.directToCommunityArticle( DirectUtils.directToCommunityArticle(
context, typeId, communityId, context, typeId, communityId,
entrance, "文章链接", sourceEntrance entrance, "文章链接"
) )
} }
} }
@ -244,22 +229,24 @@ object DefaultUrlHandler {
act, act,
paginationType, paginationType,
fieldId, fieldId,
sectionName, sectionName
sourceEntrance = sourceEntrance
) )
} }
EntranceConsts.HOST_VIDEO_DETAIL -> { EntranceConsts.HOST_VIDEO_DETAIL -> {
DirectUtils.directToVideoDetail(context, id, entrance, path, sourceEntrance) DirectUtils.directToVideoDetail(context, id, entrance, path)
} }
EntranceConsts.HOST_VIDEO_SINGLE -> { EntranceConsts.HOST_VIDEO_SINGLE -> {
val referer = uri.getQueryParameter("referer") ?: "" val referer = uri.getQueryParameter("referer") ?: ""
DirectUtils.directToVideoDetail( DirectUtils.directToVideoDetail(
context, id, VideoDetailContainerViewModel.Location.SINGLE_VIDEO.value, context, id, VideoDetailContainerViewModel.Location.SINGLE_VIDEO.value,
false, "", entrance, "", if (TextUtils.isEmpty(referer)) "" else referer, sourceEntrance false, "", entrance, "", if (TextUtils.isEmpty(referer)) "" else referer
) )
} }
EntranceConsts.HOST_VIDEO_STREAMING_HOME -> { EntranceConsts.HOST_VIDEO_STREAMING_HOME -> {
DirectUtils.directToHomeVideoTab(context) intent = Intent(context, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
intent.putExtra(MainActivity.SWITCH_TO_VIDEO, true)
context.startActivity(intent)
} }
EntranceConsts.HOST_VIDEO_STREAMING_DESC -> { EntranceConsts.HOST_VIDEO_STREAMING_DESC -> {
directToGameDetailVideoStreaming(context, id, entrance) directToGameDetailVideoStreaming(context, id, entrance)
@ -268,6 +255,10 @@ object DefaultUrlHandler {
directToGameVideo(context, id, entrance, "") directToGameVideo(context, id, entrance, "")
} }
EntranceConsts.HOST_CATEGORY -> {
val title = uri.getQueryParameter("title")
DirectUtils.directCategoryDirectory(context, id, title ?: "", entrance, "")
}
EntranceConsts.HOST_COLUMN_COLLECTION -> { EntranceConsts.HOST_COLUMN_COLLECTION -> {
val name = uri.getQueryParameter("name") val name = uri.getQueryParameter("name")
DirectUtils.directToColumnCollection(context, id, -1, entrance, name ?: "") DirectUtils.directToColumnCollection(context, id, -1, entrance, name ?: "")
@ -317,7 +308,7 @@ object DefaultUrlHandler {
val linkData = Base64.decode(dataString, Base64.DEFAULT) val linkData = Base64.decode(dataString, Base64.DEFAULT)
val linkDataString = String(linkData, Charset.defaultCharset()) val linkDataString = String(linkData, Charset.defaultCharset())
val le = gson.fromJson(linkDataString, LinkEntity::class.java) val le = gson.fromJson(linkDataString, LinkEntity::class.java)
directToLinkPage(context, le, entrance, sourceEntrance, "") directToLinkPage(context, le, entrance, "")
} }
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
@ -342,8 +333,7 @@ object DefaultUrlHandler {
} }
EntranceConsts.HOST_FORUM_DETAIL -> { EntranceConsts.HOST_FORUM_DETAIL -> {
val sectionId = uri.getQueryParameter("section_id") ?: "" DirectUtils.directForumDetail(context, id, entrance)
DirectUtils.directForumDetailSection(context, id, sectionId, entrance)
} }
EntranceConsts.HOST_GAME_RATING_DETAIL -> { EntranceConsts.HOST_GAME_RATING_DETAIL -> {
@ -356,8 +346,9 @@ object DefaultUrlHandler {
} }
EntranceConsts.HOST_FORUM -> { EntranceConsts.HOST_FORUM -> {
val position = uri.getQueryParameter(EntranceConsts.KEY_POSITION)?.toInt()
DirectUtils.directToHomeCommunityTab(context) DirectUtils.directToForum(context, position ?: 0)
} }
EntranceConsts.HOST_UPLOAD_VIDEO_NEW -> { EntranceConsts.HOST_UPLOAD_VIDEO_NEW -> {
@ -374,7 +365,7 @@ object DefaultUrlHandler {
val iconSubscript = uri.getQueryParameter("game_icon_subscript") ?: "" val iconSubscript = uri.getQueryParameter("game_icon_subscript") ?: ""
val gameEntity = val gameEntity =
if (forumType == BbsType.OFFICIAL_BBS.value && gameId.isNotEmpty() && gameName.isNotEmpty() && icon.isNotEmpty()) { if (forumType == BbsType.OFFICIAL_BBS.value && gameId.isNotEmpty() && gameName.isNotEmpty() && icon.isNotEmpty()) {
GameEntity(_id = gameId, mName = gameName, mIcon = icon, mIconSubscript = iconSubscript) GameEntity(id = gameId, mName = gameName, mIcon = icon, mIconSubscript = iconSubscript)
} else null } else null
val activityLabelEntity = if (activityId.isNotEmpty() && activityName.isNotEmpty()) { val activityLabelEntity = if (activityId.isNotEmpty() && activityName.isNotEmpty()) {
ActivityLabelEntity( ActivityLabelEntity(
@ -410,11 +401,10 @@ object DefaultUrlHandler {
val packageMd5 = uri.getQueryParameter(EntranceConsts.KEY_PACKAGE_MD5) val packageMd5 = uri.getQueryParameter(EntranceConsts.KEY_PACKAGE_MD5)
val isQaFeedback = uri.getQueryParameter(EntranceConsts.KEY_IS_QA_FEEDBACK) == "true" val isQaFeedback = uri.getQueryParameter(EntranceConsts.KEY_IS_QA_FEEDBACK) == "true"
val content = if (TextUtils.isEmpty(gameId) || TextUtils.isEmpty(packageMd5)) String.format( val content = if (TextUtils.isEmpty(gameId) || TextUtils.isEmpty(packageMd5)) String.format(
"%s—V%s—%sV%s", "%s-%s-V%s",
uri.getQueryParameter(EntranceConsts.KEY_GAME_NAME), uri.getQueryParameter(EntranceConsts.KEY_GAME_NAME),
uri.getQueryParameter(EntranceConsts.KEY_VERSION),
if (TextUtils.isEmpty(platformName)) platform else platformName, if (TextUtils.isEmpty(platformName)) platform else platformName,
uri.getQueryParameter(EntranceConsts.KEY_PLATFORM_VERSION), uri.getQueryParameter(EntranceConsts.KEY_VERSION)
) else String.format( ) else String.format(
"%s-%s-V%s\n游戏ID%s\n游戏包MD5%s\n", "%s-%s-V%s\n游戏ID%s\n游戏包MD5%s\n",
uri.getQueryParameter(EntranceConsts.KEY_GAME_NAME), uri.getQueryParameter(EntranceConsts.KEY_GAME_NAME),
@ -430,17 +420,17 @@ object DefaultUrlHandler {
directToFeedback( directToFeedback(
context, context,
content, content,
null,
isQaFeedback, isQaFeedback,
qaContentId, qaContentId,
isPlugin = false,
isSmoothGame = false,
EntranceConsts.ENTRANCE_BROWSER EntranceConsts.ENTRANCE_BROWSER
) )
} }
} }
EntranceConsts.HOST_HELP_AND_FEEDBACK -> { EntranceConsts.HOST_HELP_AND_FEEDBACK -> {
DirectUtils.directToHelpAndFeedback(context) val position = uri.getQueryParameter("position") ?: ""
DirectUtils.directToHelpAndFeedback(context, position.toInt())
} }
EntranceConsts.HOST_HELP_DETAIL -> { EntranceConsts.HOST_HELP_DETAIL -> {
@ -469,7 +459,7 @@ object DefaultUrlHandler {
} }
EntranceConsts.HOST_GAME_COLLECTION_DETAIL -> { EntranceConsts.HOST_GAME_COLLECTION_DETAIL -> {
DirectUtils.directToGameCollectionDetail(context, id, entrance, traceEvent = traceEvent) DirectUtils.directToGameCollectionDetail(context, id, entrance)
} }
EntranceConsts.HOST_GAME_COLLECTION_SQUARE -> { EntranceConsts.HOST_GAME_COLLECTION_SQUARE -> {
@ -481,24 +471,25 @@ object DefaultUrlHandler {
val activityName = uri.getQueryParameter("activity_name") ?: "" val activityName = uri.getQueryParameter("activity_name") ?: ""
val gameId = uri.getQueryParameter("game_id") ?: "" val gameId = uri.getQueryParameter("game_id") ?: ""
context.startActivity( context.startActivity(
GameCollectionEditActivity.getCreateIntent( GameCollectionEditActivity.getIntent(
context, context,
activityId, activityId,
activityName, activityName,
gameId, gameId,
entrance, entrance
"其他"
) )
) )
} }
EntranceConsts.HOST_GAME_LIBRARY -> { EntranceConsts.HOST_GAME_LIBRARY -> {
DirectUtils.directToMainActivity(context) DirectUtils.directToMainActivity(context)
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_GAME))
} }
EntranceConsts.HOST_HOME_GAME_COLLECTION_SQUARE -> { EntranceConsts.HOST_HOME_GAME_COLLECTION_SQUARE -> {
DirectUtils.directToMainActivity(context) DirectUtils.directToMainActivity(context)
DirectUtils.directToHomeDefaultTab(context) EventBus.getDefault()
.post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_HOME))
EventBus.getDefault().post(EBReuse(host)) EventBus.getDefault().post(EBReuse(host))
} }
@ -553,7 +544,7 @@ object DefaultUrlHandler {
} }
// 处理内部页面逻辑 // 处理内部页面逻辑
if (transformNormalScheme(context, url, entrance, sourceEntrance)) { if (transformNormalScheme(context, url, entrance)) {
return true return true
} }
@ -562,14 +553,14 @@ object DefaultUrlHandler {
} }
@JvmStatic @JvmStatic
fun transformNormalScheme(context: Context, url: String, entrance: String, sourceEntrance: String): Boolean { fun transformNormalScheme(context: Context, url: String, entrance: String): Boolean {
val b = transformNewNormalScheme(context, url, entrance, sourceEntrance) val b = transformNewNormalScheme(context, url, entrance)
if (b) return b if (b) return b
return transformOldNormalScheme(context, url, entrance, sourceEntrance) return transformOldNormalScheme(context, url, entrance)
} }
@JvmStatic @JvmStatic
fun transformOldNormalScheme(context: Context, url: String, entrance: String, sourceEntrance: String): Boolean { fun transformOldNormalScheme(context: Context, url: String, entrance: String): Boolean {
val uri = Uri.parse(url) val uri = Uri.parse(url)
if (uri.host == "www.ghzs666.com" if (uri.host == "www.ghzs666.com"
|| uri.host == "www.ghzs.com" || uri.host == "www.ghzs.com"
@ -585,7 +576,6 @@ object DefaultUrlHandler {
DirectUtils.directToGameDetail( DirectUtils.directToGameDetail(
context, context,
gameId, gameId,
"",
entrance, entrance,
autoDownload = false, autoDownload = false,
traceEvent = null traceEvent = null
@ -595,7 +585,7 @@ object DefaultUrlHandler {
val questionId = split("/")[2] val questionId = split("/")[2]
val answerId = uri.getQueryParameter("answer") val answerId = uri.getQueryParameter("answer")
if (answerId.isNullOrEmpty()) { if (answerId.isNullOrEmpty()) {
DirectUtils.directToQuestionDetail(context, questionId, entrance, "", sourceEntrance) DirectUtils.directToQuestionDetail(context, questionId, entrance, "")
} else { } else {
DirectUtils.directToAnswerDetail(context, answerId, entrance, "") DirectUtils.directToAnswerDetail(context, answerId, entrance, "")
} }
@ -625,7 +615,7 @@ object DefaultUrlHandler {
if ("articles" == type || "article" == type) { if ("articles" == type || "article" == type) {
DirectUtils.directToCommunityArticle( DirectUtils.directToCommunityArticle(
context, typeId, communityId, context, typeId, communityId,
entrance, "文章链接", sourceEntrance entrance, "文章链接"
) )
} }
} }
@ -656,7 +646,7 @@ object DefaultUrlHandler {
} }
@JvmStatic @JvmStatic
fun transformNewNormalScheme(context: Context, url: String, entrance: String, sourceEntrance: String): Boolean { fun transformNewNormalScheme(context: Context, url: String, entrance: String): Boolean {
val uri = Uri.parse(url) val uri = Uri.parse(url)
if (uri.host == "www.ghzs666.com" if (uri.host == "www.ghzs666.com"
|| uri.host == "www.ghzs.com" || uri.host == "www.ghzs.com"
@ -674,7 +664,7 @@ object DefaultUrlHandler {
val articleId = splits[2].substring(7) val articleId = splits[2].substring(7)
DirectUtils.directToCommunityArticle( DirectUtils.directToCommunityArticle(
context, articleId, "", context, articleId, "",
entrance, "文章链接", sourceEntrance entrance, "文章链接"
) )
} }
//https://m.ghzs666.com/article/文章ID //https://m.ghzs666.com/article/文章ID
@ -694,7 +684,7 @@ object DefaultUrlHandler {
//https://m.ghzs666.com/bbs/video-视频ID //https://m.ghzs666.com/bbs/video-视频ID
splits.size >= 3 && splits[1] == "bbs" && splits[2].startsWith("video-") -> { splits.size >= 3 && splits[1] == "bbs" && splits[2].startsWith("video-") -> {
val videoId = splits[2].substring(6) val videoId = splits[2].substring(6)
DirectUtils.directToVideoDetail(context, videoId, entrance, sourceEntrance) DirectUtils.directToVideoDetail(context, videoId, entrance)
} }
else -> return false else -> return false
} }

View File

@ -2,29 +2,31 @@ package com.gh.common
import com.gh.common.exposure.ExposureManager import com.gh.common.exposure.ExposureManager
import com.gh.common.filter.RegionSettingHelper import com.gh.common.filter.RegionSettingHelper
import com.gh.common.util.AdHelper
import com.gh.common.videolog.VideoRecordUtils import com.gh.common.videolog.VideoRecordUtils
import com.gh.download.DownloadDataHelper import com.gh.download.DownloadDataHelper
import com.gh.gamecenter.common.loghub.LoghubUtils import com.gh.gamecenter.common.loghub.LoghubUtils
import com.gh.gamecenter.common.retrofit.Response import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.doOnMainProcessOnly
import com.gh.gamecenter.common.utils.tryCatchInRelease import com.gh.gamecenter.common.utils.tryCatchInRelease
import com.gh.gamecenter.core.runOnUiThread import com.gh.gamecenter.core.runOnUiThread
import com.gh.gamecenter.entity.TimeEntity import com.gh.gamecenter.entity.TimeEntity
import com.gh.gamecenter.retrofit.RetrofitManager import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
import kotlin.concurrent.fixedRateTimer import kotlin.concurrent.fixedRateTimer
object FixedRateJobHelper { object FixedRateJobHelper {
private const val CHECKER_PERIOD: Long = 15 * 1000L private const val CHECKER_PERIOD: Long = 15 * 1000L
private const val TIME_PERIOD: Long = 10 * 60 * 1000L private const val TIME_PERIOD: Long = 600 * 1000L
private const val LOGHUB_PERIOD: Long = 2 * 60 * 1000L private const val LOGHUB_PERIOD: Long = 120 * 1000L
private const val EXPOSURE_PERIOD: Long = 1 * 60 * 1000L private const val EXPOSURE_PERIOD: Long = 300 * 1000L
private const val REGION_SETTING_PERIOD: Long = 60 * 1000L private const val REGION_SETTING_PERIOD: Long = 30 * 1000L
private const val VIDEO_RECORD_PERIOD: Long = 60 * 1000L private const val VIDEO_RECORD_PERIOD: Long = 60 * 1000L
private const val DOWNLOAD_HEARTBEAT_PERIOD: Long = 60 * 1000L private const val DOWNLOAD_HEARTBEAT_PERIOD: Long = 60 * 1000L
private const val DOWNLOAD_HEARTBEAT_SHEET_PERIOD: Long = 15 * 1000L private const val DOWNLOAD_HEARTBEAT_SHEET_PERIOD: Long = 15 * 1000L
private const val STARTUP_AD: Long = 30 * 60 * 1000L
private var mExecuteCount: Int = 0 private var mExecuteCount: Int = 0
@ -32,56 +34,64 @@ object FixedRateJobHelper {
@JvmStatic @JvmStatic
fun begin() { fun begin() {
// 时间检查每15秒检查一次 doOnMainProcessOnly {
fixedRateTimer("Global-Fixed-Rate-Timer", initialDelay = 100, period = CHECKER_PERIOD) { fixedRateTimer("Global-Fixed-Rate-Timer", initialDelay = 100, period = CHECKER_PERIOD) {
val elapsedTime = mExecuteCount * CHECKER_PERIOD // 时间校对10分钟一次
// 时间校对10分钟一次 if ((mExecuteCount * CHECKER_PERIOD) % TIME_PERIOD == 0L) {
if (elapsedTime % TIME_PERIOD == 0L) { RetrofitManager.getInstance().api.time
RetrofitManager.getInstance().api.time .subscribeOn(Schedulers.io())
.subscribeOn(Schedulers.io()) .subscribe(object : Response<TimeEntity>() {
.subscribe(object : Response<TimeEntity>() { override fun onResponse(response: TimeEntity?) {
override fun onResponse(response: TimeEntity?) { val serverTime = response?.time
val serverTime = response?.time serverTime?.let {
serverTime?.let { timeDeltaBetweenServerAndClient = it * 1000 - System.currentTimeMillis()
timeDeltaBetweenServerAndClient = it * 1000 - System.currentTimeMillis() }
} }
} })
})
}
// 提交曝光数据
if (elapsedTime % EXPOSURE_PERIOD == 0L) {
ExposureManager.commitSavedExposureEvents(true)
}
// 分片检测下载进度
if (elapsedTime % DOWNLOAD_HEARTBEAT_SHEET_PERIOD == 0L) {
tryCatchInRelease {
val upload = (mExecuteCount * CHECKER_PERIOD) % DOWNLOAD_HEARTBEAT_PERIOD == 0L
DownloadDataHelper.uploadDownloadHeartbeat(upload)
} }
}
// 提交普通 loghub 数据 // 提交曝光数据
if (elapsedTime % LOGHUB_PERIOD == 0L) { if ((mExecuteCount * CHECKER_PERIOD) % EXPOSURE_PERIOD == 0L) {
runOnUiThread { runOnUiThread {
LoghubUtils.commitSavedLoghubEvents(true) ExposureManager.commitSavedExposureEvents(true)
}
} }
}
// 更新游戏屏蔽信息 // 分片检测下载进度
if (elapsedTime % REGION_SETTING_PERIOD == 0L) { if ((mExecuteCount * CHECKER_PERIOD) % DOWNLOAD_HEARTBEAT_SHEET_PERIOD == 0L) {
if (HaloApp.getInstance().isRunningForeground) { tryCatchInRelease {
RegionSettingHelper.getRegionSetting() val upload = (mExecuteCount * CHECKER_PERIOD) % DOWNLOAD_HEARTBEAT_PERIOD == 0L
DownloadDataHelper.uploadDownloadHeartbeat(upload)
}
} }
}
// 提交视频浏览记录数据 // 提交普通 loghub 数据
if (elapsedTime % VIDEO_RECORD_PERIOD == 0L) { if ((mExecuteCount * CHECKER_PERIOD) % LOGHUB_PERIOD == 0L) {
VideoRecordUtils.commitVideoRecord() runOnUiThread {
} LoghubUtils.commitSavedLoghubEvents(true)
}
}
mExecuteCount++ // 更新游戏屏蔽信息
if ((mExecuteCount * CHECKER_PERIOD) % REGION_SETTING_PERIOD == 0L) {
if (HaloApp.getInstance().isRunningForeground) {
RegionSettingHelper.getRegionSetting()
}
}
// 提交视频浏览记录数据
if ((mExecuteCount * CHECKER_PERIOD) % VIDEO_RECORD_PERIOD == 0L) {
VideoRecordUtils.commitVideoRecord()
}
// 获取启动广告
if ((mExecuteCount * CHECKER_PERIOD) % STARTUP_AD == 0L) {
AdHelper.getSettingAdCache()
}
// ExposureUtils.logADownloadCompleteExposureEvent(GameEntity(id = mExecuteCount.toString(), name = "测试曝光上传"), platform = "", trace = null, downloadType = ExposureUtils.DownloadType.DOWNLOAD)
mExecuteCount++
}
} }
} }
} }

View File

@ -1,351 +0,0 @@
package com.gh.common.browse
import android.os.Handler
import android.os.Looper
import android.os.Message
import androidx.lifecycle.*
import androidx.lifecycle.Lifecycle.Event
/**
* 浏览时长计时器核心接口类,用于页面浏览时长相关埋点上报
*/
interface IBrowseTimerCore {
/**
* 开始计时
*/
fun start()
/**
* 结束计时
*/
fun stop()
}
/**
* 浏览时长计时器核心实现类
*/
class BrowseTimerCore internal constructor() : IBrowseTimerCore {
/**
* 延迟执行的时间
*/
var delayInMills: Long = 3000L
/**
* 开始计时函数回调
*/
var onStart: (() -> Unit)? = null
/**
* 结束计时函数回调
*/
var onResult: ((Long) -> Unit)? = null
/**
* 开始计时的时间点
*/
private var startTimeInMills: Long = 0L
/**
* Handler操作类
*/
private val handler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
if (msg.what == MESSAGE_START) {
dispatchOnStart()
}
}
}
/**
* 延迟执行开始计时
* @see delayInMills
* @see onStart
*/
override fun start() {
if (delayInMills <= 0) {
dispatchOnStart()
} else {
handler.sendEmptyMessageDelayed(MESSAGE_START, delayInMills)
}
}
/**
* 结束计时,统计浏览时长并回调结束计时函数
* @see onResult
*/
override fun stop() {
handler.removeMessages(MESSAGE_START)
if (startTimeInMills > 0L) {
onResult?.invoke(System.currentTimeMillis() - startTimeInMills)
startTimeInMills = 0L
}
}
/**
* 开始计时,回调开始计时函数
*/
private fun dispatchOnStart() {
startTimeInMills = System.currentTimeMillis()
onStart?.invoke()
}
companion object {
private const val MESSAGE_START = 1
}
}
/**
* 无数据浏览计时器接口类
*/
interface IBrowseTimer : IBrowseTimerCore {
fun withDelayInMills(delayInMills: Long): IBrowseTimer
fun withStart(onStart: () -> Unit): IBrowseTimer
fun withResult(onResult: (Long) -> Unit): IBrowseTimer
}
/**
* 无数据的浏览计时器实现类
*/
class BrowseTimer : IBrowseTimer {
private val core = BrowseTimerCore()
private var isStarted: Boolean = false
override fun withDelayInMills(delayInMills: Long): IBrowseTimer {
core.delayInMills = delayInMills
return this
}
override fun withStart(onStart: () -> Unit): IBrowseTimer {
core.onStart = onStart
return this
}
override fun withResult(onResult: (Long) -> Unit): IBrowseTimer {
core.onResult = onResult
return this
}
override fun start() {
if (isStarted) return
isStarted = true
core.start()
}
override fun stop() {
if (!isStarted) return
core.stop()
isStarted = false
}
}
/**
* 支持Lifecycle的无数据的浏览计时器
*/
class LifecycleBoundBrowseTimer internal constructor(
private val base: IBrowseTimer,
private val onStateChanged: (IBrowseTimer, Event) -> Unit
) : IBrowseTimer, LifecycleEventObserver {
override fun withDelayInMills(delayInMills: Long): IBrowseTimer {
return base.withDelayInMills(delayInMills)
}
override fun withStart(onStart: () -> Unit): IBrowseTimer {
return base.withStart(onStart)
}
override fun withResult(onResult: (Long) -> Unit): IBrowseTimer {
return base.withResult(onResult)
}
override fun start() {
base.start()
}
override fun stop() {
base.stop()
}
override fun onStateChanged(source: LifecycleOwner, event: Event) {
onStateChanged.invoke(this, event)
}
}
fun IBrowseTimer.withLifecycle(
owner: LifecycleOwner,
onStateChanged: (IBrowseTimer, Event) -> Unit = { timer, event ->
when(event) {
Event.ON_START -> timer.start()
Event.ON_STOP -> timer.stop()
else -> {}
}
}
): LifecycleBoundBrowseTimer = LifecycleBoundBrowseTimer(this, onStateChanged).apply {
owner.lifecycle.addObserver(this)
}
/**
* 带数据的浏览计时器接口类
*/
interface IValueBrowseTimer<T> : IBrowseTimerCore {
fun withDelayInMills(delayInMills: Long): IValueBrowseTimer<T>
fun withStart(onStart: (T?) -> Unit): IValueBrowseTimer<T>
fun withResult(onResult: (T?, Long) -> Unit): IValueBrowseTimer<T>
fun dispatchValue(value: T?)
}
/**
* 带数据的浏览计时器实现类
*/
class ValueBrowseTimer<T> : IValueBrowseTimer<T> {
private val core = BrowseTimerCore()
private var isDispatchValue: Boolean = false
private var isStarted: Boolean = false
private var value: T? = null
override fun withDelayInMills(delayInMills: Long): IValueBrowseTimer<T> {
core.delayInMills = delayInMills
return this
}
override fun withStart(onStart: (T?) -> Unit): IValueBrowseTimer<T> {
core.onStart = { onStart.invoke(value) }
return this
}
override fun withResult(onResult: (T?, Long) -> Unit): IValueBrowseTimer<T> {
core.onResult = { onResult.invoke(value, it) }
return this
}
override fun start() {
if (isStarted) return
isStarted = true
if (isDispatchValue) {
core.start()
}
}
override fun stop() {
if (!isStarted) return
core.stop()
isStarted = false
}
override fun dispatchValue(value: T?) {
this.value = value
if (isStarted && !isDispatchValue) {
core.start()
}
isDispatchValue = true
}
}
/**
* 支持LiveData的带数据的浏览计时器
*/
class ObserverBoundValueBrowseTimer<T> internal constructor(private val base: IValueBrowseTimer<T>) : IValueBrowseTimer<T>, Observer<T> {
override fun withDelayInMills(delayInMills: Long): IValueBrowseTimer<T> {
return base.withDelayInMills(delayInMills)
}
override fun withResult(onResult: (T?, Long) -> Unit): IValueBrowseTimer<T> {
return base.withResult(onResult)
}
override fun withStart(onStart: (T?) -> Unit): IValueBrowseTimer<T> {
return base.withStart(onStart)
}
override fun start() {
base.start()
}
override fun stop() {
base.stop()
}
override fun dispatchValue(value: T?) {
base.dispatchValue(value)
}
override fun onChanged(t: T) {
dispatchValue(t)
}
}
/**
* 支持Lifecycle的带数据的浏览计时器
*/
class LifecycleBoundValueBrowseTimer<T> internal constructor(
private val base: IValueBrowseTimer<T>,
private val onStateChanged: (IValueBrowseTimer<T>, Event) -> Unit
) : IValueBrowseTimer<T>, LifecycleEventObserver {
override fun withDelayInMills(delayInMills: Long): IValueBrowseTimer<T> {
return base.withDelayInMills(delayInMills)
}
override fun withResult(onResult: (T?, Long) -> Unit): IValueBrowseTimer<T> {
return base.withResult(onResult)
}
override fun withStart(onStart: (T?) -> Unit): IValueBrowseTimer<T> {
return base.withStart(onStart)
}
override fun start() {
base.start()
}
override fun stop() {
base.stop()
}
override fun dispatchValue(value: T?) {
base.dispatchValue(value)
}
override fun onStateChanged(source: LifecycleOwner, event: Event) {
onStateChanged.invoke(this, event)
}
}
fun <T> IValueBrowseTimer<T>.asObserver(): ObserverBoundValueBrowseTimer<T> = ObserverBoundValueBrowseTimer(this)
fun <T> IValueBrowseTimer<T>.withLifecycle(
owner: LifecycleOwner,
onStateChanged: (IValueBrowseTimer<T>, Event) -> Unit = { timer, event ->
when(event) {
Event.ON_START -> timer.start()
Event.ON_STOP -> timer.stop()
else -> {}
}
}
): LifecycleBoundValueBrowseTimer<T> = LifecycleBoundValueBrowseTimer(this, onStateChanged).apply {
owner.lifecycle.addObserver(this)
}

View File

@ -2,21 +2,20 @@ package com.gh.common.chain
import android.content.Context import android.content.Context
import com.gh.download.server.BrowserInstallHelper import com.gh.download.server.BrowserInstallHelper
import com.gh.gamecenter.core.utils.EmptyCallback
import com.gh.gamecenter.feature.entity.GameEntity import com.gh.gamecenter.feature.entity.GameEntity
class BrowserInstallHandler : DownloadChainHandler() { class BrowserInstallHandler : ChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) { override fun handleRequest(context: Context, gameEntity: GameEntity) {
BrowserInstallHelper.showBrowserInstallHintDialog( BrowserInstallHelper.showBrowserInstallHintDialog(context, gameEntity.isVGame(), object : EmptyCallback {
context, override fun onCallback() {
gameEntity, if (hasNext()) {
asVGame || gameEntity.isSplitXApk() getNext()?.handleRequest(context, gameEntity)
) { } else {
if (hasNext()) { processEndCallback?.invoke(null)
getNext()?.handleRequest(context, gameEntity, asVGame) }
} else {
processEndCallback?.invoke(asVGame, null)
} }
} })
} }
} }

View File

@ -0,0 +1,18 @@
package com.gh.common.chain
import android.content.Context
import com.gh.common.dialog.CertificationDialog
import com.gh.gamecenter.feature.entity.GameEntity
class CertificationHandler : ChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity) {
CertificationDialog.showCertificationDialog(context, gameEntity) {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
} else {
processEndCallback?.invoke(null)
}
}
}
}

View File

@ -0,0 +1,28 @@
package com.gh.common.chain
class ChainBuilder {
private val handlers: MutableList<ChainHandler> = ArrayList()
private var processEndCallback: ((Any?) -> Unit)? = null
fun setProcessEndCallback(callback: (Any?) -> Unit): ChainBuilder {
processEndCallback = callback
return this
}
fun addHandler(handler: ChainHandler): ChainBuilder {
handlers.add(handler)
return this
}
fun buildHandlerChain(): ChainHandler? {
for (i in handlers.indices) {
handlers[i].processEndCallback = processEndCallback
if (i + 1 < handlers.size) {
handlers[i].setNext(handlers[i + 1])
}
}
return if (handlers.isEmpty()) null else handlers[0]
}
}

View File

@ -0,0 +1,24 @@
package com.gh.common.chain
import android.content.Context
import com.gh.gamecenter.feature.entity.GameEntity
abstract class ChainHandler {
private var next: ChainHandler? = null
var processEndCallback: ((Any?) -> Unit)? = null
fun setNext(next: ChainHandler?) {
this.next = next
}
fun getNext(): ChainHandler? {
return next
}
fun hasNext(): Boolean {
return next != null
}
abstract fun handleRequest(context: Context, gameEntity: GameEntity)
}

View File

@ -5,15 +5,15 @@ import com.gh.common.util.DialogUtils
import com.gh.gamecenter.common.utils.safelyGetInRelease import com.gh.gamecenter.common.utils.safelyGetInRelease
import com.gh.gamecenter.feature.entity.GameEntity import com.gh.gamecenter.feature.entity.GameEntity
class CheckDownloadHandler : DownloadChainHandler() { class CheckDownloadHandler : ChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) { override fun handleRequest(context: Context, gameEntity: GameEntity) {
val apk = gameEntity.getApk().safelyGetInRelease(0) ?: return val apk = gameEntity.getApk().safelyGetInRelease(0) ?: return
DialogUtils.checkDownload(context, apk.size, gameEntity.id, gameEntity.name, gameEntity.categoryChinese) { isSubscribe: Boolean -> DialogUtils.checkDownload(context, apk.size) { isSubscribe: Boolean ->
if (hasNext()) { if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame) getNext()?.handleRequest(context, gameEntity)
} else { } else {
processEndCallback?.invoke(asVGame, isSubscribe) processEndCallback?.invoke(isSubscribe)
} }
} }

View File

@ -2,23 +2,20 @@ package com.gh.common.chain
import android.content.Context import android.content.Context
import com.gh.gamecenter.common.utils.PermissionHelper import com.gh.gamecenter.common.utils.PermissionHelper
import com.gh.gamecenter.core.utils.EmptyCallback
import com.gh.gamecenter.feature.entity.GameEntity import com.gh.gamecenter.feature.entity.GameEntity
class CheckStoragePermissionHandler : DownloadChainHandler() { class CheckStoragePermissionHandler : ChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) { override fun handleRequest(context: Context, gameEntity: GameEntity) {
PermissionHelper.checkStoragePermissionBeforeAction( PermissionHelper.checkStoragePermissionBeforeAction(context, object : EmptyCallback {
context, override fun onCallback() {
gameEntity.id, if (hasNext()) {
gameEntity.name ?: "", getNext()?.handleRequest(context, gameEntity)
gameEntity.categoryChinese, } else {
gameEntity.getApk().firstOrNull()?.format, processEndCallback?.invoke(null)
) { }
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(asVGame, null)
} }
} })
} }
} }

View File

@ -1,28 +0,0 @@
package com.gh.common.chain
class DownloadChainBuilder {
private val handlers: MutableList<DownloadChainHandler> = ArrayList()
private var processEndCallback: ((asVGame: Boolean, Any?) -> Unit)? = null
fun setProcessEndCallback(gameId: String, callback: (asVGame: Boolean, Any?) -> Unit): DownloadChainBuilder {
processEndCallback = VaPluginDownloadWrapper(gameId = gameId, callback = callback) // 其他需要添加行为的装饰者可以一直包装A(B(C(callback))), 执行顺序 A->B->C->callback
return this
}
fun addHandler(handler: DownloadChainHandler): DownloadChainBuilder {
handlers.add(handler)
return this
}
fun buildHandlerChain(): DownloadChainHandler? {
for (i in handlers.indices) {
handlers[i].processEndCallback = processEndCallback
if (i + 1 < handlers.size) {
handlers[i].setNext(handlers[i + 1])
}
}
return if (handlers.isEmpty()) null else handlers[0]
}
}

View File

@ -1,40 +0,0 @@
package com.gh.common.chain
import android.content.Context
import com.gh.gamecenter.feature.entity.GameEntity
abstract class DownloadChainHandler {
private var next: DownloadChainHandler? = null
// asVGame: 当前下载是否以畅玩游戏来进行
var processEndCallback: ((asVGame: Boolean, Any?) -> Unit)? = null
/**
* 设置下一个处理者
*/
fun setNext(next: DownloadChainHandler?) {
this.next = next
}
/**
* 获取下一个处理者
*/
fun getNext(): DownloadChainHandler? {
return next
}
/**
* 是否存在下一个处理者
*/
fun hasNext(): Boolean {
return next != null
}
/**
* 处理请求
* @param gameEntity 游戏实体
* @param asVGame 是否作为畅玩游戏进行
*/
abstract fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean)
}

View File

@ -3,18 +3,21 @@ package com.gh.common.chain
import android.content.Context import android.content.Context
import com.gh.common.util.DownloadDialogHelper import com.gh.common.util.DownloadDialogHelper
import com.gh.gamecenter.common.utils.safelyGetInRelease import com.gh.gamecenter.common.utils.safelyGetInRelease
import com.gh.gamecenter.core.utils.EmptyCallback
import com.gh.gamecenter.feature.entity.GameEntity import com.gh.gamecenter.feature.entity.GameEntity
class DownloadDialogHelperHandler : DownloadChainHandler() { class DownloadDialogHelperHandler : ChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) { override fun handleRequest(context: Context, gameEntity: GameEntity) {
val apk = gameEntity.getApk().safelyGetInRelease(0) ?: return val apk = gameEntity.getApk().safelyGetInRelease(0) ?: return
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk) { DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, object : EmptyCallback {
if (hasNext()) { override fun onCallback() {
getNext()?.handleRequest(context, gameEntity, asVGame) if (hasNext()) {
} else { getNext()?.handleRequest(context, gameEntity)
processEndCallback?.invoke(asVGame, null) } else {
processEndCallback?.invoke(null)
}
} }
} })
} }
} }

View File

@ -5,14 +5,14 @@ import androidx.appcompat.app.AppCompatActivity
import com.gh.gamecenter.feature.entity.GameEntity import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment
class GamePermissionHandler : DownloadChainHandler() { class GamePermissionHandler : ChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) { override fun handleRequest(context: Context, gameEntity: GameEntity) {
GamePermissionDialogFragment.show((context as AppCompatActivity), gameEntity, gameEntity.info) { GamePermissionDialogFragment.show((context as AppCompatActivity), gameEntity, gameEntity.info) {
if (hasNext()) { if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame) getNext()?.handleRequest(context, gameEntity)
} else { } else {
processEndCallback?.invoke(asVGame, null) processEndCallback?.invoke(null)
} }
} }
} }

View File

@ -1,40 +0,0 @@
package com.gh.common.chain
import android.app.Activity
import android.content.Context
import com.gh.common.util.DialogUtils
import com.gh.common.util.DirectUtils
import com.gh.common.util.TempCertificationUtils
import com.gh.gamecenter.feature.entity.GameEntity
class LandPageAddressHandler : DownloadChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
if (gameEntity.isLandPageAddressDialog()) {
TempCertificationUtils.checkCertificationBeforeAction(gameEntity) {
if (context is Activity && context.isFinishing) {
// 当前 context 已经无效,不需要再传递执行下去了
return@checkCertificationBeforeAction
}
DialogUtils.showLandPageAddressDialog(context, gameEntity) {// 跳转第三方落地页
if (gameEntity.isLandPageAddressDialogShowOnly()) {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(asVGame, null)
}
} else {
DirectUtils.directToExternalBrowser(context, gameEntity.landPageAddressDialog!!.link!!)
}
}
}
} else {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(asVGame, null)
}
}
}
}

View File

@ -1,34 +1,17 @@
package com.gh.common.chain package com.gh.common.chain
import android.app.Activity
import android.content.Context import android.content.Context
import com.gh.common.util.DialogUtils import com.gh.common.util.DialogUtils
import com.gh.common.util.TempCertificationUtils
import com.gh.gamecenter.feature.entity.GameEntity import com.gh.gamecenter.feature.entity.GameEntity
class OverseaDownloadHandler : DownloadChainHandler() { class OverseaDownloadHandler : ChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) { override fun handleRequest(context: Context, gameEntity: GameEntity) {
if (gameEntity.isOverseaAddressDialog()) { DialogUtils.showOverseaDownloadDialog(context, gameEntity) {
TempCertificationUtils.checkCertificationBeforeAction(gameEntity) {
if (context is Activity && context.isFinishing) {
// 当前 context 已经无效,不需要再传递执行下去了
return@checkCertificationBeforeAction
}
DialogUtils.showOverseaDownloadDialog(context, gameEntity) {// 跳转海外下载地址弹窗
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(asVGame, null)
}
}
}
} else {
if (hasNext()) { if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame) getNext()?.handleRequest(context, gameEntity)
} else { } else {
processEndCallback?.invoke(asVGame, null) processEndCallback?.invoke(null)
} }
} }
} }

View File

@ -5,14 +5,14 @@ import androidx.appcompat.app.AppCompatActivity
import com.gh.common.dialog.PackageCheckDialogFragment import com.gh.common.dialog.PackageCheckDialogFragment
import com.gh.gamecenter.feature.entity.GameEntity import com.gh.gamecenter.feature.entity.GameEntity
class PackageCheckHandler : DownloadChainHandler() { class PackageCheckHandler : ChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) { override fun handleRequest(context: Context, gameEntity: GameEntity) {
PackageCheckDialogFragment.show((context as AppCompatActivity), gameEntity) { PackageCheckDialogFragment.show((context as AppCompatActivity), gameEntity) {
if (hasNext()) { if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame) getNext()?.handleRequest(context, gameEntity)
} else { } else {
processEndCallback?.invoke(asVGame, null) processEndCallback?.invoke(null)
} }
} }
} }

View File

@ -1,29 +0,0 @@
package com.gh.common.chain
import android.content.Context
import com.gh.gamecenter.common.utils.DialogHelper
import com.gh.gamecenter.feature.entity.GameEntity
class UnsupportedFeatureHandler : DownloadChainHandler() {
override fun handleRequest(
context: Context,
gameEntity: GameEntity,
asVGame: Boolean
) {
if (shouldShowUnsupportedFeatureDialog()) {
DialogHelper.showUnsupportedFeatureDialog(context)
} else {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(asVGame, null)
}
}
}
/**
* TODO 检查某个版本是否支持指定的功能
*/
private fun shouldShowUnsupportedFeatureDialog(): Boolean = false
}

View File

@ -5,27 +5,31 @@ import com.gh.common.simulator.NewSimulatorGameManager
import com.gh.common.simulator.SimulatorGameManager import com.gh.common.simulator.SimulatorGameManager
import com.gh.gamecenter.feature.entity.GameEntity import com.gh.gamecenter.feature.entity.GameEntity
class UpdateNewSimulatorHandler: DownloadChainHandler() { class UpdateNewSimulatorHandler: ChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) { override fun handleRequest(context: Context, gameEntity: GameEntity) {
if (SimulatorGameManager.isSimulatorGame(gameEntity)) { if (SimulatorGameManager.isSimulatorGame(gameEntity)) {
if (NewSimulatorGameManager.shouldShowUpdateNewSimulatorAlert(context)) { if (NewSimulatorGameManager.shouldShowUpdateNewSimulatorAlert(context)) {
NewSimulatorGameManager.showUpdateNewsSimulator(context, gameEntity) { NewSimulatorGameManager.showUpdateNewsSimulator(context) {
if (hasNext()) { if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame) getNext()?.handleRequest(context, gameEntity)
} else { } else {
processEndCallback?.invoke(asVGame, null) processEndCallback?.invoke(null)
} }
} }
} else { }
else{
if (hasNext()) { if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame) getNext()?.handleRequest(context, gameEntity)
} }
} }
} else { }
else{
if (hasNext()) { if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame) getNext()?.handleRequest(context, gameEntity)
} }
} }
} }
} }

View File

@ -1,12 +0,0 @@
package com.gh.common.chain
import com.gh.vspace.VHelper
class VaPluginDownloadWrapper(val gameId: String, val callback: (Boolean, Any?) -> Unit) : (Boolean, Any?) -> Unit {
override fun invoke(asVGame: Boolean, any: Any?) {
callback.invoke(asVGame, any)
if (asVGame) {
VHelper.initVaPlugin(gameId)
}
}
}

View File

@ -4,23 +4,15 @@ import android.content.Context
import com.gh.gamecenter.feature.entity.GameEntity import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.vspace.VHelper import com.gh.vspace.VHelper
class ValidateVSpaceHandler : DownloadChainHandler() { class ValidateVSpaceHandler : ChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) { override fun handleRequest(context: Context, gameEntity: GameEntity) {
val closure = { VHelper.validateVSpaceBeforeAction(context, gameEntity) {
if (hasNext()) { if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame) getNext()?.handleRequest(context, gameEntity)
} else { } else {
processEndCallback?.invoke(asVGame, null) processEndCallback?.invoke(null)
} }
} }
if (asVGame) {
VHelper.validateVSpaceBeforeAction(context,gameEntity.getUniquePackageName(), gameEntity) {
closure.invoke()
}
} else {
closure.invoke()
}
} }
} }

View File

@ -3,59 +3,29 @@ package com.gh.common.chain
import android.content.Context import android.content.Context
import com.gh.gamecenter.R import com.gh.gamecenter.R
import com.gh.gamecenter.common.utils.DialogHelper import com.gh.gamecenter.common.utils.DialogHelper
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.toResString import com.gh.gamecenter.common.utils.toResString
import com.gh.gamecenter.feature.entity.GameEntity import com.gh.gamecenter.feature.entity.GameEntity
class VersionNumberHandler : DownloadChainHandler() { class VersionNumberHandler : ChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) { override fun handleRequest(context: Context, gameEntity: GameEntity) {
val confirmCallback = { val confirmCallback = {
if (hasNext()) { if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame) getNext()?.handleRequest(context, gameEntity)
} else { } else {
processEndCallback?.invoke(asVGame, null) processEndCallback?.invoke(null)
} }
} }
if (!gameEntity.isShowVersionNumber()) { if (!gameEntity.isShowVersionNumber()) {
confirmCallback.invoke() confirmCallback.invoke()
} else { } else {
SensorsBridge.trackGameDemoDialogShow(
gameId = gameEntity.id,
gameName = gameEntity.name ?: "",
gameType = gameEntity.categoryChinese
)
DialogHelper.showGuideDialog( DialogHelper.showGuideDialog(
context, context,
"温馨提示", "温馨提示",
gameEntity.getVersionNumberString(), gameEntity.getVersionNumberString(),
"继续下载", "继续下载",
com.gh.gamecenter.common.R.string.cancel.toResString(), R.string.cancel.toResString(),
{ { confirmCallback.invoke() },
confirmCallback.invoke()
SensorsBridge.trackGameDemoDialogClick(
buttonName = "继续下载",
gameId = gameEntity.id,
gameName = gameEntity.name ?: "",
gameType = gameEntity.categoryChinese
)
},
cancelClickCallback = {
SensorsBridge.trackGameDemoDialogClick(
buttonName = com.gh.gamecenter.common.R.string.cancel.toResString(),
gameId = gameEntity.id,
gameName = gameEntity.name ?: "",
gameType = gameEntity.categoryChinese
)
},
touchOutsideCallback = {
SensorsBridge.trackGameDemoDialogClick(
buttonName = "关闭弹窗",
gameId = gameEntity.id,
gameName = gameEntity.name ?: "",
gameType = gameEntity.categoryChinese
)
},
extraConfig = DialogHelper.Config(titleIcon = R.drawable.ic_dialog_tips) extraConfig = DialogHelper.Config(titleIcon = R.drawable.ic_dialog_tips)
) )
} }

View File

@ -1,59 +1,48 @@
package com.gh.common.constant; package com.gh.common.constant;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.IntentFilter;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Build; import android.os.Build;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.gh.common.util.AdHelper;
import com.gh.common.util.PackageHelper; import com.gh.common.util.PackageHelper;
import com.gh.common.util.PackageUtils; import com.gh.common.util.PackageUtils;
import com.gh.gamecenter.BuildConfig; import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.common.constant.CommonConsts; import com.gh.gamecenter.common.constant.CommonConsts;
import com.gh.gamecenter.common.constant.Constants; import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.eventbus.EBReuse; import com.gh.gamecenter.common.eventbus.EBReuse;
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
import com.gh.gamecenter.common.retrofit.BiResponse; import com.gh.gamecenter.common.retrofit.BiResponse;
import com.gh.gamecenter.common.retrofit.Response; import com.gh.gamecenter.common.retrofit.Response;
import com.gh.gamecenter.common.utils.DarkModeUtils; import com.gh.gamecenter.common.utils.DarkModeUtils;
import com.gh.gamecenter.common.utils.EnvHelper; import com.gh.gamecenter.common.utils.EnvHelper;
import com.gh.gamecenter.core.AppExecutor;
import com.gh.gamecenter.core.utils.GsonUtils; import com.gh.gamecenter.core.utils.GsonUtils;
import com.gh.gamecenter.core.utils.SPUtils; import com.gh.gamecenter.core.utils.SPUtils;
import com.gh.gamecenter.core.utils.UrlFilterUtils;
import com.gh.gamecenter.entity.AppEntity;
import com.gh.gamecenter.entity.FloatWindowSettingEntity;
import com.gh.gamecenter.entity.GameGuidePopupEntity; import com.gh.gamecenter.entity.GameGuidePopupEntity;
import com.gh.gamecenter.entity.NewApiSettingsEntity; import com.gh.gamecenter.entity.NewApiSettingsEntity;
import com.gh.gamecenter.entity.NewSettingsEntity; import com.gh.gamecenter.entity.NewSettingsEntity;
import com.gh.gamecenter.entity.VNewSetting;
import com.gh.gamecenter.entity.VSetting; import com.gh.gamecenter.entity.VSetting;
import com.gh.gamecenter.feature.entity.NewsEntity;
import com.gh.gamecenter.feature.entity.SettingsEntity; import com.gh.gamecenter.feature.entity.SettingsEntity;
import com.gh.gamecenter.feature.entity.SimulatorEntity; import com.gh.gamecenter.feature.entity.SimulatorEntity;
import com.gh.gamecenter.feature.utils.ContentBlockedHelper;
import com.gh.gamecenter.receiver.PackageChangeBroadcastReceiver;
import com.gh.gamecenter.retrofit.RetrofitManager; import com.gh.gamecenter.retrofit.RetrofitManager;
import com.gh.gamecenter.retrofit.service.VApiService;
import com.gh.vspace.VHelper; import com.gh.vspace.VHelper;
import com.halo.assistant.HaloApp; import com.halo.assistant.HaloApp;
import com.lightgame.utils.Utils;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.Single;
import io.reactivex.SingleSource;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.BehaviorSubject;
import okhttp3.ResponseBody; import okhttp3.ResponseBody;
public class Config { public class Config {
@ -63,9 +52,6 @@ public class Config {
public static final String NEW_API_HOST = EnvHelper.getNewHost(); public static final String NEW_API_HOST = EnvHelper.getNewHost();
public static final String VAPI_HOST = EnvHelper.getVHost(); public static final String VAPI_HOST = EnvHelper.getVHost();
public static final String WGAME_CPM_BUSIAPPID = BuildConfig.WGAME_CPM_BUSIAPPID;
public static final String WGAME_CPM_API_HOST = EnvHelper.getWGameCPMHost();
// Third-Party confs // Third-Party confs
public static final String WECHAT_APPID = BuildConfig.WECHAT_APPID; public static final String WECHAT_APPID = BuildConfig.WECHAT_APPID;
public static final String WECHAT_SECRET = BuildConfig.WECHAT_SECRET; public static final String WECHAT_SECRET = BuildConfig.WECHAT_SECRET;
@ -73,7 +59,8 @@ public class Config {
public static final String WEIBO_APPKEY = BuildConfig.WEIBO_APPKEY; public static final String WEIBO_APPKEY = BuildConfig.WEIBO_APPKEY;
public static final String QUICK_LOGIN_APPID = BuildConfig.QUICK_LOGIN_APPID; public static final String QUICK_LOGIN_APPID = BuildConfig.QUICK_LOGIN_APPID;
public static final String QUICK_LOGIN_APPKEY = BuildConfig.QUICK_LOGIN_APPKEY; public static final String QUICK_LOGIN_APPKEY = BuildConfig.QUICK_LOGIN_APPKEY;
public static final String URL_ARTICLE = "www.ghzs666.com/article/"; // ghzs/ghzs666 统一 // http://www.ghzs666.com/article/${articleId}.html
public static final String URL_ARTICLE = "http://www.ghzs666.com/article/"; // ghzs/ghzs666 统一
private static final String SETTINGS_KEY = "settingsKey"; private static final String SETTINGS_KEY = "settingsKey";
@ -84,26 +71,143 @@ public class Config {
private static NewApiSettingsEntity.NightMode mNightModeSetting; private static NewApiSettingsEntity.NightMode mNightModeSetting;
private static SimulatorEntity mNewSimulatorEntity; private static SimulatorEntity mNewSimulatorEntity;
private static VSetting mVSetting; private static VSetting mVSetting;
private volatile static VNewSetting mVNewSetting;
private static FloatWindowSettingEntity mFloatWindowSetting;
private static AppEntity mNew32UpdateEntity;
private static BehaviorSubject<VNewSetting> vNewSettingSubject = BehaviorSubject.create();
private static GameGuidePopupEntity mGameGuidePopupEntity; private static GameGuidePopupEntity mGameGuidePopupEntity;
private static SharedPreferences mDefaultSharedPreferences; private static SharedPreferences mDefaultSharedPreferences;
public static final String FIX_DOWNLOAD_KEY = "isFixDownload";
public static final String FIX_PLUGIN_KEY = "isFixPlugin";
public static final String FIX_ARTICLE_KEY = "isFixArticle";
public static final String FIX_COMMUNITY_KEY = "isFixCommunity";
public static final int VIDEO_PAGE_SIZE = 21; // 视频列表大多都是一行3个 public static final int VIDEO_PAGE_SIZE = 21; // 视频列表大多都是一行3个
public static boolean isShow() { public static boolean isShow() {
return !SPUtils.getBoolean(Constants.SP_TEENAGER_MODE); if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)) return false;
if (getPreferences().getBoolean(FIX_DOWNLOAD_KEY, false)) return true;
if (!isExistDownloadFilter()) return false;
for (SettingsEntity.Download entity : getSettings().getDownload()) {
if ("all".equals(entity.getGame())) {
if (entity.getPluginfy() && "normal".equals(entity.getPolicy()) && filterTime(entity.getTime())) {
return true;
}
}
}
return false;
}
public static boolean isShowDownload(String gameId) {
if (getPreferences().getBoolean(FIX_DOWNLOAD_KEY, false)) return true;
if (TextUtils.isEmpty(gameId) || !isExistDownloadFilter())
return false;
for (SettingsEntity.Download entity : getSettings().getDownload()) {
if (gameId.equals(entity.getGame())) {
if ("normal".equals(entity.getPolicy()) && filterTime(entity.getTime())) {
return true;
} else {
return false;
}
} else if ("all".equals(entity.getGame())) {
if ("normal".equals(entity.getPolicy()) && filterTime(entity.getTime())) {
return true;
}
}
}
return false;
}
/**
* 是否启用畅玩游戏
*/
public static boolean isVGameEnabled() {
if (getSettings() == null) {
return false;
}
return !"off".equals(getSettings().getGameSmooth());
}
public static boolean isShowPlugin(String gameId) {
SharedPreferences preferences = getPreferences();
boolean isFixPlugin = preferences.getBoolean(FIX_PLUGIN_KEY, false);
if (isFixPlugin) return true;
if (TextUtils.isEmpty(gameId) || !isExistDownloadFilter())
return false;
for (SettingsEntity.Download entity : getSettings().getDownload()) {
if (gameId.equals(entity.getGame())) {
if (entity.getPluginfy() && filterTime(entity.getTime())) {
return true;
} else {
return false;
}
}
if ("all".equals(entity.getGame())) {
if (entity.getPluginfy() && filterTime(entity.getTime())) {
preferences.edit().putBoolean(FIX_PLUGIN_KEY, true).apply();
return true;
}
}
}
return false;
}
public static boolean isShowPlugin() {
SharedPreferences preferences = getPreferences();
boolean isFixPlugin = preferences.getBoolean(FIX_PLUGIN_KEY, false);
if (isFixPlugin) return true;
if (!isExistDownloadFilter())
return false;
for (SettingsEntity.Download entity : getSettings().getDownload()) {
if ("all".equals(entity.getGame())) {
if (entity.getPluginfy() && filterTime(entity.getTime())) {
preferences.edit().putBoolean(FIX_PLUGIN_KEY, true).apply();
return true;
}
}
}
return false;
}
private static boolean filterTime(SettingsEntity.Download.TimeEntity timeEntity) {
long end = timeEntity.getEnd();
long start = timeEntity.getStart();
long curTime = Utils.getTime(HaloApp.getInstance().getApplication());
if ((start == 0 || curTime >= start) && (end == 0 || curTime <= end)) {
return true;
}
return false;
} }
public static void setSettings(SettingsEntity settingsEntity) { public static void setSettings(SettingsEntity settingsEntity) {
getPreferences().edit().putString(SETTINGS_KEY, GsonUtils.toJson(settingsEntity)).apply(); getPreferences().edit().putString(SETTINGS_KEY, GsonUtils.toJson(settingsEntity)).apply();
mSettingsEntity = settingsEntity; mSettingsEntity = settingsEntity;
PackageHelper.refreshPackageNameList(); // 更新设置状态
mSettingsEntity.showArticleEntrance();
mSettingsEntity.showCommunityEntrance();
// 加载完设置后刷新下
PackageHelper.initList();
// 初始化畅玩相关的东西
VHelper.init(HaloApp.getInstance(), false);
} }
@Nullable @Nullable
@ -114,8 +218,6 @@ public class Config {
if (!TextUtils.isEmpty(json)) { if (!TextUtils.isEmpty(json)) {
mSettingsEntity = GsonUtils.fromJson(json, SettingsEntity.class); mSettingsEntity = GsonUtils.fromJson(json, SettingsEntity.class);
} }
mSettingsEntity.setGameSmooth("off");
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -204,105 +306,32 @@ public class Config {
return mVSetting; return mVSetting;
} }
@Nullable
public static VNewSetting getVNewSettingEntity() {
if (mVNewSetting == null) {
try {
String json = SPUtils.getString(Constants.SP_V_NEW_SETTINGS);
if (!TextUtils.isEmpty(json)) {
mVNewSetting = GsonUtils.fromJson(json, VNewSetting.class);
vNewSettingSubject.onNext(mVNewSetting);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return mVNewSetting;
}
@Nullable
public static FloatWindowSettingEntity getFloatWindowSettingEntity() {
if (mFloatWindowSetting == null) {
try {
String json = SPUtils.getString(Constants.SP_FLOAT_WINDOW_SETTINGS);
if (!TextUtils.isEmpty(json)) {
mFloatWindowSetting = GsonUtils.fromJson(json, FloatWindowSettingEntity.class);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return mFloatWindowSetting;
}
@NonNull
public static Observable<VNewSetting> getVNewSettingObservable() {
if (mVNewSetting != null) {
return Observable.just(mVNewSetting);
} else {
return vNewSettingSubject.hide();
}
}
@Nullable
public static AppEntity getNew32UpdateEntity() {
return mNew32UpdateEntity;
}
/**
* 请求网络数据,尝试刷新畅玩相关配置
*/
@SuppressLint("CheckResult")
public static void refreshVSettingEntity() {
RetrofitManager.getInstance()
.getVApi().getSettings(BuildConfig.VERSION_NAME, Build.VERSION.SDK_INT)
.subscribeOn(Schedulers.io())
.subscribe(new BiResponse<VSetting>() {
@Override
public void onSuccess(VSetting data) {
mVSetting = data;
SPUtils.setString(Constants.SP_V_SETTINGS, GsonUtils.toJson(data));
VHelper.init(HaloApp.getInstance());
}
});
}
@SuppressLint("CheckResult")
public static void getNewSetting() {
VApiService vApi = RetrofitManager.getInstance().getVApi();
vApi.getNewSettings(BuildConfig.VERSION_NAME, Build.VERSION.SDK_INT).flatMap(new Function<VNewSetting, SingleSource<AppEntity>>() {
@Override
public SingleSource<AppEntity> apply(VNewSetting data) throws Exception {
mVNewSetting = data;
vNewSettingSubject.onNext(mVNewSetting);
SPUtils.setString(Constants.SP_V_NEW_SETTINGS, GsonUtils.toJson(data));
if (data.getVa() != null && data.getVa().getArch32() != null) {
String versionNameByPackageName = PackageUtils.getVersionNameByPackageName(data.getVa().getArch32().getPackageName());
return vApi.getNewPackageUpdate(
BuildConfig.VERSION_NAME,
versionNameByPackageName != null ? versionNameByPackageName : "",
HaloApp.getInstance().getChannel()
);
}
return Single.error(new IllegalStateException("VNewSetting entity is not expected"));
}
})
.subscribeOn(Schedulers.io())
.subscribe(new BiResponse<AppEntity>() {
@Override
public void onSuccess(AppEntity data) {
mNew32UpdateEntity = data;
}
});
}
@Nullable @Nullable
public static GameGuidePopupEntity getGameGuidePopupEntity() { public static GameGuidePopupEntity getGameGuidePopupEntity() {
return mGameGuidePopupEntity; return mGameGuidePopupEntity;
} }
private static boolean isExistDownloadFilter() {
if (getSettings() == null || getSettings().getDownload() == null || getSettings().getDownload().size() == 0) {
return false;
} else {
return true;
}
}
public static void filterPluginArticle(List<NewsEntity> list) {
if (isShowPlugin() || list == null) return;
for (int i = 0; i < list.size(); i++) {
NewsEntity newsEntity = list.get(i);
String title = newsEntity.getTitle();
if (!TextUtils.isEmpty(title) && title.contains("插件")) {
list.remove(i);
i--;
}
}
}
public static SharedPreferences getPreferences() { public static SharedPreferences getPreferences() {
if (mDefaultSharedPreferences == null) { if (mDefaultSharedPreferences == null) {
mDefaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication()); mDefaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication());
@ -314,13 +343,10 @@ public class Config {
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
public static void getGhzsSettings() { public static void getGhzsSettings() {
String channel = HaloApp.getInstance().getChannel(); String channel = HaloApp.getInstance().getChannel();
// 把请求提前,避免请求过多阻塞,首页显示广告时老是用到上一次的缓存
getNewSettings(channel);
RetrofitManager.getInstance() RetrofitManager.getInstance()
.getApi().getSettings(PackageUtils.getGhVersionName(), channel) .getApi().getSettings(PackageUtils.getGhVersionName(), channel)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<SettingsEntity>() { .subscribe(new Response<SettingsEntity>() {
@Override @Override
public void onResponse(SettingsEntity response) { public void onResponse(SettingsEntity response) {
@ -332,8 +358,11 @@ public class Config {
GsonUtils.toJson(response.getSuggestion())); GsonUtils.toJson(response.getSuggestion()));
edit.apply(); edit.apply();
if (!getPreferences().getBoolean(Config.FIX_DOWNLOAD_KEY, false) && Config.isShow()) {
getPreferences().edit().putBoolean(Config.FIX_DOWNLOAD_KEY, true).apply();
}
if (!SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)) { if (!SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)) {
AppExecutor.getUiExecutor().execute(() -> EventBus.getDefault().post(new EBReuse("Refresh"))); EventBus.getDefault().post(new EBReuse("Refresh"));
} }
} }
}); });
@ -341,6 +370,7 @@ public class Config {
RetrofitManager.getInstance() RetrofitManager.getInstance()
.getApi().getNewSettings(Build.MANUFACTURER, Build.MODEL, channel, Build.VERSION.SDK_INT, BuildConfig.VERSION_NAME) .getApi().getNewSettings(Build.MANUFACTURER, Build.MODEL, channel, Build.VERSION.SDK_INT, BuildConfig.VERSION_NAME)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BiResponse<NewSettingsEntity>() { .subscribe(new BiResponse<NewSettingsEntity>() {
@Override @Override
public void onSuccess(NewSettingsEntity data) { public void onSuccess(NewSettingsEntity data) {
@ -349,13 +379,44 @@ public class Config {
} }
}); });
refreshVSettingEntity(); if (mVSetting == null) {
getNewSetting(); RetrofitManager.getInstance()
getFloatWindowSetting(); .getVApi().getSettings(BuildConfig.VERSION_NAME)
.subscribeOn(Schedulers.io())
.subscribe(new BiResponse<VSetting>() {
@Override
public void onSuccess(VSetting data) {
mVSetting = data;
SPUtils.setString(Constants.SP_V_SETTINGS, GsonUtils.toJson(data));
}
});
}
if (mNewApiSettingsEntity == null) {
RetrofitManager.getInstance()
.getNewApi().getNewSettings(PackageUtils.getGhVersionName(), channel)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BiResponse<NewApiSettingsEntity>() {
@Override
public void onSuccess(NewApiSettingsEntity data) {
mNewApiSettingsEntity = data;
mNightModeSetting = data.getNightMode();
mNewSimulatorEntity = data.getSimulator();
if (HaloApp.getInstance().isNewForThisVersion && mNightModeSetting != null && mNightModeSetting.getInstall()) {
DarkModeUtils.INSTANCE.updateFollowSystemDarkModeToSp(true);
DarkModeUtils.INSTANCE.initDarkMode();
}
AdHelper.prefetchStartUpAd(mNewApiSettingsEntity);
SPUtils.setString(Constants.SP_NEW_API_SETTINGS, GsonUtils.toJson(data));
}
});
}
RetrofitManager.getInstance() RetrofitManager.getInstance()
.getApi().getGameGuidePopup(Build.MANUFACTURER, Build.VERSION.RELEASE, Build.MODEL, channel, BuildConfig.VERSION_NAME) .getApi().getGameGuidePopup(Build.MANUFACTURER, Build.VERSION.RELEASE, Build.MODEL, channel, BuildConfig.VERSION_NAME)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BiResponse<GameGuidePopupEntity>() { .subscribe(new BiResponse<GameGuidePopupEntity>() {
@Override @Override
public void onSuccess(GameGuidePopupEntity data) { public void onSuccess(GameGuidePopupEntity data) {
@ -367,6 +428,7 @@ public class Config {
if (manufacturer.equals("OPPO") || manufacturer.equals("VIVO")) { if (manufacturer.equals("OPPO") || manufacturer.equals("VIVO")) {
RetrofitManager.getInstance().getNewApi().getBrowserHintUrl(manufacturer) RetrofitManager.getInstance().getNewApi().getBrowserHintUrl(manufacturer)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BiResponse<ResponseBody>() { .subscribe(new BiResponse<ResponseBody>() {
@Override @Override
public void onSuccess(ResponseBody data) { public void onSuccess(ResponseBody data) {
@ -382,76 +444,4 @@ public class Config {
}); });
} }
} }
@SuppressLint("CheckResult")
private static void getNewSettings(String channel) {
if (mNewApiSettingsEntity == null) {
String filterString = UrlFilterUtils.getFilterQuery(
"manufacturer", Build.MANUFACTURER,
"model", Build.MODEL,
"android_sdk_version", String.valueOf(Build.VERSION.SDK_INT),
"rom", MetaUtil.INSTANCE.getRom().name() + " " + MetaUtil.INSTANCE.getRom().getVersionName()
);
RetrofitManager.getInstance()
.getNewApi().getNewSettings(PackageUtils.getGhVersionName(), channel, filterString)
.subscribeOn(Schedulers.io())
.subscribe(new BiResponse<NewApiSettingsEntity>() {
@Override
public void onSuccess(NewApiSettingsEntity data) {
mNewApiSettingsEntity = data;
mNightModeSetting = data.getNightMode();
mNewSimulatorEntity = data.getSimulator();
if (HaloApp.getInstance().isNewForThisVersion && mNightModeSetting != null && mNightModeSetting.getInstall()) {
DarkModeUtils.INSTANCE.updateFollowSystemDarkModeToSp(true);
AppExecutor.getUiExecutor().execute(DarkModeUtils.INSTANCE::initDarkMode);
}
SPUtils.setString(Constants.SP_NEW_API_SETTINGS, GsonUtils.toJson(data));
// 刷新屏蔽字段
if (mNewApiSettingsEntity.getGameShieldContents() != null) {
ContentBlockedHelper.INSTANCE.init(mNewApiSettingsEntity.getGameShieldContents());
}
// 更新安装列表是否开启的配置
if (mNewApiSettingsEntity.getInstalledComplianceSwitch() != null) {
PackageHelper.INSTANCE.updateIsGetInstalledPackagesApiAgreedRequired(mNewApiSettingsEntity.getInstalledComplianceSwitch());
} else {
PackageHelper.INSTANCE.updateIsGetInstalledPackagesApiAgreedRequired(false);
}
// 更新包名监听是否开启
if (mNewApiSettingsEntity.isPackageObserveEnable()) {
AppExecutor.getUiExecutor().execute(() -> observePackageChange(mNewApiSettingsEntity.getPackageObserveActions()));
}
}
});
}
}
@SuppressLint("CheckResult")
private static void getFloatWindowSetting() {
RetrofitManager.getInstance().getNewApi()
.getFloatWindowSettings()
.subscribeOn(Schedulers.io())
.subscribe(new BiResponse<FloatWindowSettingEntity>() {
@Override
public void onSuccess(FloatWindowSettingEntity data) {
mFloatWindowSetting = data;
SPUtils.setString(Constants.SP_FLOAT_WINDOW_SETTINGS, GsonUtils.toJson(data));
}
});
}
public static void observePackageChange(NewApiSettingsEntity.PackageObserveActions packageObserveActions) {
PackageChangeBroadcastReceiver receiver = new PackageChangeBroadcastReceiver(packageObserveActions);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(packageObserveActions.getAdd());
intentFilter.addAction(packageObserveActions.getRem());
intentFilter.addAction(packageObserveActions.getRep());
intentFilter.addDataScheme("package");
HaloApp.getInstance().registerReceiver(receiver, intentFilter);
}
} }

View File

@ -13,14 +13,14 @@ import android.widget.PopupWindow
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.databinding.BindingAdapter import androidx.databinding.BindingAdapter
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.gh.gamecenter.R
import com.gh.gamecenter.common.callback.OnViewClickListener import com.gh.gamecenter.common.callback.OnViewClickListener
import com.gh.gamecenter.common.databinding.LayoutPopupContainerBinding
import com.gh.gamecenter.common.utils.dip2px import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.toDrawable import com.gh.gamecenter.common.utils.toDrawable
import com.gh.gamecenter.common.view.BugFixedPopupWindow import com.gh.gamecenter.common.view.BugFixedPopupWindow
import com.gh.gamecenter.R
import com.gh.gamecenter.databinding.KaifuAddItemBinding import com.gh.gamecenter.databinding.KaifuAddItemBinding
import com.gh.gamecenter.databinding.LayoutAddKaifuPopupBinding import com.gh.gamecenter.databinding.LayoutAddKaifuPopupBinding
import com.gh.gamecenter.databinding.LayoutPopupContainerBinding
import com.gh.gamecenter.feature.entity.ServerCalendarEntity import com.gh.gamecenter.feature.entity.ServerCalendarEntity
import com.gh.gamecenter.servers.add.AddKaiFuPopupAdapter import com.gh.gamecenter.servers.add.AddKaiFuPopupAdapter
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
@ -120,14 +120,14 @@ object AddKaiFuBindingAdapter {
@BindingAdapter("kaiFuTextColor", "kaiFuTextPosition") @BindingAdapter("kaiFuTextColor", "kaiFuTextPosition")
fun kaiFuTextColor(view: EditText, dataMark: Int, position: Int) { fun kaiFuTextColor(view: EditText, dataMark: Int, position: Int) {
if (dataMark == 1 && view.id == R.id.kaifu_add_time || dataMark == 2 && view.id == R.id.kaifu_add_first_name || dataMark == 3 && view.id == R.id.kaifu_add_server_name || dataMark == 4) { if (dataMark == 1 && view.id == R.id.kaifu_add_time || dataMark == 2 && view.id == R.id.kaifu_add_first_name || dataMark == 3 && view.id == R.id.kaifu_add_server_name || dataMark == 4) {
view.setTextColor(ContextCompat.getColor(view.context, com.gh.gamecenter.common.R.color.secondary_red)) view.setTextColor(ContextCompat.getColor(view.context, R.color.theme_red))
view.setHintTextColor(ContextCompat.getColor(view.context, com.gh.gamecenter.common.R.color.secondary_red)) view.setHintTextColor(ContextCompat.getColor(view.context, R.color.theme_red))
} else if (position == 0) { } else if (position == 0) {
view.setTextColor(ContextCompat.getColor(view.context, com.gh.gamecenter.common.R.color.hint)) view.setTextColor(ContextCompat.getColor(view.context, R.color.hint))
view.setHintTextColor(ContextCompat.getColor(view.context, com.gh.gamecenter.common.R.color.hint)) view.setHintTextColor(ContextCompat.getColor(view.context, R.color.hint))
} else { } else {
view.setTextColor(ContextCompat.getColor(view.context, com.gh.gamecenter.common.R.color.text_primary)) view.setTextColor(ContextCompat.getColor(view.context, R.color.text_title))
view.setHintTextColor(ContextCompat.getColor(view.context, com.gh.gamecenter.common.R.color.hint)) view.setHintTextColor(ContextCompat.getColor(view.context, R.color.hint))
} }
} }
@ -176,7 +176,7 @@ object AddKaiFuBindingAdapter {
popupWindow.isTouchable = true popupWindow.isTouchable = true
popupWindow.inputMethodMode = PopupWindow.INPUT_METHOD_NEEDED popupWindow.inputMethodMode = PopupWindow.INPUT_METHOD_NEEDED
popupWindow.isOutsideTouchable = true popupWindow.isOutsideTouchable = true
popupWindow.animationStyle = com.gh.gamecenter.common.R.style.popwindow_option_anim_style popupWindow.animationStyle = R.style.popwindow_option_anim_style
// 设置偏移 // 设置偏移
windowPos[1] = windowPos[1] - 12F.dip2px() windowPos[1] = windowPos[1] - 12F.dip2px()

View File

@ -1,32 +1,37 @@
package com.gh.common.databind; package com.gh.common.databind;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Typeface;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.facebook.drawee.view.SimpleDraweeView;
import com.gh.common.chain.BrowserInstallHandler; import com.gh.common.chain.BrowserInstallHandler;
import com.gh.common.chain.DownloadChainBuilder; import com.gh.common.chain.CertificationHandler;
import com.gh.common.chain.DownloadChainHandler; import com.gh.common.chain.ChainBuilder;
import com.gh.common.chain.ChainHandler;
import com.gh.common.chain.CheckDownloadHandler; import com.gh.common.chain.CheckDownloadHandler;
import com.gh.common.chain.CheckStoragePermissionHandler;
import com.gh.common.chain.DownloadDialogHelperHandler; import com.gh.common.chain.DownloadDialogHelperHandler;
import com.gh.common.chain.GamePermissionHandler; import com.gh.common.chain.GamePermissionHandler;
import com.gh.common.chain.LandPageAddressHandler;
import com.gh.common.chain.OverseaDownloadHandler; import com.gh.common.chain.OverseaDownloadHandler;
import com.gh.common.chain.PackageCheckHandler; import com.gh.common.chain.PackageCheckHandler;
import com.gh.common.chain.UnsupportedFeatureHandler;
import com.gh.common.chain.ValidateVSpaceHandler; import com.gh.common.chain.ValidateVSpaceHandler;
import com.gh.common.chain.VersionNumberHandler; import com.gh.common.chain.VersionNumberHandler;
import com.gh.common.constant.Config;
import com.gh.gamecenter.feature.exposure.ExposureEvent;
import com.gh.common.filter.RegionSetting; import com.gh.common.filter.RegionSetting;
import com.gh.common.filter.RegionSettingHelper; import com.gh.common.filter.RegionSettingHelper;
import com.gh.common.history.HistoryHelper; import com.gh.common.history.HistoryHelper;
@ -38,50 +43,183 @@ import com.gh.common.util.DialogUtils;
import com.gh.common.util.GameUtils; import com.gh.common.util.GameUtils;
import com.gh.common.util.GameViewUtils; import com.gh.common.util.GameViewUtils;
import com.gh.common.util.LogUtils; import com.gh.common.util.LogUtils;
import com.gh.common.util.NewsUtils;
import com.gh.common.util.PackageInstaller; import com.gh.common.util.PackageInstaller;
import com.gh.common.util.PackageLauncher;
import com.gh.common.util.PackageUtils; import com.gh.common.util.PackageUtils;
import com.gh.gamecenter.feature.utils.PlatformUtils;
import com.gh.common.util.ReservationHelper; import com.gh.common.util.ReservationHelper;
import com.gh.gamecenter.feature.view.DownloadButton;
import com.gh.gamecenter.feature.view.GameIconView;
import com.gh.gamecenter.common.view.NoEllipsizeSpaceTextView;
import com.gh.download.DownloadManager; import com.gh.download.DownloadManager;
import com.gh.download.dialog.DownloadDialog; import com.gh.download.dialog.DownloadDialog;
import com.gh.download.server.BrowserInstallHelper;
import com.gh.gamecenter.DownloadManagerActivity; import com.gh.gamecenter.DownloadManagerActivity;
import com.gh.gamecenter.R; import com.gh.gamecenter.R;
import com.gh.gamecenter.WebActivity; import com.gh.gamecenter.WebActivity;
import com.gh.gamecenter.common.entity.LinkEntity; import com.gh.gamecenter.common.baselist.LoadStatus;
import com.gh.gamecenter.common.utils.DarkModeUtils; import com.gh.gamecenter.common.callback.OnViewClickListener;
import com.gh.gamecenter.common.utils.ExtensionsKt; import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.common.utils.FileUtils; import com.gh.gamecenter.common.utils.ImageUtils;
import com.gh.gamecenter.common.utils.NewFlatLogUtils; import com.gh.gamecenter.common.utils.DarkModeUtils;
import com.gh.gamecenter.common.utils.SensorsBridge; import com.gh.gamecenter.common.view.DrawableView;
import com.gh.gamecenter.core.utils.DisplayUtils;
import com.gh.gamecenter.core.utils.MtaHelper; import com.gh.gamecenter.core.utils.MtaHelper;
import com.gh.gamecenter.core.utils.ToastUtils; import com.gh.gamecenter.core.utils.NumberUtils;
import com.gh.gamecenter.databinding.KaifuDetailItemRowBinding;
import com.gh.gamecenter.feature.entity.ApkEntity; import com.gh.gamecenter.feature.entity.ApkEntity;
import com.gh.gamecenter.feature.entity.GameEntity; import com.gh.gamecenter.feature.entity.GameEntity;
import com.gh.gamecenter.common.entity.LinkEntity;
import com.gh.gamecenter.feature.entity.PluginLocation; import com.gh.gamecenter.feature.entity.PluginLocation;
import com.gh.gamecenter.feature.entity.ServerCalendarEntity;
import com.gh.gamecenter.feature.entity.TagStyleEntity; import com.gh.gamecenter.feature.entity.TagStyleEntity;
import com.gh.gamecenter.feature.entity.TestEntity; import com.gh.gamecenter.feature.entity.TestEntity;
import com.gh.gamecenter.feature.exposure.ExposureEvent; import com.gh.gamecenter.common.eventbus.EBReuse;
import com.gh.gamecenter.feature.utils.PlatformUtils;
import com.gh.gamecenter.feature.view.DownloadButton;
import com.gh.gamecenter.feature.view.GameIconView;
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment; import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment;
import com.gh.gamecenter.manager.PackagesManager; import com.gh.gamecenter.manager.PackagesManager;
import com.gh.gamecenter.feature.entity.CommunityVideoEntity;
import com.gh.vspace.VDownloadManagerActivity;
import com.gh.vspace.VHelper; import com.gh.vspace.VHelper;
import com.lightgame.download.DownloadEntity; import com.lightgame.download.DownloadEntity;
import com.lightgame.download.FileUtils;
import com.lightgame.utils.Utils; import com.lightgame.utils.Utils;
import org.greenrobot.eventbus.EventBus;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import kotlin.collections.CollectionsKt;
/** /**
* Created by khy on 12/02/18. * Created by khy on 12/02/18.
*/ */
public class BindingAdapters { public class BindingAdapters {
public static void loadIcon(SimpleDraweeView view, String imageUrl) {
ImageUtils.displayIcon(view, imageUrl);
}
public static void loadImage(SimpleDraweeView view, String imageUrl) {
ImageUtils.display(view, imageUrl);
}
public static void setTextSize(TextView view, int number) {
view.setTextSize(number);
}
public static void setTypeface(TextView view, String type) {
if (type == null) return;
switch (type) {
case "bold":
view.setTypeface(null, Typeface.BOLD);
break;
case "italic":
view.setTypeface(null, Typeface.ITALIC);
break;
case "bold_italic":
view.setTypeface(null, Typeface.BOLD_ITALIC);
break;
default:
view.setTypeface(null, Typeface.NORMAL);
break;
}
}
public static void addDetailKaiFuView(LinearLayout view, List<ServerCalendarEntity> list
, OnViewClickListener listener, Boolean isReadyPatch) {
if (list == null) return;
view.removeAllViews();
for (int i = 0; i < list.size() + 1; i++) { // 1 is Title
View inflate = LayoutInflater.from(view.getContext()).inflate(R.layout.kaifu_detail_item_row, null);
KaifuDetailItemRowBinding binding = KaifuDetailItemRowBinding.bind(inflate);
binding.getRoot().setBackgroundColor(isReadyPatch != null && isReadyPatch ? ExtensionsKt.toColor(R.color.theme) : ExtensionsKt.toColor(R.color.white));
binding.getRoot().setPadding(DisplayUtils.dip2px(1), DisplayUtils.dip2px(1), DisplayUtils.dip2px(1), i == list.size() ? DisplayUtils.dip2px(1) : 0);
ServerCalendarEntity serverEntity = list.get(i - 1);
binding.timeTv.setText(i == 0 ? "时间" : serverEntity.getFormatTime("HH:mm"));
binding.remarkTv.setText(i == 0 ? "备注" : serverEntity.getRemark());
binding.nameTv.setText(i == 0 ? "名字" : (TextUtils.isEmpty(serverEntity.getNote()) ? "-" : serverEntity.getNote()));
if (i != 0) {
binding.getRoot().setOnClickListener(v -> {
listener.onClick(v, isReadyPatch != null && isReadyPatch ? serverEntity : null);
});
// 滑动冲突处理
binding.getRoot().setOnTouchListener((v, event) -> {
if (list.size() > 5) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
EventBus.getDefault().post(new EBReuse("CalenderDown"));
} else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
EventBus.getDefault().post(new EBReuse("CalenderCancel"));
}
}
return false;
});
}
view.addView(inflate);
}
}
// 如果超过10000则转换为1.0W
public static void transSimpleCount(TextView view, int count) {
view.setText(NumberUtils.transSimpleCount(count));
}
public static void textColorFromString(TextView tv, String hexString) {
if (TextUtils.isEmpty(hexString)) return;
try {
tv.setTextColor(Color.parseColor(hexString));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void showHide(View view, Boolean show) {
if (show != null && show) {
view.setVisibility(View.VISIBLE);
} else {
view.setVisibility(View.GONE);
}
}
public static void goneIf(View view, Boolean gone) {
if (gone != null && gone) {
view.setVisibility(View.GONE);
} else {
view.setVisibility(View.VISIBLE);
}
}
/**
* lazy 的 paddingTop
*/
public static void lazyPaddingLeft(View view, int paddingLeftInDp) {
view.setPadding(DisplayUtils.dip2px(paddingLeftInDp), view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom());
}
/**
* lazy 的 paddingTop
*/
public static void lazyPaddingTop(View view, int paddingTopInDp) {
view.setPadding(view.getPaddingLeft(), DisplayUtils.dip2px(paddingTopInDp), view.getPaddingRight(), view.getPaddingBottom());
}
/**
* lazy 的 paddingBottom
*/
public static void lazyPaddingBottom(View view, int paddingBottomInDp) {
view.setPadding(view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), DisplayUtils.dip2px(paddingBottomInDp));
}
public static void visibleInvisible(View view, Boolean show) {
if (show != null && show) {
view.setVisibility(View.VISIBLE);
} else {
view.setVisibility(View.INVISIBLE);
}
}
public static void setMessageUnread(TextView view, int unreadCount) { public static void setMessageUnread(TextView view, int unreadCount) {
if (unreadCount < 100) { if (unreadCount < 100) {
view.setText(String.valueOf(unreadCount)); view.setText(String.valueOf(unreadCount));
@ -90,19 +228,117 @@ public class BindingAdapters {
} }
} }
public static void setServerTypePadding(TextView view, String serverType) {
int paddRight = 0;
if (TextUtils.isEmpty(serverType)) {
} else {
if ("删档内测".equals(serverType) || "不删档内测".equals(serverType)) {
if ("删档内测".equals(serverType)) {
paddRight = DisplayUtils.dip2px(view.getContext(), 50);
} else {
paddRight = DisplayUtils.dip2px(view.getContext(), 60);
}
} else {
paddRight = DisplayUtils.dip2px(view.getContext(), 30);
}
}
view.setPadding(0, 0, paddRight, 0);
}
public static void setServerType(TextView view, String serverType) {
view.setText(serverType);
if ("删档内测".equals(serverType) || "不删档内测".equals(serverType)) {
view.setBackgroundResource(R.drawable.textview_server_tag);
} else {
view.setBackgroundResource(R.drawable.textview_orange_up);
}
}
public static void setGame(View view, GameEntity gameEntity) { public static void setGame(View view, GameEntity gameEntity) {
if (gameEntity != null && view instanceof GameIconView) { if (gameEntity != null && view instanceof GameIconView) {
((GameIconView) view).displayGameIcon(gameEntity); ((GameIconView) view).displayGameIcon(gameEntity);
} }
} }
public static void setDownloadButton(DownloadButton progressBar, public static void setGameIcon(View view, GameEntity gameEntity) {
GameEntity gameEntity, if (gameEntity != null && view instanceof GameIconView) {
ExposureEvent traceEvent, ((GameIconView) view).displayGameIcon(gameEntity.getIcon(), gameEntity.getIconSubscript(), gameEntity.getIconFloat());
@Nullable View.OnClickListener clickCallBack, }
@Nullable String entrance, }
@Nullable String location) {
setDownloadButton(progressBar, gameEntity, traceEvent, clickCallBack, entrance, location, "其他"); public static void setArticleType(TextView view, String articleType) {
NewsUtils.setNewsType(view, articleType, 0, 0);
}
public static void setDetailDownloadText(TextView view, GameEntity gameEntity) {
if (gameEntity == null || gameEntity.getApk().isEmpty()) {
view.setBackgroundResource(R.drawable.game_item_btn_pause_style);
view.setTextColor(0xFF999999);
view.setClickable(false);
}
}
public static void setLiBaoBtn(TextView view, String status) {
if (TextUtils.isEmpty(status)) return;
switch (status) {
case "coming":
view.setText(R.string.libao_coming);
view.setBackgroundResource(R.drawable.textview_blue_style);
break;
case "ling":
view.setText(R.string.libao_ling);
view.setBackgroundResource(R.drawable.textview_green_style);
break;
case "tao":
view.setText(R.string.libao_tao);
view.setBackgroundResource(R.drawable.textview_orange_style);
break;
case "used_up":
view.setText(R.string.libao_used_up);
view.setBackgroundResource(R.drawable.textview_cancel_up);
break;
case "finish":
view.setText(R.string.libao_finish);
view.setBackgroundResource(R.drawable.textview_cancel_up);
break;
case "linged":
view.setText(R.string.libao_linged);
view.setBackgroundResource(R.drawable.libao_linged_style);
view.setTextColor(ContextCompat.getColorStateList(view.getContext(), R.color.libao_linged_selector));
break;
case "taoed":
view.setText(R.string.libao_taoed);
view.setBackgroundResource(R.drawable.libao_taoed_style);
view.setTextColor(ContextCompat.getColorStateList(view.getContext(), R.color.libao_taoed_selector));
break;
case "copy":
view.setText(R.string.libao_copy);
view.setBackgroundResource(R.drawable.textview_blue_style);
break;
case "repeatLing":
view.setText(R.string.libao_repeat_ling);
view.setBackgroundResource(R.drawable.textview_cancel_up);
break;
case "repeatLinged":
view.setText(R.string.libao_repeat_ling);
view.setBackgroundResource(R.drawable.textview_green_style);
break;
case "repeatTao":
view.setText(R.string.libao_repeat_tao);
view.setBackgroundResource(R.drawable.textview_cancel_up);
break;
case "repeatTaoed":
view.setText(R.string.libao_repeat_tao);
view.setBackgroundResource(R.drawable.textview_orange_style);
break;
case "unshelve":
view.setBackgroundResource(R.drawable.textview_cancel_style);
view.setText(R.string.libao_unshelve);
break;
default:
view.setBackgroundResource(R.drawable.textview_cancel_style);
view.setText("异常");
}
} }
// 大图下的进度条 // 大图下的进度条
@ -111,14 +347,14 @@ public class BindingAdapters {
ExposureEvent traceEvent, ExposureEvent traceEvent,
@Nullable View.OnClickListener clickCallBack, @Nullable View.OnClickListener clickCallBack,
@Nullable String entrance, @Nullable String entrance,
@Nullable String location, @Nullable String location) {
String sourceEntrance) {
// 恢复DialogFragment // 恢复DialogFragment
restoreDialogFragment(progressBar); restoreDialogFragment(progressBar);
// 判断是否显示按钮 // 判断是否显示按钮
if (gameEntity != null if (gameEntity != null
&& Config.isShowDownload(gameEntity.getId())
&& !"光环助手".equals(gameEntity.getName())) { && !"光环助手".equals(gameEntity.getName())) {
progressBar.setVisibility(View.VISIBLE); progressBar.setVisibility(View.VISIBLE);
} else { } else {
@ -132,9 +368,13 @@ public class BindingAdapters {
switch (progressBar.getButtonStyle()) { switch (progressBar.getButtonStyle()) {
case DOWNLOADING_PLUGIN: case DOWNLOADING_PLUGIN:
case DOWNLOADING_NORMAL: case DOWNLOADING_NORMAL:
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(v.getContext(), if (gameEntity.isVGame()) {
gameEntity.getApk().isEmpty() ? "" : gameEntity.getApk().get(0).getUrl(), entrance); v.getContext().startActivity(VDownloadManagerActivity.getIntent(v.getContext(), true));
v.getContext().startActivity(intent); } else {
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(v.getContext(),
gameEntity.getApk().get(0).getUrl(), entrance);
v.getContext().startActivity(intent);
}
break; break;
case NONE: case NONE:
Utils.toast(v.getContext(), "该游戏已关闭下载"); Utils.toast(v.getContext(), "该游戏已关闭下载");
@ -152,50 +392,37 @@ public class BindingAdapters {
boolean isInstalled = PackageUtils.isInstalledFromAllPackage(v.getContext(), gameEntity.getSimulator().getApk().getPackageName()); boolean isInstalled = PackageUtils.isInstalledFromAllPackage(v.getContext(), gameEntity.getSimulator().getApk().getPackageName());
if (downloadEntity != null && SimulatorGameManager.isSimulatorGame(gameEntity) && !isInstalled) { if (downloadEntity != null && SimulatorGameManager.isSimulatorGame(gameEntity) && !isInstalled) {
SimulatorDownloadManager.getInstance().showDownloadDialog(v.getContext(), gameEntity.getSimulator(), SimulatorDownloadManager.getInstance().showDownloadDialog(v.getContext(), gameEntity.getSimulator(),
SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.getId(), gameEntity.getName(), gameEntity.getCategoryChinese(), null); SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.getId(), gameEntity.getName(), null);
return; return;
} }
} }
DownloadChainBuilder builder = new DownloadChainBuilder(); ChainBuilder builder = new ChainBuilder();
builder.addHandler(new UnsupportedFeatureHandler());
builder.addHandler(new GamePermissionHandler());
builder.addHandler(new CheckStoragePermissionHandler());
builder.addHandler(new ValidateVSpaceHandler()); builder.addHandler(new ValidateVSpaceHandler());
builder.addHandler(new GamePermissionHandler());
builder.addHandler(new BrowserInstallHandler()); builder.addHandler(new BrowserInstallHandler());
builder.addHandler(new PackageCheckHandler()); builder.addHandler(new PackageCheckHandler());
builder.addHandler(new DownloadDialogHelperHandler()); builder.addHandler(new DownloadDialogHelperHandler());
builder.addHandler(new CertificationHandler());
builder.addHandler(new VersionNumberHandler()); builder.addHandler(new VersionNumberHandler());
builder.addHandler(new LandPageAddressHandler());
builder.addHandler(new OverseaDownloadHandler()); builder.addHandler(new OverseaDownloadHandler());
builder.addHandler(new CheckDownloadHandler()); builder.addHandler(new CheckDownloadHandler());
builder.setProcessEndCallback(gameEntity.getId(), (asVGame, isSubscribe) -> { builder.setProcessEndCallback(o -> {
download(v.getContext(), download(progressBar, gameEntity, traceEvent, (boolean) o, entrance, location);
progressBar,
gameEntity,
traceEvent,
asVGame,
(boolean) isSubscribe,
entrance,
location);
return null; return null;
}); });
final DownloadChainHandler chainHandler = builder.buildHandlerChain(); final ChainHandler chainHandler = builder.buildHandlerChain();
if (chainHandler != null) { if (chainHandler != null) {
chainHandler.handleRequest( chainHandler.handleRequest(v.getContext(), gameEntity);
v.getContext(),
gameEntity,
GameUtils.shouldPerformAsVGame(gameEntity)
);
} }
} else { } else {
DownloadChainBuilder builder = new DownloadChainBuilder(); ChainBuilder builder = new ChainBuilder();
builder.addHandler(new UnsupportedFeatureHandler());
builder.addHandler(new GamePermissionHandler()); builder.addHandler(new GamePermissionHandler());
builder.addHandler(new CertificationHandler());
builder.addHandler(new VersionNumberHandler()); builder.addHandler(new VersionNumberHandler());
builder.setProcessEndCallback(gameEntity.getId(), (asVGame, isSubscribe) -> { builder.setProcessEndCallback(o -> {
DownloadDialog.showDownloadDialog( DownloadDialog.showDownloadDialog(
v.getContext(), v.getContext(),
gameEntity, gameEntity,
@ -204,13 +431,9 @@ public class BindingAdapters {
location + ":" + gameEntity.getName()); location + ":" + gameEntity.getName());
return null; return null;
}); });
final DownloadChainHandler chainHandler = builder.buildHandlerChain(); final ChainHandler chainHandler = builder.buildHandlerChain();
if (chainHandler != null) { if (chainHandler != null) {
chainHandler.handleRequest( chainHandler.handleRequest(v.getContext(), gameEntity);
v.getContext(),
gameEntity,
GameUtils.shouldPerformAsVGame(gameEntity)
);
} }
} }
} }
@ -219,18 +442,11 @@ public class BindingAdapters {
if (gameEntity.getApk().size() == 1) { if (gameEntity.getApk().size() == 1) {
//启动模拟器游戏 //启动模拟器游戏
if (SimulatorGameManager.isSimulatorGame(gameEntity)) { if (SimulatorGameManager.isSimulatorGame(gameEntity)) {
DownloadEntity downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(gameEntity.getApk().isEmpty() ? "" : gameEntity.getApk().get(0).getUrl()); DownloadEntity downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(gameEntity.getApk().get(0).getUrl());
if (downloadEntity != null) { if (downloadEntity != null) {
File file = new File(downloadEntity.getPath()); File file = new File(downloadEntity.getPath());
if (!file.exists()) { if (!file.exists()) {
download(v.getContext(), download(progressBar, gameEntity, traceEvent, false, entrance, location);
progressBar,
gameEntity,
traceEvent,
false,
false,
entrance,
location);
return; return;
} }
@ -239,7 +455,12 @@ public class BindingAdapters {
return; return;
} }
PackageLauncher.launch(v.getContext(), gameEntity, null); if (gameEntity.isVGame()) {
VHelper.installOrLaunch((AppCompatActivity) v.getContext(), gameEntity.getApk().get(0).getPackageName());
return;
}
PackageUtils.launchApplicationByPackageName(v.getContext(), gameEntity.getApk().get(0).getPackageName());
} else { } else {
DownloadDialog.showDownloadDialog( DownloadDialog.showDownloadDialog(
v.getContext(), v.getContext(),
@ -252,34 +473,23 @@ public class BindingAdapters {
case INSTALL_PLUGIN: case INSTALL_PLUGIN:
case INSTALL_NORMAL: case INSTALL_NORMAL:
if (gameEntity.getApk().size() == 1) { if (gameEntity.getApk().size() == 1) {
NewFlatLogUtils.INSTANCE.logGameInstall(
gameEntity.getId(),
gameEntity.getName() != null ? gameEntity.getName() : "",
"主动安装"
);
SensorsBridge.trackInstallGameClick(
gameEntity.getId(),
gameEntity.getName() != null ? gameEntity.getName() : "",
"主动安装"
);
DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity); DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity);
String packageName = gameEntity.getApk().get(0).getPackageName();
if (gameEntity.isVGame()) {
VHelper.installOrLaunch(v.getContext(), packageName);
return;
}
if (downloadEntity != null) { if (downloadEntity != null) {
if (ExtensionsKt.isLocalDownloadInDualDownloadMode(downloadEntity)) { PackageInstaller.install(v.getContext(), downloadEntity);
PackageInstaller.install(v.getContext(), downloadEntity);
} else {
VHelper.installOrLaunch(v.getContext(), gameEntity, null);
}
} }
} }
break; break;
case RESERVABLE: case RESERVABLE:
GamePermissionDialogFragment.show((AppCompatActivity) v.getContext(), gameEntity, gameEntity.getInfo(), () -> { GamePermissionDialogFragment.show((AppCompatActivity) v.getContext(), gameEntity, gameEntity.getInfo(), () -> {
CheckLoginUtils.checkLogin(progressBar.getContext(), "", () -> { CheckLoginUtils.checkLogin(progressBar.getContext(), "", () -> {
ReservationHelper.reserve(v.getContext(), gameEntity, sourceEntrance, () -> { ReservationHelper.reserve(v.getContext(), gameEntity.getId(), () -> {
LogUtils.logReservation(gameEntity, traceEvent); LogUtils.logReservation(gameEntity, traceEvent);
updateReservation(progressBar, gameEntity); updateReservation(progressBar, gameEntity);
}); });
@ -294,7 +504,7 @@ public class BindingAdapters {
}); });
}); });
} else { } else {
ReservationHelper.showCancelReservationDialog(progressBar.getContext(),gameEntity, () -> { ReservationHelper.showCancelReservationDialog(progressBar.getContext(), () -> {
ReservationHelper.cancelReservation(gameEntity, () -> { ReservationHelper.cancelReservation(gameEntity, () -> {
updateReservation(progressBar, gameEntity); updateReservation(progressBar, gameEntity);
}); });
@ -358,7 +568,7 @@ public class BindingAdapters {
} }
} else { } else {
String status = GameUtils.getDownloadBtnText(progressBar.getContext(), gameEntity, true, false, PluginLocation.only_game); String status = GameUtils.getDownloadBtnText(progressBar.getContext(), gameEntity, PluginLocation.only_game);
switch (status) { switch (status) {
case "插件化": case "插件化":
progressBar.setButtonStyle(DownloadButton.ButtonStyle.PLUGIN); progressBar.setButtonStyle(DownloadButton.ButtonStyle.PLUGIN);
@ -384,20 +594,18 @@ public class BindingAdapters {
case pause: case pause:
case timeout: case timeout:
case neterror: case neterror:
case diskisfull:
case diskioerror:
case waiting: case waiting:
progressBar.setText(com.gh.gamecenter.feature.R.string.downloading); progressBar.setText(R.string.downloading);
if (downloadEntity.isPluggable() && PackagesManager.isInstalled(downloadEntity.getPackageName())) { if (downloadEntity.isPluggable() && PackagesManager.INSTANCE.isInstalled(downloadEntity.getPackageName())) {
progressBar.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_PLUGIN); progressBar.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_PLUGIN);
} else { } else {
progressBar.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_NORMAL); progressBar.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_NORMAL);
} }
break; break;
case done: case done:
progressBar.setText(com.gh.gamecenter.feature.R.string.install); progressBar.setText(R.string.install);
if (downloadEntity.isPluggable() if (downloadEntity.isPluggable()
&& PackagesManager.isInstalled(downloadEntity.getPackageName())) { && PackagesManager.INSTANCE.isInstalled(downloadEntity.getPackageName())) {
progressBar.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_PLUGIN); progressBar.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_PLUGIN);
} else { } else {
progressBar.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL); progressBar.setButtonStyle(DownloadButton.ButtonStyle.INSTALL_NORMAL);
@ -430,6 +638,24 @@ public class BindingAdapters {
} }
} }
/*private static void download(DownloadProgressBar progressBar, GameEntity gameEntity, ExposureEvent traceEvent, @Nullable String entrance, @Nullable String location, View v) {
if (gameEntity.getApk().size() == 1) {
ApkEntity apk = gameEntity.getApk().get(0);
DownloadDialogHelper.findAvailableDialogAndShow(
v.getContext(),
gameEntity,
apk,
() -> {
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
});
} else {
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
entrance, location + gameEntity.getName(), traceEvent);
}
}*/
private static void updateReservation(DownloadButton progressBar, GameEntity gameEntity) { private static void updateReservation(DownloadButton progressBar, GameEntity gameEntity) {
// 显示预约 // 显示预约
if (gameEntity.isReservable()) { if (gameEntity.isReservable()) {
@ -445,39 +671,45 @@ public class BindingAdapters {
// 开始下载 // 开始下载
private static void download(Context context, private static void download(DownloadButton progressBar,
DownloadButton progressBar,
GameEntity gameEntity, GameEntity gameEntity,
ExposureEvent traceEvent, ExposureEvent traceEvent,
boolean asVGame,
boolean isSubscribe, boolean isSubscribe,
String entrance, String entrance,
String location) { String location) {
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) { String str = progressBar.getText().toString();
ToastUtils.toast(context.getString(R.string.unsupported_browser_install_hint)); String method;
if (str.contains("更新")) {
method = "更新";
} else if (str.contains("插件化")) {
method = "插件化";
} else {
method = progressBar.getContext().getString(R.string.download);
} }
String buttonText = progressBar.getText(); ApkEntity apkEntity = gameEntity.getApk().get(0);
ApkEntity apkEntity = CollectionsKt.firstOrNull(gameEntity.getApk()); String msg = FileUtils.isCanDownload(progressBar.getContext(), apkEntity.getSize());
String msg = FileUtils.isCanDownload(progressBar.getContext(), apkEntity == null ? "" : apkEntity.getSize()); if (TextUtils.isEmpty(msg)) {
if (apkEntity != null && TextUtils.isEmpty(msg)) {
DownloadManager.createDownload(progressBar.getContext(), DownloadManager.createDownload(progressBar.getContext(),
apkEntity, apkEntity,
gameEntity, gameEntity,
asVGame, method,
gameEntity.isDualBtnModeEnabled(),
entrance, entrance,
location + gameEntity.getName(), location + gameEntity.getName(),
isSubscribe, isSubscribe,
traceEvent); traceEvent);
progressBar.setProgress(0); progressBar.setProgress(0);
progressBar.setButtonStyle(buttonText.contains("插件化") ? progressBar.setButtonStyle("插件化".equals(method) ?
DownloadButton.ButtonStyle.DOWNLOADING_PLUGIN : DownloadButton.ButtonStyle.DOWNLOADING_NORMAL); DownloadButton.ButtonStyle.DOWNLOADING_PLUGIN : DownloadButton.ButtonStyle.DOWNLOADING_NORMAL);
} else { } else {
Utils.toast(progressBar.getContext(), msg); Utils.toast(progressBar.getContext(), msg);
} }
} }
public static void setGameLabelList(LinearLayout layout, List<TagStyleEntity> tagStyle) {
GameViewUtils.setLabelList(layout.getContext(), layout, tagStyle);
}
// 包含测试开服标签 // 包含测试开服标签
public static void setGameTags(LinearLayout layout, GameEntity gameEntity) { public static void setGameTags(LinearLayout layout, GameEntity gameEntity) {
try { try {
@ -547,26 +779,57 @@ public class BindingAdapters {
} }
} }
public static void setGameName(TextView view, GameEntity game, boolean isShowPlatform) { public static void isRefreshing(SwipeRefreshLayout layout, LoadStatus status) {
if (status != LoadStatus.INIT_LOADING && status != LoadStatus.LIST_LOADING) {
layout.setRefreshing(false);
}
}
public static void setGameName(NoEllipsizeSpaceTextView view, GameEntity game, boolean isShowPlatform, @Nullable Boolean isShowSuffix) {
if (isShowSuffix == null) isShowSuffix = true; // 默认显示
String gameName; String gameName;
if (isShowPlatform && game.getApk().size() > 0) { if (isShowPlatform && game.getApk().size() > 0) {
gameName = String.format("%s - %s", game.getName(), gameName = String.format("%s - %s", !isShowSuffix ? game.getNameWithoutSuffix() : game.getName(),
PlatformUtils.getInstance(view.getContext()).getPlatformName( PlatformUtils.getInstance(view.getContext()).getPlatformName(
game.getApk().get(0).getPlatform())); game.getApk().get(0).getPlatform()));
if (!gameName.equals((String) view.getTag(com.gh.gamecenter.common.R.string.tag_game_name_id))) { if (!gameName.equals((String) view.getTag(R.string.tag_game_name_id))) {
view.setText(gameName); view.setText(gameName);
view.setTag(com.gh.gamecenter.common.R.string.tag_game_name_id, gameName); view.setTag(R.string.tag_game_name_id, gameName);
} }
} else { } else {
gameName = game.getName(); gameName = !isShowSuffix ? game.getNameWithoutSuffix() : game.getName();
if (gameName != null && !gameName.equals((String) view.getTag(com.gh.gamecenter.common.R.string.tag_game_name_id))) { if (gameName != null && !gameName.equals((String) view.getTag(R.string.tag_game_name_id))) {
view.setText(gameName); view.setText(gameName);
view.setTag(com.gh.gamecenter.common.R.string.tag_game_name_id, gameName); view.setTag(R.string.tag_game_name_id, gameName);
} }
} }
} }
public static void setCommunityImage(SimpleDraweeView imageView, List<String> images, List<CommunityVideoEntity> videos) {
if (videos.size() > 0) {
CommunityVideoEntity videoEntity = videos.get(0);
ImageUtils.display(imageView, videoEntity.getPoster());
imageView.setVisibility(View.VISIBLE);
} else if (images.size() > 0) {
imageView.setVisibility(View.VISIBLE);
ImageUtils.display(imageView, images.get(0));
} else {
imageView.setVisibility(View.GONE);
}
}
public static void setCommunityVideoDuration(TextView mVideoDuration, List<CommunityVideoEntity> videos) {
if (videos != null && videos.size() > 0) {
CommunityVideoEntity videoEntity = videos.get(0);
mVideoDuration.setBackground(DrawableView.getOvalDrawable(R.color.black_alpha_50, 999F));
mVideoDuration.setText(videoEntity.getDuration());
mVideoDuration.setVisibility(View.VISIBLE);
} else {
mVideoDuration.setVisibility(View.GONE);
}
}
public static void setGameTags(TextView view, List<TagStyleEntity> tags, int maxTags) { public static void setGameTags(TextView view, List<TagStyleEntity> tags, int maxTags) {
if (tags == null) { if (tags == null) {
view.setText(""); view.setText("");
@ -594,4 +857,16 @@ public class BindingAdapters {
} }
view.setText(span); view.setText(span);
} }
public static void setVideoData(TextView view, int count) {
if (count > 0) {
ExtensionsKt.setDrawableStart(view, ContextCompat.getDrawable(view.getContext(), R.drawable.ic_video_data_up), null, null);
view.setTextColor(ContextCompat.getColor(view.getContext(), R.color.text_EA3333));
view.setText(count + "");
} else {
ExtensionsKt.removeDrawable(view);
view.setTextColor(ContextCompat.getColor(view.getContext(), R.color.text_subtitleDesc));
view.setText("-");
}
}
} }

View File

@ -7,6 +7,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.gh.common.util.DirectUtils import com.gh.common.util.DirectUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
import com.gh.gamecenter.common.constant.EntranceConsts import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.dip2px import com.gh.gamecenter.common.utils.dip2px
@ -48,7 +49,7 @@ class ApplyModeratorDialogFragment : BaseDialogFragment() {
requireContext(), requireContext(),
startText.length, startText.length,
startText.length + mGroupNumber.length, startText.length + mGroupNumber.length,
com.gh.gamecenter.common.R.color.text_theme, R.color.theme_font,
true true
) { ) {
DirectUtils.directToQqGroup( DirectUtils.directToQqGroup(

View File

@ -0,0 +1,204 @@
package com.gh.common.dialog
import android.annotation.SuppressLint
import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.graphics.Paint
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.CheckBox
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.gh.gamecenter.common.avoidcallback.AvoidOnResultManager
import com.gh.gamecenter.common.avoidcallback.Callback
import com.gh.gamecenter.common.constant.Constants
import com.gh.common.util.*
import com.gh.gamecenter.R
import com.gh.gamecenter.ShellActivity
import com.gh.gamecenter.common.callback.ConfirmListener
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.feature.entity.AuthDialogEntity
import com.gh.gamecenter.feature.entity.AuthDialogLevel
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.login.user.UserManager
import com.google.gson.reflect.TypeToken
import com.halo.assistant.fragment.user.UserInfoEditFragment
import com.lightgame.utils.AppManager
class CertificationDialog(
context: Context,
private val authDialogEntity: AuthDialogEntity,
val gameId: String,
val listener: ConfirmListener
) :
Dialog(context, R.style.GhAlertDialog) {
private lateinit var view: View
private lateinit var detailedDesTv: TextView
private lateinit var noRemindAgainCb: CheckBox
private lateinit var actionLeftTv: TextView
private lateinit var actionRightTv: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
view = LayoutInflater.from(context).inflate(R.layout.dialog_sertification, null)
setContentView(view)
detailedDesTv = view.findViewById(R.id.detailedDesTv)
noRemindAgainCb = view.findViewById(R.id.noRemindAgainCb)
actionLeftTv = view.findViewById(R.id.actionLeftTv)
actionRightTv = view.findViewById(R.id.actionRightTv)
detailedDesTv.paint.flags = Paint.UNDERLINE_TEXT_FLAG
detailedDesTv.paint.isAntiAlias = true
detailedDesTv.setOnClickListener {
DirectUtils.directToWebView(context, authDialogEntity.link)
}
when (authDialogEntity.level) {
AuthDialogLevel.MUST_PASS.value -> {
actionLeftTv.text = "暂不下载"
actionRightTv.text = "去实名认证"
noRemindAgainCb.visibility = View.GONE
actionLeftTv.setOnClickListener {
dismiss()
}
actionRightTv.setOnClickListener {
if (UserManager.getInstance().isLoggedIn) {
gotoAuthPage()
} else {
gotoLoginPage()
}
}
}
AuthDialogLevel.ALWAYS_HINT.value -> {
actionLeftTv.text = "去实名认证"
actionRightTv.text = "继续下载"
noRemindAgainCb.visibility = View.GONE
actionLeftTv.setOnClickListener {
if (UserManager.getInstance().isLoggedIn) {
gotoAuthPage()
} else {
gotoLoginPage()
}
}
actionRightTv.setOnClickListener {
listener.onConfirm()
dismiss()
}
}
AuthDialogLevel.OPTIONAL_HINT.value -> {
actionLeftTv.text = "去实名认证"
actionRightTv.text = "继续下载"
noRemindAgainCb.visibility = View.VISIBLE
actionLeftTv.setOnClickListener {
if (noRemindAgainCb.isChecked) {
SPUtils.setBoolean(gameId, true)
}
if (UserManager.getInstance().isLoggedIn) {
gotoAuthPage()
} else {
gotoLoginPage()
}
}
actionRightTv.setOnClickListener {
if (noRemindAgainCb.isChecked) {
SPUtils.getBoolean(gameId, true)
}
listener.onConfirm()
dismiss()
}
}
}
}
//跳转登录页面
private fun gotoLoginPage() {
val currentActivity = AppManager.getInstance().currentActivity() ?: return
CheckLoginUtils.checkLogin(
currentActivity as AppCompatActivity,
null, true, "实名认证弹窗"
) {
if (UserManager.getInstance().isAuth) {
listener.onConfirm()
dismiss()
}
}
}
//跳转实名认证页面
private fun gotoAuthPage() {
val currentActivity = AppManager.getInstance().currentActivity() ?: return
AvoidOnResultManager.getInstance(currentActivity as AppCompatActivity)
.startForResult(
ShellActivity.getIntent(
context,
ShellActivity.Type.REAL_NAME_INFO,
).apply {
putExtra(EntranceConsts.KEY_GAME_ID, gameId)
}, object : Callback {
override fun onActivityResult(resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK && data != null) {
val isAuthSuccess =
data.getBooleanExtra(UserInfoEditFragment.AUTH_SUCCESS, false)
if (isAuthSuccess) {
listener.onConfirm()
dismiss()
}
}
}
})
}
companion object {
@JvmStatic
fun showCertificationDialog(context: Context, game: GameEntity, listener: ConfirmListener) {
//1.先判断是否登录 是执行2 否执行3
//2.判断是否实名认证 是终止 否执行3
//3.判断是否需要弹出认证弹窗接口
if (UserManager.getInstance().isLoggedIn) {
if (UserManager.getInstance().isAuth) {//已实名认证
listener.onConfirm()
} else {
authDialog(context, game, listener)
}
} else {
authDialog(context, game, listener)
}
}
@SuppressLint("CheckResult")
private fun authDialog(context: Context, game: GameEntity, listener: ConfirmListener) {
var authDialog: AuthDialogEntity? = null
if (game.authDialog != null) {
authDialog = game.authDialog
}
if (authDialog == null) {
val datas = SPUtils.getString(Constants.SP_AUTH_DIALOG)
val type = object : TypeToken<List<AuthDialogEntity>>() {}.type
val authDialogs = GsonUtils.gson.fromJson<List<AuthDialogEntity>>(datas, type)
if (!authDialogs.isNullOrEmpty()) {
authDialog = authDialogs.find { it.gameCategory == game.category }
}
}
val isCloseAuthDialog = SPUtils.getBoolean(game.id, false)
if (authDialog != null && (authDialog.level != AuthDialogLevel.OPTIONAL_HINT.value || !isCloseAuthDialog)) {
val dialog = CertificationDialog(context, authDialog, game.id, listener)
dialog.show()
} else {
listener.onConfirm()
}
}
}
}

View File

@ -40,7 +40,7 @@ import java.lang.ref.WeakReference
* 设备提醒弹窗 * 设备提醒弹窗
*/ */
class DeviceRemindDialog(context: Context, val entity: DeviceDialogEntity, val gameEntity: GameEntity) : class DeviceRemindDialog(context: Context, val entity: DeviceDialogEntity, val gameEntity: GameEntity) :
Dialog(context, com.gh.gamecenter.common.R.style.GhAlertDialog) { Dialog(context, R.style.GhAlertDialog) {
private val mBinding: DialogDeviceRemindBinding by lazy { DialogDeviceRemindBinding.inflate(layoutInflater) } private val mBinding: DialogDeviceRemindBinding by lazy { DialogDeviceRemindBinding.inflate(layoutInflater) }
private var currentPage = 0 private var currentPage = 0
private var mSlideLooperInterval = 3000L private var mSlideLooperInterval = 3000L
@ -136,13 +136,13 @@ class DeviceRemindDialog(context: Context, val entity: DeviceDialogEntity, val g
val isFirst = SPUtils.getBoolean(Constants.SP_FIRST_DEVICE_REMIND, false) val isFirst = SPUtils.getBoolean(Constants.SP_FIRST_DEVICE_REMIND, false)
if (!isFirst) { if (!isFirst) {
mBinding.cancelTv.isEnabled = false mBinding.cancelTv.isEnabled = false
mBinding.cancelTv.background = ContextCompat.getDrawable(context, com.gh.gamecenter.common.R.drawable.button_round_f5f5f5) mBinding.cancelTv.background = ContextCompat.getDrawable(context, R.drawable.button_round_f5f5f5)
disposable = countDownTimer(3) { finish, time -> disposable = countDownTimer(3) { finish, time ->
if (finish) { if (finish) {
mBinding.cancelTv.isEnabled = true mBinding.cancelTv.isEnabled = true
mBinding.cancelTv.background = ContextCompat.getDrawable(context, com.gh.gamecenter.common.R.drawable.button_blue_oval) mBinding.cancelTv.background = ContextCompat.getDrawable(context, R.drawable.button_blue_oval)
mBinding.cancelTv.text = "我知道了" mBinding.cancelTv.text = "我知道了"
mBinding.cancelTv.setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.white)) mBinding.cancelTv.setTextColor(ContextCompat.getColor(context, R.color.white))
} else { } else {
mBinding.cancelTv.text = "我知道了(${time}S)" mBinding.cancelTv.text = "我知道了(${time}S)"
} }
@ -153,8 +153,8 @@ class DeviceRemindDialog(context: Context, val entity: DeviceDialogEntity, val g
mBinding.noRemindAgainCb.visibility = View.VISIBLE mBinding.noRemindAgainCb.visibility = View.VISIBLE
mBinding.cancelTv.text = "我知道了" mBinding.cancelTv.text = "我知道了"
mBinding.cancelTv.isEnabled = true mBinding.cancelTv.isEnabled = true
mBinding.cancelTv.setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.white)) mBinding.cancelTv.setTextColor(ContextCompat.getColor(context, R.color.white))
mBinding.cancelTv.background = ContextCompat.getDrawable(context, com.gh.gamecenter.common.R.drawable.button_blue_oval) mBinding.cancelTv.background = ContextCompat.getDrawable(context, R.drawable.button_blue_oval)
} }
mBinding.cancelTv.setOnClickListener { mBinding.cancelTv.setOnClickListener {
SPUtils.setBoolean(Constants.SP_NO_REMIND_AGAIN, mBinding.noRemindAgainCb.isChecked) SPUtils.setBoolean(Constants.SP_NO_REMIND_AGAIN, mBinding.noRemindAgainCb.isChecked)

View File

@ -14,6 +14,7 @@ import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
import com.gh.common.util.DirectUtils import com.gh.common.util.DirectUtils
import com.gh.gamecenter.common.utils.dip2px import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.toColor import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.R
import com.gh.gamecenter.databinding.DialogGameOffServiceBinding import com.gh.gamecenter.databinding.DialogGameOffServiceBinding
import com.gh.gamecenter.feature.entity.GameEntity import com.gh.gamecenter.feature.entity.GameEntity
@ -22,7 +23,6 @@ class GameOffServiceDialogFragment : BaseDialogFragment() {
private var mDialog: GameEntity.Dialog? = null private var mDialog: GameEntity.Dialog? = null
private var mBinding: DialogGameOffServiceBinding? = null private var mBinding: DialogGameOffServiceBinding? = null
private var mCallback: (() -> Unit)? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -44,7 +44,6 @@ class GameOffServiceDialogFragment : BaseDialogFragment() {
titleTv.text = title titleTv.text = title
contentTv.text = HtmlCompat.fromHtml(content, HtmlCompat.FROM_HTML_MODE_LEGACY) contentTv.text = HtmlCompat.fromHtml(content, HtmlCompat.FROM_HTML_MODE_LEGACY)
okTv.setOnClickListener { okTv.setOnClickListener {
mCallback?.invoke()
dismissAllowingStateLoss() dismissAllowingStateLoss()
} }
@ -61,10 +60,11 @@ class GameOffServiceDialogFragment : BaseDialogFragment() {
if (index == notEmptySite.size - 1) bottomMargin = 8F.dip2px() if (index == notEmptySite.size - 1) bottomMargin = 8F.dip2px()
} }
siteTv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14F) siteTv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14F)
siteTv.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(requireContext())) siteTv.setTextColor(R.color.theme_font.toColor(requireContext()))
siteTv.text = site.text siteTv.text = site.text
siteTv.paintFlags = siteTv.paintFlags or Paint.UNDERLINE_TEXT_FLAG siteTv.paintFlags = siteTv.paintFlags or Paint.UNDERLINE_TEXT_FLAG
siteTv.setOnClickListener { siteTv.setOnClickListener {
// MtaHelper.onEvent("游戏下载状态按钮", getKey(), site.text)
DirectUtils.directToWebView(requireContext(), site.url, "(关闭下载弹窗)") DirectUtils.directToWebView(requireContext(), site.url, "(关闭下载弹窗)")
dismissAllowingStateLoss() dismissAllowingStateLoss()
} }
@ -83,13 +83,11 @@ class GameOffServiceDialogFragment : BaseDialogFragment() {
const val KEY_DIALOG = "dialog" const val KEY_DIALOG = "dialog"
@JvmStatic @JvmStatic
fun getInstance(dialog: GameEntity.Dialog, callback: (() -> Unit)? = null) = fun getInstance(dialog: GameEntity.Dialog) = GameOffServiceDialogFragment().apply {
GameOffServiceDialogFragment().apply { arguments = Bundle().apply {
arguments = Bundle().apply { putParcelable(KEY_DIALOG, dialog)
putParcelable(KEY_DIALOG, dialog)
}
mCallback = callback
} }
}
} }
} }

View File

@ -1,7 +1,6 @@
package com.gh.common.dialog package com.gh.common.dialog
import android.app.Activity.RESULT_OK import android.app.Activity.RESULT_OK
import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
@ -14,15 +13,17 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.FragmentTransaction
import com.airbnb.lottie.LottieAnimationView import com.airbnb.lottie.LottieAnimationView
import com.gh.common.constant.Config import com.gh.common.constant.Config
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.xapk.XapkInstaller import com.gh.common.xapk.XapkInstaller
import com.gh.gamecenter.R import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
import com.gh.gamecenter.common.constant.Constants import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.* import com.gh.gamecenter.common.utils.PermissionHelper
import com.gh.gamecenter.common.utils.PermissionHelper.INSTALL_PERMISSION_CODE import com.gh.gamecenter.common.utils.PermissionHelper.INSTALL_PERMISSION_CODE
import com.gh.gamecenter.common.utils.getExtension
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.core.utils.SPUtils import com.gh.gamecenter.core.utils.SPUtils
import com.lightgame.download.DownloadEntity import com.lightgame.download.DownloadEntity
import com.lightgame.utils.Utils
import kotlin.random.Random import kotlin.random.Random
class InstallPermissionDialogFragment : BaseDialogFragment() { class InstallPermissionDialogFragment : BaseDialogFragment() {
@ -30,13 +31,8 @@ class InstallPermissionDialogFragment : BaseDialogFragment() {
lateinit var mView: View lateinit var mView: View
var isXapk = false var isXapk = false
var url: String = "" var url: String = ""
var gameId: String = ""
var gameName: String = ""
var gameType: String = ""
var mCallBack: ((isFromPermissionGrantedCallback: Boolean) -> Unit)? = null var mCallBack: ((isFromPermissionGrantedCallback: Boolean) -> Unit)? = null
private var dismissByTouchInside = false
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mView = inflater.inflate(R.layout.dialog_install_permission, null, false) mView = inflater.inflate(R.layout.dialog_install_permission, null, false)
return mView return mView
@ -54,14 +50,6 @@ class InstallPermissionDialogFragment : BaseDialogFragment() {
switchLottie.setAnimation("lottie/install_permission_switch.json") switchLottie.setAnimation("lottie/install_permission_switch.json")
switchLottie.playAnimation() switchLottie.playAnimation()
if (isXapk) NewFlatLogUtils.logXApkInstallPermissionDialogShowed(gameId, gameName)
SensorsBridge.trackInstallPermissionDialogShow(
gameId = gameId,
gameName = gameName,
gameType = gameType
)
val randomNumber = if (isXapk) 1 else Random.nextInt(2) val randomNumber = if (isXapk) 1 else Random.nextInt(2)
closeTv.goneIf(randomNumber == 0) closeTv.goneIf(randomNumber == 0)
closeIv.goneIf(randomNumber != 0) closeIv.goneIf(randomNumber != 0)
@ -71,38 +59,15 @@ class InstallPermissionDialogFragment : BaseDialogFragment() {
} }
closeTv.setOnClickListener { closeTv.setOnClickListener {
dismissByTouchInside = true
if (isXapk) { if (isXapk) {
NewFlatLogUtils.logXApkInstallPermissionDialogClick("尝试解压", false, gameId, gameName)
mCallBack?.invoke(false) mCallBack?.invoke(false)
} }
SensorsBridge.trackInstallPermissionDialogClick(
buttonName = "尝试解压",
gameId = gameId,
gameName = gameName,
gameType = gameType
)
dismiss() dismiss()
} }
closeIv.setOnClickListener { closeIv.setOnClickListener {
dismissByTouchInside = true
if (isXapk) NewFlatLogUtils.logXApkInstallPermissionDialogClick("关闭", false, gameId, gameName)
SensorsBridge.trackInstallPermissionDialogClick(
buttonName = "关闭",
gameId = gameId,
gameName = gameName,
gameType = gameType
)
dismiss() dismiss()
} }
activateTv.setOnClickListener { activateTv.setOnClickListener {
NewFlatLogUtils.logXApkInstallPermissionDialogClick("立即开启", false, gameId, gameName)
SensorsBridge.trackInstallPermissionDialogClick(
buttonName = "立即开启",
gameId = gameId,
gameName = gameName,
gameType = gameType
)
PermissionHelper.toInstallPermissionSetting(requireActivity()) PermissionHelper.toInstallPermissionSetting(requireActivity())
if (isXapk) { if (isXapk) {
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, requireActivity().javaClass.name) SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, requireActivity().javaClass.name)
@ -111,25 +76,9 @@ class InstallPermissionDialogFragment : BaseDialogFragment() {
} }
} }
override fun onDismiss(dialog: DialogInterface) {
if (!dismissByTouchInside) {
SensorsBridge.trackInstallPermissionDialogClick(
buttonName = "关闭弹窗",
gameId = gameId,
gameName = gameName,
gameType = gameType
)
}
super.onDismiss(dialog)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK && requestCode == INSTALL_PERMISSION_CODE) { if (resultCode == RESULT_OK && requestCode == INSTALL_PERMISSION_CODE) {
dismissByTouchInside = true
NewFlatLogUtils.logXApkInstallPermissionDialogClick("立即开启", true, gameId, gameName)
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "") SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "")
SPUtils.setString(Constants.SP_XAPK_URL, "") SPUtils.setString(Constants.SP_XAPK_URL, "")
@ -158,7 +107,7 @@ class InstallPermissionDialogFragment : BaseDialogFragment() {
} }
if (isXapk) { if (isXapk) {
val xapkUnzipVersions = Config.getSettings()?.permissionPopupAppliedVersions?.xapkUnzip val xapkUnzipVersions = Config.getSettings()?.permissionPopupAppliedVersions?.xapkUnzip
if (xapkUnzipVersions?.contains(Build.VERSION.SDK_INT.toString()) == false || XapkInstaller.systemHasFlaw) { if (xapkUnzipVersions?.contains(Build.VERSION.SDK_INT.toString()) == false) {
callBack?.invoke(false) callBack?.invoke(false)
return return
} }
@ -175,9 +124,6 @@ class InstallPermissionDialogFragment : BaseDialogFragment() {
installPermissionDialogFragment.mCallBack = callBack installPermissionDialogFragment.mCallBack = callBack
installPermissionDialogFragment.isXapk = isXapk installPermissionDialogFragment.isXapk = isXapk
installPermissionDialogFragment.url = downloadEntity.url installPermissionDialogFragment.url = downloadEntity.url
installPermissionDialogFragment.gameId = downloadEntity.gameId
installPermissionDialogFragment.gameName = downloadEntity.name
installPermissionDialogFragment.gameType = downloadEntity.categoryChinese
val transaction: FragmentTransaction = activity.supportFragmentManager.beginTransaction() val transaction: FragmentTransaction = activity.supportFragmentManager.beginTransaction()
transaction.show(installPermissionDialogFragment) transaction.show(installPermissionDialogFragment)
transaction.commit() transaction.commit()
@ -186,9 +132,6 @@ class InstallPermissionDialogFragment : BaseDialogFragment() {
this.mCallBack = callBack this.mCallBack = callBack
this.isXapk = isXapk this.isXapk = isXapk
this.url = downloadEntity.url this.url = downloadEntity.url
this.gameId = downloadEntity.gameId
this.gameName = downloadEntity.name
this.gameType = downloadEntity.categoryChinese
} }
installPermissionDialogFragment.show( installPermissionDialogFragment.show(
activity.supportFragmentManager, activity.supportFragmentManager,

View File

@ -76,12 +76,12 @@ class NewPrivacyPolicyDialogFragment : BaseDialogFragment() {
contentText.setSpan(object : ClickableSpan() { contentText.setSpan(object : ClickableSpan() {
override fun updateDrawState(ds: TextPaint) { override fun updateDrawState(ds: TextPaint) {
super.updateDrawState(ds) super.updateDrawState(ds)
ds.color = ContextCompat.getColor(requireContext(), com.gh.gamecenter.common.R.color.text_theme) ds.color = ContextCompat.getColor(requireContext(), R.color.theme_font)
ds.isUnderlineText = false ds.isUnderlineText = false
} }
override fun onClick(widget: View) { override fun onClick(widget: View) {
val privacyPolicyUrl = requireContext().getString(com.gh.gamecenter.common.R.string.privacy_policy_url) val privacyPolicyUrl = requireContext().getString(R.string.privacy_policy_url)
val childrenPrivacyPolicyUrl = requireContext().getString(R.string.children_policy_url) val childrenPrivacyPolicyUrl = requireContext().getString(R.string.children_policy_url)
val thirdPartySdkUrl = requireContext().getString(R.string.sdk_list_url) val thirdPartySdkUrl = requireContext().getString(R.string.sdk_list_url)
val permissionListUrl = requireContext().getString(R.string.permission_and_usage_url) val permissionListUrl = requireContext().getString(R.string.permission_and_usage_url)

View File

@ -2,7 +2,6 @@ package com.gh.common.dialog
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.content.Context import android.content.Context
import android.content.DialogInterface
import android.content.pm.PackageInfo import android.content.pm.PackageInfo
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
@ -12,16 +11,15 @@ import android.view.animation.LinearInterpolator
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.gh.common.util.DirectUtils import com.gh.common.util.DirectUtils
import com.gh.common.util.LogUtils import com.gh.common.util.LogUtils
import com.gh.common.util.PackageHelper
import com.gh.common.util.PackageUtils import com.gh.common.util.PackageUtils
import com.gh.download.DownloadManager import com.gh.download.DownloadManager
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.gamecenter.common.callback.ConfirmListener import com.gh.gamecenter.common.callback.ConfirmListener
import com.gh.gamecenter.common.constant.Constants import com.gh.gamecenter.common.constant.Constants
@ -59,12 +57,10 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
private val mDuration = 3000 private val mDuration = 3000
private var mDisposable: Disposable? = null private var mDisposable: Disposable? = null
private var mAdapter: PackageCheckAdapter? = null private var mAdapter: PackageCheckAdapter? = null
private var mAllInstalledPackages = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0) private var mAllInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
var gameEntity: GameEntity? = null var gameEntity: GameEntity? = null
var callBack: ConfirmListener? = null var callBack: ConfirmListener? = null
private var mDismissByTouchInside = false
private val dataWatcher = object : DataWatcher() { private val dataWatcher = object : DataWatcher() {
override fun onDataChanged(downloadEntity: DownloadEntity) { override fun onDataChanged(downloadEntity: DownloadEntity) {
val packageName = downloadEntity.packageName val packageName = downloadEntity.packageName
@ -94,11 +90,6 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
EventBus.getDefault().register(this) EventBus.getDefault().register(this)
gameEntity?.let { gameEntity?.let {
LogUtils.uploadPackageCheck("pkg_check_pop_click", "出现弹窗", it, "", "", "", "") LogUtils.uploadPackageCheck("pkg_check_pop_click", "出现弹窗", it, "", "", "", "")
SensorsBridge.trackPkgCheckDialogShow(
gameId = it.id,
gameName = it.name ?: "",
gameType = it.categoryChinese
)
} }
} }
@ -125,7 +116,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
requireContext(), requireContext(),
0, 0,
(link.title ?: "").length, (link.title ?: "").length,
com.gh.gamecenter.common.R.color.text_theme, R.color.theme_font,
true true
) { ) {
LogUtils.uploadPackageCheck( LogUtils.uploadPackageCheck(
@ -137,18 +128,6 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
"", "",
"" ""
) )
SensorsBridge.trackPkgCheckDialogClick(
buttonName = "点击链接",
gameId = gameEntity?.id ?: "",
gameName = gameEntity?.name ?: "",
gameType = gameEntity?.categoryChinese ?: "",
isNotPrompt = if (binding.noRemindAgainCb.isVisible) {
binding.noRemindAgainCb.isChecked
} else null,
linkId = link.link ?: "",
linkType = link.type ?: "",
linkText = link.linkText ?: ""
)
DirectUtils.directToLinkPage(requireContext(), link, "包名检测弹窗", "") DirectUtils.directToLinkPage(requireContext(), link, "包名检测弹窗", "")
}.build() }.build()
spanBuilder.append(linkSpan) spanBuilder.append(linkSpan)
@ -197,7 +176,6 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
} }
val isAllPackageInstalled = isAllPackageInstalled(mAllInstalledPackages, entity) val isAllPackageInstalled = isAllPackageInstalled(mAllInstalledPackages, entity)
if (isAllPackageInstalled) { if (isAllPackageInstalled) {
mDismissByTouchInside = true
callBack?.onConfirm() callBack?.onConfirm()
dismissAllowingStateLoss() dismissAllowingStateLoss()
} else { } else {
@ -215,15 +193,6 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
"", "",
"" ""
) )
SensorsBridge.trackPkgCheckDialogClick(
buttonName = "点击前往下载",
gameId = gameEntity?.id ?: "",
gameName = gameEntity?.name ?: "",
gameType = gameEntity?.categoryChinese ?: "",
isNotPrompt = if (binding.noRemindAgainCb.isVisible) {
binding.noRemindAgainCb.isChecked
} else null
)
DirectUtils.directToLinkPage(requireContext(), packageLink, "包名检测弹窗", "") DirectUtils.directToLinkPage(requireContext(), packageLink, "包名检测弹窗", "")
} }
} }
@ -237,19 +206,6 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
saveRecord(entity) saveRecord(entity)
LogUtils.uploadPackageCheck("pkg_check_pop_click", "不再提示", gameEntity, "", "", "", "") LogUtils.uploadPackageCheck("pkg_check_pop_click", "不再提示", gameEntity, "", "", "", "")
} }
mDismissByTouchInside = true
SensorsBridge.trackPkgCheckDialogClick(
buttonName = binding.cancelTv.text.toString(),
gameId = gameEntity?.id ?: "",
gameName = gameEntity?.name ?: "",
gameType = gameEntity?.categoryChinese ?: "",
isNotPrompt = if (binding.noRemindAgainCb.isVisible) {
binding.noRemindAgainCb.isChecked
} else null
)
dismissAllowingStateLoss() dismissAllowingStateLoss()
} }
} }
@ -284,7 +240,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
if (it >= mDuration) { if (it >= mDuration) {
mDisposable?.dispose() mDisposable?.dispose()
binding.downloadBtn.isEnabled = true binding.downloadBtn.isEnabled = true
binding.downloadBtn.background = com.gh.gamecenter.common.R.drawable.bg_notification_open_btn_style_2.toDrawable() binding.downloadBtn.background = R.drawable.bg_notification_open_btn_style_2.toDrawable()
} }
} }
val animator = ValueAnimator.ofInt(0, 100) val animator = ValueAnimator.ofInt(0, 100)
@ -325,7 +281,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
mAllInstalledPackages = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0) mAllInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
gameEntity?.packageDialog?.let { gameEntity?.packageDialog?.let {
if (isAllPackageInstalled(mAllInstalledPackages, it)) { if (isAllPackageInstalled(mAllInstalledPackages, it)) {
callBack?.onConfirm() callBack?.onConfirm()
@ -344,26 +300,11 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
DownloadManager.getInstance().removeObserver(dataWatcher) DownloadManager.getInstance().removeObserver(dataWatcher)
} }
override fun onDismiss(dialog: DialogInterface) {
if (!mDismissByTouchInside) {
SensorsBridge.trackPkgCheckDialogClick(
buttonName = "关闭弹窗",
gameId = gameEntity?.id ?: "",
gameName = gameEntity?.name ?: "",
gameType = gameEntity?.categoryChinese ?: "",
isNotPrompt = if (binding.noRemindAgainCb.isVisible) {
binding.noRemindAgainCb.isChecked
} else null
)
}
super.onDismiss(dialog)
}
//安装、卸载事件 //安装、卸载事件
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(busFour: EBPackage) { fun onEventMainThread(busFour: EBPackage) {
if (busFour.isInstalledOrUninstalled()) { if (busFour.isInstalledOrUninstalled()) {
mAllInstalledPackages = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0) mAllInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
mAdapter?.notifyDataSetChanged() mAdapter?.notifyDataSetChanged()
} }
} }
@ -391,10 +332,10 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
val isAllInstalled = checkDetectionsInstalled(mAllInstalledPackages, entity.packages) val isAllInstalled = checkDetectionsInstalled(mAllInstalledPackages, entity.packages)
if (isAllInstalled) { if (isAllInstalled) {
holder.binding.statusTv.text = "已安装" holder.binding.statusTv.text = "已安装"
holder.binding.statusTv.setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.text_theme)) holder.binding.statusTv.setTextColor(ContextCompat.getColor(context, R.color.theme_font))
} else { } else {
holder.binding.statusTv.text = "未安装" holder.binding.statusTv.text = "未安装"
holder.binding.statusTv.setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.secondary_red)) holder.binding.statusTv.setTextColor(ContextCompat.getColor(context, R.color.theme_red))
} }
holder.binding.statusTv.visibility = View.VISIBLE holder.binding.statusTv.visibility = View.VISIBLE
} else { } else {
@ -416,7 +357,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
return return
} }
val allInstalledPackages = PackageHelper.getInstalledPackageNameList(HaloApp.getInstance().application, 0) val allInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
if (isAllPackageInstalled(allInstalledPackages, packageDialogEntity)) { if (isAllPackageInstalled(allInstalledPackages, packageDialogEntity)) {
callBack.onConfirm() callBack.onConfirm()
return return
@ -453,12 +394,12 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
} }
private fun checkDetectionsInstalled( private fun checkDetectionsInstalled(
allInstalledPackages: List<String>, allInstalledPackages: List<PackageInfo>,
packages: ArrayList<String> packages: ArrayList<String>
): Boolean { ): Boolean {
var isPackagesInstalled = false var isPackagesInstalled = false
packages.forEach { packageName -> packages.forEach { packageName ->
val isInstalled = allInstalledPackages.find { it == packageName } != null val isInstalled = allInstalledPackages.find { it.packageName == packageName } != null
if (isInstalled) { if (isInstalled) {
isPackagesInstalled = true isPackagesInstalled = true
return@forEach return@forEach
@ -469,7 +410,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
fun isAllPackageInstalled( fun isAllPackageInstalled(
allInstalledPackages: List<String>, allInstalledPackages: List<PackageInfo>,
packageDialogEntity: PackageDialogEntity packageDialogEntity: PackageDialogEntity
): Boolean { ): Boolean {
var isAllInstalled = true var isAllInstalled = true

View File

@ -12,6 +12,7 @@ import android.view.*
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.FragmentTransaction
import com.gh.gamecenter.R
import com.gh.gamecenter.WebActivity import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
import com.gh.gamecenter.common.constant.Constants import com.gh.gamecenter.common.constant.Constants
@ -28,15 +29,6 @@ class PrivacyPolicyDialogFragment : BaseDialogFragment() {
private var mCallBack: ((isSuccess: Boolean) -> Unit)? = null private var mCallBack: ((isSuccess: Boolean) -> Unit)? = null
private val mBinding by lazy { DialogPrivacyProtocolBinding.inflate(layoutInflater) } private val mBinding by lazy { DialogPrivacyProtocolBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState != null) {
dismiss()
return
}
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
@ -67,13 +59,13 @@ class PrivacyPolicyDialogFragment : BaseDialogFragment() {
skipText.setSpan(object : ClickableSpan() { skipText.setSpan(object : ClickableSpan() {
override fun updateDrawState(ds: TextPaint) { override fun updateDrawState(ds: TextPaint) {
super.updateDrawState(ds) super.updateDrawState(ds)
ds.color = ContextCompat.getColor(requireContext(), com.gh.gamecenter.common.R.color.text_theme) ds.color = ContextCompat.getColor(requireContext(), R.color.theme_font)
ds.isUnderlineText = false ds.isUnderlineText = false
} }
override fun onClick(widget: View) { override fun onClick(widget: View) {
val intent = val intent =
WebActivity.getIntent(requireContext(), context!!.getString(com.gh.gamecenter.common.R.string.privacy_policy_url), true) WebActivity.getIntent(requireContext(), context!!.getString(R.string.privacy_policy_url), true)
context?.startActivity(intent) context?.startActivity(intent)
} }
}, skipText.length - 6, skipText.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) }, skipText.length - 6, skipText.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
@ -109,13 +101,13 @@ class PrivacyPolicyDialogFragment : BaseDialogFragment() {
skipText.setSpan(object : ClickableSpan() { skipText.setSpan(object : ClickableSpan() {
override fun updateDrawState(ds: TextPaint) { override fun updateDrawState(ds: TextPaint) {
super.updateDrawState(ds) super.updateDrawState(ds)
ds.color = ContextCompat.getColor(requireContext(), com.gh.gamecenter.common.R.color.text_theme) ds.color = ContextCompat.getColor(requireContext(), R.color.theme_font)
ds.isUnderlineText = false ds.isUnderlineText = false
} }
override fun onClick(widget: View) { override fun onClick(widget: View) {
val intent = val intent =
WebActivity.getIntent(requireContext(), context!!.getString(com.gh.gamecenter.common.R.string.privacy_policy_url), true) WebActivity.getIntent(requireContext(), context!!.getString(R.string.privacy_policy_url), true)
context?.startActivity(intent) context?.startActivity(intent)
} }
}, skipText.length - 9, skipText.length - 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) }, skipText.length - 9, skipText.length - 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
@ -123,12 +115,12 @@ class PrivacyPolicyDialogFragment : BaseDialogFragment() {
skipText.setSpan(object : ClickableSpan() { skipText.setSpan(object : ClickableSpan() {
override fun updateDrawState(ds: TextPaint) { override fun updateDrawState(ds: TextPaint) {
super.updateDrawState(ds) super.updateDrawState(ds)
ds.color = ContextCompat.getColor(requireContext(), com.gh.gamecenter.common.R.color.text_theme) ds.color = ContextCompat.getColor(requireContext(), R.color.theme_font)
ds.isUnderlineText = false ds.isUnderlineText = false
} }
override fun onClick(widget: View) { override fun onClick(widget: View) {
val intent = WebActivity.getIntent(requireContext(), context!!.getString(com.gh.gamecenter.common.R.string.disclaimer_url), true) val intent = WebActivity.getIntent(requireContext(), context!!.getString(R.string.disclaimer_url), true)
context?.startActivity(intent) context?.startActivity(intent)
} }
}, skipText.length - 4, skipText.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) }, skipText.length - 4, skipText.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)

View File

@ -1,212 +1,92 @@
package com.gh.common.dialog package com.gh.common.dialog
import android.content.Context
import android.content.DialogInterface
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.gh.common.exposure.ExposureListener
import com.gh.common.exposure.IExposable
import com.gh.gamecenter.DownloadManagerActivity
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
import com.gh.gamecenter.common.constant.Constants import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.common.exposure.ExposureSource import com.gh.gamecenter.common.utils.fromHtml
import com.gh.gamecenter.common.utils.* import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.view.FixLinearLayoutManager import com.gh.gamecenter.common.view.FixLinearLayoutManager
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.SPUtils.getBoolean
import com.gh.gamecenter.databinding.DialogReserveBinding import com.gh.gamecenter.databinding.DialogReserveBinding
import com.gh.gamecenter.databinding.DialogReserveItemBinding import com.gh.gamecenter.databinding.DialogReserveItemBinding
import com.gh.gamecenter.feature.entity.GameEntity import com.gh.gamecenter.common.entity.SimpleGameEntity
import com.gh.gamecenter.feature.entity.ReserveOnlineEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.mygame.MyGameActivity import com.gh.gamecenter.mygame.MyGameActivity
import com.halo.assistant.HaloApp
import com.lightgame.adapter.BaseRecyclerAdapter import com.lightgame.adapter.BaseRecyclerAdapter
class ReserveDialog : BaseDialogFragment() { class ReserveDialog : BaseDialogFragment() {
private lateinit var reserveOnlineEntity: ReserveOnlineEntity private lateinit var mReserveList: List<SimpleGameEntity>
val games: List<GameEntity>
get() = reserveOnlineEntity.games
private var mDismissListener: (() -> Unit)? = null private var mDismissListener: (() -> Unit)? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState != null) {
dismiss()
return
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val binding: DialogReserveBinding = DialogReserveBinding.inflate(layoutInflater, null, false) val binding: DialogReserveBinding = DialogReserveBinding.inflate(layoutInflater, null, false)
reserveOnlineEntity = arguments?.getParcelable(RESERVE_ONLINE) ?: ReserveOnlineEntity() mReserveList = arguments?.getParcelableArrayList(RESERVE_LIST) ?: arrayListOf()
binding.tvTitle.text = binding.title.text = resources.getString(R.string.dialog_reserve_title, mReserveList.size).fromHtml()
resources.getString(R.string.dialog_reserve_title, reserveOnlineEntity.gamesTotal).fromHtml() binding.more.visibility = if (mReserveList.size > 4) {
binding.tvViewAllAppointment.setOnClickListener { View.VISIBLE
SensorsBridge.trackAppointmentGameOnlineDialogClick(buttonName = "查看全部预约") } else View.GONE
val intent = MyGameActivity.getIntentWithConfig(requireContext(), MyGameActivity.RESERVATION_INDEX) binding.more.setOnClickListener {
val intent = MyGameActivity.getIntentWithConfig(requireContext(), 2)
startActivity(intent) startActivity(intent)
}
val adapter = ReserveDialogAdapter(requireContext(), games)
binding.rvGames.layoutManager = FixLinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
binding.rvGames.adapter = adapter
val exposureListener = ExposureListener(this, adapter)
binding.rvGames.addOnScrollListener(exposureListener)
binding.ivClose.setOnClickListener {
dismissAllowingStateLoss() dismissAllowingStateLoss()
} }
binding.recyclerView.layoutManager = if (mReserveList.size > 4) {
GridLayoutManager(context, 4)
} else {
FixLinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
}
binding.recyclerView.adapter = object : BaseRecyclerAdapter<ReserveDialogItemViewHolder>(context) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ReserveDialogItemViewHolder {
val inflate = mLayoutInflater.inflate(R.layout.dialog_reserve_item, parent, false)
return ReserveDialogItemViewHolder(DialogReserveItemBinding.bind(inflate))
}
checkHasAutoDownload(binding) override fun getItemCount(): Int {
return if (mReserveList.size > 4) 4 else mReserveList.size
}
override fun onBindViewHolder(holder: ReserveDialogItemViewHolder, position: Int) {
val entity = mReserveList[position]
ImageUtils.display(holder.binding.icon, entity.icon)
holder.binding.gameNameTv.text = entity.name
holder.itemView.setOnClickListener {
GameDetailActivity.startGameDetailActivity(mContext, entity.id, "(预约弹窗)")
dismissAllowingStateLoss()
}
}
}
dialog?.setCanceledOnTouchOutside(true) dialog?.setCanceledOnTouchOutside(true)
return binding.root return binding.root
} }
private fun checkHasAutoDownload(binding: DialogReserveBinding) {
if (reserveOnlineEntity.wifiAutoDownloadTotal > 0) {
// 开启自动下载
binding.tvAutoDownloadTips.goneIf(false)
var firstAutoDownloadGameName =
reserveOnlineEntity.games.find { it.wifiAutoDownload && !it.isLandPageAddressDialog() }?.name
if(!firstAutoDownloadGameName.isNullOrBlank() && firstAutoDownloadGameName.length > GAME_NAME_SHOW_MAX_LENGTH){
firstAutoDownloadGameName = "${firstAutoDownloadGameName.take(GAME_NAME_SHOW_MAX_LENGTH-1)}..."
}
val isWifiOpen = NetworkUtils.isWifiConnected(HaloApp.getInstance())
binding.tvAutoDownloadTips.text =
if (isWifiOpen) {
if (firstAutoDownloadGameName.isNullOrBlank()) {
getString(
R.string.reserve_reminder_auto_download,
"${reserveOnlineEntity.wifiAutoDownloadTotal}"
)
} else {
getString(
R.string.reserve_reminder_auto_download_with_name,
firstAutoDownloadGameName,
"${reserveOnlineEntity.wifiAutoDownloadTotal}"
)
}
} else {
if (firstAutoDownloadGameName.isNullOrBlank()) {
getString(
R.string.reserve_reminder_wait_for_wifi_to_auto_download,
"${reserveOnlineEntity.wifiAutoDownloadTotal}"
)
} else {
getString(
R.string.reserve_reminder_wait_for_wifi_to_auto_download_with_name,
firstAutoDownloadGameName,
"${reserveOnlineEntity.wifiAutoDownloadTotal}"
)
}
}
binding.tvAutoDownloadTips.setOnClickListener {
SensorsBridge.trackAppointmentGameOnlineDialogClick(buttonName = "查看进度")
val intent = DownloadManagerActivity.getDownloadMangerIntent(requireContext(), "")
startActivity(intent)
}
} else {
binding.tvAutoDownloadTips.goneIf(true)
}
}
fun setOnDismissListener(dismissListener: () -> Unit) { fun setOnDismissListener(dismissListener: () -> Unit) {
mDismissListener = dismissListener mDismissListener = dismissListener
} }
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
SensorsBridge.trackAppointmentGameOnlineDialogClick(buttonName = "关闭弹窗")
}
override fun onStart() {
super.onStart()
dialog?.window?.let {
it.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
val params = it.attributes
params.width = DisplayUtils.dip2px(300F)
it.attributes = params
}
}
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
mDismissListener?.invoke() mDismissListener?.invoke()
} }
companion object { companion object {
const val RESERVE_ONLINE = "reserve_online" const val RESERVE_LIST = "reserve_list"
private const val GAME_NAME_SHOW_MAX_LENGTH = 8
@JvmStatic @JvmStatic
fun getInstance(reserveOnlineEntity: ReserveOnlineEntity?) = ReserveDialog().apply { fun getInstance(reserveList: List<SimpleGameEntity>) = ReserveDialog().apply {
arguments = Bundle().apply { arguments = Bundle()
putParcelable(RESERVE_ONLINE, reserveOnlineEntity) arguments?.putParcelableArrayList(RESERVE_LIST, ArrayList(reserveList))
}
} }
} }
} }
class ReserveDialogAdapter(
context: Context,
private val games: List<GameEntity>
) :
BaseRecyclerAdapter<ReserveDialogItemViewHolder>(context), IExposable {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ReserveDialogItemViewHolder {
return ReserveDialogItemViewHolder(parent.toBinding())
}
override fun getItemCount(): Int {
return if (games.size > 8) 8 else games.size
}
override fun onBindViewHolder(holder: ReserveDialogItemViewHolder, position: Int) {
val entity = games[position]
holder.binding.icon.displayGameIcon(entity)
holder.binding.gameNameTv.text = entity.name
holder.itemView.setOnClickListener {
SensorsBridge.trackAppointmentGameOnlineDialogClick(
"游戏",
entity.id,
entity.name ?: "",
entity.categoryChinese,
)
GameDetailActivity.startGameDetailActivity(mContext, entity.id, "(预约弹窗)", entity.exposureEvent)
}
entity.exposureEvent = ExposureEvent.createEvent(
entity,
listOf(ExposureSource("预约上线弹窗", ""))
)
}
override fun getEventByPosition(pos: Int): ExposureEvent? {
return games.getOrNull(pos)?.exposureEvent
}
override fun getEventListByPosition(pos: Int): List<ExposureEvent>? {
return null
}
}
class ReserveDialogItemViewHolder(val binding: DialogReserveItemBinding) : BaseRecyclerViewHolder<Any>(binding.root) class ReserveDialogItemViewHolder(val binding: DialogReserveItemBinding) : BaseRecyclerViewHolder<Any>(binding.root)

View File

@ -1,278 +0,0 @@
package com.gh.common.dialog
import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.text.InputFilter
import android.view.LayoutInflater
import androidx.core.widget.addTextChangedListener
import com.gh.gamecenter.R
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.toResString
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.databinding.DialogReserveReminderPhoneNumberBinding
import com.gh.gamecenter.entity.ReserveModifyEntity
import com.gh.gamecenter.entity.ValidateCodeResponse
import com.halo.assistant.fragment.reserve.OnReserveReminderListener
import com.halo.assistant.fragment.reserve.ReserveReminderRepository
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.HttpException
import java.util.concurrent.TimeUnit
class ReserveReminderPhoneNumberDialog(
context: Context,
themeResId: Int,
private val dialogType: Int,
private val phoneNumber: String,
private var serviceId: String,
private val gameId: String,
private val repository: ReserveReminderRepository,
private val listener: OnReserveReminderListener
) :
Dialog(context, themeResId) {
private val compositeDisposable = CompositeDisposable()
private lateinit var binding: DialogReserveReminderPhoneNumberBinding
private var hasValidated = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DialogReserveReminderPhoneNumberBinding.inflate(LayoutInflater.from(context))
setContentView(binding.root)
initView()
}
private fun initView() {
binding.vClose.setOnClickListener {
dismiss()
}
setSubmitState(phoneNumber)
binding.etInput.addTextChangedListener {
val content = binding.etInput.text?.toString() ?: ""
if (dialogType == DIALOG_TYPE_BIND_PHONE || dialogType == DIALOG_TYPE_CHANGE_PHONE) {
setSubmitState(content)
} else {
val length = content.length
if (length == VALIDATE_CODE_LENGTH) {
verifyPhoneNumber(content)
}
}
}
when (dialogType) {
DIALOG_TYPE_BIND_PHONE -> {
binding.tvTitle.setText(R.string.enable_sms_reminder)
binding.tvDescription.setText(R.string.enable_sms_reminder_description)
binding.etInput.setText(phoneNumber)
binding.etInput.setHint(com.gh.gamecenter.login.R.string.input_phone_hint)
}
DIALOG_TYPE_CHANGE_PHONE -> {
binding.tvTitle.setText(R.string.change_phone_number_2)
binding.tvDescription.setText(R.string.enable_sms_reminder_description)
binding.etInput.setText(phoneNumber)
binding.etInput.setHint(com.gh.gamecenter.login.R.string.input_phone_hint)
}
DIALOG_TYPE_VERIFY_PHONE -> {
startCountDown()
binding.tvTitle.setText(R.string.please_input_sms_verify_code)
if (phoneNumber.length == PHONE_NUMBER_LENGTH) {
val phoneNumberWithMask = phoneNumber.substring(0, 3) + MASK + phoneNumber.substring(7)
binding.tvDescription.text =
context.getString(R.string.verify_code_send_with_phone_number, phoneNumberWithMask)
}
binding.tvSubmit.alpha = 1.0F
binding.etInput.filters = arrayOf<InputFilter>(InputFilter.LengthFilter(VALIDATE_CODE_LENGTH))
binding.etInput.setHint(R.string.please_input_verify_code)
}
}
binding.tvSubmit.setOnClickListener {
val text = binding.etInput.text?.toString() ?: ""
if (dialogType == DIALOG_TYPE_VERIFY_PHONE) {
resendValidateCode()
} else {
if (isEnableSubmit(text)) {
when (dialogType) {
DIALOG_TYPE_BIND_PHONE -> bindPhoneNumber(text)
DIALOG_TYPE_CHANGE_PHONE -> bindPhoneNumber(text)
}
} else {
if (text != phoneNumber) {
ToastUtils.toast(R.string.invalid_phone_number_format.toResString())
}
}
}
}
}
private fun resendValidateCode() {
repository.sendVerifyCode(phoneNumber)
.compose(singleToMain())
.subscribe(object : BiResponse<ValidateCodeResponse>() {
override fun onSuccess(data: ValidateCodeResponse) {
serviceId = data.serviceId
startCountDown()
}
}).let(compositeDisposable::add)
}
private fun verifyPhoneNumber(content: String) {
repository.verifyPhoneNumber(phoneNumber, content, serviceId)
.compose(singleToMain())
.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {
hasValidated = true
listener.phoneNumberValidateSuccessfully()
ToastUtils.toast(R.string.phone_number_validate_successfully.toResString())
dismiss()
}
override fun onFailure(exception: Exception) {
super.onFailure(exception)
binding.etInput.text = null
ToastUtils.toast(R.string.phone_number_validate_failure.toResString())
}
}).let(compositeDisposable::add)
}
private fun bindPhoneNumber(phone: String) {
repository.bindPhone(gameId, phone)
.compose(singleToMain())
.subscribe(object : BiResponse<ReserveModifyEntity>() {
override fun onSuccess(data: ReserveModifyEntity) {
listener.bindPhoneSuccessfully(data.smsConfig.mobileValidated, phone)
dismiss()
}
override fun onFailure(exception: Exception) {
super.onFailure(exception)
if (exception is HttpException) {
try {
val string = exception.response().errorBody()?.string()
if (!string.isNullOrBlank()) {
val json = JSONObject(string)
val message = json.getJSONObject("toast").getString("sms_config.mobile")
ToastUtils.showToast(message)
}
} catch (e: Exception) {
// no implement
}
}
}
}).let(compositeDisposable::add)
}
private fun startCountDown() {
binding.tvSubmit.isEnabled = false
binding.tvSubmit.setBackgroundResource(com.gh.gamecenter.common.R.drawable.bg_common_button_light_fill_gray)
binding.tvSubmit.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
Observable.interval(0, 1, TimeUnit.SECONDS)
.take(COUNT_DOWN_DURATION)
.map {
COUNT_DOWN_DURATION - it
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<Long>() {
override fun onSubscribe(d: Disposable) {
compositeDisposable.add(d)
}
override fun onNext(time: Long) {
binding.tvSubmit.text = context.getString(R.string.resend_with_time, "$time")
}
override fun onComplete() {
binding.tvSubmit.isEnabled = true
binding.tvSubmit.setBackgroundResource(com.gh.gamecenter.common.R.drawable.bg_common_button_fill_blue)
binding.tvSubmit.setTextColor(com.gh.gamecenter.common.R.color.text_aw_primary.toColor(context))
binding.tvSubmit.setText(R.string.resend)
}
})
}
override fun dismiss() {
compositeDisposable.clear()
if (dialogType == DIALOG_TYPE_VERIFY_PHONE && !hasValidated) {
ToastUtils.toast(R.string.phone_number_validate_cancel.toResString())
}
super.dismiss()
}
private fun isEnableSubmit(phone: String) =
PHONE_NUMBER_PATTERN.toRegex().matches(phone)
&& if (dialogType == DIALOG_TYPE_CHANGE_PHONE) phone != phoneNumber else true
private fun setSubmitState(phone: String) {
val isEnable = isEnableSubmit(phone)
binding.tvSubmit.alpha = if (isEnable) {
TV_SUBMIT_ENABLE_ALPHA
} else {
TV_SUBMIT_UNABLE_ALPHA
}
}
companion object {
private const val PHONE_NUMBER_PATTERN = "^1\\d{10}$"
private const val MASK = "****"
private const val PHONE_NUMBER_LENGTH = 11
private const val VALIDATE_CODE_LENGTH = 6
const val DIALOG_TYPE_BIND_PHONE = 0
const val DIALOG_TYPE_CHANGE_PHONE = 1
const val DIALOG_TYPE_VERIFY_PHONE = 2
private const val COUNT_DOWN_DURATION = 60L
private const val TV_SUBMIT_ENABLE_ALPHA = 1F
private const val TV_SUBMIT_UNABLE_ALPHA = 0.4F
fun create(
context: Context,
dialogType: Int,
phoneNumber: String,
serviceId: String,
gameId: String,
repository: ReserveReminderRepository,
listener: OnReserveReminderListener
) =
ReserveReminderPhoneNumberDialog(
context,
com.gh.gamecenter.common.R.style.DialogWindowTransparent,
dialogType,
phoneNumber,
serviceId,
gameId,
repository,
listener
)
}
}

View File

@ -1,428 +0,0 @@
package com.gh.common.dialog
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.text.TextUtils
import android.view.*
import android.view.ViewGroup.MarginLayoutParams
import androidx.core.view.updateLayoutParams
import com.gh.common.pop.EditBindPhoneInfoPop
import com.gh.common.pop.EditBindWechatPop
import com.gh.common.pop.RealNameTipsPop
import com.gh.gamecenter.R
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.utils.toObject
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.databinding.*
import com.gh.gamecenter.entity.ReserveReminderEntity
import com.gh.gamecenter.login.entity.UserInfoEntity
import com.gh.gamecenter.login.user.UserManager
import com.halo.assistant.HaloApp
import com.halo.assistant.fragment.reserve.OnReserveReminderListener
class ReserveSuccessReminderDialog(
context: Context,
themeResId: Int,
private val listener: OnReserveReminderListener
) :
Dialog(context, themeResId), OnReserveSuccessListener {
private var reserveReminder = ReserveReminderEntity()
private val handler = Handler(Looper.getMainLooper())
private val handlers = arrayListOf<ReminderContentHandler>()
private lateinit var binding: DialogReserveSuccessWithSmsBinding
private val realNameQuestionPop by lazy {
RealNameTipsPop.create(context, listener)
}
private var hasAutoPopped = false
private var isInit = true
override fun onTouchEvent(event: MotionEvent): Boolean {
if (event.action == MotionEvent.ACTION_UP) {
if (realNameQuestionPop.isShowing) {
realNameQuestionPop.dismiss()
return true
} else if (handlers.any { it.hasPopShowing }) {
handlers.forEach {
it.dismissPop()
}
return true
}
}
return super.onTouchEvent(event)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DialogReserveSuccessWithSmsBinding.inflate(LayoutInflater.from(context))
setContentView(binding.root)
binding.ivClose.setOnClickListener {
dismiss()
}
binding.ivQuestion.setOnClickListener {
realNameQuestionPop.showAtLocation(binding.cbAutoDownload, Gravity.BOTTOM, 0, 4F.dip2px())
}
}
private fun initView() {
handlers.clear()
binding.flContentContainer.removeAllViews()
val smsConfig = reserveReminder.smsConfig
val wechatConfig = reserveReminder.wechatConfig
when {
reserveReminder.onlyShowWechatReminder && !wechatConfig.isReminderEnable -> { // 只显示微信:未开启
binding.tvContent.setText(R.string.reverse_success_without_reminder_tips)
arrayListOf(OnlyWechatReminderUnableHandler(16.dp, binding.flContentContainer, this))
}
reserveReminder.onlyShowWechatReminder && wechatConfig.isReminderEnable -> { // 只显示微信:已开
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
arrayListOf(
WechatReminderEnableHandler(
reserveReminder.wechatConfig.nickName,
8.dp,
binding.flContentContainer,
this
)
)
}
!smsConfig.notice && !wechatConfig.isReminderEnable -> { // 短信,微信未开启
binding.tvContent.setText(R.string.reverse_success_without_reminder_tips)
arrayListOf(
SmsReminderUnableHandler(16.dp, binding.flContentContainer, this),
WechatReminderUnableHandler(8.dp, binding.flContentContainer, this)
)
}
smsConfig.notice && wechatConfig.isReminderEnable -> {// 短信,微信已开启
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
arrayListOf(
SmsReminderEnableHandler(reserveReminder.smsConfig, 8.dp, binding.flContentContainer, this),
WechatReminderEnableHandler(
reserveReminder.wechatConfig.nickName,
8.dp,
binding.flContentContainer,
this
)
)
}
smsConfig.notice && !wechatConfig.isReminderEnable -> { // 短信开启,微信未开启
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
arrayListOf(
SmsReminderEnableHandler(smsConfig, 8.dp, binding.flContentContainer, this),
WechatReminderUnableHandler(16.dp, binding.flContentContainer, this)
)
}
!smsConfig.notice && wechatConfig.isReminderEnable -> { // 微信开启,短信未开启
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
arrayListOf(
WechatReminderEnableHandler(
wechatConfig.nickName,
8.dp,
binding.flContentContainer,
this
),
SmsReminderUnableHandler(16.dp, binding.flContentContainer, this)
)
}
else -> {
binding.tvContent.setText(R.string.reverse_success_without_reminder_tips)
arrayListOf()
}
}.let {
handlers.clear()
handlers.addAll(it)
}
handlers.forEach {
binding.flContentContainer.addView(it.init())
}
if (isInit) {
isInit = false
binding.gAutoDownload.goneIf(!reserveReminder.isEnableAutoDownload)
if (reserveReminder.isEnableAutoDownload) {
binding.cbAutoDownload.isChecked = reserveReminder.wifiAutoDownload
checkIfShowRealNamePop()
}
binding.cbAutoDownload.setOnCheckedChangeListener { _, isChecked ->
listener.enableAutoDownload(isChecked)
checkIfShowRealNamePop()
}
}
}
private fun checkIfShowRealNamePop() {
if (hasAutoPopped) {
return
}
hasAutoPopped = true
handler.postDelayed({
val idCard = UserManager.getInstance().userInfoEntity?.idCard
if (idCard != null && idCard.status != 1 && idCard.minor != true) {
// 账号已实名
return@postDelayed
}
val deviceCertificationInfoString =
SPUtils.getString(Constants.SP_DEVICE_CERTIFICATION_PREFIX + HaloApp.getInstance().gid)
if (!TextUtils.isEmpty(deviceCertificationInfoString)) {
val deviceIdCard = deviceCertificationInfoString.toObject<UserInfoEntity>()?.idCard
if (deviceIdCard != null && deviceIdCard.status != 1 && deviceIdCard.minor != true) {
// 设备已实名
return@postDelayed
}
}
realNameQuestionPop.showAtLocation(binding.cbAutoDownload, Gravity.BOTTOM, 0, 0)
}, 16)
}
override fun updateSmsReminder(isEnable: Boolean) {
listener.updateSmsReminder(isEnable)
}
override fun updateWechatReminder() {
listener.updateWechatReminder()
}
override fun changePhoneNumber() {
listener.changedPhoneNumber()
}
override fun verifyPhoneNumber() {
listener.verifyPhoneNumber()
}
override fun changeWechatBinding() {
listener.changeWechatBinding()
}
override fun onStart() {
super.onStart()
window?.let {
it.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
val params = it.attributes
params.width = DisplayUtils.dip2px(300F)
it.attributes = params
}
}
fun updateReserveReminder(reserveReminder: ReserveReminderEntity) {
this.reserveReminder = reserveReminder
initView()
}
override fun dismiss() {
handler.removeCallbacksAndMessages(null)
super.dismiss()
}
companion object {
private val Int.dp: Int
get() = DisplayUtils.dip2px(this.toFloat())
fun create(context: Context, listener: OnReserveReminderListener) =
ReserveSuccessReminderDialog(
context,
com.gh.gamecenter.common.R.style.DialogWindowTransparent,
listener
).apply {
}
}
abstract class ReminderContentHandler(
val topMargin: Int,
val parent: ViewGroup,
val listener: OnReserveSuccessListener
) {
open val hasPopShowing: Boolean = false
fun init(): View {
val root = createView(LayoutInflater.from(parent.context))
root.updateLayoutParams<MarginLayoutParams> {
this.topMargin = this@ReminderContentHandler.topMargin
}
initView()
return root
}
protected abstract fun createView(inflater: LayoutInflater): View
protected abstract fun initView()
open fun dismissPop() = Unit
}
class SmsReminderUnableHandler(topMargin: Int, parent: ViewGroup, listener: OnReserveSuccessListener) :
ReminderContentHandler(topMargin, parent, listener) {
private lateinit var binding: LayoutReserveSmsReminderUnableBinding
override fun createView(inflater: LayoutInflater): View {
return LayoutReserveSmsReminderUnableBinding.inflate(inflater, parent, false)
.also {
binding = it
}.root
}
override fun initView() {
binding.vSmsAdd.setOnClickListener {
listener.updateSmsReminder(true)
}
}
}
class WechatReminderUnableHandler(topMargin: Int, parent: ViewGroup, listener: OnReserveSuccessListener) :
ReminderContentHandler(topMargin, parent, listener) {
private lateinit var binding: LayoutReserveWechatReminderUnableBinding
override fun createView(inflater: LayoutInflater): View {
return LayoutReserveWechatReminderUnableBinding.inflate(inflater, parent, false)
.also {
binding = it
}.root
}
override fun initView() {
binding.vWechatAdd.setOnClickListener {
listener.updateWechatReminder()
}
}
}
class SmsReminderEnableHandler(
private val smsConfig: ReserveReminderEntity.SmsConfig,
topMargin: Int,
parent: ViewGroup, listener:
OnReserveSuccessListener
) :
ReminderContentHandler(topMargin, parent, listener) {
private lateinit var binding: LayoutReserveSmsReminderEnableBinding
override val hasPopShowing: Boolean
get() = editBindPhoneInfoPop.isShowing
override fun dismissPop() {
if (hasPopShowing) {
editBindPhoneInfoPop.dismiss()
}
}
private val editBindPhoneInfoPop by lazy {
EditBindPhoneInfoPop.create(parent.context, smsConfig.mobileValidated, listener)
}
override fun createView(inflater: LayoutInflater) =
LayoutReserveSmsReminderEnableBinding.inflate(inflater, parent, false)
.also {
binding = it
}.root
override fun initView() {
binding.tvPhone.text = smsConfig.mobile
binding.vSmsEdit.setOnClickListener {
editBindPhoneInfoPop.showAsDropDown(
binding.ivSmsEdit,
(-104).dp,
0,
)
}
}
}
class WechatReminderEnableHandler(
private val nickName: String,
topMargin: Int,
parent: ViewGroup,
listener: OnReserveSuccessListener
) :
ReminderContentHandler(topMargin, parent, listener) {
private lateinit var binding: LayoutReserveWechatReminderEnableBinding
private val editWechatPop by lazy {
EditBindWechatPop.create(parent.context, listener)
}
override fun createView(inflater: LayoutInflater) =
LayoutReserveWechatReminderEnableBinding.inflate(inflater, parent, false)
.also {
binding = it
}.root
override fun initView() {
binding.tvWechat.text = nickName
binding.vModifyWechat.setOnClickListener {
editWechatPop.showAsDropDown(
binding.ivModifyWechat,
(-104).dp,
0
)
}
}
}
class OnlyWechatReminderUnableHandler(topMargin: Int, parent: ViewGroup, listener: OnReserveSuccessListener) :
ReminderContentHandler(topMargin, parent, listener) {
private lateinit var binding: LayoutReserveOnlyWechatUnableBinding
override fun createView(inflater: LayoutInflater) =
LayoutReserveOnlyWechatUnableBinding.inflate(inflater, parent, false)
.also {
binding = it
}.root
override fun initView() {
binding.vSubmitBackground.setOnClickListener {
listener.updateWechatReminder()
}
}
}
}
interface OnReserveSuccessListener {
fun updateSmsReminder(isEnable: Boolean)
fun updateWechatReminder()
fun changePhoneNumber()
fun verifyPhoneNumber()
fun changeWechatBinding()
}

View File

@ -1,63 +0,0 @@
package com.gh.common.dialog
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.databinding.DialogWechatBindingConflictBinding
class WechatBindingConflictDialogFragment : BaseDialogFragment() {
private lateinit var binding: DialogWechatBindingConflictBinding
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return super.onCreateDialog(savedInstanceState).apply {
setCanceledOnTouchOutside(true)
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return DialogWechatBindingConflictBinding.inflate(inflater, container, false)
.also {
binding = it
}.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.tvIKnow.setOnClickListener {
dismiss()
}
}
override fun onStart() {
super.onStart()
dialog?.window?.let {
it.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
val params = it.attributes
params.width = DisplayUtils.dip2px(300F)
it.attributes = params
}
}
companion object {
fun show(context: Context) {
if (context is AppCompatActivity) {
context.supportFragmentManager
} else {
(CurrentActivityHolder.getCurrentActivity() as? AppCompatActivity)?.supportFragmentManager
}?.let {
WechatBindingConflictDialogFragment().show(it, WechatBindingConflictDialogFragment::class.java.name)
}
}
}
}

View File

@ -1,125 +0,0 @@
package com.gh.common.dialog
import android.app.Dialog
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
import com.gh.gamecenter.common.entity.ErrorEntity
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.databinding.DialogWechatBindingFailedBinding
import com.gh.gamecenter.login.user.UserRepository
import com.lightgame.utils.Utils
class WechatBindingFailedDialogFragment : BaseDialogFragment() {
private lateinit var binding: DialogWechatBindingFailedBinding
private var currentUserId: String? = null
private lateinit var userConflict: ErrorEntity.Data.UserConflict
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
userConflict = arguments?.getParcelable(KEY_USER_CONFLICT) ?: ErrorEntity.Data.UserConflict()
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return super.onCreateDialog(savedInstanceState).apply {
setCanceledOnTouchOutside(true)
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return DialogWechatBindingFailedBinding.inflate(inflater, container, false)
.also {
binding = it
}.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
UserRepository.getInstance().loginUserInfo.observe(viewLifecycleOwner) {
currentUserId = it.data.getShortUserId()
binding.tvCurrentName.text = it.data.name
binding.ivCurrentAvatar.displayAvatar(it.data.icon)
binding.tvUserId.text = getString(R.string.user_id, currentUserId)
}
binding.tvConflictName.text = userConflict.name
binding.ivConflictAvatar.displayAvatar(userConflict.icon)
binding.tvConflictUserId.text = getString(R.string.user_id, userConflict.seq)
binding.tvConflictProblem.setOnClickListener {
dismiss()
WechatBindingConflictDialogFragment.show(requireContext())
}
binding.tvIKnow.setOnClickListener {
dismiss()
}
binding.tvUserId.setOnLongClickListener {
currentUserId?.let {
copyTextToClipboard(it)
true
} ?: false
}
binding.tvConflictUserId.setOnLongClickListener {
copyTextToClipboard(userConflict.id)
true
}
}
private fun copyTextToClipboard(text: String) {
val clipboardManager = context?.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
if (clipboardManager != null) {
val clip = ClipData.newPlainText(COPY_ID_TEXT, text)
clipboardManager.setPrimaryClip(clip)
Utils.toast(requireContext(), R.string.copy_user_id_successfully)
}
}
override fun onStart() {
super.onStart()
dialog?.window?.let {
it.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
val params = it.attributes
params.width = DisplayUtils.dip2px(300F)
it.attributes = params
}
}
companion object {
private const val COPY_ID_TEXT = "user_id"
private const val KEY_USER_CONFLICT = "key_user_conflict"
fun show(context: Context, userConflict: ErrorEntity.Data.UserConflict?) {
if (context is AppCompatActivity) {
context.supportFragmentManager
} else {
(CurrentActivityHolder.getCurrentActivity() as? AppCompatActivity)?.supportFragmentManager
}?.let {
val fragment = WechatBindingFailedDialogFragment().apply {
arguments = Bundle().apply {
putParcelable(KEY_USER_CONFLICT, userConflict)
}
}
fragment.show(it, WechatBindingFailedDialogFragment::class.java.name)
}
}
}
}

View File

@ -4,9 +4,6 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.LayoutManager
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.feature.exposure.ExposureEvent import com.gh.gamecenter.feature.exposure.ExposureEvent
import io.reactivex.functions.Consumer import io.reactivex.functions.Consumer
@ -17,12 +14,11 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
val throttleBus: ExposureThrottleBus by lazy { val throttleBus: ExposureThrottleBus by lazy {
ExposureThrottleBus( ExposureThrottleBus(
{ commitExposure(it) }, Consumer { commitExposure(it) },
Consumer(Throwable::printStackTrace), Consumer(Throwable::printStackTrace)
{ commitWXCPMExposure(it) }
) )
} }
var layoutManager: LayoutManager? = null var layoutManager: LinearLayoutManager? = null
var visibleState: ExposureThrottleBus.VisibleState? = null var visibleState: ExposureThrottleBus.VisibleState? = null
init { init {
@ -51,28 +47,12 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy) super.onScrolled(recyclerView, dx, dy)
layoutManager = recyclerView.layoutManager if (layoutManager == null) layoutManager = recyclerView.layoutManager as LinearLayoutManager
if (layoutManager != null) { layoutManager?.run {
if (layoutManager is LinearLayoutManager) { visibleState =
(layoutManager as LinearLayoutManager).run { ExposureThrottleBus.VisibleState(findFirstVisibleItemPosition(), findLastVisibleItemPosition())
visibleState = throttleBus.postVisibleState(visibleState!!)
ExposureThrottleBus.VisibleState(findFirstVisibleItemPosition(), findLastVisibleItemPosition())
throttleBus.postVisibleState(visibleState!!)
}
} else if (layoutManager is StaggeredGridLayoutManager) {
(recyclerView.layoutManager as StaggeredGridLayoutManager).run {
val firstVisibleItemArray = IntArray(2)
val lastVisibleItemArray = IntArray(2)
findFirstVisibleItemPositions(firstVisibleItemArray)
findLastVisibleItemPositions(lastVisibleItemArray)
visibleState =
ExposureThrottleBus.VisibleState(firstVisibleItemArray.first(), lastVisibleItemArray.first())
throttleBus.postVisibleState(visibleState!!)
}
}
} }
} }
@ -95,32 +75,4 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
ExposureManager.log(eventList) ExposureManager.log(eventList)
} }
/**
* 微信小游戏CPM曝光事件接口上报由于普通曝光事件的上报通道存在节流特性不符合CPM接口对于数据上报的实时性和准确性的要求所以使用额外的通道进行上报
*/
private fun commitWXCPMExposure(visibleState: ExposureThrottleBus.VisibleState) {
val eventList = arrayListOf<ExposureEvent>()
for (pos in visibleState.firstVisiblePosition..visibleState.lastVisiblePosition) {
try {
exposable.getEventByPosition(pos)?.let {
if (it.payload.miniGameType == Constants.WECHAT_MINI_GAME_CPM) {
eventList.add(it)
}
}
exposable.getEventListByPosition(pos)?.let { list ->
list.forEach {
if (it.payload.miniGameType == Constants.WECHAT_MINI_GAME_CPM) {
eventList.add(it)
}
}
}
} catch (ignore: Exception) {
// Just ignore the error.
}
}
ExposureManager.logCPM(eventList)
}
} }

View File

@ -1,15 +1,12 @@
package com.gh.common.exposure package com.gh.common.exposure
import com.aliyun.sls.android.producer.Log
import com.gh.gamecenter.BuildConfig import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.common.constant.Constants import com.gh.gamecenter.common.loghub.LoghubHelper
import com.gh.gamecenter.common.loghub.TLogHubHelper
import com.gh.gamecenter.common.utils.FixedSizeLinkedHashSet import com.gh.gamecenter.common.utils.FixedSizeLinkedHashSet
import com.gh.gamecenter.common.utils.toJson import com.gh.gamecenter.common.utils.toJson
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.feature.exposure.ExposureEvent import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.minigame.wechat.WGameSubjectCPMListReportHelper
import com.lightgame.utils.Utils import com.lightgame.utils.Utils
import com.volcengine.model.tls.LogItem
/** /**
* A handful tool for committing logs to aliyun loghub. * A handful tool for committing logs to aliyun loghub.
@ -33,16 +30,11 @@ object ExposureManager {
* Log a single exposure event. * Log a single exposure event.
*/ */
fun log(event: ExposureEvent) { fun log(event: ExposureEvent) {
AppExecutor.logExecutor.execute { if (!exposureCache.contains(event.id)) {
if (event.payload.miniGameType == Constants.WECHAT_MINI_GAME_CPM) { exposureSet.add(event)
WGameSubjectCPMListReportHelper.reportExposure(event) exposureCache.add(event.id)
} } else {
if (!exposureCache.contains(event.id)) { Utils.log("Exposure", "遇到重复曝光事件,自动过滤 ${event.id} - ${event.payload.gameName}")
exposureSet.add(event)
exposureCache.add(event.id)
} else {
Utils.log("Exposure", "遇到重复曝光事件,自动过滤 ${event.id} - ${event.payload.gameName}")
}
} }
} }
@ -50,68 +42,53 @@ object ExposureManager {
* Log a collection of exposure event. * Log a collection of exposure event.
*/ */
fun log(eventList: List<ExposureEvent>) { fun log(eventList: List<ExposureEvent>) {
AppExecutor.logExecutor.execute { for (event in eventList) {
for (event in eventList) { if (!exposureCache.contains(event.id)) {
if (event != null && !exposureCache.contains(event.id)) { exposureSet.add(event)
exposureSet.add(event) exposureCache.add(event.id)
exposureCache.add(event.id) } else {
} else { Utils.log("Exposure", "遇到重复曝光事件,自动过滤 ${event.id} - ${event.payload.gameName}")
Utils.log("Exposure", "遇到重复曝光事件,自动过滤 ${event.id} - ${event.payload.gameName}")
}
}
commitSavedExposureEvents()
}
}
/**
* Log a wechat mini game cpm collection of exposure event.
*/
fun logCPM(eventList: List<ExposureEvent>) {
AppExecutor.logExecutor.execute {
if (eventList.isNotEmpty()) {
WGameSubjectCPMListReportHelper.reportExposure(eventList.toSet())
} }
} }
commitSavedExposureEvents()
} }
/** /**
* @param forcedUpload Ignore all restrictions. * @param forcedUpload Ignore all restrictions.
*/ */
fun commitSavedExposureEvents(forcedUpload: Boolean = false) { fun commitSavedExposureEvents(forcedUpload: Boolean = false) {
AppExecutor.logExecutor.execute { if (exposureSet.size < STORE_SIZE && !forcedUpload || exposureSet.size == 0) return
if (exposureSet.size < STORE_SIZE && !forcedUpload || exposureSet.size == 0) return@execute
uploadExposures(exposureSet, forcedUpload) uploadExposures(exposureSet.toList(), forcedUpload)
Utils.log("Exposure", "提交了${exposureSet.size}条曝光记录") Utils.log("Exposure", "提交了${exposureSet.size}条曝光记录")
exposureSet.clear() exposureSet.clear()
}
} }
private fun eliminateMultipleBrackets(jsonWithMultipleBracket: String): String { private fun eliminateMultipleBrackets(jsonWithMultipleBracket: String): String {
return jsonWithMultipleBracket.replace("[[", "[").replace("]]", "]") return jsonWithMultipleBracket.replace("[[", "[").replace("]]", "]")
} }
private fun uploadExposures(eventSet: HashSet<ExposureEvent>, forced: Boolean) { private fun uploadExposures(eventList: List<ExposureEvent>, forced: Boolean) {
eventSet.forEach { eventList.forEach {
TLogHubHelper.sendLog(buildLog(it), LOG_STORE) LoghubHelper.uploadLog(buildLog(it), LOG_STORE, forced)
// LoghubHelper.uploadLog(buildLog(it), LOG_STORE, forced) it.recycle()
// it.recycle()
} }
} }
private fun buildLog(event: ExposureEvent) = LogItem(System.currentTimeMillis()).apply { private fun buildLog(event: ExposureEvent) = Log().apply {
addContent("__id", event.id) putContent("id", event.id)
addContent("payload", event.payload.toJson()) putContent("payload", event.payload.toJson())
addContent("event", event.event.toString()) putContent("event", event.event.toString())
addContent("source", eliminateMultipleBrackets(event.source.toJson())) putContent("source", eliminateMultipleBrackets(event.source.toJson()))
addContent("meta", event.meta.toJson()) putContent("meta", event.meta.toJson())
addContent("real_millisecond", event.timeInMillisecond.toString()) putContent("real_millisecond", event.timeInMillisecond.toString())
addContent( putContent(
"e-traces", if (event.eTrace != null) { "e-traces", if (event.eTrace != null) {
eliminateMultipleBrackets(event.eTrace?.toJson() ?: "") eliminateMultipleBrackets(event.eTrace?.toJson() ?: "")
} else "" } else ""
) )
logTime = event.time.toLong()
} }
} }

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