Skip to content

Commit a419a5c

Browse files
authored
fix: custom theme & show av (yujincheng08#1662)
- 修复自定义主题 - 修复显示AV号 - 修复自定义字幕偶尔初始化失败
1 parent 7a8819a commit a419a5c

File tree

5 files changed

+151
-43
lines changed

5 files changed

+151
-43
lines changed

app/src/main/java/me/iacn/biliroaming/BiliBiliPackage.kt

Lines changed: 97 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ class BiliBiliPackage constructor(private val mClassLoader: ClassLoader, mContex
174174
val liveRTCSourceServiceImplClass by Weak { mHookInfo.liveQuality.sourceService.class_ from mClassLoader }
175175
val defaultRequestInterceptClass by Weak { mHookInfo.liveQuality.interceptor.class_ from mClassLoader }
176176
val httpUrlClass by Weak { mHookInfo.okHttp.httpUrl.class_ from mClassLoader }
177+
val preBuiltConfigClass by Weak { mHookInfo.preBuiltConfig.class_ from mClassLoader }
178+
val dataSPClass by Weak { mHookInfo.dataSP.class_ from mClassLoader }
177179

178180
// for v8.17.0+
179181
val useNewMossFunc = instance.viewMossClass?.declaredMethods?.any {
@@ -349,6 +351,11 @@ class BiliBiliPackage constructor(private val mClassLoader: ClassLoader, mContex
349351

350352
fun httpUrlParseMethod() = mHookInfo.okHttp.httpUrl.parse.orNull
351353

354+
fun getPreBuiltConfigMethod() = mHookInfo.preBuiltConfig.get.orNull
355+
356+
fun getDataSPMethod() = mHookInfo.dataSP.get.orNull
357+
358+
352359
private fun readHookInfo(context: Context): Configs.HookInfo {
353360
try {
354361
val hookInfoFile = File(context.cacheDir, Constant.HOOK_INFO_FILE_NAME)
@@ -793,21 +800,50 @@ class BiliBiliPackage constructor(private val mClassLoader: ClassLoader, mContex
793800
}?.name ?: return@class_
794801
}
795802
themeName = themeName {
796-
val themeNameClassRegex = Regex("""^tv\.danmaku\.bili\.ui\.garb\.\w?$""")
797-
val themeNameClass = classesList.filter {
798-
it.startsWith("tv.danmaku.bili.ui.garb") && it.contains(themeNameClassRegex)
799-
}.map {
800-
it.findClass(classloader)
801-
}.firstOrNull { c ->
802-
c.declaredFields.count {
803-
Modifier.isStatic(it.modifiers) && it.type == Map::class.java
804-
} == 1
805-
}
803+
val mainGarbClass = dexHelper.findMethodUsingString(
804+
".garb.GARB_CHANGE",
805+
false,
806+
-1,
807+
-1,
808+
null,
809+
-1,
810+
null,
811+
null,
812+
null,
813+
true
814+
).asSequence().mapNotNull {
815+
dexHelper.decodeMethodIndex(it)?.declaringClass
816+
}.firstOrNull() ?: return@themeName
817+
val id2NameIndex = dexHelper.findMethodUsingString(
818+
"white",
819+
false,
820+
-1,
821+
1,
822+
null,
823+
dexHelper.encodeClassIndex(mainGarbClass),
824+
null,
825+
null,
826+
null,
827+
true
828+
).asSequence().firstOrNull() ?: return@themeName
829+
val themeNameClass = dexHelper.findMethodInvoking(
830+
id2NameIndex,
831+
dexHelper.encodeClassIndex(Map::class.java),
832+
0,
833+
null,
834+
-1,
835+
null,
836+
null,
837+
null,
838+
true
839+
).asSequence().mapNotNull {
840+
dexHelper.decodeMethodIndex(it)?.declaringClass
841+
}.firstOrNull() ?: return@themeName
806842
class_ = class_ {
807-
name = themeNameClass?.name ?: return@class_
843+
name = themeNameClass.name
808844
}
809845
field = field {
810-
name = themeNameClass?.declaredFields?.firstOrNull {
846+
name = themeNameClass.declaredFields.firstOrNull {
811847
it.type == Map::class.java
812848
&& Modifier.isStatic(it.modifiers)
813849
}?.name ?: return@field
@@ -2225,7 +2261,55 @@ class BiliBiliPackage constructor(private val mClassLoader: ClassLoader, mContex
22252261
intercept = method { name = interceptMethod.name }
22262262
}
22272263
}
2228-
2264+
preBuiltConfig = preBuiltConfig {
2265+
val getMap = dexHelper.findMethodUsingString(
2266+
"/config.json",
2267+
false,
2268+
-1,
2269+
-1,
2270+
null,
2271+
-1,
2272+
null,
2273+
null,
2274+
null,
2275+
true
2276+
).asSequence().mapNotNull { dexHelper.decodeMethodIndex(it) }.firstOrNull()
2277+
?: return@preBuiltConfig
2278+
class_ = class_ { name = getMap.declaringClass.name }
2279+
get = method { name = getMap.name }
2280+
}
2281+
dataSP = dataSP {
2282+
val spxClass =
2283+
("com.bilibili.lib.blkv.SharedPrefX" from classloader) ?: return@dataSP
2284+
val blkvClass = ("com.bilibili.lib.blkv.BLKV" from classloader) ?: return@dataSP
2285+
val getBLSP = runCatchingOrNull {
2286+
blkvClass.getDeclaredMethod(
2287+
"getBLSharedPreferences",
2288+
Context::class.java,
2289+
File::class.java,
2290+
Boolean::class.javaPrimitiveType,
2291+
Int::class.javaPrimitiveType
2292+
)
2293+
} ?: return@dataSP
2294+
val getDataSP = dexHelper.findMethodInvoked(
2295+
dexHelper.encodeMethodIndex(getBLSP),
2296+
dexHelper.encodeClassIndex(spxClass),
2297+
-1,
2298+
null,
2299+
-1,
2300+
null,
2301+
null,
2302+
null,
2303+
false
2304+
).asSequence().mapNotNull {
2305+
dexHelper.decodeMethodIndex(it)
2306+
}.firstOrNull {
2307+
Log.d(it)
2308+
it.declaringClass.name.startsWith("com.bilibili.lib.blconfig.internal.TypedContext")
2309+
} ?: return@dataSP
2310+
class_ = class_ { name = getDataSP.declaringClass.name }
2311+
get = method { name = getDataSP.name }
2312+
}
22292313
dexHelper.close()
22302314
}
22312315

app/src/main/java/me/iacn/biliroaming/hook/EnvHook.kt

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,55 @@
11
package me.iacn.biliroaming.hook
22

33
import android.content.SharedPreferences
4+
import me.iacn.biliroaming.BiliBiliPackage.Companion.instance
45
import me.iacn.biliroaming.utils.*
56
import java.lang.reflect.Proxy
67
import java.util.regex.Pattern
78

89
class EnvHook(classLoader: ClassLoader) : BaseHook(classLoader) {
910
override fun startHook() {
1011
Log.d("startHook: Env")
11-
"com.bilibili.lib.blconfig.internal.EnvContext\$preBuiltConfig\$2".hookAfterMethod(
12-
mClassLoader,
13-
"invoke"
14-
) { param ->
15-
@Suppress("UNCHECKED_CAST")
16-
val result = param.result as MutableMap<String, String?>
17-
for (config in configSet) {
18-
(if (sPrefs.getBoolean(
19-
config.config,
20-
false
21-
)
22-
) config.trueValue else config.falseValue)
23-
?.let { result[config.key] = it } ?: result.remove(config.key)
12+
13+
// EnvContext
14+
instance.preBuiltConfigClass?.let {
15+
val hooker: Hooker = hooker@ { param ->
16+
@Suppress("UNCHECKED_CAST")
17+
val result = param.result as MutableMap<String, String?>
18+
for (config in configSet) {
19+
(if (sPrefs.getBoolean(
20+
config.config,
21+
false
22+
)
23+
) config.trueValue else config.falseValue)
24+
?.let { result[config.key] = it } ?: result.remove(config.key)
25+
}
2426
}
27+
// v8.28.0 - ?
28+
it.hookAfterMethod(instance.getPreBuiltConfigMethod(), hooker = hooker)
29+
// ? - v8.48.0 ..
30+
it.hookAfterMethod(instance.getPreBuiltConfigMethod(), it, hooker = hooker)
2531
}
26-
"com.bilibili.lib.blconfig.internal.TypedContext\$dataSp\$2".hookAfterMethod(
27-
mClassLoader,
28-
"invoke"
29-
) { param ->
30-
val result = param.result as SharedPreferences
31-
// this indicates the proper instance
32-
if (!result.contains("bv.enable_bv")) return@hookAfterMethod
33-
for (config in configSet) {
34-
(if (sPrefs.getBoolean(
35-
config.config,
36-
false
37-
)
38-
) config.trueValue else config.falseValue)
39-
?.let { result.edit().putString(config.key, it).apply() }
40-
?: result.edit().remove(config.key).apply()
32+
33+
// TypedContext
34+
instance.dataSPClass?.let {
35+
val hooker: Hooker = hooker@ { param ->
36+
val result = param.result as SharedPreferences
37+
// this indicates the proper instance
38+
if (!result.contains("bv.enable_bv")) return@hooker
39+
for (config in configSet) {
40+
(if (sPrefs.getBoolean(
41+
config.config,
42+
false
43+
)
44+
) config.trueValue else config.falseValue)
45+
?.let { result.edit().putString(config.key, it).apply() }
46+
?: result.edit().remove(config.key).apply()
47+
}
4148
}
49+
// v8.28.0 - ?
50+
it.hookAfterMethod(instance.getDataSPMethod(), hooker = hooker)
51+
// ? - v8.48.0 ..
52+
it.hookAfterMethod(instance.getDataSPMethod(), it, hooker = hooker)
4253
}
4354

4455
"com.bilibili.lib.blconfig.internal.OverrideConfig".findClassOrNull(mClassLoader)

app/src/main/java/me/iacn/biliroaming/hook/SubtitleHook.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,9 @@ class SubtitleHook(classLoader: ClassLoader) : BaseHook(classLoader) {
133133
}
134134
private val offset by lazy { sPrefs.getInt("subtitle_offset", 0) }
135135

136-
private val closeText =
136+
private val closeText by lazy {
137137
currentContext.getString(getResId("Player_option_subtitle_lan_doc_nodisplay", "string"))
138+
}
138139

139140
private var subtitleFont: Typeface? = null
140141

app/src/main/proto/me/iacn/biliroaming/configs.proto

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,16 @@ message LiveQuality {
302302
optional DefaultRequestIntercept interceptor = 3;
303303
}
304304

305+
message PreBuiltConfig {
306+
optional Class class = 1;
307+
optional Method get = 2;
308+
}
309+
310+
message DataSP {
311+
optional Class class = 1;
312+
optional Method get = 2;
313+
}
314+
305315
message HookInfo {
306316
int64 last_update_time = 1;
307317
optional MapIds map_ids = 2;
@@ -368,4 +378,6 @@ message HookInfo {
368378
optional Continuation continuation = 96;
369379
optional VipQualityTrialService vipQualityTrialService = 97;
370380
optional LiveQuality liveQuality = 98;
381+
optional PreBuiltConfig preBuiltConfig = 99;
382+
optional DataSP dataSP = 100;
371383
}

0 commit comments

Comments
 (0)