From 5e8e2512229906d2a2e04204fdfd0d47768e4ec2 Mon Sep 17 00:00:00 2001 From: areteruhiro Date: Tue, 4 Feb 2025 22:02:14 +0900 Subject: [PATCH] =?UTF-8?q?=E7=94=BB=E5=83=8F=E3=81=AE=E5=A0=B4=E5=90=88?= =?UTF-8?q?=E3=81=AE=E3=81=BF=E3=83=97=E3=83=AD=E3=83=95=E3=82=A3=E3=83=BC?= =?UTF-8?q?=E3=83=AB=E3=82=92=E6=9B=B4=E6=96=B0=E3=81=99=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 2 +- .../hiro/lime/hooks/PhotoAddNotification.java | 54 +++--- .../lime/hooks/RemoveProfileNotification.java | 162 ++++++++++++++++-- 3 files changed, 179 insertions(+), 39 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d7b2a12..5b6a141 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,7 +10,7 @@ android { minSdk 28 targetSdk 35 versionCode 116160 - versionName "1.16.17.2既読者確認機能β" + versionName "1.16.17.2asss" multiDexEnabled false proguardFiles += 'proguard-rules.pro' buildConfigField 'String', 'HOOK_TARGET_VERSION', '"141910383"' diff --git a/app/src/main/java/io/github/hiro/lime/hooks/PhotoAddNotification.java b/app/src/main/java/io/github/hiro/lime/hooks/PhotoAddNotification.java index d8108db..c6ebff4 100644 --- a/app/src/main/java/io/github/hiro/lime/hooks/PhotoAddNotification.java +++ b/app/src/main/java/io/github/hiro/lime/hooks/PhotoAddNotification.java @@ -38,6 +38,7 @@ public class PhotoAddNotification implements IHook { private static final int MAX_RETRIES = 20; private static final long RETRY_DELAY = 1000; + @Override public void hook(LimeOptions limeOptions, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable { if (!limeOptions.PhotoAddNotification.checked) return; @@ -96,12 +97,14 @@ public class PhotoAddNotification implements IHook { String tag = (String) param.args[0]; int ids = (int) param.args[1]; if (Objects.equals(notification.category, "call")) { + // logAllNotificationDetails(tag, ids, notification, notification.tickerText != null ? notification.tickerText.toString() : null); + + return; } if (limeOptions.GroupNotification.checked) { handleNotificationHook(context, db1, db2, param, notification, true); - } - else { + } else { if (param.args[0] == null) { param.setResult(null); return; @@ -112,6 +115,7 @@ public class PhotoAddNotification implements IHook { }); } + private static boolean isHandlingNotification = false; private static final Set processedNotifications = new HashSet<>(); @@ -124,7 +128,6 @@ public class PhotoAddNotification implements IHook { isHandlingNotification = true; - try { Notification originalNotification = hasTag ? (Notification) param.args[2] : (Notification) param.args[1]; String title = getNotificationTitle(originalNotification); @@ -235,7 +238,6 @@ public class PhotoAddNotification implements IHook { param.setResult(null); - int randomNotificationId = (int) System.currentTimeMillis(); NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); if (notificationManager != null) { @@ -253,6 +255,7 @@ public class PhotoAddNotification implements IHook { isHandlingNotification = false; } } + private Bitmap loadBitmapFromFile(File file) { if (!file.exists()) { return null; @@ -288,6 +291,7 @@ public class PhotoAddNotification implements IHook { return null; } } + private Notification createNotificationWithImageFromBitmap(Context context, Notification original, Bitmap bitmap, String originalText) { Notification.BigPictureStyle bigPictureStyle = new Notification.BigPictureStyle() .bigPicture(bitmap) // メインの画像 @@ -379,6 +383,7 @@ public class PhotoAddNotification implements IHook { cursor.close(); return result; } + private String getNotificationTitle(Notification notification) { if (notification.extras != null) { return notification.extras.getString(Notification.EXTRA_TITLE); @@ -392,47 +397,46 @@ public class PhotoAddNotification implements IHook { } return null; } -} -/* private void logAllNotificationDetails(String method, int ids, Notification notification, String tag) { - XposedBridge.log(method + " called. ID: " + ids + (tag != null ? ", Tag: " + tag : "")); - XposedBridge.log("Notification Icon: " + notification.icon); - XposedBridge.log("Notification When: " + notification.when); - XposedBridge.log("Notification Flags: " + notification.flags); - XposedBridge.log("Notification Priority: " + notification.priority); - XposedBridge.log("Notification Category: " + notification.category); + XposedBridge.log(method + " called. ID: " + ids + (tag != null ? ", Tag: " + tag : "")); + XposedBridge.log("Notification Icon: " + notification.icon); + XposedBridge.log("Notification When: " + notification.when); + XposedBridge.log("Notification Flags: " + notification.flags); + XposedBridge.log("Notification Priority: " + notification.priority); + XposedBridge.log("Notification Category: " + notification.category); if (notification.extras != null) { Bundle extras = notification.extras; - XposedBridge.log("Notification Extras:"); + XposedBridge.log("Notification Extras:"); for (String key : extras.keySet()) { Object value = extras.get(key); - XposedBridge.log(" " + key + ": " + (value != null ? value.toString() : "null")); + XposedBridge.log(" " + key + ": " + (value != null ? value.toString() : "null")); } } else { - XposedBridge.log("Notification has no extras."); + XposedBridge.log("Notification has no extras."); } if (notification.actions != null) { - XposedBridge.log("Notification Actions:"); + XposedBridge.log("Notification Actions:"); for (int i = 0; i < notification.actions.length; i++) { Notification.Action action = notification.actions[i]; - XposedBridge.log(" Action " + i + ": " + + XposedBridge.log(" Action " + i + ": " + "Title=" + action.title + ", Intent=" + action.actionIntent); } } else { - //XposedBridge.log("No actions found."); + //XposedBridge.log("No actions found."); } // その他の情報 - XposedBridge.log("Notification Visibility: " + notification.visibility); - XposedBridge.log("Notification Color: " + notification.color); - XposedBridge.log("Notification Group: " + notification.getGroup()); - XposedBridge.log("Notification SortKey: " + notification.getSortKey()); - XposedBridge.log("Notification Sound: " + notification.sound); - XposedBridge.log("Notification Vibrate: " + (notification.vibrate != null ? "Yes" : "No")); + XposedBridge.log("Notification Visibility: " + notification.visibility); + XposedBridge.log("Notification Color: " + notification.color); + XposedBridge.log("Notification Group: " + notification.getGroup()); + XposedBridge.log("Notification SortKey: " + notification.getSortKey()); + XposedBridge.log("Notification Sound: " + notification.sound); + XposedBridge.log("Notification Vibrate: " + (notification.vibrate != null ? "Yes" : "No")); } -*/ +} + diff --git a/app/src/main/java/io/github/hiro/lime/hooks/RemoveProfileNotification.java b/app/src/main/java/io/github/hiro/lime/hooks/RemoveProfileNotification.java index 398fcea..66d7eda 100644 --- a/app/src/main/java/io/github/hiro/lime/hooks/RemoveProfileNotification.java +++ b/app/src/main/java/io/github/hiro/lime/hooks/RemoveProfileNotification.java @@ -1,14 +1,27 @@ package io.github.hiro.lime.hooks; +import static io.github.hiro.lime.Main.limeOptions; + import android.app.Application; +import android.app.Notification; import android.content.Context; import android.content.pm.PackageManager; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; +import android.os.Bundle; +import android.os.Environment; +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.lang.reflect.Field; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; @@ -20,7 +33,31 @@ public class RemoveProfileNotification implements IHook { @Override public void hook(LimeOptions limeOptions, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable { if (!limeOptions.RemoveNotification.checked) return; - + Class notificationManagerClass = XposedHelpers.findClass( + "android.app.NotificationManager", loadPackageParam.classLoader + ); +// XposedHelpers.findAndHookMethod(notificationManagerClass, "notify", +// String.class, int.class, Notification.class, new XC_MethodHook() { +// @Override +// protected void beforeHookedMethod(MethodHookParam param) throws Throwable { +// +// Notification notification = (Notification) param.args[2]; +// String tag = (String) param.args[0]; +// int ids = (int) param.args[1]; +// // logAllNotificationDetails(tag, ids, notification, notification.tickerText != null ? notification.tickerText.toString() : null); +// +// if (Objects.equals(notification.category, "call")) { +// if (notification.extras != null && "UNKNOWN".equals(notification.extras.getString("android.title"))) { +// +// +// } +// +// +// return; +// +// } +// } +// }); XposedBridge.hookAllMethods(Application.class, "onCreate", new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { @@ -73,6 +110,7 @@ public class RemoveProfileNotification implements IHook { String type = null; String param1 = null; + String param2 = null; String[] parts = operation.split(","); for (String part : parts) { part = part.trim(); @@ -80,21 +118,14 @@ public class RemoveProfileNotification implements IHook { type = part.substring("type:".length()).trim(); } else if (part.startsWith("param1:")) { param1 = part.substring("param1:".length()).trim(); + } else if (part.startsWith("param2:")) { + param2 = part.substring("param2:".length()).trim(); } } if ("NOTIFIED_UPDATE_PROFILE".equals(type)) { - XposedBridge.log("取得したparam1: " + param1); + XposedBridge.log(paramValue); Cursor cursor = db2.rawQuery("SELECT mid, contact_type, profile_updated_time_millis, profile_name FROM contacts WHERE mid=?", new String[]{param1}); - if (cursor != null) { - try { - if (cursor.moveToFirst()) { - String mid = cursor.getString(cursor.getColumnIndex("mid")); - int rowsDeleted = db2.delete("contacts", "mid=?", new String[]{mid}); - } - } finally { - cursor.close(); - } - } + Object operationObject = param.args[1].getClass().getDeclaredField("a").get(param.args[1]); if (operationObject != null) { Field operationResponseField = operationObject.getClass().getSuperclass().getDeclaredField("value_"); @@ -102,6 +133,8 @@ public class RemoveProfileNotification implements IHook { Object operationResponse = operationResponseField.get(operationObject); if (operationResponse != null) { ArrayList operationList = (ArrayList) operationResponse.getClass().getDeclaredField("a").get(operationResponse); + Map profileMap = new HashMap<>(); // midとprofile_nameのマップ + for (Object op : operationList) { Field typeField = op.getClass().getDeclaredField("c"); typeField.setAccessible(true); @@ -109,16 +142,119 @@ public class RemoveProfileNotification implements IHook { if ("NOTIFIED_UPDATE_PROFILE".equals(typeFieldValue.toString())) { typeField.set(op, typeFieldValue.getClass().getMethod("valueOf", String.class).invoke(typeFieldValue, "DUMMY")); } + + if ("8".contains(param2)) { + if (cursor != null) { + try { + if (cursor.moveToFirst()) { + String mid = cursor.getString(cursor.getColumnIndex("mid")); + String profileName = cursor.getString(cursor.getColumnIndex("profile_name")); + + // midとprofile_nameをマップに追加 + profileMap.put(mid, profileName); + saveProfilesToFile(profileMap); + // データを削除 + int rowsDeleted = db2.delete("contacts", "mid=?", new String[]{mid}); + } + } finally { + cursor.close(); + } + } + } } + } } - } + + } } } catch (Exception e) { XposedBridge.log("RemoveProfileNotification: 予期しないエラー - " + e.getMessage()); } } }); + + + } + + private void saveProfilesToFile(Map profileMap) { + File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "LimeBackup"); + if (!dir.exists()) { + dir.mkdirs(); + } + + File file = new File(dir, "profiles.txt"); + Map existingProfiles = new HashMap<>(); + + if (file.exists()) { + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line; + while ((line = reader.readLine()) != null) { + String[] parts = line.split(","); + if (parts.length == 2) { + existingProfiles.put(parts[0], parts[1]); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + for (Map.Entry entry : profileMap.entrySet()) { + String mid = entry.getKey(); + String profileName = entry.getValue(); + existingProfiles.put(mid, profileName); + } + + try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { + for (Map.Entry entry : existingProfiles.entrySet()) { + String mid = entry.getKey(); + String profileName = entry.getValue(); + writer.write(mid + "," + profileName); + writer.newLine(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } +// private void logAllNotificationDetails(String method, int ids, Notification notification, String tag) { +// XposedBridge.log(method + " called. ID: " + ids + (tag != null ? ", Tag: " + tag : "")); +// XposedBridge.log("Notification Icon: " + notification.icon); +// XposedBridge.log("Notification When: " + notification.when); +// XposedBridge.log("Notification Flags: " + notification.flags); +// XposedBridge.log("Notification Priority: " + notification.priority); +// XposedBridge.log("Notification Category: " + notification.category); +// if (notification.extras != null) { +// Bundle extras = notification.extras; +// XposedBridge.log("Notification Extras:"); +// for (String key : extras.keySet()) { +// Object value = extras.get(key); +// XposedBridge.log(" " + key + ": " + (value != null ? value.toString() : "null")); +// } +// } else { +// XposedBridge.log("Notification has no extras."); +// } +// +// if (notification.actions != null) { +// XposedBridge.log("Notification Actions:"); +// for (int i = 0; i < notification.actions.length; i++) { +// Notification.Action action = notification.actions[i]; +// XposedBridge.log(" Action " + i + ": " + +// "Title=" + action.title + +// ", Intent=" + action.actionIntent); +// } +// } else { +// //XposedBridge.log("No actions found."); +// } +// +// // その他の情報 +// XposedBridge.log("Notification Visibility: " + notification.visibility); +// XposedBridge.log("Notification Color: " + notification.color); +// XposedBridge.log("Notification Group: " + notification.getGroup()); +// XposedBridge.log("Notification SortKey: " + notification.getSortKey()); +// XposedBridge.log("Notification Sound: " + notification.sound); +// XposedBridge.log("Notification Vibrate: " + (notification.vibrate != null ? "Yes" : "No")); +// } }