diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java index 6d559e30c7..9e7d99c97d 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java @@ -15,6 +15,7 @@ import android.widget.Toast; import androidx.activity.OnBackPressedCallback; +import androidx.appcompat.app.AlertDialog; import com.kdt.LoggerView; @@ -185,6 +186,7 @@ private void startModInstallerWithUri(Uri uri) { try { File cacheFile = new File(getCacheDir(), "mod-installer-temp"); InputStream contentStream = getContentResolver().openInputStream(uri); + if(contentStream == null) throw new IOException("Failed to open content stream"); try (FileOutputStream fileOutputStream = new FileOutputStream(cacheFile)) { IOUtils.copy(contentStream, fileOutputStream); } @@ -195,23 +197,71 @@ private void startModInstallerWithUri(Uri uri) { } } + public Runtime selectRuntime(File modFile) { + int javaVersion = getJavaVersion(modFile); + if(javaVersion == -1) { + finalErrorDialog(getString(R.string.execute_jar_failed_to_read_file)); + return null; + } + String nearestRuntime = MultiRTUtils.getNearestJreName(javaVersion); + if(nearestRuntime == null) { + finalErrorDialog(getString(R.string.multirt_nocompatiblert, javaVersion)); + return null; + } + Runtime selectedRuntime = MultiRTUtils.forceReread(nearestRuntime); + int selectedJavaVersion = Math.max(javaVersion, selectedRuntime.javaVersion); + // Don't allow versions higher than Java 17 because our caciocavallo implementation does not allow for it + if(selectedJavaVersion > 17) { + finalErrorDialog(getString(R.string.execute_jar_incompatible_runtime, selectedJavaVersion)); + return null; + } + return selectedRuntime; + } + + private File findModPath(List argList) { + int argsSize = argList.size(); + for(int i = 0; i < argsSize; i++) { + // Look for the -jar argument + if(!argList.get(i).equals("-jar")) continue; + int pathIndex = i+1; + // Check if the supposed path is out of the argument bounds + if(pathIndex >= argsSize) return null; + // Use the path as a file + return new File(argList.get(pathIndex)); + } + return null; + } + private void startModInstaller(File modFile, String javaArgs) { new Thread(() -> { - Runtime runtime = pickJreForMod(modFile); - launchJavaRuntime(runtime, modFile, javaArgs); + // Maybe replace with more advanced arg parsing logic later + List argList = javaArgs != null ? Arrays.asList(javaArgs.split(" ")) : null; + File selectedMod = modFile; + if(selectedMod == null && argList != null) { + // If modFile is not specified directly, try to extract the -jar argument from the javaArgs + selectedMod = findModPath(argList); + } + Runtime selectedRuntime; + if(selectedMod == null) { + // We were unable to find out the path to the mod. In that case, use the default runtime. + selectedRuntime = MultiRTUtils.forceReread(LauncherPreferences.PREF_DEFAULT_RUNTIME); + }else { + // Autoselect it properly in the other case. + selectedRuntime = selectRuntime(selectedMod); + // If the selection failed, just return. The autoselect function has already shown the dialog. + if(selectedRuntime == null) return; + } + launchJavaRuntime(selectedRuntime, modFile, argList); }, "JREMainThread").start(); } - private Runtime pickJreForMod(File modFile) { - String jreName = LauncherPreferences.PREF_DEFAULT_RUNTIME; - if(modFile != null) { - int javaVersion = getJavaVersion(modFile); - if(javaVersion != -1) { - String autoselectRuntime = MultiRTUtils.getNearestJreName(javaVersion); - if (autoselectRuntime != null) jreName = autoselectRuntime; - } - } - return MultiRTUtils.forceReread(jreName); + private void finalErrorDialog(CharSequence msg) { + runOnUiThread(()-> new AlertDialog.Builder(this) + .setTitle(R.string.global_error) + .setMessage(msg) + .setPositiveButton(android.R.string.ok, (d,w)->this.finish()) + .setCancelable(false) + .show()); } @Override @@ -301,21 +351,20 @@ public void toggleVirtualMouse(View v) { Toast.LENGTH_SHORT).show(); } - public void launchJavaRuntime(Runtime runtime, File modFile, String javaArgs) { + public void launchJavaRuntime(Runtime runtime, File modFile, List javaArgs) { JREUtils.redirectAndPrintJRELog(); try { List javaArgList = new ArrayList<>(); // Enable Caciocavallo Tools.getCacioJavaArgs(javaArgList,runtime.javaVersion == 8); - - if (javaArgs != null) { - javaArgList.addAll(Arrays.asList(javaArgs.split(" "))); - } else { + if(javaArgs != null) { + javaArgList.addAll(javaArgs); + } + if(modFile != null) { javaArgList.add("-jar"); javaArgList.add(modFile.getAbsolutePath()); } - if (LauncherPreferences.PREF_JAVA_SANDBOX) { Collections.reverse(javaArgList); @@ -374,7 +423,7 @@ public int getJavaVersion(File modFile) { Log.i("JavaGUILauncher", majorVersion+","+minorVersion); return classVersionToJavaVersion(majorVersion); }catch (Exception e) { - e.printStackTrace(); + Log.e("JavaVersion", "Exception thrown", e); return -1; } } diff --git a/app_pojavlauncher/src/main/res/values/strings.xml b/app_pojavlauncher/src/main/res/values/strings.xml index 53d2714404..4f5ff79c02 100644 --- a/app_pojavlauncher/src/main/res/values/strings.xml +++ b/app_pojavlauncher/src/main/res/values/strings.xml @@ -184,7 +184,7 @@ Set default Default You must have at least one Java Runtime installed. - Can\'t find any compartible Java Runtime. This version requires Java %d or newer. + Can\'t find any compatible Java Runtime. This version requires Java %d or newer. Can\'t find Java 8. In order to use this option, you need to install Java 8. Delete runtime Game directory @@ -381,4 +381,6 @@ Output\nOFF Output\nON Log output: + Failed to read the .jar file + Execute .jar feature is not compatible with Java %d