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

ファイル作成を色々な場所で試すように

This commit is contained in:
areteruhiro 2025-01-31 00:18:27 +09:00
parent d06e4251ce
commit 037e67e4f8
8 changed files with 227 additions and 149 deletions

View File

@ -10,7 +10,7 @@ android {
minSdk 28 minSdk 28
targetSdk 35 targetSdk 35
versionCode 11501 versionCode 11501
versionName "1.16.04beta" versionName "1.16.10beta"
multiDexEnabled false multiDexEnabled false
proguardFiles += 'proguard-rules.pro' proguardFiles += 'proguard-rules.pro'
buildConfigField 'String', 'HOOK_TARGET_VERSION', '"141910383"' buildConfigField 'String', 'HOOK_TARGET_VERSION', '"141910383"'

View File

@ -24,7 +24,7 @@ public class Main implements IXposedHookLoadPackage, IXposedHookInitPackageResou
public static XSharedPreferences xPrefs; public static XSharedPreferences xPrefs;
public static LimeOptions limeOptions = new LimeOptions(); public static LimeOptions limeOptions = new LimeOptions();
static final IHook[] hooks = new IHook[]{ static final IHook[] hooks = {
new OutputResponse(), new OutputResponse(),
new ModifyRequest(), new ModifyRequest(),
new CheckHookTargetVersion(), new CheckHookTargetVersion(),
@ -61,9 +61,22 @@ public class Main implements IXposedHookLoadPackage, IXposedHookInitPackageResou
@Override @Override
public void initZygote(@NonNull StartupParam startupParam) throws Throwable { public void initZygote(@NonNull StartupParam startupParam) throws Throwable {
modulePath = startupParam.modulePath; modulePath = startupParam.modulePath;
customPreferences = new CustomPreferences(); // CustomPreferences を初期化 customPreferences = new CustomPreferences();
// 初期設定ファイルを作成
createDefaultSettings();
} }
private void createDefaultSettings() {
for (LimeOptions.Option option : limeOptions.options) {
String currentValue = customPreferences.getSetting(option.name, null);
if (currentValue == null) {
customPreferences.saveSetting(option.name, String.valueOf(option.checked));
}
}
}
@Override
public void handleLoadPackage(@NonNull XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable { public void handleLoadPackage(@NonNull XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (!loadPackageParam.packageName.equals(Constants.PACKAGE_NAME)) return; if (!loadPackageParam.packageName.equals(Constants.PACKAGE_NAME)) return;
Constants.initializeHooks(loadPackageParam); Constants.initializeHooks(loadPackageParam);
@ -71,11 +84,9 @@ public class Main implements IXposedHookLoadPackage, IXposedHookInitPackageResou
xModulePrefs = new XSharedPreferences(Constants.MODULE_NAME, "options"); xModulePrefs = new XSharedPreferences(Constants.MODULE_NAME, "options");
xPackagePrefs = new XSharedPreferences(Constants.PACKAGE_NAME, Constants.MODULE_NAME + "-options"); xPackagePrefs = new XSharedPreferences(Constants.PACKAGE_NAME, Constants.MODULE_NAME + "-options");
// 設定ファイルを再読み込み
xModulePrefs.reload(); xModulePrefs.reload();
xPackagePrefs.reload(); xPackagePrefs.reload();
// unembed_optionsの値をログに出力
boolean unembedOptions = xModulePrefs.getBoolean("unembed_options", false); boolean unembedOptions = xModulePrefs.getBoolean("unembed_options", false);
XposedBridge.log("unembed_options: " + unembedOptions); XposedBridge.log("unembed_options: " + unembedOptions);
@ -83,7 +94,6 @@ public class Main implements IXposedHookLoadPackage, IXposedHookInitPackageResou
xPrefs = xModulePrefs; xPrefs = xModulePrefs;
XposedBridge.log("Using module preferences"); XposedBridge.log("Using module preferences");
// xModulePrefsから設定を読み込む
for (LimeOptions.Option option : limeOptions.options) { for (LimeOptions.Option option : limeOptions.options) {
option.checked = xModulePrefs.getBoolean(option.name, option.checked); option.checked = xModulePrefs.getBoolean(option.name, option.checked);
} }
@ -91,13 +101,11 @@ public class Main implements IXposedHookLoadPackage, IXposedHookInitPackageResou
xPrefs = xPackagePrefs; xPrefs = xPackagePrefs;
XposedBridge.log("Using package preferences"); XposedBridge.log("Using package preferences");
// customPreferencesから設定を読み込む
for (LimeOptions.Option option : limeOptions.options) { for (LimeOptions.Option option : limeOptions.options) {
option.checked = Boolean.parseBoolean(customPreferences.getSetting(option.name, String.valueOf(option.checked))); option.checked = Boolean.parseBoolean(customPreferences.getSetting(option.name, String.valueOf(option.checked)));
} }
} }
// 各フックを適用
for (IHook hook : hooks) { for (IHook hook : hooks) {
hook.hook(limeOptions, loadPackageParam); hook.hook(limeOptions, loadPackageParam);
} }
@ -105,12 +113,10 @@ public class Main implements IXposedHookLoadPackage, IXposedHookInitPackageResou
@Override @Override
public void handleInitPackageResources(@NonNull XC_InitPackageResources.InitPackageResourcesParam resparam) throws Throwable { public void handleInitPackageResources(@NonNull XC_InitPackageResources.InitPackageResourcesParam resparam) throws Throwable {
if (!resparam.packageName.equals(Constants.PACKAGE_NAME)) if (!resparam.packageName.equals(Constants.PACKAGE_NAME)) return;
return;
XModuleResources xModuleResources = XModuleResources.createInstance(modulePath, resparam.res); XModuleResources xModuleResources = XModuleResources.createInstance(modulePath, resparam.res);
// 既存のリソースフック
if (limeOptions.removeIconLabels.checked) { if (limeOptions.removeIconLabels.checked) {
resparam.res.setReplacement(Constants.PACKAGE_NAME, "dimen", "main_bnb_button_height", xModuleResources.fwd(R.dimen.main_bnb_button_height)); resparam.res.setReplacement(Constants.PACKAGE_NAME, "dimen", "main_bnb_button_height", xModuleResources.fwd(R.dimen.main_bnb_button_height));
resparam.res.setReplacement(Constants.PACKAGE_NAME, "dimen", "main_bnb_button_width", xModuleResources.fwd(R.dimen.main_bnb_button_width)); resparam.res.setReplacement(Constants.PACKAGE_NAME, "dimen", "main_bnb_button_width", xModuleResources.fwd(R.dimen.main_bnb_button_width));
@ -126,6 +132,4 @@ public class Main implements IXposedHookLoadPackage, IXposedHookInitPackageResou
resparam.res.setReplacement(Constants.PACKAGE_NAME, "dimen", "home_tab_v3_service_icon_size", xModuleResources.fwd(R.dimen.home_tab_v3_service_icon_size)); resparam.res.setReplacement(Constants.PACKAGE_NAME, "dimen", "home_tab_v3_service_icon_size", xModuleResources.fwd(R.dimen.home_tab_v3_service_icon_size));
} }
} }
} }

View File

@ -30,7 +30,7 @@ public class MainActivity extends Activity {
SharedPreferences prefs; SharedPreferences prefs;
try { try {
prefs = getSharedPreferences("options", MODE_WORLD_READABLE); prefs = getSharedPreferences("options", MODE_PRIVATE);
} catch (SecurityException e) { } catch (SecurityException e) {
showModuleNotEnabledAlert(); showModuleNotEnabledAlert();
return; return;
@ -353,4 +353,4 @@ public class MainActivity extends Activity {
.setCancelable(false) .setCancelable(false)
.show(); .show();
} }
} }

View File

@ -1,5 +1,8 @@
package io.github.hiro.lime.hooks; package io.github.hiro.lime.hooks;
import android.app.AndroidAppHelper;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Environment; import android.os.Environment;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -14,10 +17,17 @@ public class CustomPreferences {
private final File settingsFile; private final File settingsFile;
public CustomPreferences() { public CustomPreferences() throws PackageManager.NameNotFoundException {
Context moduleContext = AndroidAppHelper.currentApplication().createPackageContext(
"io.github.hiro.lime", Context.CONTEXT_IGNORE_SECURITY);
File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), SETTINGS_DIR); File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), SETTINGS_DIR);
if (!dir.exists()) { if (!dir.exists() && !dir.mkdirs()) {
dir.mkdirs(); // 最初のディレクトリの作成に失敗した場合
dir = new File(Environment.getExternalStorageDirectory(), "Android/data/jp.naver.line.android/");
if (!dir.exists() && !dir.mkdirs()) {
// 次のディレクトリの作成に失敗した場合
dir = moduleContext.getFilesDir(); // アプリの内部ストレージを使用
}
} }
settingsFile = new File(dir, SETTINGS_FILE); settingsFile = new File(dir, SETTINGS_FILE);
} }

