1
0
mirror of https://github.com/areteruhiro/LIME-beta-hiro.git synced 2025-02-05 21:11:39 +09:00

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	app/build.gradle
#	app/src/main/java/io/github/hiro/lime/LimeOptions.java
#	app/src/main/java/io/github/hiro/lime/Main.java
#	app/src/main/java/io/github/hiro/lime/hooks/Constants.java
#	app/src/main/java/io/github/hiro/lime/hooks/ReadChecker.java
#	app/src/main/java/io/github/hiro/lime/hooks/test.java
This commit is contained in:
areteruhiro 2024-11-11 22:51:38 +09:00
commit 91a0b1cbbb
12 changed files with 612 additions and 16 deletions

View File

@ -26,13 +26,13 @@ body:
label: 内容の詳細
placeholder: 具体的に記述してください
validations:
required: true
required: false
- type: textarea
attributes:
label: 再現する手順
placeholder: 可能な限り具体的に記述してください
validations:
required: true
required: false
- type: dropdown
attributes:
label: 有効にしている LIME の設定
@ -65,4 +65,4 @@ body:
label: バージョンの確認
options:
- label: 私は最新版の LIME を使用しており、それに適合するバージョンの LINE アプリを使用しています
required: true
required: false

View File

@ -54,7 +54,6 @@ Macro SAMPLE<br>
## 概要
β版です。自己責任でお願いします。
このアプリで追加されている機能は、いずれPRするものがおおいですが、機能の追加を優先しているため、修正が必要なものが多く、このような形で公開させていただいております。
@ -211,7 +210,7 @@ LI**M**E
> - 着信が入るとクラッシュ
> - コインの購入が不可
> - LINE Pay の一部の機能が使用不可
> - Wear OS (スマートウォッチ)での使用不可
> - △ Wear OS (スマートウォッチ)での連携
1. [**LSPatch**](https://github.com/LSPosed/LSPatch) をインストール
※フォークで開発されている [**NPatch**](https://github.com/HSSkyBoy/NPatch) では不具合が発生する可能性があります。

View File

@ -0,0 +1,63 @@
package io.github.hiro.lime.hooks;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import io.github.hiro.lime.LimeOptions;
import static io.github.hiro.lime.Main.limeOptions;
import android.app.AndroidAppHelper;
import android.app.Application;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.media.AudioManager;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
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;
import io.github.hiro.lime.LimeOptions;
public class CallVolume implements IHook {
@Override
public void hook(LimeOptions limeOptions, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
XposedHelpers.findAndHookMethod(AudioManager.class, "requestAudioFocus",
AudioManager.OnAudioFocusChangeListener.class, int.class, int.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
AudioManager.OnAudioFocusChangeListener listener = (AudioManager.OnAudioFocusChangeListener) param.args[0];
int focusGain = (int) param.args[1];
int mode = (int) param.args[2];
XposedBridge.log("Blocking transient audio focus request.");
param.setResult(AudioManager.AUDIOFOCUS_REQUEST_FAILED);
}
});
XposedHelpers.findAndHookMethod(AudioManager.class, "abandonAudioFocus",
AudioManager.OnAudioFocusChangeListener.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
AudioManager.OnAudioFocusChangeListener listener = (AudioManager.OnAudioFocusChangeListener) param.args[0];
}
});
}
}

View File

@ -0,0 +1,58 @@
package io.github.hiro.lime.hooks;
import android.app.Application;
import android.content.Context;
import java.io.File;
import java.lang.reflect.Field;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import io.github.hiro.lime.LimeOptions;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
public class CrashGuard implements IHook {
@Override
public void hook(LimeOptions limeOptions, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (!limeOptions.CrashGuard.checked) return;
XposedBridge.hookAllMethods(Application.class, "onCreate", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Application appContext = (Application) param.thisObject;
clearCache(appContext);
}
private void clearCache(Context context) {
try {
File cacheDir = context.getCacheDir();
if (cacheDir != null && cacheDir.isDirectory()) {
deleteDir(cacheDir);
XposedBridge.log("Cache cleared successfully.");
}
} catch (Exception e) {
XposedBridge.log("Failed to clear cache: " + e.getMessage());
}
}
private boolean deleteDir(File dir) {
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
if (children != null) {
for (String child : children) {
boolean success = deleteDir(new File(dir, child));
if (!success) {
return false;
}
}
}
}
return dir.delete();
}
});
}
}

