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
733 changed files with 5668 additions and 21451 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

View File

@ -6,8 +6,6 @@ apply plugin: 'kotlin-kapt'
// apkChannelPackage
apply plugin: 'channel'
import groovy.xml.XmlUtil
//apply from: 'tinker-support.gradle'
android {
@ -20,10 +18,6 @@ android {
enabled = true
}
viewBinding {
enabled = true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
@ -38,10 +32,6 @@ android {
javaMaxHeapSize "4g"
}
aaptOptions {
additionalParameters "--no-version-vectors"
}
defaultConfig {
multiDexEnabled true
@ -135,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}\""
@ -166,7 +144,7 @@ android {
}
// internal test dev host
internal {
dimension "env"
dimension "nonsense"
versionNameSuffix "-debug"
buildConfigField "String", "API_HOST", "\"${DEV_API_HOST}\""
@ -177,30 +155,6 @@ 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}\""
}
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}\""
}
}
}
@ -230,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'
@ -332,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"
@ -346,8 +299,6 @@ dependencies {
implementation "net.lingala.zip4j:zip4j:${zip4j}"
implementation "io.sentry:sentry-android:$sentry"
implementation("com.github.piasy:BigImageViewer:$bigImageViewer", {
exclude group: 'com.squareup.okhttp3'
exclude group: 'androidx.swiperefreshlayout'
@ -420,78 +371,3 @@ if (propFile.exists()) {
// task.name.startsWith('merge') && task.name.endsWith('Resources')
// }.each { t -> t.dependsOn generateMetaJson }
//}
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
}
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()) {
value = "keyboardHidden|orientation|screenSize|screenLayout|density|fontScale|locale"
act.attributes()['androidconfigChanges'] = value
} else {
String[] valueSplit = value.split("\\|")
if (!valueSplit.contains("keyboardHidden")) {
value += "|keyboardHidden"
}
if (!valueSplit.contains("orientation")) {
value += "|orientation"
}
if (!valueSplit.contains("screenSize")) {
value += "|screenSize"
}
if (!valueSplit.contains("screenLayout")) {
value += "|screenLayout"
}
if (!valueSplit.contains("density")) {
value += "|density"
}
if (!valueSplit.contains("fontScale")) {
value += "|fontScale"
}
if (!valueSplit.contains("locale")) {
value += "|locale"
}
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")
}
}
}
}
}

View File

@ -241,13 +241,6 @@
-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.** { *; }
@ -265,7 +258,4 @@
-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 { *; }
-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" />
<!-- 允许应用程序获取网络信息状态 -->
@ -23,6 +25,8 @@
<uses-permission android:name="android.permission.CHANGE_WIFI_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" />
@ -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" />
<!--可选,穿山甲提供“获取地理位置权限”和“不给予地理位置权限,开发者传入地理位置参数”两种方式上报用户位置,两种方式均可不选,添加位置权限或参数将帮助投放定位广告-->
@ -75,10 +79,6 @@
tools:replace="android:allowBackup"
tools:targetApi="n">
<meta-data
android:name="io.sentry.auto-init"
android:value="false" />
<!--android:launchMode = "singleTask"-->
<activity
android:name="com.gh.gamecenter.SplashScreenActivity"
@ -462,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"
@ -577,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"
@ -591,36 +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" />
<activity
android:name=".energy.EnergyHouseActivity"
android:screenOrientation="portrait" />
<activity
android:name=".personal.NewPersonalActivity"
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"
@ -632,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
@ -650,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"
@ -689,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

@ -25,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.core.Sentry;
public class AppUncaughtHandler implements UncaughtExceptionHandler {
@ -39,21 +36,17 @@ 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) {

View File

@ -32,17 +32,13 @@ import com.gh.common.util.ExtensionsKt;
import com.gh.common.util.MtaHelper;
import com.gh.common.util.PackageInstaller;
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.eventbus.EBShowDialog;
import com.lightgame.BaseAppCompatActivity;
import com.lightgame.download.DownloadEntity;
import com.lightgame.download.FileUtils;
import com.lightgame.utils.Utils;
import com.tencent.tauth.Tencent;
@ -72,7 +68,6 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
public final static String DOWNLOAD_HIJACK = "hijack";
public final static String LOGIN_EXCEPTION = "loginException";
public final static String PLUGGABLE = "plugin";
public final static int ID_ROOT_INDICATOR = 999;
@NonNull
protected String mEntrance;
@ -127,23 +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);
PackageInstaller.install(this, downloadEntity, false);
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "");
SPUtils.setString(Constants.SP_XAPK_URL, "");
}
}
}
@SuppressWarnings("ConstantConditions")
@ -207,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);

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,50 +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)
AppExecutor.uiExecutor.executeWithDelay(Runnable {
mRichEditor.scrollTo(0, 1000000)
}, 500)
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")
@ -124,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,
@ -185,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
@ -215,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()
@ -281,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) {
@ -386,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)
@ -414,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()
}
}
@ -426,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

@ -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;
@ -73,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

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

@ -17,8 +17,6 @@ import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.entity.Badge
import com.gh.gamecenter.entity.MtaEvent
import com.gh.gamecenter.entity.NotificationUgc
import com.gh.gamecenter.energy.EnergyCenterActivity
import com.gh.gamecenter.energy.EnergyHouseActivity
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.retrofit.BiResponse
import com.gh.gamecenter.retrofit.RetrofitManager
@ -117,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)
}
@ -201,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")
}
}
@ -256,26 +252,6 @@ 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))
}
@Keep
internal data class ImageEvent(var imageList: ArrayList<String> = arrayListOf(), var position: Int = 0)

View File

@ -344,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
}
@ -365,7 +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") -> {

View File

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

View File

