diff --git a/app/build.gradle b/app/build.gradle index 896e9ae..dcb1628 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,10 +2,17 @@ plugins { alias(libs.plugins.android.application) } +static def getGitHash() { + def process = "git rev-parse HEAD".execute() + process.in.text.trim() +} + android { namespace 'com.sevtinge.vojazento' compileSdk 34 + def gitHash = getGitHash() + defaultConfig { applicationId "com.sevtinge.vojazento" minSdk 24 @@ -19,8 +26,10 @@ android { buildTypes { release { minifyEnabled false + android.buildFeatures.buildConfig true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' versionNameSuffix "_" + java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd").format(java.time.LocalDateTime.now()) + buildConfigField "String", "GIT_HASH", "\"${gitHash}\"" } } compileOptions { diff --git a/app/src/main/java/com/sevtinge/vojazento/XposedInit.java b/app/src/main/java/com/sevtinge/vojazento/XposedInit.java index ebea3fb..e26c010 100644 --- a/app/src/main/java/com/sevtinge/vojazento/XposedInit.java +++ b/app/src/main/java/com/sevtinge/vojazento/XposedInit.java @@ -1,15 +1,107 @@ +/* + * This file is part of Vojazento. + + * Vojazento is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + + * Copyright (C) 2024 Sevtinge + */ package com.sevtinge.vojazento; +import static com.sevtinge.vojazento.utils.PackageUtils.*; + +import com.sevtinge.vojazento.utils.XposedLogUtils; + import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC_MethodHook; -import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class XposedInit implements IXposedHookLoadPackage { + boolean IS_CHINA_MAINLAND_BUILD = false; + + int ERROR_COUNTER = 0; + @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { - XposedHelpers.setStaticBooleanField(XposedHelpers.findClassIfExists("miui.os.Build", lpparam.classLoader), "IS_INTERNATIONAL_BUILD", true); + XposedLogUtils.logI(lpparam.packageName, "versionName = " + getPackageVersionName(lpparam) + ", versionCode = " + getPackageVersionCode(lpparam)); + try { + XposedHelpers.setStaticBooleanField(XposedHelpers.findClassIfExists("miui.os.Build", lpparam.classLoader), "IS_INTERNATIONAL_BUILD", !IS_CHINA_MAINLAND_BUILD); //是否为国际构建 + } catch (Throwable t) { + ERROR_COUNTER = ERROR_COUNTER + 1; + XposedLogUtils.logE(lpparam.packageName, "A problem occurred hook \"miui.os.Build.IS_INTERNATIONAL_BUILD\":" + t); + } + try { + XposedHelpers.setStaticBooleanField(XposedHelpers.findClassIfExists("miuix.os.Build", lpparam.classLoader), "IS_INTERNATIONAL_BUILD", !IS_CHINA_MAINLAND_BUILD); //MiuiX是否为国际构建 + } catch (Throwable t) { + ERROR_COUNTER = ERROR_COUNTER + 1; + XposedLogUtils.logE(lpparam.packageName, "A problem occurred hook \"miuix.os.Build.IS_INTERNATIONAL_BUILD\":" + t); + } + try { + XposedHelpers.setStaticBooleanField(XposedHelpers.findClassIfExists("miui.os.Build", lpparam.classLoader), "IS_GLOBAL_BUILD", !IS_CHINA_MAINLAND_BUILD); //是否为全球构建 + } catch (Throwable t) { + ERROR_COUNTER = ERROR_COUNTER + 1; + XposedLogUtils.logE(lpparam.packageName, "A problem occurred hook \"miui.os.Build.IS_GLOBAL_BUILD\":" + t); + } + try { + XposedHelpers.setStaticBooleanField(XposedHelpers.findClassIfExists("miui.os.Build", lpparam.classLoader), "IS_CM_CUSTOMIZATION", IS_CHINA_MAINLAND_BUILD); //是否为中国大陆版 + } catch (Throwable t) { + ERROR_COUNTER = ERROR_COUNTER + 1; + XposedLogUtils.logE(lpparam.packageName, "A problem occurred hook \"miui.os.Build.IS_CM_CUSTOMIZATION\":" + t); + } + try { + XposedHelpers.setStaticBooleanField(XposedHelpers.findClassIfExists("miui.os.Build", lpparam.classLoader), "IS_CM_CUSTOMIZATION_TEST", IS_CHINA_MAINLAND_BUILD); //是否为中国大陆测试版 + } catch (Throwable t) { + ERROR_COUNTER = ERROR_COUNTER + 1; + XposedLogUtils.logE(lpparam.packageName, "A problem occurred hook \"miui.os.Build.IS_CM_CUSTOMIZATION_TEST\":" + t); + } + try { + XposedHelpers.findAndHookMethod(XposedHelpers.findClassIfExists("android.os.SystemProperties", lpparam.classLoader), "get", String.class, String.class, new XC_MethodHook() { //设备名称中是否包含国际版标识 + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + String RETURN = (String) param.args[1]; + if (param.args[0].equals("ro.product.mod_device")) { + if (RETURN.contains("_global") && IS_CHINA_MAINLAND_BUILD) { + param.args[1] = RETURN.replace("_global", ""); + } else if (!RETURN.contains("_global") && !IS_CHINA_MAINLAND_BUILD) { + param.args[1] = param.args[1] + "_global"; + } + } + } + }); + } catch (Throwable t) { + ERROR_COUNTER = ERROR_COUNTER + 1; + XposedLogUtils.logE(lpparam.packageName, "A problem occurred hook \"android.os.SystemProperties.get(String, String)\":" + t); + } + try { + XposedHelpers.findAndHookMethod(XposedHelpers.findClassIfExists("miuix.core.util.SystemProperties", lpparam.classLoader), "get", String.class, String.class, new XC_MethodHook() { //miuix设备名称中是否包含国际版标识 + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + String RETURN = (String) param.args[1]; + if (param.args[0].equals("ro.product.mod_device")) { + if (RETURN.contains("_global") && IS_CHINA_MAINLAND_BUILD) { + param.args[1] = RETURN.replace("_global", ""); + } else if (!RETURN.contains("_global") && !IS_CHINA_MAINLAND_BUILD) { + param.args[1] = param.args[1] + "_global"; + } + } + } + }); + } catch (Throwable t) { + ERROR_COUNTER = ERROR_COUNTER + 1; + XposedLogUtils.logE(lpparam.packageName, "A problem occurred hook \"miuix.core.util.SystemProperties.get(String, String)\":" + t); + } + XposedLogUtils.logI(lpparam.packageName, "Hook over with " + ERROR_COUNTER + " error(s)."); } } diff --git a/app/src/main/java/com/sevtinge/vojazento/utils/PackageUtils.java b/app/src/main/java/com/sevtinge/vojazento/utils/PackageUtils.java new file mode 100644 index 0000000..6032257 --- /dev/null +++ b/app/src/main/java/com/sevtinge/vojazento/utils/PackageUtils.java @@ -0,0 +1,50 @@ +/* + * This file is part of Vojazento. + + * Vojazento is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + + * Copyright (C) 2024 Sevtinge + */ +package com.sevtinge.vojazento.utils; + +import java.io.File; + +import de.robv.android.xposed.XposedHelpers; +import de.robv.android.xposed.callbacks.XC_LoadPackage; + +public class PackageUtils { + public static String getPackageVersionName(XC_LoadPackage.LoadPackageParam lpparam) { + try { + Class parserCls = XposedHelpers.findClass("android.content.pm.PackageParser", lpparam.classLoader); + Object parser = parserCls.newInstance(); + File apkPath = new File(lpparam.appInfo.sourceDir); + Object pkg = XposedHelpers.callMethod(parser, "parsePackage", apkPath, 0); + return (String) XposedHelpers.getObjectField(pkg, "mVersionName"); + } catch (Throwable e) { + return "null"; + } + } + + public static int getPackageVersionCode(XC_LoadPackage.LoadPackageParam lpparam) { + try { + Class parserCls = XposedHelpers.findClass("android.content.pm.PackageParser", lpparam.classLoader); + Object parser = parserCls.newInstance(); + File apkPath = new File(lpparam.appInfo.sourceDir); + Object pkg = XposedHelpers.callMethod(parser, "parsePackage", apkPath, 0); + return XposedHelpers.getIntField(pkg, "mVersionCode"); + } catch (Throwable e) { + return -1; + } + } +} diff --git a/app/src/main/java/com/sevtinge/vojazento/utils/XposedLogUtils.java b/app/src/main/java/com/sevtinge/vojazento/utils/XposedLogUtils.java new file mode 100644 index 0000000..78d2590 --- /dev/null +++ b/app/src/main/java/com/sevtinge/vojazento/utils/XposedLogUtils.java @@ -0,0 +1,109 @@ +/* + * This file is part of Vojazento. + + * Vojazento is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + + * Copyright (C) 2024 Sevtinge + */ +package com.sevtinge.vojazento.utils; + +import de.robv.android.xposed.XposedBridge; + + +public class XposedLogUtils { + public static void logI(String msg) { + XposedBridge.log("[Vojazento][I]: " + msg); + } + + public static void logI(String tagOpkg, String msg) { + XposedBridge.log("[Vojazento][I][" + tagOpkg + "]: " + msg); + } + + public static void logI(String tag, String pkg, String msg) { + XposedBridge.log("[Vojazento][I][" + pkg + "][" + tag + "]: " + msg); + } + + public static void logW(String msg) { + XposedBridge.log("[Vojazento][W]: " + msg); + } + + public static void logW(String tag, String pkg, String msg) { + XposedBridge.log("[Vojazento][W][" + pkg + "][" + tag + "]: " + msg); + } + + public static void logW(String tag, String pkg, Throwable log) { + XposedBridge.log("[Vojazento][W][" + pkg + "][" + tag + "]: " + log); + } + + public static void logW(String tag, String pkg, String msg, Exception exp) { + XposedBridge.log("[Vojazento][W][" + pkg + "][" + tag + "]: " + msg + ", by: " + exp); + } + + public static void logW(String tag, String pkg, String msg, Throwable log) { + XposedBridge.log("[Vojazento][W][" + pkg + "][" + tag + "]: " + msg + ", by: " + log); + } + + public static void logW(String tag, String msg) { + XposedBridge.log("[Vojazento][W][" + tag + "]: " + msg); + } + + public static void logW(String tag, Throwable log) { + XposedBridge.log("[Vojazento][W][" + tag + "]: " + log); + } + + public static void logW(String tag, String msg, Exception exp) { + XposedBridge.log("[Vojazento][W][" + tag + "]: " + msg + ", by: " + exp); + } + + public static void logE(String tagORpkg, String msg) { + XposedBridge.log("[Vojazento][E][" + tagORpkg + "]: " + msg); + } + + public static void logE(String msg) { + XposedBridge.log("[Vojazento][E]: " + msg); + } + + public static void logE(String tag, Throwable log) { + XposedBridge.log("[Vojazento][E][" + tag + "]: " + log); + } + + public static void logE(String tag, String pkg, String msg) { + XposedBridge.log("[Vojazento][E][" + pkg + "][" + tag + "]: " + msg); + } + + public static void logE(String tag, String pkg, Throwable log) { + XposedBridge.log("[Vojazento][E][" + pkg + "][" + tag + "]: " + log); + } + + public static void logE(String tag, String pkg, Exception exp) { + XposedBridge.log("[Vojazento][E][" + pkg + "][" + tag + "]: " + exp); + } + + public static void logE(String tag, String pkg, String msg, Throwable log) { + XposedBridge.log("[Vojazento][E][" + pkg + "][" + tag + "]: " + msg + ", by: " + log); + } + + public static void logE(String tag, String pkg, String msg, Exception exp) { + XposedBridge.log("[Vojazento][E][" + pkg + "][" + tag + "]: " + msg + ", by: " + exp); + } + + public static void logD(String msg) { + XposedBridge.log("[Vojazento][D]: " + msg); + } + + public static void logD(String tag, String pkg, String msg) { + XposedBridge.log("[Vojazento][D][" + pkg + "][" + tag + "]: " + msg); + } + +}