View File

@ -16,7 +16,7 @@ public class OutputRequest implements IHook {
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log(new Communication(Communication.Type.REQUEST, param.args[0].toString(), param.args[1]).toString());
XposedBridge.log(new Communication(Communication.Type.REQUEST, param.args[0].toString(), param.args[1]).toString());
}
}
);

View File

@ -2,6 +2,7 @@ package io.github.hiro.lime.hooks;
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;
import io.github.hiro.lime.LimeOptions;
@ -10,6 +11,20 @@ public class PreventMarkAsRead implements IHook {
public void hook(LimeOptions limeOptions, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (!limeOptions.preventMarkAsRead.checked) return;
XposedHelpers.findAndHookMethod(
loadPackageParam.classLoader.loadClass(Constants.MARK_AS_READ_HOOK.className),
Constants.MARK_AS_READ_HOOK.methodName,
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) {
param.setResult(null);
}
}
);
XposedBridge.hookAllMethods(
loadPackageParam.classLoader.loadClass(Constants.REQUEST_HOOK.className),
Constants.REQUEST_HOOK.methodName,
@ -22,5 +37,19 @@ public class PreventMarkAsRead implements IHook {
}
}
);
XposedBridge.hookAllMethods(
loadPackageParam.classLoader.loadClass(Constants.RESPONSE_HOOK.className),
Constants.RESPONSE_HOOK.methodName,
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
if (param.args[0] != null && param.args[0].toString().equals("sendChatChecked")) {
param.setResult(null);
}
}
}
);
}
}

View File

@ -18,29 +18,42 @@ public class PreventUnsendMessage implements IHook {
loadPackageParam.classLoader.loadClass(Constants.RESPONSE_HOOK.className),
Constants.RESPONSE_HOOK.methodName,
new XC_MethodHook() {
@SuppressWarnings("unchecked")
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
if (param.args[0].toString().equals("sync")) {
if (!"sync".equals(param.args[0].toString())) return;
try {
Object wrapper = param.args[1].getClass().getDeclaredField("a").get(param.args[1]);
Field operationResponseField = wrapper.getClass().getSuperclass().getDeclaredField("value_");
operationResponseField.setAccessible(true);
Object operationResponse = operationResponseField.get(wrapper);
if (operationResponse == null) return;
ArrayList<?> operations = (ArrayList<?>) operationResponse.getClass().getDeclaredField("a").get(operationResponse);
if (operations == null) return;
for (Object operation : operations) {
Field typeField = operation.getClass().getDeclaredField("c");
typeField.setAccessible(true);
Object type = typeField.get(operation);
if (type.toString().equals("NOTIFIED_DESTROY_MESSAGE")) {
if ("NOTIFIED_DESTROY_MESSAGE".equals(type.toString())) {
typeField.set(operation, type.getClass().getMethod("valueOf", String.class).invoke(operation, "DUMMY"));
} else if (type.toString().equals("RECEIVE_MESSAGE")) {
} else if ("RECEIVE_MESSAGE".equals(type.toString())) {
Object message = operation.getClass().getDeclaredField("j").get(operation);
if (message == null) continue;
Map<String, String> contentMetadata = (Map<String, String>) message.getClass().getDeclaredField("k").get(message);
contentMetadata.remove("UNSENT");
if (contentMetadata != null) {
contentMetadata.remove("UNSENT");
}
}
}
} catch (Exception e) {
XposedBridge.log("PreventUnsendMessage: Exception occurred - " + e.getMessage());
}
}
}
);
}
}

