Compare commits

..

10 Commits

Author SHA1 Message Date
5a826234d0 fix 2020-12-03 14:55:02 +08:00
9f5ffb084a 修复APP更新逻辑,以VersionName为准
修复App更新无法下载安装包问题
2020-11-23 18:38:01 +08:00
b5d4cbe718 更新启动弹窗隐私协议和用户协议内容 2020-11-20 14:20:49 +08:00
b39a47c0bd 光环马甲包4.3.8修改 2020-11-20 14:18:39 +08:00
5ea6647bf7 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into video_only
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/LoginActivity.java
#	app/src/main/java/com/gh/gamecenter/MainActivity.java
#	app/src/main/java/com/gh/gamecenter/SplashScreenActivity.java
#	app/src/main/java/com/gh/gamecenter/collection/CollectionWrapperFragment.java
#	app/src/main/java/com/gh/gamecenter/fragment/MainWrapperFragment.java
#	app/src/main/java/com/gh/gamecenter/history/HistoryWrapperFragment.kt
#	app/src/main/java/com/gh/gamecenter/personal/PersonalViewModel.kt
#	app/src/main/java/com/gh/gamecenter/personalhome/UserHomeFragment.kt
#	app/src/main/res/layout/fragment_home.xml
#	app/src/main/res/layout/fragment_login.xml
#	app/src/main/res/layout/fragment_personal.xml
2020-11-13 16:04:36 +08:00
798c4a2089 update 2020-04-29 10:59:39 +08:00
0686f70df6 更新到3.7.6 2020-04-29 10:51:28 +08:00
3c30564ab6 update 2020-04-10 19:10:11 +08:00
f04070e846 update 2020-04-02 18:39:01 +08:00
fc279839fa 光环助手马甲包——视频 https://gitlab.ghzs.com/pm/yunying/issues/1051 2020-04-02 15:07:11 +08:00
2903 changed files with 34957 additions and 50151 deletions

1
.gitignore vendored
View File

@ -7,6 +7,5 @@ local.properties
captures/
build/
release-app/
test-app/
scripts/apk-channel/
app/src/test/java/com/gh/gamecenter

2
.gitmodules vendored
View File

@ -1,4 +1,4 @@
[submodule "libraries/LGLibrary"]
path = libraries/LGLibrary
url = git@git.ghzs.com:android/common-library.git
url = git@gitlab.ghzs.com:android/common-library.git
branch = master

View File

@ -2,10 +2,11 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' // kotlin
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
//apply plugin: 'io.sentry.android.gradle'
apply plugin: 'AndResGuard'
import groovy.xml.XmlUtil
// apkChannelPackage
apply plugin: 'channel'
//apply from: 'tinker-support.gradle'
android {
@ -13,9 +14,8 @@ android {
experimental = true
}
buildFeatures {
viewBinding = true
dataBinding = true
dataBinding {
enabled = true
}
compileOptions {
@ -32,10 +32,6 @@ android {
javaMaxHeapSize "4g"
}
aaptOptions {
additionalParameters "--no-version-vectors"
}
defaultConfig {
multiDexEnabled true
@ -46,7 +42,7 @@ android {
}
ndk {
abiFilters "armeabi-v7a", "x86"
abiFilters "armeabi-v7a"
}
renderscriptTargetApi 18
@ -76,8 +72,6 @@ android {
buildConfigField "String", "TTAD_APPID", "\"${TTAD_APPID}\""
buildConfigField "String", "DOUYIN_CLIENTKEY", "\"${DOUYIN_CLIENTKEY}\""
buildConfigField "String", "DOUYIN_CLIENTSECRET", "\"${DOUYIN_CLIENTSECRET}\""
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
buildConfigField "String", "MIPUSH_APPID", "\"${MIPUSH_APPID}\""
buildConfigField "String", "MIPUSH_APPKEY", "\"${MIPUSH_APPKEY}\""
@ -131,27 +125,15 @@ android {
}
}
flavorDimensions("env")
sourceSets {
publish {
java.srcDirs = ['src/main/java']
}
internal {
java.srcDirs = ['src/main/java']
}
tea {
java.srcDirs = ['src/main/java', 'src/tea/java']
}
gdt {
java.srcDirs = ['src/main/java', 'src/gdt/java']
}
}
flavorDimensions "nonsense"
/**
* 多渠道打包,渠道请参考"channel.txt"文件所有渠道值均通过java code设置
*/
productFlavors {
// publish release host
publish {
dimension "env"
dimension "nonsense"
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
buildConfigField "String", "SENSITIVE_API_HOST", "\"${SENSITIVE_API_HOST}\""
@ -162,7 +144,7 @@ android {
}
// internal test dev host
internal {
dimension "env"
dimension "nonsense"
versionNameSuffix "-debug"
buildConfigField "String", "API_HOST", "\"${DEV_API_HOST}\""
@ -173,35 +155,26 @@ android {
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${DEV_UMENG_MESSAGE_SECRET}\""
buildConfigField "String", "BUGLY_APPID", "\"${DEV_BUGLY_APPID}\""
}
tea {
dimension "env"
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
buildConfigField "String", "SENSITIVE_API_HOST", "\"${SENSITIVE_API_HOST}\""
buildConfigField "String", "UMENG_APPKEY", "\"${UMENG_APPKEY}\""
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${UMENG_MESSAGE_SECRET}\""
buildConfigField "String", "BUGLY_APPID", "\"${BUGLY_APPID}\""
manifestPlaceholders.put("APPLOG_SCHEME", "rangersapplog.byAx6uYt".toLowerCase())
}
gdt {
dimension "env"
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
buildConfigField "String", "SENSITIVE_API_HOST", "\"${SENSITIVE_API_HOST}\""
buildConfigField "String", "UMENG_APPKEY", "\"${UMENG_APPKEY}\""
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${UMENG_MESSAGE_SECRET}\""
buildConfigField "String", "BUGLY_APPID", "\"${BUGLY_APPID}\""
}
}
}
// apkChannelPackage
channel {
//多渠道包的输出目录默认为new File(project.buildDir,"channel")
baseOutputDir = new File(project.buildDir, "channel")
//多渠道包的命名规则,默认为:${appName}-${versionName}-${versionCode}-${flavorName}-${buildType}
apkNameFormat = '${appName}-${versionName}-${versionCode}-${flavorName}-${buildType}'
}
rebuildChannel {
// baseDebugApk = 已有Debug APK
// baseReleaseApk = 已有Release APK
// //默认为new File(project.buildDir, "rebuildChannel/debug")
// debugOutputDir = Debug渠道包输出目录
// //默认为new File(project.buildDir, "rebuildChannel/release")
// releaseOutputDir = Release渠道包输出目录
}
repositories {
flatDir {
dirs 'libs', 'libs/aars'
@ -211,7 +184,6 @@ repositories {
dependencies {
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
gdtImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/gdt/libs')
testImplementation 'junit:junit:4.12'
@ -222,8 +194,8 @@ dependencies {
debugImplementation "com.gu.android:toolargetool:${toolargetool}"
debugImplementation "com.github.nichbar:WhatTheStack:$whatTheStack"
implementation "androidx.core:core-ktx:${core}"
implementation "androidx.fragment:fragment-ktx:${fragment}"
implementation "androidx.core:core:${core}"
implementation "androidx.fragment:fragment:${fragment}"
implementation "androidx.multidex:multidex:${multiDex}"
implementation "androidx.appcompat:appcompat:${appCompat}"
implementation "androidx.cardview:cardview:${cardView}"
@ -244,10 +216,8 @@ dependencies {
implementation "com.kyleduo.switchbutton:library:${switchButton}"
implementation "com.facebook.fresco:fresco:${fresco}"
implementation "com.facebook.fresco:animated-gif-lite:${fresco}"
implementation "com.facebook.fresco:animated-gif:${fresco}"
implementation "com.facebook.fresco:animated-drawable:${fresco}"
implementation "com.facebook.fresco:animated-webp:${fresco}"
implementation "com.facebook.fresco:webpsupport:${fresco}"
implementation "com.squareup.okhttp3:okhttp:${okHttp}"
@ -315,11 +285,11 @@ dependencies {
implementation "com.ethanhua:skeleton:${skeleton}"
implementation "io.supercharge:shimmerlayout:${shimmerlayout}"
implementation "com.tencent.mm.opensdk:wechat-sdk-android-without-mta:${mta}"
implementation "com.github.nichbar:AndroidRomChecker:${romChecker}"
implementation "com.walkud.rom.checker:RomChecker:${romChecker}"
debugImplementation "com.github.nichbar.chucker:library:$chucker"
releaseImplementation "com.github.nichbar.chucker:library-no-op:$chucker"
teaImplementation "com.bytedance.applog:RangersAppLog-Lite-cn:$bytedanceApplog"
// implementation "com.bytedance.applog:RangersAppLog-Lite-cn:$bytedanceApplog"
// implementation "com.bytedance.ies.ugc.aweme:opensdk-china-external:$bytedanceAweme"
// implementation "com.bytedance.ies.ugc.aweme:opensdk-common:$bytedanceAweme"
@ -329,22 +299,13 @@ dependencies {
implementation "net.lingala.zip4j:zip4j:${zip4j}"
// plugin 需要字符串,故不能用值
implementation "io.sentry:sentry-android:3.2.0"
implementation("com.github.piasy:BigImageViewer:$bigImageViewer", {
exclude group: 'com.squareup.okhttp3'
exclude group: 'androidx.swiperefreshlayout'
exclude group: 'com.github.bumptech.glide'
exclude group: 'com.facebook.fresco'
})
implementation "com.github.PhilJay:MPAndroidChart:${chart}"
implementation "com.github.hsiafan:apk-parser:$apkParser"
implementation "org.nanohttpd:nanohttpd:$nanohttpd"
implementation "com.aliyun.openservices:aliyun-log-android-sdk:$aliyunLog"
implementation project(':libraries:LGLibrary')
// implementation project(':libraries:MTA')
implementation project(':libraries:QQShare')
@ -410,154 +371,3 @@ if (propFile.exists()) {
// task.name.startsWith('merge') && task.name.endsWith('Resources')
// }.each { t -> t.dependsOn generateMetaJson }
//}
andResGuard {
mappingFile = null
use7zip = true
useSign = true
// 打开这个开关会keep住所有资源的原始路径只混淆资源的名字
keepRoot = false
// 设置这个值会把arsc name列混淆成相同的名字减少string常量池的大小
fixedResName = "arg"
// 打开这个开关会合并所有哈希值相同的资源,但请不要过度依赖这个功能去除去冗余资源
mergeDuplicatedRes = true
whiteList = [
"R.drawable.icon",
"R.drawable.bg_notification_answer_style_1",
"R.drawable.bg_notification_answer_style_2",
"R.drawable.bg_notification_article_style_1",
"R.drawable.bg_notification_article_style_2",
"R.drawable.bg_notification_feedback_style_1",
"R.drawable.bg_notification_feedback_style_2",
"R.drawable.bg_notification_gift_style_1",
"R.drawable.bg_notification_gift_style_2",
"R.drawable.bg_notification_login_style_1",
"R.drawable.bg_notification_login_style_2",
"R.drawable.bg_notification_question_style_1",
"R.drawable.bg_notification_question_style_2",
"R.drawable.bg_notification_rating_style_1",
"R.drawable.bg_notification_rating_style_2",
"R.drawable.bg_notification_reserve_game_style_1",
"R.drawable.bg_notification_reserve_game_style_2",
"R.drawable.bg_notification_video_style_1",
"R.drawable.bg_notification_video_style_2",
"R.drawable.ic_search_no_1",
"R.drawable.ic_search_no_2",
"R.drawable.ic_search_no_3",
"R.drawable.ic_search_no_4",
"R.drawable.ic_search_no_5",
"R.drawable.ic_search_no_6",
"R.drawable.ic_search_no_7",
"R.drawable.ic_search_no_8",
"R.drawable.ic_search_no_9",
"R.drawable.ic_search_no_10",
"R.drawable.ic_search_no_11",
"R.drawable.ic_search_no_12",
"R.drawable.ic_search_no_13",
"R.drawable.ic_search_no_14",
"R.drawable.ic_search_no_15",
"R.drawable.ic_search_no_16",
"R.drawable.ic_search_no_17",
"R.drawable.ic_search_no_18",
"R.drawable.ic_search_no_19",
"R.drawable.ic_search_no_20",
"R.drawable.login_btn_bg",
"R.drawable.ic_quick_login_check",
"R.drawable.ic_quick_login_uncheck",
"R.anim.anim_auth_in",
"R.anim.anim_auth_out",
]
compressFilePattern = [
"*.png",
"*.jpg",
"*.jpeg",
"*.gif",
]
sevenzip {
artifact = 'com.tencent.mm:SevenZip:1.2.20'
}
}
project.afterEvaluate {
def variants = null
try {
variants = android.applicationVariants
} catch (Throwable t) {
t.printStackTrace()
try {
variants = android.libraryVariants
} catch (Throwable tt) {
tt.printStackTrace()
}
}
if (variants != null) {
variants.all { variant ->
variant.outputs.each { output ->
def task = output.processManifestProvider.get()
if (task == null) {
return
}
/**
* 为 Manifest 的 Activity 的 configChanges 添加自己手动处理 configurationChanges 配置 [https://developer.android.com/guide/topics/resources/runtime-changes]
* AGP 4.1.0 从 ProcessManifest task 里拿 manifest 的 API 变更调整可以参考这里 [https://github.com/Tencent/tinker/pull/1476/commits/d71645729b13d545ca4ba6826f93fbf558751434]
* (搞半天还是不会抽离方法,有空再把 gradle 改成用 kotlin 实现吧)
*/
task.doLast {
def manifestFile = new File(multiApkManifestOutputDirectory.get().asFile, "AndroidManifest.xml")
if (manifestFile == null || !manifestFile.exists()) {
return
}
String[] configChanges = [
"density",
"fontScale",
"keyboard",
"keyboardHidden",
"layoutDirection",
"locale",
"mcc",
"mnc",
"navigation",
"orientation",
"screenLayout",
"screenSize",
"smallestScreenSize",
"touchscreen",
"uiMode"]
def parser = new XmlSlurper(false, true)
def manifest = parser.parse(manifestFile)
def app = manifest.'application'[0]
app.'activity'.each { act ->
String value = act.attributes()['android:configChanges']
if (value == null || value.isEmpty()) {
if (value == null) value = ""
configChanges.eachWithIndex { config, index ->
if (index != configChanges.length - 1) {
value += config + "|"
} else {
value += config
}
}
act.attributes()['androidconfigChanges'] = value
} else {
String[] valueSplit = value.split("\\|")
println configChanges
configChanges.eachWithIndex { config, index ->
if (!valueSplit.contains(config)) {
value += ("|" + config)
}
}
act.attributes()['android:configChanges'] = value
}
}
def tmpManifest = XmlUtil.serialize(manifest).replaceAll("androidconfigChanges", "android:configChanges")
manifest = parser.parseText(tmpManifest)
manifestFile.setText(XmlUtil.serialize(manifest), "utf-8")
}
}
}
}
}

Binary file not shown.

View File

@ -1,271 +0,0 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in C:\Android\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# 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 *;
#}
#--------- remove logs start ----------------
-assumenosideeffects class com.lightgame.config.CommonDebug {
private static String getLogTag(...);
private static String getMethodName();
public static void logMethodName(...);
public static void logParams(...);
public static void logFields(...);
public static void logMethodWithParams(...);
}
#-assumenosideeffects class com.lightgame.config.CommonDebug {*;}
#-dontoptimize
#--------- remove logs end ----------------
-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod
-dontwarn InnerClasses
# OrmLite uses reflection
-keep class com.j256.**
-keepclassmembers class com.j256.** { *; }
-keep enum com.j256.**
-keepclassmembers enum com.j256.** { *; }
-keep interface com.j256.**
-keepclassmembers interface com.j256.** { *; }
-dontwarn com.j256.**
#okhttp3
-dontwarn com.squareup.okhttp3.**
-dontwarn okio.**
-keep class com.squareup.okhttp3.** { *;}
# stetho
-keep class com.facebook.stetho.** { *; }
-dontwarn com.facebook.stetho.**
# Retrofit 2.2
# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8
# Retain generic type information for use by reflection by converters and adapters.
-keepattributes Signature
# Retain declared checked exceptions for use by a Proxy instance.
-keepattributes Exceptions
# Retrofit 2.X
## https://square.github.io/retrofit/ ##
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
-keepclasseswithmembers class * {
@retrofit2.http.* <methods>;
}
# rxjava
-keep class rx.schedulers.Schedulers {
public static <methods>;
}
-keep class rx.schedulers.ImmediateScheduler {
public <methods>;
}
-keep class rx.schedulers.TestScheduler {
public <methods>;
}
-keep class rx.schedulers.Schedulers {
public static ** test();
}
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
long producerIndex;
long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
long producerNode;
long consumerNode;
}
-dontwarn rx.internal.util.**
## AutoScrollViewPager
-keep class cn.trinea.android.** { *; }
-keepclassmembers class cn.trinea.android.** { *; }
-dontwarn cn.trinea.android.**
## butterknife
# Retain generated class which implement Unbinder.
#-keep public class * implements butterknife.Unbinder { public <init>(**, android.view.View); }
#
## Prevent obfuscation of types which use ButterKnife annotations since the simple name
## is used to reflectively look up the generated ViewBinding.
#-keep class butterknife.*
#-keepclasseswithmembernames class * { @butterknife.* <methods>; }
#-keepclasseswithmembernames class * { @butterknife.* <fields>; }
-dontwarn butterknife.internal.**
-keep class **$$ViewInjector { *; }
-keepnames class * { @butterknife.InjectView *;}
-dontwarn butterknife.Views$InjectViewProcessor
-dontwarn com.gc.materialdesign.views.**
# eventbus
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
# weiboSdk
-keep class com.sina.weibo.sdk.** { *; }
-dontwarn android.webkit.WebView
-dontwarn android.webkit.WebViewClient
# app models
-keep class com.gh.common.view.** {*;}
-keep class com.gh.gamecenter.db.info.** {*;}
-keep class com.gh.gamecenter.entity.** {*;}
-keep class com.gh.gamecenter.qa.entity.** {*;}
-keep class com.gh.gamecenter.retrofit.** {*;}
-keep class com.gh.gamecenter.eventbus.** {*;}
-keep class com.gh.gamecenter.video.detail.** {*;}
-keep class * extends rx.Subscriber
#---------------------------------webview------------------------------------
-keepclassmembers class * extends android.webkit.WebViewClient {
public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
public boolean *(android.webkit.WebView, java.lang.String);
}
-keepclassmembers class * extends android.webkit.WebViewClient {
public void *(android.webkit.WebView, java.lang.String);
}
#----------------------------------------------------------------------------
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON @Expose annotation
-keepattributes *Annotation*
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }
# Prevent proguard from stripping interface information from TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
-keepclassmembers enum * { *; }
##---------------End: proguard configuration for Gson ----------
# ------ bugly ---------
-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}
# easypermission
-keepclassmembers class * {
@pub.devrel.easypermissions.AfterPermissionGranted <methods>;
}
# 重命名文件为SourceFile再配合mapping符号表可以拿到真实的类名
-renamesourcefileattribute SourceFile
# 保留源文件行号
-keepattributes SourceFile,LineNumberTable
-ignorewarnings
-keep @androidx.annotation.Keep class *
-keepclassmembers class ** {
@androidx.annotation.Keep *;
}
-keep class com.gh.loghub.** { *; }
### greenDAO 3
-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
public static java.lang.String TABLENAME;
}
-keep class **$Properties
-keep class org.greenrobot.greendao.** { *; }
# If you do not use SQLCipher:
-dontwarn org.greenrobot.greendao.database.**
# If you do not use RxJava:
-dontwarn rx.**
-dontwarn org.greenrobot.greendao.rx.**
-dontwarn org.greenrobot.greendao.**
### fastJson
-dontwarn com.alibaba.fastjson.**
-keep class com.alibaba.fastjson.** { *; }
-keepattributes Signature
-keepattributes Annotation
### 广点通
-dontwarn com.qq.gdt.action.**
-keep class com.qq.gdt.action.** {*;}
### AndroidX
-keep class androidx.core.app.CoreComponentFactory { *; }
#阿里云上传
-keep class com.alibaba.sdk.android.oss.** { *; }
-dontwarn okio.**
-dontwarn org.apache.commons.codec.binary.**
#视频相关
-keep class com.shuyu.gsyvideoplayer.video.** { *; }
-dontwarn com.shuyu.gsyvideoplayer.video.**
-keep class com.shuyu.gsyvideoplayer.video.base.** { *; }
-dontwarn com.shuyu.gsyvideoplayer.video.base.**
-keep class com.shuyu.gsyvideoplayer.utils.** { *; }
-dontwarn com.shuyu.gsyvideoplayer.utils.**
-keep class tv.danmaku.ijk.** { *; }
-dontwarn tv.danmaku.ijk.**
-keep public class * extends android.view.View{
*** get*();
void set*(***);
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
#穿山甲
-keep class com.bytedance.sdk.openadsdk.** { *; }
-keep public interface com.bytedance.sdk.openadsdk.downloadnew.** {*;}
-keep class com.pgl.sys.ces.* {*;}
-keep class com.gyf.immersionbar.* {*;}
-dontwarn com.gyf.immersionbar.**
-keep class com.taobao.securityjni.**{*;}
-keep class com.taobao.wireless.security.**{*;}
-keep class com.ut.secbody.**{*;}
-keep class com.taobao.dp.**{*;}
-keep class com.alibaba.wireless.security.**{*;}
-keep class com.alibaba.sdk.android.**{*;}
-keep class com.ut.**{*;}
-keep class com.ta.**{*;}
-keep class com.gh.gamecenter.GdtHelper { *; }
-keep class com.gh.gamecenter.TeaHelper { *; }

View File

@ -1,3 +1,20 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in C:\Android\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# 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 *;
#}
#--------- remove logs start ----------------
-assumenosideeffects class com.lightgame.config.CommonDebug {
@ -9,66 +26,126 @@
public static void logMethodWithParams(...);
}
-assumenosideeffects class com.lightgame.utils.Utils {
public static void log(...);
}
#-assumenosideeffects class com.lightgame.config.CommonDebug {*;}
#-dontoptimize
#--------- remove logs end ----------------
# TODO Dicard sourceFile in final release build but remain in internal build.
-renamesourcefileattribute SourceFile
# Keep Attribute
-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod,SourceFile,LineNumberTable
-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod
-dontwarn InnerClasses
# OrmLite
-keep class com.j256.*
-keepclassmembers class com.j256.* { *; }
-keep enum com.j256.*
-keepclassmembers enum com.j256.* { *; }
-keep interface com.j256.*
-keepclassmembers interface com.j256.* { *; }
# OrmLite uses reflection
-keep class com.j256.**
-keepclassmembers class com.j256.** { *; }
-keep enum com.j256.**
-keepclassmembers enum com.j256.** { *; }
-keep interface com.j256.**
-keepclassmembers interface com.j256.** { *; }
-dontwarn com.j256.**
### AutoScrollViewPager
-keep class cn.trinea.android.* { *; }
-keepclassmembers class cn.trinea.android.* { *; }
#okhttp3
-dontwarn com.squareup.okhttp3.**
-dontwarn okio.**
-keep class com.squareup.okhttp3.** { *;}
# stetho
-keep class com.facebook.stetho.** { *; }
-dontwarn com.facebook.stetho.**
# Retrofit 2.2
# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8
# Retain generic type information for use by reflection by converters and adapters.
-keepattributes Signature
# Retain declared checked exceptions for use by a Proxy instance.
-keepattributes Exceptions
# Retrofit 2.X
## https://square.github.io/retrofit/ ##
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
-keepclasseswithmembers class * {
@retrofit2.http.* <methods>;
}
# rxjava
-keep class rx.schedulers.Schedulers {
public static <methods>;
}
-keep class rx.schedulers.ImmediateScheduler {
public <methods>;
}
-keep class rx.schedulers.TestScheduler {
public <methods>;
}
-keep class rx.schedulers.Schedulers {
public static ** test();
}
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
long producerIndex;
long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
long producerNode;
long consumerNode;
}
-dontwarn rx.internal.util.**
## AutoScrollViewPager
-keep class cn.trinea.android.** { *; }
-keepclassmembers class cn.trinea.android.** { *; }
-dontwarn cn.trinea.android.**
### Butterknife
-keep public class * implements butterknife.Unbinder { public <init>(**, android.view.View); }
-keep class butterknife.*
-keepclasseswithmembernames class * { @butterknife.* <methods>; }
-keepclasseswithmembernames class * { @butterknife.* <fields>; }
## butterknife
# Retain generated class which implement Unbinder.
#-keep public class * implements butterknife.Unbinder { public <init>(**, android.view.View); }
#
## Prevent obfuscation of types which use ButterKnife annotations since the simple name
## is used to reflectively look up the generated ViewBinding.
#-keep class butterknife.*
#-keepclasseswithmembernames class * { @butterknife.* <methods>; }
#-keepclasseswithmembernames class * { @butterknife.* <fields>; }
### eventbus
-keepclassmembers class * {
-dontwarn butterknife.internal.**
-keep class **$$ViewInjector { *; }
-keepnames class * { @butterknife.InjectView *;}
-dontwarn butterknife.Views$InjectViewProcessor
-dontwarn com.gc.materialdesign.views.**
# eventbus
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
### Only required if you use AsyncExecutor
# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
### weiboSdk
-keep class com.sina.weibo.sdk.* { *; }
# weiboSdk
-keep class com.sina.weibo.sdk.** { *; }
-dontwarn android.webkit.WebView
-dontwarn android.webkit.WebViewClient
### wechatSdk
### TODO 这里用 com.tencent.*{*;} 不起效?但其它地方可以?
-keep class com.tencent.**{*;}
# app models
-keep class com.gh.common.view.** {*;}
-keep class com.gh.gamecenter.db.info.** {*;}
-keep class com.gh.gamecenter.entity.** {*;}
-keep class com.gh.gamecenter.qa.entity.** {*;}
-keep class com.gh.gamecenter.retrofit.** {*;}
-keep class com.gh.gamecenter.eventbus.** {*;}
-keep class * extends rx.Subscriber
### app models
-keep class com.gh.common.view.* {*;}
-keep class com.gh.gamecenter.db.info.* {*;}
-keep class com.gh.gamecenter.entity.* {*;}
-keep class com.gh.gamecenter.qa.entity.* {*;}
-keep class com.gh.gamecenter.retrofit.* {*;}
-keep class com.gh.gamecenter.eventbus.* {*;}
-keep class com.gh.gamecenter.video.detail.* {*;}
###
#---------------------------------webview------------------------------------
-keepclassmembers class * extends android.webkit.WebViewClient {
public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
public boolean *(android.webkit.WebView, java.lang.String);
@ -76,59 +153,109 @@
-keepclassmembers class * extends android.webkit.WebViewClient {
public void *(android.webkit.WebView, java.lang.String);
}
#----------------------------------------------------------------------------
### easypermission
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON @Expose annotation
-keepattributes *Annotation*
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }
# Prevent proguard from stripping interface information from TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
-keepclassmembers enum * { *; }
##---------------End: proguard configuration for Gson ----------
# ------ bugly ---------
-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}
# easypermission
-keepclassmembers class * {
@pub.devrel.easypermissions.AfterPermissionGranted <methods>;
}
# TODO What's this ?
# 重命名文件为SourceFile再配合mapping符号表可以拿到真实的类名
-renamesourcefileattribute SourceFile
# 保留源文件行号
-keepattributes SourceFile,LineNumberTable
-ignorewarnings
### Keep Annotation
-keep @androidx.annotation.Keep class *
-keepclassmembers class * {
-keepclassmembers class ** {
@androidx.annotation.Keep *;
}
-keep class com.gh.loghub.** { *; }
### greenDAO 3
-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
public static java.lang.String TABLENAME;
}
-keep class **$Properties
-keep class org.greenrobot.greendao.** { *; }
# If you do not use SQLCipher:
-dontwarn org.greenrobot.greendao.database.**
# If you do not use RxJava:
-dontwarn rx.**
-dontwarn org.greenrobot.greendao.rx.**
-dontwarn org.greenrobot.greendao.**
### fastJson
-dontwarn com.alibaba.fastjson.**
-keep class com.alibaba.fastjson.** { *; }
-keepattributes Signature
-keepattributes Annotation
### 广点通
-dontwarn com.qq.gdt.action.**
-keep class com.qq.gdt.action.* {*;}
-keep class com.qq.gdt.action.** {*;}
### 阿里云上传
-keep class com.alibaba.sdk.android.oss.* { *; }
### AndroidX
-keep class androidx.core.app.CoreComponentFactory { *; }
#阿里云上传
-keep class com.alibaba.sdk.android.oss.** { *; }
-dontwarn okio.**
-dontwarn org.apache.commons.codec.binary.**
### 视频相关
-keep class com.shuyu.gsyvideoplayer.video.* { *; }
#视频相关
-keep class com.shuyu.gsyvideoplayer.video.** { *; }
-dontwarn com.shuyu.gsyvideoplayer.video.**
-keep class com.shuyu.gsyvideoplayer.video.base.* { *; }
-keep class com.shuyu.gsyvideoplayer.video.base.** { *; }
-dontwarn com.shuyu.gsyvideoplayer.video.base.**
-keep class com.shuyu.gsyvideoplayer.utils.* { *; }
-keep class com.shuyu.gsyvideoplayer.utils.** { *; }
-dontwarn com.shuyu.gsyvideoplayer.utils.**
-keep class tv.danmaku.ijk.* { *; }
-keep class tv.danmaku.ijk.** { *; }
-dontwarn tv.danmaku.ijk.**
-keep public class * extends android.view.View{
*** get*();
void set*(***);
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keep class com.alibaba.sdk.android.*{*;}
-keep class com.ut.*{*;}
-keep class com.ta.*{*;}
#穿山甲
-keep class com.bytedance.sdk.openadsdk.** { *; }
-keep public interface com.bytedance.sdk.openadsdk.downloadnew.** {*;}
-keep class com.pgl.sys.ces.* {*;}
### GDT & TEA
-keep class com.gh.gamecenter.GdtHelper { *; }
-keep class com.gh.gamecenter.TeaHelper { *; }
-keep class com.gyf.immersionbar.* {*;}
-dontwarn com.gyf.immersionbar.**
### 阿里云日志
-keep class com.aliyun.sls.android.producer.* { *; }
-keep interface com.aliyun.sls.android.producer.* { *; }
-keep class com.taobao.securityjni.**{*;}
-keep class com.taobao.wireless.security.**{*;}
-keep class com.ut.secbody.**{*;}
-keep class com.taobao.dp.**{*;}
-keep class com.alibaba.wireless.security.**{*;}
### 中国移动一键登录
-dontwarn com.cmic.sso.sdk.**
-keep class com.cmic.sso.sdk.* { *; }
-keep class com.alibaba.sdk.android.**{*;}
-keep class com.ut.**{*;}
-keep class com.ta.**{*;}

View File

@ -1,77 +0,0 @@
package com.gh.gamecenter
import android.app.Application
import android.text.TextUtils
import android.util.Log
import com.gh.common.util.ToastUtils
import com.lightgame.utils.Utils
import com.qq.gdt.action.GDTAction
import org.json.JSONObject
/**
* 广点通辅助类 [https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/403]
*
* 更换帐号 [https://gitlab.ghzs.com/pm/yunying/issues/893]
*/
object GdtHelper {
const val NETWORK_TYPE = "NETWORK_TYPE"
const val PAGE_TYPE = "PAGE_TYPE"
const val CONTENT_TYPE = "CONTENT_TYPE"
const val CONTENT_ID = "CONTENT_ID"
const val KEYWORD = "KEYWORD"
const val GAME_ID = "GAME_ID"
const val SCORE = "SCORE"
const val PLATFORM = "PLATFORM"
@JvmStatic
fun init(application: Application, channel: String) {
if (shouldUseGdtHelper()) {
if (channel == "GH_728") {
GDTAction.init(application, "1111012969", "9d3d9da5b0948a317c03d08f14d445dc")
} else if (channel == "GH_729") {
GDTAction.init(application, "1111013063", "f53dabf458a356b101d99fc4069eb7f1")
} else if (channel == "GH_765") {
GDTAction.init(application, "1111327925", "588d503f0990f98f9b2394fbb795c570")
} else {
GDTAction.init(application, "1110680399", "f5ddaafbf520d7d7385499232a408d0a")
}
}
Utils.log("init GdtHelper")
}
// fun logAction(type: String) {
// if (shouldUseGdtHelper()) {
// GDTAction.logAction(type)
// Utils.log("GDT", type)
// }
// }
@JvmStatic
fun logAction(type: String, vararg kv: String?) {
try {
val actionParam = JSONObject()
for (i in kv.indices) {
if (i % 2 != 0) {
val key = kv[i - 1]
val value = kv[i]
if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
actionParam.put(key, value)
}
}
}
Utils.log("GDT", "$type + [${kv.joinToString(" , ")}]")
GDTAction.logAction(type, actionParam)
} catch (e: Exception) {
e.printStackTrace()
}
}
// TODO 确认开启的渠道条件
private fun shouldUseGdtHelper(): Boolean {
return true
//
// val channel = HaloApp.getInstance().channel
// return !(TextUtils.isEmpty(channel) || channel.contains("GDT".toLowerCase(Locale.CHINA)))
}
}

View File

@ -9,6 +9,8 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 允许应用程序读取扩展存储器 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 允许挂载和反挂载文件系统可移动存储 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- 允许应用程序访问Wi-Fi网络状态信息 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 允许应用程序获取网络信息状态 -->
@ -21,9 +23,11 @@
<uses-permission android:name="android.permission.VIBRATE" />
<!-- 允许应用程序改变Wi-Fi连接状态 -->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!-- 允许应用程序改变网络连接状态 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<!-- 允许应用程序快捷方式 -->
<!-- 允许应用程序打开系统窗口,显示其他应用程序 -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<!-- 修改系统设置的权限 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!-- 创建快捷方式的权限 -->
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission
@ -31,7 +35,7 @@
tools:ignore="ProtectedPermissions" />
<!-- bugly with tinker -->
<!-- <uses-permission android:name="android.permission.READ_LOGS" />-->
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<!--可选,穿山甲提供“获取地理位置权限”和“不给予地理位置权限,开发者传入地理位置参数”两种方式上报用户位置,两种方式均可不选,添加位置权限或参数将帮助投放定位广告-->
@ -72,19 +76,9 @@
android:largeHeap="true"
android:resizeableActivity="true"
android:theme="@style/AppCompatTheme.APP"
android:networkSecurityConfig="@xml/network_security_config"
tools:replace="android:allowBackup"
tools:targetApi="n">
<meta-data
android:name="io.sentry.auto-init"
android:value="false" />
<!-- 不让 sentry 读取系统事件 -->
<meta-data
android:name="io.sentry.breadcrumbs.system-events"
android:value="false" />
<!--android:launchMode = "singleTask"-->
<activity
android:name="com.gh.gamecenter.SplashScreenActivity"
@ -468,7 +462,7 @@
<activity
android:name="com.gh.gamecenter.video.upload.view.UploadVideoActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden" />
android:windowSoftInputMode="stateHidden"/>
<activity
android:name="com.gh.gamecenter.video.game.GameVideoActivity"
@ -583,7 +577,7 @@
<activity
android:name=".personalhome.background.BackgroundClipActivity"
android:screenOrientation="portrait"
android:theme="@style/TransparentStatusBarAndNavigationBar" />
android:theme="@style/TransparentStatusBarAndNavigationBar"/>
<activity
android:name=".personalhome.excellentcomments.ExcellentCommentsActivity"
@ -597,66 +591,12 @@
android:name=".simulatorgame.SimulatorManagementActivity"
android:screenOrientation="portrait" />
<!-- 使用小米/华为推送弹窗功能提高推送成功率-->
<activity
android:name=".catalog.CatalogActivity"
android:screenOrientation="portrait" />
<activity
android:name=".catalog.NewCatalogListActivity"
android:screenOrientation="portrait" />
<activity
android:name=".forum.search.ForumOrUserSearchActivity"
android:screenOrientation="portrait" />
<activity
android:name=".energy.EnergyCenterActivity"
android:screenOrientation="portrait"
android:launchMode="singleTask" />
<activity
android:name=".energy.EnergyHouseActivity"
android:screenOrientation="portrait" />
<activity
android:name=".personal.NewPersonalActivity"
android:screenOrientation="portrait" />
<activity
android:name=".qa.questions.draft.QuestionDraftActivity"
android:screenOrientation="portrait" />
<activity
android:name=".servers.GameServerTestActivity"
android:screenOrientation="portrait" />
<activity
android:name=".category2.CategoryV2Activity"
android:screenOrientation="portrait" />
<activity
android:name=".personal.DeliveryInfoActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.cmic.sso.sdk.activity.LoginAuthActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@android:style/Theme.Dialog"
android:screenOrientation="portrait"
android:launchMode="singleTop">
</activity>
<activity
android:name=".home.skip.PackageSkipActivity"
android:screenOrientation="portrait" />
<!-- &lt;!&ndash; 使用小米/华为推送弹窗功能提高推送成功率&ndash;&gt;-->
<!-- <activity-->
<!-- android:name="com.gh.gamecenter.PushProxyActivity"-->
<!-- android:exported="true"-->
<!-- android:launchMode="singleTask"-->
<!-- android:theme="@android:style/Theme.Translucent" />-->
android:name="com.gh.gamecenter.PushProxyActivity"
android:exported="true"
android:launchMode="singleTask"
android:theme="@android:style/Theme.Translucent" />
<activity
android:name="com.gh.gamecenter.SkipActivity"
@ -668,14 +608,6 @@
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
<intent-filter>
<data android:scheme="market" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
<activity
@ -686,11 +618,11 @@
android:screenOrientation="portrait"
android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity>
<!-- <activity-->
<!-- android:name="${applicationId}.douyinapi.DouYinEntryActivity"-->
<!-- android:launchMode="singleTask"-->
<!-- android:taskAffinity="${applicationId}"-->
<!-- android:exported="true" />-->
<!-- <activity-->
<!-- android:name="${applicationId}.douyinapi.DouYinEntryActivity"-->
<!-- android:launchMode="singleTask"-->
<!-- android:taskAffinity="${applicationId}"-->
<!-- android:exported="true" />-->
<provider
android:name="androidx.core.content.FileProvider"
@ -702,11 +634,6 @@
android:resource="@xml/provider_paths" />
</provider>
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:node="remove" />
<receiver
android:name="com.gh.gamecenter.receiver.DownloadReceiver"
android:exported="false">
@ -730,45 +657,45 @@
</intent-filter>
</receiver>
<!-- <receiver android:name="com.gh.gamecenter.receiver.UmengMessageReceiver">-->
<!-- <intent-filter>-->
<!-- <action android:name="com.gh.gamecenter.UMENG" />-->
<!-- </intent-filter>-->
<!-- </receiver>-->
<!-- <receiver android:name="com.gh.gamecenter.receiver.UmengMessageReceiver">-->
<!-- <intent-filter>-->
<!-- <action android:name="com.gh.gamecenter.UMENG" />-->
<!-- </intent-filter>-->
<!-- </receiver>-->
<!-- &lt;!&ndash;魅族push应用定义消息receiver声明 &ndash;&gt;-->
<!-- <receiver android:name="com.gh.gamecenter.receiver.UmengMeizuPushReceiver">-->
<!-- <intent-filter>-->
<!-- &lt;!&ndash; 接收push消息 &ndash;&gt;-->
<!-- <action android:name="com.meizu.flyme.push.intent.MESSAGE" />-->
<!-- &lt;!&ndash; 接收register消息 &ndash;&gt;-->
<!-- <action android:name="com.meizu.flyme.push.intent.REGISTER.FEEDBACK" />-->
<!-- &lt;!&ndash; 接收unregister消息&ndash;&gt;-->
<!-- <action android:name="com.meizu.flyme.push.intent.UNREGISTER.FEEDBACK" />-->
<!-- &lt;!&ndash; 兼容低版本Flyme3推送服务配置 &ndash;&gt;-->
<!-- <action android:name="com.meizu.c2dm.intent.REGISTRATION" />-->
<!-- <action android:name="com.meizu.c2dm.intent.RECEIVE" />-->
<!-- &lt;!&ndash;魅族push应用定义消息receiver声明 &ndash;&gt;-->
<!-- <receiver android:name="com.gh.gamecenter.receiver.UmengMeizuPushReceiver">-->
<!-- <intent-filter>-->
<!-- &lt;!&ndash; 接收push消息 &ndash;&gt;-->
<!-- <action android:name="com.meizu.flyme.push.intent.MESSAGE" />-->
<!-- &lt;!&ndash; 接收register消息 &ndash;&gt;-->
<!-- <action android:name="com.meizu.flyme.push.intent.REGISTER.FEEDBACK" />-->
<!-- &lt;!&ndash; 接收unregister消息&ndash;&gt;-->
<!-- <action android:name="com.meizu.flyme.push.intent.UNREGISTER.FEEDBACK" />-->
<!-- &lt;!&ndash; 兼容低版本Flyme3推送服务配置 &ndash;&gt;-->
<!-- <action android:name="com.meizu.c2dm.intent.REGISTRATION" />-->
<!-- <action android:name="com.meizu.c2dm.intent.RECEIVE" />-->
<!-- <category android:name="${applicationId}" />-->
<!-- </intent-filter>-->
<!-- </receiver>-->
<!-- <category android:name="${applicationId}" />-->
<!-- </intent-filter>-->
<!-- </receiver>-->
<!-- <receiver-->
<!-- android:name="com.gh.common.im.ImReceiver"-->
<!-- android:enabled="true">-->
<!-- <intent-filter android:priority="2147483647">-->
<!-- <action android:name="com.gh.im" />-->
<!-- <action android:name="action_finish" />-->
<!-- </intent-filter>-->
<!-- </receiver>-->
<!-- <receiver-->
<!-- android:name="com.gh.common.im.ImReceiver"-->
<!-- android:enabled="true">-->
<!-- <intent-filter android:priority="2147483647">-->
<!-- <action android:name="com.gh.im" />-->
<!-- <action android:name="action_finish" />-->
<!-- </intent-filter>-->
<!-- </receiver>-->
<!-- <meta-data-->
<!-- android:name="com.huawei.hms.client.appid"-->
<!-- android:value="@string/huawei_push_appid" />-->
<!-- <meta-data-->
<!-- android:name="com.huawei.hms.client.appid"-->
<!-- android:value="@string/huawei_push_appid" />-->
<!-- <service-->
<!-- android:name="com.gh.base.GHUmengNotificationService"-->
<!-- android:permission="android.permission.BIND_JOB_SERVICE" />-->
<!-- <service-->
<!-- android:name="com.gh.base.GHUmengNotificationService"-->
<!-- android:permission="android.permission.BIND_JOB_SERVICE" />-->
<!--<service android:name = "com.gh.gamecenter.statistics.AppStaticService" />-->

View File

@ -0,0 +1,40 @@
emoji_kf_1.png,:smile:
emoji_kf_2.png,:smiley:
emoji_kf_3.png,:laughing:
emoji_kf_4.png,:blush:
emoji_kf_5.png,:heart_eyes:
emoji_kf_6.png,:smirk:
emoji_kf_7.png,:flushed:
emoji_kf_8.png,:kissing_heart:
emoji_kf_9.png,:grin:
emoji_kf_10.png,:wink:
emoji_kf_11.png,:stuck_out_tongue_winking_eye:
emoji_kf_12.png,:stuck_out_tongue_closed eyes:
emoji_kf_13.png,:worried:
emoji_kf_14.png,:sleeping:
emoji_kf_15.png,:expressionless:
emoji_kf_16.png,:sweat_smile:
emoji_kf_17.png,:joy:
emoji_kf_18.png,:cold_sweat:
emoji_kf_19.png,:sob:
emoji_kf_20.png,:angry:
emoji_kf_21.png,:mask:
emoji_kf_22.png,:scream:
emoji_kf_23.png,:sunglasses:
emoji_kf_24.png,:heart:
emoji_kf_25.png,:broken_heart:
emoji_kf_26.png,:star:
emoji_kf_27.png,:anger:
emoji_kf_28.png,:exclamation:
emoji_kf_29.png,:question:
emoji_kf_30.png,:zzz:
emoji_kf_31.png,:thumbsup:
emoji_kf_32.png,:thumbsdown:
emoji_kf_33.png,:ok_hand:
emoji_kf_34.png,:punch:
emoji_kf_35.png,:yeah:
emoji_kf_36.png,:clap:
emoji_kf_37.png,:muscle:
emoji_kf_38.png,:pray:
emoji_kf_39.png,:skull:
emoji_kf_40.png,:trollface:

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,5 @@
# This is a simple Microlog configuration file
microlog.level=DEBUG
microlog.appender=LogCatAppender;FileAppender
microlog.formatter=PatternFormatter
microlog.formatter.PatternFormatter.pattern=%c [%P] %m %T

File diff suppressed because it is too large Load Diff

View File

@ -1,493 +1,161 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>光环助手软件许可及服务协议</title>
</head>
<html lang="en"><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>光环助手软件许可及服务协议</title>
<style>
* {
margin: 0;
padding: 0;
font-size: 14px;
-webkit-user-select: text;
-moz-user-select: text;
-ms-user-select: text;
user-select: text;
}
* {
-webkit-user-select: text;
-moz-user-select: text;
-ms-user-select: text;
user-select: text;
font-size: 16px;
}
</style>
</head>
<body>
<div class="content-area">
<p><b></b></p>
<p>
<b>光环</b>
<b>game</b>
<b>软件许可及服务协议</b>
</p>
<p><b>更新日期2020年11月20日</b></p>
<p><b>生效日期2020年11月30日</b></p>
<p><b>首部及导言</b></p>
<p>欢迎使用光环game软件许可及服务</p>
<p>
各位用户在使用光环game前请您务必审慎阅读、并充分理解本协议中的各项条款
<b>
特别是免除或者限制责任的条款,以及开通或使用某项服务的单独协议,并选择接受或不接受。
</b>
除非您已阅读并接受本协议所有条款,否则您无权下载、安装或使用本软件及相关服务。您的下载、安装、使用、登录等行为即视为您已阅读并同意上述协议的约束。
</p>
<p>如果您未满18周岁请在法定监护人的陪同下阅读本协议及其他上述协议。</p>
<p><b>一、权利声明</b></p>
<p>
“光环game”的一切知识产权以及与“光环game”相关的所有信息内容包括但不限于文字表述及其组合、图标、图饰、图像、图表、色彩、界面设计、版面框架、有关数据、附加程序、印刷材料或电子文档等均为光环game所有受著作权法和国际著作权条约以及其他知识产权法律法规的保护。
</p>
<p><b>二、软件使用规范</b></p>
<p>
2.1
本软件是基于Android安卓系统手机、平板电脑(PAD)等设备开发的一款软件,提供注册登录、观看视频、视频投稿等功能
</p>
<p>2.2 软件的下载、安装和使用</p>
<p>
本软件为免费软件用户可以非商业性、无限制数量地从光环game授权的渠道下载、安装及使用本软件。
</p>
<p>
<b>如果您从未经光环</b>
<b>game</b>
<b>授权的第三方获取本软件或与本软件名称相同的安装程序,光环</b>
<b>game</b>
<b>无法保证该软件能够正常使用,并对因此给您造成的损失不予负责。</b>
</p>
<p>2.3 软件的复制、分发和传播</p>
<p>
本产品以研究交流为目的。用户可以非商业性、无限制数量地复制、分发和传播本软件产品。但必须保证每一份复制、分发和传播都是完整和真实的,
包括所有有关本软件产品的软件、电子文档, 版权和商标,亦包括本协议。
</p>
<p>2.4 软件的更新</p>
<p>
为了改善用户体验、完善服务内容光环game将不断努力开发新的服务并为您不时提供软件更新这些更新可能会采取软件替换、修改、功能强化、版本升级等形式。为了保证本软件及服务的安全性和功能的一致性光环game有权不经向您特别通知而对软件进行更新或者对软件的部分功能效果进行改变或限制。本软件新版本发布后旧版本的软件可能无法使用。光环game不保证旧版本软件继续可用及相应的客户服务请您随时核对并下载最新版本。
</p>
<p><b>三、用户使用须知</b></p>
<p>3.1 您理解并同意:</p>
<p>
为了向您提供有效的服务,本软件会利用您移动通讯终端的处理器和带宽等资源。本软件使用过程中可能产生数据流量的费用,用户需自行向运营商了解相关资费信息,并自行承担相关费用.
</p>
<p>3.2您理解并同意:</p>
<p>
<b>
如果因您不正当使用本软件造成了不良影响,或因使用本软件造成的包括但不限于数据异常等问题,均由使用者自行承担,光环团队不对任意类型的使用结果承担责任;
</b>
</p>
<p>3.3您理解并同意:</p>
<p>
本软件不含任何破坏用户移动通讯设备数据和获取用户隐私信息的恶意代码,不会泄露用户的个人信息和隐私;
</p>
<p>3.4您理解并同意:</p>
<p>
<b>
对于包括但不限于互联网网络故障、计算机故障、手机故障或病毒、信息损坏或丢失、计算机系统问题,或其它任何基于不可抗力原因而产生的损失,光环团队不承担任何责任。
</b>
</p>
<p>3.5您理解并同意:</p>
<p>光环game发布、收录的视频均不代表光环立场。</p>
<p>3.6您理解并同意:</p>
<p>
用户应在遵守法律及本协议的前提下使用本软件。用户无权实施包括但不限于下列行为:
</p>
<p>3.6.1 不得删除或者改变本软件上的所有权利管理电子信息</p>
<p>
3.6.2
不得故意避开或者破坏著作权人为保护本软件著作权而采取的技术措施;&nbsp;
</p>
<p>3.6.3 用户不得利用本软件误导、欺骗他人;&nbsp;</p>
<p>
3.6.4
违反国家规定,对计算机信息系统功能进行删除、修改、增加、干扰,造成计算机信息系统不能正常运行;&nbsp;
</p>
<p>3.6.5 未经允许,进入计算机信息网络或者使用计算机信息网络资源;&nbsp;</p>
<p>3.6.6 未经允许,对计算机信息网络功能进行删除、修改或者增加;&nbsp;</p>
<p>
3.6.7
未经允许,对计算机信息网络中存储、处理或者传输的数据和应用程序进行删除、修改或者增加;&nbsp;
</p>
<p>
3.6.8
破坏本软件系统或网站的正常运行,故意传播计算机病毒等破坏性程序;&nbsp;
</p>
<p>3.6.9 其他任何危害计算机信息网络安全的行为。&nbsp;</p>
<p>3.7 您理解并同意:</p>
<p>
本软件经过详细的测试,但不能保证与所有的软硬件系统完全兼容,不能保证本软件完全没有错误。如果出现不兼容及软件错误的情况,用户可通过各反馈途径将情况告知光环团队,获得技术支持。如果无法解决兼容性问题,用户可以删除本软件。
</p>
<p><b>四、争议解决处理</b></p>
<p>
本《协议》的解释、效力及纠纷的解决适用于中华人民共和国法律。若用户和光环game之间发生任何纠纷或争议首先应友好协商解决协商不成的用户在此完全同意将纠纷或争议提交光环game所在地法院管辖
</p>
<p>
<b></b>
<b>、关于获取手机设备信息的说明</b>
</p>
<p>
1为方便区分每个用户的个人信息等本软件需获取用户的手机设备信息用于用户登录、视频评论互动交流等用户相关的行为
</p>
<p>
2为了保障软件与服务的安全运行我们会收集您的硬件型号、操作系统版本号、国际移动设备识别码、唯一设备标识符、网络设备硬件地址、IP
地址、WLAN接入点、蓝牙、基站、软件版本号、网络接入方式、类型、状态、网络质量数据、操作、使用、服务日志。
</p>
<p>
3为了预防恶意程序及安全运营所必需我们会收集安装的应用信息或正在运行的进程信息、应用程序的总体运行、使用情况与频率、应用崩溃情况、总体安装使用情况、性能数据、应用来源。
</p>
<p>
4我们可能使用您的账户信息、设备信息、服务日志信息以及我们关联公司、合作方在获得您授权或依法可以共享的信息用于判断账户安全、进行身份验证、检测及防范安全事件。
</p>
<p>5具体会发生获取手机设备信息场景如下说明</p>
<p>
&nbsp;&nbsp;1) 首次启动光环game&nbsp;2) 评论详情-发送评论功能&nbsp;3)
视频投稿-上传视频功能&nbsp;4) 视频详情-关注up主功能
</p>
<p><b>七、其他</b></p>
<p>
7.1
本协议所有条款的标题仅为阅读方便,本身并无实际涵义,不能作为本协议涵义解释的依据。
</p>
<p>
&nbsp;7.2
如果本协议中的任何条款无论因何种原因完全或部分无效或不具有执行力,或违反任何适用的法律,则该条款被视为删除,但本协议的其余条款仍应有效并且有约束力。
</p>
<p>
&nbsp;7.3
光环有权随时根据有关法律、法规的变化以及公司经营状况和经营策略的调整等修改本协议。修改后的协议会在软件设置内发布。
当发生有关争议时,以最新的协议文本为准。如果不同意改动的内容,用户可以自行删除本软件。如果用户继续使用本软件,则视为您接受本协议的变动。
</p>
<p>&nbsp;7.4 光环在法律允许的最大范围内对本协议拥有解释权与修改权。</p>
</div>
body {
margin: 10px;
}
.top {
margin-left: 0;
margin-right: 0;
padding: 10px 0 10px 0;
}
.title {
font-weight: 700;
}
p {
font-size: 14px;
word-break: break-all;
}
.bold {
font-weight: 700;
}
.margintop {
margin-top: 10px;
}
.left-indent {
margin-left: 20px;
}
.red-style {
color: red;
}
.bold-font {
font-weight: bold;
}
span.bold {
font-weight: bold;
}
.link-text {
color: #005ad0;
text-decoration: underline;
}
</style>
<body>
<h3 class="top">光环助手软件许可及服务协议</h3>
<h5 class="title">首部及导言</h5>
<p>欢迎使用光环助手软件许可及服务</p>
<p>
各位用户在使用光环助手前,请您务必审慎阅读、并充分理解本协议中的各项条款,
<span class="bold">
特别是免除或者限制责任的条款,以及开通或使用某项服务的单独协议,并选择接受或不接受。
</span>
除非您已阅读并接受本协议所有条款,否则您无权下载、安装或使用本软件及相关服务。您的下载、安装、使用、登录等行为即视为您已阅读并同意上述协议的约束。
</p>
<p>如果您未满18周岁请在法定监护人的陪同下阅读本协议及其他上述协议。</p>
<h5 class="title margintop">一、权利声明</h5>
<p>
“光环助手”的一切知识产权,以及与“光环助手”相关的所有信息内容,包括但不限于:文字表述及其组合、图标、图饰、图像、图表、色彩、界面设计、版面框架、有关数据、附加程序、印刷材料或电子文档等均为光环助手所有,受著作权法和国际著作权条约以及其他知识产权法律法规的保护。
</p>
<h5 class="title margintop">二、软件使用规范</h5>
<p>
2.1
本软件是基于Android安卓系统手机、平板电脑(PAD)等设备开发的一款软件,提供注册登录、手机游戏管理、游戏推荐、文章阅读等功能
</p>
<p>2.2 软件的下载、安装和使用</p>
<p>
本软件为免费软件,用户可以非商业性、无限制数量地从光环授权的渠道下载、安装及使用本软件。
</p>
<p>
<span class="bold">
如果您从未经光环授权的第三方获取本软件或与本软件名称相同的安装程序,光环无法保证该软件能够正常使用,并对因此给您造成的损失不予负责。
</span>
</p>
<p>2.3 软件的复制、分发和传播</p>
<p>
本产品以学习、研究交流为目的。用户可以非商业性、无限制数量地复制、分发和传播本软件产品。但必须保证每一份复制、分发和传播都是完整和真实的,
包括所有有关本软件产品的软件、电子文档, 版权和商标,亦包括本协议。
</p>
<p>2.4 软件的更新</p>
<p>
为了改善用户体验、完善服务内容,光环将不断努力开发新的服务,并为您不时提供软件更新(这些更新可能会采取软件替换、修改、功能强化、版本升级等形式)。为了保证本软件及服务的安全性和功能的一致性,光环有权不经向您特别通知而对软件进行更新,或者对软件的部分功能效果进行改变或限制。本软件新版本发布后,旧版本的软件可能无法使用。光环不保证旧版本软件继续可用及相应的客户服务,请您随时核对并下载最新版本。
</p>
<h5 class="title margintop">三、用户使用须知</h5>
<p>3.1 您理解并同意:</p>
<p>
为了向您提供有效的服务,本软件会利用您移动通讯终端的处理器和带宽等资源。本软件使用过程中可能产生数据流量的费用,用户需自行向运营商了解相关资费信息,并自行承担相关费用.
</p>
<p>3.2 您理解并同意:</p>
<p>
由本软件进行收录、推荐并提供下载、升级服务的第三方软件,由第三方享有一切合法权利,光环并不能识别用户利用本软件下载、安装的第三方软件是否有合法来源。
<span class="bold">
因第三方软件引发的任何纠纷,由该第三方负责解决,光环不承担任何责任。
</span>
同时光环不对第三方软件或技术提供客服支持,若用户需要获取支持,请与该软件或技术提供商联系,若您为有关软件的权利人,不愿本软件为您的软件提供用户下载、安装、使用的服务,也可按本协议约定的联系方式联系我们,我们将会积极配合进行处理。
</p>
<p>3.3 您理解并同意:</p>
<p>
<span class="bold">
如果因您不正当使用本软件造成了不良影响,或因使用本软件造成的包括但不限于数据异常等问题,均由使用者自行承担,光环团队不对任意类型的使用结果承担责任;
</span>
</p>
<p>3.4 您理解并同意:</p>
<p>
本软件不含任何破坏用户移动通讯设备数据和获取用户隐私信息的恶意代码,不会泄露用户的个人信息和隐私;
</p>
<p>3.5 您理解并同意:</p>
<p>
<span class="bold">
对于包括但不限于互联网网络故障、计算机故障、手机故障或病毒、信息损坏或丢失、计算机系统问题,或其它任何基于不可抗力原因而产生的损失,光环团队不承担任何责任。
</span>
</p>
<p>3.6 您理解并同意:</p>
<p>光环发布、收录的文章均不代表光环立场。</p>
<p>3.7 您理解并同意:</p>
<p>
为实现软件包括但不限于集中展示、下载、安装、卸载等游戏管理功能以及文章优先推荐功能,本软件会检测用户手机中已安装游戏的包名、版本号、版本名、游戏名称信息。除征得用户明确同意和法律明确规定外,光环不会向第三方泄露任何的用户信息
</p>
<p>3.8 您理解并同意:</p>
<p>
用户应在遵守法律及本协议的前提下使用本软件。用户无权实施包括但不限于下列行为:
</p>
3.8.1 不得删除或者改变本软件上的所有权利管理电子信息
<br />
3.8.2 不得故意避开或者破坏著作权人为保护本软件著作权而采取的技术措施;
<br />
3.8.3 用户不得利用本软件误导、欺骗他人;
<br />
3.8.4
违反国家规定,对计算机信息系统功能进行删除、修改、增加、干扰,造成计算机信息系统不能正常运行;
<br />
3.8.5 未经允许,进入计算机信息网络或者使用计算机信息网络资源;
<br />
3.8.6 未经允许,对计算机信息网络功能进行删除、修改或者增加;
<br />
3.8.7
未经允许,对计算机信息网络中存储、处理或者传输的数据和应用程序进行删除、修改或者增加;
<br />
3.8.8 破坏本软件系统或网站的正常运行,故意传播计算机病毒等破坏性程序;
<br />
3.8.9 其他任何危害计算机信息网络安全的行为。
<br />
<p>3.9 您理解并同意:</p>
<p>
本软件经过详细的测试,但不能保证与所有的软硬件系统完全兼容,不能保证本软件完全没有错误。如果出现不兼容及软件错误的情况,用户可通过各反馈途径将情况告知光环团队,获得技术支持。如果无法解决兼容性问题,用户可以删除本软件。
</p>
<h5 class="title margintop">四、争议解决处理</h5>
<p>
本《协议》的解释、效力及纠纷的解决,适用于中华人民共和国法律。若用户和光环助手之间发生任何纠纷或争议,首先应友好协商解决,协商不成的,用户在此完全同意将纠纷或争议提交光环助手所在地法院管辖
</p>
<p class="title margintop"><b>五、第三方SDK接入说明</b></p>
<p>
为保障光环助手App相关功能的实现与应用安全稳定的运行我们会接入由第三方提供的软件开发包SDK实现相关功能。
<br />
我们会对合作方获取有关信息的软件工具开发包SDK进行严格的安全检测并与授权合作伙伴约定严格的数据保护措施令其按照我们的委托目的、服务说明、本隐私权政策以及其他任何相关的保密和安全措施来处理个人信息。
<br />
<span class="red-style">
下方为整个光环助手
<span class="bold">所有版本</span>
内接入的所有信息收集类第三方SDK的权限说明因隐私政策会因光环助手版本迭代而新接入SDK或停止合作部分SDK方便照顾
<span class="bold">所有版本</span>
的用户查看自己SDK第三方权限说明。
<br />
我们对涉及用户信息使用的SDK相关情况进行了逐项列举具体如下
</span>
</p>
<p class="margintop red-style bold-font"><b>1数据统计类</b></p>
<p>1.头条推广</p>
<p>
SDK官网
<span class="link-text">
https://ad.oceanengine.com/openapi/index.html
</span>
</p>
<p>SDK包名com.bytedance</p>
<p>企业主体:北京有竹居网络技术有限公司</p>
<p>使用目的:用于广告流量统计相关服务</p>
<p>
收集信息类型设备品牌、型号、软件系统相关信息、安卓oaid、无线网SSID名称、WiFi路由器MAC地址、设备MAC地址、IMEI、地理位置
</p>
<p>
隐私政策链接:
<span class="link-text">
https://ad.oceanengine.com/openapi/register/protocol.html?rid=vo25p8sfqde
</span>
</p>
<p>2.talkingdata统计</p>
<p>
SDK官网
<span class="link-text">http://www.talkingdata.com/</span>
</p>
<p>SDK包名com.tendcloud</p>
<p>企业主体:北京腾云天下科技有限公司</p>
<p>使用目的:用于统计数据和效果分析,以便为用户提供更好的服务</p>
<p>收集信息类型:设备信息、网络信息、位置信息、应用信息</p>
<p>
隐私政策链接:
<span class="link-text">
http://www.talkingdata.com/privacy.jsp?languagetype=zh_cn
</span>
</p>
<p>3.腾讯MTA</p>
<p>
SDK官网
<span class="link-text">https://mta.qq.com/mta/</span>
</p>
<p>SDK包名com.tencent</p>
<p>企业主体:深圳市腾讯计算机系统有限公司</p>
<p>使用目的:用于统计数据和效果分析</p>
<p>
收集信息类型Mac地址、唯一设备识别码IMEI、android
ID、IDFA、OPENUDID、GUID/SIM卡IMSI信息、地理位置信息
</p>
<p>
隐私政策链接:
<span class="link-text">
https://mta.qq.com/mta/ctr_index/protocol_v2/
</span>
</p>
<p>4.腾讯广点通</p>
<p>
SDK官网
<span class="link-text">https://developers.e.qq.com/</span>
</p>
<p>SDK包名com.tencent</p>
<p>企业主体:深圳市腾讯计算机系统有限公司</p>
<p>使用目的:用于广告流量统计相关服务</p>
<p>
收集信息类型:
个人常用设备信息IMEI、AndroidID、位置信息IP地址、软件版本号
</p>
<p>
隐私政策链接:
<span class="link-text">https://e.qq.com/optout.html</span>
</p>
<p class="margintop red-style bold-font"><b>2社交登录类</b></p>
<p>5.微信登录分享</p>
<p>
SDK官网
<span class="link-text">https://open.weixin.qq.com/</span>
</p>
<p>SDK包名com.tencent.mm.opensdk</p>
<p>企业主体:深圳市腾讯计算机系统有限公司</p>
<p>使用目的:用于支持微信登录、分享</p>
<p>
收集信息类型个人常用设备信息MAC地址、IMEI、AndroidID、硬件型号、操作系统类型、软件信息软件版本号、浏览器类型、IP地址、服务日志信息、通讯日志信息
</p>
<p>
隐私政策链接:
<span class="link-text">https://privacy.tencent.com/</span>
</p>
<p>6.QQ登录分享</p>
<p>
SDK官网
<span class="link-text">https://connect.qq.com/</span>
</p>
<p>SDK包名com.tentcent</p>
<p>企业主体:深圳市腾讯计算机系统有限公司</p>
<p>使用目的用于支持QQ登录、分享</p>
<p>
收集信息类型个人常用设备信息MAC地址、IMEI、AndroidID、IMSI、ICCID、序列号、设备型号、操作系统版本、软件信息软件版本号、浏览器类型、网络信息、IP地址、服务日志信息、通讯日志信息 
</p>
<p>
隐私政策链接:
<span class="link-text">
https://wiki.connect.qq.com/qq互联sdk隐私保护声明
</span>
</p>
<p>7.微博登录分享</p>
<p>
SDK官网
<span class="link-text">http://open.weibo.com/authentication</span>
</p>
<p>SDK包名com.sina.weibo.sdk</p>
<p>企业主体:北京微梦创科网络技术有限公司</p>
<p>使用目的:用于支持微博登录、分享</p>
<p>
收集信息类型个人常用设备信息MAC地址、IMEI、AndroidID、IMSI、ICCID、序列号、网络信息、应用列表硬件型号、操作系统类型、软件信息软件版本号、浏览器类型、IP地址、服务日志信息、通讯日志信息
</p>
<p>
隐私政策链接:
<span class="link-text">https://open.weibo.com/wiki/开发者协议</span>
</p>
<p>8.头条抖音登录</p>
<p>
SDK官网
<span class="link-text">https://open.douyin.com/platform</span>
</p>
<p>SDK包名com.bytedance.sdk</p>
<p>企业主体:北京字节跳动科技有限公司</p>
<p>使用目的:用于支持抖音登录</p>
<p>
收集信息类型个人常用设备信息MAC地址、IMEI、AndroidID、硬件型号、操作系统类型、软件信息软件版本号、浏览器类型、IP地址、服务日志信息、通讯日志信息
</p>
<p>
隐私政策链接:
<span class="link-text">
https://www.douyin.com/agreements/?id=6773901168964798477
</span>
</p>
<p class="margintop red-style bold-font"><b>3推送通知类</b></p>
<p>9.友盟推送</p>
<p>
SDK官网
<span class="link-text">https://www.umeng.com/push</span>
</p>
<p>SDK包名com.umeng</p>
<p>企业主体:北京友盟网络科技有限公司</p>
<p>使用目的:用于游戏相关信息的提醒通知</p>
<p>
收集信息类型Mac地址、唯一设备识别码IMEI、android
ID、IDFA、OPENUDID、GUID/SIM卡IMSI信息、地理位置信息
</p>
<p>
隐私政策链接:
<span class="link-text">
https://www.umeng.com/page/policy?spm=a213m0.14063960.0.0.7f626e72hx3nnv
</span>
</p>
<p class="margintop red-style bold-font"><b>4其他功能类</b></p>
<p>10.阿里云反爬虫</p>
<p>
SDK官网
<span class="link-text">https://www.aliyun.com/product/antibot</span>
</p>
<p>SDK包名com.alibaba.wireless</p>
<p>企业主体:阿里巴巴网络技术有限公司</p>
<p>使用目的为APP提供网络应用安全防护</p>
<p>
收集信息类型设备相关信息例如设备型号、操作系统版本、设备设置、唯一设备标识符等软硬件特征信息、设备所在位置相关信息例如IP地址、GPS位置以及能够提供相关信息的Wi-Fi接入点、蓝牙和基站等传感器信息
</p>
<p>
隐私政策链接:
<span class="link-text">
http://terms.aliyun.com/legal-agreement/terms/suit_bu1_ali_cloud/suit_bu1_ali_cloud201902141711_54837.html?spm=a2c4g.11186623.J_9220772140.81.b7574832gmk0vr
</span>
</p>
<p>11.腾讯bugly</p>
<p>
SDK官网
<span class="link-text">https://bugly.qq.com/v2/</span>
</p>
<p>SDK包名com.tencent.bugly</p>
<p>企业主体:深圳市腾讯计算机系统有限公司</p>
<p>使用目的APP异常上报</p>
<p>
收集信息类型:设备及应用信息。如:设备名称、设备识别符、硬件型号、操作系统版本、应用程序版本
</p>
<p>
隐私政策链接:
<span class="link-text">https://bugly.qq.com/v2/contract</span>
</p>
<p>12.阿里云文件上传</p>
<p>
SDK官网
<span class="link-text">https://www.alibabacloud.com/zh</span>
</p>
<p>SDK包名com.alibaba.sdk.android</p>
<p>SDK包名com.alibaba.sdk.android</p>
<p>企业主体:阿里巴巴网络技术有限公司</p>
<p>使用目的:用于支持用户上传视频等相关内容</p>
<p>
收集信息类型设备相关信息例如设备型号、操作系统版本、设备设置、唯一设备标识符等软硬件特征信息、设备所在位置相关信息例如IP地址、GPS位置以及能够提供相关信息的Wi-Fi接入点、蓝牙和基站等传感器信息
</p>
<p>
隐私政策链接:
<span class="link-text">
http://terms.aliyun.com/legal-agreement/terms/suit_bu1_ali_cloud/suit_bu1_ali_cloud201902141711_54837.html?spm=a2c4g.11186623.J_9220772140.81.b7574832gmk0vr
</span>
</p>
<p>13.阿里云日志上传</p>
<p>
SDK官网
<span class="link-text">https://www.alibabacloud.com/zh</span>
</p>
<p>SDK包名com.aliyun.sls.android.sdk</p>
<p>企业主体:阿里巴巴网络技术有限公司</p>
<p>
使用目的:通过网络日志分析这些信息以便更及时响应您的帮助请求,以及用于改进服务
</p>
<p>
收集信息类型设备相关信息例如设备型号、操作系统版本、设备设置、唯一设备标识符等软硬件特征信息、设备所在位置相关信息例如IP地址、GPS位置以及能够提供相关信息的Wi-Fi接入点、蓝牙和基站等传感器信息
</p>
<p>
隐私政策链接:
<span class="link-text">
http://terms.aliyun.com/legal-agreement/terms/suit_bu1_ali_cloud/suit_bu1_ali_cloud201902141711_54837.html?spm=a2c4g.11186623.J_9220772140.81.b7574832gmk0vr
</span>
</p>
<p>14.容联七陌</p>
<p>
SDK官网
<span class="link-text">https://www.7moor.com/developer</span>
</p>
<p>SDK包名com.m7.imkfsdk</p>
<p>企业主体:北京七陌科技有限公司</p>
<p>使用目的:用于提供对应在线客服功能</p>
<p>
收集信息类型:设备相关信息(设备名称、设备型号、硬件序列号、操作系统和应用程序版本及类型、语言设置、分辨率、移动终端随机存储内存、摄像头/相册、通讯录权限等)
</p>
<p>
隐私政策链接:
<span class="link-text">http://m.7moor.com/72/57/p5077783560e807/</span>
</p>
<h5 class="title margintop">六、关于获取手机设备信息的说明</h5>
<div>
1为方便区分每个用户的个人信息等本软件需获取用户的手机设备信息用于游戏主动预约、论坛互动交流后进行推送等用户相关的行为
<br />
2为了保障软件与服务的安全运行我们会收集您的硬件型号、操作系统版本号、国际移动设备识别码、唯一设备标识符、网络设备硬件地址、IP
地址、WLAN接入点、蓝牙、基站、软件版本号、网络接入方式、类型、状态、网络质量数据、操作、使用、服务日志。
<br />
3为了预防恶意程序及安全运营所必需我们会收集安装的应用信息或正在运行的进程信息、应用程序的总体运行、使用情况与频率、应用崩溃情况、总体安装使用情况、性能数据、应用来源。
<br />
4我们可能使用您的账户信息、设备信息、服务日志信息以及我们关联公司、合作方在获得您授权或依法可以共享的信息用于判断账户安全、进行身份验证、检测及防范安全事件。
<br />
5具体会发生获取手机设备信息场景如下说明
<br />
<p class="left-indent">
1) 首次启动光环助手
<br />
2) 游戏列表/游戏详情/资讯文章详情/搜索结果页-预约功能
<br />
3) 礼包中心/礼包详情-领取功能
<br />
4) 评论详情-发送评论功能
<br />
5) 回答/问题详情-我来回答功能
<br />
6) 问答首页-提问功能
<br />
7) 个人主页-发文章功能
<br />
8) 帖子草稿/我的草稿-编辑功能
<br />
9) 游戏投稿功能
<br />
10) 视频投稿-上传视频功能
<br />
11) 游戏详情-关注游戏功能
</p>
</div>
<h5 class="title margintop">七、其他</h5>
<p>
7.1
本协议所有条款的标题仅为阅读方便,本身并无实际涵义,不能作为本协议涵义解释的依据。
<br />
7.2
如果本协议中的任何条款无论因何种原因完全或部分无效或不具有执行力,或违反任何适用的法律,则该条款被视为删除,但本协议的其余条款仍应有效并且有约束力。
<br />
7.3
光环有权随时根据有关法律、法规的变化以及公司经营状况和经营策略的调整等修改本协议。修改后的协议会在软件设置内发布。
当发生有关争议时,以最新的协议文本为准。如果不同意改动的内容,用户可以自行删除本软件。如果用户继续使用本软件,则视为您接受本协议的变动。
<br />
<span class="bold">
7.4 光环在法律允许的最大范围内对本协议拥有解释权与修改权。
</span>
</p>
</body>
</html>
</body></html>

View File

@ -5,7 +5,6 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.util.Log;
@ -26,9 +25,6 @@ import java.lang.Thread.UncaughtExceptionHandler;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.TimeoutException;
import io.sentry.Sentry;
public class AppUncaughtHandler implements UncaughtExceptionHandler {
@ -40,26 +36,20 @@ public class AppUncaughtHandler implements UncaughtExceptionHandler {
}
@Override
public void uncaughtException(Thread t, Throwable e) {
if (("FinalizerWatchdogDaemon").equals(t.getName())
&& e instanceof TimeoutException) {
// ignore timeoutException
// detail can be found in this didi tech blog post https://mp.weixin.qq.com/s?__biz=MzU1ODEzNjI2NA==&mid=2247487185&idx=2&sn=cf2d9e10053f625bde0f61d246f14870&source=41#wechat_redirect
} else {
new Thread(() -> {
public void uncaughtException(Thread thread, Throwable ex) {
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Utils.toast(mContext.getApplicationContext(), "\"光环助手\"发生错误");
Looper.loop();
});
saveLocalLog(mContext, e);
restart(mContext);
Sentry.captureException(e);
}
}
});
saveLocalLog(mContext, ex);
restart(mContext);
}
public static void restart(final Context context) {
// S450 这机器会无限重启循环 : (
if ("S450".equals(Build.MODEL)) return;
// 防止重复奔溃导致助手一直重启20秒内不做处理
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);

View File

@ -1,21 +1,16 @@
package com.gh.base;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Parcel;
import android.os.TransactionTooLargeException;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
@ -30,31 +25,21 @@ import androidx.lifecycle.Lifecycle;
import com.gh.base.fragment.BaseFragment;
import com.gh.common.constant.Constants;
import com.gh.common.tracker.IBusiness;
import com.gh.common.util.DialogHelper;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.common.util.ExtensionsKt;
import com.gh.common.util.MtaHelper;
import com.gh.common.util.NetworkUtils;
import com.gh.common.util.PackageInstaller;
import com.gh.common.util.QuickLoginHelper;
import com.gh.common.util.RunningUtils;
import com.gh.common.util.SPUtils;
import com.gh.common.util.ShareUtils;
import com.gh.common.util.StringUtils;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.LoginActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.SplashScreenActivity;
import com.gh.gamecenter.energy.EnergyCenterActivity;
import com.gh.gamecenter.eventbus.EBShowDialog;
import com.lightgame.BaseAppCompatActivity;
import com.lightgame.download.DownloadEntity;
import com.lightgame.download.FileUtils;
import com.lightgame.utils.Util_System_Keyboard;
import com.lightgame.utils.Utils;
import com.tencent.tauth.Tencent;
@ -67,7 +52,6 @@ import java.lang.ref.WeakReference;
import java.util.List;
import butterknife.ButterKnife;
import kotlin.Pair;
import pub.devrel.easypermissions.EasyPermissions;
import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
@ -78,24 +62,17 @@ import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
* 需要工具栏的页面请继承{@link ToolBarActivity}
*/
public abstract class BaseActivity extends BaseAppCompatActivity implements EasyPermissions.PermissionCallbacks, IBusiness {
public abstract class BaseActivity extends BaseAppCompatActivity implements EasyPermissions.PermissionCallbacks {
// global dialog key
public final static String DOWNLOAD_HIJACK = "hijack";
public final static String LOGIN_EXCEPTION = "loginException";
public final static String PLUGGABLE = "plugin";
public final static String SIGNATURE_CONFLICT = "signature_conflict";
public final static int ID_ROOT_INDICATOR = 999;
public final int MAX_BUNDLE_SIZE = 300;
@NonNull
protected String mEntrance;
private boolean mIsExistLogoutDialog;
private boolean mHasAddTaskFloat = false;
private View mTaskBackView;
private WindowManager mWM;
private WindowManager.LayoutParams mWmParams;
protected final Handler mBaseHandler = new BaseHandler(this);
@ -135,7 +112,6 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (useEventBus()) EventBus.getDefault().register(this);
if (useButterKnife()) ButterKnife.bind(this);
mEntrance = getIntent().getStringExtra(KEY_ENTRANCE);
@ -146,29 +122,6 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
if (BuildConfig.DEBUG) {
Utils.log("ACTIVITY_ENTRANCE -> " + mEntrance);
}
if (savedInstanceState != null) {
String xapkUnzipActivity = SPUtils.getString(Constants.SP_XAPK_UNZIP_ACTIVITY);
String xapkUrl = SPUtils.getString(Constants.SP_XAPK_URL);
Utils.log("页面重建了--" + xapkUnzipActivity + "--" + xapkUrl);
if (this.getClass().getName().equals(SplashScreenActivity.class.getName())) {
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "");
SPUtils.setString(Constants.SP_XAPK_URL, "");
return;
}
if (this.getClass().getName().equals(xapkUnzipActivity) && !TextUtils.isEmpty(xapkUrl)) {
DownloadEntity downloadEntity = DownloadManager.getInstance(this).getDownloadEntityByUrl(xapkUrl);
if (downloadEntity != null) {
PackageInstaller.install(this, downloadEntity, false);
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "");
SPUtils.setString(Constants.SP_XAPK_URL, "");
}
}
}
if (this.getClass().getName().equals(EnergyCenterActivity.class.getName())) {
SPUtils.setBoolean(Constants.SP_SHOW_TASK_FLOAT, false);
}
}
@SuppressWarnings("ConstantConditions")
@ -232,7 +185,6 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13);
tv.measure(0, 0);
tv.setAlpha(0.15F);
tv.setId(ID_ROOT_INDICATOR);
int height = tv.getMeasuredHeight();
int width = tv.getMeasuredWidth();
tv.setPadding(DisplayUtils.dip2px(20), 0, DisplayUtils.dip2px(20), 0);
@ -264,19 +216,13 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
if (DOWNLOAD_HIJACK.equals(showDialog.getType())) {
DialogUtils.showQqSessionDialog(this);// 建议用户联系客服
} else if (PLUGGABLE.equals(showDialog.getType())) {
DialogHelper.showPluginDialog(this, () -> {
DialogUtils.showPluginDialog(this, () -> {
if (FileUtils.isEmptyFile(showDialog.getPath())) {
toast(R.string.install_failure_hint);
} else {
PackageInstaller.uninstall(BaseActivity.this, showDialog.getPath());
}
return null;
});
} else if (SIGNATURE_CONFLICT.equals(showDialog.getType())) {
DialogHelper.showSignatureConflictDialog(this, () -> {
PackageInstaller.uninstall(BaseActivity.this, showDialog.getPath());
return null;
});
} else if (LOGIN_EXCEPTION.equals(showDialog.getType())) {
if (mIsExistLogoutDialog) return;
mIsExistLogoutDialog = true;
@ -288,14 +234,8 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
, StringUtils.buildString("", model, "")
, "知道了", "重新登录"
, null
, () -> {
if (SPUtils.getBoolean(Constants.SP_HAS_GET_PHONE_INFO) || NetworkUtils.isOpenMobileData(BaseActivity.this)) {
QuickLoginHelper.startLogin(BaseActivity.this, "你的账号已在另外一台设备登录多设备-重新登录");
} else {
startActivity(LoginActivity.getIntent(BaseActivity.this,
"你的账号已在另外一台设备登录多设备-重新登录"));
}
}
, () -> startActivity(LoginActivity.getIntent(BaseActivity.this,
"你的账号已在另外一台设备登录多设备-重新登录"))
);
mBaseHandler.postDelayed(() -> mIsExistLogoutDialog = false, 5000);
} catch (Exception e) {
@ -308,11 +248,6 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
@Override
protected void onPause() {
super.onPause();
if (mWM != null && mTaskBackView != null && mHasAddTaskFloat) {
mWM.removeView(mTaskBackView);
mHasAddTaskFloat = false;
}
if (isFinishing()) {
onFinish();
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
@ -326,87 +261,8 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
@Override
protected void onResume() {
super.onResume();
if (SPUtils.getBoolean(Constants.SP_SHOW_TASK_FLOAT) && !this.getClass().getName().equals(EnergyCenterActivity.class.getName())) {
addTaskBackView();
mHasAddTaskFloat = true;
}
}
private void addTaskBackView() {
mWM = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
mWmParams = new WindowManager.LayoutParams();
mWmParams.type = WindowManager.LayoutParams.TYPE_APPLICATION;
mWmParams.format = PixelFormat.RGBA_8888;
mWmParams.gravity = Gravity.LEFT | Gravity.BOTTOM;
mWmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mWmParams.width = DisplayUtils.dip2px(76F);
mWmParams.height = DisplayUtils.dip2px(36F);
mWmParams.y = SPUtils.getInt(Constants.SP_TASK_FLOAT_LAST_Y, DisplayUtils.dip2px(114F));
mTaskBackView = View.inflate(this, R.layout.layout_task_back, null);
mTaskBackView.setOnClickListener(v -> {
// 如果当前是在键盘输入时,点击"返回任务"要先收起键盘
Util_System_Keyboard.hideSoftKeyboard(this);
startActivity(EnergyCenterActivity.Companion.getIntent(this));
SPUtils.setBoolean(Constants.SP_SHOW_TASK_FLOAT, false);
mWM.removeView(mTaskBackView);
mHasAddTaskFloat = false;
});
setFloatTouchListener();
mWM.addView(mTaskBackView, mWmParams);
}
private void setFloatTouchListener() {
int screenHeight = getResources().getDisplayMetrics().heightPixels;
mTaskBackView.setOnTouchListener(new View.OnTouchListener() {
private int intervalY;
private int startY;
@Override
public boolean onTouch(View v, MotionEvent event) {
final int y = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
intervalY = y;
startY = y;
break;
case MotionEvent.ACTION_MOVE:
mWmParams.y -= (y - intervalY);
if (mWmParams.y < 0) {
mWmParams.y = 0;
}
if (mWmParams.y > screenHeight) {
mWmParams.y = screenHeight;
}
if (mWM != null && mTaskBackView != null && mHasAddTaskFloat) {
mWM.updateViewLayout(mTaskBackView, mWmParams);
}
intervalY = y;
return true;
case MotionEvent.ACTION_UP:
// 滑动距离少于10视为点击返回false否则视为拖动返回true
if (Math.abs(y - startY) <= 10) {
return false;
} else {
// 记录位置
SPUtils.setInt(Constants.SP_TASK_FLOAT_LAST_Y, mWmParams.y);
return true;
}
}
return false;
}
});
}
/**
* 此回调可用于确认当前 activity 已经执行了 finish() 方法并处于 isFinishing 状态
*/
@ -482,54 +338,4 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
}
return resources;
}
/**
* ActivityThread每次调用onSaveInstanceState时outState大小都会累加最终会导致{@link TransactionTooLargeException}异常
* 解决方案判断每次获取到的outState大小当达到300k时手动clear掉
*/
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
if (preventRecreateFragmentByFragmentManager()) {
outState = discardFragmentFromSaveInstanceState(outState);
}
long bundleSize = getBundleSize(outState);
if (bundleSize > MAX_BUNDLE_SIZE * 1024) {
outState.clear();
}
}
/**
* 是否停用 Activity 重建时 FragmentManager 根据 saveState 自动重建保存的 Fragment 的功能
*/
protected boolean preventRecreateFragmentByFragmentManager() {
return false;
}
private Bundle discardFragmentFromSaveInstanceState(Bundle outState) {
if (outState != null) {
outState.remove("android:support:fragments");
}
return outState;
}
private long getBundleSize(Bundle bundle) {
long dataSize;
Parcel obtain = Parcel.obtain();
try {
obtain.writeBundle(bundle);
dataSize = obtain.dataSize();
} finally {
obtain.recycle();
}
return dataSize;
}
@Override
public Pair<String, String> getBusinessId() {
return null;
}
}

View File

@ -9,18 +9,15 @@ import android.os.Bundle
import android.text.TextUtils
import android.view.View
import android.webkit.JavascriptInterface
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import androidx.core.content.ContextCompat
import butterknife.OnClick
import com.gh.common.AppExecutor
import com.gh.common.util.*
import com.gh.common.util.DialogUtils
import com.gh.common.util.MtaHelper
import com.gh.common.view.RichEditor
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.entity.MyVideoEntity
import com.gh.gamecenter.qa.article.edit.ArticleEditActivity
import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity
import com.gh.gamecenter.qa.editor.GameActivity
import com.gh.gamecenter.qa.editor.InsertAnswerWrapperActivity
import com.gh.gamecenter.qa.editor.InsertArticleWrapperActivity
@ -29,7 +26,6 @@ import com.gh.gamecenter.qa.entity.AnswerEntity
import com.gh.gamecenter.qa.entity.ArticleEntity
import com.gh.gamecenter.qa.entity.EditorInsertEntity
import com.halo.assistant.HaloApp
import com.lightgame.utils.Util_System_Keyboard
import com.lightgame.utils.Utils
import com.lightgame.view.CheckableImageView
import kotterknife.bindView
@ -37,15 +33,15 @@ import kotterknife.bindView
abstract class BaseRichEditorActivity : ToolBarActivity() {
val mRichEditor by bindView<RichEditor>(R.id.rich_editor)
val mDraftBtn by bindView<TextView>(R.id.draft_btn)
private val mEditorTextNumTv by bindView<TextView>(R.id.editorTextNumTv)
private val mEditorFont by bindView<CheckableImageView>(R.id.editor_font)
private val mEditorLink by bindView<CheckableImageView>(R.id.editor_link)
private val mEditorParagraph by bindView<CheckableImageView>(R.id.editor_paragraph)
private val mEditorFontBold by bindView<CheckableImageView>(R.id.editor_font_bold)
private val mEditorFontItalic by bindView<CheckableImageView>(R.id.editor_font_italic)
private val mEditorFontStrikeThrough by bindView<CheckableImageView>(R.id.editor_font_strikethrough)
private val mEditorFontUnderline by bindView<CheckableImageView>(R.id.editor_font_underline)
private val mEditorParagraphH1 by bindView<CheckableImageView>(R.id.editor_paragraph_h1)
private val mEditorParagraphH2 by bindView<CheckableImageView>(R.id.editor_paragraph_h2)
private val mEditorParagraphH3 by bindView<CheckableImageView>(R.id.editor_paragraph_h3)
@ -54,15 +50,9 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
private val mEditorFontContainer by bindView<View>(R.id.editor_font_container)
private val mEditorParagraphContainer by bindView<View>(R.id.editor_paragraph_container)
private val mEditorLinkContainer by bindView<View>(R.id.editor_link_container)
private val mEditorInsertDetailContainer by bindView<View>(R.id.editor_insert_detail_container)
val mAddLabelContainer by bindView<View>(R.id.add_label_container)
val mAddLabelTv by bindView<TextView>(R.id.add_label_tv)
val mLabelNumTv by bindView<TextView>(R.id.label_num_tv)
val mLabelArrowIv by bindView<ImageView>(R.id.label_arrow)
val mTagsContainer by bindView<FrameLayout>(R.id.tagsContainer)
private val mEditorInsertDetail by bindView<View>(R.id.editor_insert_detail)
private var mCurrentParagraphStyle = ""
private var mIsExtendedKeyboardShow = false
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
@ -73,47 +63,29 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
when (requestCode) {
INSERT_ANSWER_CODE -> {
val answer = data?.getParcelableExtra<AnswerEntity>(AnswerEntity::class.java.simpleName)
if (answer != null) {
mRichEditor.focusEditor()
insertData = EditorInsertEntity.transform(answer)
mRichEditor.insertCustomStyleLink(insertData)
}
if (answer != null) insertData = EditorInsertEntity.transform(answer)
}
INSERT_ARTICLE_CODE -> {
val article = data?.getParcelableExtra<ArticleEntity>(ArticleEntity::class.java.simpleName)
if (article != null) {
mRichEditor.focusEditor()
insertData = EditorInsertEntity.transform(article)
mRichEditor.insertCustomStyleLink(insertData)
}
if (article != null) insertData = EditorInsertEntity.transform(article)
}
INSERT_GAME_CODE -> {
val game = data?.getParcelableExtra<GameEntity>(GameEntity::class.java.simpleName)
if (game != null) {
mRichEditor.focusEditor()
insertData = EditorInsertEntity.transform(game)
mRichEditor.insertCustomStyleLink(insertData)
}
if (game != null) insertData = EditorInsertEntity.transform(game)
}
VideoActivity.INSERT_VIDEO_CODE -> {
val video = data?.getParcelableExtra<MyVideoEntity>(MyVideoEntity::class.java.simpleName)
if (video != null) {
mRichEditor.focusEditor()
mRichEditor.insertCustomVideo(video)
}
if (video != null) mRichEditor.insertCustomVideo(video)
return
}
}
closeExtendedKeyboard()
AppExecutor.uiExecutor.executeWithDelay(Runnable {
Util_System_Keyboard.showSoftKeyboard(this)
}, 100)
mRichEditor.insertCustomStyleLink(insertData)
}
@SuppressLint("AddJavascriptInterface", "ClickableViewAccessibility")
@SuppressLint("AddJavascriptInterface")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mAddLabelContainer.visibility = if (this is ArticleEditActivity) View.VISIBLE else View.GONE
mRichEditor.setPadding(20, 15, 20, 15)
// 防止个别手机在Js里无法获取粘贴内容
mRichEditor.addJavascriptInterface(OnPasteListener(), "onPasteListener")
@ -121,59 +93,12 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
mRichEditor.addJavascriptInterface(OnEditorTextChangeListener(), "OnEditorTextChangeListener")
mRichEditor.setInputEnabled(true)
mRichEditor.setOnTouchListener { _, _ ->
if (mIsExtendedKeyboardShow) {
closeExtendedKeyboard()
Util_System_Keyboard.showSoftKeyboard(this)
//是否消费事件根据mRichEditor是否含有焦点决定mRichEditor没有焦点则不消费事件
mRichEditor.hasFocus()
} else false
}
mDraftBtn.text = if (this is AnswerEditActivity) {
"回答草稿"
} else "帖子草稿"
}
fun closeExtendedKeyboard() {
mEditorInsertDetailContainer.visibility = View.GONE
mEditorFont.isChecked = false
mEditorLink.isChecked = false
mAddLabelContainer.isSelected = false
mIsExtendedKeyboardShow = false
}
protected fun controlEditorInsertContainerEnabled(isEnabled: Boolean) {
mEditorFont.isEnabled = isEnabled
}
fun changeAddLabel(isLabelContainerShow: Boolean) {
if (isLabelContainerShow) {
mLabelNumTv.visibility = View.GONE
mLabelArrowIv.visibility = View.VISIBLE
mAddLabelTv.setTextColor(ContextCompat.getColor(this, R.color.theme_font))
mAddLabelTv.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
mAddLabelContainer.background = ContextCompat.getDrawable(this, R.drawable.bg_editor_insert_add_label)
} else {
val selectedLabel = getSelectedLabel()
if (selectedLabel == 0) {
mAddLabelTv.text = "添加标签"
mLabelNumTv.visibility = View.GONE
mAddLabelTv.setTextColor(ContextCompat.getColor(this, R.color.text_666666))
mAddLabelTv.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(this, R.drawable.ic_add_label), null, null, null)
} else {
mAddLabelTv.text = "标签"
mLabelNumTv.visibility = View.VISIBLE
mLabelNumTv.text = selectedLabel.toString()
mAddLabelTv.setTextColor(ContextCompat.getColor(this, R.color.theme_font))
mAddLabelTv.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
}
mLabelArrowIv.visibility = View.GONE
mAddLabelContainer.background = ContextCompat.getDrawable(this, R.drawable.border_round_stroke_eee_999)
}
}
open fun getSelectedLabel(): Int = 0
@OnClick(R.id.editor_image, R.id.editor_font, R.id.editor_link, R.id.add_label_container, R.id.editor_font_underline,
@OnClick(R.id.editor_image, R.id.editor_font, R.id.editor_link, R.id.editor_paragraph,
R.id.editor_font_bold, R.id.editor_font_italic, R.id.editor_font_strikethrough,
R.id.editor_paragraph_h1, R.id.editor_paragraph_h2, R.id.editor_paragraph_h3,
R.id.editor_paragraph_h4, R.id.editor_font_container, R.id.editor_paragraph_container,
@ -182,13 +107,31 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
fun onRichClick(view: View) {
when (view.id) {
R.id.editor_font -> {
controlEditorFontContainer()
mEditorFont.isChecked = !mEditorFont.isChecked
mEditorParagraph.isChecked = false
mEditorLink.isChecked = false
mEditorFontContainer.visibility = if (mEditorFont.isChecked) View.VISIBLE else View.GONE
mEditorParagraphContainer.visibility = if (!mEditorFont.isChecked) View.VISIBLE else View.GONE
mEditorLinkContainer.visibility = if (!mEditorFont.isChecked) View.VISIBLE else View.GONE
mEditorInsertDetail.visibility = mEditorFontContainer.visibility
}
R.id.editor_paragraph -> {
mEditorParagraph.isChecked = !mEditorParagraph.isChecked
mEditorFont.isChecked = false
mEditorLink.isChecked = false
mEditorParagraphContainer.visibility = if (mEditorParagraph.isChecked) View.VISIBLE else View.GONE
mEditorFontContainer.visibility = if (!mEditorParagraph.isChecked) View.VISIBLE else View.GONE
mEditorLinkContainer.visibility = if (!mEditorParagraph.isChecked) View.VISIBLE else View.GONE
mEditorInsertDetail.visibility = mEditorParagraphContainer.visibility
}
R.id.editor_link -> {
controlEditorLinkContainer()
}
R.id.add_label_container -> {
controlAddLabelContainer()
mEditorLink.isChecked = !mEditorLink.isChecked
mEditorFont.isChecked = false
mEditorParagraph.isChecked = false
mEditorLinkContainer.visibility = if (mEditorLink.isChecked) View.VISIBLE else View.GONE
mEditorParagraphContainer.visibility = if (!mEditorLink.isChecked) View.VISIBLE else View.GONE
mEditorFontContainer.visibility = if (!mEditorLink.isChecked) View.VISIBLE else View.GONE
mEditorInsertDetail.visibility = mEditorLinkContainer.visibility
}
R.id.editor_font_bold -> {
mEditorFontBold.isChecked = !mEditorFontBold.isChecked
@ -212,14 +155,6 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
MtaHelper.onEvent(mtaEventName(), "文字样式", "文字样式-删除线")
}
}
R.id.editor_font_underline -> {
mEditorFontUnderline.isChecked = !mEditorFontUnderline.isChecked
mRichEditor.setUnderline()
if (mEditorFontUnderline.isChecked) {
MtaHelper.onEvent(mtaEventName(), "文字样式", "文字样式-下滑线")
}
}
R.id.editor_paragraph_h1 -> {
if (mEditorParagraphH1.isChecked) {
mRichEditor.formatBlock()
@ -278,93 +213,12 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
startActivityForResult(GameActivity.getIntent(this, GameActivity.INSERT_GAME_TITLE), INSERT_GAME_CODE)
}
R.id.editor_link_video -> {
PermissionHelper.checkStoragePermissionBeforeAction(this,
object : EmptyCallback {
override fun onCallback() {
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-视频")
startActivityForResult(VideoActivity.getIntent(this@BaseRichEditorActivity), VideoActivity.INSERT_VIDEO_CODE)
}
})
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-视频")
startActivityForResult(VideoActivity.getIntent(this), VideoActivity.INSERT_VIDEO_CODE)
}
}
}
private fun controlEditorFontContainer() {
mEditorFont.isChecked = !mEditorFont.isChecked
mEditorLink.isChecked = false
mAddLabelContainer.isSelected = false
val isShouldDelay = if (mEditorFont.isChecked) {
Util_System_Keyboard.hideSoftKeyboard(this)
true
} else {
Util_System_Keyboard.showSoftKeyboard(this)
false
}
mEditorInsertDetailContainer.postDelayed({
mEditorInsertDetailContainer.visibility = if (mEditorFont.isChecked) View.VISIBLE else View.GONE
mEditorFontContainer.visibility = if (mEditorFont.isChecked) View.VISIBLE else View.GONE
mEditorParagraphContainer.visibility = if (mEditorFont.isChecked) View.VISIBLE else View.GONE
mEditorLinkContainer.visibility = View.GONE
mTagsContainer.visibility = View.GONE
mIsExtendedKeyboardShow = mEditorFont.isChecked
changeAddLabel(false)
}, if (isShouldDelay) 200 else 0L)
}
private fun controlEditorLinkContainer() {
mEditorLink.isChecked = !mEditorLink.isChecked
mEditorFont.isChecked = false
mAddLabelContainer.isSelected = false
val isShouldDelay = if (mEditorLink.isChecked) {
Util_System_Keyboard.hideSoftKeyboard(this)
true
} else {
Util_System_Keyboard.showSoftKeyboard(this)
false
}
mEditorInsertDetailContainer.postDelayed({
mEditorInsertDetailContainer.visibility = if (mEditorLink.isChecked) View.VISIBLE else View.GONE
mEditorLinkContainer.visibility = if (mEditorLink.isChecked) View.VISIBLE else View.GONE
mEditorFontContainer.visibility = View.GONE
mEditorParagraphContainer.visibility = View.GONE
mTagsContainer.visibility = View.GONE
mIsExtendedKeyboardShow = mEditorLink.isChecked
changeAddLabel(false)
}, if (isShouldDelay) 200 else 0L)
}
fun controlAddLabelContainer() {
mEditorLink.isChecked = false
mEditorFont.isChecked = false
mAddLabelContainer.isSelected = !mAddLabelContainer.isSelected
val isShouldDelay = if (mAddLabelContainer.isSelected) {
Util_System_Keyboard.hideSoftKeyboard(this)
changeAddLabel(true)
true
} else {
Util_System_Keyboard.showSoftKeyboard(this)
changeAddLabel(false)
false
}
mEditorInsertDetailContainer.postDelayed({
mEditorInsertDetailContainer.visibility = if (mAddLabelContainer.isSelected) View.VISIBLE else View.GONE
mTagsContainer.visibility = if (mAddLabelContainer.isSelected) View.VISIBLE else View.GONE
mEditorLinkContainer.visibility = View.GONE
mEditorFontContainer.visibility = View.GONE
mEditorParagraphContainer.visibility = View.GONE
mIsExtendedKeyboardShow = mAddLabelContainer.isSelected
}, if (isShouldDelay) 200 else 0L)
}
override fun handleBackPressed(): Boolean {
if (mIsExtendedKeyboardShow) {
closeExtendedKeyboard()
return true
}
return super.handleBackPressed()
}
private inner class OnCursorChangeListener {
@JavascriptInterface
fun onElements(elements: String) {
@ -383,7 +237,6 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
mEditorFontBold.isChecked = elements.contains(ELEMENT_NAME_BOLD)
mEditorFontItalic.isChecked = elements.contains(ELEMENT_NAME_ITALIC)
mEditorFontStrikeThrough.isChecked = elements.contains(ELEMENT_NAME_STRIKE)
mEditorFontUnderline.isChecked = elements.contains(ELEMENT_NAME_UNDERLINE)
mEditorParagraphH1.isChecked = elements.contains(ELEMENT_PARAGRAPH_H1)
mEditorParagraphH2.isChecked = elements.contains(ELEMENT_PARAGRAPH_H2)
mEditorParagraphH3.isChecked = elements.contains(ELEMENT_PARAGRAPH_H3)
@ -411,9 +264,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
@JavascriptInterface
fun onTextChange(count: Int) {
val num = if (count > MAX_INPUT_TEXT_NUM) MAX_INPUT_TEXT_NUM - count else count
mEditorTextNumTv.post {
mEditorTextNumTv.text = num.toString()
}
mEditorTextNumTv.text = num.toString()
}
}
@ -423,7 +274,6 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
const val ELEMENT_NAME_BOLD = " b "
const val ELEMENT_NAME_ITALIC = " i "
const val ELEMENT_NAME_STRIKE = " strike "
const val ELEMENT_NAME_UNDERLINE = " u "
const val ELEMENT_PARAGRAPH_H1 = " h1 "
const val ELEMENT_PARAGRAPH_H2 = " h2 "
const val ELEMENT_PARAGRAPH_H3 = " h3 "

View File

@ -7,7 +7,6 @@ import android.os.Bundle;
import com.gh.common.notifier.Notifier;
import com.gh.common.util.DataUtils;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.SplashScreenActivity;
import com.halo.assistant.HaloApp;
import com.lightgame.utils.AppManager;
@ -42,9 +41,7 @@ public class GHActivityLifecycleCallbacksImpl implements ActivityLifecycleCallba
//FIXME 这里应该只是部分Activity需要
try {
// 初始化gameMap
if (!(activity instanceof SplashScreenActivity)) {
DownloadManager.getInstance(activity).initGameMap();
}
DownloadManager.getInstance(activity).initGameMap();
} catch (Exception e) {
e.printStackTrace();
}

View File

@ -1,17 +0,0 @@
package com.gh.base
import java.util.concurrent.ThreadFactory
import java.util.concurrent.atomic.AtomicInteger
class GHThreadFactory(threadNamePrefix: String) : ThreadFactory {
private val THREAD_NAME_STEM = "${threadNamePrefix}_%d"
private val mThreadId = AtomicInteger(0)
override fun newThread(r: Runnable?): Thread {
val t = Thread(r)
t.name = String.format(THREAD_NAME_STEM, mThreadId.getAndIncrement())
return t
}
}

View File

@ -9,8 +9,6 @@ import com.gh.gamecenter.R;
import com.lightgame.utils.RuntimeUtils;
import com.lightgame.utils.Utils;
import java.lang.reflect.Field;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
@ -31,7 +29,7 @@ public class BaseDialogFragment extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Dialog dialog = new Dialog(getActivity(), getThemeRes());
final Dialog dialog = new Dialog(getActivity(), R.style.DialogWindowTransparent);
dialog.setCanceledOnTouchOutside(false);
dialog.setOnKeyListener((dialog1, keyCode, event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK && !ClickUtils.isFastDoubleClick()) {
@ -43,10 +41,6 @@ public class BaseDialogFragment extends DialogFragment {
return dialog;
}
public int getThemeRes() {
return R.style.DialogWindowTransparent;
}
public void toast(@StringRes int res) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
toast(getString(res));
@ -77,22 +71,7 @@ public class BaseDialogFragment extends DialogFragment {
transaction.show(fragment);
transaction.commit();
} else {
try {
Class<?> clazz = DialogFragment.class;
Field dismissed = clazz.getDeclaredField("mDismissed");
dismissed.setAccessible(true);
dismissed.set(this, false);
Field shownByMe = clazz.getDeclaredField("mShownByMe");
shownByMe.setAccessible(true);
shownByMe.set(this, true);
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(this, tag);
transaction.commitAllowingStateLoss();
} catch (Exception e) {
super.show(manager, tag);
e.printStackTrace();
}
super.show(manager, tag);
}
}
}

View File

@ -140,8 +140,9 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
EventBus.getDefault().register(this);
// For data binding.
mCachedView = getInflatedLayout();
if (mCachedView == null) {
if (getInflatedLayout() != null) {
mCachedView = getInflatedLayout();
} else {
mCachedView = View.inflate(getContext(), getLayoutId(), null);
}
@ -206,10 +207,6 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if (container != null) {
container.removeView(mCachedView);
// TODO 页面重建 (framgent 的重新获取) 有大问题,这里只是修修补补
if (mCachedView != null && mCachedView.getParent() instanceof ViewGroup) {
((ViewGroup) mCachedView.getParent()).removeView(mCachedView);
}
}
return mCachedView;
}

View File

@ -11,14 +11,12 @@ package com.gh.base.fragment;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.IdRes;
import androidx.annotation.LayoutRes;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import android.view.View;
import com.gh.gamecenter.normal.NormalFragment;
@ -55,21 +53,19 @@ public abstract class BaseFragment_ViewPager extends NormalFragment implements D
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mViewPager = view.findViewById(getViewPagerId());
mFragmentsList = restoreFragments();
if (mFragmentsList.size() == 0) {
initFragmentList(mFragmentsList);
}
mFragmentsList = new ArrayList<>();
initFragmentList(mFragmentsList);
mAdapter = BaseFragmentPagerAdapter.newInstance(getChildFragmentManager(), mFragmentsList);
final Bundle args = getArguments();
if (args != null) {
mCheckedIndex = args.getInt(ARGS_INDEX);
}
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mViewPager = (ViewPager) view.findViewById(getViewPagerId());
mViewPager.setOffscreenPageLimit(mFragmentsList.size());
mViewPager.setAdapter(mAdapter);
if (mCheckedIndex < mFragmentsList.size()) {
@ -120,24 +116,9 @@ public abstract class BaseFragment_ViewPager extends NormalFragment implements D
fragment.onActivityResult(requestCode, resultCode, data);
}
}
}
public ArrayList<Fragment> restoreFragments() {
String tag = "android:switcher:" + mViewPager.getId() + ":";
ArrayList<Fragment> fragments = new ArrayList<>();
int childCount = getChildCount();
for (int index = 0; index < childCount; index++) {
Fragment fragment = getChildFragmentManager().findFragmentByTag(tag + index);
if (fragment != null) {
fragments.add(fragment);
}
}
return fragments;
}
public abstract int getChildCount();
public int getCurrentItem() {
return mViewPager != null ? mViewPager.getCurrentItem() : 0;
}

View File

@ -2,6 +2,7 @@ package com.gh.base.fragment
import android.os.Bundle
import com.gh.gamecenter.normal.NormalFragment
import com.lightgame.utils.Utils
/**
* 懒加载(支持多层嵌套)
@ -104,25 +105,15 @@ abstract class BaseLazyFragment : NormalFragment() {
isSupportVisible = visible
if (visible) {
// TODO 当 fragment 重建时这里的被调用很奇怪onActivityCreated 回调触发,但此时的 view 是空的,原因是 createView 还没被调用
// TODO 这样就造成了 onFragmentResume 里可能用到 view 的地方出现空指针异常,所以这里遇到 view 为空的时候 return 等下一次被调用才进去
if (view == null) {
return
}
if (mIsFirstVisible) {
if (mIsFirstVisible && view != null) {
mIsFirstVisible = false
onFragmentFirstVisible()
}
onFragmentResume()
dispatchChildVisibleState(true)
} else {
// 当 fragment 重建时,这个代码块可能在第一次 view 为空的 visible 后调用导致在 onFragmentPause 里可能用到 view 的地方出现空指针异常
if (!mIsFirstVisible) {
dispatchChildVisibleState(false)
onFragmentPause()
}
dispatchChildVisibleState(false)
onFragmentPause()
}
}

View File

@ -1,68 +0,0 @@
package com.gh.base.fragment
import android.view.View
import android.view.ViewStub
import com.gh.gamecenter.R
/**
* 这是在 BaseLazyFragment 之上添加了一些通用功能的抽象类
*
* 怎么将一个已有的 fragment 转化为懒加载 (延迟渲染) 的 fragment 呢?
* (继承 ListFragment 的类请改为继承 LazyListFragment)
*
* 0. 删掉旧的 getInflatedLayout() 的代码,现在由 getLayoutId() 提供 Stub 布局 (默认为 R.layout.fragment_stub若重写请注意提供 id 为 stub 的 ViewStub
* 1. 重写 getRealLayoutId(),提供实际要延迟渲染的 layout Id
* 1. 将原有在 onCreate() 的代码移动到 onFragmentFirstVisible()
* 2. 将原有在 onViewCreated() 的代码移动到 initRealView()
* 注意initRealView() 在 onFragmentFirstVisible() 中被调用,如果要初始化 viewModel 等非 UI 对象请在 super.onFragmentVisible() 调用)
* 3. 如需使用 ViewBinding ,在 onRealLayoutInflated() 的回调中初始化 ViewBinding 即可
* 4. onResume() 的代码移动到 onFragmentResume()onPause() 的代码移动到 onFragmentPause()
* 5. Done!
*/
abstract class LazyFragment : BaseLazyFragment() {
// ViewStub + ViewBinding 有莫名的 bug语法上没问题但编译时通不过。
private var mViewStub: ViewStub? = null
override fun getLayoutId() = R.layout.fragment_stub
override fun useButterKnife() = false
override fun initView(view: View?) {
super.initView(view)
mViewStub = mCachedView.findViewById(R.id.stub)
}
override fun onFragmentFirstVisible() {
super.onFragmentFirstVisible()
inflateRealView()
initRealView()
}
/**
* 真正 inflate View 的地方
*/
protected open fun inflateRealView() {
mViewStub?.layoutResource = getRealLayoutId()
mViewStub?.setOnInflateListener { _, inflatedView -> onRealLayoutInflated(inflatedView) }
mCachedView = mViewStub?.inflate()
}
/**
* 请在这个方法之后获取初始化后的各种 view
*
* 替换旧 fragment 实现时,等同于 onViewCreated
*/
protected open fun initRealView() {}
/**
* 提供要 stub inflate 的 layout
*/
protected abstract fun getRealLayoutId(): Int
/**
* 真实 layout inflate 完成的回调,可用于 viewBinding
*/
protected open fun onRealLayoutInflated(inflatedView: View) {}
}

View File

@ -10,7 +10,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentManager;
import com.gh.common.util.ExtensionsKt;
import com.gh.gamecenter.R;
/**
@ -82,17 +81,8 @@ public class WaitingDialogFragment extends BaseDialogFragment {
@Override
public void dismiss() {
dismissAllowingStateLoss();
}
@Override
public void dismissAllowingStateLoss() {
mBackListener = null;
try {
super.dismissAllowingStateLoss();
} catch (Exception e) {
e.printStackTrace();
}
super.dismiss();
}
public static class WaitingDialogData {

View File

@ -2,13 +2,12 @@ package com.gh.common
import android.os.Handler
import android.os.Looper
import com.gh.base.GHThreadFactory
import com.gh.common.AppExecutor.ioExecutor
import com.gh.common.AppExecutor.lightWeightIoExecutor
import com.gh.common.AppExecutor.logExecutor
import com.gh.common.AppExecutor.uiExecutor
import io.reactivex.schedulers.Schedulers
import java.util.concurrent.*
import java.util.concurrent.Executor
import java.util.concurrent.Executors
/**
* APP 线程池管理类
@ -16,32 +15,16 @@ import java.util.concurrent.*
* [ioExecutor] 是一个最大线程数固定的线程池,较为繁重的 IO 任务可以交给它
* [uiExecutor] 是主线程的包裹,需要切换至主线程执行可以用它
* [lightWeightIoExecutor] 是一个单线程的线程池,轻量级且需要保证同一线程的 IO 任务可以交给它
* [logExecutor] 只为上传 log 而使用的线程池
*
*/
object AppExecutor {
private val mCoreSize = Runtime.getRuntime().availableProcessors()
private val mMinimumPoolSize = 16.coerceAtLeast(mCoreSize * 4)
private val mMaximumPoolSize = 64.coerceAtLeast(mCoreSize * 16)
// TODO 因为 LinkedBlockingQueue 过大导致 MaximumPoolSize 的值几乎无效,下版本改造 [PackageRepository] 启动请求一堆游戏摘要信息的接口?
@JvmStatic
val uiExecutor by lazy { MainThreadExecutor() }
@JvmStatic
val lightWeightIoExecutor by lazy { Executors.newSingleThreadExecutor(GHThreadFactory("GH_LIGHT_WEIGHT_IO_THREAD")) }
val lightWeightIoExecutor by lazy { Executors.newSingleThreadExecutor() }
@JvmStatic
val logExecutor by lazy { Executors.newSingleThreadExecutor(GHThreadFactory("GH_LOG_THREAD")) }
@JvmStatic
val ioExecutor = ThreadPoolExecutor(
mMinimumPoolSize,
mMaximumPoolSize,
20L, TimeUnit.SECONDS,
LinkedBlockingQueue<Runnable>(1000),
GHThreadFactory("GH_IO_THREAD"))
val ioExecutor = Executors.newCachedThreadPool() // 用 by lazy 可能影响初始化速度
val cachedScheduler by lazy { Schedulers.from(ioExecutor) }

View File

@ -8,22 +8,16 @@ import androidx.annotation.Keep
import androidx.appcompat.app.AppCompatActivity
import com.gh.base.CurrentActivityHolder
import com.gh.common.constant.Constants
import com.gh.common.loghub.LoghubUtils
import com.gh.common.tracker.Tracker
import com.gh.common.util.*
import com.gh.common.view.dsbridge.CompletionHandler
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.ImageViewerActivity
import com.gh.gamecenter.LoginActivity
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.energy.EnergyCenterActivity
import com.gh.gamecenter.energy.EnergyHouseActivity
import com.gh.gamecenter.entity.Badge
import com.gh.gamecenter.entity.MtaEvent
import com.gh.gamecenter.entity.NotificationUgc
import com.gh.gamecenter.help.QaFeedbackDialogFragment
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.personalhome.border.AvatarBorderActivity
import com.gh.gamecenter.retrofit.BiResponse
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.security.BindPhoneActivity
@ -70,12 +64,8 @@ class DefaultJsApi(var context: Context) {
@JavascriptInterface
fun login(msg: Any) {
if (SPUtils.getBoolean(Constants.SP_HAS_GET_PHONE_INFO) || NetworkUtils.isOpenMobileData(context)) {
QuickLoginHelper.startLogin(context, "浏览器")
} else {
val intent = LoginActivity.getIntent(context, "浏览器")
context.startActivity(intent)
}
val intent = LoginActivity.getIntent(context, "浏览器")
context.startActivity(intent)
}
@JavascriptInterface
@ -125,7 +115,6 @@ class DefaultJsApi(var context: Context) {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {
EnergyTaskHelper.postEnergyTask("bind_wechat")
handler.complete(true)
}
@ -209,7 +198,6 @@ class DefaultJsApi(var context: Context) {
@JavascriptInterface
fun updateRegulationTestStatus(msg: Any) {
if (msg.toString().toLowerCase(Locale.getDefault()) == "pass") {
EnergyTaskHelper.postEnergyTask("finish_etiquette_exam")
SPUtils.setString(Constants.SP_REGULATION_TEST_PASS_STATUS, "pass")
}
}
@ -227,7 +215,7 @@ class DefaultJsApi(var context: Context) {
@JavascriptInterface
fun showIncompatibleVersionDialog(msg: Any) {
DialogHelper.showUpgradeDialog(context)
DialogUtils.showLowVersionDialog(context)
}
@JavascriptInterface
@ -240,20 +228,6 @@ class DefaultJsApi(var context: Context) {
MessageShareUtils.getInstance(context).shareFromWeb(context, imageShareEvent.type)
}
@JavascriptInterface
fun inviteFriends(event: Any) {
val inviteEvent = event.toString().toObject() ?: InviteFriendsEvent()
val context = CurrentActivityHolder.getCurrentActivity()
if ("poster" == inviteEvent.type) {
Base64ImageHolder.image = inviteEvent.poster.run {
if (this.startsWith("data:image/png;base64")) this.split(",")[1] else this
}
MessageShareUtils.getInstance(context).shareInviteFriends(context, inviteEvent.way)
} else {
ShareUtils.getInstance(context).shareInviteFriends(context, inviteEvent.url, inviteEvent.way)
}
}
@JavascriptInterface
fun bindPhone(msg: Any) {
val intent = BindPhoneActivity.getNormalIntent(context, false)
@ -278,82 +252,10 @@ class DefaultJsApi(var context: Context) {
}
}
@JavascriptInterface
fun openInNewWebview(url: Any) {
runOnUiThread { DirectUtils.directToWebView(context, url.toString(), "内部网页") }
}
@JavascriptInterface
fun postWearBadgeTask(msg: Any) {
EnergyTaskHelper.postEnergyTask("wear_badge")
}
@JavascriptInterface
fun startEnergyCenter(msg: Any) {
context.startActivity(EnergyCenterActivity.getIntent(context))
}
@JavascriptInterface
fun startEnergyHouse(msg: Any) {
context.startActivity(EnergyHouseActivity.getIntent(context))
}
@JavascriptInterface
fun showQaFeedbackDialog(msg: Any) {
QaFeedbackDialogFragment.show(context as AppCompatActivity, msg.toString())
}
@JavascriptInterface
fun getMetaObject(msg: Any): String {
return LogUtils.getMetaObject().toString()
}
@JavascriptInterface
fun getLaunchId(msg: Any): String {
return Tracker.launchId
}
@JavascriptInterface
fun getSessionId(msg: Any): String {
return Tracker.sessionId
}
@JavascriptInterface
fun postLogEvent(event: Any) {
val logEvent = event.toString().toObject() ?: LogEvent()
debugOnly {
Utils.log("LogUtils->${logEvent.jsonString}")
}
LoghubUtils.log(logEvent.jsonString, logEvent.logStore, false)
}
@JavascriptInterface
fun startAvatarBorderPage(msg: Any) {
context.startActivity(AvatarBorderActivity.getIntent(context, msg.toString()))
}
@JavascriptInterface
fun isNetworkConnected(): Boolean {
return NetworkUtils.isNetworkConnected(context)
}
@JavascriptInterface
fun isWifiConnected(): Boolean {
return NetworkUtils.isWifiConnected(context)
}
@Keep
internal data class ImageEvent(var imageList: ArrayList<String> = arrayListOf(), var position: Int = 0)
@Keep
internal data class ImageShareEvent(var image: String = "", var type: String = "")
@Keep
internal data class InviteFriendsEvent(var type: String = "",
var way: String = "",
var url: String = "",
var poster: String = "")
@Keep
internal data class LogEvent(var jsonString: String = "", var logStore: String = "")
}

View File

@ -287,7 +287,6 @@ object DefaultUrlHandler {
val platformName = PlatformUtils.getInstance(context).getPlatformName(platform)
val gameId = uri.getQueryParameter(EntranceUtils.KEY_GAMEID)
val packageMd5 = uri.getQueryParameter(EntranceUtils.KEY_PACKAGE_MD5)
val isQaFeedback = uri.getQueryParameter(EntranceUtils.KEY_IS_QA_FEEDBACK) == "true"
val content = if (TextUtils.isEmpty(gameId) || TextUtils.isEmpty(packageMd5)) String.format("%s-%s-V%s",
uri.getQueryParameter(EntranceUtils.KEY_GAME_NAME),
if (TextUtils.isEmpty(platformName)) platform else platformName,
@ -300,7 +299,7 @@ object DefaultUrlHandler {
if (!TextUtils.isEmpty(qaId)) {
directToQa(context, qaTitle, qaId)
} else {
directToFeedback(context, content, null, isQaFeedback, EntranceUtils.ENTRANCE_BROWSER)
directToFeedback(context, content, EntranceUtils.ENTRANCE_BROWSER)
}
}
@ -308,7 +307,7 @@ object DefaultUrlHandler {
val position = uri.getQueryParameter("position") ?: ""
DirectUtils.directToHelpAndFeedback(context, position.toInt())
}
else -> DialogHelper.showUpgradeDialog(context)
else -> DialogUtils.showLowVersionDialog(context)
}
return true
} else if ("zhiqu" == uri.scheme) {
@ -345,11 +344,6 @@ object DefaultUrlHandler {
return true
}
// 处理内部页面逻辑
if (transformNormalScheme(context, url, entrance)) {
return true
}
if ("http" != uri.scheme && "https" != uri.scheme) return true
return false
}
@ -366,8 +360,7 @@ object DefaultUrlHandler {
uri.path?.apply {
when {
contains("game") -> {
val gameId = uri.getQueryParameter("gameId") ?: uri.pathSegments.last()
?: ""
val gameId = uri.getQueryParameter("gameId") ?: ""
DirectUtils.directToGameDetail(context, gameId, entrance, autoDownload = false, traceEvent = null)
}
contains("question") -> {
@ -379,12 +372,11 @@ object DefaultUrlHandler {
DirectUtils.directToAnswerDetail(context, answerId, entrance, "")
}
}
((contains("bbs")) && contains("article") ||
(contains("communities")) && contains("article")) -> {
contains("communities") && contains("article") -> {
var communityId = ""
var type = ""
var typeId = ""
val split = replace("/communities", "").replace("/bbs", "").replace(".html", "").split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val split = replace("/communities", "").replace(".html", "").split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
for (text in split) {
if (TextUtils.isEmpty(communityId)) {
communityId = text
@ -398,7 +390,7 @@ object DefaultUrlHandler {
typeId = text
}
}
if ("articles" == type || "article" == type) {
if ("articles" == type) {
DirectUtils.directToCommunityArticle(
context, typeId, communityId,
entrance, "文章链接")
@ -406,11 +398,7 @@ object DefaultUrlHandler {
}
contains("article") -> {
val articleId = split("/")[2].replace(".html", "")
if (entrance == "隐私政策") {
DirectUtils.directToArticle(context, articleId, true, entrance)
} else {
DirectUtils.directToArticle(context, articleId, entrance)
}
DirectUtils.directToArticle(context, articleId, entrance)
}
contains("columns") -> {
val columnsId = split("/")[3]

View File

@ -11,7 +11,6 @@ import com.gh.gamecenter.entity.TimeEntity
import com.gh.gamecenter.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers
import kotlin.concurrent.fixedRateTimer
object FixedRateJobHelper {
@ -36,7 +35,7 @@ object FixedRateJobHelper {
// 时间校对10分钟一次
if ((mExecuteCount * CHECKER_PERIOD) % TIME_PERIOD == 0L) {
RetrofitManager.getInstance(HaloApp.getInstance().application).api.time
.subscribeOn(Schedulers.io())
.subscribeOn(AppExecutor.cachedScheduler)
.subscribe(object : Response<TimeEntity>() {
override fun onResponse(response: TimeEntity?) {
val serverTime = response?.time

View File

@ -5,7 +5,6 @@ import android.app.Application
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import com.gh.base.GHThreadFactory
import com.halo.assistant.HaloApp
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
@ -30,31 +29,31 @@ class TimeElapsedHelper(val fragment: Fragment?, val activity: Activity?) {
init {
activity?.application?.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
override fun onActivityStarted(a: Activity) {
override fun onActivityStarted(a: Activity?) {
}
override fun onActivitySaveInstanceState(a: Activity, outState: Bundle) {
override fun onActivitySaveInstanceState(a: Activity?, outState: Bundle?) {
}
override fun onActivityStopped(a: Activity) {
override fun onActivityStopped(a: Activity?) {
}
override fun onActivityCreated(a: Activity, savedInstanceState: Bundle?) {
override fun onActivityCreated(a: Activity?, savedInstanceState: Bundle?) {
}
override fun onActivityPaused(a: Activity) {
override fun onActivityPaused(a: Activity?) {
if (activity == a) {
pauseCounting()
}
}
override fun onActivityResumed(a: Activity) {
override fun onActivityResumed(a: Activity?) {
if (activity == a) {
resumeCounting()
}
}
override fun onActivityDestroyed(a: Activity) {
override fun onActivityDestroyed(a: Activity?) {
if (activity == a) {
HaloApp.getInstance().application.unregisterActivityLifecycleCallbacks(this)
}
@ -115,7 +114,7 @@ class TimeElapsedHelper(val fragment: Fragment?, val activity: Activity?) {
}
object TimeElapsedThreadHolder {
val threadService: ExecutorService by lazy { Executors.newSingleThreadExecutor(GHThreadFactory("TIME_ELAPSED_THREAD")) }
val threadService: ExecutorService by lazy { Executors.newSingleThreadExecutor() }
}
interface TimeoutCallback {

View File

@ -2,7 +2,6 @@ package com.gh.common.constant;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.preference.PreferenceManager;
import android.text.TextUtils;
@ -12,11 +11,9 @@ import com.gh.common.util.PackageUtils;
import com.gh.common.util.SPUtils;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.SuggestionActivity;
import com.gh.gamecenter.entity.NewSettingsEntity;
import com.gh.gamecenter.entity.NewsEntity;
import com.gh.gamecenter.entity.SettingsEntity;
import com.gh.gamecenter.eventbus.EBReuse;
import com.gh.gamecenter.retrofit.BiResponse;
import com.gh.gamecenter.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.halo.assistant.HaloApp;
@ -55,18 +52,15 @@ public class Config {
public static final String TTAD_APPID = BuildConfig.TTAD_APPID;
public static final String DOUYIN_CLIENTKEY = BuildConfig.DOUYIN_CLIENTKEY;
public static final String DOUYIN_CLIENTSECRET = BuildConfig.DOUYIN_CLIENTSECRET;
public static final String QUICK_LOGIN_APPID = BuildConfig.QUICK_LOGIN_APPID;
public static final String QUICK_LOGIN_APPKEY = BuildConfig.QUICK_LOGIN_APPKEY;
// http://www.ghzs666.com/article/${articleId}.html
public static final String URL_ARTICLE = "http://www.ghzs666.com/article/"; // ghzs/ghzs666 统一
public static final String PATCHES = "patches";
public static final String DEFAULT_CHANNEL = "GH_TEST2";
public static final String DEFAULT_CHANNEL = "GH_TEST";
private static String SETTINGS_KEY = "settingsKey";
private static SettingsEntity mSettingsEntity;
private static NewSettingsEntity mNewSettingsEntity;
public static final String FIX_DOWNLOAD_KEY = "isFixDownload";
public static final String FIX_PLUGIN_KEY = "isFixPlugin";
@ -209,21 +203,6 @@ public class Config {
return mSettingsEntity;
}
@Nullable
public static NewSettingsEntity getNewSettingsEntity() {
if (mNewSettingsEntity == null) {
try {
String json = SPUtils.getString(Constants.SP_NEW_SETTINGS);
if (!TextUtils.isEmpty(json)) {
mNewSettingsEntity = GsonUtils.fromJson(json, NewSettingsEntity.class);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return mNewSettingsEntity;
}
private static boolean isExistDownloadFilter() {
if (getSettings() == null || getSettings().getDownload() == null || getSettings().getDownload().size() == 0) {
return false;
@ -299,17 +278,5 @@ public class Config {
EventBus.getDefault().post(new EBReuse("Refresh"));
}
});
RetrofitManager.getInstance(HaloApp.getInstance().getApplication())
.getApi().getNewSettings(Build.MANUFACTURER, Build.MODEL, channel)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BiResponse<NewSettingsEntity>() {
@Override
public void onSuccess(NewSettingsEntity data) {
mNewSettingsEntity = data;
SPUtils.setString(Constants.SP_NEW_SETTINGS, GsonUtils.toJson(data));
}
});
}
}

View File

@ -27,16 +27,12 @@ public class Constants {
public static final String GAME_DETAIL_COME_IN = "game_detail_come_in"; // 从游戏详情进入
public static final String SPLASH_AD = "splash_ad"; // 启动广告
public static final String XPOSED_INSTALLER_PACKAGE_NAME = "de.robv.android.xposed.installer";
public static final String EB_QUIT_LOGIN = "quit_login";
public static final String EB_SHOW_AD = "show_ad";
public static final String EB_GAME_DETAIL = "eb_game_detail";
// 用于避免历史下载掺和到普通下载状态的 ID 修饰符
public static final String GAME_ID_DIVIDER = ":";
// 用于避免历史下载影响到部分依赖名字作为数据更新条件的修饰符
public static final String GAME_NAME_DECORATOR = " ";
@ -53,19 +49,10 @@ public class Constants {
public static final String RAW_GAME_ICON = "raw_game_icon";
public static final String GAME_ICON_SUBSCRIPT = "game_icon_subscript";
public static final String IS_PLATFORM_RECOMMEND = "isPlatformRecommend";
// 下载 id一般来说跟下载文件名一样
public static final String DOWNLOAD_ID = "download_id";
public static final String GHZS_GAME_ID = "5ae4462c2924bc7936438d07";
public static final String EXTRA_DOWNLOAD_TYPE = "extra_download_type";
public static final String SILENT_UPDATE = "静默更新";
public static final String SIMULATOR_DOWNLOAD = "下载模拟器";
public static final String SIMULATOR_GAME = "simulator_game";
public static final String SIMULATOR = "simulator";
public static final String GAME_NAME = "game_name";
public static final String SIMULATOR_DOWNLOAD_START_TIME = "simulator_download_start_time";
public static final String LAST_GHZS_UPDATE_FILE_SIZE = "last_ghzs_update_file_size";
@ -75,8 +62,6 @@ public class Constants {
public static final String SP_IMEI = "imei";
public static final String SP_ANDROID_ID = "android_id";
public static final String LAST_INSTALL_GAME = "last_install_game";
//引导设置 “通知管理” 引导弹窗
public static final String SP_SHOWED_NOTIFICATION_LOGIN = "show_notification_login_hint";
public static final String SP_SHOWED_NOTIFICATION_QUESTION = "show_notification_question_hint";
@ -121,6 +106,8 @@ public class Constants {
public static final String SP_FILTER_TAGS = "filter_tags";
//实名认证弹窗分类数据
public static final String SP_AUTH_DIALOG = "auth_dialog";
//顶部视频进度保存,重启恢复
public static final String SP_TOP_VIDEO_SCHEDULE = "top_video_schedule";
//我的光环小红点提示
public static final String SP_GH_RED_POINT_REMIND = "gh_red_point_remind";
//论坛首页引导
@ -142,56 +129,6 @@ public class Constants {
public static final String SP_IS_USER_ACCEPTED_PRIVACY_STATEMENT = "has_user_accepted_privacy_statement";
public static final String SP_BRAND_NEW_USER = "brand_new_user";
//包名检测是否点击不再提示
public static final String SP_PACKAGE_CHECK = "package_check";
//游戏详情预约引导提示
public static final String SP_GAME_DETAIL_RESERVE_GUIDE = "game_detail_reserve_guide";
public static final String SP_XAPK_UNZIP_ACTIVITY = "xapk_unzip_activity";
public static final String SP_XAPK_URL = "xapk_url";
//游戏详情推荐弹窗
public static final String SP_RECOMMEND_POPUP = "recommend_popup";
// 使用浏览器安装开关
public static final String SP_USE_BROWSER_TO_INSTALL = "use_browser_to_install";
// 游戏详情页底部使用浏览器安装提示
public static final String SP_SHOULD_SHOW_GAMEDETAIL_USE_BROWSER_TO_INSTALL_HINT = "should_show_gamedetail_use_browser_to_install_hint";
// 第一次普通安装推荐使用浏览器安装提示
public static final String SP_SHOULD_SHOW_USE_BROWSER_TO_INSTALL_HINT = "should_show_use_browser_to_install_hint";
//模拟器管理引导
public static final String SP_SIMULATOR_GUIDE = "simulator_guide";
//模拟器游戏引导
public static final String SP_SIMULATOR_GAME_GUIDE = "simulator_game_guide";
//首页视频播放进度
public static final String SP_HOME_VIDEO_PLAY_RECORD = "home_video_play_record";
// 用户是否曾经永久拒绝过存储权限
public static final String SP_USER_HAS_PERMANENTLY_DENIED_STORAGE_PERMISSION = "user_has_permanently_denied_storage_permission";
// 是否已经填写邀请码
public static final String SP_HAS_COMPLETE_INVITE_CODE = "has_complete_invite_code";
// 补充配置项
public static final String SP_NEW_SETTINGS = "new_settings";
// 头像挂件ID
public static final String SP_CHOOSE_AVATAR_ID = "choose_avatar_id";
// 是否显示返回任务悬浮图标
public static final String SP_SHOW_TASK_FLOAT = "show_task_float";
// 悬浮图标Y值
public static final String SP_TASK_FLOAT_LAST_Y = "task_float_last_y";
// 是否第一次进入新分类2.0
public static final String SP_FIRST_ENTER_CATEGORY_V2 = "first_enter_category_v2";
// 是否成功取过号
public static final String SP_HAS_GET_PHONE_INFO = "has_get_phone_info";
//手机号码匹配规则
public static final String REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
@ -227,76 +164,13 @@ public class Constants {
//版规声明
public static final String FORUM_REGULATIONS_NEWS_ID = "5f4db9cc34d44d01b92fd670";
// 权限使用场景地址
public static final String PERMISSION_SCENARIO_ADDRESS = "https://resource.ghzs.com/page/permissions/android.html";
//帮助内容详情
public static final String HELP_ADDRESS_DEV = "https://static-web.ghzs.com/ghzs_help_dev/help.html?content=";
public static final String HELP_ADDRESS = "https://static-web.ghzs.com/ghzs_help/help.html?content=";
// 注销页面
public static final String LOGOUT_ADDRESS_DEV = "https://static-web.ghzs.com/ghzs_help_dev/help.html?content=5f6b1f02786564003944a693&from=ghzs";
public static final String LOGOUT_ADDRESS = "https://static-web.ghzs.com/ghzs_help/help.html?content=5f534111b1f72909fc225672&from=ghzs";
// 商品详情
public static final String COMMODITY_DETAIL_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/product?from=ghzs";
public static final String COMMODITY_DETAIL_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/product?from=ghzs";
// 光能记录
public static final String ENERGY_RECORD_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/record?from=ghzs";
public static final String ENERGY_RECORD_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/record?from=ghzs";
// 订单中心
public static final String ORDER_CENTER_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/orders?from=ghzs";
public static final String ORDER_CENTER_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/orders?from=ghzs";
// 订单详情
public static final String ORDER_DETAIL_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/order-detail?from=ghzs";
public static final String ORDER_DETAIL_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/order-detail?from=ghzs";
// 邀请好友
public static final String INVITE_FRIENDS_ADDRESS_DEV = "https://static-web.ghzs.com/ghzs_activity_dev/inviteFriends.html#/invite";
public static final String INVITE_FRIENDS_ADDRESS = "https://static-web.ghzs.com/ghzs_activity_prod/inviteFriends.html#/invite";
// 等级页面
public static final String LEVEL_ADDRESS_DEV = "https://static-web.ghzs.com/ghzs-userhome-dev/index.html#/level";
public static final String LEVEL_ADDRESS = "https://static-web.ghzs.com/ghzs-userhome/index.html#/level";
// 兑换规则
public static final String EXCHANGE_RULE_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/exchange-rule?from=ghzs";
public static final String EXCHANGE_RULE_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/exchange-rule?from=ghzs";
// 光能规则
public static final String ENERGY_RULE_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/energy-rule?from=ghzs";
public static final String ENERGY_RULE_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/energy-rule?from=ghzs";
// 兑换商品
public static final String EXCHANGE_COMMODITY_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/exchange-log?from=ghzs";
public static final String EXCHANGE_COMMODITY_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/exchange-log?from=ghzs";
// 抽奖乐园
public static final String LOTTERY_PARADISE_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/lottery-list?from=ghzs";
public static final String LOTTERY_PARADISE_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/lottery-list?from=ghzs";
// 我的奖品
public static final String MY_PRIZE_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/mywin?from=ghzs";
public static final String MY_PRIZE_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/mywin?from=ghzs";
// 中奖订单详情
public static final String WIN_ORDER_DETAIL_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/win-order-detail?from=ghzs";
public static final String WIN_ORDER_DETAIL_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/win-order-detail?from=ghzs";
// 地址信息
public static final String ADDRESS_INFO_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/address-list?from=ghzs";
public static final String ADDRESS_INFO_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/address-list?from=ghzs";
// 领奖信息
public static final String PRIZE_INFO_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/user-info?from=ghzs";
public static final String PRIZE_INFO_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/user-info?from=ghzs";
// 提现信息
public static final String WITHDRAW_INFO_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/cash?from=ghzs";
public static final String WITHDRAW_INFO_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/cash?from=ghzs";
public static final String LOGOUT_ADDRESS_DEV = "https://static-web.ghzs.com/ghzs_help_dev/help.html?content=5f6b1f02786564003944a693";
public static final String LOGOUT_ADDRESS = "https://static-web.ghzs.com/ghzs_help/help.html?content=5f534111b1f72909fc225672";
//最少需要多少数据才能上传
public static final int DATA_AMOUNT = 20;

View File

@ -14,17 +14,10 @@ import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.databinding.BindingAdapter;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.facebook.drawee.view.SimpleDraweeView;
import com.gh.base.OnViewClickListener;
import com.gh.common.constant.Config;
import com.gh.common.dialog.CertificationDialog;
import com.gh.common.dialog.PackageCheckDialogFragment;
import com.gh.common.dialog.ReserveDialogFragment;
import com.gh.common.exposure.ExposureEvent;
import com.gh.common.history.HistoryHelper;
@ -45,15 +38,14 @@ import com.gh.common.util.NewsUtils;
import com.gh.common.util.NumberUtils;
import com.gh.common.util.PackageInstaller;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.PermissionHelper;
import com.gh.common.util.PlatformUtils;
import com.gh.common.util.RealNameHelper;
import com.gh.common.util.ReservationHelper;
import com.gh.common.view.DownloadProgressBar;
import com.gh.common.view.DrawableView;
import com.gh.common.view.GameIconView;
import com.gh.download.DownloadManager;
import com.gh.download.dialog.DownloadDialog;
import com.gh.download.server.BrowserInstallHelper;
import com.gh.gamecenter.DownloadManagerActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.WebActivity;
@ -68,7 +60,6 @@ import com.gh.gamecenter.entity.ServerCalendarEntity;
import com.gh.gamecenter.entity.TagStyleEntity;
import com.gh.gamecenter.entity.TestEntity;
import com.gh.gamecenter.eventbus.EBReuse;
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment;
import com.gh.gamecenter.manager.PackagesManager;
import com.gh.gamecenter.qa.entity.CommunityVideoEntity;
import com.lightgame.download.DownloadEntity;
@ -83,6 +74,12 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.databinding.BindingAdapter;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
/**
* Created by khy on 12/02/18.
*/
@ -259,14 +256,6 @@ public class BindingAdapters {
}
}
/**
* lazy 的 paddingTop
*/
@BindingAdapter("lazyPaddingLeft")
public static void lazyPaddingLeft(View view, int paddingLeftInDp) {
view.setPadding(DisplayUtils.dip2px(paddingLeftInDp), view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom());
}
/**
* lazy 的 paddingTop
*/
@ -459,37 +448,25 @@ public class BindingAdapters {
return;
}
}
RealNameHelper.checkIfAuth(v.getContext(), gameEntity, () -> {
GamePermissionDialogFragment.show((AppCompatActivity) v.getContext(), gameEntity, gameEntity.getInfo(), () -> {
BrowserInstallHelper.showBrowserInstallHintDialog(v.getContext(), () -> {
PackageCheckDialogFragment.show((AppCompatActivity) v.getContext(), gameEntity, () -> {
DownloadDialogHelper.findAvailableDialogAndShow(v.getContext(), gameEntity, apk, () -> {
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
DialogUtils.showOverseaDownloadDialog(v.getContext(), gameEntity, () -> {
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
});
});
});
});
DownloadDialogHelper.findAvailableDialogAndShow(v.getContext(), gameEntity, apk, () -> {
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
DialogUtils.showOverseaDownloadDialog(v.getContext(), gameEntity, () -> {
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
});
});
});
});
} else {
RealNameHelper.checkIfAuth(v.getContext(), gameEntity, () -> {
GamePermissionDialogFragment.show((AppCompatActivity) v.getContext(), gameEntity, gameEntity.getInfo(), () -> {
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
DownloadDialog.showDownloadDialog(
v.getContext(),
gameEntity,
traceEvent,
entrance,
location + ":" + gameEntity.getName());
});
});
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
DownloadDialog.showDownloadDialog(
v.getContext(),
gameEntity,
traceEvent,
entrance,
location + ":" + gameEntity.getName());
});
});
}
@ -531,15 +508,13 @@ public class BindingAdapters {
}
break;
case RESERVABLE:
RealNameHelper.checkIfAuth(v.getContext(), gameEntity, () -> {
GamePermissionDialogFragment.show((AppCompatActivity) v.getContext(), gameEntity, gameEntity.getInfo(), () -> {
CheckLoginUtils.checkLogin(progressBar.getContext(), "", () -> {
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(gameEntity, () -> {
LogUtils.logReservation(gameEntity, traceEvent);
updateReservation(progressBar, gameEntity);
});
dialogFragment.show(((AppCompatActivity) progressBar.getContext()).getSupportFragmentManager(), "reserve");
CheckLoginUtils.checkLogin(progressBar.getContext(), "", () -> {
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(progressBar.getContext(), () -> {
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(gameEntity, () -> {
LogUtils.logReservation(gameEntity, traceEvent);
updateReservation(progressBar, gameEntity);
});
dialogFragment.show(((AppCompatActivity) progressBar.getContext()).getSupportFragmentManager(), "reserve");
});
});
break;
@ -567,10 +542,8 @@ public class BindingAdapters {
HistoryHelper.insertGameEntity(gameEntity);
}
GamePermissionDialogFragment.show((AppCompatActivity) v.getContext(), gameEntity, gameEntity.getInfo(), () -> {
Intent i = new Intent(WebActivity.getIntentForWebGame(progressBar.getContext(), linkEntity.getLink(), gameEntity.getName(), isPlay, linkEntity.getCloseButton()));
progressBar.getContext().startActivity(i);
});
Intent i = new Intent(WebActivity.getIntentForWebGame(progressBar.getContext(), linkEntity.getLink(), gameEntity.getName(), isPlay, linkEntity.getCloseButton()));
progressBar.getContext().startActivity(i);
break;
case UPDATING:
Utils.toast(progressBar.getContext(), "正在加急更新版本,敬请后续留意");
@ -750,9 +723,7 @@ public class BindingAdapters {
try {
ArrayList<TagStyleEntity> tagStyle = new ArrayList<>();
TestEntity test = gameEntity.getTest();
if (test != null
// 这个判断用于开测表列表
&& !"type_tag".equals(test.getGameTag())) {
if (test != null) {
TagStyleEntity typeTag = new TagStyleEntity();
typeTag.setName(test.getType() != null ? test.getType() : "");
typeTag.setBackground("FFF3E0");

View File

@ -1,95 +0,0 @@
package com.gh.common.dialog
import android.annotation.SuppressLint
import android.app.Dialog
import android.os.Bundle
import android.view.*
import com.gh.base.fragment.BaseDialogFragment
import com.gh.gamecenter.R
import com.halo.assistant.HaloApp
abstract class BaseDraggableDialogFragment : BaseDialogFragment(), View.OnTouchListener {
private var mInitPositionY = 0f
private lateinit var mGestureDetector: GestureDetector
private lateinit var mRootView: View
private lateinit var mDragCloseView: View
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mRootView = getRootView()
mDragCloseView = getDragCloseView()
mDragCloseView.setOnTouchListener(this)
mGestureDetector = GestureDetector(requireContext(), SingleTapConfirm())
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val createDialog = super.onCreateDialog(savedInstanceState)
createDialog.setCanceledOnTouchOutside(true)
val window = createDialog.window
window?.setGravity(Gravity.BOTTOM)
window?.setWindowAnimations(R.style.community_publication_animation)
return createDialog
}
// dialog drag animation
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View, event: MotionEvent): Boolean {
if (mGestureDetector.onTouchEvent(event) && mRootView.y == 0F) {
v.performClick()
return true
}
when (event.action) {
MotionEvent.ACTION_DOWN -> {
mInitPositionY = mRootView.y - event.rawY
}
MotionEvent.ACTION_MOVE -> {
val offsetY = event.rawY + mInitPositionY
val dialogY = mRootView.y
if (dialogY + offsetY > 0) {
mRootView.animate()
.y(offsetY)
.setDuration(0)
.start()
} else {
resetDialogPosition()
}
}
MotionEvent.ACTION_CANCEL,
MotionEvent.ACTION_UP,
MotionEvent.ACTION_OUTSIDE -> {
if (mRootView.y >= mRootView.height / 2) {
dismissAllowingStateLoss()
} else {
resetDialogPosition(300)
}
}
else -> return false
}
return true
}
private fun resetDialogPosition(duration: Long = 0) {
mRootView.animate()
.y(0F)
.setDuration(duration)
.start()
}
private class SingleTapConfirm : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapUp(event: MotionEvent): Boolean {
return true
}
}
override fun onStart() {
super.onStart()
val width = HaloApp.getInstance().application.resources.displayMetrics.widthPixels
val height = dialog?.window?.attributes?.height ?: ViewGroup.LayoutParams.WRAP_CONTENT
dialog?.window?.setLayout(width, height)
}
abstract fun getRootView(): View
abstract fun getDragCloseView(): View
override fun getThemeRes(): Int = R.style.DialogFragmentDimAmount
}

View File

@ -4,8 +4,6 @@ import android.content.DialogInterface
import android.os.Bundle
import android.view.KeyEvent
import android.view.View
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentManager
import com.gh.common.util.MtaHelper
import com.lightgame.dialog.BaseDialogFragment
import java.util.concurrent.atomic.AtomicBoolean
@ -65,29 +63,4 @@ abstract class BaseTrackableDialogFragment : BaseDialogFragment() {
open fun trackWithBasicDeviceInfo() = false
override fun show(manager: FragmentManager, tag: String?) {
val fragment = manager.findFragmentByTag(tag)
if (fragment != null) {
val transaction = manager.beginTransaction()
transaction.show(fragment)
transaction.commit()
} else {
try {
val clazz: Class<*> = DialogFragment::class.java
val dismissed = clazz.getDeclaredField("mDismissed")
dismissed.isAccessible = true
dismissed[this] = false
val shownByMe = clazz.getDeclaredField("mShownByMe")
shownByMe.isAccessible = true
shownByMe[this] = true
val transaction = manager.beginTransaction()
transaction.add(this, tag)
transaction.commitAllowingStateLoss()
} catch (e: Exception) {
super.show(manager, tag)
e.printStackTrace()
}
}
}
}

View File

@ -118,9 +118,7 @@ class CertificationDialog(context: Context, private val authDialogEntity: AuthDi
//跳转登录页面
private fun gotoLoginPage() {
val currentActivity = AppManager.getInstance().currentActivity() ?: return
CheckLoginUtils.checkLogin(currentActivity as AppCompatActivity,
CheckLoginUtils.checkLogin(AppManager.getInstance().currentActivity() as AppCompatActivity,
null, true, "实名认证弹窗") {
if (UserManager.getInstance().isAuth) {
listener.onConfirm()
@ -131,9 +129,7 @@ class CertificationDialog(context: Context, private val authDialogEntity: AuthDi
//跳转实名认证页面
private fun gotoAuthPage() {
val currentActivity = AppManager.getInstance().currentActivity() ?: return
AvoidOnResultManager.getInstance(currentActivity as AppCompatActivity)
AvoidOnResultManager.getInstance(AppManager.getInstance().currentActivity() as AppCompatActivity)
.startForResult(UserInfoEditActivity.getIntent(context, UserViewModel.TYPE_ID_CARD), object : Callback {
override fun onActivityResult(resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK && data != null) {

View File

@ -60,36 +60,26 @@ class DeviceRemindDialog(context: Context, val entity: DeviceDialogEntity, val g
companion object {
fun showDeviceRemindDialog(context: Context, gameEntity: GameEntity) {
val datas = SPUtils.getString(Constants.SP_DEVICE_REMIND)
if (datas.isNotEmpty()) {
val pair = shouldShowDeviceRemindDialog(gameEntity)
if (pair.first) {
val dialog = DeviceRemindDialog(context, pair.second!!, gameEntity)
dialog.show()
}
}
}
fun shouldShowDeviceRemindDialog(gameEntity: GameEntity): Pair<Boolean, DeviceDialogEntity?> {
val datas = SPUtils.getString(Constants.SP_DEVICE_REMIND)
if (datas.isNotEmpty()) {
val type = object : TypeToken<List<DeviceDialogEntity>>() {}.type
val entities = GsonUtils.gson.fromJson<List<DeviceDialogEntity>>(datas, type)
val entitys = GsonUtils.gson.fromJson<List<DeviceDialogEntity>>(datas, type)
//1.判断设备是否匹配
val entity = entities.find { it.manufacturer.toLowerCase().startsWith(Build.MANUFACTURER.toLowerCase()) }
?: return Pair(false, null)
val entity = entitys.find { it.manufacturer.toLowerCase().startsWith(Build.MANUFACTURER.toLowerCase()) }
?: return
//2.判断游戏不含剔除标签
gameEntity.tagStyle.forEach {
if (entity.excludeTags.contains(it.name)) {
return Pair(false, null)
return
}
}
//3.不再弹出提示判断
val isNoRemindAgain = SPUtils.getBoolean(Constants.SP_NO_REMIND_AGAIN, false)
if (isNoRemindAgain) return Pair(false, null)
return Pair(true, entity)
if (isNoRemindAgain) return
val dialog = DeviceRemindDialog(context, entity, gameEntity)
dialog.show()
}
return Pair(false, null)
}
}
@ -225,7 +215,7 @@ class DeviceRemindDialog(context: Context, val entity: DeviceDialogEntity, val g
class LooperHandle(val mAdapter: BannerAdapter) : Handler() {
private val mWeakReference: WeakReference<BannerAdapter> = WeakReference(mAdapter)
override fun handleMessage(msg: Message) {
override fun handleMessage(msg: Message?) {
val adapter = mWeakReference.get()
adapter?.scrollToNextPage()
adapter?.startScroll()

View File

@ -1,6 +1,5 @@
package com.gh.common.dialog
import android.app.Dialog
import android.graphics.Paint
import android.os.Bundle
import android.util.TypedValue
@ -9,70 +8,54 @@ import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.text.HtmlCompat
import com.gh.base.fragment.BaseDialogFragment
import com.gh.common.util.DirectUtils
import com.gh.common.util.dip2px
import com.gh.common.util.toColor
import com.gh.common.util.DisplayUtils
import com.gh.common.util.MtaHelper
import com.gh.gamecenter.R
import com.gh.gamecenter.databinding.DialogGameOffServiceBinding
import com.gh.gamecenter.entity.GameEntity
import kotlinx.android.synthetic.main.dialog_game_off_service.*
// 游戏关闭下载弹窗
class GameOffServiceDialogFragment
// : BaseTrackableDialogFragment()
: BaseDialogFragment() {
:BaseDialogFragment() {
private var mDialog: GameEntity.Dialog? = null
private var mBinding: DialogGameOffServiceBinding? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return DialogGameOffServiceBinding
.inflate(inflater)
.apply { mBinding = this }
.root
return inflater.inflate(R.layout.dialog_game_off_service, null)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mBinding?.run {
mDialog?.run {
titleTv.text = title
contentTv.text = HtmlCompat.fromHtml(content, HtmlCompat.FROM_HTML_MODE_LEGACY)
okTv.setOnClickListener {
dismissAllowingStateLoss()
mDialog?.run {
titleTv.text = title
contentTv.text = HtmlCompat.fromHtml(content, HtmlCompat.FROM_HTML_MODE_LEGACY)
for (site in sites) {
val siteTv = TextView(context)
siteTv.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
topMargin = DisplayUtils.dip2px(12f)
}
siteTv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
siteTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.theme_font))
siteTv.text = site.text
siteTv.paintFlags = siteTv.paintFlags or Paint.UNDERLINE_TEXT_FLAG
siteTv.setOnClickListener {
// MtaHelper.onEvent("游戏下载状态按钮", getKey(), site.text)
DirectUtils.directToWebView(requireContext(), site.url, "(关闭下载弹窗)")
dismiss()
}
// 过滤内容为空的元素
val notEmptySite = sites.filter { it.text.isNotBlank() }
notEmptySite.forEachIndexed { index, site ->
val siteTv = TextView(context)
siteTv.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
topMargin = 24F.dip2px()
if (index == notEmptySite.size - 1) bottomMargin = 8F.dip2px()
}
siteTv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14F)
siteTv.setTextColor(R.color.theme_font.toColor())
siteTv.text = site.text
siteTv.paintFlags = siteTv.paintFlags or Paint.UNDERLINE_TEXT_FLAG
siteTv.setOnClickListener {
// MtaHelper.onEvent("游戏下载状态按钮", getKey(), site.text)
DirectUtils.directToWebView(requireContext(), site.url, "(关闭下载弹窗)")
dismissAllowingStateLoss()
}
container.addView(siteTv)
}
container.addView(siteTv)
}
}
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return super.onCreateDialog(savedInstanceState).apply { setCanceledOnTouchOutside(true) }
}
// override fun getEvent(): String {
// return "游戏下载状态按钮"
// }

View File

@ -13,19 +13,16 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentTransaction
import com.airbnb.lottie.LottieAnimationView
import com.gh.common.constant.Config
import com.gh.common.constant.Constants
import com.gh.common.util.*
import com.gh.common.util.PermissionHelper.INSTALL_PERMISSION_CODE
import com.gh.common.xapk.XapkInstaller
import com.gh.common.util.MtaHelper
import com.gh.common.util.PermissionHelper
import com.gh.common.util.PermissionHelper.INSTALL_PERMISS_CODE
import com.gh.common.util.goneIf
import com.gh.gamecenter.R
import com.lightgame.download.DownloadEntity
import kotlin.random.Random
class InstallPermissionDialogFragment : BaseTrackableDialogFragment() {
lateinit var mView: View
var isXapk = false
var url: String = ""
var mCallBack: (() -> Unit)? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@ -38,26 +35,16 @@ class InstallPermissionDialogFragment : BaseTrackableDialogFragment() {
val closeTv = mView.findViewById<TextView>(R.id.closeTv)
val closeIv = mView.findViewById<ImageView>(R.id.closeIv)
val activateTv = mView.findViewById<TextView>(R.id.activateTv)
val contentTv = mView.findViewById<TextView>(R.id.contentTv)
val switchLottie = mView.findViewById<LottieAnimationView>(R.id.switchLottie)
contentTv.text = if (isXapk) "未授权下解压XAPK可能导致解压失败" else "以保证游戏的安装和更新"
switchLottie.setAnimation("lottie/install_permission_switch.json")
switchLottie.playAnimation()
val randomNumber = if (isXapk) 1 else Random.nextInt(2)
val randomNumber = Random.nextInt(2)
closeTv.goneIf(randomNumber == 0)
closeIv.goneIf(randomNumber != 0)
if (isXapk) {
closeTv.text = "暂不,尝试解压"
closeIv.visibility = View.VISIBLE
}
closeTv.setOnClickListener {
MtaHelper.onEvent(getEvent(), getKey(), "文案样式_点击以后再说")
if (isXapk) {
mCallBack?.invoke()
}
dismiss()
}
closeIv.setOnClickListener {
@ -67,18 +54,12 @@ class InstallPermissionDialogFragment : BaseTrackableDialogFragment() {
activateTv.setOnClickListener {
MtaHelper.onEvent(getEvent(), getKey(), if (randomNumber == 0) "文案样式_点击立即开启" else "图标样式_点击立即开启")
PermissionHelper.toInstallPermissionSetting(requireActivity())
if (isXapk) {
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, requireActivity().javaClass.name)
SPUtils.setString(Constants.SP_XAPK_URL, url)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK && requestCode == INSTALL_PERMISSION_CODE) {
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "")
SPUtils.setString(Constants.SP_XAPK_URL, "")
if (resultCode == RESULT_OK && requestCode == INSTALL_PERMISS_CODE) {
mCallBack?.invoke()
dismiss()
}
@ -90,43 +71,30 @@ class InstallPermissionDialogFragment : BaseTrackableDialogFragment() {
companion object {
@JvmStatic
fun show(activity: AppCompatActivity, downloadEntity: DownloadEntity, callBack: (() -> Unit)?) {
val isXapk = XapkInstaller.XAPK_EXTENSION_NAME == downloadEntity.path.getExtension()
fun show(activity: AppCompatActivity, callBack: (() -> Unit)?) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
callBack?.invoke()
return
}
val haveInstallPermission = activity.packageManager.canRequestPackageInstalls()
if (haveInstallPermission) {
if (!Config.isPermissionPopupSwitchOpen()) {
callBack?.invoke()
return
}
if (isXapk) {
val xapkUnzipVersions = Config.getSettings()?.permissionPopupAppliedVersions?.xapkUnzip
if (xapkUnzipVersions?.contains(Build.VERSION.SDK_INT.toString()) == false) {
callBack?.invoke()
return
}
} else {
val installVersions = Config.getSettings()?.permissionPopupAppliedVersions?.install
if (installVersions?.contains(Build.VERSION.SDK_INT.toString()) == false) {
callBack?.invoke()
return
}
val haveInstallPermission = activity.packageManager.canRequestPackageInstalls();
if (haveInstallPermission) {
callBack?.invoke()
return
}
var installPermissionDialogFragment = activity.supportFragmentManager.findFragmentByTag(InstallPermissionDialogFragment::class.java.simpleName) as? InstallPermissionDialogFragment
if (installPermissionDialogFragment != null) {
installPermissionDialogFragment.mCallBack = callBack
installPermissionDialogFragment.isXapk = isXapk
installPermissionDialogFragment.url = downloadEntity.url
val transaction: FragmentTransaction = activity.supportFragmentManager.beginTransaction()
transaction.show(installPermissionDialogFragment)
transaction.commit()
} else {
installPermissionDialogFragment = InstallPermissionDialogFragment().apply {
this.mCallBack = callBack
this.isXapk = isXapk
this.url = downloadEntity.url
mCallBack = callBack
}
installPermissionDialogFragment.show(activity.supportFragmentManager, InstallPermissionDialogFragment::class.java.simpleName)
}

View File

@ -67,7 +67,7 @@ class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
activateTv.setOnClickListener {
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击立即开启")
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "${styleEntity.scenes}_${styleEntity.styleNo}_点击立即开启")
dismissAllowingStateLoss()
dismiss()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//这种方案适用于 API 26, 即8.0含8.0)以上可以用
val intent = Intent()
@ -80,7 +80,7 @@ class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
}
closeIv.setOnClickListener {
dismissAllowingStateLoss()
dismiss()
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击关闭")
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "${styleEntity.scenes}_${styleEntity.styleNo}_点击关闭")
}

View File

@ -1,381 +0,0 @@
package com.gh.common.dialog
import android.animation.ValueAnimator
import android.content.Context
import android.content.pm.PackageInfo
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.LinearInterpolator
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.Lifecycle
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.base.BaseRecyclerViewHolder
import com.gh.common.constant.Constants
import com.gh.common.util.*
import com.gh.common.view.CustomLinkMovementMethod
import com.gh.download.DownloadManager
import com.gh.gamecenter.R
import com.gh.gamecenter.databinding.FragmentPackageCheckBinding
import com.gh.gamecenter.databinding.PackageCheckItemBinding
import com.gh.gamecenter.entity.DetectionObjectEntity
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.entity.LinkEntity
import com.gh.gamecenter.entity.PackageDialogEntity
import com.gh.gamecenter.eventbus.EBPackage
import com.halo.assistant.HaloApp
import com.lightgame.adapter.BaseRecyclerAdapter
import com.lightgame.dialog.BaseDialogFragment
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
import io.reactivex.disposables.Disposable
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
/**
* 包名检测弹窗
*/
// TODO 将 gameEntity 放到 argument 里再取出,避免重建时为空
class PackageCheckDialogFragment : BaseDialogFragment() {
private lateinit var binding: FragmentPackageCheckBinding
private var mTotalWidth = 0f
private val mDuration = 3000
private var mDisposable: Disposable? = null
private var mAdapter: PackageCheckAdapter? = null
private var mAllInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
var gameEntity: GameEntity? = null
var callBack: DialogUtils.ConfirmListener? = null
private val dataWatcher = object : DataWatcher() {
override fun onDataChanged(downloadEntity: DownloadEntity) {
val packageName = downloadEntity.packageName
val detectionObjects = gameEntity?.packageDialog?.detectionObjects
if (DownloadStatus.add == downloadEntity.status || DownloadStatus.done == downloadEntity.status) {
detectionObjects?.forEach { detectionObject ->
if (detectionObject.packages.contains(packageName)) {
val packageLink = gameEntity?.packageDialog?.links?.find { it.buttonLink }
LogUtils.uploadPackageCheck("pkg_check_pop_download", if (DownloadStatus.add == downloadEntity.status) "下载开始" else "下载完成",
gameEntity, packageLink?.text ?: "", packageLink?.title
?: "", downloadEntity.gameId, downloadEntity.getMetaExtra(Constants.GAME_NAME))
}
}
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
EventBus.getDefault().register(this)
gameEntity?.let {
LogUtils.uploadPackageCheck("pkg_check_pop_click", "出现弹窗", it, "", "", "", "")
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = FragmentPackageCheckBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
gameEntity?.packageDialog?.let {
changeParams(it.detectionObjects.size)
binding.packageRv.layoutManager = LinearLayoutManager(requireContext())
mAdapter = PackageCheckAdapter(requireContext(), it.detectionObjects)
binding.packageRv.adapter = mAdapter
binding.titleTv.text = it.title
binding.contentTv.text = it.content
val spanBuilder = SpanBuilder(it.linkHintText).build()
it.links.forEachIndexed { index, link ->
val linkSpan = SpanBuilder(link.title ?: "").click(0, (link.title
?: "").length, R.color.theme_font, true) {
LogUtils.uploadPackageCheck("pkg_check_pop_click", "点击链接", gameEntity, link.text, link.title, "", "")
DirectUtils.directToLinkPage(requireContext(), link, "包名检测弹窗", "")
}.build()
spanBuilder.append(linkSpan)
if (index != it.links.size - 1) {
spanBuilder.append("")
}
}
binding.linkHintTv.text = spanBuilder
binding.linkHintTv.movementMethod = CustomLinkMovementMethod.getInstance()
when (it.level) {
"HINT_SKIP" -> {
binding.cancelTv.text = "取消"
binding.noRemindAgainCb.visibility = View.GONE
}
"ALWAYS_HINT" -> {
binding.cancelTv.text = "我知道了"
binding.noRemindAgainCb.visibility = View.GONE
}
"OPTIONAL_CURRENT_HINT" -> {
binding.cancelTv.text = "我知道了"
binding.noRemindAgainCb.visibility = View.VISIBLE
}
else -> {
binding.cancelTv.text = "我知道了"
binding.noRemindAgainCb.visibility = View.VISIBLE
}
}
initListener(it)
}
binding.root.post {
checkPackage()
}
}
private fun changeParams(size: Int) {
val params = binding.packageRv.layoutParams as LinearLayout.LayoutParams
params.height = if (size > 3) (28f.dip2px() * 3.5).toInt() else 28f.dip2px() * size
binding.packageRv.layoutParams = params
}
private fun initListener(entity: PackageDialogEntity) {
binding.downloadBtn.setOnClickListener {
if (binding.noRemindAgainCb.isChecked) {
saveRecord(entity)
}
val isAllPackageInstalled = isAllPackageInstalled(mAllInstalledPackages, entity)
if (isAllPackageInstalled) {
callBack?.onConfirm()
dismissAllowingStateLoss()
} else {
var packageLink = getNotInstalledLink(entity)
if (packageLink == null) {
packageLink = entity.links.find { it.buttonLink }
}
if (packageLink != null) {
LogUtils.uploadPackageCheck("pkg_check_pop_click", "点击前往下载", gameEntity, packageLink.text, packageLink.title, "", "")
DirectUtils.directToLinkPage(requireContext(), packageLink, "包名检测弹窗", "")
}
}
}
binding.cancelTv.setOnClickListener {
if (entity.level != "HINT_SKIP") {
callBack?.onConfirm()
}
if (binding.noRemindAgainCb.isChecked) {
saveRecord(entity)
LogUtils.uploadPackageCheck("pkg_check_pop_click", "不再提示", gameEntity, "", "", "", "")
}
dismissAllowingStateLoss()
}
}
private fun saveRecord(entity: PackageDialogEntity) {
if (entity.level == "OPTIONAL_CURRENT_HINT") {
SPUtils.setBoolean("${Constants.SP_PACKAGE_CHECK}:${gameEntity?.id}", true)
} else {
SPUtils.setBoolean("${Constants.SP_PACKAGE_CHECK}:${gameEntity?.packageDialog?.id}", true)
}
}
private fun checkPackage() {
var index = 0
mTotalWidth = (DisplayUtils.getScreenWidth() - 108f.dip2px()).toFloat()
mDisposable = rxTimer(1) {
gameEntity?.packageDialog?.detectionObjects?.let { objects ->
if (objects.isNotEmpty()) {
val averageTime = if (objects.size == 1) {
mDuration
} else {
mDuration / objects.size
}
if (it != 0L && it % averageTime == 0L && index < objects.size) {
mAdapter?.notifyPackages()
binding.packageRv.smoothScrollToPosition(index)
index++
}
}
}
if (it >= mDuration) {
mDisposable?.dispose()
binding.downloadBtn.isEnabled = true
}
}
val animator = ValueAnimator.ofInt(0, 100)
animator.duration = mDuration.toLong()
animator.interpolator = LinearInterpolator()
animator.addUpdateListener {
binding.progressBar.progress = it.animatedValue as Int
}
animator.start()
}
private fun getNotInstalledLink(packageDialogEntity: PackageDialogEntity): LinkEntity? {
val links = LinkedHashSet<LinkEntity>()
packageDialogEntity.detectionObjects.forEach { obj ->
if (!checkDetectionsInstalled(mAllInstalledPackages, obj.packages)) {
obj.assignDownload.forEach {
links.add(packageDialogEntity.links[it])
}
}
}
var link: LinkEntity? = null
if (links.size > 1) {
link = links.find { it.buttonLink } ?: links.toList()[0]
} else if (links.size == 1) {
link = links.toList()[0]
}
return link
}
override fun onStart() {
super.onStart()
val width = requireContext().resources.displayMetrics.widthPixels - 60F.dip2px()
val height = ViewGroup.LayoutParams.WRAP_CONTENT
requireDialog().window?.setLayout(width, height)
requireDialog().setCanceledOnTouchOutside(true)
DownloadManager.getInstance(context).addObserver(dataWatcher)
}
override fun onResume() {
super.onResume()
mAllInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
gameEntity?.packageDialog?.let {
if (isAllPackageInstalled(mAllInstalledPackages, it)) {
callBack?.onConfirm()
dismissAllowingStateLoss()
}
}
}
override fun onDestroyView() {
super.onDestroyView()
EventBus.getDefault().unregister(this)
if (mDisposable?.isDisposed == false) {
mDisposable?.dispose()
}
LogUtils.uploadPackageCheck("pkg_check_pop_click", "关闭弹窗", gameEntity, "", "", "", "")
DownloadManager.getInstance(context).removeObserver(dataWatcher)
}
//安装、卸载事件
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(busFour: EBPackage) {
if ("安装" == busFour.type || "卸载" == busFour.type) {
mAllInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
mAdapter?.notifyDataSetChanged()
}
}
inner class PackageCheckAdapter(val context: Context, val entities: ArrayList<DetectionObjectEntity>) : BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
private var index = -1
fun notifyPackages() {
index++
notifyItemChanged(index)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return PackageCheckViewHolder(PackageCheckItemBinding.bind(LayoutInflater.from(context).inflate(R.layout.package_check_item, parent, false)))
}
override fun getItemCount(): Int = entities.size
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is PackageCheckViewHolder) {
val entity = entities[position]
holder.binding.entity = entity
if (position <= index) {
val isAllInstalled = checkDetectionsInstalled(mAllInstalledPackages, entity.packages)
if (isAllInstalled) {
holder.binding.statusTv.text = "已安装"
holder.binding.statusTv.setTextColor(ContextCompat.getColor(context, R.color.theme_font))
} else {
holder.binding.statusTv.text = "未安装"
holder.binding.statusTv.setTextColor(ContextCompat.getColor(context, R.color.text_FF4147))
}
holder.binding.statusTv.visibility = View.VISIBLE
} else {
holder.binding.statusTv.visibility = View.GONE
}
}
}
}
class PackageCheckViewHolder(val binding: PackageCheckItemBinding) : BaseRecyclerViewHolder<DetectionObjectEntity>(binding.root)
companion object {
@JvmStatic
fun show(activity: AppCompatActivity, gameEntity: GameEntity, callBack: DialogUtils.ConfirmListener) {
val packageDialogEntity = gameEntity.packageDialog
if (packageDialogEntity == null) {
callBack.onConfirm()
return
}
val allInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
if (isAllPackageInstalled(allInstalledPackages, packageDialogEntity)) {
callBack.onConfirm()
return
}
val isChoose = SPUtils.getBoolean("${Constants.SP_PACKAGE_CHECK}:${packageDialogEntity.id}", false)
if (packageDialogEntity.level == "OPTIONAL_HINT" && isChoose) {
callBack.onConfirm()
return
}
val isCurrentGameChoose = SPUtils.getBoolean("${Constants.SP_PACKAGE_CHECK}:${gameEntity.id}", false)
if (packageDialogEntity.level == "OPTIONAL_CURRENT_HINT" && isCurrentGameChoose) {
callBack.onConfirm()
return
}
if (!activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) return
var dialogFragment = activity.supportFragmentManager.findFragmentByTag(PackageCheckDialogFragment::class.java.simpleName) as? PackageCheckDialogFragment
if (dialogFragment == null) {
dialogFragment = PackageCheckDialogFragment()
dialogFragment.gameEntity = gameEntity
dialogFragment.callBack = callBack
dialogFragment.show(activity.supportFragmentManager, PackageCheckDialogFragment::class.java.simpleName)
} else {
dialogFragment.gameEntity = gameEntity
dialogFragment.callBack = callBack
val transaction: FragmentTransaction = activity.supportFragmentManager.beginTransaction()
transaction.show(dialogFragment)
transaction.commit()
}
}
private fun checkDetectionsInstalled(allInstalledPackages: List<PackageInfo>, packages: ArrayList<String>): Boolean {
var isPackagesInstalled = false
packages.forEach { packageName ->
val isInstalled = allInstalledPackages.find { it.packageName == packageName } != null
if (isInstalled) {
isPackagesInstalled = true
return@forEach
}
}
return isPackagesInstalled
}
fun isAllPackageInstalled(allInstalledPackages: List<PackageInfo>, packageDialogEntity: PackageDialogEntity): Boolean {
var isAllInstalled = true
packageDialogEntity.detectionObjects.forEach loop@{ obj ->
if (!checkDetectionsInstalled(allInstalledPackages, obj.packages)) {
isAllInstalled = false
return isAllInstalled
}
}
return isAllInstalled
}
}
}

View File

@ -2,27 +2,23 @@ package com.gh.common.dialog
import android.app.Dialog
import android.content.DialogInterface
import android.os.Build
import android.os.Bundle
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextPaint
import android.text.method.ScrollingMovementMethod
import android.text.style.ClickableSpan
import android.view.*
import android.webkit.WebSettings
import android.webkit.WebView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentTransaction
import com.gh.base.fragment.BaseDialogFragment
import com.gh.common.util.dip2px
import com.gh.common.view.CustomLinkMovementMethod
import com.gh.gamecenter.R
import com.gh.gamecenter.WebActivity
class PrivacyDialogFragment : BaseDialogFragment() {
// private val mLocalPrivacyHtml = "file:///android_asset/privacy_policies.html"
// private val mLocalRegulationHtml = "file:///android_asset/user_regulation.html"
private val mLocalPrivacyHtml = "file:///android_asset/privacy_policies.html"
private val mLocalRegulationHtml = "file:///android_asset/user_regulation.html"
var containerView: View? = null
var mCallBack: ((isSuccess: Boolean) -> Unit)? = null
@ -34,82 +30,83 @@ class PrivacyDialogFragment : BaseDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// val mWebViewPrivacy = containerView?.findViewById<WebView>(R.id.webView)
// val mWebViewRegulation = containerView?.findViewById<WebView>(R.id.webView2)
//
// mWebViewPrivacy?.isHorizontalScrollBarEnabled = false
// mWebViewRegulation?.isHorizontalScrollBarEnabled = false
val mWebViewPrivacy = containerView?.findViewById<WebView>(R.id.webView)
val mWebViewRegulation = containerView?.findViewById<WebView>(R.id.webView2)
val contentTv = containerView?.findViewById<TextView>(R.id.contentTv)
val descTv = containerView?.findViewById<TextView>(R.id.descTv)
contentTv?.movementMethod = ScrollingMovementMethod()
mWebViewPrivacy?.isHorizontalScrollBarEnabled = false
mWebViewRegulation?.isHorizontalScrollBarEnabled = false
val skipText = SpannableStringBuilder("查看完整版的隐私政策和用户协议")
skipText.setSpan(object : ClickableSpan() {
override fun updateDrawState(ds: TextPaint) {
super.updateDrawState(ds)
ds.color = ContextCompat.getColor(requireContext(), R.color.theme_font)
ds.isUnderlineText = false
val mTitlePrivacyTv = containerView?.findViewById<TextView>(R.id.privacyTitleTv)
val mTitleRegulationTv = containerView?.findViewById<TextView>(R.id.userRegulationTitleTv)
val settingsArrayList = arrayListOf(mWebViewPrivacy?.settings, mWebViewRegulation?.settings)
for (settings in settingsArrayList) {
settings?.javaScriptEnabled = true
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
settings?.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
}
// 避免提示网页有害信息不能访问
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
settings?.safeBrowsingEnabled = false
}
override fun onClick(widget: View) {
val intent = WebActivity.getIntent(requireContext(), context!!.getString(R.string.privacy_policy_url), true)
context?.startActivity(intent)
}
}, skipText.length - 9, skipText.length - 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
// 适配大于屏幕宽度的页面
settings?.useWideViewPort = true
settings?.loadWithOverviewMode = true
settings?.domStorageEnabled = true
skipText.setSpan(object : ClickableSpan() {
override fun updateDrawState(ds: TextPaint) {
super.updateDrawState(ds)
ds.color = ContextCompat.getColor(requireContext(), R.color.theme_font)
ds.isUnderlineText = false
// 自适应屏幕
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
settings?.layoutAlgorithm = WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING
}
}
override fun onClick(widget: View) {
val intent = WebActivity.getIntent(requireContext(), context!!.getString(R.string.disclaimer_url), true)
context?.startActivity(intent)
}
}, skipText.length - 4, skipText.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
descTv?.movementMethod = CustomLinkMovementMethod()
descTv?.text = skipText
// if (NetworkUtils.isNetworkConnected(requireContext())) {
// mWebViewPrivacy?.loadUrl(requireContext().getString(R.string.privacy_policy_url))
// mWebViewRegulation?.loadUrl(requireContext().getString(R.string.user_regulation_url))
// } else {
mWebViewPrivacy?.loadUrl(mLocalPrivacyHtml)
mWebViewRegulation?.loadUrl(mLocalRegulationHtml)
// }
// val mWebViewPrivacy = containerView?.findViewById<WebView>(R.id.webView)
//
// mWebViewPrivacy?.isHorizontalScrollBarEnabled = false
//
// val settingsArrayList = arrayListOf(mWebViewPrivacy?.settings, mWebViewRegulation?.settings)
//
// for (settings in settingsArrayList) {
// settings?.javaScriptEnabled = true
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// settings?.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
// }
// // 避免提示网页有害信息不能访问
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// settings?.safeBrowsingEnabled = false
// }
//
// // 适配大于屏幕宽度的页面
// settings?.useWideViewPort = true
// settings?.loadWithOverviewMode = true
// settings?.domStorageEnabled = true
//
// // 自适应屏幕
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// settings?.layoutAlgorithm = WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING
// val client = object : WebViewClient() {
// override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
// super.onReceivedError(view, request, error)
// if (view == mWebViewPrivacy) {
// view?.loadUrl(mLocalPrivacyHtml)
// } else {
// view?.loadUrl(mLocalRegulationHtml)
// }
// }
// }
// mWebViewPrivacy?.webViewClient = client
// mWebViewRegulation?.webViewClient = client
mTitlePrivacyTv?.setOnClickListener {
mTitlePrivacyTv.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.white))
mTitleRegulationTv?.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.text_F5F5F5))
mWebViewPrivacy?.visibility = View.VISIBLE
mWebViewRegulation?.visibility = View.GONE
}
mTitleRegulationTv?.setOnClickListener {
mTitlePrivacyTv?.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.text_F5F5F5))
mTitleRegulationTv.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.white))
mWebViewPrivacy?.visibility = View.GONE
mWebViewRegulation?.visibility = View.VISIBLE
}
containerView?.findViewById<View>(R.id.refuseTv)?.setOnClickListener {
mCallBack?.invoke(false)
dismissAllowingStateLoss()
dismiss()
}
containerView?.findViewById<View>(R.id.agreeTv)?.setOnClickListener {
mCallBack?.invoke(true)
dismissAllowingStateLoss()
dismiss()
}
}

View File

@ -13,17 +13,9 @@ data class ExposureEntity(
val gameName: String? = "",
val gameVersion: String? = "",
val sequence: Int? = 0,
val outerSequence: Int? = 0,
val platform: String? = "",
var isMirrorData: Boolean = false,
@SerializedName("is_web_download")
var isWebDownload: Boolean = false,
val downloadType: String? = "",
val downloadCompleteType: String? = "",
@SerializedName("display_type")
val displayType: String? = "",
@SerializedName("is_platform_recommend")
val isPlatformRecommend: Boolean? = false,
// 下载地址的 host 和 path
var host: String? = "",

View File

@ -9,12 +9,9 @@ import com.gh.common.exposure.meta.Meta
import com.gh.common.exposure.meta.MetaUtil
import com.gh.common.exposure.time.TimeUtil
import com.gh.common.util.getFirstElementDividedByDivider
import com.gh.download.server.BrowserInstallHelper
import com.gh.gamecenter.entity.GameEntity
import com.lightgame.download.DownloadEntity
import kotlinx.android.parcel.Parcelize
import java.util.*
import kotlin.collections.ArrayList
@Keep
@Parcelize
@ -32,27 +29,19 @@ data class ExposureEvent(
// TODO 建一个 exposureEvent 池规避反复生成对象
@JvmStatic
fun createEvent(gameEntity: GameEntity?,
source: List<ExposureSource>,
eTrace: List<ExposureEvent>? = null,
event: ExposureType = ExposureType.EXPOSURE): ExposureEvent {
fun createEvent(gameEntity: GameEntity?, source: List<ExposureSource>, eTrace: List<ExposureEvent>? = null, event: ExposureType = ExposureType.EXPOSURE): ExposureEvent {
if (gameEntity?.getApk()?.size == 1) {
gameEntity.gameVersion = gameEntity.getApk().elementAtOrNull(0)?.version ?: ""
}
return ExposureEvent(
payload = ExposureEntity(
gameId = gameEntity?.id?.getFirstElementDividedByDivider(DownloadEntity.GAME_ID_DIVIDER),
gameName = eTrace?.firstOrNull()?.payload?.gameName ?: gameEntity?.name?.removeSuffix(Constants.GAME_NAME_DECORATOR),
gameVersion = eTrace?.firstOrNull()?.payload?.gameVersion ?:gameEntity?.gameVersion,
isMirrorData = eTrace?.firstOrNull()?.payload?.isMirrorData ?: gameEntity?.shouldUseMirrorInfo() ?: false,
isWebDownload = BrowserInstallHelper.isUseBrowserToInstallEnabled() && BrowserInstallHelper.shouldUseBrowserToInstall(), // 实时的值,不用从 eTrace 里取
sequence = eTrace?.firstOrNull()?.payload?.sequence ?: gameEntity?.sequence,
outerSequence = eTrace?.firstOrNull()?.payload?.outerSequence ?: gameEntity?.outerSequence,
platform = eTrace?.firstOrNull()?.payload?.platform ?:gameEntity?.platform,
gameId = gameEntity?.id?.getFirstElementDividedByDivider(Constants.GAME_ID_DIVIDER),
gameName = gameEntity?.name?.removeSuffix(Constants.GAME_NAME_DECORATOR),
gameVersion = gameEntity?.gameVersion,
sequence = gameEntity?.sequence,
platform = gameEntity?.platform,
downloadType = gameEntity?.downloadType,
downloadCompleteType = gameEntity?.downloadCompleteType,
displayType = eTrace?.firstOrNull()?.payload?.displayType ?:gameEntity?.displayContent,
isPlatformRecommend = gameEntity?.isPlatformRecommend ?: false,
// ugly
welcomeDialogId = gameEntity?.welcomeDialogId ?: eTrace?.firstOrNull()?.payload?.welcomeDialogId,
welcomeDialogLinkTitle = gameEntity?.welcomeDialogTitle ?: eTrace?.firstOrNull()?.payload?.welcomeDialogLinkTitle),
@ -60,19 +49,5 @@ data class ExposureEvent(
eTrace = eTrace,
event = event).apply { gameEntity?.exposureEvent = this }
}
@JvmStatic
fun createEventWithSourceConcat(gameEntity: GameEntity?,
basicSource: List<ExposureSource>,
source: List<ExposureSource>,
eTrace: List<ExposureEvent>? = null,
event: ExposureType = ExposureType.EXPOSURE): ExposureEvent {
val concatSourceList = ArrayList<ExposureSource>().apply {
addAll(basicSource)
addAll(source)
}
return createEvent(gameEntity, concatSourceList, eTrace, event)
}
}
}

View File

@ -11,16 +11,20 @@ import io.reactivex.functions.Consumer
*/
class ExposureListener(var fragment: Fragment, var exposable: IExposable) : RecyclerView.OnScrollListener() {
val throttleBus: ExposureThrottleBus by lazy { ExposureThrottleBus(Consumer { commitExposure(it) }, Consumer(Throwable::printStackTrace)) }
var throttleBus: ExposureThrottleBus? = null
var layoutManager: LinearLayoutManager? = null
var visibleState: ExposureThrottleBus.VisibleState? = null
init {
fragment.fragmentManager?.registerFragmentLifecycleCallbacks(
object : FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentResumed(fm: FragmentManager, f: Fragment) {
throttleBus = ExposureThrottleBus(Consumer { commitExposure(it) }, Consumer(Throwable::printStackTrace))
}
override fun onFragmentPaused(fm: FragmentManager, f: Fragment) {
visibleState?.let { commitExposure(it) }
throttleBus.clear()
throttleBus?.clear()
}
override fun onFragmentViewDestroyed(fm: FragmentManager, f: Fragment) {
@ -40,7 +44,7 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
layoutManager?.run {
visibleState = ExposureThrottleBus.VisibleState(findFirstVisibleItemPosition(), findLastVisibleItemPosition())
throttleBus.postVisibleState(visibleState!!)
throttleBus?.postVisibleState(visibleState!!)
}
}

View File

@ -1,13 +1,15 @@
package com.gh.common.exposure
import com.aliyun.sls.android.producer.Log
import com.gh.common.loghub.LoghubHelper
import com.aliyun.sls.android.sdk.model.LogGroup
import com.gh.common.exposure.time.TimeUtil
import com.gh.common.util.toJson
import com.gh.common.util.tryWithDefaultCatch
import com.gh.gamecenter.BuildConfig
import com.gh.loghub.LgLOG
import com.gh.loghub.LoghubHelper
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
/**
* A handful tool for committing logs to aliyun loghub.
@ -20,23 +22,26 @@ import java.util.concurrent.ExecutorService
*/
object ExposureManager {
private const val ENDPOINT = "cn-qingdao.log.aliyuncs.com"
private const val PROJECT = "ghzs"
private const val STORE_SIZE = 100
private const val LOG_STORE = BuildConfig.EXPOSURE_REPO
private val loghubHelper = LoghubHelper.getInstance()
// exposureCache 用来过滤掉具有相同 id 的曝光事件,避免重复发送事件
private val exposureSet by lazy { hashSetOf<ExposureEvent>() }
private var exposureExecutor: ExecutorService? = null
private val exposureExecutor by lazy { Executors.newSingleThreadExecutor() }
private val exposureCache by lazy { FixedSizeLinkedHashSet<String>(300) }
private val exposureDao by lazy { ExposureDatabase.buildDatabase(HaloApp.getInstance().application).logHubEventDao() }
@JvmStatic
fun init(excutor: ExecutorService) {
exposureExecutor = excutor
exposureExecutor?.execute {
tryWithDefaultCatch {
val eventList = exposureDao.getAll()
exposureSet.addAll(eventList)
}
fun init() {
loghubHelper.init(HaloApp.getInstance().application, ENDPOINT, PROJECT, LOG_STORE) { TimeUtil.currentTimeMillis() }
exposureExecutor.execute {
val eventList = exposureDao.getAll()
exposureSet.addAll(eventList)
}
}
@ -44,7 +49,7 @@ object ExposureManager {
* Log a single exposure event.
*/
fun log(event: ExposureEvent) {
exposureExecutor?.execute {
exposureExecutor.execute {
try {
if (!exposureCache.contains(event.id)) {
// Catch `android.database.sqlite.SQLiteFullException: database or disk is full` exception.
@ -66,7 +71,7 @@ object ExposureManager {
* Log a collection of exposure event.
*/
fun log(eventList: List<ExposureEvent>) {
exposureExecutor?.execute {
exposureExecutor.execute {
for (event in eventList) {
try {
if (!exposureCache.contains(event.id)) {
@ -89,13 +94,14 @@ object ExposureManager {
* @param forced Ignore all restrictions.
*/
fun commitSavedExposureEvents(forced: Boolean = false) {
exposureExecutor?.execute {
exposureExecutor.execute {
tryWithDefaultCatch {
// TODO 初始化 loghubHelper 去掉这个 tryCatch 块
if (exposureSet.size < STORE_SIZE && !forced || exposureSet.size == 0) return@execute
val exposureList = exposureSet.toList()
uploadExposures(exposureList)
// uploadLogGroup 是一个异步方法LoghubHelper 里面实现了重传功能,所以这里交给它就好了
loghubHelper.uploadLogGroup(buildLogGroup(exposureList))
Utils.log("Exposure", "提交了${exposureList.size}条曝光记录")
exposureSet.removeAll(exposureList)
@ -108,25 +114,31 @@ object ExposureManager {
return jsonWithMultipleBracket.replace("[[", "[").replace("]]", "]")
}
private fun uploadExposures(eventList: List<ExposureEvent>) {
eventList.forEach {
LoghubHelper.uploadLog(buildLog(it), LOG_STORE)
}
private fun buildLogGroup(eventList: List<ExposureEvent>): LogGroup {
val logGroup = LogGroup("sls android", "no ip")
eventList.forEach { logGroup.PutLog(buildLog(it)) }
return logGroup
}
private fun buildLog(event: ExposureEvent) = Log().apply {
putContent("id", event.id)
putContent("payload", event.payload.toJson())
putContent("event", event.event.toString())
putContent("source", eliminateMultipleBrackets(event.source.toJson()))
putContent("meta", event.meta.toJson())
putContent("e-traces", if (event.eTrace != null) {
private fun buildLog(event: ExposureEvent): LgLOG {
val log = LgLOG(TimeUtil.currentTime())
log.PutContent("id", event.id)
log.PutContent("payload", event.payload.toJson())
log.PutContent("event", event.event.toString())
log.PutContent("source", eliminateMultipleBrackets(event.source.toJson()))
log.PutContent("meta", event.meta.toJson())
log.PutContent("e-traces", if (event.eTrace != null) {
eliminateMultipleBrackets(event.eTrace?.toJson() ?: "")
} else "")
logTime = event.time.toLong()
log.PutTime(event.time)
return log
}
class FixedSizeLinkedHashSet<T>(var maxSize: Int) : LinkedHashSet<T>() {
internal class FixedSizeLinkedHashSet<T>(var maxSize: Int) : LinkedHashSet<T>() {
override fun add(element: T): Boolean {
if (size == maxSize) {
pop()

View File

@ -2,39 +2,35 @@ package com.gh.common.exposure
import android.text.TextUtils
import com.g00fy2.versioncompare.Version
import com.gh.common.constant.Constants
import com.gh.common.util.PackageUtils
import com.gh.common.util.toObject
import com.gh.gamecenter.entity.ApkEntity
import com.gh.gamecenter.entity.GameEntity
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
import java.util.*
object ExposureUtils {
private val mDownloadCompleteTraceEventIdSet = ExposureManager.FixedSizeLinkedHashSet<String>(3)
@JvmStatic
fun logADownloadExposureEvent(entity: GameEntity,
platform: String?,
traceEvent: ExposureEvent?,
downloadType: DownloadType): ExposureEvent {
val gameEntity = entity.clone()
gameEntity.id = if (entity.id.contains(DownloadEntity.GAME_ID_DIVIDER)) {
entity.id.split(DownloadEntity.GAME_ID_DIVIDER).toTypedArray()[0]
gameEntity.id = if (entity.id.contains(Constants.GAME_ID_DIVIDER)) {
entity.id.split(Constants.GAME_ID_DIVIDER).toTypedArray()[0]
} else {
entity.id
}
gameEntity.gameVersion = entity.getApk().elementAtOrNull(0)?.version
?: gameEntity.gameVersion
gameEntity.gameVersion = entity.getApk().elementAtOrNull(0)?.version ?: gameEntity.gameVersion
gameEntity.platform = platform
gameEntity.downloadType = downloadType.toString()
val exposureEvent = ExposureEvent.createEvent(gameEntity = gameEntity,
source = traceEvent?.source ?: ArrayList(),
eTrace = ExposureTraceUtils.appendTrace(traceEvent),
event = ExposureType.DOWNLOAD)
if (!TextUtils.isEmpty(entity.id)) {
ExposureManager.log(exposureEvent)
}
ExposureManager.log(exposureEvent)
return exposureEvent
}
@ -49,16 +45,6 @@ object ExposureUtils {
gameEntity.platform = platform
gameEntity.downloadCompleteType = downloadType.toString()
val traceEvent = trace?.toObject<ExposureEvent>()
if (TextUtils.isEmpty(entity.id)) return
// 避免生成 trace 相同的下载完成事件,根据日志看下载完成的同一秒有可能生成两条
if (mDownloadCompleteTraceEventIdSet.contains(traceEvent?.id)) {
return
}
traceEvent?.payload?.gameId?.let { mDownloadCompleteTraceEventIdSet.add(it) }
val exposureEvent = ExposureEvent.createEvent(gameEntity = gameEntity,
source = traceEvent?.source ?: ArrayList(),
eTrace = ExposureTraceUtils.appendTrace(traceEvent),
@ -94,15 +80,6 @@ object ExposureUtils {
}
}
@JvmStatic
fun updateExposureSequence(gameList: List<GameEntity>?) {
gameList?.let {
for ((index, game) in it.withIndex()) {
game.sequence = index
}
}
}
enum class DownloadType {
DOWNLOAD,

View File

@ -8,10 +8,10 @@ import kotlinx.android.parcel.Parcelize
@Parcelize
data class Meta(
val mac: String? = "",
val jnfj: String? = "",
val imei: String? = "",
val model: String? = "",
val manufacturer: String? = "",
val dia: String? = "",
val android_id: String? = "",
val android_sdk: Int? = -1,
val android_version: String? = "",
val network: String? = "",

View File

@ -11,7 +11,6 @@ import android.telephony.TelephonyManager
import android.text.TextUtils
import com.gh.common.constant.Constants
import com.gh.common.util.SPUtils
import com.gh.common.util.tryWithDefaultCatch
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.manager.UserManager
import com.halo.assistant.HaloApp
@ -25,27 +24,14 @@ object MetaUtil {
private var m: Meta? = null
private var imei: String? = null
private var base64EncodedImei: String? = null
private var androidId: String? = null
private var base64EncodedAndroidId: String? = null
private var romName: String? = null
private var romVersion: String? = null
fun refreshMeta() {
if (romName == null) {
tryWithDefaultCatch {
romName = RomIdentifier.getRom().name
romVersion = RomIdentifier.getRom().versionName
}
}
m = Meta(mac = "",
jnfj = getBase64EncodedIMEI(),
imei = getIMEI(),
model = getModel(),
manufacturer = getManufacturer(),
dia = getBase64EncodedAndroidId(),
android_id = getAndroidId(),
android_sdk = getAndroidSDK(),
android_version = getAndroidVersion(),
network = getNetwork(),
@ -56,7 +42,7 @@ object MetaUtil {
appVersion = BuildConfig.VERSION_NAME,
userId = UserManager.getInstance().userId,
exposureVersion = BuildConfig.EXPOSURE_VERSION,
rom = romName + "" + romVersion)
rom = RomIdentifier.getRom().name + "" + RomIdentifier.getRom().versionName)
}
fun getMeta(): Meta {
@ -118,42 +104,6 @@ object MetaUtil {
}
@JvmStatic
fun getBase64EncodedIMEI(): String {
if (imei == null) {
getIMEI()
}
if (TextUtils.isEmpty(base64EncodedImei) && imei != null) {
try {
base64EncodedImei = android.util.Base64.encodeToString(getIMEI().trim().toByteArray(), android.util.Base64.NO_WRAP)
} catch (e: java.lang.Exception) {
e.printStackTrace()
return ""
}
}
return base64EncodedImei ?: ""
}
@JvmStatic
fun getBase64EncodedAndroidId(): String {
if (androidId == null) {
getAndroidId()
}
if (TextUtils.isEmpty(base64EncodedAndroidId) && androidId != null) {
try {
base64EncodedAndroidId = android.util.Base64.encodeToString(getAndroidId().trim().toByteArray(), android.util.Base64.NO_WRAP)
} catch (e: java.lang.Exception) {
e.printStackTrace()
return ""
}
}
return base64EncodedAndroidId ?: ""
}
fun getModel(): String? {
return Build.MODEL
}

View File

@ -1,6 +1,7 @@
package com.gh.common.filter
import android.annotation.SuppressLint
import com.gh.common.AppExecutor
import com.gh.common.constant.Constants
import com.gh.common.util.SPUtils
import com.gh.common.util.debounceActionWithInterval
@ -13,7 +14,6 @@ import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Function
import io.reactivex.schedulers.Schedulers
object RegionSettingHelper {
@ -67,7 +67,7 @@ object RegionSettingHelper {
RetrofitManager.getInstance(HaloApp.getInstance().application)
.sensitiveApi
.getRegionSetting(HaloApp.getInstance().channel)
.subscribeOn(Schedulers.io())
.subscribeOn(AppExecutor.cachedScheduler)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<RegionSetting>() {
override fun onSuccess(data: RegionSetting) {
@ -76,7 +76,7 @@ object RegionSettingHelper {
}
override fun onFailure(exception: Exception) {
SPUtils.getString(SP_SETTING)?.toObject<RegionSetting>()?.let {
SPUtils.getString(SP_SETTING).toObject<RegionSetting>()?.let {
updateSettingsInMemory(it)
}
}

View File

@ -15,7 +15,7 @@ import com.gh.gamecenter.room.converter.*
import com.gh.gamecenter.room.dao.*
import com.halo.assistant.HaloApp
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class], version = 8, exportSchema = false)
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class], version = 7, exportSchema = false)
@TypeConverters(CountConverter::class,
CommunityConverter::class,
TimeConverter::class,
@ -23,10 +23,8 @@ import com.halo.assistant.HaloApp
ThumbnailConverter::class,
TagStyleListConverter::class,
StringArrayListConverter::class,
ListStringConverter::class,
CommunityVideoConverter::class,
UserConverter::class,
ImageInfoConverter::class)
UserConverter::class)
abstract class HistoryDatabase : RoomDatabase() {
@ -71,14 +69,6 @@ abstract class HistoryDatabase : RoomDatabase() {
}
}
val MIGRATION_7_8: Migration = object : Migration(7, 8) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("Alter TABLE ArticleEntity add images TEXT NOT NULL DEFAULT ''")
database.execSQL("Alter TABLE ArticleEntity add imagesInfo TEXT NOT NULL DEFAULT ''")
database.execSQL("Alter TABLE AnswerEntity add imagesInfo TEXT NOT NULL DEFAULT ''")
}
}
val instance by lazy {
Room.databaseBuilder(HaloApp.getInstance().application, HistoryDatabase::class.java, "USER_TRACK_HISTORY_DATABASE")
.addMigrations(MIGRATION_2_3)
@ -86,7 +76,6 @@ abstract class HistoryDatabase : RoomDatabase() {
.addMigrations(MIGRATION_4_5)
.addMigrations(MIGRATION_5_6)
.addMigrations(MIGRATION_6_7)
.addMigrations(MIGRATION_7_8)
.build()
}
}

View File

@ -4,7 +4,6 @@ import com.gh.common.runOnIoThread
import com.gh.common.util.clearHtmlFormatCompletely
import com.gh.common.util.removeInsertedContent
import com.gh.common.util.removeVideoContent
import com.gh.common.util.tryCatchInRelease
import com.gh.gamecenter.entity.*
import com.gh.gamecenter.qa.entity.AnswerDetailEntity
import com.gh.gamecenter.qa.entity.AnswerEntity
@ -15,28 +14,27 @@ object HistoryHelper {
fun insertAnswerEntity(answerDetailEntity: AnswerDetailEntity) {
val answerEntity = convertAnswerDetailToAnswer(answerDetailEntity)
// 偶尔有设备会出现磁盘满了写不进数据库的问题 database or disk is full 异常,毕竟只是插入个本地历史,这里直接捕抓
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.answerDao().addAnswer(answerEntity) } }
runOnIoThread { HistoryDatabase.instance.answerDao().addAnswer(answerEntity) }
}
fun insertArticleEntity(articleDetailEntity: ArticleDetailEntity) {
val articleEntity = convertArticleDetailToArticle(articleDetailEntity)
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.articleDao().addArticle(articleEntity) } }
runOnIoThread { HistoryDatabase.instance.articleDao().addArticle(articleEntity) }
}
@JvmStatic
fun insertGameEntity(gameEntity: GameEntity) {
val historyGameEntity = convertGameEntityToHistoryGameEntity(gameEntity)
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.gameDao().addGame(historyGameEntity) } }
runOnIoThread { HistoryDatabase.instance.gameDao().addGame(historyGameEntity) }
}
@JvmStatic
fun insertGameEntity(updateEntity: GameUpdateEntity) {
val historyGameEntity = convertGameUpdateEntityToHistoryGameEntity(updateEntity)
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.gameDao().addGame(historyGameEntity) } }
runOnIoThread { HistoryDatabase.instance.gameDao().addGame(historyGameEntity) }
}
private fun convertGameUpdateEntityToHistoryGameEntity(updateEntity: GameUpdateEntity): HistoryGameEntity {
private fun convertGameUpdateEntityToHistoryGameEntity(updateEntity: GameUpdateEntity): HistoryGameEntity{
val historyGame = HistoryGameEntity()
historyGame.orderTag = System.currentTimeMillis()
@ -69,49 +67,48 @@ object HistoryHelper {
@JvmStatic
fun insertNewsEntity(newsEntity: NewsEntity) {
newsEntity.orderTag = System.currentTimeMillis()
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.newsDao().addNews(newsEntity) } }
runOnIoThread { HistoryDatabase.instance.newsDao().addNews(newsEntity) }
}
@JvmStatic
fun deleteNewsEntity(newsId: String) {
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.newsDao().deleteNews(NewsEntity().apply { id = newsId }) } }
runOnIoThread { HistoryDatabase.instance.newsDao().deleteNews(NewsEntity().apply { id = newsId }) }
}
@JvmStatic
fun deleteGameEntity(gameId: String) {
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.gameDao().deleteGame(HistoryGameEntity(id = gameId)) } }
runOnIoThread { HistoryDatabase.instance.gameDao().deleteGame(HistoryGameEntity(id = gameId)) }
}
@JvmStatic
fun deleteArticleEntity(articleId: String) {
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.articleDao().deleteArticle(ArticleEntity(id = articleId)) } }
runOnIoThread { HistoryDatabase.instance.articleDao().deleteArticle(ArticleEntity(id = articleId)) }
}
@JvmStatic
fun deleteAnswerEntity(answerId: String) {
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.answerDao().deleteAnswer(AnswerEntity().apply { primaryKey = answerId }) } }
runOnIoThread { HistoryDatabase.instance.answerDao().deleteAnswer(AnswerEntity().apply { primaryKey = answerId }) }
}
@JvmStatic
fun deleteVideoEntity(videoId: String) {
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.videoHistoryDao().deleteVideo(MyVideoEntity().apply { id = videoId }) } }
}
@JvmStatic
fun deleteAttentionVideoRecord() {
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.videoHistoryDao().deleteAttentionVideoRecord() } }
runOnIoThread { HistoryDatabase.instance.videoHistoryDao().deleteVideo(MyVideoEntity().apply { id = videoId }) }
}
@JvmStatic
fun emptyDatabase() {
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.clearAllTables() } }
runOnIoThread { HistoryDatabase.instance.clearAllTables() }
}
private fun convertArticleDetailToArticle(articleDetailEntity: ArticleDetailEntity): ArticleEntity {
val articleEntity = ArticleEntity()
articleEntity.id = articleDetailEntity.id
articleEntity.brief = articleDetailEntity.content.removeVideoContent().removeInsertedContent().clearHtmlFormatCompletely().replace(" +".toRegex(), " ")
articleEntity.brief = articleDetailEntity.content.
removeVideoContent().
removeInsertedContent().
clearHtmlFormatCompletely().
replace(" +".toRegex()," ")
articleEntity.count = articleDetailEntity.count
articleDetailEntity.community.id = articleDetailEntity.communityId
articleEntity.community = articleDetailEntity.community
@ -119,9 +116,6 @@ object HistoryHelper {
articleEntity.title = articleDetailEntity.title
articleEntity.user = articleDetailEntity.user
articleEntity.orderTag = System.currentTimeMillis()
articleEntity.images = articleDetailEntity.images
articleEntity.imagesInfo = articleDetailEntity.imagesInfo
articleEntity.videos = articleDetailEntity.videos
return articleEntity
}
@ -136,11 +130,12 @@ object HistoryHelper {
answerEntity.vote = answerDetailEntity.vote
answerEntity.user = answerDetailEntity.user
answerEntity.orderTag = System.currentTimeMillis()
answerEntity.brief = answerDetailEntity.content.removeVideoContent().removeInsertedContent().clearHtmlFormatCompletely().replace(" +".toRegex(), " ")
answerEntity.brief = answerDetailEntity.content.
removeVideoContent().
removeInsertedContent().
clearHtmlFormatCompletely().
replace(" +".toRegex(), " ")
answerEntity.time = answerDetailEntity.time
answerEntity.images = answerDetailEntity.images
answerEntity.imagesInfo = answerDetailEntity.imagesInfo
answerEntity.videos = answerDetailEntity.videos
return answerEntity
}

View File

@ -1,90 +0,0 @@
package com.gh.common.loghub
import com.aliyun.sls.android.producer.*
import com.gh.common.util.isPublishEnv
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
/**
* 上传阿里云日志辅助类
*/
object LoghubHelper {
private const val ACCESS_KEY_ID = "LTAIV3i0sNc4TPK1"
private const val ACCESS_KEY_SECRET = "8dKtTPeE5WYA6ZCeuIBcIVp7eB0ir4"
private const val ENDPOINT = "cn-qingdao.log.aliyuncs.com"
private const val PROJECT = "ghzs"
private val mClientMaps by lazy { hashMapOf<String, LogProducerClient>() }
fun uploadLog(log: Log, logStore: String) {
getClient(logStore)?.addLog(log)
}
fun uploadLogs(logs: List<Log>, logStore: String) {
logs.forEach {
uploadLog(it, logStore)
}
}
private fun getClient(logStore: String): LogProducerClient? {
if (!mClientMaps.containsKey(logStore)) {
mClientMaps[logStore] = createClient(logStore)
}
return mClientMaps[logStore]
}
private fun createClient(logStore: String): LogProducerClient {
val config = LogProducerConfig(ENDPOINT, PROJECT, logStore, ACCESS_KEY_ID, ACCESS_KEY_SECRET).apply {
// 1 开启断点续传功能, 0 关闭
// 每次发送前会把日志保存到本地的binlog文件只有发送成功才会删除保证日志上传At Least Once
setPersistent(1)
// 持久化的文件名,需要保证文件所在的文件夹已创建。配置多个客户端时,不应设置相同文件
setPersistentFilePath(HaloApp.getInstance().application.filesDir.absolutePath + "/log.dat")
// 是否每次AddLog强制刷新高可靠性场景建议打开
setPersistentForceFlush(1)
// 持久化文件滚动个数建议设置成10。
setPersistentMaxFileCount(10)
// 每个持久化文件的大小建议设置成1-10M
setPersistentMaxFileSize(1024 * 1024)
// 本地最多缓存的日志数不建议超过1M通常设置为65536即可
setPersistentMaxLogCount(65536)
//网络连接超时时间整数单位秒默认为10
setConnectTimeoutSec(15)
//日志发送超时时间整数单位秒默认为15
setSendTimeoutSec(15)
//flusher线程销毁最大等待时间整数单位秒默认为1
setDestroyFlusherWaitSec(2)
//sender线程池销毁最大等待时间整数单位秒默认为1
setDestroySenderWaitSec(2)
//日志时间与本机时间之差,超过该大小后会根据 `drop_delay_log` 选项进行处理。
//一般此种情况只会在设置persistent的情况下出现即设备下线后超过几天/数月启动,发送退出前未发出的日志
//整数单位秒默认为7*24*3600即7天
setMaxLogDelayTime(7 * 24 * 3600)
//对于超过 `max_log_delay_time` 日志的处理策略
//0 不丢弃,把日志时间修改为当前时间; 1 丢弃,默认为 1 (丢弃)
setDropDelayLog(0)
//是否丢弃鉴权失败的日志0 不丢弃1丢弃
//默认为 0即不丢弃
setDropUnauthorizedLog(0)
}
return if (isPublishEnv()) {
LogProducerClient(config)
} else {
return LogProducerClient(config,
LogProducerCallback { resultCode, reqId, errorMessage, logBytes, compressedBytes ->
// resultCode 返回结果代码
// reqId 请求id
// errorMessage 错误信息没有为null
// logBytes 日志大小
// compressedBytes 压缩后日志大小
Utils.log("LoghubHelper -> ${String.format("%s %s %s %s %s",
LogProducerResult.fromInt(resultCode), reqId, errorMessage, logBytes, compressedBytes)}")
})
}
}
}

View File

@ -2,12 +2,14 @@ package com.gh.common.loghub
import android.app.Application
import androidx.annotation.Keep
import com.aliyun.sls.android.producer.Log
import com.aliyun.sls.android.sdk.model.Log
import com.aliyun.sls.android.sdk.model.LogGroup
import com.gh.common.exposure.ExposureEntity
import com.gh.common.exposure.meta.Meta
import com.gh.common.util.tryWithDefaultCatch
import com.gh.loghub.LoghubHelper
import org.json.JSONObject
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
object LoghubUtils {
@ -15,25 +17,22 @@ object LoghubUtils {
private lateinit var mApplication: Application
private val loghubEventSet by lazy { hashSetOf<LoghubEvent>() }
private var loghubEventExecutor: ExecutorService? = null
private val loghubEventExecutor by lazy { Executors.newSingleThreadExecutor() }
private val loghubEventDao by lazy { LoghubDatabase.buildDatabase(mApplication).logHubEventDao() }
@JvmStatic
fun init(application: Application, executor: ExecutorService) {
fun init(application: Application) {
mApplication = application
loghubEventExecutor = executor
loghubEventExecutor?.execute {
tryWithDefaultCatch {
val eventList = loghubEventDao.getAll()
loghubEventSet.addAll(eventList)
}
loghubEventExecutor.execute {
val eventList = loghubEventDao.getAll()
loghubEventSet.addAll(eventList)
}
}
@JvmStatic
fun log(logJson: JSONObject, logStore: String, forcedUpload: Boolean) {
loghubEventExecutor?.execute {
loghubEventExecutor.execute {
try {
val event = LoghubEvent(time = (System.currentTimeMillis() / 1000L).toString(), content = logJson.toString(), logStore = logStore)
loghubEventSet.add(event)
@ -50,7 +49,7 @@ object LoghubUtils {
@JvmStatic
fun log(jsonString: String, logStore: String, forcedUpload: Boolean) {
loghubEventExecutor?.execute {
loghubEventExecutor.execute {
try {
val event = LoghubEvent(time = (System.currentTimeMillis() / 1000L).toString(), content = jsonString, logStore = logStore)
loghubEventSet.add(event)
@ -65,37 +64,49 @@ object LoghubUtils {
}
}
private fun uploadLogGroup(logGroup: LogGroup, logStore: String) {
LoghubHelper.getInstance().uploadLogGroup(logGroup, logStore)
}
fun commitSavedLoghubEvents() {
loghubEventExecutor?.execute {
loghubEventExecutor.execute {
// TODO 初始化 loghubHelper 去掉这个 tryCatch 块
tryWithDefaultCatch {
if (loghubEventSet.isEmpty()) return@execute
val exposureList = loghubEventSet.toList()
uploadEvents()
createLogGroupAndUpload()
loghubEventSet.removeAll(exposureList)
loghubEventDao.deleteMany(exposureList)
}
}
}
private fun uploadEvents() {
private fun createLogGroupAndUpload() {
val logGroupHashMap = hashMapOf<String, LogGroup>()
for (event in loghubEventSet) {
if (!logGroupHashMap.containsKey(event.logStore)) {
logGroupHashMap[event.logStore] = LogGroup("sls android", "no ip")
}
val log = Log()
// 特殊处理以下logStore不需要用content包裹数据
if (event.logStore == "collection" || event.logStore == "common" || event.logStore == "halo-api-device-installed") {
val contentJson = JSONObject(event.content)
for (key in contentJson.keys()) {
log.putContent(key, contentJson.get(key).toString())
log.PutContent(key, contentJson.get(key).toString())
}
} else {
log.putContent("current time ", event.time)
log.putContent("content", event.content)
log.PutContent("current time ", event.time)
log.PutContent("content", event.content)
}
logGroupHashMap[event.logStore]?.PutLog(log)
}
LoghubHelper.uploadLog(log, event.logStore)
for ((logStore, logGroup) in logGroupHashMap) {
uploadLogGroup(logGroup, logStore)
}
}

View File

@ -4,7 +4,6 @@ import android.content.Context
import android.database.ContentObserver
import android.media.AudioManager
import android.os.Handler
import com.gh.common.util.tryCatchInRelease
class VolumeObserver(var context: Context, handler: Handler, var callback: MuteCallback? = null)
: ContentObserver(handler) {
@ -12,20 +11,14 @@ class VolumeObserver(var context: Context, handler: Handler, var callback: MuteC
init {
val audio = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
// 部分设备的 audioManager getStreamVolume 内部会触发空指针 :(
tryCatchInRelease { previousVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC) }
previousVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC)
}
override fun onChange(selfChange: Boolean) {
super.onChange(selfChange)
val audio = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
var currentVolume = 0
tryCatchInRelease {
// 部分设备(Meizu 7.1.2 M6 Note)的 audioManager getStreamVolume 内部会触发空指针 :(
currentVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC)
}
val currentVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC)
val delta = previousVolume - currentVolume

View File

@ -2,12 +2,10 @@ package com.gh.common.simulator
import android.app.Dialog
import android.content.Context
import android.view.Gravity
import android.view.View
import android.view.Window
import android.widget.ProgressBar
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import com.g00fy2.versioncompare.Version
@ -15,6 +13,7 @@ import com.gh.common.AppExecutor.uiExecutor
import com.gh.common.constant.Constants
import com.gh.common.dialog.TrackableDialog
import com.gh.common.util.*
import com.gh.common.util.PackageInstaller.getDownloadPath
import com.gh.download.DownloadManager
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.ApkEntity
@ -23,7 +22,6 @@ import com.gh.gamecenter.entity.TrackableEntity
import com.halo.assistant.HaloApp
import com.lightgame.download.*
import com.lightgame.utils.Utils
import java.lang.ref.WeakReference
import java.text.DecimalFormat
class SimulatorDownloadManager private constructor() {
@ -35,7 +33,6 @@ class SimulatorDownloadManager private constructor() {
private var appProgressFilling: View? = null
private var appProgressAnchor: View? = null
private var downloadDialog: Dialog? = null
private var mContextRef: WeakReference<Context>? = null
private var simulatorLocation: SimulatorLocation? = null
private var simulator: SimulatorEntity? = null
@ -73,10 +70,7 @@ class SimulatorDownloadManager private constructor() {
val startTime = downloadEntity.getMetaExtra(Constants.SIMULATOR_DOWNLOAD_START_TIME)
LogUtils.uploadSimulatorDownload("simulator_download_complete", fileName, simulator?.id, downloadEntity.name, gameId, locationStr, downloadType, startTime)
DownloadManager.getInstance(HaloApp.getInstance().application).cancel(downloadEntity.url, false, true)
val activity = mContextRef?.get() as? AppCompatActivity
if (activity?.isFinishing == false) {
downloadDialog?.dismiss()
}
downloadDialog?.dismiss()
}
DownloadStatus.neterror == downloadEntity.status -> {
ToastUtils.showToast("网络不稳定,下载任务已暂停")
@ -99,9 +93,7 @@ class SimulatorDownloadManager private constructor() {
showDownloadDialog(context, simulator, location, "", "", null)
}
fun showDownloadDialog(context: Context?, simulator: SimulatorEntity?, location: SimulatorLocation, gameId: String = "", gameName: String = "", cancelCallback: (() -> Unit)? = null) {
if (context == null) return
mContextRef = WeakReference(context)
fun showDownloadDialog(context: Context, simulator: SimulatorEntity?, location: SimulatorLocation, gameId: String = "", gameName: String = "", cancelCallback: (() -> Unit)? = null) {
this.simulatorLocation = location
this.simulator = simulator
this.gameId = gameId
@ -124,8 +116,8 @@ class SimulatorDownloadManager private constructor() {
key = if (shouldShowUpdate && isInstalled) "更新弹窗" else "下载弹窗",
logShowEvent = true
)
DialogUtils.showNewAlertDialog(context, title, message, negativeText, positiveText, trackableEntity, Gravity.LEFT, false, {
if (shouldShowUpdate && isInstalled) {
DialogUtils.showNewAlertDialog(context, title, message, negativeText, positiveText, trackableEntity, {
if (shouldShowUpdate && isInstalled){
cancelCallback?.invoke()
MtaHelper.onEvent(trackableEntity.event, trackableEntity.key, "点击下次再说")
}
@ -160,10 +152,7 @@ class SimulatorDownloadManager private constructor() {
view.findViewById<View>(R.id.app_tv_cancel).setOnClickListener {
DownloadManager.getInstance(context).pause(simulator?.apk?.url)
MtaHelper.onEvent("模拟器下载", "下载中弹窗", "点击关闭")
val activity = mContextRef?.get() as? AppCompatActivity
if (activity?.isFinishing == false) {
downloadDialog?.dismiss()
}
downloadDialog?.dismiss()
}
downloadDialog?.setOnDismissListener {
@ -194,7 +183,6 @@ class SimulatorDownloadManager private constructor() {
DownloadManager.getInstance(context).pauseAll()
val entity = DownloadManager.getInstance(context).getDownloadEntityByUrl(apkEntity.url)
HaloApp.put(simulator.name, simulator)
if (entity != null) {
when (entity.status) {
DownloadStatus.pause, DownloadStatus.subscribe,
@ -214,18 +202,16 @@ class SimulatorDownloadManager private constructor() {
private fun createDownload(context: Context, apkEntity: ApkEntity, simulator: SimulatorEntity) {
DownloadManager.getInstance(context).addObserver(dataWatcher)
val downloadId = PackageInstaller.createDownloadId(simulator.name)
val downloadEntity = DownloadEntity()
downloadEntity.url = apkEntity.url
downloadEntity.name = simulator.name
downloadEntity.path = PackageInstaller.getDownloadPathWithId(downloadId, apkEntity.format)
downloadEntity.path = getDownloadPath(simulator.name, apkEntity.format)
downloadEntity.platform = apkEntity.getPlatform()
downloadEntity.packageName = apkEntity.packageName
downloadEntity.versionName = apkEntity.version
downloadEntity.addMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE, Constants.SIMULATOR_DOWNLOAD)
downloadEntity.addMetaExtra(Constants.SIMULATOR_DOWNLOAD_START_TIME, (System.currentTimeMillis() / 1000).toString())
downloadEntity.addMetaExtra(Constants.DOWNLOAD_ID, downloadId)
uiExecutor.executeWithDelay(Runnable { DownloadManager.getInstance(context).add(downloadEntity) }, 200)
val locationStr = if (simulatorLocation == SimulatorLocation.LAUNCH) "${simulatorLocation?.value}${gameName}" else simulatorLocation?.value

View File

@ -3,29 +3,24 @@ package com.gh.common.simulator
import android.annotation.SuppressLint
import android.content.ActivityNotFoundException
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import android.text.TextUtils
import com.g00fy2.versioncompare.Version
import com.gh.common.util.*
import com.gh.download.DownloadManager
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.entity.SimulatorGameRecordEntity
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.retrofit.BiResponse
import com.gh.gamecenter.retrofit.EmptyResponse
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.room.AppDatabase
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadDao
import com.lightgame.download.DownloadEntity
import com.lightgame.download.FileUtils
import com.lightgame.utils.AppManager
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import java.io.ByteArrayOutputStream
import java.io.File
@ -38,7 +33,7 @@ object SimulatorGameManager {
@JvmStatic
fun deleteLocalGames(names: List<String>) {
val downloadEntityList = DownloadManager.getInstance(HaloApp.getInstance().application).allDownloadEntity
val downloadEntityList = DownloadDao.getInstance(HaloApp.getInstance().application).all
names.forEach { name ->
val downloadEntity = downloadEntityList.find { it.name == name }
if (downloadEntity != null) {
@ -53,7 +48,7 @@ object SimulatorGameManager {
@JvmStatic
fun deleteLocalGame(name: String) {
val downloadEntityList = DownloadManager.getInstance(HaloApp.getInstance().application).allDownloadEntity
val downloadEntityList = DownloadDao.getInstance(HaloApp.getInstance().application).all
val downloadEntity = downloadEntityList.find { it.name == name }
if (downloadEntity != null) {
val file = File(downloadEntity.path)
@ -95,62 +90,31 @@ object SimulatorGameManager {
}
}
@SuppressLint("CheckResult")
private fun jumpToSimulator(downloadEntity: DownloadEntity, gameEntity: GameEntity) {
Single.just(gameEntity.icon ?: "")
.flatMap {
getBitmapFormCache(it)
}.map {
BitmapUtils.compressBitmap(it, 100)
}.map {
val baos = ByteArrayOutputStream()
it.compress(Bitmap.CompressFormat.WEBP, 100, baos)
baos.toByteArray()
}
.compose(singleToMain())
.subscribe({
val intent = Intent()
intent.data = Uri.fromFile(File(downloadEntity.path))
if (gameEntity.simulatorType == "FBA" || gameEntity.simulatorType == "FBN") {
val apkEntity = gameEntity.getApk()[0]
intent.putExtra("rom_name", apkEntity.packageName)
}
intent.putExtra("default_path", downloadEntity.path.substring(0, downloadEntity.path.lastIndexOf('/')))
intent.putExtra("game_type", gameEntity.simulatorType)
intent.putExtra("title", downloadEntity.name)
intent.putExtra("icon", gameEntity.icon ?: "")
intent.putExtra("iconStream", it)
intent.putExtra("meta", LogUtils.getMetaObject().toString())
intent.putExtra("simulatorId", gameEntity.simulator?.id)
intent.putExtra("simulatorName", gameEntity.simulator?.name)
intent.putExtra("gameId", gameEntity.id)
val destActivity = "com.gh.emu.RequestPermissionActivity"
intent.setClassName(gameEntity.simulator?.apk?.packageName ?: "", destActivity)
try {
AppManager.getInstance().recentActiveActivity?.startActivity(intent)
} catch (e: ActivityNotFoundException) {
ToastUtils.showToast("模拟器安装错误")
}
recordPlaySimulatorGames(gameEntity.id)
}, {
ToastUtils.showToast("跳转失败")
})
}
private fun getBitmapFormCache(url: String): Single<Bitmap> {
return Single.create {
ImageUtils.getBitmap(url, object : BiCallback<Bitmap, Boolean> {
override fun onFirst(first: Bitmap) {
it.onSuccess(first)
}
override fun onSecond(second: Boolean) {
it.onError(Throwable("获取bitmap失败"))
}
})
val intent = Intent()
intent.data = Uri.fromFile(File(downloadEntity.path))
if (gameEntity.simulatorType == "FBA") {
val apkEntity = gameEntity.getApk()[0]
intent.putExtra("rom_name", apkEntity.packageName)
}
intent.putExtra("default_path", downloadEntity.path.substring(0, downloadEntity.path.lastIndexOf('/')))
intent.putExtra("game_type", gameEntity.simulatorType)
intent.putExtra("title", downloadEntity.name)
intent.putExtra("icon", gameEntity.icon ?: "")
intent.putExtra("meta", LogUtils.getMetaObject().toString())
intent.putExtra("simulatorId", gameEntity.simulator?.id)
intent.putExtra("simulatorName", gameEntity.simulator?.name)
intent.putExtra("gameId", gameEntity.id)
val destActivity = "com.gh.emu.RequestPermissionActivity"
intent.setClassName(gameEntity.simulator?.apk?.packageName ?: "", destActivity)
try {
AppManager.getInstance().recentActiveActivity.startActivity(intent)
} catch (e: ActivityNotFoundException) {
ToastUtils.showToast("模拟器安装错误")
}
recordPlaySimulatorGames(gameEntity.id)
}
@ -159,42 +123,16 @@ object SimulatorGameManager {
*/
@SuppressLint("CheckResult")
@JvmStatic
fun recordDownloadSimulatorGames(gameId: String, type: String) {
fun recordDownloadSimulatorGames(gameId: String) {
val requestMap = hashMapOf<String, Any>()
requestMap["game_id"] = gameId
requestMap["package"] = "-"
val body = requestMap.createRequestBodyAny()
RetrofitManager.getInstance(HaloApp.getInstance().application).api
.downloadSimulatorGames(HaloApp.getInstance().gid, body)
.compose(singleToMain())
.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {
refreshSimulatorGame(gameId, type)
}
})
}
@SuppressLint("CheckResult")
private fun refreshSimulatorGame(gameId: String, type: String) {
val simulatorGameDao = AppDatabase.getInstance(HaloApp.getInstance()).simulatorGameDao()
RetrofitManager.getInstance(HaloApp.getInstance().application).api
.getSimulatorGames(HaloApp.getInstance().gid, 1, getFilter(type))
.compose(singleToMain())
.subscribe(object : BiResponse<List<GameEntity>>() {
override fun onSuccess(data: List<GameEntity>) {
val simulatorGameRecordList = ArrayList<SimulatorGameRecordEntity>()
data.forEach {
val entity = it.convertSimulatorGameRecordEntity()
entity.isRecentlyPlayed = it.id == gameId
simulatorGameRecordList.add(entity)
}
simulatorGameDao.addSimulatorGameList(simulatorGameRecordList)
}
})
}
private fun getFilter(type: String): String {
return UrlFilterUtils.getFilterQuery("type", type)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(EmptyResponse())
}
/**
@ -209,7 +147,8 @@ object SimulatorGameManager {
val body = requestMap.toRequestBody()
RetrofitManager.getInstance(HaloApp.getInstance().application).api
.postPlayedGame(UserManager.getInstance().userId, body)
.compose(singleToMain())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(EmptyResponse())
}
}
@ -250,7 +189,6 @@ object SimulatorGameManager {
/**
* 批量删除设备下载模拟器游戏的记录
*/
@JvmStatic
@SuppressLint("CheckResult")
fun deleteSimulatorGames(gameIds: List<String>, callback: () -> Unit) {
val requestMap = hashMapOf<String, Any>()

View File

@ -80,7 +80,7 @@ class ExampleAdapter(context: Context) : ListAdapter<AnswerEntity>(context), ISy
ItemViewType.ITEM_FOOTER -> {
val footerViewHolder = holder as FooterViewHolder
footerViewHolder.initItemPadding()
footerViewHolder.initFooterViewHolder(mIsLoading, mIsNetworkError, mIsOver)
footerViewHolder.initFooterViewHolder(mIsLoading, mIsNetworkError, mIsOver, R.string.ask_loadover_hint)
}
}
}

View File

@ -1,24 +0,0 @@
package com.gh.common.tracker
import android.app.Activity
import android.app.Application
import android.os.Bundle
// TODO SplashActivity 没有回调 onStart 和 onStop
class ActivityLifecycleWatcher(private val mTrack: ITrack) : Application.ActivityLifecycleCallbacks {
override fun onActivityStarted(activity: Activity) {
mTrack.onActivityStarted(activity)
}
override fun onActivityStopped(activity: Activity) {
mTrack.onActivityStopped(activity)
}
override fun onActivityDestroyed(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
override fun onActivityResumed(activity: Activity) {}
}

View File

@ -1,72 +0,0 @@
package com.gh.common.tracker
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import java.util.*
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicLong
import kotlin.concurrent.fixedRateTimer
/**
* 应用声明周期观察者
*/
class AppLifecycleWatcher(private val mTrack: ITrack) : DefaultLifecycleObserver {
private var mWatchVisibleCount = 0 // 检查是否满足上传可见的次数
private val mLastVisibleTime by lazy { AtomicLong(0L) } // 最后可见时间
private val mIsVisible by lazy { AtomicBoolean(false) } // 当前是否可见
private val mWatchInterval by lazy { AtomicLong(MIN_WATCH_VISIBLE_INTERVAL) } // 与上次上报可见的间隔时间
init {
fixedRateTimer(FIXED_RATE_TIMER_NAME, initialDelay = MIN_WATCH_VISIBLE_INTERVAL, period = MIN_WATCH_VISIBLE_INTERVAL) {
if (mIsVisible.get()) {
// 单位间隔发送
val meetLogVisibleInterval = (mWatchVisibleCount++) * MIN_WATCH_VISIBLE_INTERVAL == mWatchInterval.get()
val equalToMinVisibleInterval = mWatchInterval.get() == MIN_WATCH_VISIBLE_INTERVAL
val equalToMaxVisibleInterval = mWatchInterval.get() == MAX_WATCH_VISIBLE_INTERVAL
if (meetLogVisibleInterval || equalToMinVisibleInterval) {
// 上报完重置计数
mWatchVisibleCount = 0
mTrack.onAppVisible(mWatchInterval.get() / 1000)
if (!equalToMaxVisibleInterval) {
mWatchInterval.set(mWatchInterval.get() * 2) // 间隔递增两倍
}
}
}
}
}
override fun onStart(owner: LifecycleOwner) {
super.onStart(owner)
if (mLastVisibleTime.get() == 0L
|| (mLastVisibleTime.get() + SESSION_ALIVE_INTERVAL) < System.currentTimeMillis() / 1000) {
mTrack.onSessionChanged(UUID.randomUUID().toString())
}
mIsVisible.set(true)
mTrack.onAppStarted()
}
override fun onStop(owner: LifecycleOwner) {
super.onStop(owner)
mIsVisible.set(false)
mLastVisibleTime.set(System.currentTimeMillis() / 1000)
mWatchInterval.set(MIN_WATCH_VISIBLE_INTERVAL)
mTrack.onAppStopped()
}
companion object {
private const val FIXED_RATE_TIMER_NAME = "APP_TRACKER_TIMER"
private const val SESSION_ALIVE_INTERVAL = 30L // 30s
private const val MIN_WATCH_VISIBLE_INTERVAL = 5000L // 5s
private const val MAX_WATCH_VISIBLE_INTERVAL = 320000L // 320s
}
}

View File

@ -1,8 +0,0 @@
package com.gh.common.tracker
import androidx.annotation.Nullable
interface IBusiness {
@Nullable
fun getBusinessId(): Pair<String, String>
}

View File

@ -1,14 +0,0 @@
package com.gh.common.tracker
import android.app.Activity
interface ITrack {
fun onActivityStarted(activity: Activity)
fun onActivityStopped(activity: Activity)
fun onAppStarted()
fun onAppVisible(interval: Long)
fun onAppStopped()
fun onSessionChanged(sessionId: String)
}

View File

@ -1,70 +0,0 @@
package com.gh.common.tracker
import android.app.Activity
import android.app.Application
import androidx.lifecycle.ProcessLifecycleOwner
import java.util.*
object Tracker : ITrack {
private var mSessionId: String = ""
private val mLaunchId by lazy { UUID.randomUUID().toString() }
val sessionId: String
get() = mSessionId
val launchId: String
get() = mLaunchId
private var mIsInitialized = false
@JvmStatic
fun init(application: Application) {
if (mIsInitialized) {
return
}
ProcessLifecycleOwner.get().lifecycle.addObserver(AppLifecycleWatcher(this))
application.registerActivityLifecycleCallbacks(ActivityLifecycleWatcher(this))
mIsInitialized = true
}
override fun onActivityStarted(activity: Activity) {
val businessId = if (activity is IBusiness) activity.getBusinessId() else null
TrackerLogger.logActivityStart(
mLaunchId,
mSessionId,
System.identityHashCode(activity).toString(),
activity::class.java.simpleName,
businessId)
}
override fun onActivityStopped(activity: Activity) {
val businessId = if (activity is IBusiness) activity.getBusinessId() else null
TrackerLogger.logActivityStop(
mLaunchId,
mSessionId,
System.identityHashCode(activity).toString(),
activity::class.java.simpleName,
businessId)
}
override fun onAppStarted() {
TrackerLogger.logAppStart(mLaunchId, mSessionId)
}
override fun onAppVisible(interval: Long) {
TrackerLogger.logAppVisible(mLaunchId, mSessionId, interval)
}
override fun onAppStopped() {
TrackerLogger.logAppStop(mLaunchId, mSessionId)
}
override fun onSessionChanged(sessionId: String) {
mSessionId = sessionId
}
}

View File

@ -1,178 +0,0 @@
package com.gh.common.tracker
import com.gh.common.exposure.meta.MetaUtil
import com.gh.common.exposure.meta.MetaUtil.getBase64EncodedAndroidId
import com.gh.common.exposure.meta.MetaUtil.getBase64EncodedIMEI
import com.gh.common.loghub.LoghubUtils
import com.gh.common.util.tryCatchInRelease
import com.lightgame.utils.Utils
import org.json.JSONException
import org.json.JSONObject
object TrackerLogger {
private const val LOG_STORE = "launch_activity"
fun logAppStart(launchId: String, sessionId: String) {
logAppVisible(launchId, sessionId, 0)
}
fun logAppVisible(launchId: String, sessionId: String, interval: Long) {
val jsonObject = JSONObject()
val payloadObject = JSONObject()
tryCatchInRelease {
payloadObject.put("launch_id", launchId)
payloadObject.put("session_id", sessionId)
payloadObject.put("interval", interval)
jsonObject.put("event", "app_visible")
jsonObject.put("payload", payloadObject)
jsonObject.put("meta", getMeta())
}
uploadToLoghub(jsonObject, true)
}
fun logAppStop(launchId: String, sessionId: String) {
val jsonObject = JSONObject()
val payloadObject = JSONObject()
tryCatchInRelease {
payloadObject.put("launch_id", launchId)
payloadObject.put("session_id", sessionId)
jsonObject.put("event", "app_invisible")
jsonObject.put("payload", payloadObject)
jsonObject.put("meta", getMeta())
}
uploadToLoghub(jsonObject, true)
}
fun logActivityStart(launchId: String,
sessionId: String,
activityId: String,
activityName: String,
activityBusinessId: Pair<String, String>? = null) {
val jsonObject = JSONObject()
val payloadObject = JSONObject()
tryCatchInRelease {
payloadObject.put("launch_id", launchId)
payloadObject.put("session_id", sessionId)
payloadObject.put("activity_id", activityId)
payloadObject.put("activity_name", activityName)
if (activityBusinessId != null) {
payloadObject.put("activity_primary_business_id", activityBusinessId.first)
if (activityBusinessId.second.isNotEmpty()) {
payloadObject.put("activity_secondary_business_id", activityBusinessId.second)
}
}
jsonObject.put("event", "activity_visible")
jsonObject.put("payload", payloadObject)
jsonObject.put("meta", getMeta())
}
uploadToLoghub(jsonObject, false)
}
fun logActivityStop(launchId: String,
sessionId: String,
activityId: String,
activityName: String,
activityBusinessId: Pair<String, String>? = null) {
val jsonObject = JSONObject()
val payloadObject = JSONObject()
tryCatchInRelease {
payloadObject.put("launch_id", launchId)
payloadObject.put("session_id", sessionId)
payloadObject.put("activity_id", activityId)
payloadObject.put("activity_name", activityName)
if (activityBusinessId != null) {
payloadObject.put("activity_primary_business_id", activityBusinessId.first)
if (activityBusinessId.second.isNotEmpty()) {
payloadObject.put("activity_secondary_business_id", activityBusinessId.second)
}
}
jsonObject.put("event", "activity_invisible")
jsonObject.put("payload", payloadObject)
jsonObject.put("meta", getMeta())
}
uploadToLoghub(jsonObject, false)
}
@JvmStatic
fun logHomeTabSelected(launchId: String,
sessionId: String,
tabPosition: Int,
tabContent: String) {
val jsonObject = JSONObject()
val payloadObject = JSONObject()
tryCatchInRelease {
payloadObject.put("launch_id", launchId)
payloadObject.put("session_id", sessionId)
payloadObject.put("tab_position", tabPosition)
payloadObject.put("tab_content", tabContent)
jsonObject.put("event", "home_tab_select")
jsonObject.put("payload", payloadObject)
jsonObject.put("meta", getMeta())
}
uploadToLoghub(jsonObject, false)
}
@JvmStatic
fun logAppLaunch(launchId: String, sessionId: String) {
val jsonObject = JSONObject()
val payloadObject = JSONObject()
tryCatchInRelease {
payloadObject.put("launch_id", launchId)
payloadObject.put("session_id", sessionId)
jsonObject.put("event", "app_launch")
jsonObject.put("payload", payloadObject)
jsonObject.put("meta", getMeta())
}
uploadToLoghub(jsonObject, true)
}
@JvmStatic
fun logAppLaunchSuccessful(launchId: String, sessionId: String) {
val jsonObject = JSONObject()
val payloadObject = JSONObject()
tryCatchInRelease {
payloadObject.put("launch_id", launchId)
payloadObject.put("session_id", sessionId)
jsonObject.put("event", "app_launch_successful")
jsonObject.put("payload", payloadObject)
jsonObject.put("meta", getMeta())
}
uploadToLoghub(jsonObject, true)
}
private fun uploadToLoghub(jsonObject: JSONObject, uploadImmediately: Boolean) {
jsonObject.put("timestamp", System.currentTimeMillis() / 1000)
Utils.log("Tracker -> $jsonObject")
LoghubUtils.log(jsonObject, LOG_STORE, uploadImmediately)
}
private fun getMeta(): JSONObject {
val (_, _, model, manufacturer, _, _, android_version, network, _, gid, _, channel, appVersion, userId) = MetaUtil.getMeta()
val metaObject = JSONObject()
try {
metaObject.put("dia", getBase64EncodedAndroidId())
metaObject.put("android_version", android_version)
metaObject.put("app_version", appVersion)
metaObject.put("channel", channel)
metaObject.put("gid", gid)
metaObject.put("jnfj", getBase64EncodedIMEI())
metaObject.put("manufacturer", manufacturer)
metaObject.put("model", model)
metaObject.put("network", network)
metaObject.put("user_id", userId)
} catch (e: JSONException) {
e.printStackTrace()
}
return metaObject
}
}

View File

@ -1,14 +1,7 @@
package com.gh.common.util
import android.annotation.SuppressLint
import androidx.lifecycle.MutableLiveData
import com.gh.common.constant.Config
import com.gh.gamecenter.entity.SettingsEntity
import com.gh.gamecenter.entity.StartupAdEntity
import com.gh.gamecenter.retrofit.BiResponse
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers
object AdHelper {
@ -19,28 +12,6 @@ object AdHelper {
const val LOCATION_DISCOVER = "discover"
const val LOCATION_SIMULATOR_GAME = "simulator_game"
@JvmField
var startupAd = MutableLiveData<StartupAdEntity>()
@JvmStatic
@SuppressLint("CheckResult")
fun getStartUpAd() {
if (!NetworkUtils.isNetworkConnected(HaloApp.getInstance())) {
startupAd.postValue(null)
return
}
RetrofitManager.getInstance(HaloApp.getInstance())
.api
.getSplashAd(HaloApp.getInstance().channel)
.subscribeOn(Schedulers.io())
.subscribe(object : BiResponse<StartupAdEntity>() {
override fun onSuccess(data: StartupAdEntity) {
startupAd.postValue(data)
}
})
}
fun getAd(location: String): SettingsEntity.AD? {
val adList = Config.getSettings()?.adList ?: return null

View File

@ -333,19 +333,14 @@ public class BitmapUtils {
}
/**
* 压缩图片
*
* @param bitmap
* @param compressSize 压缩大小(单位k)
*/
public static Bitmap compressBitmap(Bitmap bitmap, int compressSize) {
public static Bitmap compressBitmap(Bitmap bitmap) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Matrix matrix = new Matrix();
Bitmap result = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
result.compress(Bitmap.CompressFormat.WEBP, 100, bos);
while (bos.toByteArray().length > compressSize * 1024) {
while (bos.toByteArray().length > 400 * 1024) {
System.out.println(bos.toByteArray().length);
matrix.setScale(0.9f, 0.9f);
result = Bitmap.createBitmap(result, 0, 0, result.getWidth(), result.getHeight(), matrix, true);
bos.reset();

View File

@ -1,14 +1,16 @@
package com.gh.common.util;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import com.gh.common.constant.Constants;
import com.gh.common.avoidcallback.Callback;
import com.gh.gamecenter.LoginActivity;
import com.gh.gamecenter.manager.UserManager;
import com.lightgame.utils.Utils;
import org.jetbrains.annotations.Nullable;
/**
* Created by khy on 28/06/17.
@ -22,15 +24,11 @@ public class CheckLoginUtils {
LogUtils.login("dialog", null, entrance);
LogUtils.login("activity", null, entrance);
if (SPUtils.getBoolean(Constants.SP_HAS_GET_PHONE_INFO) || NetworkUtils.isOpenMobileData(context)) {
QuickLoginHelper.startLogin(context, entrance);
} else {
// 有可能App未启动
Bundle bundle = new Bundle();
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance);
bundle.putString(EntranceUtils.KEY_TO, LoginActivity.class.getName());
EntranceUtils.jumpActivity(context, bundle);
}
// 有可能App未启动
Bundle bundle = new Bundle();
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance);
bundle.putString(EntranceUtils.KEY_TO, LoginActivity.class.getName());
EntranceUtils.jumpActivity(context, bundle);
} else {
if (listener != null) {
listener.onLogin();

View File

@ -33,7 +33,6 @@ object CommentHelper {
showConversation: Boolean,
articleId: String,
communityId: String,
isShowTop: Boolean = false,
ignoreModerator: Boolean = false,
listener: OnCommentOptionClickListener?) {
showCommentOptions(view = view,
@ -41,7 +40,6 @@ object CommentHelper {
showConversation = showConversation,
articleId = articleId,
communityId = communityId,
isShowTop = isShowTop,
ignoreModerator = ignoreModerator,
listener = listener)
}
@ -81,16 +79,11 @@ object CommentHelper {
communityId: String? = null,
answerId: String? = null,
videoId: String? = null,
isShowTop: Boolean = false,
ignoreModerator: Boolean = false,
isVideoAuthor: Boolean = false,
listener: OnCommentOptionClickListener? = null) {
val context = view.context
val dialogOptions = ArrayList<String>()
if (isShowTop && articleId != null && commentEntity.me?.isArticleOrAnswerAuthor == true) {
dialogOptions.add(if (commentEntity.isTop) "取消置顶" else "置顶")
}
dialogOptions.add("复制")
if (commentEntity.user.id != UserManager.getInstance().userId) {
dialogOptions.add("投诉")
@ -118,13 +111,13 @@ object CommentHelper {
}
val inflater = LayoutInflater.from(context)
val layout = inflater.inflate(R.layout.layout_popup_container, null)
val layout = inflater.inflate(R.layout.comment_more_option, null)
val popupWindow = BugFixedPopupWindow(layout,
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT)
val container = layout.findViewById<LinearLayout>(R.id.container)
for (text in dialogOptions) {
val item = inflater.inflate(R.layout.layout_popup_option_item, container, false)
val item = inflater.inflate(R.layout.comment_more_option_item, container, false)
container.addView(item)
val hitText = item.findViewById<TextView>(R.id.hint_text)

View File

@ -2,6 +2,7 @@ package com.gh.common.util;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.ClipboardManager;
import android.content.Context;
import android.graphics.Color;
import android.text.TextUtils;
@ -11,9 +12,6 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.gh.gamecenter.CommentDetailActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.adapter.viewholder.CommentViewHolder;
@ -41,6 +39,8 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;
@ -334,16 +334,15 @@ public class CommentUtils {
});
});
}
public static void voteVideoComment(final Context context,
String answerId,
String articleId,
String articleCommunityId,
String videoId,
final CommentEntity commentEntity,
final TextView commentLikeCountTv,
final ImageView commentLikeIv,
final OnVoteListener listener) {
String answerId,
String articleId,
String articleCommunityId,
String videoId,
final CommentEntity commentEntity,
final TextView commentLikeCountTv,
final ImageView commentLikeIv,
final OnVoteListener listener) {
String entrance = "视频流-评论-点赞";
CheckLoginUtils.checkLogin(context, entrance, () -> {
@ -390,10 +389,10 @@ public class CommentUtils {
}
public static void unVoteVideoComment(final Context context,
String videoId,
final CommentEntity commentEntity,
final TextView commentLikeCountTv,
final ImageView commentLikeIv) {
String videoId,
final CommentEntity commentEntity,
final TextView commentLikeCountTv,
final ImageView commentLikeIv) {
String entrance = "视频流-评论-取消点赞";
CheckLoginUtils.checkLogin(context, entrance, () -> {
RetrofitManager.getInstance(context).getApi()
@ -435,10 +434,10 @@ public class CommentUtils {
holder.commentLikeIv.setImageResource(R.drawable.comment_vote_unselect);
if (userDataEntity == null || !userDataEntity.isCommentOwner()) {
if (holder.replyLine != null) holder.replyLine.setVisibility(View.VISIBLE);
holder.replyLine.setVisibility(View.VISIBLE);
holder.commentReply.setVisibility(View.VISIBLE);
} else {
if (holder.replyLine != null) holder.replyLine.setVisibility(View.GONE);
holder.replyLine.setVisibility(View.GONE);
holder.commentReply.setVisibility(View.GONE);
}
@ -530,7 +529,10 @@ public class CommentUtils {
//复制文字
public static void copyText(String copyContent, Context context) {
ExtensionsKt.copyTextAndToast(copyContent, "复制成功");
ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
cmb.setText(copyContent);
ToastUtils.INSTANCE.showToast("复制成功");
}

View File

@ -35,7 +35,7 @@ public class DataCollectionUtils {
public static void uploadDownload(Context context, DownloadEntity downloadEntity, String status) {
Map<String, Object> map = new HashMap<>();
map.put("game", StringsKt.removeSuffix(downloadEntity.getName(), Constants.GAME_NAME_DECORATOR));
map.put("game_id", downloadEntity.getGameId());
map.put("game_id", downloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER));
if (downloadEntity.isPluggable()) {
map.put("method", "插件化");
map.put("btn_status", "插件化");

View File

@ -52,8 +52,8 @@ public class DataLogUtils {
String user = Installation.getUUID(context);
String channel = HaloApp.getInstance().getChannel();
map.put("version", version);
map.put("resu", user);
map.put("jnfj", MetaUtil.getBase64EncodedIMEI());
map.put("user", user);
map.put("device_id", MetaUtil.getIMEI());
map.put("channel", channel);
Map<String, String> params = new HashMap<>();

View File

@ -3,14 +3,11 @@ package com.gh.common.util;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Build;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import com.gh.common.AppExecutor;
import com.gh.common.constant.Constants;
import com.gh.common.exposure.meta.MetaUtil;
import com.gh.gamecenter.BuildConfig;
import com.gh.gid.GidCallback;
import com.gh.gid.GidHelper;
import com.halo.assistant.HaloApp;
@ -19,9 +16,7 @@ import com.lightgame.utils.Utils;
import java.util.HashMap;
import java.util.Map;
import io.sentry.Sentry;
import io.sentry.android.core.SentryAndroid;
import java.util.Properties;
/**
* Created by LGT on 2016/6/15.
@ -40,10 +35,6 @@ public class DataUtils {
if (CommonDebug.IS_DEBUG) {
return;
}
// 初始化 Sentry 约占用 90ms这里切换到子线程初始化
AppExecutor.getIoExecutor().execute(() -> initSentry(context, channel));
//TalkingData
// try {
// TCAgent.LOG_ON = false;
@ -112,41 +103,6 @@ public class DataUtils {
// }
}
private static void initSentry(Context context, String channel) {
SentryAndroid.init(context, options -> {
// Sentry 疯狂报 ANR (很大一部分还是莫名奇妙的 ANR)严重影响到其它闪退日志的收集
// 这里将它局限到只有官网渠道的包才统计 ANR
if ("GH_206".equals(channel)) {
options.setAnrEnabled(true);
options.setAnrTimeoutIntervalMillis(6000);
} else {
options.setAnrEnabled(false);
}
options.setDebug(BuildConfig.DEBUG);
options.setEnableSessionTracking(true);
options.setEnvironment(BuildConfig.FLAVOR);
options.setDsn("https://6b1caf0d17c1408e8680f3f73ff80bd0@sentry.ghzs.com/22");
options.setBeforeSend((event, hint) -> {
if (BuildConfig.DEBUG) {
return null;
} else {
return event;
}
});
});
Sentry.configureScope(scope -> {
if (BuildConfig.BUILD_TIME != 0L) {
scope.setTag("alias", "内测版" + BuildConfig.VERSION_NAME);
} else {
scope.setTag("alias", "正式版" + BuildConfig.VERSION_NAME);
scope.setTag("channel", channel);
}
});
}
// MTA ->【次数统计】Key-Value参数的事件
public static void onMtaEvent(Context context, String eventId, String... kv) {
@ -183,8 +139,8 @@ public class DataUtils {
}
public static void onEvent(Context var0, String var1, String var2) {
// Properties prop = new Properties();
// prop.setProperty(var1, var2);
Properties prop = new Properties();
prop.setProperty(var1, var2);
// StatService.trackCustomKVEvent(var0, var1, prop);
}
@ -205,64 +161,64 @@ public class DataUtils {
}
public static void onEvent(Context var0, String var1, String var2, Map<String, Object> var3) {
// Properties prop = new Properties();
// prop.setProperty("label", var2);
// for (String key : var3.keySet()) {
// prop.setProperty(key, var3.get(key) + "");
// }
Properties prop = new Properties();
prop.setProperty("label", var2);
for (String key : var3.keySet()) {
prop.setProperty(key, var3.get(key) + "");
}
// StatService.trackCustomKVEvent(var0, var1, prop);
}
public static void trackTimeEvent(Context context, String eventId, int costTime, String... kv) {
//
// Properties prop = new Properties();
// for (int i = 0; i < kv.length; i++) {
// if (i % 2 != 0 || i != 0) {
// String key = kv[i - 1];
// String value = kv[i];
// if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
// prop.setProperty(key, value);
// }
// }
// }
//
// if (prop.size() == 0) return;
//
Properties prop = new Properties();
for (int i = 0; i < kv.length; i++) {
if (i % 2 != 0 || i != 0) {
String key = kv[i - 1];
String value = kv[i];
if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
prop.setProperty(key, value);
}
}
}
if (prop.size() == 0) return;
// StatService.trackCustomKVTimeIntervalEvent(context, costTime, eventId, prop);
}
// 游戏下载
public static void onGameDownloadEvent(Context context, String gameName, String platform, String entrance, String status, String method) {
Map<String, Object> kv = new HashMap<>();
platform = PlatformUtils.getInstance(HaloApp.getInstance().getApplication()).getPlatformName(platform);
kv.put("版本", platform);
kv.put("用户机型", Build.MODEL);
kv.put("设备JNFJ", MetaUtil.getBase64EncodedIMEI());
kv.put("网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
kv.put("光环助手版本", BuildConfig.VERSION_NAME);
kv.put("位置", entrance);
kv.put("类型", method);
kv.put("厂商", Build.MANUFACTURER);
kv.put("Android版本", Build.VERSION.RELEASE);
onEvent(context, "游戏下载", gameName, kv);
Map<String, Object> kv2 = new HashMap<>();
kv2.put("状态", status);
kv2.put("位置", entrance);
if (status.equals("开始")) {
kv2.put("版本", entrance + "-开始");
kv2.put("游戏分平台", gameName + "-" + platform + "-开始");
kv2.put("光环助手版本", BuildConfig.VERSION_NAME + "-开始");
} else {
kv2.put("版本", platform);
kv2.put("游戏分平台", gameName + "-" + platform);
kv2.put("光环助手版本", BuildConfig.VERSION_NAME);
}
onEvent(context, "游戏下载位置", gameName, kv2);
// Map<String, Object> kv = new HashMap<>();
//
// platform = PlatformUtils.getInstance(HaloApp.getInstance().getApplication()).getPlatformName(platform);
//
// kv.put("版本", platform);
// kv.put("用户机型", Build.MODEL);
// kv.put("设备IMEI", Util_System_Phone_State.getDeviceId(HaloApp.getInstance().getApplication()));
// kv.put("网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
// kv.put("光环助手版本", BuildConfig.VERSION_NAME);
// kv.put("位置", entrance);
// kv.put("类型", method);
// kv.put("厂商", Build.MANUFACTURER);
// kv.put("Android版本", Build.VERSION.RELEASE);
// onEvent(context, "游戏下载", gameName, kv);
//
// Map<String, Object> kv2 = new HashMap<>();
// kv2.put("状态", status);
// kv2.put("位置", entrance);
//
// if (status.equals("开始")) {
// kv2.put("版本", entrance + "-开始");
// kv2.put("游戏分平台", gameName + "-" + platform + "-开始");
// kv2.put("光环助手版本", BuildConfig.VERSION_NAME + "-开始");
// } else {
// kv2.put("版本", platform);
// kv2.put("游戏分平台", gameName + "-" + platform);
// kv2.put("光环助手版本", BuildConfig.VERSION_NAME);
// }
//
// onEvent(context, "游戏下载位置", gameName, kv2);
}
// 游戏更新

View File

@ -41,11 +41,11 @@ public class DeviceUtils {
context = context.getApplicationContext();
JSONObject object = new JSONObject();
object.put("os", "Android");
object.put("jnfj", MetaUtil.getBase64EncodedIMEI());
object.put("imei", MetaUtil.getIMEI());
object.put("mac", getMac(context));
object.put("model", MODEL);
object.put("manufacturer", MANUFACTURER);
object.put("dia", MetaUtil.getBase64EncodedAndroidId());
object.put("android_id", MetaUtil.getAndroidId());
object.put("android_sdk", Build.VERSION.SDK_INT);
object.put("android_version", android.os.Build.VERSION.RELEASE);
object.put("ip", "");
@ -57,8 +57,8 @@ public class DeviceUtils {
public static JSONObject getUserDevice(Context context) { // 判断新老用户device数据
JSONObject object = new JSONObject();
try {
object.put("JNFJ", MetaUtil.getBase64EncodedIMEI());
object.put("DIA", MetaUtil.getBase64EncodedAndroidId());
object.put("IMEI", MetaUtil.getIMEI());
object.put("ANDROID_ID", MetaUtil.getAndroidId());
object.put("MAC", getMac(context));
// object.put("MTA_ID", StatConfig.getMid(context));
object.put("MANUFACTURER", MANUFACTURER);
@ -258,7 +258,7 @@ public class DeviceUtils {
}
}
public static long getTotalRamSizeOfDevice(Context context) {
public static long getTotalRamSizeOfDevice(Context context) {
ActivityManager actManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
if (actManager != null) {

View File

@ -2,40 +2,39 @@ package com.gh.common.util
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.Window
import android.widget.TextView
import com.gh.common.dialog.TrackableDialog
import com.gh.common.util.DialogUtils.checkDialogContext
import com.gh.gamecenter.AboutActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.databinding.DialogAlertDefaultBinding
object DialogHelper {
/**
* 光环常规弹窗
* Material Design 风格弹窗
*
* extraConfig可选标题居中、内容居中、是否显示关闭按钮以及是否显示正文辅助文本等
*
* uiModificationCallback可用来手动微调样式的回调可使用 binding 来修改颜色、文字大小等
* @param context
* @param title 标题
* @param content 内容
* @param positiveText 确认按钮文本
* @param negativeText 取消按钮文本
* @param positiveClickCallback 确认按钮监听
* @param negativeClickCallback 取消按钮监听
* @param trackMtaEvent 是否记录出现、关闭弹窗MTA事件
* @param mtaEvent MTA 的事件名
* @param mtaKey MTA 的事件 Key
*/
fun showDialog(
context: Context,
title: String,
content: CharSequence,
confirmText: String,
cancelText: String,
confirmClickCallback: (() -> Unit)? = null,
cancelClickCallback: (() -> Unit)? = null,
extraConfig: Config? = null,
uiModificationCallback: ((binding: DialogAlertDefaultBinding) -> Unit)? = null,
trackMtaEvent: Boolean = false,
mtaEvent: String = "",
mtaKey: String = ""): Dialog {
fun showDialog(context: Context,
title: String,
content: CharSequence,
positiveText: String,
negativeText: String,
positiveClickCallback: (() -> Unit)? = null,
negativeClickCallback: (() -> Unit)? = null,
trackMtaEvent: Boolean = false,
mtaEvent: String = "",
mtaKey: String = ""): Dialog {
val solidContext = checkDialogContext(context)
val dialog = if (trackMtaEvent) {
@ -44,58 +43,32 @@ object DialogHelper {
Dialog(solidContext, R.style.GhAlertDialog)
}
val binding = DialogAlertDefaultBinding.inflate(LayoutInflater.from(solidContext))
val contentView = binding.root
binding.contentTv.text = content
binding.titleTv.text = title
val contentView = LayoutInflater.from(solidContext).inflate(R.layout.dialog_alert, null)
val contentTv = contentView.findViewById<TextView>(R.id.dialog_content)
val titleTv = contentView.findViewById<TextView>(R.id.dialog_title)
val negativeTv = contentView.findViewById<TextView>(R.id.dialog_negative)
val positiveTv = contentView.findViewById<TextView>(R.id.dialog_positive)
contentTv.text = content
titleTv.text = title
negativeTv.text = negativeText
positiveTv.text = positiveText
extraConfig?.let {
if (it.hint.isNotEmpty()) {
binding.hintTv.visibility = View.VISIBLE
binding.hintTv.text = it.hint
}
negativeTv.setOnClickListener {
if (trackMtaEvent) MtaHelper.onEvent(mtaEvent, mtaKey, "点击" + negativeText)
if (it.centerTitle) {
binding.titleTv.gravity = Gravity.CENTER
}
if (it.centerContent) {
binding.contentTv.gravity = Gravity.CENTER
}
if (it.showCloseIcon) {
binding.closeContainer.visibility = View.VISIBLE
binding.closeContainer.setOnClickListener { dialog.dismiss() }
}
}
if (cancelText.isEmpty()) {
binding.cancelTv.visibility = View.GONE
binding.centerDivider.visibility = View.GONE
}
binding.cancelTv.text = cancelText
binding.confirmTv.text = confirmText
binding.cancelTv.setOnClickListener {
if (trackMtaEvent) MtaHelper.onEvent(mtaEvent, mtaKey, "点击$cancelText")
cancelClickCallback?.invoke()
negativeClickCallback?.invoke()
dialog.dismiss()
}
binding.confirmTv.setOnClickListener {
if (trackMtaEvent) MtaHelper.onEvent(mtaEvent, mtaKey, "点击$confirmText")
positiveTv.setOnClickListener {
if (trackMtaEvent) MtaHelper.onEvent(mtaEvent, mtaKey, "点击$positiveText")
confirmClickCallback?.invoke()
positiveClickCallback?.invoke()
dialog.dismiss()
}
uiModificationCallback?.invoke(binding)
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
dialog.setContentView(contentView)
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialog.show()
return dialog
}
@ -104,7 +77,6 @@ object DialogHelper {
* For legacy java invocation
*/
@JvmStatic
@Deprecated("Kotlin 中请使用其它方法调用")
fun showDialog(context: Context,
title: String,
content: CharSequence,
@ -115,87 +87,7 @@ object DialogHelper {
trackMtaEvent: Boolean = false,
mtaEvent: String = "",
mtaKey: String = ""): Dialog {
return showDialog(
context = context,
title = title,
content = content,
confirmText = positiveText,
cancelText = negativeText,
confirmClickCallback = { positiveClickCallback.onCallback() },
cancelClickCallback = { negativeClickCallback.onCallback() },
trackMtaEvent = trackMtaEvent,
mtaEvent = mtaEvent,
mtaKey = mtaKey)
return showDialog(context, title, content, positiveText, negativeText, { positiveClickCallback.onCallback() }, { negativeClickCallback.onCallback() }, trackMtaEvent, mtaEvent, mtaKey)
}
@JvmStatic
fun showSignatureConflictDialog(context: Context,
confirmClickCallback: (() -> Unit)? = null) {
showDialog(
context,
"温馨提示",
"检测到安装包与已安装应用的签名不一致,需要卸载后才能安装,是否立即卸载",
"卸载",
"取消",
{ confirmClickCallback?.invoke() },
null,
Config(hint = "注意:卸载会让游戏数据丢失,请提前做好备份"),
{ binding -> binding.hintTv.setTextColor(R.color.theme_font.toColor()) }
)
}
@JvmStatic
fun showPluginDialog(context: Context,
confirmClickCallback: (() -> Unit)? = null) {
MtaHelper.onEvent("插件化", "插件化安装弹窗", "出现弹窗提示")
showDialog(
context,
"插件化安装",
"您将进行插件化安装以实现插件功能,此过程将卸载当前使用的版本并安装插件版本",
"确认,开始插件化",
"取消",
{
confirmClickCallback?.invoke()
MtaHelper.onEvent("插件化", "插件化安装弹窗", "确认并开始")
},
{ MtaHelper.onEvent("插件化", "插件化安装弹窗", "取消") },
Config(hint = "注意:卸载前请妥善保存游戏账号与密码"),
{ binding -> binding.hintTv.setTextColor(R.color.text_FF0000.toColor()) }
)
}
@JvmStatic
fun showUpgradeDialog(context: Context) {
showDialog(
context,
"提示",
"当前版本暂不支持该功能,\n建议您升级到最新版本体验哦",
"检查升级",
"取消",
confirmClickCallback = { context.startActivity(AboutActivity.getIntent(context, true)); },
uiModificationCallback = {
it.titleTv.gravity = Gravity.CENTER
it.contentTv.gravity = Gravity.CENTER
}
)
}
@JvmStatic
fun showDowngradeHintDialog(context: Context,
confirmClickCallback: (() -> Unit)? = null) {
showDialog(
context,
"温馨提示",
"您已安装较高版本,若要安装历史版本需先卸载再安装\n",
"我知道了",
"",
{ confirmClickCallback?.invoke() })
}
data class Config(val hint: String = "",
val showCloseIcon: Boolean = false,
val centerTitle: Boolean = false,
val centerContent: Boolean = false)
}

View File

@ -1,6 +1,5 @@
package com.gh.common.util;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
@ -15,15 +14,12 @@ import android.os.CountDownTimer;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.URLSpan;
import android.text.style.UnderlineSpan;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@ -37,7 +33,6 @@ import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
@ -47,15 +42,11 @@ import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;
import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import com.facebook.drawee.generic.GenericDraweeHierarchy;
import com.facebook.drawee.view.SimpleDraweeView;
import com.gh.common.AppExecutor;
import com.gh.common.constant.Config;
import com.gh.common.dialog.TrackableDialog;
import com.gh.common.view.CustomLinkMovementMethod;
import com.gh.common.view.DrawableView;
import com.gh.common.view.FixLinearLayoutManager;
import com.gh.common.view.LimitHeightLinearLayout;
@ -64,12 +55,7 @@ import com.gh.gamecenter.AboutActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.SuggestionActivity;
import com.gh.gamecenter.adapter.viewholder.PrivacyPolicyItemViewHolder;
import com.gh.gamecenter.databinding.DialogBindPhoneBinding;
import com.gh.gamecenter.databinding.DialogOverseaConfirmationBinding;
import com.gh.gamecenter.databinding.DialogPackageParseErrorBinding;
import com.gh.gamecenter.databinding.DialogQuickLoginPermissionBinding;
import com.gh.gamecenter.databinding.DialogReceiveLibaoSuccessBinding;
import com.gh.gamecenter.databinding.DialogReportReasonBinding;
import com.gh.gamecenter.databinding.ImprintContentItemBinding;
import com.gh.gamecenter.databinding.PrivacyItemBinding;
import com.gh.gamecenter.entity.ApkEntity;
@ -78,7 +64,6 @@ import com.gh.gamecenter.entity.BadgeEntity;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.PrivacyPolicyEntity;
import com.gh.gamecenter.entity.SettingsEntity;
import com.gh.gamecenter.entity.SimpleGameEntity;
import com.gh.gamecenter.entity.TrackableEntity;
import com.gh.gamecenter.suggest.SuggestType;
import com.halo.assistant.HaloApp;
@ -326,6 +311,33 @@ public class DialogUtils {
showCancelListenerDialog(context, "取消关注", content, "确定取消", "暂不取消", listener, cancelListener);
}
public static void showPluginDialog(Context context, final ConfirmListener listener) {
context = checkDialogContext(context);
MtaHelper.onEvent("插件化", "插件化安装弹窗", "出现弹窗提示");
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_plugin, null);
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
negativeTv.setOnClickListener(v -> {
dialog.dismiss();
MtaHelper.onEvent("插件化", "插件化安装弹窗", "取消");
});
positiveTv.setOnClickListener(view -> {
if (listener != null) {
listener.onConfirm();
}
dialog.dismiss();
MtaHelper.onEvent("插件化", "插件化安装弹窗", "确认并开始");
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
}
/**
* ios 风格弹窗
*
@ -338,7 +350,7 @@ public class DialogUtils {
* @param cmListener 确认按钮监听
*/
public static Dialog showNewAlertDialog(Context context, String title, CharSequence message
, String negative, String positive, TrackableEntity trackableEntity, int gravity, boolean shouldShowCloseBtn, final CancelListener clListener, final ConfirmListener cmListener) {
, String negative, String positive, TrackableEntity trackableEntity, final CancelListener clListener, final ConfirmListener cmListener) {
context = checkDialogContext(context);
final Dialog dialog;
if (trackableEntity != null) {
@ -361,9 +373,6 @@ public class DialogUtils {
TextView cancelBtn = contentView.findViewById(R.id.cancel);
TextView confirmBtn = contentView.findViewById(R.id.confirm);
View middleLine = contentView.findViewById(R.id.middle_line);
View closeIv = contentView.findViewById(R.id.closeIv);
titleTv.setGravity(gravity);
contentTv.setGravity(gravity);
titleTv.setText(title);
contentTv.setText(message);
@ -378,8 +387,6 @@ public class DialogUtils {
confirmBtn.setVisibility(View.GONE);
middleLine.setVisibility(View.GONE);
}
closeIv.setVisibility(shouldShowCloseBtn ? View.VISIBLE : View.GONE);
closeIv.setOnClickListener(v -> dialog.dismiss());
cancelBtn.setOnClickListener(v -> {
if (clListener != null) clListener.onCancel();
@ -404,12 +411,7 @@ public class DialogUtils {
public static Dialog showNewAlertDialog(Context context, String title, CharSequence message
, String negative, String positive, final CancelListener clListener, final ConfirmListener cmListener) {
return showNewAlertDialog(context, title, message, negative, positive, null, Gravity.LEFT, false, clListener, cmListener);
}
public static Dialog showNewAlertDialog(Context context, String title, CharSequence message
, String negative, String positive, int gravity, boolean shouldShowCloseBtn, final CancelListener clListener, final ConfirmListener cmListener) {
return showNewAlertDialog(context, title, message, negative, positive, null, gravity, shouldShowCloseBtn, clListener, cmListener);
return showNewAlertDialog(context, title, message, negative, positive, null, clListener, cmListener);
}
/**
@ -786,6 +788,33 @@ public class DialogUtils {
dialog.show();
}
public static void showLowVersionDialog(Context context) {
final Context activityContext = checkDialogContext(context);
final Dialog dialog = new Dialog(activityContext, R.style.GhAlertDialog);
View contentView = LayoutInflater.from(activityContext).inflate(R.layout.dialog_alert, null);
TextView contentTv = contentView.findViewById(R.id.dialog_content);
TextView titleTv = contentView.findViewById(R.id.dialog_title);
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
contentTv.setText("链接超出范围,请检查升级至最新版本的光环助手");
titleTv.setText("提示");
negativeTv.setText("关闭");
positiveTv.setText("检查升级");
negativeTv.setOnClickListener(view -> dialog.dismiss());
positiveTv.setOnClickListener(view -> {
activityContext.startActivity(AboutActivity.getIntent(activityContext, true));
dialog.dismiss();
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
}
public static void showLowSystemVersionDialog(Context context) {
final Context activityContext = checkDialogContext(context);
@ -939,7 +968,7 @@ public class DialogUtils {
public static void showPrivacyPolicyDialog(Context context,
@NonNull PrivacyPolicyEntity entity,
SimpleCallback<Boolean> callback) {
EmptyCallback callback) {
final Context activityContext = checkDialogContext(context);
@ -957,13 +986,13 @@ public class DialogUtils {
WindowManager.LayoutParams params = window.getAttributes();
params.horizontalMargin = 0;
params.width = context.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(40);
// int height = context.getResources().getDisplayMetrics().heightPixels - DisplayUtils.dip2px(120);
// int maxHeight = DisplayUtils.dip2px(446);
// if (height > maxHeight) {
// params.height = maxHeight;
// } else {
// params.height = height;
// }
int height = context.getResources().getDisplayMetrics().heightPixels - DisplayUtils.dip2px(120);
int maxHeight = DisplayUtils.dip2px(446);
if (height > maxHeight) {
params.height = maxHeight;
} else {
params.height = height;
}
window.setAttributes(params);
}
@ -996,6 +1025,8 @@ public class DialogUtils {
hierarchy.setPlaceholderImage(R.drawable.permission_storage);
} else if (position == 1) {
hierarchy.setPlaceholderImage(R.drawable.permission_phone_state);
} else {
hierarchy.setPlaceholderImage(R.drawable.permission_sdk);
}
}
}
@ -1055,31 +1086,19 @@ public class DialogUtils {
title.setText(entity.getTitle());
linkContent.setText(skipText);
linkContent.setMovementMethod(LinkMovementMethod.getInstance());
linkContent.setMovementMethod(new LinkMovementMethod());
topContent.setText(entity.getTopContent());
bottomContent.setText(ExtensionsKt.fromHtml(entity.getBottomContent()));
bottomContent.setMovementMethod(CustomLinkMovementMethod.getInstance());
// Remove underline
Spannable sa = (Spannable) bottomContent.getText();
for (URLSpan u : sa.getSpans(0, sa.length(), URLSpan.class)) {
sa.setSpan(new UnderlineSpan() {
public void updateDrawState(TextPaint tp) {
tp.setUnderlineText(false);
}
}, sa.getSpanStart(u), sa.getSpanEnd(u), 0);
}
bottomContent.setText(entity.getBottomContent());
allowButton.setOnClickListener(view -> {
dialog.dismiss();
callback.onCallback(true);
callback.onCallback();
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击同意");
});
disallowButton.setOnClickListener(v -> {
dialog.dismiss();
callback.onCallback(false);
// showPrivacyPolicyDisallowDialog(activityContext, entity, callback);
showPrivacyPolicyDisallowDialog(activityContext, entity, callback);
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "不同意并退出App");
});
@ -1883,305 +1902,6 @@ public class DialogUtils {
dialog.show();
}
public static Dialog showCancelOrDeleteReservationDialog(Context context, String title, String message
, String positive, String negative, final ConfirmListener cmListener, final CancelListener clListener) {
context = checkDialogContext(context);
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_cancel_reservation, null);
TextView contentTv = contentView.findViewById(R.id.dialog_content);
TextView titleTv = contentView.findViewById(R.id.dialog_title);
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
contentTv.setText(message);
titleTv.setText(title);
negativeTv.setText(negative);
positiveTv.setText(positive);
negativeTv.setOnClickListener(view -> {
if (clListener != null) {
clListener.onCancel();
}
dialog.dismiss();
});
positiveTv.setOnClickListener(view -> {
if (cmListener != null) {
cmListener.onConfirm();
}
dialog.dismiss();
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
Window window = dialog.getWindow();
if (window != null) {
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
WindowManager.LayoutParams params = window.getAttributes();
params.width = context.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(60f);
window.setAttributes(params);
}
return dialog;
}
public static void showEnergyDialog(Context context, String userName, int energy) {
context = checkDialogContext(context);
final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent);
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_energy, null);
((TextView) contentView.findViewById(R.id.userName)).setText("\"" + userName + "\"");
((TextView) contentView.findViewById(R.id.energy)).setText(energy + "");
contentView.findViewById(R.id.dialog_positive).setOnClickListener(v -> {
dialog.dismiss();
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
}
public static void showEnergyTaskNoticeDialog(Context context, String title, String content) {
context = checkDialogContext(context);
final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent);
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_notice, null);
TextView titleTv = contentView.findViewById(R.id.dialog_title);
TextView contentTv = contentView.findViewById(R.id.dialog_content);
TextView okTv = contentView.findViewById(R.id.dialog_ok);
if (title == null) {
titleTv.setVisibility(View.GONE);
} else {
titleTv.setVisibility(View.VISIBLE);
titleTv.setText(title);
}
contentTv.setText(content);
okTv.setTextColor(ContextCompat.getColor(context, R.color.theme_font));
okTv.setOnClickListener(v -> {
dialog.dismiss();
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
}
public static void showSimulatorParseErrorDialog(Context context, String gameId, String gameName, ConfirmListener confirmListener) {
context = checkDialogContext(context);
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
DialogPackageParseErrorBinding binding = DialogPackageParseErrorBinding.inflate(LayoutInflater.from(context), null, false);
Context finalContext = context;
SpannableStringBuilder builder = new SpanBuilder("您也可以点击提交反馈跟我们联系").click(6, 10, R.color.theme_font, true, new Function0<Unit>() {
@Override
public Unit invoke() {
SimpleGameEntity entity = new SimpleGameEntity(gameId, gameName, "");
SuggestionActivity.startSuggestionActivity(finalContext, SuggestType.gameQuestion, "notfound", "模拟器安装包解析错误", entity, "-");
dialog.dismiss();
return null;
}
}).build();
binding.feedbackTv.setText(builder);
binding.feedbackTv.setMovementMethod(new LinkMovementMethod());
binding.cancel.setOnClickListener(v -> {
dialog.dismiss();
});
binding.confirm.setOnClickListener(v -> {
confirmListener.onConfirm();
dialog.dismiss();
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(binding.getRoot());
dialog.show();
Window window = dialog.getWindow();
if (window != null) {
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
WindowManager.LayoutParams params = window.getAttributes();
params.width = context.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(60f);
window.setAttributes(params);
}
}
@SuppressLint("SetTextI18n")
public static void showReportReasonDialog(Context context, ReportReasonCallBack callBack) {
context = checkDialogContext(context);
final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent);
DialogReportReasonBinding binding = DialogReportReasonBinding.inflate(LayoutInflater.from(context));
binding.reasonOne.setOnClickListener(v -> {
dialog.dismiss();
callBack.onResponse(binding.reasonOne.getText().toString(), "");
});
binding.reasonTwo.setOnClickListener(v -> {
dialog.dismiss();
callBack.onResponse(binding.reasonTwo.getText().toString(), "");
});
binding.reasonThree.setOnClickListener(v -> {
dialog.dismiss();
callBack.onResponse(binding.reasonThree.getText().toString(), "");
});
binding.reasonFour.setOnClickListener(v -> {
dialog.dismiss();
callBack.onResponse(binding.reasonFour.getText().toString(), "");
});
binding.reasonOther.setOnClickListener(v -> {
binding.reasonTitle.setText(R.string.report_reason_other_title);
binding.normalReasonContainer.setVisibility(View.GONE);
binding.otherReasonContainer.setVisibility(View.VISIBLE);
});
binding.negativeBtn.setOnClickListener(v -> {
binding.reasonTitle.setText(R.string.report_reason_title);
binding.normalReasonContainer.setVisibility(View.VISIBLE);
binding.otherReasonContainer.setVisibility(View.GONE);
});
binding.positiveBtn.setOnClickListener(v -> {
if (TextUtils.isEmpty(binding.otherReasonEt.getText().toString().trim())) {
ToastUtils.INSTANCE.showToast("请填写举报原因");
} else {
dialog.dismiss();
callBack.onResponse("其它", binding.otherReasonEt.getText().toString());
}
});
Context finalContext = context;
ExtensionsKt.setTextChangedListener(binding.otherReasonEt, (s, start, before, count) -> {
int tvCount = s.length();
if (tvCount >= 500) {
binding.tvCount.setTextColor(ContextCompat.getColor(finalContext, R.color.text_FF4147));
}
binding.tvCount.setText(tvCount + "/500");
return null;
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(binding.getRoot());
dialog.show();
}
public static void showSignSuccessDialog(Context context, ConfirmListener listener) {
context = checkDialogContext(context);
final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent);
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_sign_success, null);
ImageView signBg = contentView.findViewById(R.id.signBg);
RelativeLayout signContainer = contentView.findViewById(R.id.signContainer);
Animation animation1 = AnimationUtils.loadAnimation(context, R.anim.anim_badge_light_bg);
signBg.startAnimation(animation1);
Animation animation2 = AnimationUtils.loadAnimation(context, R.anim.anim_sign_dialog_dismiss);
signContainer.postDelayed(() -> signContainer.startAnimation(animation2), 2000);
signContainer.postDelayed(dialog::dismiss, 3000);
dialog.setOnDismissListener(dialogInterface -> listener.onConfirm());
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
}
public static void showSignRuleDialog(Context context) {
context = checkDialogContext(context);
final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent);
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_sign_rule, null);
contentView.findViewById(R.id.dialog_ok).setOnClickListener(v -> dialog.dismiss());
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
}
public static void showBindPhoneDialog(Context context, ConfirmListener listener) {
context = checkDialogContext(context);
final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent);
DialogBindPhoneBinding binding = DialogBindPhoneBinding.inflate(LayoutInflater.from(context));
binding.positiveTv.setOnClickListener(v -> {
dialog.dismiss();
listener.onConfirm();
});
binding.closeIv.setOnClickListener(v -> {
dialog.dismiss();
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(binding.getRoot());
dialog.show();
}
public static void showReceiveLibaoSuccessDialog(Context context, String title, String des, String libaoCode, ConfirmListener listener) {
context = checkDialogContext(context);
final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent);
DialogReceiveLibaoSuccessBinding binding = DialogReceiveLibaoSuccessBinding.inflate(LayoutInflater.from(context));
binding.title.setText(title);
binding.libaoCodeTv.setText(libaoCode);
binding.desTv.setText(des);
binding.confirm.setOnClickListener(v -> {
dialog.dismiss();
listener.onConfirm();
});
binding.cancel.setOnClickListener(v -> {
dialog.dismiss();
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(binding.getRoot());
dialog.show();
Window window = dialog.getWindow();
if (window != null) {
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
WindowManager.LayoutParams params = window.getAttributes();
params.width = context.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(60f);
window.setAttributes(params);
}
}
public static void showQuickLoginPermissionDialog(Context context, ConfirmListener confirmListener, CancelListener cancelListener) {
context = checkDialogContext(context);
final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent);
DialogQuickLoginPermissionBinding binding = DialogQuickLoginPermissionBinding.inflate(LayoutInflater.from(context));
binding.confirmBtn.setOnClickListener(v -> {
dialog.dismiss();
confirmListener.onConfirm();
});
binding.cancelBtn.setOnClickListener(v -> {
dialog.dismiss();
cancelListener.onCancel();
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(binding.getRoot());
dialog.show();
}
/**
* @param context may be is application context
* @return activity context
@ -2215,7 +1935,4 @@ public class DialogUtils {
void onResponse(boolean isSubscribe);
}
public interface ReportReasonCallBack {
void onResponse(String reason, String desc);
}
}

View File

@ -1,6 +1,5 @@
package com.gh.common.util
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
@ -23,9 +22,7 @@ import com.gh.common.exposure.ExposureType
import com.gh.common.util.EntranceUtils.*
import com.gh.gamecenter.*
import com.gh.gamecenter.amway.AmwayActivity
import com.gh.gamecenter.catalog.CatalogActivity
import com.gh.gamecenter.category.CategoryDirectoryActivity
import com.gh.gamecenter.category2.CategoryV2Activity
import com.gh.gamecenter.download.DownloadFragment.Companion.INDEX_UPDATE
import com.gh.gamecenter.entity.*
import com.gh.gamecenter.eventbus.EBReuse
@ -41,8 +38,6 @@ import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.mygame.PlayedGameActivity
import com.gh.gamecenter.personalhome.UserHomeActivity
import com.gh.gamecenter.personalhome.background.PersonalityBackgroundActivity
import com.gh.gamecenter.personalhome.border.AvatarBorderActivity
import com.gh.gamecenter.qa.CommunityFragment
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity
import com.gh.gamecenter.qa.article.SimpleArticleListActivity
@ -52,19 +47,17 @@ import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity
import com.gh.gamecenter.qa.subject.CommunitySubjectActivity
import com.gh.gamecenter.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.security.BindPhoneActivity
import com.gh.gamecenter.servers.GameServerTestActivity
import com.gh.gamecenter.servers.GameServersActivity
import com.gh.gamecenter.subject.SubjectActivity
import com.gh.gamecenter.suggest.SuggestType
import com.gh.gamecenter.tag.TagsActivity
import com.gh.gamecenter.user.UserViewModel
import com.gh.gamecenter.video.data.VideoDataActivity
import com.gh.gamecenter.video.detail.VideoDetailActivity
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
import com.gh.gamecenter.video.game.GameVideoActivity
import com.gh.gamecenter.video.videomanager.VideoManagerActivity
import com.halo.assistant.HaloApp
import com.lightgame.utils.Util_System_ClipboardManager
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
@ -140,9 +133,7 @@ object DirectUtils {
"server",
"top_game_comment",
"wechat_bind",
"video",
"catalog"
)
"video")
fun directToLinkPage(context: Context,
linkEntity: LinkEntity,
@ -209,10 +200,6 @@ object DirectUtils {
"category", "分类" -> directCategoryDirectory(context, linkEntity.link!!, linkEntity.text!!)
"catalog" -> directCatalog(context, linkEntity.link!!, linkEntity.text!!, entrance, path)
"category_v2" -> directCategoryV2(context, linkEntity.link!!, linkEntity.text!!, entrance, path)
"block", "版块" -> {
if (linkEntity.link.isNullOrEmpty()) return
directToBlock(context,
@ -242,7 +229,7 @@ object DirectUtils {
"libao", "礼包" -> directToGiftDetail(context, linkEntity.link ?: "", entrance)
"feedback" -> directToFeedback(context, linkEntity.name, linkEntity.text, false, entrance)
"feedback" -> directToFeedback(context, linkEntity.name, linkEntity.text, entrance)
"qa", "Q&A" -> directToQa(context, linkEntity.text ?: "", linkEntity.link ?: "")
@ -258,71 +245,6 @@ object DirectUtils {
"bbs_detail" -> directForumDetail(context, linkEntity.link ?: "", entrance)
"mobile_bind" -> {
CheckLoginUtils.checkLogin(context, entrance) {
context.startActivity(BindPhoneActivity.getNormalIntent(context, false))
}
}
"authentication" -> {
CheckLoginUtils.checkLogin(context, entrance) {
context.startActivity(UserInfoEditActivity.getIntent(context, UserViewModel.TYPE_ID_CARD))
}
}
"user_background" -> {
CheckLoginUtils.checkLogin(context, entrance) {
context.startActivity(PersonalityBackgroundActivity.getIntent(context))
}
}
"avatar_frame" -> {
CheckLoginUtils.checkLogin(context, entrance) {
context.startActivity(AvatarBorderActivity.getIntent(context))
}
}
"badge" -> {
CheckLoginUtils.checkLogin(context, entrance) {
UserManager.getInstance().userInfoEntity?.run {
directToBadgeWall(context, userId, name, icon)
}
}
}
"etiquette_exam" -> directToRegulationTestPage(context)
"setting" -> context.startActivity(SettingActivity.getIntent(context, false, entrance))
"index_page" -> directToHomeTab(context)
"video_upload" -> context.startActivity(VideoManagerActivity.getIntent(context, "", entrance))
"bbs" -> directToForum(context)
"user_page" -> directToHomeActivity(context, UserManager.getInstance().userId, "", entrance)
"video_tab" -> directToVideoTab(context)
"toolkit" -> context.startActivity(ToolBoxActivity.getIntent(context, entrance))
"column_test" -> context.startActivity(GameServerTestActivity.getIntent(context, linkEntity.link
?: "", linkEntity.text ?: "", entrance))
"toolkit_detail" -> {
linkEntity.toolkit?.run {
if (url != null && url!!.contains(Config.URL_ARTICLE)) {
val newsId = url!!.substring(url!!.lastIndexOf("/") + 1, url!!.length - 5) // 5: ".html"
val intent = NewsDetailActivity.getIntentById(context, newsId, entrance)
context.startActivity(intent)
} else {
context.startActivity(WebActivity.getWebByCollectionTools(context, this, false))
}
} ?: ""
}
"halo_tab" -> directToPersonalTab(context)
//"h5_game_center" -> directLetoGameCenter(context)
"" -> {
@ -332,7 +254,7 @@ object DirectUtils {
if (unknownCallback != null) {
unknownCallback.invoke()
} else {
DialogHelper.showUpgradeDialog(context)
DialogUtils.showLowVersionDialog(context)
}
}
}
@ -431,20 +353,6 @@ object DirectUtils {
jumpActivity(context, bundle)
}
/**
* 跳转到新闻详情
*/
@JvmStatic
fun directToArticle(context: Context, id: String, hideUselessInfo: Boolean, entrance: String? = null) {
if (id.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, NewsDetailActivity::class.java.simpleName)
bundle.putString(KEY_NEWSID, id)
bundle.putBoolean(KEY_HIDE_USELESS_INFO, hideUselessInfo)
jumpActivity(context, bundle)
}
/**
* 跳转至个人主页
*/
@ -459,7 +367,6 @@ object DirectUtils {
*/
@JvmStatic
fun directToHomeActivity(context: Context, userId: String?, position: Int, entrance: String? = null, path: String? = null) {
IntegralLogHelper.log("view_homepage", "个人主页")
val bundle = Bundle()
bundle.putString(KEY_USER_ID, userId)
bundle.putString(KEY_TO, UserHomeActivity::class.java.name)
@ -561,27 +468,21 @@ object DirectUtils {
// 反馈
@JvmStatic
fun directToFeedback(context: Context, content: String? = null, entrance: String? = null) {
directToFeedback(context, content, null, false, entrance)
directToFeedback(context, content, null, entrance)
}
@JvmStatic
fun directToFeedback(context: Context, content: String? = null, hintType: String? = null, isQaFeedback: Boolean = false, entrance: String? = null) {
fun directToFeedback(context: Context, content: String? = null, hintType: String? = null, entrance: String? = null) {
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, SuggestionActivity::class.java.simpleName)
if (isQaFeedback) {
bundle.putBoolean(KEY_IS_QA_FEEDBACK, true)
bundle.putSerializable(KEY_SUGGESTTYPE, SuggestType.normal)
bundle.putString(KEY_CONTENT, content)
if (TextUtils.isEmpty(hintType)) {
bundle.putString(KEY_SUGGEST_HINT_TYPE, KEY_PLUGIN)
} else {
bundle.putString(KEY_CONTENT, content)
bundle.putSerializable(KEY_SUGGESTTYPE, SuggestType.gameQuestion)
if (TextUtils.isEmpty(hintType)) {
bundle.putString(KEY_SUGGEST_HINT_TYPE, KEY_PLUGIN)
} else {
bundle.putString(KEY_SUGGEST_HINT_TYPE, hintType)
}
bundle.putString(KEY_SUGGEST_HINT_TYPE, hintType)
}
bundle.putSerializable(KEY_SUGGESTTYPE, SuggestType.gameQuestion)
jumpActivity(context, bundle)
}
@ -673,17 +574,12 @@ object DirectUtils {
@JvmStatic
fun directToExternalBrowser(context: Context, url: String) {
try {
if (url.isEmpty()) return
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(Uri.decode(url)))
if (context !is AppCompatActivity) {
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(browserIntent)
} catch (e: ActivityNotFoundException) {
e.printStackTrace()
Utils.toast(context, "跳转地址无效")
if (url.isEmpty()) return
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
if (context !is AppCompatActivity) {
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(browserIntent)
}
// 跳转 QQqqNumber 为空选择默认客服 QQ
@ -710,7 +606,8 @@ object DirectUtils {
context.startActivity(intent)
} else {
// 没有安装QQ 复制账号
qq?.copyTextAndToast("已复制 QQ $qq")
Util_System_ClipboardManager.setText(context, qq)
Utils.toast(context, "已复制 QQ $qq")
}
}
@ -992,34 +889,6 @@ object DirectUtils {
jumpActivity(context, bundle)
}
/**
* 跳转新分类
*/
@JvmStatic
fun directCatalog(context: Context, catalogId: String, catalogTitle: String, entrance: String? = null, path: String? = "") {
if (catalogId.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_TO, CatalogActivity::class.java.name)
bundle.putString(KEY_CATALOG_ID, catalogId)
bundle.putString(KEY_CATALOG_TITLE, catalogTitle)
bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
jumpActivity(context, bundle)
}
/**
* 跳转新分类2.0
*/
@JvmStatic
fun directCategoryV2(context: Context, categoryId: String, categoryTitle: String, entrance: String? = null, path: String? = "") {
if (categoryId.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_TO, CategoryV2Activity::class.java.name)
bundle.putString(KEY_CATEGORY_ID, categoryId)
bundle.putString(KEY_CATEGORY_TITLE, categoryTitle)
bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
jumpActivity(context, bundle)
}
/**
* 跳转到问题标签详情
*/
@ -1144,28 +1013,7 @@ object DirectUtils {
}
/**
* 到首页-首页 tab
*/
@JvmStatic
fun directToHomeTab(context: Context) {
if (RunningUtils.isRunning(context)
&& MainActivity::class.java.name == RunningUtils.getBaseActivity(context)) {
val intent = Intent(context, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
context.startActivity(intent)
// 这里换个线程操作是为了做一点延时
AppExecutor.ioExecutor.execute {
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_HOME))
}
} else {
jumpActivity(context, Bundle().apply { putInt(KEY_POSITION, MainWrapperFragment.INDEX_HOME) })
}
}
/**
* 到首页-论坛 tab
* 到首页论坛 tab
*/
@JvmStatic
fun directToForum(context: Context) {
@ -1184,46 +1032,6 @@ object DirectUtils {
}
}
/**
* 到首页-视频 tab
*/
@JvmStatic
fun directToVideoTab(context: Context) {
if (RunningUtils.isRunning(context)
&& MainActivity::class.java.name == RunningUtils.getBaseActivity(context)) {
val intent = Intent(context, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
context.startActivity(intent)
// 这里换个线程操作是为了做一点延时
AppExecutor.ioExecutor.execute {
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_VIDEO))
}
} else {
jumpActivity(context, Bundle().apply { putInt(KEY_POSITION, MainWrapperFragment.INDEX_VIDEO) })
}
}
/**
* 到首页-我的光环 tab
*/
@JvmStatic
fun directToPersonalTab(context: Context) {
if (RunningUtils.isRunning(context)
&& MainActivity::class.java.name == RunningUtils.getBaseActivity(context)) {
val intent = Intent(context, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
context.startActivity(intent)
// 这里换个线程操作是为了做一点延时
AppExecutor.ioExecutor.execute {
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_PERSONAL))
}
} else {
jumpActivity(context, Bundle().apply { putInt(KEY_POSITION, MainWrapperFragment.INDEX_PERSONAL) })
}
}
/**
* 跳转至使用帮助与反馈
* @param position 使用帮助:[HelpAndFeedbackActivity.HELP_ITEM],意见反馈:[HelpAndFeedbackActivity.SUGGESTION_ITEM]
@ -1235,230 +1043,4 @@ object DirectUtils {
bundle.putInt(BaseActivity_TabLayout.PAGE_INDEX, position)
jumpActivity(context, bundle)
}
/**
* 跳转至商品详情
*/
@JvmStatic
fun directToCommodityDetail(context: Context, commodityId: String) {
var url: String = if ("internal" == BuildConfig.FLAVOR) {
Constants.COMMODITY_DETAIL_ADDRESS_DEV
} else {
Constants.COMMODITY_DETAIL_ADDRESS
}
url = String.format(Locale.CHINA, "%s&shopid=%s&timestamp=%d", url, commodityId, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至光能记录默认跳到光能记录第一个Tab
*/
@JvmStatic
fun directToEnergyRecord(context: Context) {
directToEnergyRecord(context, 0)
}
@JvmStatic
fun directToEnergyRecord(context: Context, position: Int) {
var url: String = if ("internal" == BuildConfig.FLAVOR) {
Constants.ENERGY_RECORD_ADDRESS_DEV
} else {
Constants.ENERGY_RECORD_ADDRESS
}
url = String.format(Locale.CHINA, "%s&position=%s&timestamp=%d", url, position, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至订单中心
*/
@JvmStatic
fun directToOrderCenter(context: Context) {
var url: String = if ("internal" == BuildConfig.FLAVOR) {
Constants.ORDER_CENTER_ADDRESS_DEV
} else {
Constants.ORDER_CENTER_ADDRESS
}
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至订单详情
*/
@JvmStatic
fun directToOrderDetail(context: Context, orderId: String) {
var url: String = if ("internal" == BuildConfig.FLAVOR) {
Constants.ORDER_DETAIL_ADDRESS_DEV
} else {
Constants.ORDER_DETAIL_ADDRESS
}
url = String.format(Locale.CHINA, "%s&order_id=%s&timestamp=%d", url, orderId, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至邀请好友
*/
@JvmStatic
fun directToInviteFriends(context: Context) {
var url: String = if ("internal" == BuildConfig.FLAVOR) {
Constants.INVITE_FRIENDS_ADDRESS_DEV
} else {
Constants.INVITE_FRIENDS_ADDRESS
}
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至等级页面
*/
@JvmStatic
fun directToLevelPage(context: Context) {
var url: String = if (isPublishEnv()) {
Constants.LEVEL_ADDRESS
} else {
Constants.LEVEL_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s?timestamp=%d", url, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至兑换规则
*/
@JvmStatic
fun directToExchangeRulePage(context: Context) {
var url: String = if (isPublishEnv()) {
Constants.EXCHANGE_RULE_ADDRESS
} else {
Constants.EXCHANGE_RULE_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s&timestamp=%d", url, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至光能规则
*/
@JvmStatic
fun directToEnergyRulePage(context: Context) {
var url: String = if (isPublishEnv()) {
Constants.ENERGY_RULE_ADDRESS
} else {
Constants.ENERGY_RULE_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s&timestamp=%d", url, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至兑换商品
*/
@JvmStatic
fun directToExchangeCommodityPage(context: Context) {
var url: String = if (isPublishEnv()) {
Constants.EXCHANGE_COMMODITY_ADDRESS
} else {
Constants.EXCHANGE_COMMODITY_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s&timestamp=%d", url, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至抽奖乐园
*/
@JvmStatic
fun directToLotteryParadisePage(context: Context) {
var url: String = if (isPublishEnv()) {
Constants.LOTTERY_PARADISE_ADDRESS
} else {
Constants.LOTTERY_PARADISE_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s&timestamp=%d", url, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至我的奖品
*/
@JvmStatic
fun directToMyPrizePage(context: Context) {
var url: String = if (isPublishEnv()) {
Constants.MY_PRIZE_ADDRESS
} else {
Constants.MY_PRIZE_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s&timestamp=%d", url, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至中奖订单详情
*/
@JvmStatic
fun directToWinOrderDetail(context: Context, orderId: String, activityId: String) {
var url: String = if (isPublishEnv()) {
Constants.WIN_ORDER_DETAIL_ADDRESS
} else {
Constants.WIN_ORDER_DETAIL_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s&order_id=%s&activity_id=%s&timestamp=%d", url, orderId, activityId, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至地址信息
*/
@JvmStatic
fun directToAddressInfo(context: Context) {
var url: String = if (isPublishEnv()) {
Constants.ADDRESS_INFO_ADDRESS
} else {
Constants.ADDRESS_INFO_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s&timestamp=%d", url, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至领奖信息
*/
@JvmStatic
fun directToPrizeInfo(context: Context) {
var url: String = if (isPublishEnv()) {
Constants.PRIZE_INFO_ADDRESS
} else {
Constants.PRIZE_INFO_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s&timestamp=%d", url, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至提现信息
*/
@JvmStatic
fun directToWithdrawInfo(context: Context) {
var url: String = if (isPublishEnv()) {
Constants.WITHDRAW_INFO_ADDRESS
} else {
Constants.WITHDRAW_INFO_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s&timestamp=%d", url, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
}

View File

@ -21,74 +21,67 @@ object DownloadDialogHelper {
}
private fun retrieveAvailableDialog(gameEntity: GameEntity, apkEntity: ApkEntity): GameEntity.Dialog? {
val downloadDialog = if (gameEntity.shouldUseMirrorInfo()) {
gameEntity.mirrorData?.downloadDialog
} else {
gameEntity.downloadDialog
}
if (gameEntity.downloadDialog.isNullOrEmpty()) return null
if (downloadDialog.isNullOrEmpty()) return null
for (dialog in downloadDialog) {
val versionName = PackageUtils.getVersionName()
val noticeVersions = dialog.rule.noticeVersions
if (noticeVersions.isEmpty() || noticeVersions.contains(versionName)) {
// 共有 8 种可能
// 1. 不指定包名、机型和系统版本
if (dialog.rule.packageName.isEmpty()
&& dialog.rule.models.isEmpty()
&& dialog.rule.systemVersions.isEmpty()) {
return dialog
}
for (dialog in gameEntity.downloadDialog!!) {
// 2. 指定包名不管机型和系统
if (dialog.rule.packageName == apkEntity.packageName
&& dialog.rule.models.isEmpty()
&& dialog.rule.systemVersions.isEmpty()) {
return dialog
}
// 共有 8 种可能
// 1. 不指定包名、机型和系统版本
if (dialog.rule.packageName.isEmpty()
&& dialog.rule.models.isEmpty()
&& dialog.rule.systemVersions.isEmpty()) {
return dialog
}
// 3. 指定机型不管包名和系统
if (dialog.rule.models.contains(Build.MODEL)
&& dialog.rule.packageName.isEmpty()
&& dialog.rule.systemVersions.isEmpty()) {
return dialog
}
// 2. 指定包名不管机型和系统
if (dialog.rule.packageName == apkEntity.packageName
&& dialog.rule.models.isEmpty()
&& dialog.rule.systemVersions.isEmpty()) {
return dialog
}
// 4. 指定系统不管包名和机型
if (dialog.rule.systemVersions.contains(Build.VERSION.RELEASE)
&& dialog.rule.packageName.isEmpty()
&& dialog.rule.models.isEmpty()) {
return dialog
}
// 3. 指定机型不管包名和系统
if (dialog.rule.models.contains(Build.MODEL)
&& dialog.rule.packageName.isEmpty()
&& dialog.rule.systemVersions.isEmpty()) {
return dialog
}
// 5. 指定包名和机型不管系统
if (dialog.rule.packageName == apkEntity.packageName
&& dialog.rule.models.contains(Build.MODEL)
&& dialog.rule.systemVersions.isEmpty()) {
return dialog
}
// 4. 指定系统不管包名和机型
if (dialog.rule.systemVersions.contains(Build.VERSION.RELEASE)
&& dialog.rule.packageName.isEmpty()
&& dialog.rule.models.isEmpty()) {
return dialog
}
// 6. 指定包名和系统不管机型
if (dialog.rule.packageName == apkEntity.packageName
&& dialog.rule.systemVersions.contains(Build.VERSION.RELEASE)
&& dialog.rule.models.isEmpty()) {
return dialog
}
// 5. 指定包名和机型不管系统
if (dialog.rule.packageName == apkEntity.packageName
&& dialog.rule.models.contains(Build.MODEL)
&& dialog.rule.systemVersions.isEmpty()) {
return dialog
}
// 7. 指定机型和系统不管包名
if (dialog.rule.systemVersions.contains(Build.VERSION.RELEASE)
&& dialog.rule.models.contains(Build.MODEL)
&& dialog.rule.packageName.isEmpty()) {
return dialog
}
// 6. 指定包名和系统不管机型
if (dialog.rule.packageName == apkEntity.packageName
&& dialog.rule.systemVersions.contains(Build.VERSION.RELEASE)
&& dialog.rule.models.isEmpty()) {
return dialog
}
// 7. 指定机型和系统不管包名
if (dialog.rule.systemVersions.contains(Build.VERSION.RELEASE)
&& dialog.rule.models.contains(Build.MODEL)
&& dialog.rule.packageName.isEmpty()) {
return dialog
}
// 8.指定包名、机型和系统版本
if (dialog.rule.packageName == apkEntity.packageName
&& dialog.rule.models.contains(Build.MODEL)
&& dialog.rule.systemVersions.contains(Build.VERSION.RELEASE)) {
return dialog
}
// 8.指定包名、机型和系统版本
if (dialog.rule.packageName == apkEntity.packageName
&& dialog.rule.models.contains(Build.MODEL)
&& dialog.rule.systemVersions.contains(Build.VERSION.RELEASE)) {
return dialog
}
} else return null
}
return null

View File

@ -8,16 +8,9 @@ import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.collection.ArrayMap;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.gh.common.constant.Config;
import com.gh.common.dialog.CertificationDialog;
import com.gh.common.dialog.DeviceRemindDialog;
import com.gh.common.dialog.PackageCheckDialogFragment;
import com.gh.common.dialog.ReserveDialogFragment;
import com.gh.common.exposure.ExposureEvent;
import com.gh.common.history.HistoryHelper;
@ -28,7 +21,6 @@ import com.gh.common.xapk.XapkInstaller;
import com.gh.common.xapk.XapkUnzipStatus;
import com.gh.download.DownloadManager;
import com.gh.download.dialog.DownloadDialog;
import com.gh.download.server.BrowserInstallHelper;
import com.gh.gamecenter.DownloadManagerActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.WebActivity;
@ -37,7 +29,6 @@ import com.gh.gamecenter.entity.ApkEntity;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.LinkEntity;
import com.gh.gamecenter.entity.PluginLocation;
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment;
import com.gh.gamecenter.manager.PackagesManager;
import com.lightgame.download.DownloadConfig;
import com.lightgame.download.DownloadEntity;
@ -48,6 +39,12 @@ import com.lightgame.utils.Utils;
import java.io.File;
import java.util.concurrent.LinkedBlockingQueue;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.collection.ArrayMap;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
/**
* todo 下载判断不能以按钮文案为判断条件,否则按钮文案修改时又要修改判断逻辑
*/
@ -127,18 +124,16 @@ public class DownloadItemUtils {
public static void updateItemWithReserveStatus(GameViewHolder holder, GameEntity gameEntity) {
if ("download".equals(gameEntity.getReserveStatus())) {
// 已上线
// holder.gameDownloadBtn.setVisibility(View.VISIBLE);
// holder.gameDownloadBtn.setText("已上线");
// holder.gameDownloadBtn.setTextColor(Color.WHITE);
// holder.gameDownloadBtn.setBackground(ContextCompat.getDrawable(holder.gameDes.getContext(), R.drawable.game_item_btn_pause_dn));
updateItem(holder.gameDes.getContext(), gameEntity, holder, false);
holder.gameDownloadBtn.setVisibility(View.VISIBLE);
holder.gameDownloadBtn.setText("已上线");
holder.gameDownloadBtn.setTextColor(Color.WHITE);
holder.gameDownloadBtn.setBackground(ContextCompat.getDrawable(holder.gameDes.getContext(), R.drawable.game_item_btn_pause_dn));
} else if ("appointment".equals(gameEntity.getReserveStatus())) {
// 已预约
holder.gameDownloadBtn.setVisibility(View.VISIBLE);
holder.gameDownloadBtn.setText("已预约");
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(holder.gameDes.getContext(), R.color.aaaaaa));
holder.gameDownloadBtn.setBackgroundResource(R.drawable.button_round_f5f5f5);
updateItemViewStatus(holder, false, null);
holder.gameDownloadBtn.setTextColor(Color.WHITE);
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_pause_dn);
}
}
@ -424,7 +419,7 @@ public class DownloadItemUtils {
}
/**
* @param clickCallback 供那些需要知道点击回调的地方使用,触发具体响应才会回调
* @param clickCallback 供那些需要知道点击回调的地方使用
*/
public static void setOnClickListener(final Context context,
final TextView downloadBtn,
@ -436,50 +431,27 @@ public class DownloadItemUtils {
final ExposureEvent traceEvent,
@Nullable final EmptyCallback clickCallback) {
setOnClickListener(context, downloadBtn, gameEntity, position, adapter, entrance, location, traceEvent, clickCallback, null);
}
/**
* @param allStateClickCallback 供那些需要知道点击回调的地方使用,只要触发点击动作就会回调
*/
public static void setOnClickListener(final Context context,
final TextView downloadBtn,
final GameEntity gameEntity,
final int position,
final RecyclerView.Adapter<? extends RecyclerView.ViewHolder> adapter,
final String entrance,
final String location,
final ExposureEvent traceEvent,
@Nullable final EmptyCallback clickCallback,
@Nullable final EmptyCallback allStateClickCallback) {
if (gameEntity.isReservable()) {
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.getId())) {
downloadBtn.setOnClickListener(v -> {
if (allStateClickCallback != null) {
allStateClickCallback.onCallback();
}
CheckLoginUtils.checkLogin(context, entrance, () -> {
if (clickCallback != null) {
clickCallback.onCallback();
}
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(
gameEntity,
() -> {
LogUtils.logReservation(gameEntity, traceEvent);
adapter.notifyItemChanged(position);
}
);
dialogFragment.show(((AppCompatActivity) context).getSupportFragmentManager(), "reserve");
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(context, () -> {
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(
gameEntity,
() -> {
LogUtils.logReservation(gameEntity, traceEvent);
adapter.notifyItemChanged(position);
}
);
dialogFragment.show(((AppCompatActivity) context).getSupportFragmentManager(), "reserve");
});
});
});
} else {
downloadBtn.setOnClickListener(v -> {
if (allStateClickCallback != null) {
allStateClickCallback.onCallback();
}
if (clickCallback != null) {
clickCallback.onCallback();
}
@ -503,10 +475,6 @@ public class DownloadItemUtils {
if (gameEntity.getApk().size() == 0 && gameEntity.getH5Link() != null) {
downloadBtn.setOnClickListener(v -> {
if (allStateClickCallback != null) {
allStateClickCallback.onCallback();
}
MtaHelper.onEvent("H5页面", "入口", "列表页_" + gameEntity.getName());
LinkEntity linkEntity = gameEntity.getH5Link();
@ -522,10 +490,6 @@ public class DownloadItemUtils {
} else if (gameEntity.getApk().size() == 1) {
downloadBtn.setOnClickListener(v -> {
EmptyCallback clickRunnable = () -> {
if (allStateClickCallback != null) {
allStateClickCallback.onCallback();
}
if (clickCallback != null) {
clickCallback.onCallback();
}
@ -541,27 +505,128 @@ public class DownloadItemUtils {
});
} else {
downloadBtn.setOnClickListener(v -> {
if (allStateClickCallback != null) {
allStateClickCallback.onCallback();
}
if (clickCallback != null) {
clickCallback.onCallback();
}
RealNameHelper.checkIfAuth(v.getContext(), gameEntity, () -> {
GamePermissionDialogFragment.show((AppCompatActivity) context, gameEntity, gameEntity.getInfo(), () -> {
PermissionHelper.checkStoragePermissionBeforeAction(context, () -> {
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
DialogUtils.showVersionNumberDialog(context, gameEntity, () -> {
DownloadDialog.showDownloadDialog(
v.getContext(),
gameEntity,
traceEvent,
entrance,
location);
});
PermissionHelper.checkStoragePermissionBeforeAction(context, () -> {
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
DialogUtils.showVersionNumberDialog(context, gameEntity, () -> {
DownloadDialog.showDownloadDialog(
v.getContext(),
gameEntity,
traceEvent,
entrance,
location);
});
});
});
});
}
}
/**
* @param clickCallback 供那些需要知道点击回调的地方使用,只要触发了点击事件就响应回调(未登录状态下点击预约也要响应回调)
*/
public static void setOnClickListenerWithInvokeCallbackForAllState(final Context context,
final TextView downloadBtn,
final GameEntity gameEntity,
final int position,
final RecyclerView.Adapter<? extends RecyclerView.ViewHolder> adapter,
final String entrance,
final String location,
final ExposureEvent traceEvent,
@Nullable final EmptyCallback clickCallback) {
if (gameEntity.isReservable()) {
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.getId())) {
downloadBtn.setOnClickListener(v -> {
if (clickCallback != null) {
clickCallback.onCallback();
}
CheckLoginUtils.checkLogin(context, entrance, () -> {
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(context, () -> {
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(
gameEntity,
() -> {
LogUtils.logReservation(gameEntity, traceEvent);
adapter.notifyItemChanged(position);
}
);
dialogFragment.show(((AppCompatActivity) context).getSupportFragmentManager(), "reserve");
});
});
});
} else {
downloadBtn.setOnClickListener(v -> {
if (clickCallback != null) {
clickCallback.onCallback();
}
if ("download".equals(gameEntity.getReserveStatus())) {
ReservationHelper.showDeleteReservationDialog(context, () -> {
ReservationHelper.deleteReservation(gameEntity, () -> {
adapter.notifyItemChanged(position);
});
});
} else {
ReservationHelper.showCancelReservationDialog(context, () -> {
ReservationHelper.cancelReservation(gameEntity, () -> {
adapter.notifyItemChanged(position);
});
});
}
});
}
return;
}
if (gameEntity.getApk().size() == 0 && gameEntity.getH5Link() != null) {
downloadBtn.setOnClickListener(v -> {
if (clickCallback != null) {
clickCallback.onCallback();
}
MtaHelper.onEvent("H5页面", "入口", "列表页_" + gameEntity.getName());
LinkEntity linkEntity = gameEntity.getH5Link();
boolean isPlay = "play".equals(linkEntity.getType()); // 是否为开始玩
if (isPlay) {
HistoryHelper.insertGameEntity(gameEntity);
}
Intent i = WebActivity.getIntentForWebGame(context, gameEntity.getH5Link().getLink(), gameEntity.getName(), isPlay, linkEntity.getCloseButton());
context.startActivity(i);
});
} else if (gameEntity.getApk().size() == 1) {
downloadBtn.setOnClickListener(v -> {
EmptyCallback clickRunnable = () -> {
if (clickCallback != null) {
clickCallback.onCallback();
}
onNormalClick(context, downloadBtn, gameEntity, position, adapter, entrance, location, traceEvent);
};
// 启动不需要请求存储权限
if (downloadBtn.getText().toString().equals(context.getString(R.string.launch))) {
clickRunnable.onCallback();
} else {
PermissionHelper.checkStoragePermissionBeforeAction(context, clickRunnable);
}
});
} else {
downloadBtn.setOnClickListener(v -> {
if (clickCallback != null) {
clickCallback.onCallback();
}
PermissionHelper.checkStoragePermissionBeforeAction(context, () -> {
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
DialogUtils.showVersionNumberDialog(context, gameEntity, () -> {
DownloadDialog.showDownloadDialog(
v.getContext(),
gameEntity,
traceEvent,
entrance,
location);
});
});
});
});
@ -587,45 +652,28 @@ public class DownloadItemUtils {
final String location,
@Nullable final ExposureEvent traceEvent) {
String str = downloadBtn.getText().toString();
if (gameEntity.getApk().isEmpty()) return;
ApkEntity apk = ExtensionsKt.safelyGetInRelease(gameEntity.getApk(), 0);
if (apk == null) return;
ApkEntity apk = gameEntity.getApk().get(0);
if (str.equals(context.getString(R.string.download))) {
// 先弹下载弹窗(如果需要的话)
RealNameHelper.checkIfAuth(context, gameEntity, () -> {
GamePermissionDialogFragment.show((AppCompatActivity) context, gameEntity, gameEntity.getInfo(), () -> {
BrowserInstallHelper.showBrowserInstallHintDialog(context, () -> {
PackageCheckDialogFragment.show((AppCompatActivity) context, gameEntity, () -> {
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
DialogUtils.showOverseaDownloadDialog(context, gameEntity, () -> {
DialogUtils.checkDownload(context, apk.getSize(),
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
});
});
});
});
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
DialogUtils.showOverseaDownloadDialog(context, gameEntity, () -> {
DialogUtils.checkDownload(context, apk.getSize(),
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
});
});
});
DataLogUtils.uploadGameLog(context, gameEntity.getId(), gameEntity.getName(), entrance);
} else if (str.equals(context.getString(R.string.attempt))) {
RealNameHelper.checkIfAuth(context, gameEntity, () -> {
GamePermissionDialogFragment.show((AppCompatActivity) context, gameEntity, gameEntity.getInfo(), () -> {
BrowserInstallHelper.showBrowserInstallHintDialog(context, () -> {
PackageCheckDialogFragment.show((AppCompatActivity) context, gameEntity, () -> {
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
DialogUtils.showVersionNumberDialog(context, gameEntity, () -> {
DialogUtils.showOverseaDownloadDialog(context, gameEntity, () -> {
DialogUtils.checkDownload(context, apk.getSize(),
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
});
});
});
});
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
DialogUtils.showVersionNumberDialog(context, gameEntity, () -> {
DialogUtils.showOverseaDownloadDialog(context, gameEntity, () -> {
DialogUtils.checkDownload(context, apk.getSize(),
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
});
});
});
@ -652,7 +700,7 @@ public class DownloadItemUtils {
boolean isInstalled = PackageUtils.isInstalledFromAllPackage(context, gameEntity.getSimulator().getApk().getPackageName());
if (downloadEntity != null && SimulatorGameManager.isSimulatorGame(gameEntity) && !isInstalled) {
SimulatorDownloadManager.getInstance().showDownloadDialog(context, gameEntity.getSimulator(),
SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.getId(), gameEntity.getName(), null);
SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.getId(), gameEntity.getName(),null);
return;
}
}
@ -676,8 +724,6 @@ public class DownloadItemUtils {
}
DataUtils.onGameLaunchEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), location);
PackageUtils.launchApplicationByPackageName(context, gameEntity.getApk().get(0).getPackageName());
EnergyTaskHelper.postEnergyTask("play_game", gameEntity.getId(), gameEntity.getApk().get(0).getPackageName());
} else if (str.equals(context.getString(R.string.update))) {
if (entrance.contains("我的游戏")) {
MtaHelper.onEvent("我的游戏_启动", "更新", gameEntity.getName());
@ -690,7 +736,6 @@ public class DownloadItemUtils {
context.startActivity(DownloadManagerActivity.getDownloadMangerIntent(context,
apk.getUrl(), entrance + "+(" + location.split(":")[0] + ")"));
}
}
//下载
@ -750,10 +795,7 @@ public class DownloadItemUtils {
}
adapter.notifyItemChanged(position);
} else if (PackageUtils.isCanPluggable(apkEntity)) {
DialogHelper.showPluginDialog(context, () -> {
PackageInstaller.uninstall(context, path);
return null;
});
DialogUtils.showPluginDialog(context, () -> PackageInstaller.uninstall(context, path));
} else {
PackageInstaller.install(context, downloadEntity);
}

View File

@ -1,14 +1,14 @@
package com.gh.common.util
import android.content.pm.PackageManager
import android.os.Build
import android.preference.PreferenceManager
import com.gh.base.BaseActivity
import com.gh.common.constant.Constants
import com.gh.common.exposure.ExposureUtils
import com.gh.common.exposure.meta.MetaUtil
import com.gh.common.simulator.SimulatorDownloadManager
import com.gh.common.simulator.SimulatorGameManager
import com.gh.common.util.EnergyTaskHelper.postEnergyTask
import com.gh.common.exposure.meta.MetaUtil
import com.gh.common.xapk.XapkInstaller
import com.gh.download.DownloadDataHelper
import com.gh.download.DownloadManager
@ -17,7 +17,6 @@ import com.gh.gamecenter.R
import com.gh.gamecenter.SuggestionActivity
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.entity.SimpleGameEntity
import com.gh.gamecenter.entity.SimulatorEntity
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.eventbus.EBShowDialog
import com.gh.gamecenter.retrofit.Response
@ -52,7 +51,7 @@ object DownloadObserver {
val xapkStatus = downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS]
if (!xapkStatus.isNullOrEmpty()) return
val gameId = downloadEntity.gameId
val gameId = downloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER)
val downloadManager = DownloadManager.getInstance(HaloApp.getInstance().application)
tryCatchInRelease {
@ -78,10 +77,9 @@ object DownloadObserver {
// MtaHelper.onEventWithBasicDeviceInfo("下载失败弹窗",
// "游戏", downloadEntity.name,
// "平台", downloadEntity.platform)
val currentActivity = AppManager.getInstance().currentActivity() ?: return
DialogUtils.showAlertDialog(currentActivity, "下载失败", "下载链接已失效,建议提交反馈", "立即反馈", "取消", {
SuggestionActivity.startSuggestionActivity(currentActivity,
DialogUtils.showAlertDialog(AppManager.getInstance().currentActivity(), "下载失败", "下载链接已失效,建议提交反馈", "立即反馈", "取消", {
SuggestionActivity.startSuggestionActivity(AppManager.getInstance().currentActivity(),
SuggestType.gameQuestion, "notfound",
StringUtils.buildString(downloadEntity.name, ",问题反馈:下载链接失效"),
SimpleGameEntity(gameId, downloadEntity.name, ""))
@ -113,26 +111,21 @@ object DownloadObserver {
}
if (DownloadStatus.done == downloadEntity.status) {
if (downloadEntity.name.contains(mApplication.getString(R.string.app_name))) {
statDoneEvent(downloadEntity)
MtaHelper.onEvent("软件更新", "下载完成")
// 会有 ActivityNotFoundException 异常catch 掉不管了
tryWithDefaultCatch {
if (Constants.SILENT_UPDATE != downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE)) {
// TODO 在 Android 11 上没有授权安装未知应用的权限前第一次调用这个方法系统会杀掉我们的进程...
// 没能找到类似的解释,最接近的是这个 https://issuetracker.google.com/issues/154157387但也只是点授权杀进程而已
PackageInstaller.install(mApplication, downloadEntity);
PackageInstaller.install(mApplication, downloadEntity)
DataLogUtils.uploadUpgradeLog(mApplication, "install") //上传更新安装数据
}
}
} else {
statDoneEvent(downloadEntity)
postEnergyTask("download_game", downloadEntity.gameId, downloadEntity.packageName)
val platform = PlatformUtils.getInstance(mApplication)
.getPlatformName(downloadEntity.platform)
if (platform != null) {
when {
// TODO 插件化传 path 从 apk 中获取 packageName 的形式有可能出现拿不到 packageName 的情况
downloadEntity.isPluggable -> // 弹出插件化提示框
EventBus.getDefault().post(EBShowDialog(BaseActivity.PLUGGABLE, downloadEntity.path))
downloadEntity.isPlugin -> Utils.toast(mApplication, downloadEntity.name + " - " + platform + " - 下载完成")
@ -143,20 +136,17 @@ object DownloadObserver {
}
if (!downloadEntity.isPluggable) {
if (downloadEntity.isSimulatorGame()) {
val simulatorJson = downloadEntity.getMetaExtra(Constants.SIMULATOR)
val gameName = downloadEntity.getMetaExtra(Constants.GAME_NAME)
if (simulatorJson.isEmpty()) return
val simulator = GsonUtils.fromJson(simulatorJson, SimulatorEntity::class.java)
val isInstalled = PackageUtils.isInstalledFromAllPackage(HaloApp.getInstance().application, simulator.apk?.packageName)
if (!isInstalled) {
val currentActivity = AppManager.getInstance().currentActivity()
?: return
SimulatorDownloadManager.getInstance().showDownloadDialog(currentActivity, simulator,
SimulatorDownloadManager.SimulatorLocation.LAUNCH, downloadEntity.gameId, gameName, null)
val gameEntity = HaloApp.get(GameEntity::class.java.simpleName, true) as? GameEntity
if (gameEntity?.simulator != null) {
val isInstalled = PackageUtils.isInstalledFromAllPackage(HaloApp.getInstance().application, gameEntity.simulator!!.apk!!.packageName)
if (!isInstalled) {
SimulatorDownloadManager.getInstance().showDownloadDialog(AppManager.getInstance().currentActivity(), gameEntity.simulator,
SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.id, gameEntity.name
?: "", null)
}
SimulatorGameManager.recordDownloadSimulatorGames(gameEntity.id)
SimulatorGameManager.postPlayedGame(gameEntity.id, downloadEntity.packageName)
}
SimulatorGameManager.recordDownloadSimulatorGames(downloadEntity.gameId, simulator.type)
SimulatorGameManager.postPlayedGame(downloadEntity.gameId, downloadEntity.packageName)
} else {
val downloadType = downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE)
// 是否是自动安装
@ -173,11 +163,7 @@ object DownloadObserver {
}
} else {
// 弹出卸载提示框
if (downloadEntity.isPlugin) {
EventBus.getDefault().post(EBShowDialog(BaseActivity.PLUGGABLE, downloadEntity.path))
} else {
EventBus.getDefault().post(EBShowDialog(BaseActivity.SIGNATURE_CONFLICT, downloadEntity.path))
}
EventBus.getDefault().post(EBShowDialog(BaseActivity.PLUGGABLE, downloadEntity.path))
}
}
}
@ -189,32 +175,14 @@ object DownloadObserver {
}
// 下载过程分析统计
// 部分设备 (已知 vivo 5.1.1) 在调用 packageManager.getPackageArchiveInfo 获取比较大的 APK 文件时会出现 ANR
// 这里为了让它能用就不判断是否解析包错误了
if (PackageUtils.isDeviceUnableToHandleBigApkFile(downloadEntity.path)) {
return
}
val pm = mApplication.packageManager
val packageInfo = pm.getPackageArchiveInfo(downloadEntity.path, 0)
val packageInfo = pm.getPackageArchiveInfo(downloadEntity.path, PackageManager.GET_ACTIVITIES)
if (packageInfo == null) {
// MtaHelper.onEventWithBasicDeviceInfo("解析包错误分析",
// "游戏名字", downloadEntity.name + ":" + PlatformUtils.getInstance(mApplication).getPlatformName(downloadEntity.platform))
//
// MtaHelper.onEventWithBasicDeviceInfo("解析包错误_新",
// "游戏", downloadEntity.name + ":" + PlatformUtils.getInstance(mApplication).getPlatformName(downloadEntity.platform))
val downloadType = downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE)
if (downloadType == Constants.SIMULATOR_DOWNLOAD) {
val currentActivity = AppManager.getInstance().currentActivity()
?: return
DialogUtils.showSimulatorParseErrorDialog(currentActivity, downloadEntity.gameId, downloadEntity.name) {
val simulator = HaloApp.get(downloadEntity.name, true) as? SimulatorEntity
?: return@showSimulatorParseErrorDialog
DownloadManager.getInstance(currentActivity).cancel(downloadEntity.url, true, true)
SimulatorDownloadManager.getInstance().showDownloadDialog(currentActivity, simulator, SimulatorDownloadManager.SimulatorLocation.SIMULATOR_GAME)
}
}
}
}
@ -247,7 +215,7 @@ object DownloadObserver {
kv1["版本"] = platform
kv1["状态"] = "下载完成"
kv1["用户机型"] = Build.MODEL
kv1["设备JNFJ"] = MetaUtil.getBase64EncodedIMEI()
kv1["设备IMEI"] = MetaUtil.getIMEI()
kv1["网络状态"] = DeviceUtils.getNetwork(HaloApp.getInstance().application)
kv1["光环助手版本"] = BuildConfig.VERSION_NAME
if (downloadEntity.isUpdate) {
@ -283,12 +251,11 @@ object DownloadObserver {
// "操作", "下载完成",
// "网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().application))
}
val isPlatformRecommend = java.lang.Boolean.parseBoolean(downloadEntity.getMetaExtra(Constants.IS_PLATFORM_RECOMMEND))
ExposureUtils.logADownloadCompleteExposureEvent(
GameEntity(id = downloadEntity.gameId,
GameEntity(id = downloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER),
mName = downloadEntity.name.removeSuffix(Constants.GAME_NAME_DECORATOR),
gameVersion = downloadEntity.versionName ?: "",
isPlatformRecommend = isPlatformRecommend),
gameVersion = downloadEntity.versionName ?: ""),
downloadEntity.platform,
downloadEntity.exposureTrace,
downloadEntity.meta[DownloadEntity.DOWNLOAD_HOST_KEY] ?: "unknown",
@ -316,7 +283,7 @@ object DownloadObserver {
params["game"] = id
params["platform"] = platform ?: ""
val body = RequestBody.create(MediaType.parse("application/json"),
JSONObject(params as Map<*, *>).toString())
JSONObject(params).toString())
RetrofitManager.getInstance(mApplication).api.postDownload(body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())

View File

@ -1,157 +0,0 @@
package com.gh.common.util
import android.annotation.SuppressLint
import android.view.Gravity
import android.view.View
import android.widget.LinearLayout
import android.widget.PopupWindow
import android.widget.TextView
import com.gh.common.constant.Constants
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.R
import com.gh.gamecenter.energy.EnergyCenterActivity
import com.gh.gamecenter.entity.EnergyTaskCompleteEntity
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.retrofit.BiResponse
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.lightgame.utils.AppManager
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.RequestBody
import org.json.JSONObject
/**
* 上报光能任务辅助类
*/
object EnergyTaskHelper {
@JvmStatic
fun postEnergyTask(action: String) {
postEnergyTask(action, null, null, null)
}
@JvmStatic
fun postEnergyTask(action: String, id: String) {
postEnergyTask(action, id, null, null)
}
@JvmStatic
fun postEnergyTask(action: String, id: String, packageName: String) {
postEnergyTask(action, id, packageName, null)
}
@JvmStatic
fun postEnergyTaskForWeb(action: String, url: String) {
postEnergyTask(action, null, null, url)
}
@JvmStatic
fun postEnergyTaskForShare(type: String, id: String, url: String) {
when (type) {
"游戏详情" -> postEnergyTask("share_game_detail", id)
"视频" -> postEnergyTask("share_video", id)
"资讯文章" -> postEnergyTask("share_article", id)
"问题详情" -> postEnergyTask("share_question", id)
"回答详情" -> postEnergyTask("share_answer", id)
"文章详情" -> postEnergyTask("share_community_article", id)
"工具箱" -> postEnergyTask("share_toolkit", id)
"web链接" -> postEnergyTaskForWeb("share_web", url)
}
}
@SuppressLint("CheckResult")
@JvmStatic
fun postEnergyTask(action: String, id: String? = null, packageName: String? = null, url: String? = null) {
if (BuildConfig.DEBUG || BuildConfig.BUILD_TIME != 0L) {
val taskParams = JSONObject()
taskParams.put("action", action)
val actionParams = JSONObject()
if (id != null) actionParams.put("_id", id)
if (packageName != null) actionParams.put("package", packageName)
if (url != null) actionParams.put("url", url)
taskParams.put("action_param", actionParams)
debugOnly { Utils.log("EnergyTaskHelper -> $taskParams") }
val body = RequestBody.create(MediaType.parse("application/json"), taskParams.toString())
RetrofitManager.getInstance(HaloApp.getInstance().application)
.api.postEnergyTask(UserManager.getInstance().userId, body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<List<EnergyTaskCompleteEntity>>() {
override fun onSuccess(data: List<EnergyTaskCompleteEntity>) {
data.forEach { showCompletePopup(it) }
}
})
}
}
@SuppressLint("CheckResult")
@JvmStatic
fun postInviteCodeTask(code: String, from: String, callback: (() -> Unit)?) {
if (BuildConfig.DEBUG || BuildConfig.BUILD_TIME != 0L) {
val taskParams = JSONObject()
taskParams.put("action", "enter_invite_code")
val actionParams = JSONObject()
actionParams.put("code", code)
actionParams.put("type", "new")
actionParams.put("from", from)
taskParams.put("action_param", actionParams)
debugOnly { Utils.log("EnergyTaskHelper -> $taskParams") }
val body = RequestBody.create(MediaType.parse("application/json"), taskParams.toString())
RetrofitManager.getInstance(HaloApp.getInstance().application)
.api.postEnergyTask(UserManager.getInstance().userId, body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<List<EnergyTaskCompleteEntity>>() {
override fun onSuccess(data: List<EnergyTaskCompleteEntity>) {
SPUtils.setBoolean(Constants.SP_HAS_COMPLETE_INVITE_CODE, true)
callback?.invoke()
data.forEach { showCompletePopup(it) }
}
})
}
}
// 完成弹窗
@JvmStatic
fun showCompletePopup(entity: EnergyTaskCompleteEntity) {
val currentActivity = AppManager.getInstance().recentActiveActivity
currentActivity?.run {
val contentView = View.inflate(this, R.layout.popup_energy_task, null)
contentView.run {
findViewById<TextView>(R.id.taskDesc).text = "恭喜你!完成任务:${entity.name}"
findViewById<TextView>(R.id.taskEnergy).text = "+${entity.energy}光能"
isFocusable = true
isFocusableInTouchMode = true
setOnClickListener {
if (currentActivity::class.java.simpleName != EnergyCenterActivity::class.java.simpleName) {
currentActivity.startActivity(EnergyCenterActivity.getIntent(currentActivity))
}
}
}
val popWindow = PopupWindow(contentView, LinearLayout.LayoutParams.MATCH_PARENT, 88F.dip2px())
popWindow.showAtLocation(currentActivity.window.decorView, Gravity.TOP, 0, 0)
countDownTimer(3) { finish, _ ->
if (finish && popWindow != null && popWindow.isShowing) {
popWindow.dismiss()
}
}
}
}
}

View File

@ -148,10 +148,8 @@ public class EntranceUtils {
public static final String KEY_RECOMMENDS_CONTENTS = "isRecommendsContents";
public static final String KEY_VERSION_UPDATE = "versionUpdate";
public static final String KEY_CHECK_QUESTION_CONCERN = "check_question_concern";
public static final String KEY_IS_COLUMN_COLLECTION = "is_column_collection";//是专题合集
public static final String KEY_DRAFT_ID = "draft_id";
public static final String KEY_KAIFU_LIST = "kaifuList";
public static final String KEY_CATEGORY = "category";
public static final String KEY_CATEGORY_ID = "category_id";
public static final String KEY_CATEGORY_TITLE = "category_title";
public static final String KEY_CATEGORY_INIT_TITLE = "category_init_title";
@ -169,7 +167,6 @@ public class EntranceUtils {
public static final String KEY_COLUMN_ID = "column_id";
public static final String KEY_AUTO_DOWNLOAD = "auto_download";
public static final String KEY_HIDE_SUGGEST_HINT = "hide_suggest_hint";
public static final String KEY_HIDE_USELESS_INFO = "hide_useless_info";
public static final String KEY_COMMUNITY_ARTICLE_ID = "communityArticleId";
public static final String KEY_ARTICLE_COMMENT_ID = "articleCommentId";
public static final String KEY_SHOW_ARTICLE_COMMENT = "showArticleComment";
@ -193,7 +190,6 @@ public class EntranceUtils {
public static final String KEY_UUID = "uuid";
public static final String KEY_IS_HOME_VIDEO = "isHomeVideo";
public static final String KEY_IS_HOME = "isHome";
public static final String KEY_TAB_COUNT = "tab_count";
public static final String KEY_WEB_SHARE = "webShare";
public static final String KEY_ACTIVITY_NAME = "activityName";//活动名称
public static final String KEY_PAGINATION_TYPE = "paginationType";//活动分页方式
@ -216,26 +212,9 @@ public class EntranceUtils {
public static final String KEY_CHANGE_PHONE = "changePhone";
public static final String KEY_CONFLICT_PHONE = "conflictPhone";
public static final String KEY_CONFLICT_USER = "conflictUser";
public static final String KEY_EXPOSURE_SOURCE = "exposure_source";
public static final String KEY_BBS_ID = "bbs_id";
public static final String KEY_DIAGNOSIS = "diagnosis";
public static final String KEY_SIMULATOR = "simulator";
public static final String KEY_MARKET_DETAILS = "market_details";
public static final String KEY_CATALOG_ID = "catalogId";
public static final String KEY_PRIMARY_CATALOG_ID = "primaryCatalogId";
public static final String KEY_PRIMARY_CATALOG_NAME = "primaryCatalogName";
public static final String KEY_CATALOG_TITLE = "catalog_title";
public static final String KEY_CATALOG_INIT_TITLE = "catalog_init_title";
public static final String KEY_CATEGORY_LIST = "categoty_list";
public static final String KEY_IS_FREE = "is_free";
public static final String KEY_IS_SIGN = "is_sign";
public static final String KEY_IS_CHOOSE_APK = "is_choose_apk";
public static final String KEY_TAB_INDEX = "tab_index";
public static final String KEY_IS_CATEGORY_V2 = "is_category_v2";
public static final String KEY_SUB_CATEGORY_ID = "sub_category_id";
public static final String KEY_IS_QA_FEEDBACK = "is_qa_feedback";
public static final String KEY_IS_CLICK_RECEIVE_BTN = "is_click_receive_btn";
public static final String KEY_SHOW_QUICK_LOGIN = "show_quick_login";
public static void jumpActivity(Context context, Bundle bundle) {
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);

View File

@ -6,7 +6,6 @@ import com.gh.gamecenter.R
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.entity.ErrorEntity
import com.lightgame.utils.Utils
import retrofit2.HttpException
/**
* 这个类用来管理一些错误像弹窗、TOAST 什么的
@ -18,7 +17,6 @@ object ErrorHelper {
* [showHighPriorityHint] 用来标识有同样错误码可以触发两种处理时,为 true 时选择重要的
* [customizedHandler] 返回 true 为已处理该错误码false 则交由 [handleError] 处理
*/
@JvmStatic
fun handleErrorWithCustomizedHandler(context: Context,
errorString: String?,
showHighPriorityHint: Boolean = false,
@ -171,23 +169,4 @@ object ErrorHelper {
}, null)
}
@JvmStatic
fun handleLoginError(context: Context, httpException: HttpException?) {
try {
val errorEntity: ErrorEntity? = httpException?.response()?.errorBody()?.string()?.toObject()
when {
errorEntity?.code == 403099 -> {
Utils.toast(context, "当前账号正在注销,禁止登录")
}
errorEntity?.toast?.isNotEmpty() == true -> {
Utils.toast(context, errorEntity.toast)
}
else -> Utils.toast(context, R.string.login_failure)
}
} catch (e: Exception) {
e.printStackTrace()
Utils.toast(context, R.string.login_failure)
}
}
}

View File

@ -1,12 +1,8 @@
package com.gh.common.util
import android.animation.Animator
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.os.Build
import android.text.*
@ -47,11 +43,8 @@ import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
import com.lightgame.utils.Utils
import io.reactivex.Observable
import io.reactivex.ObservableTransformer
import io.reactivex.SingleTransformer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.RequestBody
import java.net.URI
@ -70,16 +63,11 @@ inline fun <reified VM : ViewModel> FragmentActivity.viewModelProvider(
/**
* 创建以 activity 为观察者上下文的 viewModel
* 额外的 key: 用于区分单 activity 多 viewModel 的情况 (如首页tab)
*/
inline fun <reified VM : ViewModel> Fragment.viewModelProviderFromParent(
provider: ViewModelProvider.Factory? = null,
key: String = ""
) = if (key.isEmpty()) {
ViewModelProviders.of(requireActivity(), provider).get(VM::class.java)
} else {
ViewModelProviders.of(requireActivity(), provider).get(key, VM::class.java)
}
provider: ViewModelProvider.Factory? = null
) =
ViewModelProviders.of(requireActivity(), provider).get(VM::class.java)
/**
* 创建以 activity 为观察者上下文的 viewModel
@ -121,16 +109,12 @@ fun ViewPager.addOnPageChangeListener(onSelected: ((position: Int) -> Unit)? = n
addOnPageChangeListener(listener)
}
fun ViewPager.doOnScroll(onStateChanged: ((state: Int) -> Unit)? = null,
onPageScrolled: ((position: Int, positionOffset: Float, positionOffsetPixels: Int) -> Unit)? = null,
onPageSelected: ((position: Int) -> Unit)? = null) {
fun ViewPager.addOnScrollStateChanged(onStateChanged: ((state: Int) -> Unit)? = null) {
val listener = object : ViewPager.OnPageChangeListener {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
onPageScrolled?.invoke(position, positionOffset, positionOffsetPixels)
}
override fun onPageSelected(position: Int) {
onPageSelected?.invoke(position)
}
override fun onPageScrollStateChanged(state: Int) {
@ -140,20 +124,6 @@ fun ViewPager.doOnScroll(onStateChanged: ((state: Int) -> Unit)? = null,
addOnPageChangeListener(listener)
}
/**
* Fragment related
*/
inline fun <reified T : Fragment> Fragment.fragmentFromActivity() =
parentFragmentManager.findFragmentByTag(T::class.java.simpleName) as? T
?: parentFragmentManager.fragmentFactory.instantiate(requireContext().classLoader, T::class.java.canonicalName) as T
inline fun <reified T : Fragment> Fragment.fragmentFromParentFragment() =
childFragmentManager.findFragmentByTag(T::class.java.simpleName) as? T
?: childFragmentManager.fragmentFactory.instantiate(requireContext().classLoader, T::class.java.canonicalName) as T
/**
* RecyclerView Extensions
*/
@ -285,23 +255,23 @@ fun String.containHtmlTag(): Boolean {
* 用户行为相关
*/
fun Fragment.showRegulationTestDialogIfNeeded(action: (() -> Unit)) {
if (UserManager.getInstance().userShouldTakeRegulationBaseOnLastRemind()) {
DialogUtils.showRegulationTestDialog(requireContext(),
{ DirectUtils.directToRegulationTestPage(requireContext()) },
{ action.invoke() })
} else {
// if (UserManager.getInstance().userShouldTakeRegulationBaseOnLastRemind()) {
// DialogUtils.showRegulationTestDialog(requireContext(),
// { DirectUtils.directToRegulationTestPage(requireContext()) },
// { action.invoke() })
// } else {
action()
}
// }
}
fun Context.showRegulationTestDialogIfNeeded(action: (() -> Unit)) {
if (UserManager.getInstance().userShouldTakeRegulationBaseOnLastRemind()) {
DialogUtils.showRegulationTestDialog(this,
{ DirectUtils.directToRegulationTestPage(this) },
{ action.invoke() })
} else {
// if (UserManager.getInstance().userShouldTakeRegulationBaseOnLastRemind()) {
// DialogUtils.showRegulationTestDialog(this,
// { DirectUtils.directToRegulationTestPage(this) },
// { action.invoke() })
// } else {
action()
}
// }
}
/**
@ -359,15 +329,6 @@ fun throwExceptionInDebug(message: String = "", predicate: Boolean = true) {
}
}
/**
* 在自动打包的包里弹 toast
*/
fun toastInInternalRelease(content: String) {
if (BuildConfig.BUILD_TIME != 0L) {
Utils.toast(HaloApp.getInstance(), content)
}
}
/**
* 主动抛出异常
*/
@ -427,25 +388,11 @@ fun String.getFirstElementDividedByDivider(divider: String): String {
return this
}
fun String.copyText() {
this.copyTextAndToast("")
}
fun String.copyTextAndToast(toastText: String = "复制成功") {
try {
val application = HaloApp.getInstance().application
val cmb = application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText(null, this)
cmb.setPrimaryClip(clip)
if (!TextUtils.isEmpty(toastText)) {
ToastUtils.showToast(toastText)
}
} catch (e: SecurityException) {
// 在一些情况下会报以下这样的错误,可能是以浮动窗口显示然后没有焦点?(https://developer.android.com/about/versions/10/privacy/changes#clipboard-data)
// java.lang.Throwable: java.lang.SecurityException: com.xunmeng.pinduoduo from uid 10317 not allowed to perform READ_CLIPBOARD
ToastUtils.showToast("复制失败,请重试")
}
val application = HaloApp.getInstance().application
val cmb = application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
cmb.text = this
ToastUtils.showToast(toastText)
}
fun Map<String, String>.createRequestBody(): RequestBody {
@ -489,10 +436,6 @@ fun Float.sp2px(): Int {
return (this * scale + 0.5f).toInt()
}
fun Float.roundTo(n: Int): Float {
return "%.${n}f".format(Locale.CHINA, this).toFloat()
}
/**
* PopupWindow 自动适配方向
* 弹出与锚点右对齐
@ -616,24 +559,6 @@ fun TextView.setTextChangedListener(action: (s: CharSequence, start: Int, before
})
}
/**
* List related
*/
fun <T> List<T>.safelyGetInRelease(index: Int): T? {
return if (index >= size) {
throwExceptionInDebug("这里触发了数组越界,请检查 (index $index >= size $size)")
toastInInternalRelease("这个操作可能触发闪退,请确定复现方式并联系开发处理")
null
} else {
try {
this[index]
} catch (e: IndexOutOfBoundsException) {
e.printStackTrace()
null
}
}
}
/**
* 拦截 TextView 中的 Url Span用应用内页面的形式打开链接
* @param shrankText 未展开时的文字
@ -707,10 +632,6 @@ fun Int.toColor(): Int {
return ContextCompat.getColor(HaloApp.getInstance().application, this)
}
fun Int.toDrawable(): Drawable? {
return ContextCompat.getDrawable(HaloApp.getInstance().application, this)
}
fun Int.toResString(): String {
return HaloApp.getInstance().application.resources.getString(this)
}
@ -730,16 +651,11 @@ fun SimpleDraweeView.display(url: String) {
* DownloadEntity extension
*/
fun DownloadEntity.addMetaExtra(key: String, value: String?) {
value?.let {
if (meta == null) {
meta = hashMapOf()
}
meta[key] = value
}
value?.let { meta[key] = value }
}
fun DownloadEntity.getMetaExtra(key: String): String {
return meta?.get(key) ?: ""
return meta[key] ?: ""
}
fun DownloadEntity.isSilentUpdate(): Boolean {
@ -761,9 +677,6 @@ fun Context.doOnMainProcessOnly(callback: EmptyCallback) {
doOnMainProcessOnly { callback.onCallback() }
}
/**
* 虽然现在我们没有了友盟以后只是单进程APP但在 debug 模式下还有 whatTheStack 这个进程如果不限定主进程会出现奇奇怪怪的问题 (BroadcastReceiver相关)
*/
inline fun Context.doOnMainProcessOnly(f: () -> Unit) {
val processName = PackageUtils.obtainProcessName(this)
if (processName == null || BuildConfig.APPLICATION_ID == processName) {
@ -936,25 +849,4 @@ fun SeekBar.doOnSeekBarChangeListener(progressChange: ((progress: Int) -> Unit)?
onStopTrackingTouch?.invoke()
}
})
}
fun <T> observableToMain(): ObservableTransformer<T, T> {
return ObservableTransformer { upstream ->
upstream.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
}
fun <T> singleToMain(): SingleTransformer<T, T> {
return SingleTransformer { upstream ->
upstream.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
}
fun View.getBitmapFromView(): Bitmap? {
val bitmap = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
this.draw(canvas)
return bitmap
}

View File

@ -78,9 +78,6 @@ public class GameUtils {
int pluginCount = 0; // 可插件化数量
int updateCount = 0; // 可更新数量
int installCount = 0; // 已安装数量
boolean isRelatedEmulatorInstalled = false; // 若该游戏是模拟器游戏时其对应的模拟器是否已经安装
DownloadEntity downloadEntity;
Object gh_id;
apkFor:
@ -116,10 +113,7 @@ public class GameUtils {
&& !PackageUtils.isSignedByGh(context, apkEntity.getPackageName())
&& apkEntity.isShowPlugin(pluginLocation)) {
pluginCount++;
} else if (gh_id == null
|| gh_id.equals(gameEntity.getId())
// 当使用镜像时,可能会存在镜像 gh_id 与当前游戏 id 不一样的情况,这时也让它通过,避免装完还是显示`下载`
|| gameEntity.shouldUseMirrorInfo()) {
} else if (gh_id == null || gh_id.equals(gameEntity.getId())) {
installCount++;
}
}
@ -129,26 +123,20 @@ public class GameUtils {
boolean isInstalled = PackageUtils.isInstalledFromAllPackage(context, gameEntity.getSimulator().getApk().getPackageName());
if (isInstalled) {
installCount++;
isRelatedEmulatorInstalled = true;
} else {
doneCount++;
}
}
}
}
if (isRelatedEmulatorInstalled && doneCount != 0) {
if (installCount != 0) {
return context.getString(R.string.launch);
}
if (doneCount != 0) {
return context.getString(R.string.install);
} else if (pluginCount != 0 && !SimulatorGameManager.isSimulatorGame(gameEntity)) {
return context.getString(R.string.pluggable);
} else if (updateCount != 0 && !SimulatorGameManager.isSimulatorGame(gameEntity)) {
return context.getString(R.string.update);
} else if (installCount != 0) {
return context.getString(R.string.launch);
} else if (doneCount != 0) {
return context.getString(R.string.install);
} else if (gameEntity.getVersionNumber().contains("无版号") && Config.isGameDomeSwitchOpen() && !SimulatorGameManager.isSimulatorGame(gameEntity)) {
return context.getString(R.string.attempt);
} else {

View File

@ -0,0 +1,55 @@
package com.gh.common.util
import android.app.Application
/**
* 广点通辅助类 [https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/403]
*
* 更换帐号 [https://gitlab.ghzs.com/pm/yunying/issues/893]
*/
object GdtHelper {
const val NETWORK_TYPE = "NETWORK_TYPE"
const val PAGE_TYPE = "PAGE_TYPE"
const val CONTENT_TYPE = "CONTENT_TYPE"
const val CONTENT_ID = "CONTENT_ID"
const val KEYWORD = "KEYWORD"
const val GAME_ID = "GAME_ID"
const val SCORE = "SCORE"
const val PLATFORM = "PLATFORM"
fun init(application: Application, channel: String) {
// if (channel == "GH_728") {
// GDTAction.init(application, "1111012969", "9d3d9da5b0948a317c03d08f14d445dc")
// } else if (channel == "GH_729") {
// GDTAction.init(application, "1111013063", "f53dabf458a356b101d99fc4069eb7f1")
// } else {
// GDTAction.init(application, "1110680399", "f5ddaafbf520d7d7385499232a408d0a")
// }
}
fun logAction(type: String) {
// GDTAction.logAction(type)
// Utils.log("GDT", type)
}
fun logAction(type: String, vararg kv: String?) {
// try {
// val actionParam = JSONObject()
// for (i in kv.indices) {
// if (i % 2 != 0) {
// val key = kv[i - 1]
// val value = kv[i]
// if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
// actionParam.put(key, value)
// }
// }
// }
// Utils.log("GDT", "$type + [${kv.joinToString(" , ")}]")
// GDTAction.logAction(type, actionParam)
// } catch (e: Exception) {
// e.printStackTrace()
// }
}
}

View File

@ -15,7 +15,7 @@ object HomePluggableHelper {
if (apkList.isNotEmpty()) {
val apk = apkList.first()
val tag = if (isNever) "never" else apk.version ?: ""
tryCatchInRelease { mHomePluggableFilterDao.addData(HomePluggableFilterEntity(pkgName = apk.packageName, tag = tag, active = isNever)) }
mHomePluggableFilterDao.addData(HomePluggableFilterEntity(pkgName = apk.packageName, tag = tag, active = isNever))
}
}
@ -24,39 +24,27 @@ object HomePluggableHelper {
val apkList = gameEntity.getApk()
if (apkList.isNotEmpty()) {
val apk = apkList.first()
tryCatchInRelease {
val filterData = mHomePluggableFilterDao.getDataByPkgName(apk.packageName)
if (filterData?.active == true) {
val filterTag = filterData.tag
return filterTag != "never" && apk.version != filterTag
}
val filterData = mHomePluggableFilterDao.getDataByPkgName(apk.packageName)
if (filterData?.active == true) {
val filterTag = filterData.tag
return filterTag != "never" && apk.version != filterTag
}
}
return true
}
@JvmStatic
fun getPermanentInactivePluggablePackage(): List<HomePluggableFilterEntity>? {
tryCatchInRelease {
return mHomePluggableFilterDao.getDataByTag("never")
}
return emptyList()
}
fun getPermanentInactivePluggablePackage() = mHomePluggableFilterDao.getDataByTag("never")
@JvmStatic
fun activationFilterData() {
try {
val filterList = mHomePluggableFilterDao.getDataByActive(false)
val filterList = mHomePluggableFilterDao.getDataByActive(false)
if (filterList != null) {
for (entity in filterList) {
entity.active = true
}
mHomePluggableFilterDao.addData(filterList)
if (filterList != null) {
for (entity in filterList) {
entity.active = true
}
} catch (e: Exception) {
e.printStackTrace()
toastInInternalRelease("数据库/磁盘已满,插件筛选失败")
mHomePluggableFilterDao.addData(filterList)
}
}
}

View File

@ -67,15 +67,4 @@ public class HtmlUtils {
return htmlStr.trim(); //返回文本字符串
}
/**
* 过滤掉标签,保留标签内容
*/
public static String filterHtmlLabel(String htmlStr) {
String regEx_html = "<[^>]+>([\\s\\S]*?)<\\/[^>]+>"; //定义HTML标签的正则表达式
Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
Matcher m_html = p_html.matcher(htmlStr);
htmlStr = m_html.replaceAll("$1"); //过滤html标签
return htmlStr.trim(); //返回文本字符串
}
}

View File

@ -24,7 +24,6 @@ import com.facebook.imagepipeline.image.CloseableImage
import com.facebook.imagepipeline.image.ImageInfo
import com.facebook.imagepipeline.request.ImageRequest
import com.facebook.imagepipeline.request.ImageRequestBuilder
import com.facebook.imagepipeline.request.Postprocessor
import com.gh.common.constant.Config
import com.gh.common.structure.FixedSizeLinkedHashSet
import com.gh.gamecenter.R
@ -43,8 +42,6 @@ object ImageUtils {
private val LARGE_GIF_SIZE = 80F.dip2px()
private val STANDARD_GIF_SIZE = 60F.dip2px()
const val TARGET_WIDTH = R.dimen.width_placeholder
private val mImageUrlCacheSet by lazy { FixedSizeLinkedHashSet<String>(maxSize = 200) }
@JvmStatic
@ -88,14 +85,8 @@ object ImageUtils {
@JvmStatic
fun addLimitWidth(imageUrl: String?, width: Int?): String? {
val jpegConfig = Config.getSettings()?.image?.oss?.jpeg
val webpConfig = Config.getSettings()?.image?.oss?.webp
?: Config.getSettings()?.image?.oss?.gif
if (jpegConfig != null) {
return if (width == 0 || width == null) {
"$imageUrl$webpConfig"
} else {
"$imageUrl$jpegConfig,w_$width"
}
return "$imageUrl$jpegConfig,w_$width"
}
return imageUrl
}
@ -288,112 +279,92 @@ object ImageUtils {
})
}
@JvmStatic
fun display(view: SimpleDraweeView?, url: String?) {
display(view, url, true)
}
/**
* 规则 width>0 Wifi/4G:x2 traffic:x1
* 统一加载 webp 忽略掉第二种方案
* 第一种方案:通过LayoutParams获取 可以快速(无延迟)获取宽高,但是无法获取wrap_content和match_parent的View
* ~~第二种方案(备用方案):有延迟,View的宽高需要在Measure过程后才能确定,能够在这里获取到正确的宽高~~
* @param isAutoPlayGif 是否禁止播放动图
* 第二种方案(备用方案):有延迟,View的宽高需要在Measure过程后才能确定,能够在这里获取到正确的宽高
*/
@JvmStatic
fun display(view: SimpleDraweeView?,
url: String?,
isAutoPlayGif: Boolean = true,
processor: Postprocessor? = null) {
if (url == null) return
fun display(view: SimpleDraweeView?, url: String?) {
url?.let {
val width = view?.layoutParams?.width
val height = view?.layoutParams?.height
// 部分自适应宽高图片需要一个 TARGET_WIDTH 来避免加载过小图片
val width = (view?.getTag(TARGET_WIDTH) as? Int) ?: view?.layoutParams?.width
val height = view?.layoutParams?.height
var lowResUrl = ""
var highResUrl = ""
var lowResUrl = ""
var highResUrl = ""
// 找同一图片地址已加载过的图片作为低质量预览图
// TODO 根据实际请求大小(w_width)来避免小图用大图作为低质量图片
for (cachedImageUrl in mImageUrlCacheSet) {
if (url.isNotEmpty() && cachedImageUrl.contains(url)) {
lowResUrl = cachedImageUrl
break
// 找同一图片地址已加载过的图片作为低质量预览图
// TODO 根据实际请求大小(w_width)来避免小图用大图作为低质量图片
for (cachedImageUrl in mImageUrlCacheSet) {
if (cachedImageUrl.contains(url)) {
lowResUrl = cachedImageUrl
break
}
}
}
val loadImageClosure: (autoPlay: Boolean, highResUrl: String, lowResUrl: String) -> Unit = { autoPlay, hUrl, lUrl ->
val imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(hUrl))
.setPostprocessor(processor)
.build()
val controller = Fresco.newDraweeControllerBuilder()
.setImageRequest(imageRequest)
.apply {
if (lUrl.isNotEmpty()
&& lUrl != hUrl
&& hUrl != view?.getTag(R.string.highResImageTag)) {
lowResImageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(lUrl))
.setPostprocessor(processor)
.build()
val loadImageClosure: (autoPlay: Boolean, highResUrl: String, lowResUrl: String) -> Unit = { autoPlay, hUrl, lUrl ->
view?.controller = Fresco.newDraweeControllerBuilder()
.setImageRequest(ImageRequest.fromUri(hUrl))
.apply {
if (lUrl.isNotEmpty()
&& lUrl != hUrl
&& hUrl != view?.getTag(R.string.highResImageTag)) {
lowResImageRequest = ImageRequest.fromUri(lUrl)
}
autoPlayAnimations = autoPlay
}
autoPlayAnimations = autoPlay
}
.build()
view?.controller = controller
.build()
view?.setTag(R.string.highResImageTag, highResUrl)
}
view?.setTag(R.string.highResImageTag, highResUrl)
}
// 低于 2G 运行内存的不加载 gif
val shouldLoadAsGif = url.endsWith(".gif")
&& isAutoPlayGif
&& (HaloApp.getInstance().deviceRamSize == 0L || HaloApp.getInstance().deviceRamSize > 2500)
&& view?.getTag(R.id.tag_show_gif) != false
val shouldLoadAsGif = it.endsWith(".gif") && view?.getTag(R.id.tag_show_gif) != false
if (shouldLoadAsGif && view?.tag == url) return
if (shouldLoadAsGif && view?.tag == url) return
if (!shouldLoadAsGif) {
highResUrl = getTransformLimitUrl(url, width ?: 0, view?.context) ?: ""
loadImageClosure(shouldLoadAsGif, highResUrl, lowResUrl)
} else {
if (width != null && width > 0) {
highResUrl = resizeGif(url, view!!.width, height ?: 0)
highResUrl = if (shouldLoadAsGif) {
resizeGif(url, width, height ?: 0)
} else {
getTransformLimitUrl(url, width, view.context) ?: ""
}
loadImageClosure(shouldLoadAsGif, highResUrl, lowResUrl)
} else {
view?.post {
highResUrl = resizeGif(url, view.width, height ?: 0)
highResUrl = if (shouldLoadAsGif) {
resizeGif(url, view.width, height ?: 0)
} else {
getTransformLimitUrl(url, view.width, view.context) ?: ""
}
loadImageClosure(shouldLoadAsGif, highResUrl, lowResUrl)
}
}
view?.tag = url
}
view?.tag = url
}
// Wifi/4G:x2 traffic:x1
@JvmStatic
fun getTransformLimitUrl(url: String?, width: Int?, context: Context?): String? {
val transformUrl: String?
var transformUrl: String? = url
if (width != null && width > 0) {
// 加载大小是实际 ImageView 大小两倍的图片真的有意义吗?
val transformUrlX2 = addLimitWidth(url, width * 2)
val transformUrlX1 = addLimitWidth(url, width)
// 当网络为 WIFI 或 4G 且系统版本大于 5.0 && 手机内存大于 4G 才用高清图片 (x2)
transformUrl = if (NetworkUtils.isWifiOr4GConnected(context)
// 当网络为 WIFI 或 4G 且系统版本大于 5.0 && 手机内存大于 1G 才用高清图片
if (NetworkUtils.isWifiOr4GConnected(context)
&& Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP
&& HaloApp.getInstance().deviceRamSize > 4500) {
transformUrlX2
&& HaloApp.getInstance().deviceRamSize > 1024) {
transformUrl = transformUrlX2
} else {
// 检查X2大图是否被缓存
if (Fresco.getImagePipeline().isInBitmapMemoryCache(Uri.parse(transformUrlX2)) ||
Fresco.getImagePipeline().isInDiskCacheSync(Uri.parse(transformUrlX2))) {
transformUrlX2
transformUrl = transformUrlX2
} else {
transformUrlX1
transformUrl = transformUrlX1
}
}
} else {
transformUrl = addLimitWidth(url, null)
}
addCachedUrl(transformUrl ?: "")
return transformUrl
@ -406,7 +377,9 @@ object ImageUtils {
if (width != null && width > 0) {
view.setImageURI(addLimitWidth(url, width * 2))
} else {
view?.setImageURI(addLimitWidth(url, view.width * 2))
view?.post {
view.setImageURI(addLimitWidth(url, view.width * 2))
}
}
}
@ -416,18 +389,6 @@ object ImageUtils {
}
}
/**
* 获取已缓存的图片地址,不区分质量,暂时只供查看大图页面使用
*/
fun getCachedUrl(url: String): String {
for (decoratedUrl in mImageUrlCacheSet) {
if (decoratedUrl.contains(url)) {
return decoratedUrl
}
}
return url
}
@JvmStatic
fun bmpToByteArray(bmp: Bitmap, needRecycle: Boolean): ByteArray {
val output = ByteArrayOutputStream()
@ -477,29 +438,11 @@ object ImageUtils {
}
}
interface OnImageloadListener {
public interface OnImageloadListener {
fun onLoadFinal(imageInfo: ImageInfo?)
}
fun getVideoSnapshot(videoUrl: String, progress: Long): String {
return "$videoUrl?x-oss-process=video/snapshot,t_$progress,f_jpg,w_0,h_0"
}
/**
* 虽然在 Application 里有使用子线程初始化但有可能出现初始化超时(卡住?)的情况,
* 这里反射获取 sDraweecontrollerbuildersupplier 根据是否有值确定是否被初始化了
*/
@JvmStatic
fun isFrescoInitialized(): Boolean {
val clazz = SimpleDraweeView::class.java
return try {
val field =
clazz.getDeclaredField("sDraweecontrollerbuildersupplier")
field.isAccessible = true
val obj = field[SimpleDraweeView::class.java]
obj != null
} catch (ignore: java.lang.Exception) {
false
}
}
}

View File

@ -48,7 +48,7 @@ public class InstallUtils {
public void handleMessage(Message msg) {
if (msg.what == INSTALL_WHAT && packageManager != null) {
ArrayList<String> list = new ArrayList<>();
List<PackageInfo> packageInfos = PackageUtils.getInstalledPackages(context, 0);
List<PackageInfo> packageInfos = packageManager.getInstalledPackages(0);
for (PackageInfo packageInfo : packageInfos) {
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
list.add(packageInfo.packageName);

View File

@ -18,11 +18,11 @@ public class Installation {
private static String sID = null;
public synchronized static String getUUID(Context context) {
String imei = MetaUtil.getBase64EncodedIMEI();
String imei = MetaUtil.getIMEI();
if (!TextUtils.isEmpty(imei)) {
return imei;
}
String android_id = MetaUtil.getBase64EncodedAndroidId();
String android_id = MetaUtil.getAndroidId();
if (!TextUtils.isEmpty(android_id)) {
return android_id;
}

View File

@ -1,157 +0,0 @@
package com.gh.common.util
import com.gh.common.loghub.LoghubUtils.log
import com.gh.common.tracker.Tracker.launchId
import com.gh.common.tracker.Tracker.sessionId
import com.lightgame.utils.Utils
import org.json.JSONObject
object IntegralLogHelper {
fun log(event: String, location: String) = log(event, location, null)
fun log(event: String, location: String, entrance: String? = null) {
val json = JSONObject().apply {
tryWithDefaultCatch {
put("meta", LogUtils.getMetaObject())
put("event", event)
put("location", location)
put("timestamp", System.currentTimeMillis() / 1000)
put("launch_id", launchId)
put("session_id", sessionId)
entrance?.let {
put("entrance", it)
}
}
}
debugOnly {
Utils.log("LogUtils->$json")
}
log(json, "score", false)
}
fun logTask(event: String, location: String, jobId: String, jobName: String, jobType: String) {
val json = JSONObject().apply {
tryWithDefaultCatch {
put("meta", LogUtils.getMetaObject())
put("event", event)
put("location", location)
put("timestamp", System.currentTimeMillis() / 1000)
put("launch_id", launchId)
put("session_id", sessionId)
put("job_id", jobId)
put("job_name", jobName)
put("job_type", jobType)
}
}
debugOnly {
Utils.log("LogUtils->$json")
}
log(json, "score", false)
}
fun logCommodityCategory(event: String, location: String, entrance: String, categoryId: String, categoryName: String) {
val json = JSONObject().apply {
tryWithDefaultCatch {
put("meta", LogUtils.getMetaObject())
put("event", event)
put("location", location)
put("timestamp", System.currentTimeMillis() / 1000)
put("launch_id", launchId)
put("session_id", sessionId)
put("entrance", entrance)
put("goods_species_id", categoryId)
put("goods_species_name", categoryName)
}
}
debugOnly {
Utils.log("LogUtils->$json")
}
log(json, "score", false)
}
fun logCommodity(event: String, location: String, commodityId: String, categoryId: String, categoryName: String) {
val json = JSONObject().apply {
tryWithDefaultCatch {
put("meta", LogUtils.getMetaObject())
put("event", event)
put("location", location)
put("timestamp", System.currentTimeMillis() / 1000)
put("launch_id", launchId)
put("session_id", sessionId)
put("goods_id", commodityId)
put("goods_species_id", categoryId)
put("goods_species_name", categoryName)
}
}
debugOnly {
Utils.log("LogUtils->$json")
}
log(json, "score", false)
}
fun logEnergyRange(event: String, location: String, range: String) {
val json = JSONObject().apply {
tryWithDefaultCatch {
put("meta", LogUtils.getMetaObject())
put("event", event)
put("location", location)
put("timestamp", System.currentTimeMillis() / 1000)
put("launch_id", launchId)
put("session_id", sessionId)
put("energy_range", range)
}
}
debugOnly {
Utils.log("LogUtils->$json")
}
log(json, "score", false)
}
fun logPendent(event: String, location: String, pendentId: String, pendentType: String? = null) {
val json = JSONObject().apply {
tryWithDefaultCatch {
put("meta", LogUtils.getMetaObject())
put("event", event)
put("location", location)
put("timestamp", System.currentTimeMillis() / 1000)
put("launch_id", launchId)
put("session_id", sessionId)
put("pendant_id", pendentId)
pendentType?.run {
put("pendant_type", this)
}
}
}
debugOnly {
Utils.log("LogUtils->$json")
}
log(json, "score", false)
}
fun logInviteResult(result: String, type: String? = null) {
val json = JSONObject().apply {
tryWithDefaultCatch {
put("meta", LogUtils.getMetaObject())
put("event", "invite_result")
put("location", "邀请途径面板")
put("timestamp", System.currentTimeMillis() / 1000)
put("launch_id", launchId)
put("session_id", sessionId)
put("invitation_result", result)
put("invitation_type", type)
}
}
debugOnly {
Utils.log("LogUtils->$json")
}
log(json, "score", false)
}
}

View File

@ -1,6 +1,7 @@
package com.gh.common.util;
import android.app.Dialog;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.graphics.Color;
@ -10,8 +11,6 @@ import android.text.TextUtils;
import android.util.Log;
import android.widget.TextView;
import androidx.core.content.ContextCompat;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.R;
import com.gh.gamecenter.adapter.LibaoDetailAdapter;
@ -28,18 +27,16 @@ import com.gh.gamecenter.manager.UserManager;
import com.gh.gamecenter.retrofit.JSONObjectResponse;
import com.gh.gamecenter.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.halo.assistant.HaloApp;
import com.lightgame.utils.Utils;
import org.greenrobot.eventbus.EventBus;
import org.json.JSONException;
import org.json.JSONObject;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import androidx.core.content.ContextCompat;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
@ -154,10 +151,9 @@ public class LibaoUtils {
});
}
public static void setLiBaoBtnStatusRound(final TextView libaoBtn, LibaoEntity libaoEntity, boolean shouldUpdateStatus, Context context) {
String status = shouldUpdateStatus ? updateStatus(libaoEntity) : libaoEntity.getStatus();
public static void setLiBaoBtnStatusRound(final TextView libaoBtn, String status, Context context) {
libaoBtn.setTextColor(Color.WHITE);
if (status == null || TextUtils.isEmpty(status)) return;
if (TextUtils.isEmpty(status)) return;
switch (status) {
case "ling":
libaoBtn.setText(R.string.libao_ling);
@ -184,8 +180,8 @@ public class LibaoUtils {
break;
case "linged":
libaoBtn.setText(R.string.libao_linged);
libaoBtn.setBackgroundResource(R.drawable.button_border_round_gray);
libaoBtn.setTextColor(context.getResources().getColor(R.color.button_gray));
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_border);
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme_font));
break;
case "taoed":
libaoBtn.setText(R.string.libao_taoed);
@ -197,17 +193,23 @@ public class LibaoUtils {
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
break;
case "repeatLing":
case "repeatLinged":
libaoBtn.setText(R.string.libao_repeat_ling);
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_border);
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme_font));
break;
case "repeatLinged":
libaoBtn.setText(R.string.libao_repeat_ling);
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
break;
case "repeatTao":
case "repeatTaoed":
libaoBtn.setText(R.string.libao_repeat_tao);
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_border);
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme_font));
break;
case "repeatTaoed":
libaoBtn.setText(R.string.libao_repeat_tao);
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
break;
case "unshelve":
libaoBtn.setBackgroundResource(R.drawable.button_border_round_gray);
libaoBtn.setText(R.string.libao_unshelve);
@ -225,272 +227,198 @@ public class LibaoUtils {
}
}
public static String updateStatus(LibaoEntity libaoEntity) {
String status = libaoEntity.getStatus();
String beforeStatus = libaoEntity.getBeforeStatus();
if (libaoEntity.getRepeat() > 0 && libaoEntity.getMe() != null
&& libaoEntity.getMe().getUserDataLibaoList() != null) {
MeEntity userData = libaoEntity.getMe();
List<UserDataLibaoEntity> userDataLibaoList = userData.getUserDataLibaoList();
int repeat = libaoEntity.getRepeat();
int curStatusCount = 0; // 当前状态的领取/淘号数量
for (UserDataLibaoEntity userDataLibaoEntity : userDataLibaoList) {
if (beforeStatus != null && beforeStatus.equals(userDataLibaoEntity.getType())) {
curStatusCount++;
}
}
// 由领取到淘号的状态转换
if (repeat <= curStatusCount || curStatusCount == 0) { // 当前领取/淘号总数是否超过总重复领取次数 / 当前状态的礼包没有领取/淘号过
if (curStatusCount == 0 && ("ling".equals(beforeStatus) || "tao".equals(beforeStatus))) {
if (isCanLing(libaoEntity)) { // 恢复原始状态
return beforeStatus;
}
}
return status;
}
if ((("linged").equals(status) || ("taoed").equals(status)) &&
("ling".equals(beforeStatus) || "tao".equals(beforeStatus))) { //检查是否到了重复领取时间
if (isCanLing(libaoEntity)) {
if ("ling".equals(beforeStatus)) {
return "repeatLinged"; // 可以重复领取
} else {
return "repeatTaoed"; // 可以重复领取
}
} else {
if ("ling".equals(beforeStatus)) {
return "repeatLing"; // 预备重复领取
} else {
return "repeatTao"; // 预备重复领取
}
}
}
}
return status;
}
public static boolean isCanLing(LibaoEntity libaoEntity) {
List<UserDataLibaoEntity> userDataLibaoList = libaoEntity.getMe().getUserDataLibaoList();
UserDataLibaoEntity userDataLibaoEntity = userDataLibaoList.get(userDataLibaoList.size() - 1);
SimpleDateFormat formatDay = new SimpleDateFormat("dd", Locale.CHINA);
long lingTime = userDataLibaoEntity.getTime() * 1000;
long curTime = Utils.getTime(HaloApp.getInstance()) * 1000;
int lingDay = Integer.parseInt(formatDay.format(lingTime));
int curDay = Integer.parseInt(formatDay.format(curTime));
if (curDay != lingDay || curTime - lingTime > 24 * 60 * 60 * 1000) {
return true;
} else {
return false;
}
}
public static void initLibaoBtn(final Context context, final TextView libaoBtn, final LibaoEntity libaoEntity,
final boolean isInstallRequired, final LibaoDetailAdapter adapter, boolean shouldUpdateStatus, final String entrance) {
final boolean isInstallRequired, final LibaoDetailAdapter adapter, final String entrance) {
String status = libaoEntity.getStatus();
setLiBaoBtnStatusRound(libaoBtn, libaoEntity, shouldUpdateStatus, context);
if (adapter != null) {
if (libaoBtn.getText().toString().equals("再领")) {
libaoBtn.setText("再领一个");
}
if (libaoBtn.getText().toString().equals("再淘")) {
libaoBtn.setText("再淘一个");
}
}
setLiBaoBtnStatusRound(libaoBtn, status, context);
libaoBtn.setOnClickListener(v -> {
String btnStatus = libaoBtn.getText().toString();
// 领取限制
CheckLoginUtils.checkLogin(context, "礼包详情-[" + btnStatus + "]", () -> {
if ("领取".equals(btnStatus) || "淘号".equals(btnStatus)) {
if (isInstallRequired && !isAppInstalled(context, libaoEntity.getPackageName())) {
String platform;
if (TextUtils.isEmpty(libaoEntity.getPlatform())) {
platform = "";
} else {
platform = PlatformUtils.getInstance(context).getPlatformName(libaoEntity.getPlatform());
}
boolean isExistPlatform = false;
ArrayList<ApkEntity> apk = adapter.getGameEntity().getApk();
for (ApkEntity apkEntity : apk) {
if (TextUtils.isEmpty(libaoEntity.getPlatform())) break;
if (libaoEntity.getPlatform().equals(apkEntity.getPlatform())) {
isExistPlatform = true;
break;
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(context, () -> {
if ("领取".equals(btnStatus) || "淘号".equals(btnStatus)) {
if (isInstallRequired && !isAppInstalled(context, libaoEntity.getPackageName())) {
String platform;
if (TextUtils.isEmpty(libaoEntity.getPlatform())) {
platform = "";
} else {
platform = PlatformUtils.getInstance(context).getPlatformName(libaoEntity.getPlatform());
}
}
String dialogContent = context.getString(R.string.ling_rules_dialog, libaoEntity.getGame().getName(), platform);
boolean finalIsExistPlatform = isExistPlatform;
DialogUtils.showWarningDialog(context, "条件不符",
Html.fromHtml(dialogContent), isExistPlatform ? "关闭" : null,
isExistPlatform ? "立即安装" : "关闭",
() -> {
if (finalIsExistPlatform) {
adapter.openDownload(libaoEntity.getPlatform());
boolean isExistPlatform = false;
ArrayList<ApkEntity> apk = adapter.getGameEntity().getApk();
for (ApkEntity apkEntity : apk) {
if (TextUtils.isEmpty(libaoEntity.getPlatform())) break;
if (libaoEntity.getPlatform().equals(apkEntity.getPlatform())) {
isExistPlatform = true;
break;
}
}
String dialogContent = context.getString(R.string.ling_rules_dialog, libaoEntity.getGame().getName(), platform);
boolean finalIsExistPlatform = isExistPlatform;
DialogUtils.showWarningDialog(context, "条件不符",
Html.fromHtml(dialogContent), isExistPlatform ? "关闭" : null,
isExistPlatform ? "立即安装" : "关闭",
() -> {
if (finalIsExistPlatform) {
adapter.openDownload(libaoEntity.getPlatform());
}
}, null);
return;
}
}
switch (btnStatus) {
case "未开始":
Utils.toast(context, "还没到开始领取时间");
break;
case "查看":
if (!TextUtils.isEmpty(libaoEntity.getDes())) {
DialogUtils.showAlertDialog(v.getContext(), "使用说明",
Html.fromHtml(libaoEntity.getDes()), "关闭", null, null, null);
}
break;
case "再领一个":
case "领取":
if ("repeatLing".equals(status)) {
DialogUtils.showWarningDialog(context, "礼包刷新提醒"
, "礼包每天0点刷新换新区或者换新角色需要继续领取礼包的童鞋请于明天0点之后回来即可[再领一个]"
, null, "知道了", null, null);
} else {
libaoLing(context, libaoBtn, libaoEntity, adapter, isInstallRequired, null, entrance);
}
break;
case "再淘一个":
case "淘号":
if ("repeatTao".equals(status)) {
Utils.toast(context, "没到重复淘号时间, 礼包每天0点刷新");
return;
}
final Dialog loadingDialog = DialogUtils.showWaitDialog(context, "淘号中...");
postLibaoTao(context, libaoEntity.getId(), new PostLibaoListener() {
@Override
public void postSucceed(Object response) {
if (loadingDialog != null) loadingDialog.dismiss();
JSONObject responseBody = (JSONObject) response;
String libaoCode = null;
try {
libaoCode = responseBody.getString("code");
} catch (JSONException e) {
e.printStackTrace();
}
}, null);
return;
}
}
switch (btnStatus) {
case "未开始":
Utils.toast(context, "还没到开始领取时间");
break;
case "查看":
if (!TextUtils.isEmpty(libaoEntity.getDes())) {
DialogUtils.showAlertDialog(v.getContext(), "使用说明",
Html.fromHtml(libaoEntity.getDes()), "关闭", null, null, null);
}
break;
case "再领":
case "再领一个":
case "领取":
if ("repeatLing".equals(status)) {
DialogUtils.showWarningDialog(context, "礼包刷新提醒"
, "礼包每天0点刷新换新区或者换新角色需要继续领取礼包的童鞋请于明天0点之后回来即可[再领一个]"
, null, "知道了", null, null);
} else {
libaoLing(context, libaoBtn, libaoEntity, adapter, isInstallRequired, null, entrance);
}
break;
case "再淘":
case "再淘一个":
case "淘号":
libaoTao(context, libaoBtn, libaoEntity, isInstallRequired, adapter, status, entrance);
break;
}
});
});
}
if (TextUtils.isEmpty(libaoCode)) {
try {
String detail = responseBody.getString("detail");
switch (detail) {
case "maintaining":
Utils.toast(context, "网络状态异常,请稍后再试");
break;
case "fail to compete":
Utils.toast(context, "淘号失败,稍后重试");
break;
default:
Utils.toast(context, "淘号异常");
break;
}
} catch (JSONException e) {
e.printStackTrace();
}
return;
}
private static void libaoTao(Context context, TextView libaoBtn, LibaoEntity libaoEntity, boolean isInstallRequired, LibaoDetailAdapter adapter, String status, String entrance) {
if ("repeatTao".equals(status)) {
Utils.toast(context, "没到重复淘号时间, 礼包每天0点刷新");
return;
}
final Dialog loadingDialog = DialogUtils.showWaitDialog(context, "淘号中...");
postLibaoTao(context, libaoEntity.getId(), new PostLibaoListener() {
@Override
public void postSucceed(Object response) {
Utils.toast(context, "淘号成功");
if (loadingDialog != null) loadingDialog.dismiss();
libaoEntity.setStatus("taoed");
JSONObject responseBody = (JSONObject) response;
String libaoCode = null;
boolean hasSame = false;
try {
hasSame = responseBody.getBoolean("has_same");
libaoCode = responseBody.getString("code");
} catch (JSONException e) {
e.printStackTrace();
}
EventBus.getDefault().post(new EBReuse("libaoChanged"));
if (TextUtils.isEmpty(libaoCode)) {
try {
String detail = responseBody.getString("detail").toLowerCase();
switch (detail) {
case "maintaining":
Utils.toast(context, "网络状态异常,请稍后再试");
break;
case "fail to compete":
Utils.toast(context, "淘号失败,稍后重试");
break;
default:
Utils.toast(context, "淘号异常");
break;
}
} catch (JSONException e) {
e.printStackTrace();
}
return;
}
Utils.toast(context, "淘号成功");
libaoEntity.setStatus("taoed");
EventBus.getDefault().post(new EBReuse("libaoChanged"));
adapter.initLibaoCode(new UserDataLibaoEntity(libaoCode, "tao", Utils.getTime(context)));
uploadEvent(libaoEntity, true, entrance);
final String finalLibaoCode = libaoCode;
String des;
if (!hasSame) {
des = "淘到的礼包码不保证可以兑换,请尽快前往游戏兑换";
} else {
des = "您已领取过相同的礼包,可能无法成功兑换,请自行尝试";
}
DialogUtils.showReceiveLibaoSuccessDialog(context, "淘号成功", des, finalLibaoCode, () -> {
copyLink(finalLibaoCode, context);
if (isInstallRequired) {
libaoBtn.postDelayed(() -> {
Spanned msg = Html.fromHtml(
context.getString(R.string.taoed_copy_dialog
, finalLibaoCode));
lunningAppDialog(context
, msg, libaoEntity);
}, 300);
adapter.initLibaoCode(new UserDataLibaoEntity(libaoCode, "tao", Utils.getTime(context)));
final String finalLibaoCode = libaoCode;
DialogUtils.showWarningDialog(context, "淘号成功"
, Html.fromHtml(context.getString(R.string.taoed_dialog, libaoCode))
, "关闭", " 复制礼包码"
, () -> {
copyLink(finalLibaoCode, context);
if (isInstallRequired) {
libaoBtn.postDelayed(() -> {
Spanned msg = Html.fromHtml(
context.getString(R.string.taoed_copy_dialog
, finalLibaoCode));
lunningAppDialog(context
, msg, libaoEntity);
}, 300);
}
}, null);
}
@Override
public void postFailed(Throwable error) {
Utils.log("---" + error.toString());
if (loadingDialog != null) loadingDialog.dismiss();
if (error instanceof HttpException) {
HttpException exception = (HttpException) error;
if (exception.code() == 403) {
try {
JSONObject errorJson = new JSONObject(exception.response().errorBody().string());
String detail = errorJson.getString("detail");
// Utils.toast(context, "返回::" + detail);
switch (detail) {
case "coming":
Utils.toast(context, "礼包领取时间未开始");
break;
case "finish":
Utils.toast(context, "礼包领取时间已结束");
break;
case "fetched":
Utils.toast(context, "你今天已领过这个礼包了, 不能再淘号");
libaoBtn.setText("已淘号");
libaoBtn.setBackgroundResource(R.drawable.libao_taoed_style);
libaoBtn.setTextColor(ContextCompat.getColorStateList(context, R.color.libao_taoed_selector));
libaoEntity.setStatus("taoed");
break;
case "try tao":
case "used up":
DialogUtils.showHintDialog(context, "礼包已领光"
, "手速不够快,礼包已经被抢光了,十分抱歉", "知道了");
break;
case "maintaining":
Utils.toast(context, "网络状态异常,请稍后再试");
break;
case "fail to compete":
Utils.toast(context, "淘号失败,稍后重试");
break;
default:
Utils.toast(context, "操作失败");
break;
}
} catch (Exception ex) {
ex.printStackTrace();
Utils.toast(context, "礼包处理异常" + ex.toString());
}
return;
} else if (exception.code() == 401) {
return;
}
}
Utils.toast(context, "发生异常");
}
});
break;
}
});
}
@Override
public void postFailed(Throwable error) {
Utils.log("---" + error.toString());
if (loadingDialog != null) loadingDialog.dismiss();
if (error instanceof HttpException) {
HttpException exception = (HttpException) error;
if (exception.code() == 403) {
try {
JSONObject errorJson = new JSONObject(exception.response().errorBody().string());
String detail = errorJson.getString("detail").toLowerCase();
switch (detail) {
case "coming":
Utils.toast(context, "礼包领取时间未开始");
break;
case "finish":
Utils.toast(context, "礼包领取时间已结束");
break;
case "fetched":
Utils.toast(context, "你今天已领过这个礼包了, 不能再淘号");
libaoBtn.setText("已淘号");
libaoBtn.setBackgroundResource(R.drawable.libao_taoed_style);
libaoBtn.setTextColor(ContextCompat.getColorStateList(context, R.color.libao_taoed_selector));
libaoEntity.setStatus("taoed");
break;
case "try tao":
case "used up":
DialogUtils.showHintDialog(context, "礼包已领光"
, "手速不够快,礼包已经被抢光了,十分抱歉", "知道了");
break;
case "maintaining":
Utils.toast(context, "网络状态异常,请稍后再试");
break;
case "fail to compete":
Utils.toast(context, "淘号失败,稍后重试");
break;
default:
Utils.toast(context, "操作失败");
break;
}
} catch (Exception ex) {
ex.printStackTrace();
Utils.toast(context, "礼包处理异常" + ex.toString());
}
return;
} else if (exception.code() == 401) {
return;
}
}
Utils.toast(context, "发生异常");
}
});
});
}
@ -509,56 +437,45 @@ public class LibaoUtils {
if (loadingDialog != null) loadingDialog.dismiss();
JSONObject responseBody = (JSONObject) response;
boolean hasSame = false; //是否领取过相同的礼包
String libaoCode = null;
int gameApkSize = 1;//游戏apk的size大于1为“多版本插件游戏”否则为“非插件游戏/单版本插件游戏”
try {
hasSame = responseBody.getBoolean("has_same");
libaoCode = responseBody.getString("code");
gameApkSize = responseBody.getInt("game_apk_size");
} catch (JSONException e) {
e.printStackTrace();
}
if (TextUtils.isEmpty(libaoCode)) {
Utils.toast(context, "领取异常");
return;
}
libaoEntity.setAvailable(libaoEntity.getAvailable() - 1);
libaoEntity.setStatus("linged");
EventBus.getDefault().post(new EBReuse("libaoChanged"));
uploadEvent(libaoEntity, false, entrance);
libaoEntity.setStatus("linged");
EventBus.getDefault().post(new EBReuse("libaoChanged"));
adapter.initLibaoCode(new UserDataLibaoEntity(libaoCode, "ling", Utils.getTime(context)));
adapter.notifyDataSetChanged();
final String finalLibaoCode = libaoCode;
boolean finalHasSame = hasSame;
int finalGameApkSize = gameApkSize;
NotificationHelper.showNotificationHintDialog(NotificationUgc.GIFT, isShow -> {
if (!isShow) {
String des;
if (!finalHasSame) {
if (finalGameApkSize > 1) {
des = "礼包码将于60分钟后进入淘号池部分礼包兑换有平台限制请根据使用说明兑换";
} else {
des = "礼包码将于60分钟后进入淘号池,请尽快前往游戏兑换";
}
} else {
des = "您已领取过相同的礼包,可能无法成功兑换,请自行尝试";
}
DialogUtils.showReceiveLibaoSuccessDialog(context, "领取成功", des, finalLibaoCode, () -> {
copyLink(finalLibaoCode, context);
if (isInstallRequired) {
libaoBtn.postDelayed(() -> {
Spanned msg = Html.fromHtml(context.getString(R.string.linged_copy_dialog, finalLibaoCode));
lunningAppDialog(context
, msg, libaoEntity);
}, 300);
}
});
if (!isShow){
DialogUtils.showWarningDialog(context, "领取成功", Html.fromHtml(context.getString(R.string.linged_dialog, finalLibaoCode))
, "关闭", " 复制礼包码"
, () -> {
copyLink(finalLibaoCode, context);
if (isInstallRequired) {
libaoBtn.postDelayed(() -> {
Spanned msg = Html.fromHtml(context.getString(R.string.linged_copy_dialog, finalLibaoCode));
lunningAppDialog(context
, msg, libaoEntity);
}, 300);
}
}, null);
}
return null;
});
}
@Override
@ -571,7 +488,7 @@ public class LibaoUtils {
try {
String string = exception.response().errorBody().string();
JSONObject errorJson = new JSONObject(string);
String detail = errorJson.getString("detail").toLowerCase();
String detail = errorJson.getString("detail");
switch (detail) {
case "coming":
Utils.toast(context, "礼包领取时间未开始");
@ -601,7 +518,7 @@ public class LibaoUtils {
DialogUtils.showHintDialog(context, "礼包已领光"
, "手速不够快,礼包已经被抢光了,十分抱歉", "知道了");
libaoEntity.setStatus("used_up");
initLibaoBtn(context, libaoBtn, libaoEntity, isInstallRequired, adapter, false, entrance);
initLibaoBtn(context, libaoBtn, libaoEntity, isInstallRequired, adapter, entrance);
break;
case "maintaining":
Utils.toast(context, "网络状态异常,请稍后再试");
@ -629,26 +546,9 @@ public class LibaoUtils {
}, captchaCode);
}
private static void uploadEvent(LibaoEntity libaoEntity, boolean isTao, String entrance) {
String location = "";
if (!libaoEntity.getClickReceiveBtnIn()) {
location = "礼包详情";
} else {
if (entrance.contains("游戏详情")) {
location = "游戏详情";
} else if (entrance.contains("礼包中心:最新")) {
location = "礼包中心-最新";
} else if (entrance.contains("礼包中心:关注")) {
location = "礼包中心-关注";
}
}
String event = isTao ? "game_gift_dig_successful" : "game_gift_get_successful";
LogUtils.uploadReceiveGift(event, libaoEntity.getId(), libaoEntity.getName(), location,
libaoEntity.getGame() == null ? "" : libaoEntity.getGame().getId(), libaoEntity.getGame() == null ? "" : libaoEntity.getGame().getName());
}
public static boolean isAppInstalled(Context context, String packageName) {
List<PackageInfo> pinfo = PackageUtils.getInstalledPackages(context, 0);
final android.content.pm.PackageManager packageManager = context.getPackageManager();
List<PackageInfo> pinfo = packageManager.getInstalledPackages(0);
if (pinfo != null) {
for (int i = 0; i < pinfo.size(); i++) {
String pn = pinfo.get(i).packageName;
@ -676,7 +576,10 @@ public class LibaoUtils {
//复制文字
public static void copyLink(String copyContent, Context context) {
ExtensionsKt.copyTextAndToast(copyContent, copyContent + " 复制成功");
ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
cmb.setText(copyContent);
Utils.toast(context, copyContent + " 复制成功");
}

View File

@ -16,12 +16,9 @@ import com.gh.common.loghub.LoghubUtils;
import com.gh.common.loghub.SimpleLogContainerEntity;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.entity.CommunityEntity;
import com.gh.gamecenter.entity.DetectionObjectEntity;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.PackageDialogEntity;
import com.gh.gamecenter.entity.ShareResultEntity;
import com.gh.gamecenter.entity.SpecialColumn;
import com.gh.gamecenter.entity.StartupAdEntity;
import com.gh.gamecenter.manager.UserManager;
import com.gh.gamecenter.qa.entity.Questions;
import com.gh.gamecenter.retrofit.EmptyResponse;
@ -29,7 +26,6 @@ import com.gh.gamecenter.retrofit.RetrofitManager;
import com.halo.assistant.HaloApp;
import com.lightgame.utils.Utils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@ -37,7 +33,6 @@ import java.util.ArrayList;
import java.util.List;
import androidx.annotation.Nullable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.RequestBody;
@ -239,11 +234,6 @@ public class LogUtils {
object.put("game_name", gameEntity.getName());
object.put("game_id", gameEntity.getId());
object.put("game_platform", gameEntity.getPlatform());
if (event != null) {
object.put("sequence", event.getPayload().getSequence());
object.put("outer_sequence", event.getPayload().getOuterSequence());
}
object.put("download_open", gameEntity.getDownloadOffStatus() == null ? "true" : "false");
} catch (JSONException e) {
e.printStackTrace();
}
@ -264,15 +254,14 @@ public class LogUtils {
try {
object.put("version", PackageUtils.getVersionName());
object.put("channel", HaloApp.getInstance().getChannel());
object.put("dia", MetaUtil.getBase64EncodedAndroidId());
object.put("android_id", MetaUtil.getAndroidId());
object.put("time", Utils.getTime(context));
object.put("network", DeviceUtils.getNetwork(context));
object.put("user_id", UserManager.getInstance().getUserId());
object.put("device_system", android.os.Build.VERSION.RELEASE);
object.put("device_model", android.os.Build.MODEL);
object.put("jnfj", MetaUtil.getBase64EncodedIMEI());
object.put("imei", MetaUtil.getIMEI());
object.put("G_ID", UserManager.getInstance().getDeviceId());
object.put("oaid", HaloApp.getInstance().getOAID());
} catch (JSONException e) {
e.printStackTrace();
}
@ -289,13 +278,13 @@ public class LogUtils {
try {
object.put("version", PackageUtils.getVersionName());
object.put("channel", HaloApp.getInstance().getChannel());
object.put("dia", MetaUtil.getBase64EncodedAndroidId());
object.put("android_id", MetaUtil.getAndroidId());
object.put("time", Utils.getTime(context));
object.put("network", DeviceUtils.getNetwork(context));
object.put("user_id", UserManager.getInstance().getUserId());
object.put("device_system", android.os.Build.VERSION.RELEASE);
object.put("device_model", android.os.Build.MODEL);
object.put("jnfj", MetaUtil.getBase64EncodedIMEI());
object.put("imei", MetaUtil.getIMEI());
object.put("G_ID", UserManager.getInstance().getDeviceId());
} catch (JSONException e) {
e.printStackTrace();
@ -308,13 +297,13 @@ public class LogUtils {
Meta meta = MetaUtil.INSTANCE.getMeta();
JSONObject metaObject = new JSONObject();
try {
metaObject.put("dia", MetaUtil.getBase64EncodedAndroidId());
metaObject.put("android_id", meta.getAndroid_id());
metaObject.put("android_sdk", meta.getAndroid_sdk());
metaObject.put("android_version", meta.getAndroid_version());
metaObject.put("appVersion", meta.getAppVersion());
metaObject.put("channel", meta.getChannel());
metaObject.put("gid", meta.getGid());
metaObject.put("jnfj", MetaUtil.getBase64EncodedIMEI());
metaObject.put("imei", meta.getImei());
metaObject.put("mac", meta.getMac());
metaObject.put("manufacturer", meta.getManufacturer());
metaObject.put("model", meta.getModel());
@ -386,63 +375,6 @@ public class LogUtils {
uploadVideoStreaming(object);
}
public static void uploadTopVideoStreamingPlaying(String action, String videoId, String videoTitle, String gameId, String gameName, String videoModel, String videoPlayStatus, double videoSize, int videoTotalTime, int videoPlayTs, int progress) {
JSONObject object = new JSONObject();
JSONObject payloadObject = new JSONObject();
try {
object.put("event", "TOP_VIDEO_PLAYING");
object.put("action", action);
payloadObject.put("video_mode", videoModel);//视频播放方式 ["自动播放"/"点击播放"/"全屏播放"]
payloadObject.put("video_id", videoId);
payloadObject.put("video_title", videoTitle);
payloadObject.put("game_id", gameId);
payloadObject.put("game_name", gameName);
payloadObject.put("video_size", videoSize);
payloadObject.put("video_total_time", videoTotalTime);
payloadObject.put("progress", progress);
payloadObject.put("video_play_ts", videoPlayTs);
payloadObject.put("video_play_status", videoPlayStatus);
object.put("payload", payloadObject);
object.put("meta", getMetaObject());
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "video_streaming", false);
}
public static void uploadHomeVideoStreamingPlaying(String action, boolean videoShade, String videoId, String videoTitle, String gameId, String gameName, double videoSize, int videoTotalTime, int videoPlayTs, int progress) {
JSONObject object = new JSONObject();
JSONObject payloadObject = new JSONObject();
try {
object.put("event", "HOME_VIDEO_PLAYING");
object.put("action", action);
payloadObject.put("video_id", videoId);
payloadObject.put("video_title", videoTitle);
payloadObject.put("game_id", gameId);
payloadObject.put("game_name", gameName);
payloadObject.put("video_size", videoSize);
payloadObject.put("video_total_time", videoTotalTime);
payloadObject.put("progress", progress);
payloadObject.put("video_play_ts", videoPlayTs);
payloadObject.put("video_shade", String.valueOf(videoShade));//["true"/"false"]是否存在引导遮罩
object.put("payload", payloadObject);
object.put("meta", getMetaObject());
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "video_streaming", false);
}
public static void uploadWelcomeDialog(String action, String dialogId, String linkTitle) {
ExposureEntity payload = new ExposureEntity();
payload.setWelcomeDialogId(dialogId);
@ -496,13 +428,13 @@ public class LogUtils {
Meta meta = MetaUtil.INSTANCE.getMeta();
JSONObject metaObject = new JSONObject();
try {
metaObject.put("dia", MetaUtil.getBase64EncodedAndroidId());
metaObject.put("android_id", meta.getAndroid_id());
metaObject.put("android_sdk", meta.getAndroid_sdk());
metaObject.put("android_version", meta.getAndroid_version());
metaObject.put("appVersion", meta.getAppVersion());
metaObject.put("channel", meta.getChannel());
metaObject.put("gid", meta.getGid());
metaObject.put("jnfj", MetaUtil.getBase64EncodedIMEI());
metaObject.put("imei", meta.getImei());
metaObject.put("mac", meta.getMac());
metaObject.put("manufacturer", meta.getManufacturer());
metaObject.put("model", meta.getModel());
@ -590,20 +522,19 @@ public class LogUtils {
Meta meta = MetaUtil.INSTANCE.getMeta();
JSONObject metaObject = new JSONObject();
try {
metaObject.put("dia", MetaUtil.getBase64EncodedAndroidId());
metaObject.put("android_id", meta.getAndroid_id());
metaObject.put("android_sdk", meta.getAndroid_sdk());
metaObject.put("android_version", meta.getAndroid_version());
metaObject.put("appVersion", meta.getAppVersion());
metaObject.put("channel", meta.getChannel());
metaObject.put("gid", meta.getGid());
metaObject.put("jnfj", MetaUtil.getBase64EncodedIMEI());
metaObject.put("imei", meta.getImei());
metaObject.put("mac", meta.getMac());
metaObject.put("manufacturer", meta.getManufacturer());
metaObject.put("model", meta.getModel());
metaObject.put("network", meta.getNetwork());
metaObject.put("os", meta.getOs());
metaObject.put("userId", meta.getUserId());
metaObject.put("oaid", HaloApp.getInstance().getOAID());
} catch (JSONException e) {
e.printStackTrace();
@ -680,16 +611,10 @@ public class LogUtils {
}
public static void uploadSearchGame(String event, String location, String key, String searchType) {
uploadSearchClick(event, location, key, searchType, "", "", false);
uploadSearchClick(event, location, key, searchType, "", "");
}
public static void uploadSearchClick(String event,
String location,
String key,
String searchType,
String gameId,
String gameName,
Boolean isMirrorData) {
public static void uploadSearchClick(String event, String location, String key, String searchType, String gameId, String gameName) {
JSONObject object = new JSONObject();
JSONObject payload = new JSONObject();
try {
@ -702,7 +627,6 @@ public class LogUtils {
payload.put("search_type", searchType); //搜索类型, 有四种取值 默认搜索/历史搜索/自动搜索/主动搜索
payload.put("game_id", gameId); //event为search_click才取值
payload.put("game_name", gameName); //event为search_click才取值
payload.put("is_mirror_data", isMirrorData);
object.put("payload", payload);
} catch (JSONException e) {
e.printStackTrace();
@ -713,450 +637,4 @@ public class LogUtils {
}
LoghubUtils.log(object, "event", false);
}
public static void logGameDetailStrategyButtonEvent(String gameId,
String gameName,
String text) {
JSONObject object = new JSONObject();
try {
object.put("event", "game_detail_click_strategy_button");
object.put("timestamp", System.currentTimeMillis() / 1000);
object.put("meta", getMetaObject());
object.put("game_id", gameId);
object.put("game_name", gameName);
object.put("text", text);
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "event", false);
}
public static void logServerTestAccessEvent(String entrance,
String entranceDetail,
String serverTestName,
String serverTestNote) {
JSONObject payload = new JSONObject();
try {
payload.put("server_test_name", serverTestName);
payload.put("server_test_note", serverTestNote);
payload.put("entrance", entrance);
payload.put("entrance_detail", entranceDetail);
} catch (JSONException e) {
e.printStackTrace();
}
logServerTestEvent("access_to_server_test", payload);
}
public static void logServerTestSelectTypeEvent(String buttonText,
String serverTestName,
String serverTestNote) {
JSONObject payload = new JSONObject();
try {
payload.put("server_test_name", serverTestName);
payload.put("server_test_note", serverTestNote);
payload.put("button_text", buttonText);
} catch (JSONException e) {
e.printStackTrace();
}
logServerTestEvent("server_test_select_type", payload);
}
public static void logServerTestSelectTimeEvent(String buttonText,
String serverTestName,
String serverTestNote) {
JSONObject payload = new JSONObject();
try {
payload.put("server_test_name", serverTestName);
payload.put("server_test_note", serverTestNote);
payload.put("button_text", buttonText);
} catch (JSONException e) {
e.printStackTrace();
}
logServerTestEvent("server_test_select_time", payload);
}
public static void logServerTestClickAllEvent(String serverTestName,
String serverTestNote) {
JSONObject payload = new JSONObject();
try {
payload.put("server_test_name", serverTestName);
payload.put("server_test_note", serverTestNote);
} catch (JSONException e) {
e.printStackTrace();
}
logServerTestEvent("server_test_click_all", payload);
}
public static void logServerTestClickMoreEvent(String serverTestName,
String serverTestNote,
String redirectType,
String redirectLink) {
JSONObject payload = new JSONObject();
try {
payload.put("server_test_name", serverTestName);
payload.put("server_test_note", serverTestNote);
payload.put("redirect_type", redirectType);
payload.put("redirect_link", redirectLink);
} catch (JSONException e) {
e.printStackTrace();
}
logServerTestEvent("server_test_click_more", payload);
}
private static void logServerTestEvent(String event, JSONObject payload) {
JSONObject object = new JSONObject();
try {
object.put("event", event);
object.put("meta", getMetaObject());
object.put("timestamp", System.currentTimeMillis() / 1000);
object.put("payload", payload);
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "event", false);
}
public static void logNewCatalogAppearanceEvent(String entrance, String key) {
logCatalogEvent("access_to_classification", entrance, key, -1, -1, -1, -1);
}
public static void logSubCatalogClickEvent(String entrance, String key, int seq1) {
logCatalogEvent("click_first_classification", entrance, key, seq1, -1, -1, -1);
}
public static void logSubCatalogContentClickEvent(String entrance, String key, int seq1, int seq2) {
logCatalogEvent("click_secondary_classification", entrance, key, seq1, seq2, -1, -1);
}
public static void logSpecialCatalogContentClickEvent(String entrance, String key, int seq1, int seqContent) {
logCatalogEvent("click_content", entrance, key, seq1, -1, seqContent, -1);
}
public static void logSpecialCatalogSpecificContentClickEvent(String entrance, String key, int seq1, int seqContent, int seqContentList) {
logCatalogEvent("click_content_list", entrance, key, seq1, -1, seqContent, seqContentList);
}
public static void logSpecialCatalogBannerClickEvent(String key, int seq) {
JSONObject object = new JSONObject();
try {
object.put("event", "category_lunbo_click");
object.put("meta", getMetaObject());
object.put("timestamp", System.currentTimeMillis() / 1000);
object.put("key", key);
object.put("sequence", seq);
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "event", false);
}
private static void logCatalogEvent(String event, String entrance, String key, int seq1, int seq2, int seqContent, int seqContentList) {
JSONObject object = new JSONObject();
JSONObject payload = new JSONObject();
try {
object.put("event", event);
object.put("meta", getMetaObject());
object.put("timestamp", System.currentTimeMillis() / 1000);
payload.put("entrance", entrance); //入口分类, 分为 首页或版块,
payload.put("key", key); //搜索类型, 有四种取值 默认搜索/历史搜索/自动搜索/主动搜索
payload.put("seq_1st", seq1); //从0开始,默认-1表示没有
payload.put("seq_2nd", seq2); //从0开始,默认-1表示没有
payload.put("seq_content", seqContent); //精选页上 图片、专题-全部按钮、专题合集-全部按钮 的排序;从0开始,默认-1表示没有
payload.put("seq_content_list", seqContentList);
object.put("payload", payload);
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "event", false);
}
public static void uploadPackageSkip(String event, String action, String gameId, String gameName) {
JSONObject object = new JSONObject();
try {
object.put("event", event);//external_jump/external_show
object.put("action", action);
if (!TextUtils.isEmpty(gameId) && !TextUtils.isEmpty(gameName)) {
object.put("game_id", gameId);
object.put("game_name", gameName);
}
object.put("meta", getMetaObject());
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "event", false);
}
public static void logStartAd(String event, StartupAdEntity adEntity) {
JSONObject object = new JSONObject();
try {
object.put("event", event);
object.put("timestamp", System.currentTimeMillis() / 1000);
object.put("meta", getMetaObject());
if (adEntity != null) {
object.put("abs_id", adEntity.getId());
object.put("abs_text", adEntity.getDesc());
if (adEntity.getButton()) {
object.put("abs_type", adEntity.getJump().getType());
object.put("abs_link", adEntity.getJump().getLink());
object.put("abs_link_title", adEntity.getJump().getText());
}
}
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "event", false);
}
public static void logRecommendClick(String entrance, String recommendName, String linkType, String linkTitle, int sequence) {
JSONObject object = new JSONObject();
try {
object.put("event", "recommend_click");
object.put("timestamp", System.currentTimeMillis() / 1000);
object.put("meta", getMetaObject());
object.put("entrance", entrance);
object.put("recommend_name", recommendName);
object.put("link_type", linkType);
object.put("link_title", linkTitle);
object.put("sequence", sequence);
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "event", false);
}
public static void uploadPackageCheck(String event, String action, GameEntity gameEntity, String linkTitle, String linkDesc, String downloadGameId, String downloadGameName) {
if (gameEntity == null) return;
PackageDialogEntity packageDialog = gameEntity.getPackageDialog();
if (packageDialog == null) return;
JSONObject object = new JSONObject();
JSONObject payloadObject = new JSONObject();
try {
object.put("event", event);
object.put("action", action);
payloadObject.put("game_id", gameEntity.getId());
payloadObject.put("game_name", gameEntity.getName());
payloadObject.put("link_title", linkTitle);
payloadObject.put("link_desc", linkDesc);
payloadObject.put("download_game_id", downloadGameId);
payloadObject.put("download_game_name", downloadGameName);
JSONArray detectionArray = new JSONArray();
for (DetectionObjectEntity entity : packageDialog.getDetectionObjects()) {
JSONObject detectionObject = new JSONObject();
detectionObject.put("text", entity.getText());
detectionObject.put("packages", new JSONArray(GsonUtils.toJson(entity.getPackages())));
detectionArray.put(detectionObject);
}
payloadObject.put("detection_objects", detectionArray);
object.put("meta", getMetaObject());
object.put("payload", payloadObject);
object.put("timestamp", System.currentTimeMillis() / 1000);
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "event", false);
}
public static void logCategoryV2AppearanceEvent(String entrance, String classification) {
logCategoryV2Event("access_to_classification_v2", entrance, classification, "", "", "", "", "", -1, -1, -1, -1);
}
public static void logCategoryV2ClickSideEvent(String entrance, String classification, String sideClassification, int seq) {
logCategoryV2Event("click_side", entrance, classification, sideClassification, "", "", "", "", seq, -1, -1, -1);
}
public static void logCategoryV2ClickClassificationEvent(String entrance, String classification, String sideClassification, String classification1, String classification2, int seq1, int seq2) {
logCategoryV2Event("click_classification", entrance, classification, sideClassification, classification1, classification2, "", "", -1, -1, seq1, seq2);
}
public static void logCategoryV2ClickClassificationDeleteEvent(String entrance, String classification, String classification1, String classification2, String location) {
logCategoryV2Event("click_classification_delete", entrance, classification, "", classification1, classification2, "", location, -1, -1, -1, -1);
}
public static void logCategoryV2ClickDetermineEvent(String entrance, String classification, String classification2) {
logCategoryV2Event("click_determine", entrance, classification, "", "", classification2, "", "", -1, -1, -1, -1);
}
public static void logCategoryV2ClickResetEvent(String entrance, String classification, String classification2, String location) {
logCategoryV2Event("click_reset", entrance, classification, "", "", classification2, "", location, -1, -1, -1, -1);
}
public static void logSpecialCategoryV2BannerClickEvent(String entrance, String classification, String detail, int seq) {
logCategoryV2Event("category_lunbo_click_v2", entrance, classification, "", "", "", detail, "", seq, -1, -1, -1);
}
public static void logSpecialCategoryV2ContentClickEvent(String entrance, String classification, String detail, int seq) {
logCategoryV2Event("click_content_v2", entrance, classification, "", "", "", detail, "", seq, -1, -1, -1);
}
public static void logSpecialCategoryV2SpecificContentClickEvent(String entrance, String classification, String detail, int seq, int outSeq) {
logCategoryV2Event("click_content_list_v2", entrance, classification, "", "", "", detail, "", seq, outSeq, -1, -1);
}
public static void logCategoryV2Event(String event,
String entrance,
String classification,
String sideClassification,
String classification1,
String classification2,
String detail,
String location,
int seq,
int outSeq,
int seq1,
int seq2) {
JSONObject object = new JSONObject();
try {
object.put("event", event);
object.put("meta", getMetaObject());
object.put("timestamp", System.currentTimeMillis() / 1000);
object.put("entrance", entrance);
object.put("classification", classification);
object.put("side_classification", sideClassification);
object.put("classification_1st", classification1);
object.put("classification_2nd", classification2);
object.put("detail", detail);
object.put("location", location);
object.put("sequence", seq);
object.put("outer_sequence", outSeq);
object.put("seq_1st", seq1);
object.put("seq_2nd", seq2);
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "event", false);
}
public static void logGameDetailFixedTopArticleClick(String gameId, String gameName, String url) {
JSONObject object = new JSONObject();
try {
object.put("event", "game_detail_click_top_strategy");
object.put("game_id", gameId);
object.put("game_name", gameName);
object.put("top_strategy_url", url);
object.put("meta", getMetaObject());
object.put("timestamp", System.currentTimeMillis() / 1000);
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "event", false);
}
public static void logHomeTopTabClick(String tabName, String linkType, String linkTitle, int sequence) {
JSONObject object = new JSONObject();
try {
object.put("event", "top_tab_click");
object.put("tab_name", tabName);
object.put("link_type", linkType);
object.put("link_title", linkTitle);
object.put("sequence", sequence);
object.put("meta", getMetaObject());
object.put("timestamp", System.currentTimeMillis() / 1000);
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "event", false);
}
public static void uploadRecommendPopup(String event, String popupId, String gameId, String gameName,
String linkType, String linkTitle, String downloadGameId, String downloadGameName) {
JSONObject object = new JSONObject();
JSONObject payloadObject = new JSONObject();
try {
object.put("event", event);//recommend_pop_show推荐弹窗出现、recommend_pop_close推荐弹窗手动关闭、recommend_pop_link_click点击推荐弹窗链接、recommend_pop_download推荐弹窗下载开始、recommend_pop_download_complete推荐弹窗下载完成
payloadObject.put("recommend_pop_id", popupId);
payloadObject.put("game_id", gameId);
payloadObject.put("game_name", gameName);
if (!TextUtils.isEmpty(linkType)) {
payloadObject.put("link_type", linkType);
}
if (!TextUtils.isEmpty(linkTitle)) {
payloadObject.put("link_title", linkTitle);
}
if (!TextUtils.isEmpty(downloadGameId)) {
payloadObject.put("download_game_id", downloadGameId);
}
if (!TextUtils.isEmpty(downloadGameName)) {
payloadObject.put("download_game_name", downloadGameName);
}
object.put("payload", payloadObject);
object.put("meta", getMetaObject());
object.put("timestamp", System.currentTimeMillis() / 1000);
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "event", false);
}
public static void uploadReceiveGift(String event, String giftId, String giftName, String location, String gameId, String gameName) {
JSONObject object = new JSONObject();
JSONObject payloadObject = new JSONObject();
try {
object.put("event", event);//game_gift_get_successful领取礼包、game_gift_dig_successful淘号
payloadObject.put("gift_id", giftId);
payloadObject.put("gift_name", giftName);
payloadObject.put("location", location);
payloadObject.put("game_id", gameId);
payloadObject.put("game_name", gameName);
object.put("payload", payloadObject);
object.put("meta", getMetaObject());
object.put("timestamp", System.currentTimeMillis() / 1000);
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "event", false);
}
}

View File

@ -8,7 +8,6 @@ import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
@ -30,10 +29,7 @@ import android.widget.TextView;
import com.gh.common.Base64ImageHolder;
import com.gh.common.constant.Config;
import com.gh.gamecenter.R;
import com.gh.gamecenter.WeiBoShareActivity;
import com.lightgame.utils.Utils;
import com.sina.weibo.sdk.WbSdk;
import com.sina.weibo.sdk.auth.AuthInfo;
import com.tencent.connect.auth.QQToken;
import com.tencent.connect.share.QQShare;
import com.tencent.mm.opensdk.modelmsg.SendMessageToWX;
@ -52,8 +48,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.Date;
import static com.gh.common.util.LoginHelper.WEIBO_SCOPE;
import java.util.List;
/**
* Created by khy on 2016/11/8.
@ -70,9 +65,6 @@ public class MessageShareUtils {
private PopupWindow mPopupWindow;
private Bitmap shareBm; //分享截图
private String picName;
private ShareWay shareWay;
private boolean isFromInviteFriends = false;
private String mWriteBitmapPath;
private String[] mArrLabel = {"微信好友", "朋友圈", "QQ好友", "QQ空间", "保存"};
@ -84,51 +76,23 @@ public class MessageShareUtils {
R.drawable.share_save
};
public enum ShareWay {
qq("qq"),
qqZone("qq空间"),
weibo("微博"),
wechat("微信"),
wechatMoments("朋友圈");
private String name;
ShareWay(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
//QQ或者QQ空间分享回调处理
public IUiListener QqShareListener = new IUiListener() {
@Override
public void onComplete(Object o) {
Utils.toast(mContext, "分享成功");
if (isFromInviteFriends) {
IntegralLogHelper.INSTANCE.logInviteResult("成功", shareWay.getName());
}
}
@Override
public void onError(UiError uiError) {
if (isFromInviteFriends) {
IntegralLogHelper.INSTANCE.logInviteResult("失败", shareWay.getName());
}
// 单分享图片不支持显示未安装弹窗,手动调出
if (mActivity != null) {
Activity activity = mActivity.get();
if (activity != null && !ShareUtils.isQQClientAvailable(activity.getApplication())) {
new TDialog(activity,
"",
"http://openmobile.qq.com/oauth2.0/m_jump_by_version",
null,
new QQToken("")).show();
} else {
Utils.toast(mContext, "分享失败");
}
Activity activity = mActivity.get();
if (activity != null && !ShareUtils.isQQClientAvailable(activity.getApplication())) {
new TDialog(activity,
"",
"http://openmobile.qq.com/oauth2.0/m_jump_by_version",
null,
new QQToken("")).show();
} else {
Utils.toast(mContext, "分享失败");
}
@ -137,9 +101,6 @@ public class MessageShareUtils {
@Override
public void onCancel() {
Utils.toast(mContext, R.string.share_cancel_hint);
if (isFromInviteFriends) {
IntegralLogHelper.INSTANCE.logInviteResult("取消", shareWay.getName());
}
}
};
@ -156,12 +117,6 @@ public class MessageShareUtils {
mTencent = Tencent.createInstance(Config.TENCENT_APPID, context); //初始化QQ分享
mIWXAPI = WXAPIFactory.createWXAPI(context, Config.WECHAT_APPID); //初始化微信分享
mContext = context.getApplicationContext();
// 安卓11无法访问Android/data目录
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
mWriteBitmapPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/ShareImg/";
} else {
mWriteBitmapPath = context.getExternalCacheDir().getPath() + "/ShareImg/";
}
}
public static MessageShareUtils getInstance(Context context) {
@ -251,70 +206,55 @@ public class MessageShareUtils {
});
}
public void shareInviteFriends(Activity activity, String type) {
isFromInviteFriends = true;
shareFromWeb(activity, type);
}
public void shareFromWeb(Activity activity, String type) {
// base64转bitmap
byte[] decode = Base64.decode(Base64ImageHolder.INSTANCE.getImage(), Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(decode, 0, decode.length);
// 转完后重新置位
Base64ImageHolder.INSTANCE.setImage("");
this.picName = "shareImgPic.jpg";
this.mActivity = new WeakReference<>(activity);
this.shareBm = bitmap;
if ("weibo".equals(type)) {
shareWay = ShareWay.weibo;
weiboShare();
} else {
// base64转bitmap
byte[] decode = Base64.decode(Base64ImageHolder.INSTANCE.getImage(), Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(decode, 0, decode.length);
// 转完后重新置位
Base64ImageHolder.INSTANCE.setImage("");
this.picName = "shareImgPic.jpg";
this.shareBm = bitmap;
// 保存图片
File file = new File(activity.getExternalCacheDir().getPath() + "/ShareImg");
if (!file.isDirectory()) {
file.delete();
file.mkdirs();
}
if (!file.exists()) {
file.mkdirs();
}
writeBitmap(file.getPath(), picName, bitmap, false);
// 保存图片
File file = new File(mWriteBitmapPath);
if (!file.isDirectory()) {
file.delete();
file.mkdirs();
}
if (!file.exists()) {
file.mkdirs();
}
writeBitmap(file.getPath(), picName, bitmap, false);
// 分享
switch (type) {
case "qq" :
shareWay = ShareWay.qq;
qqShare();
break;
case "qq_zone" :
shareWay = ShareWay.qqZone;
qZoneShare();
break;
case "wechat" :
shareWay = ShareWay.wechat;
wechatShare();
break;
case "wechat_moments" :
shareWay = ShareWay.wechatMoments;
wechatMomentsShare();
break;
case "save" :
String savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/ghzhushou/";
writeBitmap(savePath, "gh-" + new Date().getTime() + ".jpg", shareBm, true);
break;
}
// 分享
switch (type) {
case "qq" :
qqSahre();
break;
case "qq_zone" :
qZoneSahre();
break;
case "wechat" :
wechatSahre();
break;
case "wechat_moments" :
wechatMomentsSahre();
case "save" :
String savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/ghzhushou/";
writeBitmap(savePath, "gh-" + new Date().getTime() + ".jpg", shareBm, true);
break;
}
}
//QQ分享
private void qqShare() {
private void qqSahre() {
Utils.toast(mContext, "分享跳转中...");
Bundle params = new Bundle();
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE,
QQShare.SHARE_TO_QQ_TYPE_IMAGE);
params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, mWriteBitmapPath + picName);
params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, mContext.getExternalCacheDir().getPath() + "/ShareImg/" + picName);
params.putString(QQShare.SHARE_TO_QQ_APP_NAME, mContext.getString(R.string.app_name));
params.putInt(QQShare.SHARE_TO_QQ_EXT_INT,
QQShare.SHARE_TO_QQ_FLAG_QZONE_ITEM_HIDE);
@ -329,12 +269,12 @@ public class MessageShareUtils {
}
//QQ空间分享
private void qZoneShare() {
private void qZoneSahre() {
Utils.toast(mContext, "分享跳转中...");
Bundle params = new Bundle();
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE,
QQShare.SHARE_TO_QQ_TYPE_IMAGE);
params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, mWriteBitmapPath + picName);
params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, mContext.getExternalCacheDir().getPath() + "/ShareImg/" + picName);
params.putString(QQShare.SHARE_TO_QQ_APP_NAME, mContext.getString(R.string.app_name));
params.putInt(QQShare.SHARE_TO_QQ_EXT_INT,
QQShare.SHARE_TO_QQ_FLAG_QZONE_AUTO_OPEN);
@ -349,7 +289,7 @@ public class MessageShareUtils {
}
//微信好友分享
private void wechatShare() {
private void wechatSahre() {
Utils.toast(mContext, "分享跳转中...");
if (!PackageHelper.INSTANCE.getLocalPackageNameSet().contains("com.tencent.mm")) {
@ -359,7 +299,7 @@ public class MessageShareUtils {
//官方分享
WXImageObject imgObj = new WXImageObject();
imgObj.setImagePath(mWriteBitmapPath + picName);
imgObj.setImagePath(mContext.getExternalCacheDir().getPath() + "/ShareImg/" + picName);
WXMediaMessage msg = new WXMediaMessage();
msg.mediaObject = imgObj;
@ -385,7 +325,7 @@ public class MessageShareUtils {
}
//微信朋友圈分享
private void wechatMomentsShare() {
private void wechatMomentsSahre() {
Utils.toast(mContext, "分享跳转中...");
if (!PackageHelper.INSTANCE.getLocalPackageNameSet().contains("com.tencent.mm")) {
@ -394,7 +334,7 @@ public class MessageShareUtils {
}
WXImageObject imgObj = new WXImageObject();
imgObj.setImagePath(mWriteBitmapPath + picName);
imgObj.setImagePath(mContext.getExternalCacheDir().getPath() + "/ShareImg/" + picName);
WXMediaMessage msg = new WXMediaMessage();
msg.mediaObject = imgObj;
@ -412,20 +352,6 @@ public class MessageShareUtils {
mPopupWindow.dismiss();
}
//新浪微博分享
public void weiboShare() {
WbSdk.install(mContext, new AuthInfo(mContext, Config.WEIBO_APPKEY, "http://www.sina.com", WEIBO_SCOPE));
Activity activity = mActivity.get();
if (activity != null) {
Intent intent = WeiBoShareActivity.getWeiboImageShareIntent(activity);
activity.startActivity(intent);
}
if (mPopupWindow == null) return;
mPopupWindow.dismiss();
}
private String buildTransaction(final String type) {
return (type == null) ? String.valueOf(System.currentTimeMillis()) : type + System.currentTimeMillis();
}
@ -548,22 +474,22 @@ public class MessageShareUtils {
holder.itemView.setOnClickListener(v -> {
switch (holder.getPosition()) {
case 0:
wechatShare();
wechatSahre();
if (shareType != 2) {
// activity.finish();
}
break;
case 1:
wechatMomentsShare();
wechatMomentsSahre();
if (shareType != 2) {
// activity.finish();
}
break;
case 2:
qqShare();
qqSahre();
break;
case 3:
qZoneShare();
qZoneSahre();
break;
case 4:
String savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/ghzhushou/";

View File

@ -9,7 +9,7 @@ object MtaHelper {
// if (kv.size == 1) {
// prop.setProperty(kv[0], kv[0])
// StatService.trackCustomKVEvent(HaloApp.getInstance().application, eventId, prop)
// Utils.log("MTA", "$eventId + [${kv.joinToString(" , ")}]")
// Utils.log("MTA","$eventId + [${kv.joinToString(" , ")}]")
// return
// }
//
@ -23,7 +23,7 @@ object MtaHelper {
// }
// }
//
// Utils.log("MTA", "$eventId + [${kv.joinToString(" , ")}]")
// Utils.log("MTA","$eventId + [${kv.joinToString(" , ")}]")
// StatService.trackCustomKVEvent(HaloApp.getInstance().application, eventId, prop)
}
@ -45,7 +45,7 @@ object MtaHelper {
// }
//
// if (prop.size == 0) return
// Utils.log("MTA", "$eventId + [${kv.joinToString(" , ")}] + last $time seconds")
// Utils.log("MTA","$eventId + [${kv.joinToString(" , ")}] + last $time seconds")
// StatService.trackCustomKVTimeIntervalEvent(HaloApp.getInstance().application, time, eventId, prop)
}
@ -75,7 +75,7 @@ object MtaHelper {
// prop.setProperty("GID", HaloApp.getInstance().gid)
// }
//
// Utils.log("MTA", "$eventId + [${kv.joinToString(" , ")}]")
// Utils.log("MTA","$eventId + [${kv.joinToString(" , ")}]")
// StatService.trackCustomKVEvent(HaloApp.getInstance().application, eventId, prop)
}

View File

@ -5,11 +5,6 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.telephony.TelephonyManager;
import com.cmic.sso.sdk.auth.AuthnHelper;
import org.json.JSONException;
import org.json.JSONObject;
public class NetworkUtils {
/**
@ -80,26 +75,6 @@ public class NetworkUtils {
return false;
}
/**
* 判断是否打开数据流量(一键登录必须要打开流量才能获取到手机号码)
*
* AuthnHelper的getNetworkType方法用于获取用户当前的网络环境和运营商返回的是JSONObject其中
* operatorType字段获取网络运营商: 0.未知 1.移动流量 2.联通流量 3.电信流量,
* networkType字段获取网络状态0.未知1.流量 2.wifi3.数据流量+wifi
*/
public static boolean isOpenMobileData(Context context){
AuthnHelper helper = AuthnHelper.getInstance(context);
JSONObject jsonObject = helper.getNetworkType(context);
int net;
try {
net = Integer.parseInt(jsonObject.getString("networkType"));
if (net == 1 || net == 3) return true;
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
/**
* 获取当前网络连接的类型信息
*

View File

@ -58,7 +58,7 @@ object NotificationHelper {
when (ugc) {
NotificationUgc.LOGIN -> {
if (!isShowedLogin) {
show(AppManager.getInstance().recentActiveActivity as? AppCompatActivity, ugc, callBack)
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_LOGIN, true)
// 设置今天的时间,表示今天已经触发过了
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
@ -68,7 +68,7 @@ object NotificationHelper {
}
NotificationUgc.QUESTION -> {
if (!isShowedQuestion) {
show(AppManager.getInstance().recentActiveActivity as? AppCompatActivity, ugc, callBack)
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_QUESTION, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
@ -77,7 +77,7 @@ object NotificationHelper {
}
NotificationUgc.ANSWER -> {
if (!isShowedAnswer) {
show(AppManager.getInstance().recentActiveActivity as? AppCompatActivity, ugc, callBack)
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ANSWER, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
@ -86,7 +86,7 @@ object NotificationHelper {
}
NotificationUgc.ARTICLE -> {
if (!isShowedArticle) {
show(AppManager.getInstance().recentActiveActivity as? AppCompatActivity, ugc, callBack)
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ARTICLE, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
@ -95,7 +95,7 @@ object NotificationHelper {
}
NotificationUgc.VIDEO -> {
if (!isShowedVideo) {
show(AppManager.getInstance().recentActiveActivity as? AppCompatActivity, ugc, callBack)
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_VIDEO, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
@ -104,7 +104,7 @@ object NotificationHelper {
}
NotificationUgc.RATING -> {
if (!isShowedRating) {
show(AppManager.getInstance().recentActiveActivity as? AppCompatActivity, ugc, callBack)
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_RATING, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
@ -113,7 +113,7 @@ object NotificationHelper {
}
NotificationUgc.GIFT -> {
if (!isShowedGift) {
show(AppManager.getInstance().recentActiveActivity as? AppCompatActivity, ugc, callBack)
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_GIFT, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
@ -122,7 +122,7 @@ object NotificationHelper {
}
NotificationUgc.RESERVE_GAME -> {
if (!isShowedReserveGame) {
show(AppManager.getInstance().recentActiveActivity as? AppCompatActivity, ugc, callBack)
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_RESERVE_GAME, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
@ -131,7 +131,7 @@ object NotificationHelper {
}
NotificationUgc.FEEDBACK -> {
if (!isShowedFeedback) {
show(AppManager.getInstance().recentActiveActivity as? AppCompatActivity, ugc, callBack)
show(AppManager.getInstance().recentActiveActivity as AppCompatActivity, ugc, callBack)
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_FEEDBACK, true)
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
} else {
@ -154,8 +154,8 @@ object NotificationHelper {
callBack?.invoke(false)
} else {
callBack?.invoke(true)
if (activity.supportFragmentManager.isStateSaved) return
NotificationHintDialogFragment.getInstance(ugc).show(activity.supportFragmentManager, "notification")
// if (activity.supportFragmentManager.isStateSaved) return
// NotificationHintDialogFragment.getInstance(ugc).show(activity.supportFragmentManager, "notification")
}
}

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