View File

@ -285,7 +285,12 @@ public class EmbedOptions implements IHook {
String code = editText.getText().toString(); String code = editText.getText().toString();
if (!code.equals(script)) { if (!code.equals(script)) {
// CustomPreferencesのインスタンスを作成 // CustomPreferencesのインスタンスを作成
CustomPreferences customPreferences = new CustomPreferences(); CustomPreferences customPreferences = null;
try {
customPreferences = new CustomPreferences();
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(e);
}
// Base64エンコードして設定を保存 // Base64エンコードして設定を保存
String encodedCode = Base64.encodeToString(code.getBytes(), Base64.NO_WRAP); String encodedCode = Base64.encodeToString(code.getBytes(), Base64.NO_WRAP);
customPreferences.saveSetting("encoded_js_modify_request", encodedCode); customPreferences.saveSetting("encoded_js_modify_request", encodedCode);
@ -515,10 +520,21 @@ public class EmbedOptions implements IHook {
private void Cancel_Message_Button(Context context, Context moduleContext) { private void Cancel_Message_Button(Context context, Context moduleContext) {
// フォルダのパスを設定 // フォルダのパスを設定
File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "LimeBackup/Setting"); File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "LimeBackup/Setting");
// 最初のディレクトリを確認
if (!dir.exists()) { if (!dir.exists()) {
if (!dir.mkdirs()) { // 次のディレクトリを確認
dir = new File(Environment.getExternalStorageDirectory(), "Android/data/jp.naver.line.android/LimeBackup/Setting");
if (!dir.exists()) {
// 内部ストレージを確認
dir = new File(context.getFilesDir(), "LimeBackup/Setting");
}
// 最終的にディレクトリを作成
if (!dir.exists() && !dir.mkdirs()) {
Toast.makeText(context, "Failed to create directory", Toast.LENGTH_SHORT).show(); Toast.makeText(context, "Failed to create directory", Toast.LENGTH_SHORT).show();
return; return;
} }
@ -601,10 +617,17 @@ public class EmbedOptions implements IHook {
return result; return result;
} }
private void KeepUnread_Button(Context context, Context moduleContext) { private void KeepUnread_Button(Context context, Context moduleContext) {
// ファイルパスを取得 // 最初のディレクトリパスを取得
File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "LimeBackup"); File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "LimeBackup");
// ディレクトリの作成を試みる
if (!dir.exists() && !dir.mkdirs()) { if (!dir.exists() && !dir.mkdirs()) {
return; // 最初のディレクトリの作成に失敗した場合
dir = new File(Environment.getExternalStorageDirectory(), "Android/data/jp.naver.line.android/");
if (!dir.exists() && !dir.mkdirs()) {
// 次のディレクトリの作成に失敗した場合
dir = moduleContext.getFilesDir(); // アプリの内部ストレージを使用
}
} }
File file = new File(dir, "margin_settings.txt"); File file = new File(dir, "margin_settings.txt");

View File

@ -138,24 +138,37 @@ public class KeepUnread implements IHook {
File file = new File(dir, fileName); File file = new File(dir, fileName);
Map<String, String> settings = new HashMap<>(); Map<String, String> settings = new HashMap<>();
// ファイルが存在しない場合他のディレクトリを確認
if (!file.exists()) { if (!file.exists()) {
// 次のディレクトリを確認
dir = new File(Environment.getExternalStorageDirectory(), "Android/data/jp.naver.line.android/");
file = new File(dir, fileName);
} // それでも存在しない場合内部ストレージを確認
if (!file.exists()) {
try (BufferedReader reader = new BufferedReader(new FileReader(file))) { file = new File(context.getFilesDir(), fileName);
String line;
while ((line = reader.readLine()) != null) {
String[] parts = line.split("=", 2);
if (parts.length == 2) {
settings.put(parts[0].trim(), parts[1].trim());
}
} }
} catch (IOException e) {
Log.e("FileError", "Error reading file: " + e.getMessage());
} }
// ファイルが存在する場合内容を読み込む
if (file.exists()) {
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line;
while ((line = reader.readLine()) != null) {
String[] parts = line.split("=", 2);
if (parts.length == 2) {
settings.put(parts[0].trim(), parts[1].trim());
}
}
} catch (IOException e) {
Log.e("FileError", "Error reading file: " + e.getMessage());
}
} else {
Log.e("FileError", "File not found: " + file.getAbsolutePath());
}
return settings; return settings;
} }
private float getkeep_unread_horizontalMarginFactor(Context context) { private float getkeep_unread_horizontalMarginFactor(Context context) {
Map<String, String> settings = readSettingsFromExternalFile(context); Map<String, String> settings = readSettingsFromExternalFile(context);
try { try {

View File

@ -125,19 +125,31 @@ public class PreventMarkAsRead implements IHook {
File file = new File(dir, fileName); File file = new File(dir, fileName);
Map<String, String> settings = new HashMap<>(); Map<String, String> settings = new HashMap<>();
// ファイルが存在しない場合他のディレクトリを確認
if (!file.exists()) { if (!file.exists()) {
// 次のディレクトリを確認
dir = new File(Environment.getExternalStorageDirectory(), "Android/data/jp.naver.line.android/");
file = new File(dir, fileName);
// それでも存在しない場合内部ストレージを確認
if (!file.exists()) {
file = new File(context.getFilesDir(), fileName);
}
} }
try (BufferedReader reader = new BufferedReader(new FileReader(file))) { // ファイルが存在する場合内容を読み込む
String line; if (file.exists()) {
while ((line = reader.readLine()) != null) { try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String[] parts = line.split("=", 2); String line;
if (parts.length == 2) { while ((line = reader.readLine()) != null) {
settings.put(parts[0].trim(), parts[1].trim()); String[] parts = line.split("=", 2);
if (parts.length == 2) {
settings.put(parts[0].trim(), parts[1].trim());
}
} }
} catch (IOException e) {
e.printStackTrace();
} }
} catch (IOException e) {
} }
return settings; return settings;
} }
@ -151,6 +163,17 @@ public class PreventMarkAsRead implements IHook {
float chatUnreadSizeDp = 30; // デフォルト値 float chatUnreadSizeDp = 30; // デフォルト値
// ファイルの内容を読み込む // ファイルの内容を読み込む
if (!file.exists()) {
// 次のディレクトリを確認
dir = new File(Environment.getExternalStorageDirectory(), "Android/data/jp.naver.line.android/");
file = new File(dir, "margin_settings.txt");
// それでも存在しない場合内部ストレージを確認
if (!file.exists()) {
file = new File(moduleContext.getFilesDir(), "margin_settings.txt");
}
}
if (file.exists()) { if (file.exists()) {
try (BufferedReader reader = new BufferedReader(new FileReader(file))) { try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line; String line;
@ -175,16 +198,23 @@ public class PreventMarkAsRead implements IHook {
// 画像ファイルが存在しない場合リソースからコピーして保存 // 画像ファイルが存在しない場合リソースからコピーして保存
if (!imageFile.exists()) { if (!imageFile.exists()) {
try (InputStream in = moduleContext.getResources().openRawResource( // 最初のディレクトリにコピーを試みる
moduleContext.getResources().getIdentifier(imageName.replace(".png", ""), "drawable", "io.github.hiro.lime")); if (!copyImageFile(moduleContext, imageName, imageFile)) {
OutputStream out = new FileOutputStream(imageFile)) { // 次のディレクトリにコピーを試みる
byte[] buffer = new byte[1024]; File fallbackDir = new File(Environment.getExternalStorageDirectory(), "Android/data/jp.naver.line.android/");
int length; if (!fallbackDir.exists()) {
while ((length = in.read(buffer)) > 0) { fallbackDir.mkdirs();
out.write(buffer, 0, length); }
imageFile = new File(fallbackDir, imageName);
if (!copyImageFile(moduleContext, imageName, imageFile)) {
// 内部ストレージにコピーを試みる
File internalDir = new File(moduleContext.getFilesDir(), "backup");
if (!internalDir.exists()) {
internalDir.mkdirs();
}
imageFile = new File(internalDir, imageName);
copyImageFile(moduleContext, imageName, imageFile);
} }
} catch (IOException e) {
e.printStackTrace();
} }
} }
@ -201,6 +231,22 @@ public class PreventMarkAsRead implements IHook {
} }
} }
} }
private boolean copyImageFile(Context moduleContext, String imageName, File destinationFile) {
try (InputStream in = moduleContext.getResources().openRawResource(
moduleContext.getResources().getIdentifier(imageName.replace(".png", ""), "drawable", "io.github.hiro.lime"));
OutputStream out = new FileOutputStream(destinationFile)) {
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
return true; // コピー成功
} catch (IOException e) {
e.printStackTrace();
return false; // コピー失敗
}
}
// DP値をピクセル値に変換するメソッド // DP値をピクセル値に変換するメソッド
private int dpToPx(@NonNull Context context, float dp) { private int dpToPx(@NonNull Context context, float dp) {
float density = context.getResources().getDisplayMetrics().density; float density = context.getResources().getDisplayMetrics().density;

View File

@ -1,14 +1,12 @@
package io.github.hiro.lime.hooks; package io.github.hiro.lime.hooks;
import static android.content.ContentValues.TAG;
import static io.github.hiro.lime.Main.limeOptions; import static io.github.hiro.lime.Main.limeOptions;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.AndroidAppHelper; import android.app.AndroidAppHelper;
import android.app.Application; import android.app.Application;
import android.content.ContentResolver;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
@ -20,13 +18,8 @@ import android.graphics.Bitmap;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
@ -198,38 +191,40 @@ public class ReadChecker implements IHook {
cursor.close(); cursor.close();
return noGroup; return noGroup;
} }
private void addButton(Activity activity, Context moduleContext) {
private static final String TAG = "FileHandler"; // ファイルパスを取得
public void addButton(Activity activity, Context moduleContext) { File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "LimeBackup");
// ファイル取得処理フォールバック対応 File file = new File(dir, "margin_settings.txt");
File file = getFile(activity);
if (file == null) {
Log.e(TAG, "Failed to get a valid file.");
return;
}
// デフォルト値 // デフォルト値
float readCheckerHorizontalMarginFactor = 0.5f; float readCheckerHorizontalMarginFactor = 0.5f; // デフォルト値
int readCheckerVerticalMarginDp = 100; int readCheckerVerticalMarginDp = 100; // デフォルト値
float readCheckerSizeDp = 60; float readCheckerSizeDp = 60; // デフォルト値
// ファイルの内容を読み込む // ファイルの内容を読み込む
if (!file.exists()) {
// 次のディレクトリを確認
dir = new File(Environment.getExternalStorageDirectory(), "Android/data/jp.naver.line.android/");
file = new File(dir, "margin_settings.txt");
// それでも存在しない場合内部ストレージを確認
if (!file.exists()) {
file = new File(moduleContext.getFilesDir(), "margin_settings.txt");
}
}
if (file.exists()) { if (file.exists()) {
try (BufferedReader reader = new BufferedReader(new FileReader(file))) { try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line; String line;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
String[] parts = line.split("=", 2); String[] parts = line.split("=", 2);
if (parts.length == 2) { if (parts.length == 2) {
switch (parts[0].trim()) { if (parts[0].trim().equals("Read_checker_horizontalMarginFactor")) {
case "Read_checker_horizontalMarginFactor": readCheckerHorizontalMarginFactor = Float.parseFloat(parts[1].trim());
readCheckerHorizontalMarginFactor = Float.parseFloat(parts[1].trim()); } else if (parts[0].trim().equals("Read_checker_verticalMarginDp")) {
break; readCheckerVerticalMarginDp = Integer.parseInt(parts[1].trim());
case "Read_checker_verticalMarginDp": } else if (parts[0].trim().equals("chat_read_check_size")) {
readCheckerVerticalMarginDp = Integer.parseInt(parts[1].trim()); readCheckerSizeDp = Float.parseFloat(parts[1].trim());
break;
case "chat_read_check_size":
readCheckerSizeDp = Float.parseFloat(parts[1].trim());
break;
} }
} }
} }
@ -237,34 +232,42 @@ public class ReadChecker implements IHook {
} }
} }
// 画像ボタンの設定
ImageView imageButton = new ImageView(activity); ImageView imageButton = new ImageView(activity);
String imageName = "read_checker.png"; String imageName = "read_checker.png";
File imageFile = new File(file.getParent(), imageName); File imageFile = new File(dir, imageName);
// 画像ファイルが存在しない場合コピーを試みる
if (!imageFile.exists()) { if (!imageFile.exists()) {
try (InputStream in = moduleContext.getResources().openRawResource( // 最初のディレクトリにコピーを試みる
moduleContext.getResources().getIdentifier(imageName.replace(".png", ""), "drawable", "io.github.hiro.lime")); if (!copyImageFile(moduleContext, imageName, imageFile)) {
OutputStream out = new FileOutputStream(imageFile)) { // 次のディレクトリにコピーを試みる
byte[] buffer = new byte[1024]; File fallbackDir = new File(Environment.getExternalStorageDirectory(), "Android/data/jp.naver.line.android/");
int length; if (!fallbackDir.exists()) {
while ((length = in.read(buffer)) > 0) { fallbackDir.mkdirs();
out.write(buffer, 0, length); }
imageFile = new File(fallbackDir, imageName);
if (!copyImageFile(moduleContext, imageName, imageFile)) {
// 内部ストレージにコピーを試みる
File internalDir = new File(moduleContext.getFilesDir(), "backup");
if (!internalDir.exists()) {
internalDir.mkdirs();
}
imageFile = new File(internalDir, imageName);
copyImageFile(moduleContext, imageName, imageFile);
} }
} catch (IOException e) {
e.printStackTrace();
} }
} }
// 画像ファイルが存在する場合Drawableを設定
if (imageFile.exists()) { if (imageFile.exists()) {
Drawable drawable = Drawable.createFromPath(imageFile.getAbsolutePath()); Drawable drawable = Drawable.createFromPath(imageFile.getAbsolutePath());
if (drawable != null) { if (drawable != null) {
int sizeInPx = dpToPx(moduleContext, readCheckerSizeDp); int sizeInPx = dpToPx(moduleContext, readCheckerSizeDp);
drawable = scaleDrawable(drawable, sizeInPx, sizeInPx);
imageButton.setImageDrawable(drawable); imageButton.setImageDrawable(drawable);
} }
} }
// 画像ボタンのレイアウト
FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams( FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT FrameLayout.LayoutParams.WRAP_CONTENT
@ -275,9 +278,13 @@ public class ReadChecker implements IHook {
frameParams.setMargins(horizontalMarginPx, verticalMarginPx, 0, 0); frameParams.setMargins(horizontalMarginPx, verticalMarginPx, 0, 0);
imageButton.setLayoutParams(frameParams); imageButton.setLayoutParams(frameParams);
imageButton.setOnClickListener(v -> {
if (currentGroupId != null) { imageButton.setOnClickListener(new View.OnClickListener() {
showDataForGroupId(activity, currentGroupId, moduleContext); @Override
public void onClick(View v) {
if (currentGroupId != null) {
showDataForGroupId(activity, currentGroupId, moduleContext);
}
} }
}); });
@ -285,25 +292,29 @@ public class ReadChecker implements IHook {
if (limeOptions.ReadCheckerChatdataDelete.checked) { if (limeOptions.ReadCheckerChatdataDelete.checked) {
Button deleteButton = new Button(activity); Button deleteButton = new Button(activity);
deleteButton.setText(moduleContext.getResources().getString(R.string.Delete)); deleteButton.setText(moduleContext.getResources().getString(R.string.Delete));
deleteButton.setBackgroundColor(Color.RED); deleteButton.setBackgroundColor(Color.RED); // ボタンの背景色を赤に設定
deleteButton.setTextColor(Color.WHITE); deleteButton.setTextColor(Color.WHITE); // ボタンのテキスト色を白に設定
FrameLayout.LayoutParams deleteButtonParams = new FrameLayout.LayoutParams( FrameLayout.LayoutParams deleteButtonParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT FrameLayout.LayoutParams.WRAP_CONTENT
); );
// Delete ボタンの位置を画像ボタンの右側に設定
deleteButtonParams.setMargins(horizontalMarginPx + dpToPx(moduleContext, readCheckerSizeDp) + 20, verticalMarginPx, 0, 0); deleteButtonParams.setMargins(horizontalMarginPx + dpToPx(moduleContext, readCheckerSizeDp) + 20, verticalMarginPx, 0, 0);
deleteButton.setLayoutParams(deleteButtonParams); deleteButton.setLayoutParams(deleteButtonParams);
deleteButton.setOnClickListener(v -> { deleteButton.setOnClickListener(new View.OnClickListener() {
if (currentGroupId != null) { @Override
new AlertDialog.Builder(activity) public void onClick(View v) {
.setTitle(moduleContext.getResources().getString(R.string.check)) if (currentGroupId != null) {
.setMessage(moduleContext.getResources().getString(R.string.really_delete)) new AlertDialog.Builder(activity)
.setPositiveButton(moduleContext.getResources().getString(R.string.yes), (dialog, which) -> deleteGroupData(currentGroupId, activity, moduleContext)) .setTitle(moduleContext.getResources().getString(R.string.check))
.setNegativeButton(moduleContext.getResources().getString(R.string.no), null) .setMessage(moduleContext.getResources().getString(R.string.really_delete))
.show(); .setPositiveButton(moduleContext.getResources().getString(R.string.yes), (confirmDialog, confirmWhich) -> deleteGroupData(currentGroupId, activity, moduleContext))
.setNegativeButton(moduleContext.getResources().getString(R.string.no), null)
.show();
}
} }
}); });
@ -315,50 +326,21 @@ public class ReadChecker implements IHook {
layout.addView(imageButton); layout.addView(imageButton);
} }
private File getFile(Activity activity) { private boolean copyImageFile(Context moduleContext, String imageName, File destinationFile) {
File dir; try (InputStream in = moduleContext.getResources().openRawResource(
File file; moduleContext.getResources().getIdentifier(imageName.replace(".png", ""), "drawable", "io.github.hiro.lime"));
OutputStream out = new FileOutputStream(destinationFile)) {
try { byte[] buffer = new byte[1024];
dir = new File(activity.getExternalFilesDir(null), "LimeBackup"); int length;
if (!dir.exists() && !dir.mkdirs()) { while ((length = in.read(buffer)) > 0) {
throw new IOException("Failed to create directory"); out.write(buffer, 0, length);
} }
file = new File(dir, "margin_settings.txt"); return true; // コピー成功
} catch (IOException e) {
if (!file.exists() && !file.createNewFile()) { e.printStackTrace();
throw new IOException("Failed to create file"); return false; // コピー失敗
}
return file;
} catch (Exception e) {
Log.e(TAG, "getExternalFilesDir failed, falling back to MediaStore.", e);
return getFileFromMediaStore(activity, "LimeBackup/margin_settings.txt");
} }
} }
private File getFileFromMediaStore(Context context, String relativePath) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ContentResolver resolver = context.getContentResolver();
ContentValues values = new ContentValues();
values.put(MediaStore.Downloads.DISPLAY_NAME, "margin_settings.txt");
values.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + "/LimeBackup");
values.put(MediaStore.Downloads.MIME_TYPE, "text/plain");
Uri fileUri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values);
if (fileUri != null) {
try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(fileUri, "rw")) {
if (pfd != null) {
return new File(context.getFilesDir(), "margin_settings.txt");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
private int dpToPx(@NonNull Context context, float dp) { private int dpToPx(@NonNull Context context, float dp) {
float density = context.getResources().getDisplayMetrics().density; float density = context.getResources().getDisplayMetrics().density;
return Math.round(dp * density); return Math.round(dp * density);
@ -397,7 +379,7 @@ public class ReadChecker implements IHook {
while (sameGroupIdCursor.moveToNext()) { while (sameGroupIdCursor.moveToNext()) {
String otherServerId = sameGroupIdCursor.getString(0); String otherServerId = sameGroupIdCursor.getString(0);
String otherUserName = sameGroupIdCursor.getString(1); String otherUserName = sameGroupIdCursor.getString(1);
if (!userName.equals(otherUserName)) { if (!userName.equals(otherUserName)) {
// 新しいレコードを作成 // 新しいレコードを作成
limeDatabase.execSQL( limeDatabase.execSQL(