diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/NewJREUtil.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/NewJREUtil.java index cd4290cf7..76ca98ca1 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/NewJREUtil.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/NewJREUtil.java @@ -3,32 +3,26 @@ package net.kdt.pojavlaunch; import static net.kdt.pojavlaunch.Architecture.archAsString; import static net.kdt.pojavlaunch.Architecture.getDeviceArchitecture; import static net.kdt.pojavlaunch.Tools.NATIVE_LIB_DIR; -import static net.kdt.pojavlaunch.Tools.downloadFile; import static net.kdt.pojavlaunch.Tools.isOnline; import android.app.Activity; +import android.content.Context; import android.content.res.AssetManager; import android.util.Log; -import androidx.appcompat.app.AlertDialog; - import com.kdt.mcgui.ProgressLayout; import net.kdt.pojavlaunch.multirt.MultiRTUtils; import net.kdt.pojavlaunch.multirt.Runtime; import net.kdt.pojavlaunch.progresskeeper.DownloaderProgressWrapper; -import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper; import net.kdt.pojavlaunch.utils.DownloadUtils; -import net.kdt.pojavlaunch.utils.JREUtils; import net.kdt.pojavlaunch.utils.MathUtils; import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles; import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile; -import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; import java.util.Arrays; import java.util.List; @@ -72,7 +66,7 @@ public class NewJREUtil { } private static MathUtils.RankedValue getNearestInstalledRuntime(int targetVersion) { - List runtimes = MultiRTUtils.getRuntimes(); + List runtimes = MultiRTUtils.getInstalledRuntimes(); return MathUtils.findNearestPositive(targetVersion, runtimes, (runtime)->runtime.javaVersion); } @@ -169,8 +163,8 @@ public class NewJREUtil { activity.getString(R.string.multirt_nocompatiblert, verInfo.javaVersion.majorVersion)); } - public static boolean isValidJavaVersion(int version) { - for (InternalRuntime javaVersion : InternalRuntime.values()) { + public static boolean isJavaVersionAvailableForDownload(int version) { + for (ExternalRuntime javaVersion : ExternalRuntime.values()) { if (javaVersion.majorVersion == version) { return true; } @@ -179,34 +173,35 @@ public class NewJREUtil { } private static String getJreSource(int javaVersion, String arch){ - return String.format("https://github.com/AngelAuraMC/angelauramc-openjdk-build/releases/latest/download/jre%s-android-%s.tar.xz", javaVersion, arch); + return String.format("https://github.com/AngelAuraMC/angelauramc-openjdk-build/releases/download/download_jre%1$s/jre%1$s-android-%2$s.tar.xz", javaVersion, arch); } /** * @return whether installation was successful or not */ - private static boolean tryDownloadRuntime(Activity activity, int gameRequiredVersion){ - if (!isOnline(activity)) return false; + private static void tryDownloadRuntime(Context activity, int javaVersion){ + if (!isOnline(activity)) throw new RuntimeException(activity.getString(R.string.multirt_no_internet)); String arch = archAsString(getDeviceArchitecture()); - if (!isValidJavaVersion(gameRequiredVersion)) return false; + // Checks for using this method + if (!isJavaVersionAvailableForDownload(javaVersion)) throw new RuntimeException("This is not an available JRE version"); + if ((getDeviceArchitecture() == Architecture.ARCH_X86 && javaVersion >= 21)) throw new RuntimeException("x86 is not supported on Java"+javaVersion); try { - File outputFile = new File(Tools.DIR_CACHE, String.format("jre%s-android-%s.tar.xz", gameRequiredVersion, arch)); + File outputFile = new File(Tools.DIR_CACHE, String.format("jre%s-android-%s.tar.xz", javaVersion, arch)); DownloaderProgressWrapper monitor = new DownloaderProgressWrapper(R.string.newdl_downloading_jre_runtime, ProgressLayout.UNPACK_RUNTIME); - monitor.extraString = Integer.toString(gameRequiredVersion); + monitor.extraString = Integer.toString(javaVersion); DownloadUtils.downloadFileMonitored( - getJreSource(gameRequiredVersion, arch), + getJreSource(javaVersion, arch), outputFile, null, monitor ); - String jreName = "External-" + gameRequiredVersion; + String jreName = "External-" + javaVersion; MultiRTUtils.installRuntimeNamed(NATIVE_LIB_DIR, new FileInputStream(outputFile), jreName); MultiRTUtils.postPrepare(jreName); outputFile.delete(); } catch (IOException e) { - throw new RuntimeException("Failed to download Java "+gameRequiredVersion+" for "+arch, e); + throw new RuntimeException("Failed to download Java "+javaVersion+" for "+arch, e); } - return true; } private enum InternalRuntime { @@ -223,4 +218,24 @@ public class NewJREUtil { } } + public enum ExternalRuntime { + JRE_8(8, "External-8"), + JRE_17(17, "External-17"), + JRE_21(21, "External-21"), + JRE_25(25, "External-25"); + public final int majorVersion; + public final String name; + public final String downloadLink; + public boolean isDownloading = false; + + ExternalRuntime(int majorVersion, String name) { + this.majorVersion = majorVersion; + this.name = name; + this.downloadLink = getJreSource(majorVersion, archAsString(getDeviceArchitecture())); + } + public void downloadRuntime(Context activity){ + tryDownloadRuntime(activity, majorVersion); + } + } + } \ No newline at end of file diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/ProfileEditorFragment.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/ProfileEditorFragment.java index aa3f8363f..45eff0b29 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/ProfileEditorFragment.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/ProfileEditorFragment.java @@ -42,7 +42,6 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Objects; public class ProfileEditorFragment extends Fragment implements CropperUtils.CropperListener{ public static final String TAG = "ProfileEditorFragment"; @@ -173,7 +172,7 @@ public class ProfileEditorFragment extends Fragment implements CropperUtils.Crop ); // Runtime spinner - List runtimes = MultiRTUtils.getRuntimes(); + List runtimes = MultiRTUtils.getInstalledRuntimes(); int jvmIndex = runtimes.indexOf(new Runtime("")); if (mTempProfile.javaDir != null) { String selectedRuntime = mTempProfile.javaDir.substring(Tools.LAUNCHERPROFILES_RTPREFIX.length()); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTConfigDialog.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTConfigDialog.java index 60fe9083f..b3fc48e11 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTConfigDialog.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTConfigDialog.java @@ -27,11 +27,16 @@ public class MultiRTConfigDialog { if(adapter != null) adapter.notifyDataSetChanged(); } + public MultiRTConfigDialog get() { + return this; + } + /** Build the dialog behavior and style */ public void prepare(Context activity, ActivityResultLauncher installJvmLauncher) { mDialogView = new RecyclerView(activity); mDialogView.setLayoutManager(new LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)); RTRecyclerViewAdapter adapter = new RTRecyclerViewAdapter(); + adapter.setDialog(get()); mDialogView.setAdapter(adapter); mDialog = new AlertDialog.Builder(activity) diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java index 09e602cd4..e09ff738b 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java @@ -1,5 +1,6 @@ package net.kdt.pojavlaunch.multirt; +import static net.kdt.pojavlaunch.Architecture.getDeviceArchitecture; import static net.kdt.pojavlaunch.Tools.NATIVE_LIB_DIR; import static org.apache.commons.io.FileUtils.listFiles; @@ -8,6 +9,8 @@ import android.util.Log; import com.kdt.mcgui.ProgressLayout; +import net.kdt.pojavlaunch.Architecture; +import net.kdt.pojavlaunch.NewJREUtil.ExternalRuntime; import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.Tools; import net.kdt.pojavlaunch.utils.MathUtils; @@ -36,7 +39,7 @@ public class MultiRTUtils { private static final String JAVA_VERSION_STR = "JAVA_VERSION=\""; private static final String OS_ARCH_STR = "OS_ARCH=\""; - public static List getRuntimes() { + public static List getInstalledRuntimes() { if(!RUNTIME_FOLDER.exists() && !RUNTIME_FOLDER.mkdirs()) { throw new RuntimeException("Failed to create runtime directory"); } @@ -51,8 +54,25 @@ public class MultiRTUtils { return runtimes; } + /** + * + * @return Java versions which are not installed but are present in {@link ExternalRuntime} + */ + public static List getRuntimesToDownload() { + List runtimesToDownload = new ArrayList<>(); + ExternalRuntime[] downloadableRuntimes = ExternalRuntime.values(); + for (ExternalRuntime downloadableruntime : downloadableRuntimes) { + if(getExactJreName(downloadableruntime.majorVersion) == null){ + // x86 isn't supported anymore for JRE25 + if (!(getDeviceArchitecture() == Architecture.ARCH_X86 && downloadableruntime.majorVersion >= 21)) + runtimesToDownload.add(downloadableruntime); + } + } + return runtimesToDownload; + } + public static String getExactJreName(int majorVersion) { - List runtimes = getRuntimes(); + List runtimes = getInstalledRuntimes(); for(Runtime r : runtimes) if(r.javaVersion == majorVersion)return r.name; @@ -60,7 +80,7 @@ public class MultiRTUtils { } public static String getNearestJreName(int majorVersion) { - List runtimes = getRuntimes(); + List runtimes = getInstalledRuntimes(); MathUtils.RankedValue nearestRankedRuntime = MathUtils.findNearestPositive(majorVersion, runtimes, (runtime)->runtime.javaVersion); if(nearestRankedRuntime == null) return null; Runtime nearestRuntime = nearestRankedRuntime.value; diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/RTRecyclerViewAdapter.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/RTRecyclerViewAdapter.java index 02e4072e2..00efae87e 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/RTRecyclerViewAdapter.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/RTRecyclerViewAdapter.java @@ -18,6 +18,7 @@ import androidx.appcompat.app.AlertDialog; import androidx.recyclerview.widget.RecyclerView; import net.kdt.pojavlaunch.Architecture; +import net.kdt.pojavlaunch.NewJREUtil; import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.Tools; import net.kdt.pojavlaunch.prefs.LauncherPreferences; @@ -28,6 +29,7 @@ import java.util.List; public class RTRecyclerViewAdapter extends RecyclerView.Adapter { private boolean mIsDeleting = false; + private MultiRTConfigDialog dialog; @NonNull @Override @@ -38,13 +40,18 @@ public class RTRecyclerViewAdapter extends RecyclerView.Adapter runtimes = MultiRTUtils.getRuntimes(); - holder.bindRuntime(runtimes.get(position),position); + final List installedRuntimes = MultiRTUtils.getInstalledRuntimes(); + final List downloadableRuntimes = MultiRTUtils.getRuntimesToDownload(); + if (installedRuntimes.size() > position) { + holder.bindInstalledRuntime(installedRuntimes.get(position),position); + } else if (installedRuntimes.size() + downloadableRuntimes.size() > position) { + holder.bindDownloadableRuntime(downloadableRuntimes.get(position - installedRuntimes.size()), position); + } } @Override public int getItemCount() { - return MultiRTUtils.getRuntimes().size(); + return MultiRTUtils.getInstalledRuntimes().size() + MultiRTUtils.getRuntimesToDownload().size(); } public boolean isDefaultRuntime(Runtime rt) { @@ -68,6 +75,10 @@ public class RTRecyclerViewAdapter extends RecyclerView.Adapter { if (mCurrentRuntime == null) return; - if(MultiRTUtils.getRuntimes().size() < 2) { + if(MultiRTUtils.getInstalledRuntimes().size() < 2) { new AlertDialog.Builder(mContext) .setTitle(R.string.global_error) .setMessage(R.string.multirt_config_removeerror_last) @@ -129,7 +140,7 @@ public class RTRecyclerViewAdapter extends RecyclerView.Adapter { + runtime.isDownloading = true; + mSetDefaultButton.setEnabled(false); + mSetDefaultButton.setText(R.string.global_download); + sExecutorService.execute(() -> { + mSetDefaultButton.setText(R.string.global_installing); + try { + runtime.downloadRuntime(v.getContext()); + } catch (RuntimeException e) { + Tools.showErrorRemote(e); + } + v.post(() -> { + // Reset the listener for this button so SET DEFAULT actually sets default + setupOnClickListeners(); + // Update the UI so it knows it got installed + notifyDataSetChanged(); + runtime.isDownloading = false; + }); + }); + }); + + } + private void updateButtonsVisibility(){ mSetDefaultButton.setVisibility(mIsDeleting ? View.GONE : View.VISIBLE); mDeleteButton.setVisibility(mIsDeleting ? View.VISIBLE : View.GONE); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java index 2ab740b7a..543a23695 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java @@ -133,11 +133,11 @@ public class LauncherPreferences { if(DEFAULT_PREF.contains("defaultRuntime")) { PREF_DEFAULT_RUNTIME = DEFAULT_PREF.getString("defaultRuntime",""); }else{ - if(MultiRTUtils.getRuntimes().isEmpty()) { + if(MultiRTUtils.getInstalledRuntimes().isEmpty()) { PREF_DEFAULT_RUNTIME = ""; return; } - PREF_DEFAULT_RUNTIME = MultiRTUtils.getRuntimes().get(0).name; + PREF_DEFAULT_RUNTIME = MultiRTUtils.getInstalledRuntimes().get(0).name; LauncherPreferences.DEFAULT_PREF.edit().putString("defaultRuntime",LauncherPreferences.PREF_DEFAULT_RUNTIME).apply(); } } diff --git a/app_pojavlauncher/src/main/res/values/strings.xml b/app_pojavlauncher/src/main/res/values/strings.xml index d7a737302..6f695e916 100644 --- a/app_pojavlauncher/src/main/res/values/strings.xml +++ b/app_pojavlauncher/src/main/res/values/strings.xml @@ -502,5 +502,9 @@ Sodium is unsupported, you are on your own. No support will be given in the discord server.\nUsing sodium may result in bugs, glitches, and crashes. No help will be given even if you lose any of your worlds or saves.\n\nNow what\'s %1$s multiplied by %2$s plus %3$s minus %4$s? Not a modpack file! + Not Installed + Download + Failed to download, check your internet connection. + Installing…