View File

@ -11,31 +11,46 @@ public class RemoveNotification implements IHook {
@Override
public void hook(LimeOptions limeOptions, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (!limeOptions.RemoveNotification.checked) return;
XposedBridge.hookAllMethods(
loadPackageParam.classLoader.loadClass(Constants.RESPONSE_HOOK.className),
Constants.RESPONSE_HOOK.methodName,
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
if (param.args[0].toString().equals("sync")) {
if (!"sync".equals(param.args[0].toString())) return;
try {
Object wrapper = param.args[1].getClass().getDeclaredField("a").get(param.args[1]);
if (wrapper == null) return;
Field operationResponseField = wrapper.getClass().getSuperclass().getDeclaredField("value_");
operationResponseField.setAccessible(true);
Object operationResponse = operationResponseField.get(wrapper);
if (operationResponse == null) return;
ArrayList<?> operations = (ArrayList<?>) operationResponse.getClass().getDeclaredField("a").get(operationResponse);
if (operations == null) return;
for (int i = operations.size() - 1; i >= 0; i--) {
Object operation = operations.get(i);
Field typeField = operation.getClass().getDeclaredField("c");
typeField.setAccessible(true);
Object type = typeField.get(operation);
if (type.toString().equals("NOTIFIED_UPDATE_PROFILE")) {
if ("NOTIFIED_UPDATE_PROFILE".equals(type.toString())) {
typeField.set(operation, type.getClass().getMethod("valueOf", String.class).invoke(type, "DUMMY"));
}
}
} catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException e) {
XposedBridge.log("RemoveNotification: Error accessing fields - " + e.getMessage());
} catch (Exception e) {
XposedBridge.log("RemoveNotification: Unexpected error - " + e.getMessage());
}
}
}
);
}
}

View File