@ -129,13 +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 REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
@ -179,22 +172,6 @@ public class Constants {
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 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 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,6 +38,7 @@ 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.ReservationHelper;
import com.gh.common.view.DownloadProgressBar;
@ -80,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.
*/
@ -256,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
*/
@ -456,14 +448,12 @@ public class BindingAdapters {
return;
}
}
PackageCheckDialogFragment.show((AppCompatActivity) v.getContext(), gameEntity.getPackageDialog(), () -> {
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));
});
});
});
@ -519,11 +509,13 @@ public class BindingAdapters {
break;
case RESERVABLE:
CheckLoginUtils.checkLogin(progressBar.getContext(), "", () -> {
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(gameEntity, () -> {
LogUtils.logReservation(gameEntity, traceEvent);
updateReservation(progressBar, gameEntity);
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(progressBar.getContext(), () -> {
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(gameEntity, () -> {
LogUtils.logReservation(gameEntity, traceEvent);
updateReservation(progressBar, gameEntity);
});
dialogFragment.show(((AppCompatActivity) progressBar.getContext()).getSupportFragmentManager(), "reserve");
});
dialogFragment.show(((AppCompatActivity) progressBar.getContext()).getSupportFragmentManager(), "reserve");
});
break;
case RESERVED:

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

@ -215,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

@ -48,7 +48,7 @@ class GameOffServiceDialogFragment
siteTv.setOnClickListener {
// MtaHelper.onEvent("游戏下载状态按钮", getKey(), site.text)
DirectUtils.directToWebView(requireContext(), site.url, "(关闭下载弹窗)")
dismissAllowingStateLoss()
dismiss()
}
container.addView(siteTv)

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,307 +0,0 @@
package com.gh.common.dialog
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.RelativeLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentTransaction
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.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.PackageDialogEntity
import com.gh.gamecenter.eventbus.EBPackage
import com.halo.assistant.HaloApp
import com.lightgame.adapter.BaseRecyclerAdapter
import com.lightgame.dialog.BaseDialogFragment
import io.reactivex.disposables.Disposable
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
/**
* 包名检测弹窗
*/
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
var packageDialogEntity: PackageDialogEntity? = null
var callBack: DialogUtils.ConfirmListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
EventBus.getDefault().register(this)
}
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)
packageDialogEntity?.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) {
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
}
else -> {
binding.cancelTv.text = "我知道了"
binding.noRemindAgainCb.visibility = View.VISIBLE
}
}
initListener(it)
}
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) {
SPUtils.setBoolean(Constants.SP_PACKAGE_CHECK, true)
}
val isAllPackageInstalled = isAllPackageInstalled(entity)
if (isAllPackageInstalled) {
callBack?.onConfirm()
dismissAllowingStateLoss()
} else {
val packageLink = entity.links.find { it.buttonLink }
if (packageLink != null) {
DirectUtils.directToLinkPage(requireContext(), packageLink, "包名检测弹窗", "")
}
}
}
binding.cancelTv.setOnClickListener {
if (entity.level != "HINT_SKIP") {
callBack?.onConfirm()
}
if (binding.noRemindAgainCb.isChecked) {
SPUtils.setBoolean(Constants.SP_PACKAGE_CHECK, true)
}
dismissAllowingStateLoss()
}
}
private fun checkPackage() {
var index = 0
mTotalWidth = (DisplayUtils.getScreenWidth() - 108f.dip2px()).toFloat()
mDisposable = rxTimer(1) {
val width = (mTotalWidth / mDuration) * it
val params = binding.progressView.layoutParams as RelativeLayout.LayoutParams
params.width = width.toInt()
binding.progressView.layoutParams = params
packageDialogEntity?.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
binding.progressText.text = "检测完成"
binding.progressView.background = ContextCompat.getDrawable(requireContext(), R.drawable.package_check_complete_bg)
}
}
}
override fun onStart() {
super.onStart()
val width = requireContext().resources.displayMetrics.widthPixels - 60F.dip2px()
val height = ViewGroup.LayoutParams.WRAP_CONTENT
dialog?.window?.setLayout(width, height)
dialog?.setCanceledOnTouchOutside(true)
}
override fun onResume() {
super.onResume()
packageDialogEntity?.let {
if (isAllPackageInstalled(it)) {
callBack?.onConfirm()
dismissAllowingStateLoss()
}
}
}
override fun onDestroyView() {
super.onDestroyView()
EventBus.getDefault().unregister(this)
if (mDisposable?.isDisposed == false) {
mDisposable?.dispose()
}
}
//安装、卸载事件
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(busFour: EBPackage) {
if ("安装" == busFour.type || "卸载" == busFour.type) {
mAdapter?.notifyDataSetChanged()
}
}
class PackageCheckAdapter(val context: Context, val entities: ArrayList<DetectionObjectEntity>) : BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
private var index = -1
fun notifyPackages() {
index++
notifyDataSetChanged()
}
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) {
var isAllInstalled = false
entity.packages.forEach { packageName ->
val isInstalled = PackageUtils.getInstalledPackages(context, 0).find { it.packageName == packageName } != null
if (isInstalled) {
isAllInstalled = true
return@forEach
}
}
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, packageDialogEntity: PackageDialogEntity?, callBack: DialogUtils.ConfirmListener) {
if (packageDialogEntity == null) {
callBack.onConfirm()
return
}
if (isAllPackageInstalled(packageDialogEntity)) {
callBack.onConfirm()
return
}
val isChoose = SPUtils.getBoolean(Constants.SP_PACKAGE_CHECK, false)
if (packageDialogEntity.level == "OPTIONAL_HINT" && isChoose) {
callBack.onConfirm()
return
}
if (activity.isFinishing) return
var dialogFragment = activity.supportFragmentManager.findFragmentByTag(PackageCheckDialogFragment::class.java.simpleName) as? PackageCheckDialogFragment
if (dialogFragment == null) {
dialogFragment = PackageCheckDialogFragment()
dialogFragment.packageDialogEntity = packageDialogEntity
dialogFragment.callBack = callBack
dialogFragment.show(activity.supportFragmentManager, PackageCheckDialogFragment::class.java.simpleName)
} else {
dialogFragment.packageDialogEntity = packageDialogEntity
dialogFragment.callBack = callBack
val transaction: FragmentTransaction = activity.supportFragmentManager.beginTransaction()
transaction.show(dialogFragment)
transaction.commit()
}
}
fun isAllPackageInstalled(packageDialogEntity: PackageDialogEntity): Boolean {
var isAllInstalled = true
val isPackagesInstall: (ArrayList<String>) -> Boolean = { packages ->
var isPackagesInstalled = false
packages.forEach { packageName ->
val isInstalled = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0).find { it.packageName == packageName } != null
if (isInstalled) {
isPackagesInstalled = true
return@forEach
}
}
isPackagesInstalled
}
packageDialogEntity.detectionObjects.forEach loop@{ obj ->
if (!isPackagesInstall(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.DirectUtils.directToExternalBrowser
import com.gh.common.util.dip2px
import com.gh.common.view.CustomLinkMovementMethod
import com.gh.gamecenter.R
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,80 +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) {
directToExternalBrowser(context!!, context!!.getString(R.string.privacy_policy_url))
}
}, 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) {
directToExternalBrowser(requireContext(), requireContext().getString(R.string.disclaimer_url))
}
}, 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,9 +13,7 @@ data class ExposureEntity(
val gameName: String? = "",
val gameVersion: String? = "",
val sequence: Int? = 0,
val outerSequence: Int? = 0,
val platform: String? = "",
var isMirrorData: Boolean = false,
val downloadType: String? = "",
val downloadCompleteType: String? = "",

View File

@ -36,12 +36,10 @@ data class ExposureEvent(
return ExposureEvent(
payload = ExposureEntity(
gameId = gameEntity?.id?.getFirstElementDividedByDivider(Constants.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,
sequence = eTrace?.firstOrNull()?.payload?.sequence ?: gameEntity?.sequence,
outerSequence = eTrace?.firstOrNull()?.payload?.outerSequence ?: gameEntity?.outerSequence,
platform = eTrace?.firstOrNull()?.payload?.platform ?:gameEntity?.platform,
gameName = gameEntity?.name?.removeSuffix(Constants.GAME_NAME_DECORATOR),
gameVersion = gameEntity?.gameVersion,
sequence = gameEntity?.sequence,
platform = gameEntity?.platform,
downloadType = gameEntity?.downloadType,
downloadCompleteType = gameEntity?.downloadCompleteType,
// ugly

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

@ -40,10 +40,8 @@ object ExposureManager {
loghubHelper.init(HaloApp.getInstance().application, ENDPOINT, PROJECT, LOG_STORE) { TimeUtil.currentTimeMillis() }
exposureExecutor.execute {
tryWithDefaultCatch {
val eventList = exposureDao.getAll()
exposureSet.addAll(eventList)
}
val eventList = exposureDao.getAll()
exposureSet.addAll(eventList)
}
}
@ -140,7 +138,7 @@ object ExposureManager {
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

@ -8,11 +8,10 @@ import com.gh.common.util.toObject
import com.gh.gamecenter.entity.ApkEntity
import com.gh.gamecenter.entity.GameEntity
import com.halo.assistant.HaloApp
import java.util.*
object ExposureUtils {
private val mDownloadCompleteTraceEventIdSet = ExposureManager.FixedSizeLinkedHashSet<String>(3)
@JvmStatic
fun logADownloadExposureEvent(entity: GameEntity,
platform: String?,
@ -24,8 +23,7 @@ object ExposureUtils {
} 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,
@ -47,14 +45,6 @@ object ExposureUtils {
gameEntity.platform = platform
gameEntity.downloadCompleteType = downloadType.toString()
val traceEvent = trace?.toObject<ExposureEvent>()
// 避免生成 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),
@ -90,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

@ -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,44 +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 }) } }
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
@ -114,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
}
@ -131,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

@ -25,10 +25,8 @@ object LoghubUtils {
mApplication = application
loghubEventExecutor.execute {
tryWithDefaultCatch {
val eventList = loghubEventDao.getAll()
loghubEventSet.addAll(eventList)
}
val eventList = loghubEventDao.getAll()
loghubEventSet.addAll(eventList)
}
}

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
@ -24,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() {
@ -36,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
@ -74,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("网络不稳定,下载任务已暂停")
@ -100,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
@ -125,8 +116,8 @@ class SimulatorDownloadManager private constructor() {
key = if (shouldShowUpdate && isInstalled) "更新弹窗" else "下载弹窗",
logShowEvent = true
)
DialogUtils.showNewAlertDialog(context, title, message, negativeText, positiveText, trackableEntity, Gravity.LEFT, {
if (shouldShowUpdate && isInstalled) {
DialogUtils.showNewAlertDialog(context, title, message, negativeText, positiveText, trackableEntity, {
if (shouldShowUpdate && isInstalled){
cancelCallback?.invoke()
MtaHelper.onEvent(trackableEntity.event, trackableEntity.key, "点击下次再说")
}
@ -161,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 {

View File

@ -33,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) {
@ -48,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)
@ -109,7 +109,7 @@ object SimulatorGameManager {
val destActivity = "com.gh.emu.RequestPermissionActivity"
intent.setClassName(gameEntity.simulator?.apk?.packageName ?: "", destActivity)
try {
AppManager.getInstance().recentActiveActivity?.startActivity(intent)
AppManager.getInstance().recentActiveActivity.startActivity(intent)
} catch (e: ActivityNotFoundException) {
ToastUtils.showToast("模拟器安装错误")
}

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("投诉")

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;
@ -529,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

@ -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,13 +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.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;
@ -18,10 +16,7 @@ import com.lightgame.utils.Utils;
import java.util.HashMap;
import java.util.Map;
import io.sentry.android.core.SentryAndroid;
import io.sentry.core.Sentry;
import io.sentry.core.protocol.User;
import java.util.Properties;
/**
* Created by LGT on 2016/6/15.
@ -40,40 +35,6 @@ public class DataUtils {
if (CommonDebug.IS_DEBUG) {
return;
}
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);
}
});
//TalkingData
// try {
// TCAgent.LOG_ON = false;
@ -178,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);
}
@ -200,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);

View File

@ -350,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, 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) {
@ -373,8 +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);
titleTv.setGravity(gravity);
contentTv.setGravity(gravity);
titleTv.setText(title);
contentTv.setText(message);
@ -413,7 +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, clListener, cmListener);
return showNewAlertDialog(context, title, message, negative, positive, null, clListener, cmListener);
}
/**
@ -988,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);
}
@ -1027,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);
}
}
}
@ -1902,95 +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();
}
/**
* @param context may be is application context
* @return activity context

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,7 +22,6 @@ 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.download.DownloadFragment.Companion.INDEX_UPDATE
import com.gh.gamecenter.entity.*
@ -40,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
@ -51,18 +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.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
@ -138,9 +133,7 @@ object DirectUtils {
"server",
"top_game_comment",
"wechat_bind",
"video",
"catalog"
)
"video")
fun directToLinkPage(context: Context,
linkEntity: LinkEntity,
@ -207,8 +200,6 @@ object DirectUtils {
"category", "分类" -> directCategoryDirectory(context, linkEntity.link!!, linkEntity.text!!)
"catalog" -> directCatalog(context, linkEntity.link!!, linkEntity.text!!, entrance, path)
"block", "版块" -> {
if (linkEntity.link.isNullOrEmpty()) return
directToBlock(context,
@ -254,68 +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))
"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)
"" -> {
@ -645,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
@ -682,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")
}
}
@ -964,20 +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)
}
/**
* 跳转到问题标签详情
*/
@ -1102,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) {
@ -1142,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]
@ -1193,67 +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)
}
}

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;
@ -46,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 下载判断不能以按钮文案为判断条件,否则按钮文案修改时又要修改判断逻辑
*/
@ -125,17 +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);
holder.gameDownloadBtn.setTextColor(Color.WHITE);
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_pause_dn);
}
}
@ -421,7 +419,7 @@ public class DownloadItemUtils {
}
/**
* @param clickCallback 供那些需要知道点击回调的地方使用,触发具体响应才会回调
* @param clickCallback 供那些需要知道点击回调的地方使用
*/
public static void setOnClickListener(final Context context,
final TextView downloadBtn,
@ -433,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();
}
@ -500,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();
@ -519,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();
}
@ -538,10 +505,115 @@ public class DownloadItemUtils {
});
} else {
downloadBtn.setOnClickListener(v -> {
if (allStateClickCallback != null) {
allStateClickCallback.onCallback();
if (clickCallback != null) {
clickCallback.onCallback();
}
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();
}
@ -580,33 +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))) {
// 先弹下载弹窗(如果需要的话)
PackageCheckDialogFragment.show((AppCompatActivity) context, gameEntity.getPackageDialog(), () -> {
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))) {
PackageCheckDialogFragment.show((AppCompatActivity) context, gameEntity.getPackageDialog(), () -> {
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));
});
});
});
@ -633,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;
}
}
@ -657,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());
@ -692,8 +757,6 @@ public class DownloadItemUtils {
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
downloadBtn.setTextColor(ContextCompat.getColorStateList(context, R.color.text_downloading_style));
DeviceRemindDialog.Companion.showDeviceRemindDialog(context, gameEntity);
EnergyTaskHelper.postEnergyTask("download_game", gameEntity.getId(), gameEntity.getApk().get(0).getPackageName());
} else {
Utils.toast(context, msg);
}

