Compare commits
3 Commits
feat/GHZSC
...
v5.22.1-79
| Author | SHA1 | Date | |
|---|---|---|---|
| 468e6b7c88 | |||
| 8ef59242d5 | |||
| 44c31e65b7 |
@ -1,12 +1,57 @@
|
||||
stages:
|
||||
- analysis
|
||||
- sendmail
|
||||
- android-build && analysis
|
||||
- docker-build && sendmail
|
||||
- deploy-trigger
|
||||
|
||||
## 代码检查
|
||||
android_build:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: android-build && analysis
|
||||
image: hub.shanqu.cc/devops/ci-android:jdk11
|
||||
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/meta_build.sh --config_id 6400549c21c2c94ead074500 --sdk_platform toutiao --sdk_version 5.3.0 --channel BD-GHZS-ZP-KY --activate_reporting_ratio 60 --first_lanuch_jump e1wibGlua190eXBlXCI6XCJcIixcImxpbmtfaWRcIjpcIlwiLFwibGlua190ZXh0XCI6XCJcIixcImhvbWVfaW5kZXhcIjpcIlwiLFwiYm90dG9tX2luZGV4XCI6XCJcIn0= --unix_timestamp 1677657618 --output ./release/com.gh.gamecenter_5.17.4_694_BD-GHZS-ZP-KY_toutiao_5.3.0_1677657618.apk
|
||||
- rm -rf ./.gradle/caches/build-cache-1
|
||||
cache:
|
||||
paths:
|
||||
- .gradle
|
||||
artifacts:
|
||||
paths:
|
||||
- Dockerfile
|
||||
expire_in: 15 mins
|
||||
only:
|
||||
- feature-meta_build
|
||||
|
||||
# 构建推送docker镜像
|
||||
docker-build:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: docker-build && sendmail
|
||||
image: hub.shanqu.cc/library/docker:latest
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
script:
|
||||
- projectPath=`echo $CI_PROJECT_PATH | sed 's#/#-#g'`
|
||||
- docker build -t registry.cn-shenzhen.aliyuncs.com/ghzs/$projectPath:latest .
|
||||
- docker push registry.cn-shenzhen.aliyuncs.com/ghzs/$projectPath:latest
|
||||
- docker run -e PROJECTKEY=$projectPath -e EMAIL=$GITLAB_USER_EMAIL -e BRANCH=$CI_COMMIT_REF_NAME --name send-email --rm hub.shanqu.cc/platform/send-sonar-report:latest
|
||||
cache:
|
||||
paths:
|
||||
- .gradle
|
||||
policy: pull
|
||||
only:
|
||||
- feature-meta_build
|
||||
|
||||
# 代码检查
|
||||
sonarqube_analysis:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: analysis
|
||||
stage: android-build && analysis
|
||||
image: sonarsource/sonar-scanner-cli:latest
|
||||
dependencies: [] #禁止传递来的artifact
|
||||
script:
|
||||
@ -27,17 +72,12 @@ sonarqube_analysis:
|
||||
-Dsonar.gitlab.merge_request_discussion=true
|
||||
-Dsonar.java.binaries=. # 如果不使用Maven或Gradle进行分析,则必须手动提供测试二进制文件
|
||||
only:
|
||||
- dev
|
||||
|
||||
## 发送简易检测结果报告
|
||||
send_sonar_report:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: sendmail
|
||||
image: hub.shanqu.cc/library/docker:latest
|
||||
dependencies: [] #禁止传递来的artifact
|
||||
script:
|
||||
- group=`echo $CI_PROJECT_PATH | sed 's#/#-#g'`
|
||||
- docker run -e PROJECTKEY=$group -e EMAIL=$GITLAB_USER_EMAIL --name send-email --rm hub.shanqu.cc/platform/send-sonar-report:latest
|
||||
only:
|
||||
- dev
|
||||
- feature-meta_build
|
||||
|
||||
## 触发多项目构建
|
||||
trigger_job:
|
||||
stage: deploy-trigger
|
||||
trigger:
|
||||
project: devops/automation/build-eci
|
||||
branch: dev
|
||||
|
||||
|
||||
8
.gitmodules
vendored
8
.gitmodules
vendored
@ -1,13 +1,13 @@
|
||||
[submodule "libraries/LGLibrary"]
|
||||
path = libraries/LGLibrary
|
||||
url = git@git.shanqu.cc:android/common-library.git
|
||||
url = ../../../android/common-library.git
|
||||
branch = master
|
||||
[submodule "vspace-bridge"]
|
||||
path = vspace-bridge
|
||||
url = git@git.shanqu.cc: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 = git@git.shanqu.cc:halo/android/assistant-android-mock.git
|
||||
url = ../../../halo/android/assistant-android-mock.git
|
||||
[submodule "ndownload"]
|
||||
path = ndownload
|
||||
url = git@git.shanqu.cc:android/ndownload.git
|
||||
url = ../../../android/ndownload.git
|
||||
|
||||
15
Dockerfile
Normal file
15
Dockerfile
Normal file
@ -0,0 +1,15 @@
|
||||
FROM openjdk:11-jdk
|
||||
WORKDIR /project
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
#配置SDK环境变量
|
||||
ENV ANDROID_SDK_ROOT /usr/lib/sdk
|
||||
ENV ANDROID_HOME /usr/lib/sdk
|
||||
ENV PATH $ANDROID_SDK_ROOT:$PATH
|
||||
ENV PATH=$PATH:${ANDROID_HOME}/cmdline-tools/cmdline-tools/bin/
|
||||
ENV GRADLE_USER_HOME /project/.gradle
|
||||
RUN source ~/.bashrc
|
||||
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 install --yes lib32stdc++6 lib32z1 libncurses5 util-linux bash tzdata librdkafka-dev pkgconf \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
COPY .gradle /project/.gradle
|
||||
@ -9,6 +9,9 @@ import groovy.xml.XmlUtil
|
||||
|
||||
android {
|
||||
|
||||
String CONFIG_ID = ""
|
||||
String FIRST_LAUNCH = ""
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
dataBinding true
|
||||
@ -67,9 +70,13 @@ android {
|
||||
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-fresco.txt'
|
||||
|
||||
/**
|
||||
* All third-party appid/appkey
|
||||
*/
|
||||
// 推广用的配置 id
|
||||
buildConfigField "String", "CONFIG_ID", "\"${CONFIG_ID}\""
|
||||
|
||||
// 首次启动的跳转配置
|
||||
buildConfigField "String", "FIRST_LAUNCH", "\"${FIRST_LAUNCH}\""
|
||||
|
||||
// All third-party appid/appkey
|
||||
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "NEW_API_HOST", "\"${NEW_API_HOST}\""
|
||||
buildConfigField "String", "VAPI_HOST", "\"${VAPI_HOST}\""
|
||||
@ -312,6 +319,7 @@ dependencies {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
implementation(project(':module_vpn'))
|
||||
implementation(project(':module_pkg'))
|
||||
// 默认不接入光能模块,提高编译速度
|
||||
// debugImplementation(project(':module_energy')) {
|
||||
// exclude group: 'androidx.swiperefreshlayout'
|
||||
|
||||
@ -119,6 +119,8 @@
|
||||
android:name="io.sentry.breadcrumbs.system-events"
|
||||
android:value="false" />
|
||||
|
||||
<service android:name = "com.gh.ndownload.NDownloadService" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SplashScreenActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
|
||||
@ -593,6 +593,7 @@ public class BindingAdapters {
|
||||
case pause:
|
||||
case timeout:
|
||||
case neterror:
|
||||
case diskisfull:
|
||||
case waiting:
|
||||
progressBar.setText(R.string.downloading);
|
||||
if (downloadEntity.isPluggable() && PackagesManager.INSTANCE.isInstalled(downloadEntity.getPackageName())) {
|
||||
|
||||
@ -22,8 +22,12 @@ import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity
|
||||
import com.gh.gamecenter.feature.entity.SimulatorEntity
|
||||
import com.gh.gamecenter.entity.TrackableEntity
|
||||
import com.gh.ndownload.NDataChanger
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.*
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
import com.lightgame.download.FileUtils
|
||||
import com.lightgame.utils.Utils
|
||||
import java.lang.ref.WeakReference
|
||||
import java.text.DecimalFormat
|
||||
@ -95,6 +99,9 @@ class SimulatorDownloadManager private constructor() {
|
||||
downloadDialog?.dismiss()
|
||||
}
|
||||
}
|
||||
DownloadStatus.diskisfull == downloadEntity.status -> {
|
||||
ToastUtils.showToast("存储空间已满,下载任务已暂停")
|
||||
}
|
||||
DownloadStatus.neterror == downloadEntity.status -> {
|
||||
ToastUtils.showToast("网络不稳定,下载任务已暂停")
|
||||
}
|
||||
@ -290,13 +297,16 @@ class SimulatorDownloadManager private constructor() {
|
||||
HaloApp.put(simulator.name, simulator)
|
||||
if (entity != null) {
|
||||
when (entity.status) {
|
||||
DownloadStatus.pause, DownloadStatus.subscribe,
|
||||
DownloadStatus.neterror, DownloadStatus.timeout -> {
|
||||
DownloadStatus.pause,
|
||||
DownloadStatus.subscribe,
|
||||
DownloadStatus.neterror,
|
||||
DownloadStatus.timeout,
|
||||
DownloadStatus.diskisfull -> {
|
||||
DownloadManager.getInstance().addObserver(dataWatcher)
|
||||
uiExecutor.executeWithDelay(Runnable { DownloadManager.getInstance().resume(entity, true) }, 200)
|
||||
downloadDialog?.show()
|
||||
}
|
||||
DownloadStatus.done -> DataChanger.notifyDataChanged(entity)
|
||||
DownloadStatus.done -> NDataChanger.notifyDataChanged(entity)
|
||||
|
||||
else -> createDownload(apkEntity, simulator)
|
||||
}
|
||||
|
||||
@ -262,6 +262,7 @@ public class DetailDownloadUtils {
|
||||
case downloading:
|
||||
case redirected:
|
||||
case pause:
|
||||
case diskisfull:
|
||||
case overflow:
|
||||
String downloadingText = "游戏加载中 " + downloadEntity.getPercent() + "%";
|
||||
String resumeText = "继续加载 " + downloadEntity.getPercent() + "%";
|
||||
@ -348,6 +349,7 @@ public class DetailDownloadUtils {
|
||||
case timeout:
|
||||
case neterror:
|
||||
case subscribe:
|
||||
case diskisfull:
|
||||
case pause:
|
||||
viewHolder.mDownloadPb.setText("继续加载 " + viewHolder.downloadEntity.getPercent() + "%");
|
||||
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.DOWNLOADING_NORMAL);
|
||||
|
||||
@ -310,6 +310,7 @@ object DownloadItemUtils {
|
||||
DownloadStatus.timeout,
|
||||
DownloadStatus.neterror,
|
||||
DownloadStatus.subscribe,
|
||||
DownloadStatus.diskisfull,
|
||||
DownloadStatus.overflow -> {
|
||||
buttonStyle = DownloadButton.ButtonStyle.NORMAL
|
||||
setText(R.string.resume)
|
||||
@ -429,6 +430,7 @@ object DownloadItemUtils {
|
||||
DownloadStatus.pause,
|
||||
DownloadStatus.timeout,
|
||||
DownloadStatus.neterror,
|
||||
DownloadStatus.diskisfull,
|
||||
DownloadStatus.subscribe,
|
||||
DownloadStatus.overflow -> {
|
||||
if (isMultiVersion) {
|
||||
|
||||
@ -98,18 +98,19 @@ object DownloadNotificationHelper {
|
||||
DownloadStatus.waiting -> builder.setContentText("等待中")
|
||||
DownloadStatus.subscribe,
|
||||
DownloadStatus.timeout,
|
||||
DownloadStatus.diskisfull,
|
||||
DownloadStatus.neterror -> builder.setContentText("已暂停,连接WiFi自动下载")
|
||||
else -> builder.setContentText("暂停中")
|
||||
}
|
||||
builder.setProgress(PROGRESS_MAX, entity.percent.toInt(), false)
|
||||
}
|
||||
|
||||
when {
|
||||
entity.status == DownloadStatus.done -> {
|
||||
when (entity.status) {
|
||||
DownloadStatus.done -> {
|
||||
builder.setSortKey("A")
|
||||
builder.setOngoing(true) // 垃圾华为 sortKey 不起效 priority 也不起效,要将下载完成任务的通知置顶只能设置为 ongoing,喷了
|
||||
}
|
||||
entity.status == DownloadStatus.downloading -> builder.setSortKey("B")
|
||||
DownloadStatus.downloading -> builder.setSortKey("B")
|
||||
else -> builder.setSortKey("C")
|
||||
}
|
||||
|
||||
|
||||
@ -87,7 +87,9 @@ object DownloadObserver {
|
||||
)
|
||||
}, extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true))
|
||||
return
|
||||
} else if (DownloadStatus.neterror == downloadEntity.status || DownloadStatus.timeout == downloadEntity.status) {
|
||||
} else if (DownloadStatus.neterror == downloadEntity.status
|
||||
|| DownloadStatus.timeout == downloadEntity.status
|
||||
|| DownloadStatus.diskisfull == downloadEntity.status) {
|
||||
if (downloadEntity.meta[Constants.MARK_RETRY_DOWNLOAD].isNullOrEmpty()
|
||||
&& NetworkUtils.isWifiConnected(HaloApp.getInstance().application)
|
||||
) {
|
||||
@ -98,7 +100,12 @@ object DownloadObserver {
|
||||
Utils.log("DownloadObserver", "下载重试->" + downloadEntity.toJson())
|
||||
}
|
||||
} else {
|
||||
Utils.toast(mApplication, "网络不稳定,下载任务已暂停")
|
||||
if (DownloadStatus.diskisfull == downloadEntity.status) {
|
||||
ToastUtils.toast("磁盘已满,请清理空间后重试下载")
|
||||
} else {
|
||||
ToastUtils.toast("网络不稳定,下载任务已暂停")
|
||||
}
|
||||
|
||||
DataLogUtils.uploadNeterrorLog(mApplication, downloadEntity)
|
||||
|
||||
debugOnly {
|
||||
|
||||
@ -1,16 +1,17 @@
|
||||
package com.gh.common.xapk
|
||||
|
||||
import android.content.Context
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.DownloadNotificationHelper
|
||||
import com.gh.common.util.PackageInstaller
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.common.utils.debugOnly
|
||||
import com.gh.gamecenter.common.utils.getExtension
|
||||
import com.gh.gamecenter.common.utils.throwExceptionInDebug
|
||||
import com.gh.gamecenter.common.utils.tryCatchInRelease
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.SentryHelper
|
||||
import com.gh.ndownload.NDataChanger
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DataChanger
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.utils.Utils
|
||||
import java.text.DecimalFormat
|
||||
@ -81,7 +82,7 @@ object XapkInstaller : IXapkUnzipListener {
|
||||
}
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = percent.toString()
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.UNZIPPING.name
|
||||
DataChanger.notifyDataChanged(downloadEntity)
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
}
|
||||
|
||||
debugOnly {
|
||||
@ -111,7 +112,7 @@ object XapkInstaller : IXapkUnzipListener {
|
||||
AppExecutor.uiExecutor.execute {
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "0.0"
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.CANCEL.name
|
||||
DataChanger.notifyDataChanged(downloadEntity)
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
}
|
||||
}
|
||||
@ -122,7 +123,7 @@ object XapkInstaller : IXapkUnzipListener {
|
||||
AppExecutor.uiExecutor.execute {
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.FAILURE.name
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
|
||||
DataChanger.notifyDataChanged(downloadEntity)
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
}
|
||||
|
||||
@ -156,7 +157,7 @@ object XapkInstaller : IXapkUnzipListener {
|
||||
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "100.0"
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.SUCCESS.name
|
||||
DataChanger.notifyDataChanged(downloadEntity)
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
}
|
||||
|
||||
|
||||
@ -13,8 +13,8 @@ import com.gh.gamecenter.common.utils.getExtension
|
||||
import com.gh.gamecenter.common.utils.getMetaExtra
|
||||
import com.gh.gamecenter.common.utils.isSimulatorGame
|
||||
import com.gh.gamecenter.core.utils.SentryHelper
|
||||
import com.gh.ndownload.NDataChanger
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DataChanger
|
||||
import com.lightgame.download.DownloadConfig
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
@ -128,6 +128,7 @@ object DownloadDataHelper {
|
||||
payloadObject.put("platform", downloadEntity.platform)
|
||||
payloadObject.put("package", downloadEntity.packageName)
|
||||
payloadObject.put("filename", getFileName(downloadEntity))
|
||||
payloadObject.put("task_num", NDataChanger.downloadingTasks.size)
|
||||
jsonObject.put("payload", payloadObject)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
@ -202,6 +203,8 @@ object DownloadDataHelper {
|
||||
|
||||
// payload
|
||||
val payloadObject = JSONObject()
|
||||
val parallel = downloadEntity.meta[DOWNLOAD_THREAD_SIZE]?.toInt()
|
||||
|
||||
payloadObject.put("host", downloadEntity.meta[DownloadEntity.DOWNLOAD_HOST_KEY] ?: "unknown")
|
||||
payloadObject.put("path", downloadEntity.meta[DownloadEntity.DOWNLOAD_PATH_KEY] ?: "unknown")
|
||||
payloadObject.put("game_id", downloadEntity.gameId)
|
||||
@ -210,7 +213,10 @@ object DownloadDataHelper {
|
||||
payloadObject.put("package", downloadEntity.packageName)
|
||||
payloadObject.put("filename", getFileName(downloadEntity))
|
||||
payloadObject.put("launch_ms", startupTime)
|
||||
payloadObject.put("parallel", downloadEntity.meta[DOWNLOAD_THREAD_SIZE]?.toInt() ?: 0)
|
||||
payloadObject.put("task_num", NDataChanger.downloadingTasks.size)
|
||||
if (parallel != null) {
|
||||
payloadObject.put("parallel", parallel)
|
||||
}
|
||||
jsonObject.put("payload", payloadObject)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
@ -234,7 +240,9 @@ object DownloadDataHelper {
|
||||
|
||||
// payload
|
||||
val payloadObject = JSONObject()
|
||||
val parallel = downloadEntity.meta[DOWNLOAD_THREAD_SIZE]?.toInt()
|
||||
val sizeInMB = downloadEntity.size / 1024 / 1024
|
||||
|
||||
payloadObject.put("host", downloadEntity.meta[DownloadEntity.DOWNLOAD_HOST_KEY] ?: "unknown")
|
||||
payloadObject.put("path", downloadEntity.meta[DownloadEntity.DOWNLOAD_PATH_KEY] ?: "unknown")
|
||||
payloadObject.put("game_id", downloadEntity.gameId)
|
||||
@ -243,7 +251,9 @@ object DownloadDataHelper {
|
||||
payloadObject.put("package", downloadEntity.packageName)
|
||||
payloadObject.put("filename", getFileName(downloadEntity))
|
||||
payloadObject.put("total_size", sizeInMB)
|
||||
payloadObject.put("parallel", downloadEntity.meta[DOWNLOAD_THREAD_SIZE]?.toInt() ?: 0)
|
||||
if (parallel != null) {
|
||||
payloadObject.put("parallel", parallel)
|
||||
}
|
||||
|
||||
if (statusAlias == "下载完成") {
|
||||
val elapsedTimeString = downloadEntity.meta[DownloadConfig.KEY_DOWNLOAD_ELAPSED_TIME]
|
||||
@ -264,7 +274,7 @@ object DownloadDataHelper {
|
||||
payloadObject.put("speed", speed)
|
||||
}
|
||||
} else {
|
||||
payloadObject.put("task_num", DataChanger.downloadingTasks.size)
|
||||
payloadObject.put("task_num", NDataChanger.downloadingTasks.size)
|
||||
}
|
||||
payloadObject.put("completed_size", downloadEntity.progress / 1024 / 1024)
|
||||
if (downloadEntity.status == DownloadStatus.resume) {
|
||||
@ -301,6 +311,8 @@ object DownloadDataHelper {
|
||||
|
||||
// payload
|
||||
val payloadObject = JSONObject()
|
||||
val parallel = downloadEntity.meta[DOWNLOAD_THREAD_SIZE]?.toInt()
|
||||
|
||||
payloadObject.put("host", downloadEntity.meta[DownloadEntity.DOWNLOAD_HOST_KEY] ?: "unknown")
|
||||
payloadObject.put("path", downloadEntity.meta[DownloadEntity.DOWNLOAD_PATH_KEY] ?: "unknown")
|
||||
payloadObject.put("game_id", downloadEntity.gameId)
|
||||
@ -311,8 +323,10 @@ object DownloadDataHelper {
|
||||
payloadObject.put("speed_progress", JSONArray(averageSpeedList))
|
||||
payloadObject.put("is_finished", downloadEntity.status == DownloadStatus.done)
|
||||
payloadObject.put("completed_size", downloadEntity.progress / 1024 / 1024)
|
||||
payloadObject.put("parallel", downloadEntity.meta[DOWNLOAD_THREAD_SIZE]?.toInt() ?: 0)
|
||||
payloadObject.put("task_num", DataChanger.downloadingTasks.size)
|
||||
if (parallel != null) {
|
||||
payloadObject.put("parallel", parallel)
|
||||
}
|
||||
payloadObject.put("task_num", NDataChanger.downloadingTasks.size)
|
||||
jsonObject.put("payload", payloadObject)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
@ -335,7 +349,7 @@ object DownloadDataHelper {
|
||||
* 在后台唤醒的情况下 下载状态可能无法修正
|
||||
* see [DownloadManager.initDownloadService]
|
||||
*/
|
||||
if (downloadEntity.status == DownloadStatus.downloading && DataChanger.downloadingTasks[downloadEntity.url] != null) {
|
||||
if (downloadEntity.status == DownloadStatus.downloading && NDataChanger.downloadingTasks[downloadEntity.url] != null) {
|
||||
var sheet = mDownloadHeartbeatSheet[downloadEntity.url]
|
||||
if (sheet == null) {
|
||||
sheet = JSONObject()
|
||||
|
||||
@ -49,17 +49,17 @@ import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.gh.gamecenter.login.user.UserManager;
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository;
|
||||
import com.gh.ndownload.NDataChanger;
|
||||
import com.gh.ndownload.NDownloadBridge;
|
||||
import com.gh.ndownload.NDownloadService;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.download.ConnectionUtils;
|
||||
import com.lightgame.download.DataChanger;
|
||||
import com.lightgame.download.DataWatcher;
|
||||
import com.lightgame.download.DownloadConfig;
|
||||
import com.lightgame.download.DownloadDao;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.DownloadService;
|
||||
import com.lightgame.download.DownloadStatus;
|
||||
import com.lightgame.download.DownloadStatusListener;
|
||||
import com.lightgame.download.DownloadStatusManager;
|
||||
import com.lightgame.download.DownloadTask;
|
||||
import com.lightgame.download.FileUtils;
|
||||
import com.lightgame.download.HttpDnsManager;
|
||||
@ -91,9 +91,9 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
private final Map<String, ConcurrentHashMap<String, DownloadEntity>> gameMap;
|
||||
|
||||
private final ArrayMap<String, DownloadStatus> statusMap;
|
||||
private final ArrayMap<String, DownloadEntity> downloadingMap;
|
||||
private final ConcurrentHashMap<String, DownloadEntity> downloadingMap;
|
||||
|
||||
private ArrayList<DownloadEntity> mInvisiblePendingTaskList; // 用户不可见的 pending 任务
|
||||
private final ArrayList<DownloadEntity> mInvisiblePendingTaskList; // 用户不可见的 pending 任务
|
||||
private final DownloadDao mDownloadDao;
|
||||
private final DownloadedGameIdAndPackageNameDao mDownloadedGameIdAndPackageNameDao;
|
||||
|
||||
@ -169,8 +169,6 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
|
||||
mUpdateMarks = SPUtils.getStringSet(UPDATE_IS_READ_MARK);
|
||||
|
||||
DownloadStatusManager.getInstance().registerTaskStatusListener(this);
|
||||
|
||||
// 只有下载模块需要这坨东西,因此移动到这里初始化
|
||||
ConnectionUtils.initHttpsUrlConnection(mContext);
|
||||
|
||||
@ -180,7 +178,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
platformMap = new ArrayMap<>();
|
||||
gameMap = new ConcurrentHashMap<>();
|
||||
statusMap = new ArrayMap<>();
|
||||
downloadingMap = new ArrayMap<>();
|
||||
downloadingMap = new ConcurrentHashMap<>();
|
||||
// mDownloadSnapshotList = new ArrayList<>();
|
||||
mInvisiblePendingTaskList = new ArrayList<>();
|
||||
|
||||
@ -226,10 +224,6 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayMap<String, DownloadEntity> getDownloadingMap() {
|
||||
return downloadingMap;
|
||||
}
|
||||
|
||||
public static DownloadManager getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
@ -444,7 +438,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
|
||||
if (isDownloadCompleted(url)) {
|
||||
downloadEntity.setStatus(DownloadStatus.done);
|
||||
DataChanger.INSTANCE.notifyDataChanged(downloadEntity);
|
||||
NDataChanger.INSTANCE.notifyDataChanged(downloadEntity);
|
||||
} else if (!isTaskDownloading(url)) {
|
||||
startDownloadService(downloadEntity, DownloadStatus.add);
|
||||
}
|
||||
@ -465,7 +459,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
checkDownloadEntryRecordValidate(url);
|
||||
if (isDownloadCompleted(url)) {
|
||||
downloadEntity.setStatus(DownloadStatus.done);
|
||||
DataChanger.INSTANCE.notifyDataChanged(downloadEntity);
|
||||
NDataChanger.INSTANCE.notifyDataChanged(downloadEntity);
|
||||
} else if (!isTaskDownloading(url)) {
|
||||
DownloadEntity daoEntity = mDownloadDao.get(downloadEntity.getUrl());
|
||||
if (automatic) {
|
||||
@ -500,7 +494,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
checkDownloadEntryRecordValidate(url);
|
||||
if (isDownloadCompleted(url)) {
|
||||
downloadEntity.setStatus(DownloadStatus.done);
|
||||
DataChanger.INSTANCE.notifyDataChanged(downloadEntity);
|
||||
NDataChanger.INSTANCE.notifyDataChanged(downloadEntity);
|
||||
} else if (!isTaskDownloading(url)) {
|
||||
startDownloadService(downloadEntity, DownloadStatus.subscribe);
|
||||
}
|
||||
@ -546,7 +540,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
* 任务是否已经下载中
|
||||
*/
|
||||
public boolean isTaskDownloading(String url) {
|
||||
if (DataChanger.INSTANCE.getDownloadingTasks().get(url) != null) {
|
||||
if (NDataChanger.INSTANCE.getDownloadingTasks().get(url) != null) {
|
||||
Utils.log(DownloadManager.class.getSimpleName(), url + "正在下载!");
|
||||
return true;
|
||||
}
|
||||
@ -554,7 +548,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
}
|
||||
|
||||
private Intent getIntent(DownloadEntity entry, DownloadStatus status) {
|
||||
Intent service = new Intent(mContext, DownloadService.class);
|
||||
Intent service = new Intent(mContext, NDownloadService.class);
|
||||
service.putExtra(DownloadConfig.KEY_DOWNLOAD_ENTRY, entry);
|
||||
service.putExtra(DownloadConfig.KEY_DOWNLOAD_ACTION, status.name());
|
||||
return service;
|
||||
@ -583,6 +577,16 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
return mDownloadDao.getAllSnapshots();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取快照
|
||||
*
|
||||
* @param url 下载地址
|
||||
*/
|
||||
@Nullable
|
||||
public DownloadEntity getDownloadEntitySnapshot(String url) {
|
||||
return mDownloadDao.getSnapshot(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取快照
|
||||
*
|
||||
@ -823,6 +827,8 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
DownloadEntity entry = mDownloadDao.getSnapshot(url);
|
||||
if (entry != null) {
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
NDownloadBridge.INSTANCE.cancel(url);
|
||||
|
||||
mDownloadDao.delete(url);
|
||||
|
||||
if (isDeleteFile) {
|
||||
@ -856,19 +862,16 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
private void cancelAndNotify(DownloadEntity entry, boolean cancelSilently) {
|
||||
mDownloadDao.removeErrorMessage(entry.getUrl());
|
||||
|
||||
DownloadTask task = DataChanger.INSTANCE.getDownloadingTasks().get(entry.getUrl());
|
||||
DownloadTask task = NDataChanger.INSTANCE.getDownloadingTasks().get(entry.getUrl());
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
// 改任务队列的状态
|
||||
DataChanger.INSTANCE.getDownloadingTasks().remove(entry.getUrl());
|
||||
if (!cancelSilently) {
|
||||
DataChanger.INSTANCE.notifyDataChanged(entry);
|
||||
}
|
||||
NDataChanger.INSTANCE.getDownloadingTasks().remove(entry.getUrl());
|
||||
}
|
||||
DataChanger.INSTANCE.getDownloadEntries().remove(entry.getUrl());
|
||||
NDataChanger.INSTANCE.getDownloadEntries().remove(entry.getUrl());
|
||||
if (!cancelSilently) {
|
||||
DataChanger.INSTANCE.notifyDataChanged(entry);
|
||||
DownloadStatusManager.getInstance().onTaskCancelled(entry);
|
||||
NDataChanger.INSTANCE.notifyDataChanged(entry);
|
||||
onTaskCancelled(entry);
|
||||
}
|
||||
|
||||
Utils.log(DownloadManager.class.getSimpleName(), "cancel");
|
||||
@ -878,7 +881,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
* 暂停所有正在下载的任务
|
||||
*/
|
||||
public void pauseAll() {
|
||||
for (DownloadEntity entity : DataChanger.INSTANCE.getDownloadEntries().values()) {
|
||||
for (DownloadEntity entity : NDataChanger.INSTANCE.getDownloadEntries().values()) {
|
||||
pause(entity.getUrl());
|
||||
}
|
||||
Utils.log(DownloadManager.class.getSimpleName(), "pause all");
|
||||
@ -889,7 +892,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
*/
|
||||
public void pause(String url) {
|
||||
checkDownloadEntryRecordValidate(url);
|
||||
DownloadEntity entry = DataChanger.INSTANCE.getDownloadEntries().get(url);
|
||||
DownloadEntity entry = NDataChanger.INSTANCE.getDownloadEntries().get(url);
|
||||
if (entry != null) {
|
||||
startDownloadService(entry, DownloadStatus.pause);
|
||||
put(url, System.currentTimeMillis());
|
||||
@ -905,14 +908,14 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
* 3.检查是否显示下载通知栏
|
||||
*/
|
||||
public void initDownloadService() {
|
||||
final List<String> urlList = new ArrayList<>(DataChanger.INSTANCE.getDownloadingTasks().keySet());
|
||||
final List<String> urlList = new ArrayList<>(NDataChanger.INSTANCE.getDownloadingTasks().keySet());
|
||||
for (DownloadEntity downloadEntity : getAllDownloadEntity()) {
|
||||
if (!urlList.contains(downloadEntity.getUrl()) &&
|
||||
(downloadEntity.getStatus().equals(DownloadStatus.downloading)
|
||||
|| downloadEntity.getStatus().equals(DownloadStatus.waiting))) {
|
||||
downloadEntity.setStatus(DownloadStatus.subscribe);
|
||||
mDownloadDao.newOrUpdate(downloadEntity);
|
||||
DataChanger.INSTANCE.notifyDataChanged(downloadEntity);
|
||||
NDataChanger.INSTANCE.notifyDataChanged(downloadEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@ -925,7 +928,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
*/
|
||||
public void addObserver(DataWatcher dataWatcher) {
|
||||
Utils.log(DownloadManager.class.getSimpleName(), "addObserver");
|
||||
DataChanger.INSTANCE.addObserver(dataWatcher);
|
||||
NDataChanger.INSTANCE.addObserver(dataWatcher);
|
||||
|
||||
notifyDownloadStatusASAP(dataWatcher);
|
||||
}
|
||||
@ -935,7 +938,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
*/
|
||||
public void removeObserver(DataWatcher dataWatcher) {
|
||||
Utils.log(DownloadManager.class.getSimpleName(), "removeObserver");
|
||||
DataChanger.INSTANCE.deleteObserver(dataWatcher);
|
||||
NDataChanger.INSTANCE.deleteObserver(dataWatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -951,11 +954,11 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
* 初始化下载服务
|
||||
*/
|
||||
public void startDownloadService() {
|
||||
Intent serviceIntent = new Intent(mContext, DownloadService.class);
|
||||
Intent serviceIntent = new Intent(mContext, NDownloadService.class);
|
||||
// 当满足系统版本大于 8.0 并且应用在后台运行时以前台服务开启
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
|
||||
&& !PackageUtils.isAppOnForeground(mContext)) {
|
||||
serviceIntent.putExtra(DownloadService.KEY_SERVICE_ACTION, DownloadService.START_FOREGROUND);
|
||||
serviceIntent.putExtra(NDownloadService.KEY_SERVICE_ACTION, NDownloadService.START_FOREGROUND);
|
||||
mContext.startForegroundService(serviceIntent);
|
||||
} else {
|
||||
/*
|
||||
@ -995,7 +998,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
// 当满足系统版本大于 8.0 并且应用在后台运行时以前台服务开启
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
|
||||
&& !PackageUtils.isAppOnForeground(mContext)) {
|
||||
serviceIntent.putExtra(DownloadService.KEY_SERVICE_ACTION, DownloadService.START_FOREGROUND);
|
||||
serviceIntent.putExtra(NDownloadService.KEY_SERVICE_ACTION, NDownloadService.START_FOREGROUND);
|
||||
mContext.startForegroundService(serviceIntent);
|
||||
} else {
|
||||
mContext.startService(serviceIntent);
|
||||
@ -1126,7 +1129,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
String mark = downloadEntity.getMeta().get(DOWNLOADED_IS_READ_MARK);
|
||||
if (TextUtils.isEmpty(mark)) {
|
||||
downloadEntity.getMeta().put(DOWNLOADED_IS_READ_MARK, DOWNLOADED_IS_READ_MARK);
|
||||
mDownloadDao.newOrUpdate(downloadEntity);
|
||||
mDownloadDao.update(downloadEntity, false);
|
||||
if (!markHasChanged) markHasChanged = true;
|
||||
}
|
||||
}
|
||||
@ -1166,12 +1169,12 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
String mark = downloadEntity.getMeta().get(DOWNLOADING_IS_READ_MARK);
|
||||
if (TextUtils.isEmpty(mark)) {
|
||||
downloadEntity.getMeta().put(DOWNLOADING_IS_READ_MARK, DOWNLOADING_IS_READ_MARK);
|
||||
mDownloadDao.newOrUpdate(downloadEntity);
|
||||
mDownloadDao.update(downloadEntity, false);
|
||||
if (!markHasChanged) markHasChanged = true;
|
||||
}
|
||||
} else {
|
||||
downloadEntity.getMeta().put(DOWNLOADING_IS_READ_MARK, "");
|
||||
mDownloadDao.newOrUpdate(downloadEntity);
|
||||
mDownloadDao.update(downloadEntity, false);
|
||||
if (!markHasChanged) markHasChanged = true;
|
||||
}
|
||||
}
|
||||
@ -1229,7 +1232,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
* 更新数据库中的下载实体
|
||||
*/
|
||||
public void updateDownloadEntity(DownloadEntity downloadEntity) {
|
||||
mDownloadDao.newOrUpdate(downloadEntity);
|
||||
mDownloadDao.update(downloadEntity, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -83,10 +83,6 @@ object DownloadMessageHandler : InnerDownloadListener {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDownloadComplete(id: String?, elapsedTime: Long) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* 重定向中的回调
|
||||
* @param id 下载 id
|
||||
@ -218,6 +214,10 @@ object DownloadMessageHandler : InnerDownloadListener {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
override fun onDownloadComplete(id: String?, elapsedTime: Long) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
fun registerListener(id: String, listener: DownloadListener) {
|
||||
var listenerList = mListenerMap[id]
|
||||
if (listenerList == null) {
|
||||
|
||||
@ -37,6 +37,7 @@ import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.entity.PrivacyPolicyEntity
|
||||
import com.gh.gamecenter.feature.utils.PlatformUtils
|
||||
import com.gh.gamecenter.pkg.PkgHelper
|
||||
import com.gh.vspace.VHelper
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.FileUtils
|
||||
@ -386,6 +387,10 @@ class SplashScreenActivity : BaseActivity() {
|
||||
checkAndPostUsageStats()
|
||||
updateGameSubstituteRepository()
|
||||
|
||||
if (BuildConfig.CONFIG_ID.isNotEmpty()) {
|
||||
PkgHelper.requestPkgConfig(BuildConfig.CONFIG_ID)
|
||||
}
|
||||
|
||||
// 获取自动刷新的cd,获取版本对应表
|
||||
val time = mSharedPreferences!!.getString("refresh_time", null)
|
||||
val format = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
|
||||
|
||||
@ -161,7 +161,8 @@ public class GameDownloadFragment extends BaseFragment implements View.OnClickLi
|
||||
adapter.notifyItemChanged(adapter.getBase() + location + 1);
|
||||
}
|
||||
}
|
||||
if (downloadEntity.getStatus() == DownloadStatus.neterror) {
|
||||
if (downloadEntity.getStatus() == DownloadStatus.neterror
|
||||
|| downloadEntity.getStatus() == DownloadStatus.diskisfull) {
|
||||
adapter.notifyItemChanged(adapter.getBase());
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -231,6 +231,7 @@ class GameDownloadFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
} else if (status.equals(DownloadStatus.pause)
|
||||
|| status.equals(DownloadStatus.timeout)
|
||||
|| status.equals(DownloadStatus.neterror)
|
||||
|| status.equals(DownloadStatus.diskisfull)
|
||||
|| status.equals(DownloadStatus.subscribe)) {
|
||||
viewHolder.binding.dmItemTvStartorpause.setText(R.string.resume);
|
||||
viewHolder.binding.dmItemTvStartorpause.setButtonStyle(DownloadButton.ButtonStyle.NORMAL);
|
||||
@ -240,6 +241,8 @@ class GameDownloadFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
|| status.equals(DownloadStatus.neterror)
|
||||
|| status.equals(DownloadStatus.subscribe)) {
|
||||
viewHolder.binding.dmItemTvSpeed.setText("等待WIFI");
|
||||
} else if (status.equals(DownloadStatus.diskisfull)) {
|
||||
viewHolder.binding.dmItemTvSpeed.setText("已暂停,磁盘空间不足");
|
||||
} else {
|
||||
viewHolder.binding.dmItemTvSpeed.setText("已暂停");
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import com.gh.gamecenter.common.utils.singleToMain
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.entity.HomeDataEntity
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
import com.gh.gamecenter.pkg.PkgHelper
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
@ -64,6 +65,20 @@ class HomeSearchToolWrapperViewModel(application: Application) : AndroidViewMode
|
||||
if (homeTab.size == 0) {
|
||||
homeTab.add(SubjectRecommendEntity(type = "home"))
|
||||
}
|
||||
|
||||
// 从推广包配置信息里找是否需要默认选中一个 tab
|
||||
PkgHelper.getPkgConfig(true)?.let { pkgLinkEntity ->
|
||||
if (pkgLinkEntity.shouldStayAtHomePage) {
|
||||
for ((index, tab) in homeTab.withIndex()) {
|
||||
if (pkgLinkEntity.type == tab.type
|
||||
&& (pkgLinkEntity.link == tab.link || tab.link == null)) {
|
||||
defaultTabPosition = index
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isRefresh) {
|
||||
tabs.postValue(homeTab)
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ import com.facebook.imagepipeline.image.ImageInfo;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.PrivacyPolicyDialogFragment;
|
||||
import com.gh.common.dialog.ReserveDialog;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.util.HomeBottomBarHelper;
|
||||
import com.gh.common.util.IntegralLogHelper;
|
||||
import com.gh.common.util.LogUtils;
|
||||
@ -41,6 +42,7 @@ import com.gh.gamecenter.common.callback.BiCallback;
|
||||
import com.gh.gamecenter.common.callback.OnDoubleTapListener;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
import com.gh.gamecenter.common.entity.PkgConfigEntity;
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.common.syncpage.SyncPageRepository;
|
||||
import com.gh.gamecenter.common.tracker.TrackerLogger;
|
||||
@ -67,6 +69,7 @@ import com.gh.gamecenter.login.entity.UserInfoEntity;
|
||||
import com.gh.gamecenter.message.MessageUnreadRepository;
|
||||
import com.gh.gamecenter.message.MessageUnreadViewModel;
|
||||
import com.gh.gamecenter.personal.HaloPersonalFragment;
|
||||
import com.gh.gamecenter.pkg.PkgHelper;
|
||||
import com.gh.gamecenter.servers.GameServersPublishFragment;
|
||||
import com.gh.gamecenter.servers.GameServersTestFragment;
|
||||
import com.gh.gamecenter.subject.SubjectFragment;
|
||||
@ -271,6 +274,43 @@ public class MainWrapperFragment extends BaseFragment_ViewPager_Checkable implem
|
||||
.getUnreadMessageTotalLiveData().observe(this, isShow -> ExtensionsKt.goneIf(mBinding.mainIvMessageHint, !isShow));
|
||||
}
|
||||
|
||||
private void applyPkgConfig() {
|
||||
PkgConfigEntity.PkgLinkEntity pkgLinkEntity = PkgHelper.INSTANCE.getPkgConfig(false);
|
||||
if (pkgLinkEntity != null) {
|
||||
String bottomTab = pkgLinkEntity.getHomeBottomTab();
|
||||
|
||||
if (!pkgLinkEntity.getShouldStayAtHomePage()) {
|
||||
// 不停留在首页,执行跳转,标记已用
|
||||
PkgHelper.INSTANCE.markConfigUsed();
|
||||
DirectUtils.directToLinkPage(requireContext(), pkgLinkEntity, "推广包配置", "首页");
|
||||
} else if (!"home".equals(bottomTab)) {
|
||||
// 停留首页,但选中底部 tab 不是首页的,执行选中,标记已用
|
||||
PkgHelper.INSTANCE.markConfigUsed();
|
||||
// TODO 根据具体 tab 来作为跳转的具体位置,避免硬编码
|
||||
int targetIndex = INDEX_HOME;
|
||||
|
||||
switch (bottomTab) {
|
||||
case "game_lib":
|
||||
targetIndex = INDEX_GAME;
|
||||
break;
|
||||
case "community":
|
||||
targetIndex = INDEX_BBS;
|
||||
break;
|
||||
case "video":
|
||||
targetIndex = INDEX_VIDEO;
|
||||
break;
|
||||
case "gh":
|
||||
targetIndex = INDEX_PERSONAL;
|
||||
break;
|
||||
}
|
||||
|
||||
mViewPager.setCurrentItem(targetIndex);
|
||||
onPageChanged(targetIndex);
|
||||
changeColor(targetIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void getDialog() {
|
||||
mViewModel.requestOpeningData();
|
||||
mViewModel.getPrivacyPolicyDialog().observe(this, it -> {
|
||||
@ -354,6 +394,8 @@ public class MainWrapperFragment extends BaseFragment_ViewPager_Checkable implem
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
applyPkgConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -47,8 +47,8 @@ import com.gh.gamecenter.entity.AppEntity;
|
||||
import com.gh.gamecenter.feature.entity.GameEntity;
|
||||
import com.gh.gamecenter.common.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.gh.ndownload.NDataChanger;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.download.DataChanger;
|
||||
import com.lightgame.download.DataWatcher;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.DownloadStatus;
|
||||
@ -158,6 +158,8 @@ public class UpdateManager {
|
||||
}
|
||||
} else if (DownloadStatus.neterror.equals(downloadEntity.getStatus())) {
|
||||
Utils.toast(mApplicationContext, "网络错误,请稍后重试");
|
||||
} else if (DownloadStatus.diskisfull.equals(downloadEntity.getStatus())) {
|
||||
Utils.toast(mApplicationContext, "磁盘已满,请清理后重试");
|
||||
} else if (DownloadStatus.timeout.equals(downloadEntity.getStatus())) {
|
||||
Utils.toast(mApplicationContext, "请求超时,请稍后重试");
|
||||
} else if (DownloadStatus.notfound.equals(downloadEntity.getStatus())) {
|
||||
@ -479,7 +481,7 @@ public class UpdateManager {
|
||||
if (!isSilentUpdate
|
||||
&& DownloadManager.getInstance().isTaskDownloading(appEntity.getUrl())) {
|
||||
try {
|
||||
DownloadEntity entity = DataChanger.INSTANCE.getDownloadEntries().get(appEntity.getUrl());
|
||||
DownloadEntity entity = NDataChanger.INSTANCE.getDownloadEntries().get(appEntity.getUrl());
|
||||
|
||||
if (entity != null) {
|
||||
ExtensionsKt.addMetaExtra(entity, Constants.EXTRA_DOWNLOAD_TYPE, "不再是静默更新");
|
||||
|
||||
62
app/src/main/java/com/gh/gamecenter/pkg/PkgHelper.kt
Normal file
62
app/src/main/java/com/gh/gamecenter/pkg/PkgHelper.kt
Normal file
@ -0,0 +1,62 @@
|
||||
package com.gh.gamecenter.pkg
|
||||
|
||||
import android.util.Base64
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.entity.PkgConfigEntity
|
||||
import com.gh.gamecenter.common.utils.toObject
|
||||
import com.gh.gamecenter.core.provider.IPkgProvider
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import java.nio.charset.Charset
|
||||
|
||||
object PkgHelper {
|
||||
|
||||
private var mPkgConfigLink: PkgConfigEntity.PkgLinkEntity? = null
|
||||
private const val SP_PKG_CONFIG_IS_USED = "pkg_config_is_used"
|
||||
|
||||
private val mPkgProvider by lazy {
|
||||
ARouter.getInstance().build(RouteConsts.provider.pkg).navigation() as? IPkgProvider<PkgConfigEntity>
|
||||
}
|
||||
|
||||
fun getPkgConfig(isFromHomeTopTab: Boolean): PkgConfigEntity.PkgLinkEntity? {
|
||||
if (mPkgConfigLink == null
|
||||
&& !SPUtils.getBoolean(SP_PKG_CONFIG_IS_USED, false)
|
||||
&& BuildConfig.FIRST_LAUNCH.isNotEmpty()
|
||||
) {
|
||||
|
||||
mPkgConfigLink =
|
||||
String(Base64.decode(BuildConfig.FIRST_LAUNCH, Base64.DEFAULT), Charset.defaultCharset()).toObject()
|
||||
|
||||
return if (isFromHomeTopTab) {
|
||||
if (mPkgConfigLink?.shouldStayAtHomePage != true && mPkgConfigLink?.homeBottomTab == "home") {
|
||||
markConfigUsed()
|
||||
mPkgConfigLink
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} else {
|
||||
mPkgConfigLink
|
||||
}
|
||||
}
|
||||
|
||||
return mPkgConfigLink
|
||||
}
|
||||
|
||||
fun markConfigUsed() {
|
||||
mPkgConfigLink = null
|
||||
SPUtils.setBoolean(SP_PKG_CONFIG_IS_USED, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取特殊包配置
|
||||
*/
|
||||
fun requestPkgConfig(configId: String) {
|
||||
if (SPUtils.getBoolean(SP_PKG_CONFIG_IS_USED, false)) return
|
||||
|
||||
mPkgProvider?.requestPkgConfig(configId) {
|
||||
mPkgConfigLink = it.data?.link
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
37
app/src/main/java/com/gh/ndownload/NDataChanger.kt
Normal file
37
app/src/main/java/com/gh/ndownload/NDataChanger.kt
Normal file
@ -0,0 +1,37 @@
|
||||
package com.gh.ndownload
|
||||
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadTask
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* 下载进度变化通知
|
||||
*/
|
||||
object NDataChanger : Observable() {
|
||||
|
||||
val downloadingTasks: MutableMap<String, DownloadTask> = Collections.synchronizedMap(HashMap())//当前正在下载的任务队列
|
||||
val downloadEntries: MutableMap<String, DownloadEntity> = Collections.synchronizedMap(HashMap())//包含所有下载任务的任务队列
|
||||
|
||||
@Synchronized
|
||||
fun notifyDataChanged(entry: DownloadEntity?) {
|
||||
runOnUiThread {
|
||||
if (entry != null) {
|
||||
if (downloadEntries[entry.url] != null) {
|
||||
downloadEntries[entry.url] = entry
|
||||
}
|
||||
setChanged()
|
||||
notifyObservers(entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun pauseDownloadingTask(url: String) {
|
||||
runOnUiThread {
|
||||
val downloadTask = downloadingTasks.remove(url)
|
||||
downloadTask?.pause()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
409
app/src/main/java/com/gh/ndownload/NDownloadBridge.kt
Normal file
409
app/src/main/java/com/gh/ndownload/NDownloadBridge.kt
Normal file
@ -0,0 +1,409 @@
|
||||
package com.gh.ndownload
|
||||
|
||||
import android.text.TextUtils
|
||||
import com.gh.download.DownloadDataHelper
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.common.utils.NetworkUtils
|
||||
import com.gh.gamecenter.common.utils.addMetaExtra
|
||||
import com.gh.gamecenter.common.utils.deepClone
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lg.download.DownloadError
|
||||
import com.lg.download.listener.InnerDownloadListener
|
||||
import com.lg.ndownload.*
|
||||
import com.lightgame.download.DownloadDao
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.FileUtils
|
||||
import com.lightgame.utils.Utils
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.io.IOException
|
||||
import java.math.RoundingMode
|
||||
import java.net.URL
|
||||
import java.net.URLConnection
|
||||
import java.text.DecimalFormat
|
||||
import java.text.DecimalFormatSymbols
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
/**
|
||||
* 是串联丑陋的下载模块与新下载模块之间的桥梁
|
||||
*/
|
||||
object NDownloadBridge : InnerDownloadListener, IErrorRetryHandler {
|
||||
|
||||
private const val TAG = "NDownloadBridge"
|
||||
private const val DEFAULT_DOWNLOAD_THREAD_SIZE = 2
|
||||
private const val NO_NETWORK_MAX_RETRY_COUNT = 5
|
||||
|
||||
private var mRetryTimer: Timer? = null // 用于错误重试的 timer
|
||||
private val mRetryCountMap: ConcurrentHashMap<String, Int> by lazy { ConcurrentHashMap() }
|
||||
|
||||
private val mStartUpTimeMap: ConcurrentHashMap<String, Long> by lazy { ConcurrentHashMap() }
|
||||
|
||||
init {
|
||||
DownloadQueue.getInstance().setMaxDownloadingTask(3)
|
||||
}
|
||||
|
||||
override fun onError(id: String, error: DownloadError?, exception: Exception?) {
|
||||
Utils.log(TAG, "id $id encounter $error -> ${exception?.message}")
|
||||
|
||||
resetRetryCount(id)
|
||||
getDownloadEntity(id)?.let { downloadEntity ->
|
||||
when (error) {
|
||||
DownloadError.EMPTY_URL,
|
||||
DownloadError.HTTP_NOT_FOUND,
|
||||
DownloadError.CONTENT_LENGTH_IS_ZERO -> {
|
||||
doCancel(downloadEntity)
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.notfound
|
||||
}
|
||||
DownloadError.HIJACKED -> {
|
||||
doCancel(downloadEntity)
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.hijack
|
||||
}
|
||||
DownloadError.DOWNLOAD_SIZE_NOT_MATCH_CONTENT_LENGTH -> {
|
||||
doCancel(downloadEntity)
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.overflow
|
||||
DownloadManager.getInstance().onTaskError(downloadEntity)
|
||||
}
|
||||
DownloadError.PREVIOUS_DOWNLOAD_IS_DELETED,
|
||||
DownloadError.FILE_CORRUPTED -> {
|
||||
doCancel(downloadEntity)
|
||||
ToastUtils.toast("文件已损坏,请重新下载")
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.cancel
|
||||
}
|
||||
DownloadError.PRE_DOWNLOAD_INTERNAL_ERROR,
|
||||
DownloadError.DOWNLOAD_CONNECTION_ERROR,
|
||||
DownloadError.PRE_DOWNLOAD_CONNECTION_ERROR -> {
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.neterror
|
||||
DownloadManager.getInstance().onTaskError(downloadEntity)
|
||||
NDownloadService.getService()?.removeFromDataChangerAndResumeWaitingTask(downloadEntity, true)
|
||||
|
||||
DownloadDao.getInstance(HaloApp.getInstance()).update(downloadEntity, false)
|
||||
}
|
||||
DownloadError.DISK_IS_FULL -> {
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.diskisfull
|
||||
NDownloadService.getService()?.removeFromDataChangerAndResumeWaitingTask(downloadEntity, true)
|
||||
|
||||
DownloadDao.getInstance(HaloApp.getInstance()).update(downloadEntity, false)
|
||||
}
|
||||
DownloadError.RESOURCE_IS_FORBIDDEN -> {
|
||||
val errorString = exception?.message
|
||||
if (!errorString.isNullOrEmpty()) {
|
||||
handleForbiddenException(downloadEntity, errorString)
|
||||
}
|
||||
|
||||
doCancel(downloadEntity)
|
||||
}
|
||||
DownloadError.PERSONAL_NO_CERTIFICATION -> {
|
||||
doCancel(downloadEntity)
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.uncertificated
|
||||
}
|
||||
DownloadError.PERSONAL_TEENAGER -> {
|
||||
doCancel(downloadEntity)
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.unqualified
|
||||
}
|
||||
else -> {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onProgress(id: String?, progress: Float) {
|
||||
getDownloadEntity(id)?.let { downloadEntity ->
|
||||
var percent = (progress * 100.0)
|
||||
val df = DecimalFormat("#.#", DecimalFormatSymbols(Locale.CHINA))
|
||||
df.roundingMode = RoundingMode.FLOOR
|
||||
percent = df.format(percent).toDouble()
|
||||
|
||||
downloadEntity.progress = (downloadEntity.size * progress).toLong()
|
||||
downloadEntity.percent = percent
|
||||
|
||||
// 有可能还处于 redirected 状态,这里检查并置换状态
|
||||
if (com.lightgame.download.DownloadStatus.downloading != downloadEntity.status) {
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.downloading
|
||||
}
|
||||
|
||||
DownloadDao.getInstance(HaloApp.getInstance()).update(downloadEntity, false)
|
||||
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onProgressWithoutThrottle(id: String?, progress: Float) {
|
||||
if (id != null && (mStartUpTimeMap[id] ?: 0) > 0) {
|
||||
val startupTime: Long = System.currentTimeMillis() - (mStartUpTimeMap[id] ?: 0)
|
||||
getDownloadEntity(id)?.let { downloadEntity ->
|
||||
downloadEntity.meta.put(DownloadEntity.DOWNLOAD_STARTUP_TIME_KEY, startupTime.toString())
|
||||
}
|
||||
mStartUpTimeMap[id] = 0
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSizeReceived(id: String?, fileSize: Long) {
|
||||
Utils.log(TAG, "id $id onSizeReceived $fileSize")
|
||||
|
||||
getDownloadEntity(id)?.let { downloadEntity ->
|
||||
downloadEntity.size = fileSize
|
||||
|
||||
DownloadDao.getInstance(HaloApp.getInstance()).update(downloadEntity, false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReadyToDownload(id: String?, actualThreadSize: Int) {
|
||||
Utils.log(TAG, "id $id onReadyToDownload, actualThreadSize is -> $actualThreadSize")
|
||||
|
||||
getDownloadEntity(id)?.let { downloadEntity ->
|
||||
downloadEntity.meta[DownloadDataHelper.DOWNLOAD_THREAD_SIZE] = actualThreadSize.toString()
|
||||
|
||||
DownloadDao.getInstance(HaloApp.getInstance()).update(downloadEntity, false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStatusChanged(id: String, status: com.lg.download.DownloadStatus?) {
|
||||
Utils.log(TAG, "id $id onStatusChanged $status")
|
||||
|
||||
resetRetryCount(id)
|
||||
getDownloadEntity(id)?.let { originDownloadEntity ->
|
||||
// 状态更新使用全新的拷贝对象,避免因为不同线程对数据的变更造成通知错乱
|
||||
val downloadEntity = originDownloadEntity.deepClone<DownloadEntity>() ?: return@let
|
||||
when (status) {
|
||||
com.lg.download.DownloadStatus.CANCELLED -> {
|
||||
doCancel(downloadEntity)
|
||||
|
||||
DownloadManager.getInstance().onTaskPaused(downloadEntity)
|
||||
NDownloadService.getService()?.removeFromDataChangerAndResumeWaitingTask(downloadEntity, true)
|
||||
}
|
||||
com.lg.download.DownloadStatus.PAUSED -> {
|
||||
downloadEntity.speed = 0
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.pause
|
||||
|
||||
NDownloadService.getService()?.removeFromDataChangerAndResumeWaitingTask(downloadEntity, false)
|
||||
}
|
||||
com.lg.download.DownloadStatus.WAITINGWIFI -> {
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.waiting
|
||||
}
|
||||
com.lg.download.DownloadStatus.DOWNLOADING -> {
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.downloading
|
||||
DownloadManager.getInstance().onTaskAdded(downloadEntity)
|
||||
}
|
||||
com.lg.download.DownloadStatus.QUEUED -> {
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.add
|
||||
}
|
||||
else -> {
|
||||
Utils.log(TAG, "status not supported yet -> $status")
|
||||
}
|
||||
}
|
||||
|
||||
DownloadDao.getInstance(HaloApp.getInstance()).update(downloadEntity, false)
|
||||
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDownloadComplete(id: String?, elapsedTime: Long) {
|
||||
getDownloadEntity(id)?.let { originDownloadEntity ->
|
||||
val downloadEntity = originDownloadEntity.deepClone<DownloadEntity>() ?: return@let
|
||||
|
||||
downloadEntity.speed = 0
|
||||
downloadEntity.progress = downloadEntity.size
|
||||
downloadEntity.percent = 100.0
|
||||
downloadEntity.end = System.currentTimeMillis()
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.done
|
||||
downloadEntity.addMetaExtra(com.lightgame.download.DownloadConfig.KEY_DOWNLOAD_ELAPSED_TIME, elapsedTime.toString())
|
||||
|
||||
DownloadManager.getInstance().onTaskDone(downloadEntity)
|
||||
NDownloadService.getService()?.removeFromDataChangerAndResumeWaitingTask(downloadEntity, true)
|
||||
|
||||
DownloadDao.getInstance(HaloApp.getInstance()).update(downloadEntity, false)
|
||||
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSpeedChanged(id: String, speed: Float) {
|
||||
getDownloadEntity(id)?.let { downloadEntity ->
|
||||
downloadEntity.speed = speed.toLong()
|
||||
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRedirectingUrl(id: String, connection: URLConnection?, config: DownloadConfig?) {
|
||||
getDownloadEntity(id)?.let { downloadEntity ->
|
||||
if (!TextUtils.isEmpty(downloadEntity.eTag)) {
|
||||
val eTag: String = getRealETag(connection?.getHeaderField("Halo-ETag") ?: "")
|
||||
downloadEntity.haloEtag = eTag
|
||||
DownloadDao.getInstance(HaloApp.getInstance()).update(downloadEntity, false)
|
||||
}
|
||||
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRedirectedUrl(id: String, connection: URLConnection?, redirectedUrl: String?) {
|
||||
getDownloadEntity(id)?.let { downloadEntity ->
|
||||
downloadEntity.finalRedirectedUrl = redirectedUrl
|
||||
val url = URL(redirectedUrl)
|
||||
if (url.host != null && url.path != null) {
|
||||
downloadEntity.meta[DownloadEntity.DOWNLOAD_HOST_KEY] = url.host
|
||||
downloadEntity.meta[DownloadEntity.DOWNLOAD_PATH_KEY] = url.path
|
||||
DownloadDao.getInstance(HaloApp.getInstance()).update(downloadEntity, false)
|
||||
}
|
||||
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.redirected
|
||||
|
||||
// downloadEntity 的 etag 的值用来判断是否需要进行劫持校验,值不参与到最后判断是否被劫持的校验中去
|
||||
val shouldCompareETag = !TextUtils.isEmpty(downloadEntity.eTag)
|
||||
val currentETag = connection?.getHeaderField("ETag")
|
||||
if (shouldCompareETag
|
||||
&& !TextUtils.isEmpty(currentETag)
|
||||
&& currentETag != downloadEntity.haloEtag
|
||||
) {
|
||||
// 链接被劫持,抛出异常
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.hijack
|
||||
}
|
||||
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRetryOption(id: String, e: Exception?): Int {
|
||||
val downloadEntity =
|
||||
DownloadDao.getInstance(HaloApp.getInstance()).getSnapshot(id) ?: return IErrorRetryHandler.RETRY_DIRECTLY
|
||||
|
||||
return if (e is IOException && FileUtils.getFreeSpaceByPath(downloadEntity.path) < 10F) {
|
||||
IErrorRetryHandler.REFUSE_TO_RETRY
|
||||
} else if (NetworkUtils.isWifiConnected(HaloApp.getInstance()) || isDownloadViaTrafficAllowed(downloadEntity)) {
|
||||
IErrorRetryHandler.RETRY_DIRECTLY
|
||||
} else {
|
||||
IErrorRetryHandler.RETRY_MANUALLY
|
||||
}
|
||||
}
|
||||
|
||||
override fun retryManually(id: String, retryRunnable: Runnable, pauseRunnable: Runnable) {
|
||||
if (mRetryTimer == null) {
|
||||
mRetryTimer = Timer()
|
||||
}
|
||||
|
||||
Utils.log(TAG, "about to retry download manually")
|
||||
|
||||
mRetryTimer?.schedule(object : TimerTask() {
|
||||
override fun run() {
|
||||
if (NetworkUtils.isWifiConnected(HaloApp.getInstance())) {
|
||||
resetRetryCount(id)
|
||||
retryRunnable.run()
|
||||
} else {
|
||||
mRetryCountMap[id] = (mRetryCountMap[id] ?: 0) + 1
|
||||
if (mRetryCountMap[id]!! <= NO_NETWORK_MAX_RETRY_COUNT) {
|
||||
retryManually(id, retryRunnable, pauseRunnable)
|
||||
} else {
|
||||
resetRetryCount(id)
|
||||
pauseRunnable.run()
|
||||
}
|
||||
}
|
||||
}
|
||||
}, GlobalDownloadConfig.ERROR_RETRY_INTERVAL)
|
||||
}
|
||||
|
||||
private fun isDownloadViaTrafficAllowed(downloadEntity: DownloadEntity?): Boolean {
|
||||
val mNetworkMobileStatus = "2G3G4G5G"
|
||||
val networkStatus: String? = downloadEntity?.meta?.get(DownloadEntity.NETWORK_STATUS_KEY)
|
||||
Utils.log("download network status$networkStatus")
|
||||
return if (networkStatus == null) false else mNetworkMobileStatus.contains(networkStatus)
|
||||
}
|
||||
|
||||
fun download(downloadEntity: DownloadEntity) {
|
||||
val config = DownloadConfigBuilder()
|
||||
.setUniqueId(downloadEntity.url)
|
||||
.setFileName("")
|
||||
.setUrl(downloadEntity.url)
|
||||
.setPathToStore(downloadEntity.path)
|
||||
.setHttpClient(NHttpClient())
|
||||
.setDownloadThreadSize(DEFAULT_DOWNLOAD_THREAD_SIZE)
|
||||
.setDownloadListener(NDownloadBridge)
|
||||
.setErrorRetryHandler(this)
|
||||
.setDownloadExecutor(AppExecutor.downloadExecutor)
|
||||
.setMeta(downloadEntity.meta as HashMap<String, String>?)
|
||||
.setErrorRetryHandler(this)
|
||||
.build()
|
||||
|
||||
mStartUpTimeMap[downloadEntity.url] = System.currentTimeMillis()
|
||||
|
||||
DownloadQueue.getInstance().submitNewTask(config)
|
||||
}
|
||||
|
||||
fun resume(id: String?) {
|
||||
id?.let {
|
||||
DownloadQueue.getInstance().resume(id)
|
||||
|
||||
getDownloadEntity(id)?.let { downloadEntity ->
|
||||
mStartUpTimeMap[downloadEntity.url] = System.currentTimeMillis()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun pause(id: String?) {
|
||||
id?.let {
|
||||
DownloadQueue.getInstance().pause(id)
|
||||
}
|
||||
}
|
||||
|
||||
fun cancel(id: String?) {
|
||||
id?.let {
|
||||
NDataChanger.downloadEntries.remove(id)
|
||||
DownloadQueue.getInstance().cancel(id)
|
||||
}
|
||||
}
|
||||
|
||||
private fun doCancel(downloadEntity: DownloadEntity) {
|
||||
DownloadManager.getInstance().cancel(downloadEntity.url)
|
||||
}
|
||||
|
||||
private fun getRealETag(originETag: String): String {
|
||||
var realETag = originETag
|
||||
if (!TextUtils.isEmpty(realETag) && realETag.startsWith("\"") && realETag.endsWith("\"")) {
|
||||
realETag = realETag.substring(1, realETag.length - 1)
|
||||
}
|
||||
return realETag
|
||||
}
|
||||
|
||||
private fun handleForbiddenException(downloadEntity: DownloadEntity, errorString: String) {
|
||||
try {
|
||||
val resultObject = JSONObject(errorString)
|
||||
|
||||
if ("403001" == resultObject.getString("code")) {
|
||||
// 未实名
|
||||
if (resultObject.has("force") && !resultObject.getBoolean("force")) {
|
||||
downloadEntity.meta["force_real_name"] = "false"
|
||||
}
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.uncertificated
|
||||
} else if ("403002" == resultObject.getString("code")) {
|
||||
// 未成年
|
||||
if (resultObject.has("force") && !resultObject.getBoolean("force")) {
|
||||
downloadEntity.meta["force_real_name"] = "false"
|
||||
}
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.unqualified
|
||||
} else if ("403003" == resultObject.getString("code")) {
|
||||
// 该游戏未接入防沉迷系统禁止下载
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.unavailable
|
||||
} else if ("403004" == resultObject.getString("code")) {
|
||||
// 后台禁止该设备下载
|
||||
downloadEntity.status = com.lightgame.download.DownloadStatus.banned
|
||||
}
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun resetRetryCount(id: String) {
|
||||
mRetryCountMap[id] = 0
|
||||
}
|
||||
|
||||
private fun getDownloadEntity(id: String?): DownloadEntity? {
|
||||
return DownloadManager.getInstance().getDownloadEntitySnapshot(id)
|
||||
}
|
||||
|
||||
}
|
||||
276
app/src/main/java/com/gh/ndownload/NDownloadService.java
Normal file
276
app/src/main/java/com/gh/ndownload/NDownloadService.java
Normal file
@ -0,0 +1,276 @@
|
||||
package com.gh.ndownload;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.lightgame.BuildConfig;
|
||||
import com.lightgame.download.DownloadConfig;
|
||||
import com.lightgame.download.DownloadDao;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.DownloadStatus;
|
||||
import com.lightgame.download.DownloadTask;
|
||||
import com.lightgame.download.ForegroundNotificationManager;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class NDownloadService extends Service {
|
||||
|
||||
public static final String KEY_SERVICE_ACTION = "service_action";
|
||||
public static final String START_FOREGROUND = "start_foreground";
|
||||
private static final String SERVICE_CHANNEL_ID = "Halo_Download";
|
||||
|
||||
private static NDownloadService sService = null;
|
||||
|
||||
private ForegroundNotificationManager mForegroundNotificationManager;
|
||||
|
||||
@Nullable
|
||||
public static NDownloadService getService() {
|
||||
return sService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
sService = this;
|
||||
|
||||
mForegroundNotificationManager = new ForegroundNotificationManager(this, this.getApplication());
|
||||
Utils.log(NDownloadService.class.getSimpleName(), "onCreate");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
Utils.log(NDownloadService.class.getSimpleName(), "onStartCommand");
|
||||
|
||||
int randomNotificationId = getNextIntExcludeZero();
|
||||
|
||||
if (intent != null && intent.getExtras() != null) {
|
||||
String serviceAction = intent.getStringExtra(KEY_SERVICE_ACTION);
|
||||
|
||||
if (START_FOREGROUND.equals(serviceAction)) {
|
||||
startForegroundIfNeeded(randomNotificationId);
|
||||
}
|
||||
|
||||
String statusString = intent.getStringExtra(DownloadConfig.KEY_DOWNLOAD_ACTION);
|
||||
if (!TextUtils.isEmpty(statusString)) {
|
||||
// 看不懂的操作
|
||||
DownloadStatus status = DownloadStatus.valueOf(statusString);
|
||||
DownloadEntity entry = (DownloadEntity) intent.getSerializableExtra(DownloadConfig.KEY_DOWNLOAD_ENTRY);
|
||||
|
||||
DownloadEntity downloadEntity = DownloadDao.getInstance(this).get(entry.getUrl());
|
||||
if (downloadEntity == null) {
|
||||
// 设置开始下载时间(排序用到)
|
||||
entry.setStart(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
// 置换最新状态
|
||||
entry.setStatus(status);
|
||||
|
||||
// 删除下载错误信息
|
||||
entry.setError("");
|
||||
DownloadDao.getInstance(this).removeErrorMessage(entry.getUrl());
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log(NDownloadService.class.getSimpleName(), entry.getPackageName() + "==>" + entry.getStatus().getStatus());
|
||||
}
|
||||
switch (status) {
|
||||
case subscribe:
|
||||
subscribeDownload(entry);
|
||||
break;
|
||||
case add:
|
||||
addDownload(entry);
|
||||
break;
|
||||
case pause:
|
||||
case timeout:
|
||||
case neterror:
|
||||
case diskisfull:
|
||||
pauseDownload(entry);
|
||||
break;
|
||||
case resume:
|
||||
resumeDownload(entry);
|
||||
break;
|
||||
case cancel:
|
||||
cancelDownload(entry);
|
||||
break;
|
||||
default:
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log(NDownloadService.class.getSimpleName(), "无法处理的下载状态:" + entry.getStatus().getStatus());
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log(NDownloadService.class.getSimpleName(), "启动了一个空的下载服务");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 无参时也默认以前台启动
|
||||
startForegroundIfNeeded(randomNotificationId);
|
||||
}
|
||||
|
||||
stopForegroundIfNeeded(randomNotificationId);
|
||||
|
||||
// 不需要 intent 为空的重建
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
synchronized void subscribeDownload(DownloadEntity entry) {
|
||||
NDataChanger.INSTANCE.getDownloadEntries().put(entry.getUrl(), entry);
|
||||
DownloadDao.getInstance(this).newOrUpdate(entry);
|
||||
NDataChanger.INSTANCE.notifyDataChanged(entry);
|
||||
DownloadManager.getInstance().onTaskAdded(entry);
|
||||
}
|
||||
|
||||
synchronized void addDownload(DownloadEntity entry) {
|
||||
if (NDataChanger.INSTANCE.getDownloadingTasks().size() >= DownloadConfig.MAX_DOWNLOADING_SIZE) {
|
||||
// 1.改任务队列的状态
|
||||
entry.setStatus(DownloadStatus.waiting);
|
||||
NDataChanger.INSTANCE.getDownloadEntries().put(entry.getUrl(), entry);
|
||||
// 2.改数据库状态
|
||||
DownloadDao.getInstance(this).newOrUpdate(entry);
|
||||
// 3.通知更新
|
||||
NDataChanger.INSTANCE.notifyDataChanged(entry);
|
||||
} else {
|
||||
startDownload(entry);
|
||||
}
|
||||
DownloadManager.getInstance().onTaskAdded(entry);
|
||||
}
|
||||
|
||||
synchronized void pauseDownload(DownloadEntity entry) {
|
||||
if (entry != null) {
|
||||
entry.setStatus(DownloadStatus.pause);
|
||||
|
||||
// 1.改任务队列的状态
|
||||
NDownloadBridge.INSTANCE.pause(entry.getUrl());
|
||||
NDataChanger.INSTANCE.pauseDownloadingTask(entry.getUrl());
|
||||
|
||||
// 2.改数据库状态
|
||||
DownloadDao.getInstance(this).update(entry, false);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void resumeDownload(DownloadEntity entry) {
|
||||
addDownload(entry);
|
||||
}
|
||||
|
||||
synchronized void cancelDownload(DownloadEntity downloadEntity) {
|
||||
DownloadTask task = NDataChanger.INSTANCE.getDownloadingTasks()
|
||||
.get(downloadEntity.getUrl());
|
||||
if (task != null) {
|
||||
NDownloadBridge.INSTANCE.cancel(downloadEntity.getUrl());
|
||||
// 改任务队列的状态
|
||||
NDataChanger.INSTANCE.getDownloadingTasks().remove(downloadEntity.getUrl());
|
||||
NDataChanger.INSTANCE.notifyDataChanged(downloadEntity);
|
||||
}
|
||||
NDataChanger.INSTANCE.getDownloadEntries().remove(downloadEntity.getUrl());
|
||||
NDataChanger.INSTANCE.notifyDataChanged(downloadEntity);
|
||||
DownloadManager.getInstance().onTaskCancelled(downloadEntity);
|
||||
}
|
||||
|
||||
synchronized void startDownload(DownloadEntity entry) {
|
||||
DownloadTask task = NDataChanger.INSTANCE.getDownloadingTasks().get(entry.getUrl());
|
||||
if (task == null) {
|
||||
// 刷新初始状态
|
||||
NDataChanger.INSTANCE.notifyDataChanged(entry);
|
||||
|
||||
entry.getMeta().put(DownloadEntity.DOWNLOAD_STARTUP_STATUS_KEY, entry.getStatus().getStatus());
|
||||
// 1.改任务队列的状态
|
||||
entry.setStatus(DownloadStatus.downloading);
|
||||
NDataChanger.INSTANCE.getDownloadEntries().put(entry.getUrl(), entry);
|
||||
NDataChanger.INSTANCE.getDownloadingTasks().put(entry.getUrl(), new DownloadTask(null, entry, this));
|
||||
|
||||
// 2.改数据库状态
|
||||
DownloadDao.getInstance(this).newOrUpdate(entry);
|
||||
|
||||
// 3.执行下载
|
||||
NDownloadBridge.INSTANCE.download(entry);
|
||||
|
||||
// 4.通知更新
|
||||
NDataChanger.INSTANCE.notifyDataChanged(entry);
|
||||
} else {
|
||||
Utils.log("Fuck this, we received multiple download request for the same url");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 DataChanger 里移除掉数据,并找到下一个处于 waiting 状态的任务继续
|
||||
* @param downloadEntity 需要移除的数据
|
||||
* @param removeCompletely 是否完全移除,false 时只从下载中 hashMap 移除
|
||||
*/
|
||||
public synchronized void removeFromDataChangerAndResumeWaitingTask(DownloadEntity downloadEntity, boolean removeCompletely) {
|
||||
NDataChanger.INSTANCE.getDownloadingTasks().remove(downloadEntity.getUrl());
|
||||
if (removeCompletely) {
|
||||
NDataChanger.INSTANCE.getDownloadEntries().remove(downloadEntity.getUrl());
|
||||
}
|
||||
for (DownloadEntity entry : NDataChanger.INSTANCE.getDownloadEntries().values()) {
|
||||
if (DownloadStatus.waiting.equals(entry.getStatus())) {
|
||||
// 刷新状态(从等待中到开始下载,状态应该变为继续下载)
|
||||
entry.setStatus(DownloadStatus.resume);
|
||||
startDownload(entry);
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log(NDownloadService.class.getSimpleName(), entry.getPackageName() + "==>" + entry.getStatus().getStatus());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startForegroundIfNeeded(int notificationId) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannel channel = new NotificationChannel(SERVICE_CHANNEL_ID, "Halo Download", NotificationManager.IMPORTANCE_LOW);
|
||||
NotificationManager manager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
manager.createNotificationChannel(channel);
|
||||
Notification notification = new NotificationCompat.Builder(this, SERVICE_CHANNEL_ID)
|
||||
.setSmallIcon(com.lightgame.R.drawable.ic_download_notification)
|
||||
.build();
|
||||
|
||||
if (mForegroundNotificationManager != null) {
|
||||
mForegroundNotificationManager.notify(notificationId, notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void stopForegroundIfNeeded(int notificationId) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (mForegroundNotificationManager != null) {
|
||||
mForegroundNotificationManager.cancel(notificationId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 0 以外的随机 int 数值
|
||||
*/
|
||||
private int getNextIntExcludeZero() {
|
||||
int randomNumber = new Random().nextInt();
|
||||
if (randomNumber != 0) {
|
||||
return randomNumber;
|
||||
} else {
|
||||
return getNextIntExcludeZero();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
31
app/src/main/java/com/gh/ndownload/NHttpClient.kt
Normal file
31
app/src/main/java/com/gh/ndownload/NHttpClient.kt
Normal file
@ -0,0 +1,31 @@
|
||||
package com.gh.ndownload
|
||||
|
||||
import android.text.TextUtils
|
||||
import com.lg.download.httpclient.DefaultHttpClient
|
||||
import com.lightgame.download.HttpDnsManager
|
||||
|
||||
class NHttpClient : DefaultHttpClient() {
|
||||
|
||||
override fun addHeader(url: String?, meta: HashMap<String, String>?) {
|
||||
super.addHeader(url, meta)
|
||||
|
||||
mConnection.setRequestProperty(HttpDnsManager.APP_VERSION, HttpDnsManager.metaMap[HttpDnsManager.APP_VERSION])
|
||||
mConnection.setRequestProperty(HttpDnsManager.CHANNEL, HttpDnsManager.metaMap[HttpDnsManager.CHANNEL])
|
||||
mConnection.setRequestProperty(HttpDnsManager.GID, HttpDnsManager.metaMap[HttpDnsManager.GID])
|
||||
mConnection.setRequestProperty(HttpDnsManager.USER_ID, HttpDnsManager.metaMap[HttpDnsManager.USER_ID])
|
||||
mConnection.setRequestProperty(HttpDnsManager.IMEI, HttpDnsManager.metaMap[HttpDnsManager.IMEI])
|
||||
mConnection.setRequestProperty(HttpDnsManager.OAID, HttpDnsManager.metaMap[HttpDnsManager.OAID])
|
||||
mConnection.setRequestProperty(HttpDnsManager.TOKEN, HttpDnsManager.metaMap[HttpDnsManager.TOKEN])
|
||||
mConnection.setRequestProperty(HttpDnsManager.IS_OVERWRITE, HttpDnsManager.metaMap[HttpDnsManager.IS_OVERWRITE])
|
||||
|
||||
val isEmulator = meta?.get("is_emulator")
|
||||
val isForcedRealName = meta?.get("force_real_name")
|
||||
if (!TextUtils.isEmpty(isForcedRealName) && "false" == isForcedRealName) {
|
||||
mConnection.setRequestProperty("force", isForcedRealName)
|
||||
}
|
||||
if (!TextUtils.isEmpty(isEmulator)) {
|
||||
mConnection.setRequestProperty("simulator", isEmulator)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -188,6 +188,7 @@ class HomeRecentVGameAdapter(context: Context) : DiffUtilAdapter<VGameItemData>(
|
||||
DownloadStatus.uncertificated,
|
||||
DownloadStatus.unqualified,
|
||||
DownloadStatus.notfound,
|
||||
DownloadStatus.diskisfull,
|
||||
DownloadStatus.unavailable,
|
||||
DownloadStatus.overflow -> {
|
||||
binding.root.setOnClickListener {
|
||||
|
||||
@ -101,7 +101,7 @@ object VArchiveHelper {
|
||||
.setHttpClient(DefaultHttpClient())
|
||||
.setDownloadThreadSize(2)
|
||||
.setDownloadListener(DownloadMessageHandler)
|
||||
.setDownloadExecutor(AppExecutor.ioExecutor)
|
||||
.setDownloadExecutor(AppExecutor.downloadExecutor)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
@ -387,6 +387,7 @@ class VDownloadManagerAdapter(
|
||||
DownloadStatus.timeout,
|
||||
DownloadStatus.neterror,
|
||||
DownloadStatus.subscribe,
|
||||
DownloadStatus.diskisfull,
|
||||
DownloadStatus.overflow -> {
|
||||
btnText = context.getString(R.string.resume)
|
||||
downloadDes.visibility = View.VISIBLE
|
||||
|
||||
@ -55,6 +55,7 @@ data class VGameItemData(
|
||||
DownloadStatus.cancel,
|
||||
DownloadStatus.timeout,
|
||||
DownloadStatus.neterror,
|
||||
DownloadStatus.diskisfull,
|
||||
DownloadStatus.hijack,
|
||||
DownloadStatus.uncertificated,
|
||||
DownloadStatus.unqualified,
|
||||
@ -62,6 +63,8 @@ data class VGameItemData(
|
||||
DownloadStatus.unavailable,
|
||||
DownloadStatus.overflow -> {
|
||||
controlText = "重试"
|
||||
shouldShowMask = true
|
||||
shouldShowControlTv = true
|
||||
}
|
||||
else -> {
|
||||
// do nothing
|
||||
|
||||
@ -176,6 +176,7 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
overflow,
|
||||
timeout,
|
||||
neterror,
|
||||
diskisfull,
|
||||
waiting,
|
||||
subscribe -> {
|
||||
downloadBtn.setText(R.string.waiting)
|
||||
|
||||
@ -48,6 +48,7 @@ class VSpaceLoadingFragment : BaseFragment<Any>() {
|
||||
hijack,
|
||||
notfound,
|
||||
neterror,
|
||||
diskisfull,
|
||||
overflow -> requireActivity().finish()
|
||||
unqualified -> {
|
||||
ToastUtils.toast("暂不支持未成年人下载")
|
||||
|
||||
@ -69,6 +69,7 @@ import com.gh.gamecenter.receiver.NetworkStateReceiver;
|
||||
import com.gh.vspace.VHelper;
|
||||
import com.github.piasy.biv.BigImageViewer;
|
||||
import com.github.piasy.biv.loader.fresco.FrescoImageLoader;
|
||||
import com.lg.ndownload.DownloadDbManager;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.llew.huawei.verifier.LoadedApkHuaWei;
|
||||
import com.shuyu.gsyvideoplayer.cache.CacheFactory;
|
||||
@ -218,6 +219,8 @@ public class HaloApp extends MultiDexApplication {
|
||||
|
||||
// 异步初始化 SP
|
||||
SPUtils.getString("");
|
||||
|
||||
DownloadDbManager.init(this);
|
||||
});
|
||||
|
||||
RxJavaPlugins.setIoSchedulerHandler(scheduler -> AppExecutor.INSTANCE.getCachedScheduler());
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/background"
|
||||
android:gravity="center"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
android:background="@color/background"
|
||||
android:gravity="center"
|
||||
app:elevation="0dp"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<include
|
||||
android:id="@+id/reuseSearchBar"
|
||||
|
||||
@ -48,7 +48,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/head_container"
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
android:background="@color/background_white"
|
||||
android:fitsSystemWindows="true"
|
||||
app:elevation="0dp"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<com.gh.gamecenter.common.view.ScrimAwareCollapsingToolbarLayout
|
||||
android:id="@+id/collapsingToolbar"
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
android:gravity="center"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
android:background="@color/background"
|
||||
android:fitsSystemWindows="true"
|
||||
android:gravity="center"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<com.gh.gamecenter.common.view.ScrimAwareCollapsingToolbarLayout
|
||||
android:id="@+id/collapsingToolbar"
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
android:background="@color/background_white"
|
||||
android:fitsSystemWindows="true"
|
||||
android:gravity="center"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
app:elevation="0dp"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/recordForumsContainer"
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
android:fitsSystemWindows="true"
|
||||
android:gravity="center"
|
||||
app:elevation="0dp"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:id="@id/collapsingToolbar"
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
android:background="@color/background_white"
|
||||
android:gravity="center"
|
||||
app:elevation="0dp"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:id="@id/collapsingToolbar"
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
android:background="@color/background_white"
|
||||
android:fitsSystemWindows="true"
|
||||
app:elevation="0dp"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<com.gh.gamecenter.common.view.ScrimAwareCollapsingToolbarLayout
|
||||
android:id="@+id/collapsingToolbar"
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
app:elevation="0dp"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<com.gh.common.view.CollapsingMotionLayout
|
||||
android:id="@+id/motionLayout"
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:elevation="0dp"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@color/background_white"
|
||||
android:gravity="center"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
android:background="@color/background"
|
||||
android:gravity="center"
|
||||
app:elevation="0dp"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<include
|
||||
android:id="@+id/search_bar"
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/transparent"
|
||||
app:elevation="0dp"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:id="@+id/collapsingToolbar"
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/background_white"
|
||||
android:gravity="center"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior">
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/subject_type_list"
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
android:background="@color/background_white"
|
||||
android:fitsSystemWindows="true"
|
||||
android:gravity="center"
|
||||
app:layout_behavior=".common.view.FixAppBarLayoutBehavior"
|
||||
app:layout_behavior="com.gh.gamecenter.common.view.FixAppBarLayoutBehavior"
|
||||
tools:visibility="visible">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
|
||||
48
app/src/tea/java/com/gh/gamecenter/TeaHelper
Normal file
48
app/src/tea/java/com/gh/gamecenter/TeaHelper
Normal file
@ -0,0 +1,48 @@
|
||||
package com.gh.gamecenter
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import com.bytedance.applog.AppLog
|
||||
import com.bytedance.applog.GameReportHelper
|
||||
import com.bytedance.applog.InitConfig
|
||||
import com.bytedance.applog.util.UriConstants
|
||||
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
/**
|
||||
* 5.3.0 版本的 SDK
|
||||
**/
|
||||
object TeaHelper {
|
||||
|
||||
@JvmStatic
|
||||
fun init(context: Context, activity: Activity, channel: String) {
|
||||
val config = InitConfig("163824", channel)
|
||||
config.setUriConfig(UriConstants.DEFAULT)
|
||||
config.appName = "guanghuan1"
|
||||
config.setEnablePlay(true)
|
||||
config.setAutoStart(true)
|
||||
AppLog.init(context, config)
|
||||
|
||||
AppLog.setOaidObserver {
|
||||
if (!TextUtils.isEmpty(it.id)) {
|
||||
HaloApp.getInstance().oaid = it.id
|
||||
MetaUtil.refreshMeta()
|
||||
}
|
||||
Utils.log("oaid is $it.id")
|
||||
}
|
||||
|
||||
// gameReportHelper ?!
|
||||
GameReportHelper.onEventRegister("wechat", true)
|
||||
GameReportHelper.onEventPurchase("gift", "flower", "008", 1, "wechat", "¥", true, 1)
|
||||
Utils.log("init TeaHelper")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onEvent(type: String) {
|
||||
AppLog.onEventV3(type)
|
||||
}
|
||||
|
||||
}
|
||||
@ -3,6 +3,7 @@ package com.gh.gamecenter.provider
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.text.TextUtils
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.bytedance.hume.readapk.HumeSDK
|
||||
import com.gh.gamecenter.TeaHelper
|
||||
import com.gh.gamecenter.core.provider.IFlavorProvider
|
||||
@ -16,7 +17,7 @@ class FlavorProviderImp : IFlavorProvider {
|
||||
|
||||
override fun init(application: Application, activity: Activity) {
|
||||
|
||||
mIsLuckyEnoughToUseTea = amILucky()
|
||||
mIsLuckyEnoughToUseTea = amILucky(BuildConfig.ACTIVATE_REPORTING_RATIO)
|
||||
|
||||
if (mIsLuckyEnoughToUseTea) {
|
||||
TeaHelper.init(application, activity, getChannelStr(application))
|
||||
|
||||
Submodule libraries/LGLibrary updated: 9de633eae8...077b43ed8a
@ -76,6 +76,8 @@ object RouteConsts {
|
||||
|
||||
const val vpn = "/vpn/vpn"
|
||||
|
||||
const val pkg = "/pkg/pkg"
|
||||
|
||||
const val sensors = "/sensors/sensors"
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
package com.gh.gamecenter.common.entity
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
class PkgConfigEntity(
|
||||
@SerializedName("code") var code: Int? = null,
|
||||
@SerializedName("data") var data: Data? = Data()
|
||||
) {
|
||||
data class Data(
|
||||
@SerializedName("first_lanuch_jump") var link: PkgLinkEntity? = PkgLinkEntity(),
|
||||
)
|
||||
|
||||
class PkgLinkEntity(
|
||||
@SerializedName("home_index")
|
||||
var shouldStayAtHomePage: Boolean = false,
|
||||
@SerializedName("bottom_index")
|
||||
var homeBottomTab: String = ""
|
||||
) : LinkEntity()
|
||||
}
|
||||
@ -206,24 +206,25 @@ object MetaUtil {
|
||||
?: return "unknown"
|
||||
|
||||
return when (activeNetwork.type) {
|
||||
ConnectivityManager.TYPE_WIFI -> "Wifi"
|
||||
ConnectivityManager.TYPE_WIMAX -> "WifiMax"
|
||||
ConnectivityManager.TYPE_WIFI -> "WIFI"
|
||||
ConnectivityManager.TYPE_WIMAX -> "WIMAX"
|
||||
ConnectivityManager.TYPE_MOBILE -> {
|
||||
val telephonyManager = application.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
|
||||
if (telephonyManager.simState != TelephonyManager.SIM_STATE_READY) return "unknown"
|
||||
when (telephonyManager.networkType) {
|
||||
// Unknown
|
||||
TelephonyManager.NETWORK_TYPE_UNKNOWN -> "Cellular - Unknown"
|
||||
TelephonyManager.NETWORK_TYPE_UNKNOWN -> "unknown"
|
||||
// Cellular Data–2G
|
||||
TelephonyManager.NETWORK_TYPE_EDGE, TelephonyManager.NETWORK_TYPE_GPRS, TelephonyManager.NETWORK_TYPE_CDMA,
|
||||
TelephonyManager.NETWORK_TYPE_IDEN, TelephonyManager.NETWORK_TYPE_1xRTT -> "Cellular - 2G"
|
||||
TelephonyManager.NETWORK_TYPE_IDEN, TelephonyManager.NETWORK_TYPE_1xRTT -> "2G"
|
||||
// Cellular Data–3G
|
||||
TelephonyManager.NETWORK_TYPE_UMTS, TelephonyManager.NETWORK_TYPE_HSDPA, TelephonyManager.NETWORK_TYPE_HSPA,
|
||||
TelephonyManager.NETWORK_TYPE_HSPAP, TelephonyManager.NETWORK_TYPE_HSUPA, TelephonyManager.NETWORK_TYPE_EVDO_0,
|
||||
TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyManager.NETWORK_TYPE_EVDO_B -> "Cellular - 3G"
|
||||
TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyManager.NETWORK_TYPE_EVDO_B -> "3G"
|
||||
// Cellular Data–4G
|
||||
TelephonyManager.NETWORK_TYPE_LTE -> "Cellular - 4G"
|
||||
else -> "Cellular - Unknown Generation"
|
||||
TelephonyManager.NETWORK_TYPE_LTE -> "4G"
|
||||
TelephonyManager.NETWORK_TYPE_NR -> "5G"
|
||||
else -> "unknown"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -149,6 +149,9 @@ public class DeviceUtils {
|
||||
case TelephonyManager.NETWORK_TYPE_LTE:
|
||||
status = "4G";
|
||||
break;
|
||||
case TelephonyManager.NETWORK_TYPE_NR:
|
||||
status = "5G";
|
||||
break;
|
||||
default:
|
||||
status = "未知";
|
||||
break;
|
||||
|
||||
@ -68,6 +68,7 @@ import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.io.*
|
||||
import java.net.URI
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
@ -412,6 +413,25 @@ fun Context.showRegulationTestDialogIfNeeded(action: (() -> Unit)) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializable 相关
|
||||
*/
|
||||
fun <T> Serializable.deepClone(): T? {
|
||||
Utils.log("深复制对象 $this")
|
||||
return try {
|
||||
val baos = ByteArrayOutputStream()
|
||||
val oos = ObjectOutputStream(baos)
|
||||
oos.writeObject(this)
|
||||
val bais = ByteArrayInputStream(baos.toByteArray())
|
||||
val ois = ObjectInputStream(bais)
|
||||
ois.readObject() as T
|
||||
} catch (e: IOException) {
|
||||
null
|
||||
} catch (e: ClassNotFoundException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在限定 interval 里只触发一次 action
|
||||
*/
|
||||
|
||||
@ -17,6 +17,7 @@ import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.gamecenter.common.R
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.provider.IActivationProvider
|
||||
import com.gh.gamecenter.core.provider.IAppProvider
|
||||
import com.gh.gamecenter.core.provider.IDirectProvider
|
||||
@ -102,12 +103,14 @@ object PermissionHelper {
|
||||
.subscribe { permission ->
|
||||
when {
|
||||
permission.granted -> {
|
||||
emptyCallback.onCallback()
|
||||
SPUtils.setBoolean(Constants.SP_USER_HAS_PERMANENTLY_DENIED_STORAGE_PERMISSION, false)
|
||||
|
||||
// 获得存储权限后刷新 gid 避免下载仍需实名
|
||||
(ARouter.getInstance().build(RouteConsts.provider.app)
|
||||
.navigation() as? IAppProvider)?.refreshGid()
|
||||
(ARouter.getInstance().build(RouteConsts.provider.app).navigation() as? IAppProvider)?.refreshGid()
|
||||
|
||||
// 延迟 100ms 确保能够正常获取到 gid
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
emptyCallback.onCallback()
|
||||
}, 100)
|
||||
SPUtils.setBoolean(Constants.SP_USER_HAS_PERMANENTLY_DENIED_STORAGE_PERMISSION, false)
|
||||
}
|
||||
permission.shouldShowRequestPermissionRationale -> {
|
||||
// do nothing
|
||||
|
||||
@ -60,6 +60,10 @@ object AppExecutor {
|
||||
)
|
||||
}
|
||||
|
||||
val downloadExecutor: ExecutorService by lazy {
|
||||
Executors.newCachedThreadPool(GHThreadFactory("GH_DOWNLOAD_THREAD"))
|
||||
}
|
||||
|
||||
val cachedScheduler by lazy { Schedulers.from(ioExecutor) }
|
||||
|
||||
class MainThreadExecutor : Executor {
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
package com.gh.gamecenter.core.provider
|
||||
|
||||
import com.alibaba.android.arouter.facade.template.IProvider
|
||||
|
||||
interface IPkgProvider<T> : IProvider {
|
||||
|
||||
fun requestPkgConfig(configId: String, onConfigReceived: (config: T) -> Unit)
|
||||
|
||||
}
|
||||
1
module_pkg/.gitignore
vendored
Normal file
1
module_pkg/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
||||
87
module_pkg/build.gradle
Normal file
87
module_pkg/build.gradle
Normal file
@ -0,0 +1,87 @@
|
||||
if (isRelease.toBoolean()) {
|
||||
apply plugin: 'com.android.library'
|
||||
} else {
|
||||
apply plugin: 'com.android.application'
|
||||
}
|
||||
apply plugin: 'org.jetbrains.kotlin.android'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'kotlin-parcelize'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
|
||||
defaultConfig {
|
||||
if (!isRelease.toBoolean()) {
|
||||
applicationId "com.gh.pkg"
|
||||
multiDexEnabled true
|
||||
}
|
||||
minSdk rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode rootProject.ext.versionCode
|
||||
versionName rootProject.ext.versionName
|
||||
|
||||
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
if (isRelease.toBoolean()) {
|
||||
manifest.srcFile 'src/main/AndroidManifest.xml'
|
||||
java {
|
||||
exclude 'manifest/**'
|
||||
}
|
||||
} else {
|
||||
java {
|
||||
srcDirs = ['src/main/java', "src/pkg/java"]
|
||||
}
|
||||
manifest.srcFile 'src/main/manifest/AndroidManifest.xml'
|
||||
res.srcDirs = ['src/main/res','src/pkg/res']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kapt {
|
||||
arguments {
|
||||
arg("AROUTER_MODULE_NAME", project.name)
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
if (!isRelease.toBoolean()) {
|
||||
buildConfigField "String", "DEV_API_HOST", "\"${DEV_API_HOST}\""
|
||||
}
|
||||
}
|
||||
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
|
||||
if (!isRelease.toBoolean()) {
|
||||
buildConfigField "String", "DEV_API_HOST", "\"${API_HOST}\""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
|
||||
kapt "com.alibaba:arouter-compiler:$arouterVersion"
|
||||
if (!isRelease.toBoolean()) {
|
||||
implementation "androidx.multidex:multidex:${multiDex}"
|
||||
}
|
||||
|
||||
compileOnly(project(path: ":module_common"))
|
||||
}
|
||||
25
module_pkg/proguard-rules.pro
vendored
Normal file
25
module_pkg/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
|
||||
-renamesourcefileattribute SourceFile
|
||||
# Keep Attribute
|
||||
-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod,SourceFile,LineNumberTable
|
||||
8
module_pkg/src/main/AndroidManifest.xml
Normal file
8
module_pkg/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.gh.gamecenter.pkg">
|
||||
|
||||
<application>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
44
module_pkg/src/main/java/com/gh/gamecenter/pkg/HaloApp.kt
Normal file
44
module_pkg/src/main/java/com/gh/gamecenter/pkg/HaloApp.kt
Normal file
@ -0,0 +1,44 @@
|
||||
package com.gh.gamecenter.pkg
|
||||
|
||||
import android.app.Application
|
||||
import android.content.res.Configuration
|
||||
import com.gh.gamecenter.core.iinterface.IApplication
|
||||
import com.google.auto.service.AutoService
|
||||
|
||||
@AutoService(IApplication::class)
|
||||
class HaloApp : IApplication {
|
||||
|
||||
override fun attachBaseContext() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
override fun onCreate(application: Application) {
|
||||
mApp = application
|
||||
}
|
||||
|
||||
|
||||
override fun onLowMemory() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
override fun onTerminate() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
override fun onTrimMemory(level: Int) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
companion object {
|
||||
private lateinit var mApp: Application
|
||||
|
||||
@JvmStatic
|
||||
fun getInstance(): Application {
|
||||
return mApp
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.gh.gamecenter.pkg
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.entity.PkgConfigEntity
|
||||
import com.gh.gamecenter.core.provider.IPkgProvider
|
||||
import com.gh.gamecenter.pkg.retrofit.RetrofitManager
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
@Route(path = RouteConsts.provider.pkg, name = "PKG 暴露服务")
|
||||
class PkgProviderImpl : IPkgProvider<PkgConfigEntity> {
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
override fun requestPkgConfig(configId: String, onConfigReceived: (config: PkgConfigEntity) -> Unit) {
|
||||
RetrofitManager.getInstance().api.getPkgConfig(configId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
onConfigReceived.invoke(it)
|
||||
}, {
|
||||
it.printStackTrace()
|
||||
})
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.gh.gamecenter.pkg.retrofit
|
||||
|
||||
import com.gh.gamecenter.common.entity.PkgConfigEntity
|
||||
import io.reactivex.Single
|
||||
import retrofit2.http.*
|
||||
|
||||
interface ApiService {
|
||||
|
||||
/**
|
||||
* 获取推广包配置
|
||||
*/
|
||||
@GET("pkg/{path}")
|
||||
fun getPkgConfig(@Path("path") config: String): Single<PkgConfigEntity>
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.gh.gamecenter.pkg.retrofit
|
||||
|
||||
import com.gh.gamecenter.common.retrofit.BaseRetrofitManager
|
||||
import com.gh.gamecenter.common.utils.EnvHelper.getHost
|
||||
import com.gh.gamecenter.core.utils.SingletonHolder
|
||||
import com.gh.gamecenter.pkg.HaloApp
|
||||
|
||||
class RetrofitManager private constructor() : BaseRetrofitManager() {
|
||||
|
||||
val api: ApiService
|
||||
|
||||
init {
|
||||
val context = HaloApp.getInstance().applicationContext
|
||||
val okHttpNormalConfig = getOkHttpConfig(context, 0, 2)
|
||||
api = provideService(okHttpNormalConfig, getHost(), ApiService::class.java)
|
||||
}
|
||||
|
||||
companion object : SingletonHolder<RetrofitManager>(::RetrofitManager)
|
||||
|
||||
}
|
||||
40
module_pkg/src/main/manifest/AndroidManifest.xml
Normal file
40
module_pkg/src/main/manifest/AndroidManifest.xml
Normal file
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.gh.gamecenter.pkg">
|
||||
|
||||
<!-- 允许应用程序访问网络连接 -->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<!-- 允许应用程序获取网络信息状态 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<!-- 允许应用程序读取电话状态 -->
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<!-- 允许应用程序获取当前或最近运行的应用 -->
|
||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
<application
|
||||
android:name=".PkgModuleApp"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppCompatTheme"
|
||||
tools:replace="android:name,android:allowBackup">
|
||||
|
||||
<activity
|
||||
android:name=".view.PkgActivity"
|
||||
android:launchMode="singleTop">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<meta-data
|
||||
android:name="io.sentry.auto-init"
|
||||
android:value="false" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
3
module_pkg/src/main/res/values/strings.xml
Normal file
3
module_pkg/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">PKG</string>
|
||||
</resources>
|
||||
@ -0,0 +1,36 @@
|
||||
package com.gh.gamecenter.pkg
|
||||
|
||||
import androidx.multidex.MultiDexApplication
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.gamecenter.core.iinterface.IApplication
|
||||
import java.util.*
|
||||
|
||||
class PkgModuleApp : MultiDexApplication() {
|
||||
|
||||
private val mApplicationList = ServiceLoader.load(IApplication::class.java, this.javaClass.classLoader)
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
initArouter()
|
||||
mApp = this
|
||||
for (application in mApplicationList) {
|
||||
application.onCreate(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initArouter() {
|
||||
if (BuildConfig.DEBUG) { // 这两行必须写在init之前,否则这些配置在init过程中将无效
|
||||
ARouter.openLog() // 打印日志
|
||||
ARouter.openDebug() // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
|
||||
}
|
||||
ARouter.init(this) // 尽可能早,推荐在Application中初始化
|
||||
}
|
||||
|
||||
companion object {
|
||||
private lateinit var mApp: PkgModuleApp
|
||||
|
||||
fun getInstance(): PkgModuleApp {
|
||||
return mApp
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
package com.gh.gamecenter.pkg.provider
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IAppProvider
|
||||
import com.gh.gamecenter.core.provider.IFlavorProvider
|
||||
import com.gh.gamecenter.pkg.HaloApp
|
||||
import com.gh.gamecenter.pkg.R
|
||||
|
||||
@Route(path = RouteConsts.provider.app, name = "Application暴露服务")
|
||||
class AppProviderImpl : IAppProvider {
|
||||
override fun init(context: Context?) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
override fun get(key: String, isRemove: Boolean): Any? {
|
||||
return ""
|
||||
}
|
||||
|
||||
override fun put(key: String, any: Any) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
override fun getAppName(): String {
|
||||
return HaloApp.getInstance().getString(R.string.app_name)
|
||||
}
|
||||
|
||||
override fun getGid(): String {
|
||||
return ""
|
||||
}
|
||||
|
||||
override fun refreshGid() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
override fun getOaid(): String {
|
||||
return ""
|
||||
}
|
||||
|
||||
override fun getChannel(): String {
|
||||
return ""
|
||||
}
|
||||
|
||||
override fun setChannel(channel: String) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
override fun getUserAgent(): String {
|
||||
return ""
|
||||
}
|
||||
|
||||
override fun getServerUserMark(): String {
|
||||
return ""
|
||||
}
|
||||
|
||||
override fun getDeviceRamSize(): Long {
|
||||
return 0L
|
||||
}
|
||||
|
||||
override fun getTemporaryLocalDeviceId(): String {
|
||||
return ""
|
||||
}
|
||||
|
||||
override fun getFlavorProvider(): IFlavorProvider {
|
||||
return object : IFlavorProvider {
|
||||
override fun getChannelStr(application: Application): String {
|
||||
return ""
|
||||
}
|
||||
|
||||
override fun init(application: Application, activity: Activity) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
override fun logEvent(content: String) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun isUserAcceptPrivacyPolicy(context: Context): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.gh.gamecenter.pkg.view
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.gamecenter.pkg.R
|
||||
|
||||
class PkgActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContentView(R.layout.activity_pkg)
|
||||
}
|
||||
|
||||
}
|
||||
15
module_pkg/src/pkg/res/layout/activity_pkg.xml
Normal file
15
module_pkg/src/pkg/res/layout/activity_pkg.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:text="开启/关闭 VPN" />
|
||||
|
||||
</RelativeLayout>
|
||||
Submodule ndownload updated: 54cb6c0c32...89f0ede089
119
scripts/meta_build.sh
Executable file
119
scripts/meta_build.sh
Executable file
@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env bash
|
||||
# @author juntao
|
||||
# @2023.03.06
|
||||
|
||||
git_sha=`git rev-parse --short HEAD`
|
||||
versionName=$(awk -v FS="versionName = " 'NF>1{print $2}' dependencies.gradle | sed "s/\"//g")
|
||||
versionCode=$(awk -v FS="versionCode = " 'NF>1{print $2}' dependencies.gradle | sed "s/\"//g")
|
||||
build_time=$(TZ=Asia/Shanghai date +'%Y-%m%d-%H%M')
|
||||
|
||||
cwd=$(cd "$(dirname "$0")"; pwd)
|
||||
apk_release_path=""
|
||||
|
||||
# 重置 app build.gradle
|
||||
git checkout app/build.gradle
|
||||
# 重置 module_common build.gradle
|
||||
git checkout module_common/build.gradle
|
||||
|
||||
# 开启 mapping 上传
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
sed -i '' '1 a plugins { id "io.sentry.android.gradle" version "2.1.5" }' app/build.gradle
|
||||
else
|
||||
sed -i '1 a plugins { id "io.sentry.android.gradle" version "2.1.5" }' app/build.gradle
|
||||
fi
|
||||
|
||||
./gradlew --stop
|
||||
./gradlew clean
|
||||
|
||||
mkdir -p release/
|
||||
|
||||
OPTIONS=$(getopt -o '' -l config_id:,sdk_platform:,sdk_version:,channel:,activate_reporting_ratio:,first_launch_jump:,output:,unix_timestamp:, -- "$@")
|
||||
|
||||
eval set -- "$OPTIONS"
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
--config_id) config_id="$2"; shift 2;;
|
||||
--sdk_platform) sdk_platform="$2"; shift 2;;
|
||||
--sdk_version) sdk_version="$2"; shift 2;;
|
||||
--channel) channel="$2"; shift 2;;
|
||||
--activate_reporting_ratio) activate_reporting_ratio="$2"; shift 2;;
|
||||
--first_launch_jump) first_launch_jump="$2"; shift 2;;
|
||||
--output) output="$2"; shift 2;;
|
||||
--unix_timestamp) unix_timestamp="$2"; shift 2;;
|
||||
--) shift; break;;
|
||||
*) echo "Invalid option: $1" >&2; exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
function updateChannelIfNeeded {
|
||||
if [ "${channel}" != "" ]; then
|
||||
java -jar ${cwd}/ApkChannelPackage.jar put -c $channel $1 release
|
||||
rm $1
|
||||
find . -type f -name "*.apk" -exec mv {} "${apk_release_path}" \;
|
||||
fi
|
||||
}
|
||||
|
||||
# 保存 output 文件名
|
||||
if [ "${output}" != "" ]; then
|
||||
apk_release_path="$output"
|
||||
fi
|
||||
|
||||
# 保存 config_id
|
||||
if [ "${config_id}" != "" ]; then
|
||||
sed -i "s/String CONFIG_ID = \"\"/String CONFIG_ID = \"${config_id}\"/g" app/build.gradle
|
||||
fi
|
||||
|
||||
# 保存 first_launch_jump
|
||||
if [ "${first_launch_jump}" != "" ]; then
|
||||
sed -i "s/String FIRST_LAUNCH = \"\"/String FIRST_LAUNCH = \"${first_launch_jump}\"/g" app/build.gradle
|
||||
fi
|
||||
|
||||
# 是否选择了 sdk 类型
|
||||
if [ "${sdk_platform}" != "" ]; then
|
||||
# 头条包
|
||||
if [ "${sdk_platform}" == "toutiao" ]; then
|
||||
if [ "${activate_reporting_ratio}" == "" ]; then
|
||||
activate_reporting_ratio="100"
|
||||
fi
|
||||
# 调整上报比例
|
||||
sed -i "75i buildConfigField "\"int\"", "\"ACTIVATE_REPORTING_RATIO\"", \""${activate_reporting_ratio}"\"" app/build.gradle
|
||||
|
||||
if [ "${sdk_version}" == "5.3.0" ]; then
|
||||
sed -i "s/bytedanceApplog = \"6.14.1\"/bytedanceApplog = \"${sdk_version}\"/g" dependencies.gradle
|
||||
rm app/src/tea/java/com/gh/gamecenter/TeaHelper.kt
|
||||
mv app/src/tea/java/com/gh/gamecenter/TeaHelper app/src/tea/java/com/gh/gamecenter/TeaHelper.kt
|
||||
else
|
||||
sdk_version="6.14.1"
|
||||
fi
|
||||
|
||||
./gradlew aTR -I init.gradle
|
||||
|
||||
echo "${sdk_version}_${activate_reporting_ratio}_光环助手_${versionName}_${versionCode}_头条推广包_${git_sha}_${build_time}"
|
||||
|
||||
cp -R app/build/outputs/apk/tea/release/app-tea-release.apk "${apk_release_path}"
|
||||
fi
|
||||
# 广点通包
|
||||
if [ "${sdk_platform}" == "guangdiantong" ]; then
|
||||
|
||||
# 广点通 SDK 执行 ASM 后处理后会有问题
|
||||
./gradlew aGR
|
||||
|
||||
echo "光环助手_${versionName}_${versionCode}_广点通推广包_${git_sha}_${build_time}"
|
||||
cp -R app/build/outputs/apk/gdt/release/app-gdt-release.apk "${apk_release_path}"
|
||||
fi
|
||||
# 快手包
|
||||
if [ "${sdk_platform}" == "kuaishou" ]; then
|
||||
./gradlew aKR -I init.gradle
|
||||
|
||||
echo "光环助手_${versionName}_${versionCode}_快手推广包_${git_sha}_${build_time}"
|
||||
cp -R app/build/outputs/apk/kuaishou/release/app-kuaishou-release.apk "${apk_release_path}"
|
||||
fi
|
||||
|
||||
updateChannelIfNeeded ${apk_release_path}
|
||||
fi
|
||||
|
||||
# 重置 app build.gradle
|
||||
git checkout app/build.gradle
|
||||
# 重置 module_common build.gradle
|
||||
git checkout module_common/build.gradle
|
||||
@ -14,4 +14,5 @@ include ':ndownload'
|
||||
include ':module_core_feature'
|
||||
include ':module_lib'
|
||||
include ':module_vpn'
|
||||
include ':module_pkg'
|
||||
include ':module_sensors_data'
|
||||
|
||||
Reference in New Issue
Block a user