@ -0,0 +1,419 @@
package io.github.hiro.lime.hooks;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import dalvik.system.DexFile;
import io.github.hiro.lime.LimeOptions;
import java.io.File;
import java.lang.reflect.Method;
import java.util.Enumeration;
public class Test implements IHook {
private boolean isButtonAdded = false; // ボタンが追加されたかどうかを追跡するフラグ
@Override
public void hook(LimeOptions limeOptions, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
String packageName = loadPackageParam.packageName;
XposedBridge.log("Hooking package: " + packageName);
hookOnViewAdded(loadPackageParam.classLoader);
hookAllClassesInPackage(loadPackageParam.classLoader, loadPackageParam);
hookFragmentOnCreateView(loadPackageParam.classLoader);
//hookChatHistoryActivity(loadPackageParam.classLoader); // ChatHistoryActivityのフック
//hookLongClickListeners(loadPackageParam.classLoader); // 長押しリスナーのフック
}
private void hookAllClassesInPackage(ClassLoader classLoader, XC_LoadPackage.LoadPackageParam loadPackageParam) {
try {
String apkPath = loadPackageParam.appInfo.sourceDir;
if (apkPath == null) {
XposedBridge.log("Could not get APK path.");
return;
}
DexFile dexFile = new DexFile(new File(apkPath));
Enumeration<String> classNames = dexFile.entries();
while (classNames.hasMoreElements()) {
String className = classNames.nextElement();
// 指定されたパッケージで始まるクラスのみをフック
// if (className.startsWith("com.linecorp.line") || className.startsWith("jp.naver.line.android")) {
try {
Class<?> clazz = Class.forName(className, false, classLoader);
hookAllMethods(clazz);
} catch (ClassNotFoundException e) {
XposedBridge.log("Class not found: " + className);
} catch (Throwable e) {
XposedBridge.log("Error loading class " + className + ": " + e.getMessage());
}
// }
}
} catch (Throwable e) {
XposedBridge.log("Error while hooking classes: " + e.getMessage());
}
}
private void hookAllClasses(ClassLoader classLoader, XC_LoadPackage.LoadPackageParam loadPackageParam) {
try {
String apkPath = loadPackageParam.appInfo.sourceDir;
if (apkPath == null) {
XposedBridge.log("Could not get APK path.");
return;
}
DexFile dexFile = new DexFile(new File(apkPath));
Enumeration<String> classNames = dexFile.entries();
while (classNames.hasMoreElements()) {
String className = classNames.nextElement();
try {
Class<?> clazz = Class.forName(className, false, classLoader);
hookAllMethods(clazz);
} catch (ClassNotFoundException e) {
XposedBridge.log("Class not found: " + className);
} catch (Throwable e) {
XposedBridge.log("Error loading class " + className + ": " + e.getMessage());
}
}
} catch (Throwable e) {
XposedBridge.log("Error while hooking classes: " + e.getMessage());
}
}
private void hookFragmentOnCreateView(ClassLoader classLoader) {
try {
Class<?> fragmentClass = Class.forName("androidx.fragment.app.Fragment", false, classLoader);
Method onCreateViewMethod = fragmentClass.getDeclaredMethod("onCreateView", LayoutInflater.class, ViewGroup.class, Bundle.class);
XposedBridge.hookMethod(onCreateViewMethod, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("Before calling: " + fragmentClass.getName() + ".onCreateView");
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
ViewGroup rootView = (ViewGroup) param.getResult(); // ルートのViewGroupを取得
Context context = rootView.getContext();
// IDによるビューの取得
int messageContainerId = getIdByName(context, "message_context_menu_content_container");
View messageContainer = rootView.findViewById(messageContainerId);
if (messageContainer != null) {
XposedBridge.log("messageContainer found: " + messageContainer.toString());
} else {
XposedBridge.log("messageContainer not found");
}
// 新しいビューの追加を監視
rootView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
@Override
public void onChildViewAdded(View parent, View child) {
XposedBridge.log("Child view added: " + child.toString());
}
@Override
public void onChildViewRemoved(View parent, View child) {
XposedBridge.log("Child view removed: " + child.toString());
}
});
}
});
} catch (ClassNotFoundException e) {
XposedBridge.log("Class not found: androidx.fragment.app.Fragment");
} catch (NoSuchMethodException e) {
XposedBridge.log("Method not found: onCreateView in Fragment");
} catch (Throwable e) {
XposedBridge.log("Error hooking onCreateView: " + e.getMessage());
}
}
private void hookOnViewAdded(ClassLoader classLoader) {
try {
Class<?> constraintLayoutClass = Class.forName("androidx.constraintlayout.widget.ConstraintLayout", false, classLoader);
Method onViewAddedMethod = constraintLayoutClass.getDeclaredMethod("onViewAdded", View.class);
XposedBridge.hookMethod(onViewAddedMethod, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
View addedView = (View) param.args[0];
XposedBridge.log(addedView.toString());
}
private boolean isButtonAdded = false; // ボタンが追加されたかどうかを追跡するフラグ
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
View addedView = (View) param.args[0];
XposedBridge.log("Called: " + constraintLayoutClass.getName() + ".onViewAdded");
// 追加されたビューの ID を取得
int addedViewId = addedView.getId();
// 親ビューを取得
ViewGroup parent = (ViewGroup) param.thisObject;
// 追加されたビューのリソース名を取得
String resourceName = parent.getContext().getResources().getResourceEntryName(addedViewId);
// リソース名が chat_ui_message_context_menu_row_container の場合
if ("chat_ui_message_context_menu_row_container".equals(resourceName) && !isButtonAdded) {
// ボタンを作成
}
}
private void createAndAddButton(ConstraintLayout parent, View referenceView) {
// ボタンを作成
Button newButton = new Button(parent.getContext());
newButton.setText("新しいボタン");
// ボタンの ID を設定
newButton.setId(View.generateViewId());
// ボタンのレイアウトパラメータを設定
ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams(
ConstraintLayout.LayoutParams.WRAP_CONTENT,
ConstraintLayout.LayoutParams.WRAP_CONTENT
);
// ボタンを親ビューに追加
parent.addView(newButton, params);
// 制約を設定
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(parent);
// ボタンに対する制約を設定
constraintSet.connect(newButton.getId(), ConstraintSet.TOP, referenceView.getId(), ConstraintSet.BOTTOM); // 上に参照ビューを設定
constraintSet.connect(newButton.getId(), ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START); // 左端に設定
constraintSet.connect(newButton.getId(), ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END); // 右端に設定
constraintSet.setHorizontalBias(newButton.getId(), 0.5f); // 中央に配置
// 制約を適用
constraintSet.applyTo(parent);
}
private void createAndAddButton(ViewGroup parent) {
// ボタンを作成
Button newButton = new Button(parent.getContext());
newButton.setText("新しいボタン"); // ボタンのテキストを設定
// ボタンのレイアウトパラメータを設定
ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams(
ConstraintLayout.LayoutParams.WRAP_CONTENT,
ConstraintLayout.LayoutParams.WRAP_CONTENT
);
// 親の一番右に追加するために適切な位置を設定
params.startToEnd = parent.getChildAt(parent.getChildCount() - 1).getId(); // 最後のビューの右側に配置
params.topToTop = ConstraintLayout.LayoutParams.PARENT_ID; // 上部を親の上部に固定
newButton.setLayoutParams(params);
// 親ビューにボタンを追加
parent.addView(newButton);
}
});
} catch (ClassNotFoundException e) {
XposedBridge.log("Class not found: androidx.constraintlayout.widget.ConstraintLayout");
} catch (NoSuchMethodException e) {
XposedBridge.log("Method not found: onViewAdded in ConstraintLayout");
} catch (Throwable e) {
XposedBridge.log("Error hooking onViewAdded: " + e.getMessage());
}
}
private int getIdByName(Context context, String resourceName) {
return context.getResources().getIdentifier(resourceName, "id", context.getPackageName());
}
private void hookAllMethods(Class<?> clazz) {
// クラス内のすべてのメソッドを取得
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
// 抽象メソッドをスキップ
if (java.lang.reflect.Modifier.isAbstract(method.getModifiers())) {
continue;
}
// 対象メソッドが特定のビュー関連メソッドであるか確認
if (!"invokeSuspend".equals(method.getName()) &&
!"setOnLongClickListener".equals(method.getName()) &&
!"setOnTouchListener".equals(method.getName()) &&
!"setVisibility".equals(method.getName()) &&
!"setAlpha".equals(method.getName()) &&
!"setEnabled".equals(method.getName()) &&
!"setFocusable".equals(method.getName()) &&
!"setOnClickListener".equals(method.getName()) &&
!"setBackgroundColor".equals(method.getName()) &&
!"setPadding".equals(method.getName()) &&
!"setLayoutParams".equals(method.getName()) &&
!"requestLayout".equals(method.getName()) &&
!"invalidate".equals(method.getName()) &&
!"setText".equals(method.getName()) && // 新しく追加されたメソッド
!"setTextColor".equals(method.getName()) && // 新しく追加されたメソッド
!"setHint".equals(method.getName()) && // 新しく追加されたメソッド
!"setHintTextColor".equals(method.getName()) && // 新しく追加されたメソッド
!"onStart".equals(method.getName()) &&
!"setCompoundDrawables".equals(method.getName()) &&
!"getActivity".equals(method.getName()) && // PendingIntent method
!"onViewAdded".equals(method.getName()) && // PendingIntent method
!"setState".equals(method.getName())) { // PendingIntent method
continue;
}
method.setAccessible(true); // アクセス可能に設定
try {
// メソッドをフックする
XposedBridge.hookMethod(method, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
StringBuilder argsString = new StringBuilder("Args: ");
// 引数が複数の場合すべてを追加
for (int i = 0; i < param.args.length; i++) {
Object arg = param.args[i];
argsString.append("Arg[").append(i).append("]: ")
.append(arg != null ? arg.toString() : "null")
.append(", ");
}
// メソッドに応じたログ出力
if ("invokeSuspend".equals(method.getName())) {
XposedBridge.log("Before calling invokeSuspend in class: " + clazz.getName() + " with args: " + argsString);
} else if ("setVisibility".equals(method.getName())) {
XposedBridge.log("Before calling setVisibility in class: " + clazz.getName() + " with args: " + argsString);
} else if ("setAlpha".equals(method.getName())) {
XposedBridge.log("Before calling setAlpha in class: " + clazz.getName() + " with args: " + argsString);
} else if ("setEnabled".equals(method.getName())) {
XposedBridge.log("Before calling setEnabled in class: " + clazz.getName() + " with args: " + argsString);
} else if ("setFocusable".equals(method.getName())) {
XposedBridge.log("Before calling setFocusable in class: " + clazz.getName() + " with args: " + argsString);
} else if ("setOnClickListener".equals(method.getName())) {
XposedBridge.log("Before calling setOnClickListener in class: " + clazz.getName() + " with args: " + argsString);
} else if ("setBackgroundColor".equals(method.getName())) {
XposedBridge.log("Before calling setBackgroundColor in class: " + clazz.getName() + " with args: " + argsString);
} else if ("setPadding".equals(method.getName())) {
XposedBridge.log("Before calling setPadding in class: " + clazz.getName() + " with args: " + argsString);
} else if ("setLayoutParams".equals(method.getName())) {
XposedBridge.log("Before calling setLayoutParams in class: " + clazz.getName() + " with args: " + argsString);
} else if ("requestLayout".equals(method.getName())) {
XposedBridge.log("Before calling requestLayout in class: " + clazz.getName() + " with args: " + argsString);
} else if ("invalidate".equals(method.getName())) {
XposedBridge.log("Before calling invalidate in class: " + clazz.getName() + " with args: " + argsString);
} else if ("setText".equals(method.getName())) {
XposedBridge.log("Before calling setText in class: " + clazz.getName() + " with args: " + argsString);
} else if ("setTextColor".equals(method.getName())) {
XposedBridge.log("Before calling setTextColor in class: " + clazz.getName() + " with args: " + argsString);
} else if ("setHint".equals(method.getName())) {
XposedBridge.log("Before calling setHint in class: " + clazz.getName() + " with args: " + argsString);
} else if ("setHintTextColor".equals(method.getName())) {
XposedBridge.log("Before calling setHintTextColor in class: " + clazz.getName() + " with args: " + argsString);
} else if ("setCompoundDrawables".equals(method.getName())) {
XposedBridge.log("Before calling setCompoundDrawables in class: " + clazz.getName() + " with args: " + argsString);
} else if ("onStart".equals(method.getName())) {
XposedBridge.log("Before calling onStart in class: " + clazz.getName() + " with args: " + argsString);
} else if ("getActivity".equals(method.getName())) {
XposedBridge.log("Before calling getActivity in class: " + clazz.getName() + " with args: " + argsString);
} else if ("onViewAdded".equals(method.getName())) {
XposedBridge.log("Before calling onViewAdded in class: " + clazz.getName() + " with args: " + argsString);
} else if ("getService".equals(method.getName())) {
XposedBridge.log("Before calling getService in class: " + clazz.getName() + " with args: " + argsString);
} else if ("setState".equals(method.getName())) {
XposedBridge.log("Before setState invoke in class: " + clazz.getName() + " with args: " + argsString);
}
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Object result = param.getResult();
if ("invokeSuspend".equals(method.getName())) {
XposedBridge.log("Before calling invokeSuspend in class: " + clazz.getName() + (result != null ? result.toString() : "null"));
} else if ("setVisibility".equals(method.getName())) {
XposedBridge.log("After calling setVisibility in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("setAlpha".equals(method.getName())) {
XposedBridge.log("After calling setAlpha in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("setEnabled".equals(method.getName())) {
XposedBridge.log("After calling setEnabled in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("setFocusable".equals(method.getName())) {
XposedBridge.log("After calling setFocusable in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("setOnClickListener".equals(method.getName())) {
XposedBridge.log("After calling setOnClickListener in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("setBackgroundColor".equals(method.getName())) {
XposedBridge.log("After calling setBackgroundColor in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("setPadding".equals(method.getName())) {
XposedBridge.log("After calling setPadding in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("setLayoutParams".equals(method.getName())) {
XposedBridge.log("After calling setLayoutParams in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("requestLayout".equals(method.getName())) {
XposedBridge.log("After calling requestLayout in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("invalidate".equals(method.getName())) {
XposedBridge.log("After calling invalidate in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("setText".equals(method.getName())) {
XposedBridge.log("After calling setText in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("setTextColor".equals(method.getName())) {
XposedBridge.log("After calling setTextColor in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("setHint".equals(method.getName())) {
XposedBridge.log("After calling setHint in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("setHintTextColor".equals(method.getName())) {
XposedBridge.log("After calling setHintTextColor in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("setCompoundDrawables".equals(method.getName())) {
XposedBridge.log("After calling setCompoundDrawables in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("onStart".equals(method.getName())) {
XposedBridge.log("Before calling onStart in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("getActivity".equals(method.getName())) {
XposedBridge.log("After calling getActivity in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("onViewAdded".equals(method.getName())) {
XposedBridge.log("After calling onViewAdded in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("getService".equals(method.getName())) {
XposedBridge.log("After calling getService in class: " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
} else if ("setState".equals(method.getName())) {
XposedBridge.log("setState " + clazz.getName() + " with result: " + (result != null ? result.toString() : "null"));
}
}
});
} catch (IllegalArgumentException e) {
XposedBridge.log("Error hooking method " + method.getName() + " in class " + clazz.getName() + " : " + e.getMessage());
} catch (Throwable e) {
XposedBridge.log("Unexpected error hooking method " + method.getName() + " in class " + clazz.getName() + " : " + Log.getStackTraceString(e));
}
}
}
private boolean isViewCreationMethod(Method method) {
// View作成に関連するメソッドを検出
String methodName = method.getName().toLowerCase();
return methodName.contains("inflate") || methodName.contains("new") || methodName.contains("create");
}
}

View File

@ -45,8 +45,6 @@ public class UnsentRec implements IHook {
public static final String Main_file = "UNSENT_REC.txt";
public static final String Main_backup = "BackUpFile.txt";
SQLiteDatabase db1 = null;
SQLiteDatabase db2 = null;
@Override
public void hook(LimeOptions limeOptions, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {

View File

@ -95,5 +95,6 @@
<string name="ReadChecker">送信したメッセージの既読者の確認</string>
<string name="switch_KeepUnreadLSpatch">LsPatch用「未読のまま閲覧」スイッチを表示</string>
<string name="SleepCall">連続で通話がかかってこないとかからないように</string>
<string name="CrashGuard">随時キャッシュを削除してクラッシュを予防</string>
</resources>

View File

@ -96,4 +96,5 @@
<string name="switch_KeepUnreadLSpatch">LsPatch用「未読のまま閲覧」スイッチを表示</string>
<string name="AutomaticBackup">定期的にバックアップ\n</string>
<string name="SleepCall">連続で通話がかかってこないとかからないように</string>
<string name="CrashGuard">随時キャッシュを削除してクラッシュを予防</string>
</resources>