View File

@ -1,13 +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.exposure.meta.MetaUtil
import com.gh.common.xapk.XapkInstaller
import com.gh.download.DownloadDataHelper
import com.gh.download.DownloadManager
@ -76,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, ""))
@ -115,9 +115,7 @@ object DownloadObserver {
// 会有 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") //上传更新安装数据
}
}
@ -138,13 +136,11 @@ object DownloadObserver {
}
if (!downloadEntity.isPluggable) {
if (downloadEntity.isSimulatorGame()) {
val gameEntity = HaloApp.get(downloadEntity.path, true) as? GameEntity
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) {
val currentActivity = AppManager.getInstance().currentActivity() ?: return
SimulatorDownloadManager.getInstance().showDownloadDialog(currentActivity, gameEntity.simulator,
SimulatorDownloadManager.getInstance().showDownloadDialog(AppManager.getInstance().currentActivity(), gameEntity.simulator,
SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.id, gameEntity.name
?: "", null)
}
@ -179,15 +175,15 @@ object DownloadObserver {
}
// 下载过程分析统计
// val pm = mApplication.packageManager
// val packageInfo = pm.getPackageArchiveInfo(downloadEntity.path, 0)
// if (packageInfo == null) {
val pm = mApplication.packageManager
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))
// }
}
}
if (downloadEntity.status == DownloadStatus.done) {
@ -219,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) {
@ -287,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,121 +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.gamecenter.R
import com.gh.gamecenter.entity.EnergyTaskCompleteEntity
import com.gh.gamecenter.energy.EnergyCenterActivity
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) {
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) }
}
})
}
// 完成弹窗
@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 {
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

@ -215,13 +215,6 @@ public class EntranceUtils {
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 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 什么的
@ -170,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,7 +1,6 @@
package com.gh.common.util
import android.animation.Animator
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.graphics.drawable.GradientDrawable
@ -44,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
@ -128,20 +124,6 @@ fun ViewPager.addOnScrollStateChanged(onStateChanged: ((state: Int) -> Unit)? =
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
*/
@ -273,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()
}
// }
}
/**
@ -347,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)
}
}
/**
* 主动抛出异常
*/
@ -415,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 {
@ -477,7 +436,6 @@ fun Float.sp2px(): Int {
return (this * scale + 0.5f).toInt()
}
/**
* PopupWindow 自动适配方向
* 弹出与锚点右对齐
@ -601,19 +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 {
this[index]
}
}
/**
* 拦截 TextView 中的 Url Span用应用内页面的形式打开链接
* @param shrankText 未展开时的文字
@ -904,18 +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())
}
}

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:
@ -126,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

@ -1,6 +1,5 @@
package com.gh.common.util
import android.database.sqlite.SQLiteFullException
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.entity.HomePluggableFilterEntity
import com.gh.gamecenter.room.AppDatabase
@ -16,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))
}
}
@ -39,18 +38,13 @@ object HomePluggableHelper {
@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: SQLiteFullException) {
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
@ -280,80 +279,68 @@ object ImageUtils {
})
}
@JvmStatic
fun display(view: SimpleDraweeView?, url: String?) {
display(view, url, true)
}
/**
* 规则 width>0 Wifi/4G:x2 traffic:x1
* 第一种方案:通过LayoutParams获取 可以快速(无延迟)获取宽高,但是无法获取wrap_content和match_parent的View
* 第二种方案(备用方案):有延迟,View的宽高需要在Measure过程后才能确定,能够在这里获取到正确的宽高
* @param isAutoPlayGif 是否禁止播放动图
*/
@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
val width = 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)
}
val shouldLoadAsGif = url.endsWith(".gif") && isAutoPlayGif && view?.getTag(R.id.tag_show_gif) != false
if (shouldLoadAsGif && view?.tag == url) return
if (width != null && width > 0) {
highResUrl = if (shouldLoadAsGif) {
resizeGif(url, width, height ?: 0)
} else {
getTransformLimitUrl(url, width, view.context) ?: ""
view?.setTag(R.string.highResImageTag, highResUrl)
}
loadImageClosure(shouldLoadAsGif, highResUrl, lowResUrl)
} else {
view?.post {
val shouldLoadAsGif = it.endsWith(".gif") && view?.getTag(R.id.tag_show_gif) != false
if (shouldLoadAsGif && view?.tag == url) return
if (width != null && width > 0) {
highResUrl = if (shouldLoadAsGif) {
resizeGif(url, view.width, height ?: 0)
resizeGif(url, width, height ?: 0)
} else {
getTransformLimitUrl(url, view.width, view.context) ?: ""
getTransformLimitUrl(url, width, view.context) ?: ""
}
loadImageClosure(shouldLoadAsGif, highResUrl, lowResUrl)
} else {
view?.post {
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
@ -402,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()

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,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;
@ -37,6 +36,7 @@ import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import androidx.core.content.ContextCompat;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
@ -237,160 +237,85 @@ public class LibaoUtils {
// 领取限制
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());
}
}, null);
return;
}
}
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;
}
}
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点刷新");
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;
}
final Dialog loadingDialog = DialogUtils.showWaitDialog(context, "淘号中...");
postLibaoTao(context, libaoEntity.getId(), new PostLibaoListener() {
@Override
public void postSucceed(Object response) {
}
if (loadingDialog != null) loadingDialog.dismiss();
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) {
JSONObject responseBody = (JSONObject) response;
String libaoCode = null;
try {
libaoCode = responseBody.getString("code");
} catch (JSONException e) {
e.printStackTrace();
}
if (loadingDialog != null) loadingDialog.dismiss();
if (TextUtils.isEmpty(libaoCode)) {
JSONObject responseBody = (JSONObject) response;
String libaoCode = null;
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;
}
libaoCode = responseBody.getString("code");
} 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)));
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) {
if (TextUtils.isEmpty(libaoCode)) {
try {
JSONObject errorJson = new JSONObject(exception.response().errorBody().string());
String detail = errorJson.getString("detail");
// Utils.toast(context, "返回::" + detail);
String detail = responseBody.getString("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;
@ -398,24 +323,101 @@ public class LibaoUtils {
Utils.toast(context, "淘号失败,稍后重试");
break;
default:
Utils.toast(context, "操作失败");
Utils.toast(context, "淘号异常");
break;
}
} catch (Exception ex) {
ex.printStackTrace();
Utils.toast(context, "礼包处理异常" + ex.toString());
} catch (JSONException e) {
e.printStackTrace();
}
return;
} else if (exception.code() == 401) {
return;
}
Utils.toast(context, "淘号成功");
libaoEntity.setStatus("taoed");
EventBus.getDefault().post(new EBReuse("libaoChanged"));
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);
}
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");
// 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;
}
});
});
});
}
@ -456,7 +458,7 @@ public class LibaoUtils {
adapter.notifyDataSetChanged();
final String finalLibaoCode = libaoCode;
NotificationHelper.showNotificationHintDialog(NotificationUgc.GIFT, isShow -> {
if (!isShow) {
if (!isShow){
DialogUtils.showWarningDialog(context, "领取成功", Html.fromHtml(context.getString(R.string.linged_dialog, finalLibaoCode))
, "关闭", " 复制礼包码"
, () -> {
@ -545,7 +547,8 @@ public class LibaoUtils {
}
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;
@ -573,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

@ -33,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;
@ -235,7 +234,6 @@ public class LogUtils {
object.put("game_name", gameEntity.getName());
object.put("game_id", gameEntity.getId());
object.put("game_platform", gameEntity.getPlatform());
object.put("download_open", gameEntity.getDownloadOffStatus() == null ? "true" : "false");
} catch (JSONException e) {
e.printStackTrace();
}
@ -256,13 +254,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();
@ -280,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();
@ -299,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());
@ -430,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());
@ -524,13 +522,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());
@ -613,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 {
@ -635,52 +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();
}
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);
}
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();

View File

@ -86,17 +86,13 @@ public class MessageShareUtils {
@Override
public void onError(UiError uiError) {
// 单分享图片不支持显示未安装弹窗,手动调出
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, "分享失败");
}

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

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

View File

@ -37,15 +37,4 @@ object NumberUtils {
val minute = Math.round((totalMinute - hour * 60).toFloat())
return hour.toString() + "小时" + if (minute == 0) "" else minute.toString() + "分钟"
}
@JvmStatic
fun findMax(lastPositions: IntArray): Int {
var max = lastPositions[0]
for (value in lastPositions) {
if (value > max) {
max = value
}
}
return max
}
}

View File

@ -63,7 +63,7 @@ object PackageHelper {
private fun getAllPackageName(context: Context): HashSet<String> {
val set = HashSet<String>()
return try {
val packageInfos = PackageUtils.getInstalledPackages(context, 0)
val packageInfos = context.applicationContext.packageManager.getInstalledPackages(0)
for (packageInfo in packageInfos) {
if (packageInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM == 0) {
if (context.packageName != packageInfo.packageName) {

View File

@ -1,6 +1,5 @@
package com.gh.common.util
import android.app.Activity
import android.app.Application
import android.content.Context
import android.content.Intent
@ -26,8 +25,8 @@ object PackageInstaller {
* 为了兼容java代码
*/
@JvmStatic
fun install(context: Context, downloadEntity: DownloadEntity?) {
downloadEntity?.let { install(context, downloadEntity, true) }
fun install(context: Context, downloadEntity: DownloadEntity) {
install(context, downloadEntity, true)
}
/**
@ -39,24 +38,16 @@ object PackageInstaller {
*/
@JvmStatic
fun install(context: Context, downloadEntity: DownloadEntity, showUnzipToast: Boolean) {
val pkgPath = downloadEntity.path
val isXapk = XapkInstaller.XAPK_EXTENSION_NAME == pkgPath.getExtension()
InstallPermissionDialogFragment.show(AppManager.getInstance().currentActivity() as AppCompatActivity) {
// 取消状态栏下载完成的通知,若存在
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
val currentActivity = AppManager.getInstance().currentActivity() ?: return
// TODO 此处可能遇到 activity 是 WXEntryActivity
// TODO 当 activity 全部出栈,但是应用还在下载游戏,下载完会唤不起安装!
if (currentActivity is AppCompatActivity) {
InstallPermissionDialogFragment.show(currentActivity, downloadEntity) {
// 取消状态栏下载完成的通知,若存在
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
if (isXapk) {
XapkInstaller.install(context, downloadEntity, showUnzipToast)
} else {
install(context, downloadEntity.path)
}
val pkgPath = downloadEntity.path
if (XapkInstaller.XAPK_EXTENSION_NAME == pkgPath.getExtension()) {
XapkInstaller.install(context, downloadEntity, showUnzipToast)
} else {
install(context, downloadEntity.path)
}
}
}
@ -122,9 +113,6 @@ object PackageInstaller {
val uninstallIntent = Intent()
uninstallIntent.action = Intent.ACTION_DELETE
uninstallIntent.addCategory(Intent.CATEGORY_DEFAULT)
if (context !is Activity) {
uninstallIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
val packageName = PackageUtils.getPackageNameByPath(context, path)
uninstallIntent.data = Uri.parse("package:$packageName")
InstallUtils.getInstance(context).addUninstall(packageName)

View File

@ -30,11 +30,8 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
@ -183,13 +180,11 @@ public class PackageUtils {
return null;
}
// TODO 找一个更好的办法来比较签名并且不触发 ANR
public static boolean compareSignatureBetweenInstalledAppWithApk(Context context, String packageName, String apkFilePath) {
try {
// 据 Sentry 统计,刚上架一个周末的包里对这个方法有 700+ 次调用,然后其中一部分会造成 ANR
Signature sig = context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures[0];
// 调用 getPackageArchiveInfo 获取较大的 apk 的签名时会耗时超过5秒造成 ANR没有找到解决方法
// Fuck HUAWEI, 华为系统调用 getPackageArchiveInfo 获取魔羯 apk 的签名时会耗时超过5秒造成 ANR没有找到解决方法
// 如果可以的话尽量避免调用 getPackageArchiveInfo 方法
Signature releaseSig = context.getPackageManager().getPackageArchiveInfo(apkFilePath, PackageManager.GET_SIGNATURES).signatures[0];
return sig.hashCode() == releaseSig.hashCode();
@ -291,7 +286,7 @@ public class PackageUtils {
*/
public static String getPackageNameByPath(Context context, String path) {
PackageManager packageManager = context.getApplicationContext().getPackageManager();
PackageInfo info = packageManager.getPackageArchiveInfo(path, 0);
PackageInfo info = packageManager.getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES);
if (info != null) {
ApplicationInfo appInfo = info.applicationInfo;
return appInfo.packageName;
@ -375,7 +370,7 @@ public class PackageUtils {
*/
public static ArrayList<String> getAllPackageName(Context context) {
ArrayList<String> list = new ArrayList<>();
List<PackageInfo> packageInfos = getInstalledPackages(context, 0);
List<PackageInfo> packageInfos = context.getApplicationContext().getPackageManager().getInstalledPackages(0);
for (PackageInfo packageInfo : packageInfos) {
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
if (!context.getPackageName().equals(packageInfo.packageName)) {
@ -390,7 +385,7 @@ public class PackageUtils {
JSONArray jsonArray = new JSONArray();
try {
PackageManager pm = context.getPackageManager();
List<PackageInfo> packageInfos = getInstalledPackages(context, 0);
List<PackageInfo> packageInfos = pm.getInstalledPackages(0);
for (PackageInfo packageInfo : packageInfos) {
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
JSONObject jsonObject = new JSONObject();
@ -516,21 +511,15 @@ public class PackageUtils {
* @return 进程名
*/
public static String obtainProcessName(Context context) {
try {
final int pid = android.os.Process.myPid();
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> listTaskInfo = am.getRunningAppProcesses();
if (listTaskInfo != null && !listTaskInfo.isEmpty()) {
for (ActivityManager.RunningAppProcessInfo info : listTaskInfo) {
if (info != null && info.pid == pid) {
return info.processName;
}
final int pid = android.os.Process.myPid();
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> listTaskInfo = am.getRunningAppProcesses();
if (listTaskInfo != null && !listTaskInfo.isEmpty()) {
for (ActivityManager.RunningAppProcessInfo info : listTaskInfo) {
if (info != null && info.pid == pid) {
return info.processName;
}
}
} catch (Exception e) {
// 遇到异常了让这次调用正常执行
e.printStackTrace();
return BuildConfig.APPLICATION_ID;
}
return null;
}
@ -568,42 +557,4 @@ public class PackageUtils {
}
/**
* 在5.1系统手机使用PackageManager获取已安装应用容易发生Package manager has died异常
* https://stackoverflow.com/questions/13235793/transactiontoolargeeception-when-trying-to-get-a-list-of-applications-installed/30062632#30062632
*/
public static List<PackageInfo> getInstalledPackages(Context context, int flags) {
final PackageManager pm = context.getPackageManager();
try {
return pm.getInstalledPackages(flags);
} catch (Exception ignored) {
//we don't care why it didn't succeed. We'll do it using an alternative way instead
}
// use fallback:
Process process;
List<PackageInfo> result = new ArrayList<>();
BufferedReader bufferedReader = null;
try {
process = Runtime.getRuntime().exec("pm list packages");
bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
final String packageName = line.substring(line.indexOf(':') + 1);
final PackageInfo packageInfo = pm.getPackageInfo(packageName, flags);
result.add(packageInfo);
}
process.waitFor();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bufferedReader != null)
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
}

View File

@ -13,7 +13,7 @@ import com.tbruyelle.rxpermissions2.RxPermissions
object PermissionHelper {
const val INSTALL_PERMISSION_CODE = 100
const val INSTALL_PERMISS_CODE = 100
@JvmStatic
fun requestReadPhoneStateAndStoragePermissionFromStartUp(context: Context) {
@ -232,7 +232,7 @@ object PermissionHelper {
} else {
val packageURI = Uri.fromParts("package", activity.packageName, null)
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI)
activity.startActivityForResult(intent, INSTALL_PERMISSION_CODE)
activity.startActivityForResult(intent, INSTALL_PERMISS_CODE)
}
}

View File

@ -64,24 +64,34 @@ object ReservationHelper {
@JvmStatic
fun showDeleteReservationDialog(context: Context, emptyCallback: EmptyCallback) {
DialogUtils.showCancelOrDeleteReservationDialog(context,
DialogHelper.showDialog(
context,
"删除预约",
"游戏已上线,你可以删除此预约记录,确定删除吗?",
"确定删除",
"暂不删除", {
emptyCallback.onCallback()
}, null)
"暂不删除",
{ emptyCallback.onCallback() },
null,
trackMtaEvent = true
// , mtaEvent = "预约游戏",
// mtaKey = "删除预约弹窗"
)
}
@JvmStatic
fun showCancelReservationDialog(context: Context, emptyCallback: EmptyCallback) {
DialogUtils.showCancelOrDeleteReservationDialog(context,
DialogHelper.showDialog(
context,
"取消预约",
"取消之后你将无法收到游戏上线的通知,确定取消预约吗?",
"确定取消",
"暂不取消", {
emptyCallback.onCallback()
}, null)
"暂不取消",
{ emptyCallback.onCallback() },
null,
trackMtaEvent = true
// , mtaEvent = "预约游戏",
// mtaKey = "取消预约弹窗"
)
}

View File

@ -1,47 +0,0 @@
package com.gh.common.util
import android.text.TextUtils
import com.lightgame.utils.Utils
import io.sentry.core.Sentry
import io.sentry.core.SentryEvent
import io.sentry.core.SentryLevel
import io.sentry.core.protocol.Message
object SentryHelper {
/**
* 注意 tag-key 不支持中文
*/
fun onEvent(eventId: String, vararg kv: String?) {
val sentryEvent = SentryEvent()
val message = Message()
message.message = eventId
sentryEvent.message = message
sentryEvent.level = SentryLevel.LOG
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)) {
sentryEvent.setTag(key, value)
debugOnly {
throwExceptionInDebug("tag-key 不支持中文", isContainChinese(key))
}
}
}
}
Utils.log("Sentry", "$eventId + [${kv.joinToString(" , ")}]")
Sentry.captureEvent(sentryEvent)
}
// 判断一个字符串是否含有中文
private fun isContainChinese(str: String?): Boolean {
if (str == null) return false
for (c in str.toCharArray()) {
if (c.toInt() in 0x4E00..0x9FA5) return true
}
return false
}
}

View File

@ -1,9 +1,11 @@
package com.gh.common.util;
import android.app.Activity;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@ -22,9 +24,6 @@ import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.gh.common.constant.Config;
import com.gh.gamecenter.R;
import com.gh.gamecenter.WeiBoShareActivity;
@ -51,6 +50,9 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import static com.gh.common.util.LoginHelper.WEIBO_SCOPE;
/**
@ -124,7 +126,6 @@ public class ShareUtils {
EventBus.getDefault().post(new EBShare(ShareUtils.shareEntrance));
LogUtils.uploadShareResult(shareType, ShareUtils.shareEntrance.getName(), "success",
ShareUtils.shareEntity.getShareUrl(), ShareUtils.shareEntity.getShareTitle(), ShareUtils.shareEntity.getSummary(), ShareUtils.resourceId);
EnergyTaskHelper.postEnergyTaskForShare(ShareUtils.shareEntrance.getName(), ShareUtils.resourceId, ShareUtils.shareEntity.getShareUrl());
}
@Override
@ -158,7 +159,8 @@ public class ShareUtils {
//检查是否安装手机QQ
public static boolean isQQClientAvailable(Context context) {
List<PackageInfo> pinfo = PackageUtils.getInstalledPackages(context, 0);
final 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;
@ -319,27 +321,13 @@ public class ShareUtils {
});
}
public void shareGameDetail(Activity activity, String url, String icon, String shareTitle, String shareSummary, ShareEntrance shareEntrance, String id, ShareCallBack callBack) {
if (activity.isFinishing()) return;
this.mActivity = new WeakReference<>(activity);
this.shareIcon = icon;
this.shareUrl = url;
this.mSummary = shareSummary;
this.mTitle = shareTitle;
this.mShareEntrance = shareEntrance;
ShareUtils.shareEntrance = mShareEntrance;
ShareUtils.resourceId = id;
ShareUtils.shareEntity = new ShareEntity(shareUrl, mTitle, mSummary);
LogUtils.uploadShareEnter(mShareEntrance.getName(), shareUrl, mTitle, mSummary, id);
}
public void showShareWindows(Activity activity, View view, String url, String icon, String shareTitle, String shareSummary, ShareEntrance shareEntrance, String id) {
showShareWindowsCallback(activity, view, url, icon, shareTitle, shareSummary, shareEntrance, id, null);
}
//QQ分享
public void qqShare() {
private void qqShare() {
Utils.toast(mContext, R.string.share_skip);
Bundle params = new Bundle();
@ -374,7 +362,7 @@ public class ShareUtils {
}
//微信好友分享
public void wechatShare() {
private void wechatShare() {
Utils.toast(mContext, R.string.share_skip);
if (!PackageHelper.INSTANCE.getLocalPackageNameSet().contains("com.tencent.mm")) {
@ -491,7 +479,7 @@ public class ShareUtils {
}
//QQ空间分享
public void qZoneShare() {
private void qZoneShare() {
Utils.toast(mContext, R.string.share_skip);
Bundle params = new Bundle();
@ -530,7 +518,7 @@ public class ShareUtils {
}
//微信朋友圈分享
public void wechatMomentsShare() {
private void wechatMomentsShare() {
Utils.toast(mContext, R.string.share_skip);
if (!PackageHelper.INSTANCE.getLocalPackageNameSet().contains("com.tencent.mm")) {
@ -573,7 +561,7 @@ public class ShareUtils {
}
//新浪微博分享
public void sinaWeiboShare() {
private void sinaWeiboShare() {
WbSdk.install(mContext, new AuthInfo(mContext, Config.WEIBO_APPKEY, "http://www.sina.com", WEIBO_SCOPE));
if (mShareEntrance == ShareEntrance.qaDetail) {
@ -599,7 +587,7 @@ public class ShareUtils {
}
//短信分享
public void shortMessageShare() {
private void shortMessageShare() {
String smsBody;
switch (mShareEntrance) {
case news:
@ -643,14 +631,16 @@ public class ShareUtils {
}
//复制文字链接
public void copyLink(String copyContent) {
private void copyLink(String copyContent) {
shareType = "copy_link";
LogUtils.uploadShareType(shareType, shareEntrance.getName(), shareUrl, mTitle, mSummary, resourceId);
ClipboardManager cmb = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
cmb.setText(copyContent);
if (mShareEntrance != ShareEntrance.shareGh) {
ExtensionsKt.copyTextAndToast(copyContent, "复制成功");
Utils.toast(mContext, "复制成功");
safelyDismiss();
} else {
ExtensionsKt.copyTextAndToast(copyContent, "复制成功,请到微信/QQ粘贴分享");
Utils.toast(mContext, "复制成功,请到微信/QQ粘贴分享");
}
}
@ -679,7 +669,6 @@ public class ShareUtils {
if (listener != null) {
listener.onItemClick(holder.getAdapterPosition());
}
switch (holder.getPosition()) {
case 0:
shareType = "wechat_friend";
@ -765,7 +754,7 @@ public class ShareUtils {
}
private void safelyDismiss() {
if (popupWindow != null && popupWindow.get() != null) {
if (popupWindow.get() != null) {
popupWindow.get().dismiss();
}
}

View File

@ -23,7 +23,7 @@ object SPUtils {
@JvmStatic
fun getString(key: String): String {
return sp.getString(key, "")?:""
return sp.getString(key, "")
}
@JvmStatic

View File

@ -13,7 +13,7 @@ import androidx.core.content.ContextCompat
import com.gh.common.view.CenterImageSpan
import com.halo.assistant.HaloApp
class SpanBuilder(content: CharSequence) {
class SpanBuilder(content: String) {
private var spannableString: SpannableStringBuilder = SpannableStringBuilder(content)
fun color(context: Context, start: Int, end: Int, colorRes: Int): SpanBuilder {
@ -70,12 +70,12 @@ class SpanBuilder(content: CharSequence) {
return this
}
fun click(start: Int, end: Int, colorRes: Int, isUnderlineText: Boolean = false, onClick: () -> Unit): SpanBuilder {
fun click(start: Int, end: Int, colorRes: Int, onClick: () -> Unit): SpanBuilder {
val clickSpan = object : ClickableSpan() {
override fun updateDrawState(ds: TextPaint) {
super.updateDrawState(ds)
ds.color = ContextCompat.getColor(HaloApp.getInstance().application, colorRes)
ds.isUnderlineText = isUnderlineText
ds.isUnderlineText = false
}
override fun onClick(widget: View) {

View File

@ -71,7 +71,7 @@ object SyncDataBetweenPageHelper {
val fields = syncData::class.java.declaredFields
var isNeedNotify = false
for (field in fields) {
if (field.getAnnotation(Synchronize::class.java) != null && resultData != null) {
if (field.getAnnotation(Synchronize::class.java) != null) {
// 同步数据
val resultField = resultData::class.java.getDeclaredField(field.name)
resultField.isAccessible = true

View File

@ -0,0 +1,32 @@
package com.gh.common.util
import android.content.Context
/**
* 今日头条的激活统计 SDK https://gitlab.ghzs.com/pm/halo-app-issues/issues/567
*
* 更新 SDK https://gitlab.ghzs.com/pm/halo-app-issues/issues/743
*/
object TeaHelper {
@JvmStatic
fun init(context: Context, channel: String) {
// val config = InitConfig("163824", channel)
// config.setUriConfig(UriConfig.DEFAULT)
// config.appName = "guanghuan1"
// config.setEnablePlay(true)
// AppLog.setEnableLog(false)
// AppLog.init(context, config)
//
// AppLog.setOaidObserver {
// HaloApp.getInstance().oaid = it.id
// Utils.log("oaid is $it.id")
// MetaUtil.refreshMeta()
// }
//
// // gameReportHelper ?!
// GameReportHelper.onEventRegister("wechat", true)
// GameReportHelper.onEventPurchase("gift", "flower", "008", 1, "wechat", "¥", true, 1)
}
}

View File

@ -117,17 +117,6 @@ object TimeUtils {
return calendar.timeInMillis
}
@JvmStatic
fun getTimeOfToday(hour: Int): Long {
val calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"))
calendar.timeInMillis = getJavaTimestamp(System.currentTimeMillis())
calendar.set(Calendar.HOUR_OF_DAY, hour)
calendar.set(Calendar.MINUTE, 0)
calendar.set(Calendar.SECOND, 0)
calendar.set(Calendar.MILLISECOND, 0)
return calendar.timeInMillis
}
@JvmStatic
fun getJavaTimestamp(timestamp: Long): Long {
return if ((log10(timestamp.toDouble()) + 1).toInt() == 10) {

View File

@ -6,7 +6,6 @@ import com.gh.common.constant.Constants;
import com.gh.gamecenter.BuildConfig;
import com.halo.assistant.HaloApp;
import java.util.ArrayList;
import java.util.regex.Pattern;
import androidx.collection.ArrayMap;
@ -18,12 +17,10 @@ public class TimestampUtils {
private static ArrayMap<String, Integer> intervalMap; // 间隔
private static ArrayMap<String, Integer> cdMap; // cd
private static ArrayList<String> whiteList; // 白名单
public static void initMap() {
initIntervalMap();
initCDMap();
initWhiteList();
}
private static void initIntervalMap() {
@ -46,25 +43,11 @@ public class TimestampUtils {
cdMap.put(".*packages.*", Constants.PACKAGES_CD);
}
private static void initWhiteList() {
whiteList = new ArrayList<>();
whiteList.add(".*tasks:check.*");
whiteList.add(".*novice_tasks.*");
whiteList.add(".*daily_tasks.*");
whiteList.add(".*energies.*");
}
/*
* 为url添加timestamp
*/
public static String addTimestamp(String url) {
for (String key : whiteList) {
if (Pattern.matches(key, url)) {
return url;
}
}
if (BuildConfig.DEBUG || "GH_REFRESH".equals(HaloApp.getInstance().getChannel())) {
if (TextUtils.isEmpty(url)) {
return url;

View File

@ -1,21 +0,0 @@
package com.gh.common.util
import android.graphics.Bitmap
import android.graphics.Matrix
import com.facebook.common.references.CloseableReference
import com.facebook.imagepipeline.bitmaps.PlatformBitmapFactory
import com.facebook.imagepipeline.request.BasePostprocessor
class TopCutProcess(private val cutRatio: Float) : BasePostprocessor() {
override fun process(sourceBitmap: Bitmap, bitmapFactory: PlatformBitmapFactory): CloseableReference<Bitmap>? {
val viewWidth = sourceBitmap.width
val viewHeight = sourceBitmap.height.toFloat()
var newHeight = viewWidth / cutRatio
if (newHeight > viewHeight) {
newHeight = viewHeight
}
val bitmapRef = bitmapFactory.createBitmap(sourceBitmap, 0, 0, viewWidth, (newHeight).toInt())
return CloseableReference.cloneOrNull(bitmapRef)
}
}

View File

@ -0,0 +1,127 @@
package com.gh.common.util;
import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
public class UriUtils {
@SuppressLint("NewApi")
public static String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.parseLong(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{split[1]};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
* @param selection (Optional) Filter used in the query.
* @param selectionArgs (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
*/
private static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {column};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
private static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
private static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
private static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
}

View File

@ -10,7 +10,6 @@ import android.app.AppOpsManager.MODE_ALLOWED
import android.app.AppOpsManager.OPSTR_GET_USAGE_STATS
import android.app.usage.UsageEvents
import android.app.usage.UsageStatsManager
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.os.Build
@ -258,15 +257,10 @@ object UsageStatsHelper {
@JvmStatic
fun skipToUsageStats(context: Context, requestCode: Int = -1) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
try {
if (context is Activity && requestCode != -1) {
context.startActivityForResult(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS), requestCode)
} else {
context.startActivity(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS))
}
} catch (e: ActivityNotFoundException) {
Utils.toast(context, "当前设备不支持直接跳转查看应用使用情况页面,请手动进入并打开")
e.printStackTrace()
if (context is Activity && requestCode != -1) {
context.startActivityForResult(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS), requestCode)
} else {
context.startActivity(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS))
}
} else {
Utils.toast(context, "当前设备不支持查看应用使用情况")

View File

@ -2,10 +2,7 @@ package com.gh.common.videolog
import android.annotation.SuppressLint
import android.app.Application
import android.database.sqlite.SQLiteFullException
import com.gh.common.util.toRequestBody
import com.gh.common.util.toastInInternalRelease
import com.gh.common.util.tryWithDefaultCatch
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.retrofit.BiResponse
import com.gh.gamecenter.retrofit.RetrofitManager
@ -29,10 +26,8 @@ object VideoRecordUtils {
mApplication = application
videoRecordExecutor.execute {
tryWithDefaultCatch {
val recordList = videoRecordDao.getAll()
videoRecordSet.addAll(recordList)
}
val recordList = videoRecordDao.getAll()
videoRecordSet.addAll(recordList)
}
}
@ -44,9 +39,6 @@ object VideoRecordUtils {
videoRecordDao.insert(entity)
} catch (e: Exception) {
e.printStackTrace()
if (e is SQLiteFullException) {
toastInInternalRelease("数据库/磁盘已满,写入视频新日志失败")
}
}
if (videoRecordSet.size >= STORE_SIZE) {
commitVideoRecord()
@ -60,11 +52,7 @@ object VideoRecordUtils {
uploadVideoRecord()
val exposureList = videoRecordSet.toList()
videoRecordSet.removeAll(exposureList)
try {
videoRecordDao.deleteMany(exposureList)
} catch (e: SQLiteFullException) {
toastInInternalRelease("数据库/磁盘已满,删除视频日志失败")
}
videoRecordDao.deleteMany(exposureList)
}
}

View File

@ -3,6 +3,7 @@ package com.gh.common.view
import android.content.Context
import android.util.AttributeSet
import android.view.*
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
@ -13,6 +14,7 @@ import com.gh.common.util.ImageUtils
import com.gh.common.util.rxTimer
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.SettingsEntity
import com.squareup.picasso.Picasso
import io.reactivex.disposables.Disposable
import kotlin.math.abs

View File

@ -5,7 +5,7 @@ import android.graphics.drawable.PaintDrawable
import android.view.View
import android.widget.PopupWindow
open class BugFixedPopupWindow @JvmOverloads constructor(contentView: View? = null, width: Int = 0, height: Int = 0)
class BugFixedPopupWindow @JvmOverloads constructor(contentView: View? = null, width: Int = 0, height: Int = 0)
: PopupWindow(contentView, width, height) {
init {

View File

@ -1,301 +0,0 @@
package com.gh.common.view
import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.PopupWindow
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.gh.common.util.toColor
import com.gh.common.util.visibleIf
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.CatalogEntity
import com.gh.gamecenter.entity.SubjectSettingEntity
import com.google.android.flexbox.FlexboxLayout
class CatalogFilterView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : LinearLayout(context, attrs, defStyleAttr) {
private var mTypeTv: TextView
private var mCatalogTv: TextView
private var mSizeTv: TextView
private var mTypeContainer: View
private var mCatalogContainer: View
private var mSizeContainer: View
private var mTypeFilterArray = ArrayList<SortType>()
private var mCatalogFilterArray = ArrayList<CatalogEntity.SubCatalogEntity>()
private var sizeFilterArray: ArrayList<SubjectSettingEntity.Size>? = null
private var mOnCatalogFilterSetupListener: OnCatalogFilterSetupListener? = null
init {
View.inflate(context, R.layout.layout_catalog_filter, this)
mTypeTv = findViewById(R.id.type_tv)
mCatalogTv = findViewById(R.id.catalog_tv)
mSizeTv = findViewById(R.id.size_tv)
mTypeContainer = findViewById(R.id.container_type)
mCatalogContainer = findViewById(R.id.container_catalog)
mSizeContainer = findViewById(R.id.container_size)
mTypeContainer.setOnClickListener {
showSelectTypePopupWindow(this, mTypeTv, mTypeTv.text.toString())
}
mCatalogContainer.setOnClickListener {
showSelectCatalogPopupWindow(this, mCatalogTv, mCatalogTv.text.toString())
}
mSizeContainer.setOnClickListener {
showSelectSizePopupWindow(this, mSizeTv, mSizeTv.text.toString())
}
}
fun setTypeList(switch: CatalogEntity.CatalogSwitch) {
switch.run {
if ("on" == hotSort) mTypeFilterArray.add(SortType.RECOMMENDED)
if ("on" == newSort) mTypeFilterArray.add(SortType.NEWEST)
if ("on" == starSort) mTypeFilterArray.add(SortType.RATING)
}
if (mTypeFilterArray.isNotEmpty()) mTypeTv.text = mTypeFilterArray[0].value
}
fun setCatalogList(subCatalogList: List<CatalogEntity.SubCatalogEntity>, initCatalogName: String) {
mCatalogFilterArray = ArrayList(subCatalogList)
mCatalogTv.text = initCatalogName
}
fun setOnConfigSetupListener(onCatalogFilterSetupListener: OnCatalogFilterSetupListener) {
mOnCatalogFilterSetupListener = onCatalogFilterSetupListener
}
private fun toggleHighlightedTextView(targetTextView: TextView, highlightIt: Boolean) {
if (highlightIt) {
targetTextView.background = ContextCompat.getDrawable(targetTextView.context, R.drawable.bg_tag_text)
targetTextView.setTextColor(Color.WHITE)
} else {
targetTextView.background = null
targetTextView.setTextColor(ContextCompat.getColor(targetTextView.context, R.color.text_757575))
}
}
private fun showSelectTypePopupWindow(containerView: View, typeTv: TextView, typeText: String) {
val drawableUp = ContextCompat.getDrawable(typeTv.context, R.drawable.ic_filter_arrow_up)
val drawableDown = ContextCompat.getDrawable(typeTv.context, R.drawable.ic_filter_arrow_down)
drawableUp?.setBounds(0, 0, drawableUp.minimumWidth, drawableUp.minimumHeight)
drawableDown?.setBounds(0, 0, drawableDown.minimumWidth, drawableDown.minimumHeight)
typeTv.setTextColor(R.color.theme_font.toColor())
typeTv.setCompoundDrawables(null, null, drawableUp, null)
val inflater = LayoutInflater.from(typeTv.context)
val layout = inflater.inflate(R.layout.layout_filter_size, null)
val popupWindow = PopupWindow(
layout,
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT)
val flexboxLayout = layout.findViewById<FlexboxLayout>(R.id.flexbox)
val backgroundView = layout.findViewById<View>(R.id.background)
backgroundView.setOnClickListener {
popupWindow.dismiss()
}
for (type in mTypeFilterArray) {
val item = inflater.inflate(R.layout.item_filter_size, flexboxLayout, false)
// 单列 3 个,强行设置宽度为屏幕的 1/3
val width = typeTv.context.resources.displayMetrics.widthPixels / 3
val height = item.layoutParams.height
item.layoutParams = ViewGroup.LayoutParams(width, height)
flexboxLayout.addView(item)
val tv = item.findViewById<TextView>(R.id.size_tv)
tv.text = type.value
toggleHighlightedTextView(tv, typeText == type.value)
tv.tag = type.value
item.setOnClickListener {
toggleHighlightedTextView(tv, true)
popupWindow.dismiss()
typeTv.text = type.value
mOnCatalogFilterSetupListener?.onSetupSortType(type)
}
}
popupWindow.setOnDismissListener {
typeTv.setTextColor(R.color.text_757575.toColor())
typeTv.setCompoundDrawables(null, null, drawableDown, null)
}
popupWindow.isTouchable = true
popupWindow.isFocusable = true
popupWindow.animationStyle = 0
popupWindow.showAsDropDown(containerView, 0, 0)
}
private fun showSelectCatalogPopupWindow(containerView: View, catalogTv: TextView, catalogText: String) {
val drawableUp = ContextCompat.getDrawable(catalogTv.context, R.drawable.ic_filter_arrow_up)
val drawableDown = ContextCompat.getDrawable(catalogTv.context, R.drawable.ic_filter_arrow_down)
drawableUp?.setBounds(0, 0, drawableUp.minimumWidth, drawableUp.minimumHeight)
drawableDown?.setBounds(0, 0, drawableDown.minimumWidth, drawableDown.minimumHeight)
catalogTv.setTextColor(R.color.theme_font.toColor())
catalogTv.setCompoundDrawables(null, null, drawableUp, null)
val inflater = LayoutInflater.from(catalogTv.context)
val layout = inflater.inflate(R.layout.layout_filter_size, null)
val popupWindow = PopupWindow(
layout,
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT)
val flexboxLayout = layout.findViewById<FlexboxLayout>(R.id.flexbox)
val backgroundView = layout.findViewById<View>(R.id.background)
backgroundView.setOnClickListener {
popupWindow.dismiss()
}
for (entity in mCatalogFilterArray) {
val item = inflater.inflate(R.layout.item_filter_size, flexboxLayout, false)
// 单列 3 个,强行设置宽度为屏幕的 1/3
val width = catalogTv.context.resources.displayMetrics.widthPixels / 3
val height = item.layoutParams.height
item.layoutParams = ViewGroup.LayoutParams(width, height)
flexboxLayout.addView(item)
val tv = item.findViewById<TextView>(R.id.size_tv)
val iv = item.findViewById<ImageView>(R.id.recommend_iv)
tv.text = entity.name
iv.visibleIf(entity.recommended)
toggleHighlightedTextView(tv, catalogText == entity.name)
tv.tag = entity.name
item.setOnClickListener {
toggleHighlightedTextView(tv, true)
popupWindow.dismiss()
catalogTv.text = entity.name
mOnCatalogFilterSetupListener?.onSetupSortCatalog(entity)
}
}
popupWindow.setOnDismissListener {
catalogTv.setTextColor(R.color.text_757575.toColor())
catalogTv.setCompoundDrawables(null, null, drawableDown, null)
}
popupWindow.isTouchable = true
popupWindow.isFocusable = true
popupWindow.animationStyle = 0
popupWindow.showAsDropDown(containerView, 0, 0)
}
private fun showSelectSizePopupWindow(containerView: View, sizeTv: TextView, sizeText: String) {
val drawableUp = ContextCompat.getDrawable(sizeTv.context, R.drawable.ic_filter_arrow_up)
val drawableDown = ContextCompat.getDrawable(sizeTv.context, R.drawable.ic_filter_arrow_down)
drawableUp?.setBounds(0, 0, drawableUp.minimumWidth, drawableUp.minimumHeight)
drawableDown?.setBounds(0, 0, drawableDown.minimumWidth, drawableDown.minimumHeight)
sizeTv.setTextColor(R.color.theme_font.toColor())
sizeTv.setCompoundDrawables(null, null, drawableUp, null)
val inflater = LayoutInflater.from(sizeTv.context)
val layout = inflater.inflate(R.layout.layout_filter_size, null)
val popupWindow = PopupWindow(
layout,
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT)
val flexboxLayout = layout.findViewById<FlexboxLayout>(R.id.flexbox)
val backgroundView = layout.findViewById<View>(R.id.background)
sizeFilterArray = if (sizeFilterArray == null) {
getDefaultSizeFilterArray()
} else {
sizeFilterArray?.apply {
if (firstOrNull()?.text != "全部大小") {
add(0, SubjectSettingEntity.Size(min = -1, max = -1, text = "全部大小"))
}
}
}
backgroundView.setOnClickListener {
popupWindow.dismiss()
}
for (size in sizeFilterArray!!) {
val item = inflater.inflate(R.layout.item_filter_size, flexboxLayout, false)
// 单列 3 个,强行设置宽度为屏幕的 1/3
val width = sizeTv.context.resources.displayMetrics.widthPixels / 3
val height = item.layoutParams.height
item.layoutParams = ViewGroup.LayoutParams(width, height)
flexboxLayout.addView(item)
val tv = item.findViewById<TextView>(R.id.size_tv)
tv.text = size.text
toggleHighlightedTextView(tv, sizeText == size.text)
tv.tag = size.text
item.setOnClickListener {
toggleHighlightedTextView(tv, true)
popupWindow.dismiss()
sizeTv.text = size.text
mOnCatalogFilterSetupListener?.onSetupSortSize(size)
}
}
popupWindow.setOnDismissListener {
sizeTv.setTextColor(R.color.text_757575.toColor())
sizeTv.setCompoundDrawables(null, null, drawableDown, null)
}
popupWindow.isTouchable = true
popupWindow.isFocusable = true
popupWindow.animationStyle = 0
popupWindow.showAsDropDown(containerView, 0, 0)
}
private fun getDefaultSizeFilterArray(): ArrayList<SubjectSettingEntity.Size> {
return arrayListOf<SubjectSettingEntity.Size>().apply {
add(SubjectSettingEntity.Size(min = -1, max = -1, text = "全部大小"))
add(SubjectSettingEntity.Size(min = -1, max = 100, text = "100M以下"))
add(SubjectSettingEntity.Size(min = 100, max = 300, text = "100-300M"))
add(SubjectSettingEntity.Size(min = 300, max = 500, text = "300-500M"))
add(SubjectSettingEntity.Size(min = 500, max = 1000, text = "500M-1G"))
add(SubjectSettingEntity.Size(min = 1000, max = -1, text = "1G以上"))
}
}
interface OnCatalogFilterSetupListener {
fun onSetupSortSize(sortSize: SubjectSettingEntity.Size)
fun onSetupSortType(sortType: SortType)
fun onSetupSortCatalog(sortCatalog: CatalogEntity.SubCatalogEntity)
}
enum class SortType(val value: String) {
RECOMMENDED("热门推荐"),
NEWEST("最新上线"),
RATING("最高评分")
}
}

View File

@ -12,7 +12,7 @@ import android.widget.PopupWindow
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import com.gh.common.util.toColor
import com.gh.common.util.DisplayUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.SubjectSettingEntity
import com.google.android.flexbox.FlexboxLayout
@ -69,13 +69,16 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
mOnConfigFilterSetupListener = onConfigFilterSetupListener
}
private fun toggleHighlightedTextView(targetTextView: TextView, highlightIt: Boolean) {
fun toggleHighlightedTextView(targetTextView: TextView, highlightIt: Boolean) {
if (highlightIt) {
targetTextView.background = ContextCompat.getDrawable(targetTextView.context, R.drawable.bg_tag_text)
targetTextView.background = ContextCompat.getDrawable(targetTextView.context, R.drawable.text_blue_background)
targetTextView.setTextColor(Color.WHITE)
} else {
targetTextView.background = null
targetTextView.setTextColor(ContextCompat.getColor(targetTextView.context, R.color.text_757575))
val colorDrawable = GradientDrawable()
colorDrawable.setColor(Color.WHITE)
colorDrawable.cornerRadius = DisplayUtils.dip2px(1.5f).toFloat()
targetTextView.background = colorDrawable
targetTextView.setTextColor(ContextCompat.getColor(targetTextView.context, R.color.text_3a3a3a))
}
}
@ -85,8 +88,8 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
drawableUp?.setBounds(0, 0, drawableUp.minimumWidth, drawableUp.minimumHeight)
drawableDown?.setBounds(0, 0, drawableDown.minimumWidth, drawableDown.minimumHeight)
sizeTv.setTextColor(R.color.theme_font.toColor())
sizeTv.setCompoundDrawables(null, null, drawableUp, null)
sizeTv.text = "收起"
val inflater = LayoutInflater.from(sizeTv.context)
val layout = inflater.inflate(R.layout.layout_filter_size, null)
@ -143,24 +146,25 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
}
popupWindow.setOnDismissListener {
sizeTv.setTextColor(R.color.text_757575.toColor())
sizeTv.setCompoundDrawables(null, null, drawableDown, null)
if (sizeTv.text == "收起") {
sizeTv.text = sizeText
}
}
popupWindow.isTouchable = true
popupWindow.isFocusable = true
popupWindow.animationStyle = 0
popupWindow.showAsDropDown(containerView, 0, 0)
}
private fun getDefaultSizeFilterArray(): ArrayList<SubjectSettingEntity.Size> {
return arrayListOf<SubjectSettingEntity.Size>().apply {
add(SubjectSettingEntity.Size(min = -1, max = -1, text = "全部大小"))
add(SubjectSettingEntity.Size(min = -1, max = 100, text = "100M以下"))
add(SubjectSettingEntity.Size(min = 100, max = 300, text = "100-300M"))
add(SubjectSettingEntity.Size(min = 300, max = 500, text = "300-500M"))
add(SubjectSettingEntity.Size(min = 500, max = 1000, text = "500M-1G"))
add(SubjectSettingEntity.Size(min = 1000, max = -1, text = "1G以上"))
add(SubjectSettingEntity.Size(min = -1, max = 20, text = "20M以下"))
add(SubjectSettingEntity.Size(min = 20, max = 50, text = "20-50M"))
add(SubjectSettingEntity.Size(min = 50, max = 100, text = "50-100M"))
add(SubjectSettingEntity.Size(min = 100, max = 500, text = "100-500M"))
add(SubjectSettingEntity.Size(min = 500, max = -1, text = "500M以上"))
}
}

View File

@ -1,7 +1,6 @@
package com.gh.common.view
import android.content.Context
import android.graphics.RectF
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.ViewConfiguration
@ -38,9 +37,7 @@ class DraggableBigImageView @JvmOverloads constructor(context: Context, attrs: A
MotionEvent.ACTION_DOWN -> if (mInitScale == null || mInitScale == 0F) mInitScale = ssiv?.scale
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> up()
MotionEvent.ACTION_MOVE -> {
val rectF = RectF()
ssiv?.getPanRemaining(rectF)
if (mSingleTouch && mInitScale != 0F && (rectF.top == 0f || rectF.bottom == 0f)) {
if (mSingleTouch && mInitScale != 0F && ssiv?.scale == mInitScale) {
if (mLastX == 0F) mLastX = event.rawX
if (mLastY == 0F) mLastY = event.rawY
val offsetX = event.rawX - mLastX

View File

@ -100,8 +100,7 @@ public class ExpandTextView extends AppCompatTextView {
/**
* 适用于不使用 maxLines 而是整段收起时的文字来确定“...更多”的位置的样式
*
* @param shrankText 收起时的文字 (“...更多”跟在 shrankText 后)
* @param shrankText 收起时的文字 (“...更多”跟在 shrankText 后)
* @param expandedText 展开时的文字
*/
public void setShrankTextAndExpandedText(CharSequence shrankText, CharSequence expandedText) {
@ -123,11 +122,6 @@ public class ExpandTextView extends AppCompatTextView {
}
private void showExpandButton() {
// 避免二次生成展开按钮 (有点粗暴,但是为了满足 recyclerView 复用后没问题,还是每次都用当前文字来判断比较好)
if (getText().toString().endsWith(mExpandText)) {
return;
}
String finalEndText = "";
TextPaint paint = getPaint();
@ -166,10 +160,6 @@ public class ExpandTextView extends AppCompatTextView {
float subSequenceWidth;
for (int i = lastLineText.length() - 1; i > 0; i--) {
if (mUseGradientAlphaEndText) {
// 避免 additionalEntTextCount 大于 i 造成数组越界 (TODO 代码太多,有时间再检查)
if (additionalEndTextCount > i) return;
subSequence = lastLineText.subSequence(0, i - additionalEndTextCount);
subSequenceWidth = paint.measureText(subSequence.toString());

View File

@ -1,33 +0,0 @@
package com.gh.common.view;
import android.content.Context;
import android.util.AttributeSet;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class FixGridLayoutManager extends GridLayoutManager {
public FixGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public FixGridLayoutManager(Context context, int spanCount) {
super(context, spanCount);
}
public FixGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
super(context, spanCount, orientation, reverseLayout);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
try {
super.onLayoutChildren(recycler, state);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -4,7 +4,6 @@ import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.widget.ScrollView
import java.lang.IllegalArgumentException
/**
* 不能滑动的 ScrollView
@ -12,16 +11,10 @@ import java.lang.IllegalArgumentException
class FixedScrollView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : ScrollView(context, attrs) {
override fun onTouchEvent(ev: MotionEvent?): Boolean {
// super.onTouchEvent may cause IllegalArgumentException which is crazy!
try {
return when (ev?.action) {
MotionEvent.ACTION_DOWN -> true
else -> super.onTouchEvent(ev)
}
} catch (e: IllegalArgumentException) {
e.printStackTrace()
return when (ev?.action) {
MotionEvent.ACTION_DOWN -> true
else -> super.onTouchEvent(ev)
}
return false
}
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {

View File

@ -5,7 +5,6 @@ import android.text.TextUtils
import android.util.AttributeSet
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import com.facebook.drawee.generic.RoundingParams
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.common.util.DisplayUtils
@ -19,7 +18,6 @@ class GameIconView : ConstraintLayout {
private var mCornerRadius = 10
private var mBorderColor = 0
private var mGameIconOverlayColor = 0
private var mBorderWidth = 1
private var mFadeDuration = -1
@ -38,15 +36,11 @@ class GameIconView : ConstraintLayout {
val ta = context.obtainStyledAttributes(attrs, R.styleable.GameIconView)
mCornerRadius = ta.getDimensionPixelSize(R.styleable.GameIconView_gameIconCornerRadius, DisplayUtils.dip2px(10F))
mBorderColor = ta.getColor(R.styleable.GameIconView_gameIconBorderColor, 0)
mGameIconOverlayColor = ta.getColor(R.styleable.GameIconView_gameIconOverlayColor, 0)
mBorderWidth = ta.getDimensionPixelSize(R.styleable.GameIconView_gameIconBorderWidth, 1)
mFadeDuration = ta.getInt(R.styleable.GameIconView_gameIconFadeDuration, -1)
ta.recycle()
val roundingParams = RoundingParams.fromCornersRadius(mCornerRadius.toFloat())
if (mGameIconOverlayColor != 0) {
roundingParams.overlayColor = mGameIconOverlayColor
}
if (mBorderColor != 0) {
roundingParams.setBorder(mBorderColor, mBorderWidth.toFloat())

View File

@ -20,7 +20,7 @@ class GradientAlphaTextSpan(var textColor: Int) : ReplacementSpan() {
originalColor, originalColorWithAlphaChanged, Shader.TileMode.CLAMP)
paint.shader = mShader
canvas.drawText(text ?: "", start, end, x, y.toFloat(), paint)
canvas.drawText(text, start, end, x, y.toFloat(), paint)
paint.shader = null
}

View File

@ -1,221 +0,0 @@
package com.gh.common.view
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import com.facebook.drawee.drawable.ScalingUtils
import com.gh.common.util.*
import com.gh.gamecenter.ImageViewerActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.databinding.ItemCommunityImageBinding
import com.gh.gamecenter.qa.entity.AnswerEntity
import com.gh.gamecenter.qa.entity.CommunityVideoEntity
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
import java.util.ArrayList
class ImageContainerView : LinearLayout {
private var mAnswerEntity: AnswerEntity? = null
//三图默认宽度
private var mDefaultWidth = 0f
//单图固定宽度
private var mFixdWidth = 0f
//最小比例
private var mMinRatio = 3 / 4f
//最大比例
private var mMaxRatio = 3 / 2f
//长图比例
private var mLongPictureRatio = 9 / 18f
private var mEntrance = ""
private var mPath = ""
//图片之间的间距
private val mItemSpace = 4f.dip2px()
private var index = 0
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
initView(attrs)
}
private fun initView(attrs: AttributeSet?) {
orientation = HORIZONTAL
val ta = context.obtainStyledAttributes(attrs, R.styleable.ImageContainerView)
val offset = ta.getDimensionPixelSize(R.styleable.ImageContainerView_offset, 0)
mDefaultWidth = (DisplayUtils.getScreenWidth() - offset.toFloat() - mItemSpace * 2) / 3
mFixdWidth = (DisplayUtils.getScreenWidth() - offset.toFloat() - mItemSpace * 2) * 2 / 3
ta.recycle()
}
fun bindData(entity: AnswerEntity, entrance: String = "", path: String = "") {
mAnswerEntity = entity
mEntrance = entrance
mPath = path
index = 0
removeAllViews()
if (entity.getPassVideos().isNullOrEmpty() && entity.images.isNullOrEmpty()) {
visibility = View.GONE
return
}
visibility = View.VISIBLE
if (mAnswerEntity?.type == "community_article") {
//若文章内容含有图片及视频,则信息流卡片,仅展示图片,且标题后带有‘有视频’标签
//若文章内容仅含有图片,则信息流卡片,仅展示图片,无标签
//若文章内容仅含有视频,则信息流卡片,仅展示视频,无标签
when {
entity.images.isNotEmpty() -> {
val imagesInfo = entity.imagesInfo
val images = entity.images.take(3)
images.forEachIndexed { index, url ->
val width = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].width else 0
val height = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].height else 0
bindImage(url, width, height, images.size == 1)
}
}
entity.getPassVideos().isNotEmpty() -> {
val video = entity.getPassVideos()[0]
bindVideo(video, video.width, video.height, true)
}
else -> {
// do noting
}
}
} else {
//若问答内容含有图片及视频,则信息流卡片,同时展示图片及视频,且参考以往排序逻辑(视频优先放置第一位),无标签
//若问答内容仅含有图片,则信息流卡片,仅展示图片,无标签
//若问答内容仅含有视频,则信息流卡片,仅展示视频,无标签
if (entity.getPassVideos().isNotEmpty()) {
val video = entity.getPassVideos()[0]
bindVideo(video, video.width, video.height, mAnswerEntity?.images.isNullOrEmpty())
entity.images.take(2).forEachIndexed { index, url ->
val imagesInfo = entity.imagesInfo
val width = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].width else 0
val height = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].height else 0
bindImage(url, width, height, false)
}
} else {
val images = entity.images.take(3)
images.forEachIndexed { index, url ->
val imagesInfo = entity.imagesInfo
val width = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].width else 0
val height = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].height else 0
bindImage(url, width, height, images.size == 1)
}
}
}
}
private fun bindVideo(video: CommunityVideoEntity, width: Int, height: Int, isChangeRatio: Boolean) {
val binding = ItemCommunityImageBinding.inflate(LayoutInflater.from(context), null, false)
addView(binding.root)
binding.durationOrNumTv.visibility = View.VISIBLE
binding.videoPlay.visibility = View.VISIBLE
binding.labelIcon.visibility = View.GONE
binding.durationOrNumTv.text = video.duration
displayImage(binding, video.poster, width.toFloat(), height.toFloat(), isChangeRatio, true)
binding.root.setOnClickListener {
debounceActionWithInterval(it.id, 1000) {
if (mAnswerEntity == null) return@debounceActionWithInterval
val videoEntity = mAnswerEntity!!.getPassVideos()[0]
DirectUtils.directToVideoDetail(context,
videoEntity.id,
VideoDetailContainerViewModel.Location.VIDEO_HOT.value,
showComment = false,
entrance = mEntrance,
path = mPath)
}
}
index++
}
private fun bindImage(url: String, width: Int, height: Int, isChangeRatio: Boolean) {
val binding = ItemCommunityImageBinding.inflate(LayoutInflater.from(context), null, false)
binding.root.tag = index
addView(binding.root)
binding.durationOrNumTv.visibility = View.GONE
binding.videoPlay.visibility = View.GONE
displayImage(binding, url, width.toFloat(), height.toFloat(), isChangeRatio)
binding.root.setOnClickListener {
debounceActionWithInterval(it.id, 1000) {
if (mAnswerEntity == null) return@debounceActionWithInterval
val position = if (mAnswerEntity?.type == "community_article") {
binding.root.tag as Int
} else {
if (mAnswerEntity!!.getPassVideos().isNullOrEmpty()) binding.root.tag as Int else (binding.root.tag as Int) - 1
}
val intent = ImageViewerActivity.getIntent(context, mAnswerEntity!!.images as ArrayList<String>, position, binding.root,
if (mAnswerEntity?.type == "community_article") mAnswerEntity else null, mEntrance)
context.startActivity(intent)
}
}
index++
}
private fun displayImage(binding: ItemCommunityImageBinding, url: String, width: Float, height: Float, isChangeRatio: Boolean, isVideo: Boolean = false) {
val params = binding.root.layoutParams as LayoutParams
val hierarchy = binding.image.hierarchy
binding.labelIcon.visibility = View.GONE
if (width != 0f && height != 0f) {
val picRatio = width / height
if (isChangeRatio) {
when {
picRatio <= mMinRatio -> {
params.height = (mFixdWidth / mMinRatio).toInt()
ImageUtils.display(binding.image, url, false, TopCutProcess(mMinRatio))
}
picRatio >= mMaxRatio -> {
params.height = (mFixdWidth / mMaxRatio).toInt()
ImageUtils.display(binding.image, url, false)
}
else -> {
params.height = (mFixdWidth / picRatio).toInt()
ImageUtils.display(binding.image, url, false)
}
}
params.width = mFixdWidth.toInt()
} else {
params.width = mDefaultWidth.toInt()
params.height = mDefaultWidth.toInt()
ImageUtils.display(binding.image, url, false)
}
//长图
if (!isVideo && picRatio <= mLongPictureRatio) {
binding.labelIcon.visibility = View.VISIBLE
binding.labelIcon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_long_pic_label))
}
} else {
params.width = mDefaultWidth.toInt()
params.height = mDefaultWidth.toInt()
ImageUtils.display(binding.image, url, false)
}
if (url.endsWith(".gif")) {
binding.labelIcon.visibility = View.VISIBLE
binding.labelIcon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_gif_label))
}
val mediaCount = if (mAnswerEntity?.type == "community_article") {
mAnswerEntity?.images?.size ?: 0
} else {
(mAnswerEntity?.images?.size ?: 0) + (mAnswerEntity?.getPassVideos()?.size ?: 0)
}
if (!isVideo && index == 2 && mediaCount > 3) {
binding.labelIcon.visibility = View.GONE
binding.durationOrNumTv.visibility = View.VISIBLE
binding.durationOrNumTv.text = "+${mAnswerEntity?.images?.size}"
}
hierarchy.actualImageScaleType = ScalingUtils.ScaleType.CENTER_CROP
if (index != 0) params.leftMargin = mItemSpace
binding.root.layoutParams = params
}
}

View File

@ -2,7 +2,6 @@ package com.gh.common.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.Html;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
@ -32,7 +31,6 @@ public class MarqueeView extends ViewFlipper {
private int textSize = 14;
private int textColor = 0xffffffff;
private boolean useSingleLineText = false;
private boolean isHtmlText = false;
public MarqueeView(Context context, AttributeSet attrs) {
super(context, attrs);
@ -123,13 +121,9 @@ public class MarqueeView extends ViewFlipper {
tv.setEllipsize(TextUtils.TruncateAt.END);
}
tv.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
tv.setTextSize(textSize);
tv.setText(text);
tv.setTextColor(textColor);
if (isHtmlText) {
tv.setText(Html.fromHtml(text));
} else {
tv.setText(text);
}
tv.setTextSize(textSize);
return tv;
}
@ -139,12 +133,6 @@ public class MarqueeView extends ViewFlipper {
start();
}
public void startWithListForHtmlText(List<String> notices) {
isHtmlText = true;
setNotices(notices);
start();
}
public void enableSingleLineText() {
useSingleLineText = true;
}

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