diff --git a/app/src/main/java/xfk233/GenshinProxy/MainHook.kt b/app/src/main/java/xfk233/GenshinProxy/MainHook.kt index e64ac52..ca08faf 100644 --- a/app/src/main/java/xfk233/GenshinProxy/MainHook.kt +++ b/app/src/main/java/xfk233/GenshinProxy/MainHook.kt @@ -3,65 +3,102 @@ package xfk233.GenshinProxy import android.annotation.SuppressLint import android.app.Activity import android.app.AlertDialog +import android.app.Application +import android.content.Context +import android.content.res.XModuleResources import android.text.Editable import android.text.TextWatcher import android.widget.EditText +import android.widget.LinearLayout +import android.widget.Switch import android.widget.Toast 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.findMethod import com.github.kyuubiran.ezxhelper.utils.findMethodOrNull import com.github.kyuubiran.ezxhelper.utils.hookBefore 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.callbacks.XC_LoadPackage 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 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) { if (lpparam.packageName != "com.miHoYo.GenshinImpact") return EzXHelperInit.initHandleLoadPackage(lpparam) - findMethod("com.miHoYo.GetMobileInfo.MainActivity") { name == "onCreate" }.hookBefore { - val context = it.thisObject as Activity - val sp = context.getPreferences(0) + findMethod(Application::class.java, true) { name == "attachBaseContext" }.hookBefore { + val context = it.args[0] as Context + 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 { - setTitle("Select server / 选择服务器") - setMessage("Input server address / 请输入服务器地址: ") - setView(EditText(context).apply { - hint = "http(s)://server.com:1234" - val str = sp.getString("serverip", "") ?: "" - 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) {} + setCancelable(false) + setTitle(moduleRes.getString(R.string.SelectServer)) + setMessage(moduleRes.getString(R.string.Tips)) + setView(LinearLayout(context).apply { + orientation = LinearLayout.VERTICAL + addView(EditText(context).apply { + hint = "http(s)://server.com:1234" + val str = sp.getString("serverip", "") ?: "" + 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") - override fun afterTextChanged(p0: Editable) { + @SuppressLint("CommitPrefEdits") + 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 { - putString("serverip", p0.toString()) + putBoolean("forceUrl", (it as Switch).isChecked) apply() } + forceUrl = (it as Switch).isChecked } }) }) - setNegativeButton("Custom server / 自定义服务器") { _, _ -> + setNegativeButton(moduleRes.getString(R.string.CustomServer)) { _, _ -> val ip = sp.getString("serverip", "") ?: "" if (ip == "") { - Toast.makeText(context, "Server address error.", Toast.LENGTH_LONG).show() - exitProcess(1) + Toast.makeText(context, moduleRes.getString(R.string.ServerAddressError), Toast.LENGTH_LONG).show() + context.finish() } else { server = ip + forceUrl = true } - sslHook(lpparam) - hook() } - setNeutralButton("Official server / 官方服务器") { _, _ -> + setNeutralButton(moduleRes.getString(R.string.OfficialServer)) { _, _ -> + forceUrl = false + server = "" } }.show() } @@ -79,62 +116,40 @@ class MainHook : IXposedHookLoadPackage { private fun hook() { 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()) - val m = regex.matcher(it.args[1].toString()) - if (m.find()) { - it.args[1] = m.replaceAll(server) - } - XposedBridge.log("new: " + it.args[1].toString()) + replaceUrl(it, 1) } findMethod("okhttp3.HttpUrl") { name == "parse" && parameterTypes[0] == String::class.java }.hookBefore { - XposedBridge.log("old: " + it.args[0].toString()) - val m = regex.matcher(it.args[0].toString()) - if (m.find()) { - it.args[0] = m.replaceAll(server) - } - XposedBridge.log("new: " + it.args[0].toString()) + replaceUrl(it, 0) } findMethod("com.combosdk.lib.third.okhttp3.HttpUrl") { name == "parse" && parameterTypes[0] == String::class.java }.hookBefore { - XposedBridge.log("old: " + it.args[0].toString()) - val m = regex.matcher(it.args[0].toString()) - if (m.find()) { - it.args[0] = m.replaceAll(server) - } - XposedBridge.log("new: " + it.args[0].toString()) + replaceUrl(it, 0) } 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()) - val m = regex.matcher(it.args[0].toString()) - if (m.find()) { - it.args[0] = m.replaceAll(server) - } - XposedBridge.log("new: " + it.args[0].toString()) + replaceUrl(it, 0) } findConstructor("java.net.URL") { parameterTypes[0] == String::class.java }.hookBefore { - XposedBridge.log("old: " + it.args[0].toString()) - val m = regex.matcher(it.args[0].toString()) - if (m.find()) { - it.args[0] = m.replaceAll(server) - } - XposedBridge.log("new: " + it.args[0].toString()) + replaceUrl(it, 0) } findMethod("com.combosdk.lib.third.okhttp3.Request\$Builder") { name == "url" && parameterTypes[0] == String::class.java }.hookBefore { - XposedBridge.log("old: " + it.args[0].toString()) - val m = regex.matcher(it.args[0].toString()) - if (m.find()) { - it.args[0] = m.replaceAll(server) - } - XposedBridge.log("new: " + it.args[0].toString()) + replaceUrl(it, 0) } findMethod("okhttp3.Request\$Builder") { name == "url" && parameterTypes[0] == String::class.java }.hookBefore { - XposedBridge.log("old: " + it.args[0].toString()) - val m = regex.matcher(it.args[0].toString()) - if (m.find()) { - it.args[0] = m.replaceAll(server) - } - XposedBridge.log("new: " + it.args[0].toString()) + replaceUrl(it, 0) } } + + 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()) + } } diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 0000000..ab1fa84 --- /dev/null +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,10 @@ + + + Genshin Impact Proxy + 自定义服务器 + 官方服务器 + 选择服务器 + 第一次使用请输入好服务器地址后进入官方服务器下载资源,之后便可进入私服。\n强制模式: 强制替换全部域名\n\n请输入服务器地址: + 强制模式 (需重启) + 服务器地址错误 + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fac8215..de32885 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,9 @@ Genshin Impact Proxy + Custom server + Official server + Select server + 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: + Forced mode (restart required) + Server address error. \ No newline at end of file