diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/manage/ModListPage.java b/FCL/src/main/java/com/tungsten/fcl/ui/manage/ModListPage.java index 03656cd6..483ad9f2 100644 --- a/FCL/src/main/java/com/tungsten/fcl/ui/manage/ModListPage.java +++ b/FCL/src/main/java/com/tungsten/fcl/ui/manage/ModListPage.java @@ -144,6 +144,7 @@ public class ModListPage extends FCLCommonPage implements ManageUI.VersionLoadab add(); } if (v == checkUpdateButton) { + checkUpdateButton.setFocusable(false); checkUpdates(); } if (v == refreshButton) { @@ -339,6 +340,7 @@ public class ModListPage extends FCLCommonPage implements ManageUI.VersionLoadab return null; }) .whenComplete(Schedulers.androidUIThread(), (result, exception) -> { + checkUpdateButton.setFocusable(true); if (exception != null || result == null) { FCLAlertDialog.Builder builder = new FCLAlertDialog.Builder(getContext()); builder.setCancelable(false); diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/manage/VersionSettingPage.java b/FCL/src/main/java/com/tungsten/fcl/ui/manage/VersionSettingPage.java index 213d9026..b41d4deb 100644 --- a/FCL/src/main/java/com/tungsten/fcl/ui/manage/VersionSettingPage.java +++ b/FCL/src/main/java/com/tungsten/fcl/ui/manage/VersionSettingPage.java @@ -130,7 +130,7 @@ public class VersionSettingPage extends FCLCommonPage implements ManageUI.Versio FCLTextView scaleFactorText = findViewById(R.id.scale_factor_text); scaleFactorSeekbar.addProgressListener(); - scaleFactorText.stringProperty().bind(Bindings.createStringBinding(() -> scaleFactorSeekbar.getProgress() + " %", scaleFactorSeekbar.percentProgressProperty())); + scaleFactorText.stringProperty().bind(Bindings.createStringBinding(() -> (int) (lastVersionSetting.getScaleFactor() * 100) + " %", scaleFactorSeekbar.percentProgressProperty())); // add spinner data ArrayList javaVersionDataList = new ArrayList<>(); diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/setting/SettingUI.java b/FCL/src/main/java/com/tungsten/fcl/ui/setting/SettingUI.java index 3a76a5c6..00e994d7 100644 --- a/FCL/src/main/java/com/tungsten/fcl/ui/setting/SettingUI.java +++ b/FCL/src/main/java/com/tungsten/fcl/ui/setting/SettingUI.java @@ -41,7 +41,9 @@ public class SettingUI extends FCLMultiPageUI implements TabLayout.OnTabSelected @Override public void onStart() { super.onStart(); - ((VersionSettingPage) pageManager.getPageById(SettingPageManager.PAGE_ID_SETTING_GAME)).loadVersion(Profiles.getSelectedProfile(), null); + if (pageManager != null) { + ((VersionSettingPage) pageManager.getPageById(SettingPageManager.PAGE_ID_SETTING_GAME)).loadVersion(Profiles.getSelectedProfile(), null); + } } @Override diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/util/io/NetworkUtils.java b/FCLCore/src/main/java/com/tungsten/fclcore/util/io/NetworkUtils.java index ca45854b..25d5f48c 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/util/io/NetworkUtils.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/util/io/NetworkUtils.java @@ -29,6 +29,8 @@ import java.util.Map.Entry; import static java.nio.charset.StandardCharsets.UTF_8; +import com.tungsten.fclauncher.utils.FCLPath; +import com.tungsten.fclcore.R; import com.tungsten.fclcore.util.Pair; public final class NetworkUtils { @@ -84,8 +86,20 @@ public final class NetworkUtils { return result; } + private static boolean endsWithDomainSuffix(String host, String domainSuffix) { + return host.endsWith(domainSuffix.toLowerCase()); + } + public static URLConnection createConnection(URL url) throws IOException { URLConnection connection = url.openConnection(); + String host = url.getHost().toLowerCase(); + if (endsWithDomainSuffix(host, "d.pcs.baidu.com") || endsWithDomainSuffix(host, "baidupcs.com")) { + // Docs: https://alist.nn.ci/zh/guide/drivers/baidu.html + connection.setRequestProperty("User-Agent", "pan.baidu.com"); + } else { + // Default + connection.setRequestProperty("User-Agent", "FCL/" + FCLPath.CONTEXT.getString(R.string.app_version)); + } connection.setUseCaches(false); connection.setConnectTimeout(5000); connection.setReadTimeout(5000); diff --git a/FCLCore/src/main/res/values/strings.xml b/FCLCore/src/main/res/values/strings.xml new file mode 100644 index 00000000..212db027 --- /dev/null +++ b/FCLCore/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + auto_change_by_gradle + \ No newline at end of file diff --git a/FCLauncher/src/main/java/com/tungsten/fclauncher/bridge/FCLBridge.java b/FCLauncher/src/main/java/com/tungsten/fclauncher/bridge/FCLBridge.java index 0a141c90..1521ee13 100644 --- a/FCLauncher/src/main/java/com/tungsten/fclauncher/bridge/FCLBridge.java +++ b/FCLauncher/src/main/java/com/tungsten/fclauncher/bridge/FCLBridge.java @@ -77,7 +77,6 @@ public class FCLBridge implements Serializable { private boolean surfaceDestroyed; private Handler handler; private Thread thread; - private Thread fclLogThread; static { System.loadLibrary("xhook"); @@ -123,15 +122,24 @@ public class FCLBridge implements Serializable { this.handler = new Handler(); this.callback = callback; this.surface = surface; - fclLogThread = new Thread(() -> { - receiveLog("invoke redirectStdio"); - int errorCode = redirectStdio(getLogPath()); - if (errorCode != 0) { - receiveLog("Can't exec redirectStdio! Error code: " + errorCode); - } - }); - fclLogThread.setName("FCLLogThread"); - fclLogThread.start(); + setFCLBridge(this); + receiveLog("invoke redirectStdio"); + int errorCode = redirectStdio(getLogPath()); + if (errorCode != 0) { + receiveLog("Can't exec redirectStdio! Error code: " + errorCode); + } + receiveLog("invoke setLogPipeReady"); + // set graphic output and event pipe + if (surface != null) { + handleWindow(); + } + receiveLog("invoke setEventPipe"); + setEventPipe(); + + // start + if (thread != null) { + thread.start(); + } } public void pushEventMouseButton(int button, boolean press) { @@ -273,25 +281,6 @@ public class FCLBridge implements Serializable { this.logPath = logPath; } - public void setLogPipeReady() { - receiveLog("invoke setLogPipeReady"); - handler.post(() -> { - receiveLog("invoke setFCLBridge"); - setFCLBridge(this); - // set graphic output and event pipe - if (surface != null) { - handleWindow(); - } - receiveLog("invoke setEventPipe"); - setEventPipe(); - - // start - if (thread != null) { - thread.start(); - } - }); - } - public void receiveLog(String log) { if (callback != null) { callback.onLog(log); diff --git a/FCLauncher/src/main/jni/fcl/fcl_loader.c b/FCLauncher/src/main/jni/fcl/fcl_loader.c index 82bc7e81..746ac976 100644 --- a/FCLauncher/src/main/jni/fcl/fcl_loader.c +++ b/FCLauncher/src/main/jni/fcl/fcl_loader.c @@ -12,6 +12,7 @@ #include #include #include +#include #define FULL_VERSION "1.8.0-internal" #define DOT_VERSION "1.8" @@ -30,79 +31,69 @@ typedef void (*android_update_LD_LIBRARY_PATH_t)(const char*); static volatile jobject exitTrap_bridge; static volatile jmethodID exitTrap_method; static JavaVM *exitTrap_jvm; -static bool logPipeReady = false; -static volatile jobject log_bridge; static volatile jmethodID log_method; static JavaVM *log_pipe_jvm; -jstring CStr2Jstring(JNIEnv *env, const char *buffer); +static int fclFd[2]; +static pthread_t logger; -jstring CStr2Jstring(JNIEnv *env, const char *buffer) { - jsize len = strlen(buffer); - jclass strClass = (*env)->FindClass(env, "java/lang/String"); - jstring encoding = (*env)->NewStringUTF(env, "UTF-8"); - jmethodID ctorID = (*env)->GetMethodID(env, strClass, "", "([BLjava/lang/String;)V"); - jbyteArray bytes = (*env)->NewByteArray(env, len); - (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *) buffer); - return (jstring) (*env)->NewObject(env, strClass, ctorID, bytes, encoding); -} - -void fclLog(const char *buffer) { - if (logPipeReady) { - JNIEnv *env; - (*log_pipe_jvm)->AttachCurrentThread(log_pipe_jvm, &env, NULL); - (*env)->CallVoidMethod(env, log_bridge, log_method, CStr2Jstring(env, buffer)); - (*log_pipe_jvm)->DetachCurrentThread(log_pipe_jvm); - } -} - -JNIEXPORT jint JNICALL Java_com_tungsten_fclauncher_bridge_FCLBridge_redirectStdio(JNIEnv* env, jobject jobject, jstring path) { - int fclFd[2]; - if (pipe(fclFd) < 0) { - __android_log_print(ANDROID_LOG_ERROR, "FCL", "Failed to create log pipe!"); - return 1; - } - - if (dup2(fclFd[1], STDOUT_FILENO) != STDOUT_FILENO && dup2(fclFd[1], STDERR_FILENO) != STDERR_FILENO) { - __android_log_print(ANDROID_LOG_ERROR, "FCL", "failed to redirect stdio!"); - return 2; - } +static void *logger_thread() { + JNIEnv *env; + JavaVM *vm = fcl->android_jvm; + (*vm)->AttachCurrentThread(vm, &env, NULL); char buffer[1024]; - jclass bridge = (*env) -> FindClass(env, "com/tungsten/fclauncher/bridge/FCLBridge"); - jmethodID method_setLogPipeReady = (*env) -> GetMethodID(env, bridge, "setLogPipeReady", "()V"); - if (!method_setLogPipeReady) { - __android_log_print(ANDROID_LOG_ERROR, "FCL", "Failed to find setLogPipeReady method!"); - return 3; - } - fcl->logFile = fdopen(fclFd[1], "a"); - FCL_INTERNAL_LOG("Log pipe ready."); - (*env) -> CallVoidMethod(env, jobject, method_setLogPipeReady); - log_method = (*env) -> GetMethodID(env, bridge, "receiveLog", "(Ljava/lang/String;)V"); - if (!log_method) { - __android_log_print(ANDROID_LOG_ERROR, "FCL", "Failed to find receive method!"); - return 4; - } - log_bridge = (*env)->NewGlobalRef(env, jobject); - (*env)->GetJavaVM(env, &log_pipe_jvm); - logPipeReady = true; + ssize_t _s; + jstring str; while (1) { memset(buffer, '\0', sizeof(buffer)); - ssize_t _s = read(fclFd[0], buffer, sizeof(buffer) - 1); + _s = read(fclFd[0], buffer, sizeof(buffer) - 1); if (_s < 0) { __android_log_print(ANDROID_LOG_ERROR, "FCL", "Failed to read log!"); close(fclFd[0]); close(fclFd[1]); - return 5; + (*vm)->DetachCurrentThread(vm); + return NULL; } else { buffer[_s] = '\0'; } if (buffer[0] == '\0') continue; else { - (*env)->CallVoidMethod(env, jobject, log_method, CStr2Jstring(env, buffer)); + str = (*env)->NewStringUTF(env, buffer); + (*env)->CallVoidMethod(env, fcl->object_FCLBridge, log_method, str); + (*env)->DeleteLocalRef(env, str); } } } +JNIEXPORT jint JNICALL Java_com_tungsten_fclauncher_bridge_FCLBridge_redirectStdio(JNIEnv* env, jobject jobject, jstring path) { + setvbuf(stdout, 0, _IOLBF, 0); + setvbuf(stderr, 0, _IONBF, 0); + if (pipe(fclFd) < 0) { + __android_log_print(ANDROID_LOG_ERROR, "FCL", "Failed to create log pipe!"); + return 1; + } + if (dup2(fclFd[1], STDOUT_FILENO) != STDOUT_FILENO && + dup2(fclFd[1], STDERR_FILENO) != STDERR_FILENO) { + __android_log_print(ANDROID_LOG_ERROR, "FCL", "failed to redirect stdio!"); + return 2; + } + jclass bridge = (*env) -> FindClass(env, "com/tungsten/fclauncher/bridge/FCLBridge"); + log_method = (*env) -> GetMethodID(env, bridge, "receiveLog", "(Ljava/lang/String;)V"); + if (!log_method) { + __android_log_print(ANDROID_LOG_ERROR, "FCL", "Failed to find receive method!"); + return 4; + } + fcl->logFile = fdopen(fclFd[1], "a"); + FCL_INTERNAL_LOG("Log pipe ready."); + (*env)->GetJavaVM(env, &log_pipe_jvm); + int result = pthread_create(&logger, 0, logger_thread, 0); + if (result != 0){ + return 5; + } + pthread_detach(logger); + return 0; +} + JNIEXPORT jint JNICALL Java_com_tungsten_fclauncher_bridge_FCLBridge_chdir(JNIEnv* env, jobject jobject, jstring path) { char const* dir = (*env)->GetStringUTFChars(env, path, 0); diff --git a/version_map.json b/version_map.json index 6d489821..0f44f98e 100644 --- a/version_map.json +++ b/version_map.json @@ -14,7 +14,7 @@ "text": "支持 NeoForge\n支持 Jar 文件执行\n更好的模组下载\n修复一些错误,详情见 Github,若无法下载或下载速度过慢,请使用网盘下载。" } ], - "netdiskUrl": "https://www.123pan.com/s/AVu2jv-oB80A.html", + "netdiskUrl": "https://alist.8mi.tech/FCL", "url": "https://github.com/FCL-Team/FoldCraftLauncher/releases/download/1.1.2/FCL-release-1.1.2.apk" } ]