diff --git a/app/build.gradle b/app/build.gradle index ade1356..e205e97 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,7 +10,7 @@ android { minSdk 28 targetSdk 35 versionCode 15 - versionName "1.14.7.8" + versionName "1.14.7.7.9.betaa" multiDexEnabled false proguardFiles += 'proguard-rules.pro' buildConfigField 'String', 'HOOK_TARGET_VERSION', '"141910383"' diff --git a/app/src/main/java/io/github/hiro/lime/hooks/EmbedOptions.java b/app/src/main/java/io/github/hiro/lime/hooks/EmbedOptions.java index 0a0b49d..7292355 100644 --- a/app/src/main/java/io/github/hiro/lime/hooks/EmbedOptions.java +++ b/app/src/main/java/io/github/hiro/lime/hooks/EmbedOptions.java @@ -464,8 +464,9 @@ public class EmbedOptions implements IHook { int keep_unread_verticalMarginDp = 15; float read_button_horizontalMarginFactor = 0.6f; int read_button_verticalMarginDp = 60; - float read_checker_horizontalMarginFactor = 0.5f; // Read_checker ボタンの初期値 - int read_checker_verticalMarginDp = 60; // Read_checker ボタンの初期値 + float read_checker_horizontalMarginFactor = 0.5f; + int read_checker_verticalMarginDp = 60; + float keep_unread_size = 60.0f; // 新しい項目の初期値 // ファイルの内容を読み込む if (file.exists()) { @@ -474,18 +475,28 @@ public class EmbedOptions implements IHook { while ((line = reader.readLine()) != null) { String[] parts = line.split("=", 2); if (parts.length == 2) { - if (parts[0].trim().equals("keep_unread_horizontalMarginFactor")) { - keep_unread_horizontalMarginFactor = Float.parseFloat(parts[1].trim()); - } else if (parts[0].trim().equals("keep_unread_verticalMarginDp")) { - keep_unread_verticalMarginDp = Integer.parseInt(parts[1].trim()); - } else if (parts[0].trim().equals("Read_buttom_Chat_horizontalMarginFactor")) { - read_button_horizontalMarginFactor = Float.parseFloat(parts[1].trim()); - } else if (parts[0].trim().equals("Read_buttom_Chat_verticalMarginDp")) { - read_button_verticalMarginDp = Integer.parseInt(parts[1].trim()); - } else if (parts[0].trim().equals("Read_checker_horizontalMarginFactor")) { - read_checker_horizontalMarginFactor = Float.parseFloat(parts[1].trim()); - } else if (parts[0].trim().equals("Read_checker_verticalMarginDp")) { - read_checker_verticalMarginDp = Integer.parseInt(parts[1].trim()); + switch (parts[0].trim()) { + case "keep_unread_horizontalMarginFactor": + keep_unread_horizontalMarginFactor = Float.parseFloat(parts[1].trim()); + break; + case "keep_unread_verticalMarginDp": + keep_unread_verticalMarginDp = Integer.parseInt(parts[1].trim()); + break; + case "Read_buttom_Chat_horizontalMarginFactor": + read_button_horizontalMarginFactor = Float.parseFloat(parts[1].trim()); + break; + case "Read_buttom_Chat_verticalMarginDp": + read_button_verticalMarginDp = Integer.parseInt(parts[1].trim()); + break; + case "Read_checker_horizontalMarginFactor": + read_checker_horizontalMarginFactor = Float.parseFloat(parts[1].trim()); + break; + case "Read_checker_verticalMarginDp": + read_checker_verticalMarginDp = Integer.parseInt(parts[1].trim()); + break; + case "keep_unread_size": + keep_unread_size = Float.parseFloat(parts[1].trim()); + break; } } } @@ -499,19 +510,31 @@ public class EmbedOptions implements IHook { "Read_buttom_Chat_horizontalMarginFactor=0.6\n" + "Read_buttom_Chat_verticalMarginDp=60\n" + "Read_checker_horizontalMarginFactor=0.5\n" + - "Read_checker_verticalMarginDp=60"; - + "Read_checker_verticalMarginDp=60\n" + + "keep_unread_size=60"; writer.write(defaultSettings); } catch (IOException ignored) { return; } } - // 横マージンの入力フィールド + // レイアウト設定 LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); layoutParams.setMargins(16, 16, 16, 16); + + + // "keep_unread_size" 入力フィールド + TextView keepUnreadSizeLabel = new TextView(context); + keepUnreadSizeLabel.setText(moduleContext.getResources().getString(R.string.keep_unread_size)); + keepUnreadSizeLabel.setLayoutParams(layoutParams); + + final EditText keepUnreadSizeInput = new EditText(context); + keepUnreadSizeInput.setText(String.valueOf(keep_unread_size)); + keepUnreadSizeInput.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL); + keepUnreadSizeInput.setLayoutParams(layoutParams); + TextView horizontalLabel = new TextView(context); horizontalLabel.setText(moduleContext.getResources().getString(R.string.keep_unread_horizontalMarginFactor)); horizontalLabel.setLayoutParams(layoutParams); @@ -577,6 +600,8 @@ public class EmbedOptions implements IHook { saveButton.setLayoutParams(layoutParams); saveButton.setOnClickListener(v -> { try { + // 追加: keep_unread_size の取得 + int newKeepUnreadSize = Integer.parseInt(keepUnreadSizeInput.getText().toString().trim()); float newKeepUnreadHorizontalMarginFactor = Float.parseFloat(horizontalInput.getText().toString().trim()); int newKeepUnreadVerticalMarginDp = Integer.parseInt(verticalInput.getText().toString().trim()); float newReadButtonHorizontalMarginFactor = Float.parseFloat(readButtonHorizontalInput.getText().toString().trim()); @@ -586,6 +611,8 @@ public class EmbedOptions implements IHook { // ファイルに保存 try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { + // 追加: keep_unread_size の書き込み + writer.write("keep_unread_size=" + newKeepUnreadSize + "\n"); writer.write("keep_unread_horizontalMarginFactor=" + newKeepUnreadHorizontalMarginFactor + "\n"); writer.write("keep_unread_verticalMarginDp=" + newKeepUnreadVerticalMarginDp + "\n"); writer.write("Read_buttom_Chat_horizontalMarginFactor=" + newReadButtonHorizontalMarginFactor + "\n"); @@ -604,9 +631,11 @@ public class EmbedOptions implements IHook { context.startActivity(new Intent().setClassName(Constants.PACKAGE_NAME, "jp.naver.line.android.activity.SplashActivity")); }); - // レイアウトを構築 +// レイアウトを構築 LinearLayout layout = new LinearLayout(context); layout.setOrientation(LinearLayout.VERTICAL); + layout.addView(keepUnreadSizeLabel); + layout.addView(keepUnreadSizeInput); layout.addView(horizontalLabel); layout.addView(horizontalInput); layout.addView(verticalLabel); @@ -621,10 +650,14 @@ public class EmbedOptions implements IHook { layout.addView(readCheckerVerticalInput); layout.addView(saveButton); - // ダイアログを作成 +// ScrollView を作成 + ScrollView scrollView = new ScrollView(context); + scrollView.addView(layout); + +// ダイアログを作成 AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(moduleContext.getResources().getString(R.string.edit_margin_settings)); - builder.setView(layout); + builder.setView(scrollView); // ScrollView をダイアログのビューとして設定 builder.setNegativeButton(moduleContext.getResources().getString(R.string.cancel), null); builder.show(); } diff --git a/app/src/main/java/io/github/hiro/lime/hooks/KeepUnread.java b/app/src/main/java/io/github/hiro/lime/hooks/KeepUnread.java index b32ff5e..17d1b8c 100644 --- a/app/src/main/java/io/github/hiro/lime/hooks/KeepUnread.java +++ b/app/src/main/java/io/github/hiro/lime/hooks/KeepUnread.java @@ -31,7 +31,9 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; import java.util.HashMap; import java.util.Map; @@ -173,20 +175,48 @@ public class KeepUnread implements IHook { } private void updateSwitchImage(ImageView imageView, boolean isOn, Context moduleContext) { + String imageName = isOn ? "switch_on.png" : "switch_off.png"; // 拡張子を追加 + File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "LimeBackup"); + // ディレクトリが存在しない場合は作成 + if (!dir.exists()) { + dir.mkdirs(); + } - String imageName = isOn ? "unread" : "read"; - int imageResource = moduleContext.getResources().getIdentifier(imageName, "drawable", "io.github.hiro.lime"); + File imageFile = new File(dir, imageName); + // 画像ファイルが存在しない場合はリソースからコピー + if (!imageFile.exists()) { + try (InputStream in = moduleContext.getResources().openRawResource( + moduleContext.getResources().getIdentifier(imageName.replace(".png", ""), "drawable", "io.github.hiro.lime")); + OutputStream out = new FileOutputStream(imageFile)) { + byte[] buffer = new byte[1024]; + int length; + while ((length = in.read(buffer)) > 0) { + out.write(buffer, 0, length); + } + } catch (IOException e) { + e.printStackTrace(); + } + } - if (imageResource != 0) { - Drawable drawable = moduleContext.getResources().getDrawable(imageResource, null); + // コピーした画像をImageViewに設定 + if (imageFile.exists()) { + Drawable drawable = Drawable.createFromPath(imageFile.getAbsolutePath()); if (drawable != null) { - drawable = scaleDrawable(drawable, 86, 86); + Map settings = readSettingsFromExternalFile(moduleContext); + float sizeInDp = Float.parseFloat(settings.getOrDefault("keep_unread_size", "60")); // 既定値 38dp + int sizeInPx = dpToPx(moduleContext, sizeInDp); // dp を px に変換 + drawable = scaleDrawable(drawable, sizeInPx, sizeInPx); imageView.setImageDrawable(drawable); } } } + private int dpToPx(Context context, float dp) { + float density = context.getResources().getDisplayMetrics().density; + return Math.round(dp * density); + } + private Drawable scaleDrawable(Drawable drawable, int width, int height) { 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 61a2f54..538577a 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 @@ -22,6 +22,7 @@ import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.HashSet; +import java.util.Objects; import java.util.Set; import de.robv.android.xposed.XC_MethodHook; @@ -90,8 +91,13 @@ public class PhotoAddNotification implements IHook { protected void beforeHookedMethod(MethodHookParam param) throws Throwable { Notification notification = (Notification) param.args[2]; - - if (param.args[0] != null) { + String tag = (String) param.args[0]; + int ids = (int) param.args[1]; + logAllNotificationDetails("notify", ids, notification, tag); + if (Objects.equals(notification.category, "call")) { + return; + } + if (param.args[0] == null) { param.setResult(null); return; } @@ -123,11 +129,6 @@ public class PhotoAddNotification implements IHook { String originalText = getNotificationText(originalNotification); Notification newNotification = originalNotification; - if (originalText.contains("LINE音声通話を着信中") || - originalText.contains("Incoming LINE voice call") || - originalText.contains("LINE語音通話來電中")) { - return; - } if (title == null) { return; } @@ -151,9 +152,7 @@ public class PhotoAddNotification implements IHook { } if (originalText != null && (originalText.contains("写真を送信しました") || originalText.contains("sent a photo") || originalText.contains("傳送了照片"))) { - String tag = (String) param.args[0]; - int ids = (int) param.args[1]; - logAllNotificationDetails("notify", ids, notification, tag); + Bundle extras = notification.extras; if (extras.containsKey("line.message.id")) { @@ -394,42 +393,42 @@ public class PhotoAddNotification implements IHook { 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 + ": " + -// "Title=" + action.title + -// ", Intent=" + action.actionIntent); + 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")); + 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/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 58fb12c..183eb9a 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -133,7 +133,7 @@ 音声ボタンを無効化 (既読機能)自分以外のメッセージを表示しない (Root用)着信音のミュート - KeepUnreadボタンの位置 + ボタンの設定 横マージン (KeepUnread) 縦マージン (KeepUnread) 発信音を無効にする\n diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index cab8d00..b5c3883 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -127,7 +127,7 @@ (閱讀功能)不要顯示您自己的資訊以外的信息 (對於 Root) 鈴聲靜音 - 保留未讀按鈕位置 + 按鈕設定 水平邊距 (KeepUnread) 垂直邊距 (KeepUnread) 停用撥號音 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b543619..69c066e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -137,7 +137,7 @@ 既読 %S (For Root) Mute ringtone - KeepUnread button location + button setting Horizontal margin (KeepUnread) Vertical margin (KeepUnread) Disable dial tone @@ -147,5 +147,5 @@ Read button (horizontal margin) (Read function) Do not display messages other than your own - + keep unread button size