feat: 【光环助手】推广组测试打包任务 https://jira.shanqu.cc/browse/GHZS-972

This commit is contained in:
chenjuntao
2023-03-06 15:55:44 +08:00
parent 210f731b59
commit 18e96d1c0c
29 changed files with 821 additions and 26 deletions

View File

@ -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
- feature-meta_build
## 触发多项目构建
trigger_job:
stage: deploy-trigger
trigger:
project: devops/automation/build-eci
branch: 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

8
.gitmodules vendored
View File

@ -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
View 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

View File

@ -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'

View File

@ -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())

View File

@ -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()?.let { pkgLinkEntity ->
if (pkgLinkEntity.isHomeTopTabLink) {
PkgHelper.markConfigUsed()
for ((index, tab) in homeTab.withIndex()) {
if (pkgLinkEntity.type == tab.type && pkgLinkEntity.link == tab.link) {
defaultTabPosition = index
break
}
}
}
}
if (!isRefresh) {
tabs.postValue(homeTab)
}

View File

@ -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;
@ -266,11 +269,47 @@ public class MainWrapperFragment extends BaseFragment_ViewPager_Checkable implem
}
});
applyPkgConfig();
ViewModelProviders.of(this)
.get(MessageUnreadViewModel.class)
.getUnreadMessageTotalLiveData().observe(this, isShow -> ExtensionsKt.goneIf(mBinding.mainIvMessageHint, !isShow));
}
private void applyPkgConfig() {
PkgConfigEntity.PkgLinkEntity pkgLinkEntity = PkgHelper.INSTANCE.getPkgConfig();
if (pkgLinkEntity != null && !pkgLinkEntity.isHomeTopTabLink()) {
String bottomTab = pkgLinkEntity.getHomeBottomTab();
PkgHelper.INSTANCE.markConfigUsed();
if (!TextUtils.isEmpty(bottomTab)) {
// 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);
} else {
DirectUtils.directToLinkPage(requireContext(), pkgLinkEntity, "推广包配置", "首页");
}
}
}
public void getDialog() {
mViewModel.requestOpeningData();
mViewModel.getPrivacyPolicyDialog().observe(this, it -> {

View File

@ -0,0 +1,47 @@
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
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(): PkgConfigEntity.PkgLinkEntity? {
if (mPkgConfigLink == null
&& !SPUtils.getBoolean(SP_PKG_CONFIG_IS_USED, false)
&& BuildConfig.FIRST_LAUNCH.isNotEmpty()) {
mPkgConfigLink = Base64.decode(BuildConfig.FIRST_LAUNCH, Base64.DEFAULT).toString().toObject()
}
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
}
}
}

View 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)
}
}

View File

@ -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))

View File

@ -76,6 +76,8 @@ object RouteConsts {
const val vpn = "/vpn/vpn"
const val pkg = "/pkg/pkg"
const val sensors = "/sensors/sensors"
}

View File

@ -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 isHomeTopTabLink: Boolean = false,
@SerializedName("bottom_index")
var homeBottomTab: String = ""
) : LinkEntity()
}

View File

@ -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
View File

@ -0,0 +1 @@
/build

87
module_pkg/build.gradle Normal file
View 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
View 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

View 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>

View 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
}
}
}

View File

@ -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
}
}

View File

@ -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>
}

View File

@ -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)
}

View 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>

View File

@ -0,0 +1,3 @@
<resources>
<string name="app_name" translatable="false">PKG</string>
</resources>

View File

@ -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
}
}
}

View File

@ -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
}
}

View File

@ -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)
}
}

View 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>

119
scripts/meta_build.sh Executable file
View 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

View File

@ -14,4 +14,5 @@ include ':ndownload'
include ':module_core_feature'
include ':module_lib'
include ':module_vpn'
include ':module_pkg'
include ':module_sensors_data'