Add forced mode

This commit is contained in:
方块君 2022-05-11 23:13:45 +08:00
parent 27f2c13ff5
commit d371a68382
3 changed files with 97 additions and 66 deletions

View File

@ -3,65 +3,102 @@ package xfk233.GenshinProxy
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.app.AlertDialog import android.app.AlertDialog
import android.app.Application
import android.content.Context
import android.content.res.XModuleResources
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.widget.EditText import android.widget.EditText
import android.widget.LinearLayout
import android.widget.Switch
import android.widget.Toast import android.widget.Toast
import com.github.kyuubiran.ezxhelper.init.EzXHelperInit import com.github.kyuubiran.ezxhelper.init.EzXHelperInit
import com.github.kyuubiran.ezxhelper.init.InitFields
import com.github.kyuubiran.ezxhelper.utils.findConstructor import com.github.kyuubiran.ezxhelper.utils.findConstructor
import com.github.kyuubiran.ezxhelper.utils.findMethod import com.github.kyuubiran.ezxhelper.utils.findMethod
import com.github.kyuubiran.ezxhelper.utils.findMethodOrNull import com.github.kyuubiran.ezxhelper.utils.findMethodOrNull
import com.github.kyuubiran.ezxhelper.utils.hookBefore import com.github.kyuubiran.ezxhelper.utils.hookBefore
import de.robv.android.xposed.IXposedHookLoadPackage import de.robv.android.xposed.IXposedHookLoadPackage
import de.robv.android.xposed.IXposedHookZygoteInit
import de.robv.android.xposed.XC_MethodHook
import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedBridge
import de.robv.android.xposed.callbacks.XC_LoadPackage import de.robv.android.xposed.callbacks.XC_LoadPackage
import java.util.regex.Pattern import java.util.regex.Pattern
import kotlin.system.exitProcess
class MainHook : IXposedHookLoadPackage { class MainHook : IXposedHookLoadPackage, IXposedHookZygoteInit {
private val regex = Pattern.compile("http(s|)://.*?\\.(hoyoverse|mihoyo|yuanshen|mob)\\.com") private val regex = Pattern.compile("http(s|)://.*?\\.(hoyoverse|mihoyo|yuanshen|mob)\\.com")
private lateinit var server: String private lateinit var server: String
private var forceUrl = false
private lateinit var modulePath: String
private lateinit var moduleRes: XModuleResources
override fun initZygote(startupParam: IXposedHookZygoteInit.StartupParam) {
modulePath = startupParam.modulePath
moduleRes = XModuleResources.createInstance(modulePath, null)
}
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) { override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
if (lpparam.packageName != "com.miHoYo.GenshinImpact") return if (lpparam.packageName != "com.miHoYo.GenshinImpact") return
EzXHelperInit.initHandleLoadPackage(lpparam) EzXHelperInit.initHandleLoadPackage(lpparam)
findMethod("com.miHoYo.GetMobileInfo.MainActivity") { name == "onCreate" }.hookBefore { findMethod(Application::class.java, true) { name == "attachBaseContext" }.hookBefore {
val context = it.thisObject as Activity val context = it.args[0] as Context
val sp = context.getPreferences(0) val sp = context.getSharedPreferences("serverConfig", 0)
forceUrl = sp.getBoolean("forceUrl", false)
server = sp.getString("serverip", "") ?: ""
}
sslHook(lpparam)
hook()
findMethod("com.miHoYo.GetMobileInfo.MainActivity") { name == "onCreate" }.hookBefore { param ->
val context = param.thisObject as Activity
val sp = context.getSharedPreferences("serverConfig", 0)
AlertDialog.Builder(context).apply { AlertDialog.Builder(context).apply {
setTitle("Select server / 选择服务器") setCancelable(false)
setMessage("Input server address / 请输入服务器地址: ") setTitle(moduleRes.getString(R.string.SelectServer))
setView(EditText(context).apply { setMessage(moduleRes.getString(R.string.Tips))
hint = "http(s)://server.com:1234" setView(LinearLayout(context).apply {
val str = sp.getString("serverip", "") ?: "" orientation = LinearLayout.VERTICAL
setText(str.toCharArray(), 0, str.length) addView(EditText(context).apply {
addTextChangedListener(object : TextWatcher { hint = "http(s)://server.com:1234"
override fun beforeTextChanged(p0: CharSequence, p1: Int, p2: Int, p3: Int) {} val str = sp.getString("serverip", "") ?: ""
override fun onTextChanged(p0: CharSequence, p1: Int, p2: Int, p3: Int) {} setText(str.toCharArray(), 0, str.length)
addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence, p1: Int, p2: Int, p3: Int) {}
override fun onTextChanged(p0: CharSequence, p1: Int, p2: Int, p3: Int) {}
@SuppressLint("CommitPrefEdits") @SuppressLint("CommitPrefEdits")
override fun afterTextChanged(p0: Editable) { override fun afterTextChanged(p0: Editable) {
sp.edit().run {
putString("serverip", p0.toString())
apply()
}
}
})
})
addView(Switch(context).apply {
text = moduleRes.getString(R.string.ForcedMode)
isChecked = sp.getBoolean("forceUrl", false)
setOnClickListener {
sp.edit().run { sp.edit().run {
putString("serverip", p0.toString()) putBoolean("forceUrl", (it as Switch).isChecked)
apply() apply()
} }
forceUrl = (it as Switch).isChecked
} }
}) })
}) })
setNegativeButton("Custom server / 自定义服务器") { _, _ -> setNegativeButton(moduleRes.getString(R.string.CustomServer)) { _, _ ->
val ip = sp.getString("serverip", "") ?: "" val ip = sp.getString("serverip", "") ?: ""
if (ip == "") { if (ip == "") {
Toast.makeText(context, "Server address error.", Toast.LENGTH_LONG).show() Toast.makeText(context, moduleRes.getString(R.string.ServerAddressError), Toast.LENGTH_LONG).show()
exitProcess(1) context.finish()
} else { } else {
server = ip server = ip
forceUrl = true
} }
sslHook(lpparam)
hook()
} }
setNeutralButton("Official server / 官方服务器") { _, _ -> setNeutralButton(moduleRes.getString(R.string.OfficialServer)) { _, _ ->
forceUrl = false
server = ""
} }
}.show() }.show()
} }
@ -79,62 +116,40 @@ class MainHook : IXposedHookLoadPackage {
private fun hook() { private fun hook() {
findMethod("com.miHoYo.sdk.webview.MiHoYoWebview") { name == "load" && parameterTypes[0] == String::class.java && parameterTypes[1] == String::class.java }.hookBefore { findMethod("com.miHoYo.sdk.webview.MiHoYoWebview") { name == "load" && parameterTypes[0] == String::class.java && parameterTypes[1] == String::class.java }.hookBefore {
XposedBridge.log("old: " + it.args[1].toString()) replaceUrl(it, 1)
val m = regex.matcher(it.args[1].toString())
if (m.find()) {
it.args[1] = m.replaceAll(server)
}
XposedBridge.log("new: " + it.args[1].toString())
} }
findMethod("okhttp3.HttpUrl") { name == "parse" && parameterTypes[0] == String::class.java }.hookBefore { findMethod("okhttp3.HttpUrl") { name == "parse" && parameterTypes[0] == String::class.java }.hookBefore {
XposedBridge.log("old: " + it.args[0].toString()) replaceUrl(it, 0)
val m = regex.matcher(it.args[0].toString())
if (m.find()) {
it.args[0] = m.replaceAll(server)
}
XposedBridge.log("new: " + it.args[0].toString())
} }
findMethod("com.combosdk.lib.third.okhttp3.HttpUrl") { name == "parse" && parameterTypes[0] == String::class.java }.hookBefore { findMethod("com.combosdk.lib.third.okhttp3.HttpUrl") { name == "parse" && parameterTypes[0] == String::class.java }.hookBefore {
XposedBridge.log("old: " + it.args[0].toString()) replaceUrl(it, 0)
val m = regex.matcher(it.args[0].toString())
if (m.find()) {
it.args[0] = m.replaceAll(server)
}
XposedBridge.log("new: " + it.args[0].toString())
} }
findMethod("com.google.gson.Gson") { name == "fromJson" && parameterTypes[0] == String::class.java && parameterTypes[1] == java.lang.reflect.Type::class.java }.hookBefore { findMethod("com.google.gson.Gson") { name == "fromJson" && parameterTypes[0] == String::class.java && parameterTypes[1] == java.lang.reflect.Type::class.java }.hookBefore {
XposedBridge.log("old: " + it.args[0].toString()) replaceUrl(it, 0)
val m = regex.matcher(it.args[0].toString())
if (m.find()) {
it.args[0] = m.replaceAll(server)
}
XposedBridge.log("new: " + it.args[0].toString())
} }
findConstructor("java.net.URL") { parameterTypes[0] == String::class.java }.hookBefore { findConstructor("java.net.URL") { parameterTypes[0] == String::class.java }.hookBefore {
XposedBridge.log("old: " + it.args[0].toString()) replaceUrl(it, 0)
val m = regex.matcher(it.args[0].toString())
if (m.find()) {
it.args[0] = m.replaceAll(server)
}
XposedBridge.log("new: " + it.args[0].toString())
} }
findMethod("com.combosdk.lib.third.okhttp3.Request\$Builder") { name == "url" && parameterTypes[0] == String::class.java }.hookBefore { findMethod("com.combosdk.lib.third.okhttp3.Request\$Builder") { name == "url" && parameterTypes[0] == String::class.java }.hookBefore {
XposedBridge.log("old: " + it.args[0].toString()) replaceUrl(it, 0)
val m = regex.matcher(it.args[0].toString())
if (m.find()) {
it.args[0] = m.replaceAll(server)
}
XposedBridge.log("new: " + it.args[0].toString())
} }
findMethod("okhttp3.Request\$Builder") { name == "url" && parameterTypes[0] == String::class.java }.hookBefore { findMethod("okhttp3.Request\$Builder") { name == "url" && parameterTypes[0] == String::class.java }.hookBefore {
XposedBridge.log("old: " + it.args[0].toString()) replaceUrl(it, 0)
val m = regex.matcher(it.args[0].toString())
if (m.find()) {
it.args[0] = m.replaceAll(server)
}
XposedBridge.log("new: " + it.args[0].toString())
} }
} }
private fun replaceUrl(method: XC_MethodHook.MethodHookParam, args: Int) {
if (!forceUrl) return
if (!this::server.isInitialized) return
if (server == "") return
if (BuildConfig.DEBUG) XposedBridge.log("old: " + method.args[args].toString())
val m = regex.matcher(method.args[args].toString())
if (m.find()) {
method.args[args] = m.replaceAll(server)
}
if (BuildConfig.DEBUG) XposedBridge.log("new: " + method.args[args].toString())
}
} }

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Genshin Impact Proxy</string>
<string name="CustomServer">自定义服务器</string>
<string name="OfficialServer">官方服务器</string>
<string name="SelectServer">选择服务器</string>
<string name="Tips">第一次使用请输入好服务器地址后进入官方服务器下载资源,之后便可进入私服。\n强制模式: 强制替换全部域名\n\n请输入服务器地址: </string>
<string name="ForcedMode">强制模式 (需重启)</string>
<string name="ServerAddressError">服务器地址错误</string>
</resources>

View File

@ -1,3 +1,9 @@
<resources> <resources>
<string name="app_name">Genshin Impact Proxy</string> <string name="app_name">Genshin Impact Proxy</string>
<string name="CustomServer">Custom server</string>
<string name="OfficialServer">Official server</string>
<string name="SelectServer">Select server</string>
<string name="Tips">For the first time, please enter the server address and enter the official server to download resources. Then you can enter the private server.\nForced mode: Forced replacement of all domain names\n\nInput server address: </string>
<string name="ForcedMode">Forced mode (restart required)</string>
<string name="ServerAddressError">Server address error.</string>
</resources> </resources>