Skip to content

Commit 5ce3158

Browse files
committed
feat: Manual JRE downloads
Lets you decide if you wanna download the JREs in the runtime manager
1 parent afaa9bd commit 5ce3158

7 files changed

Lines changed: 128 additions & 32 deletions

File tree

app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/NewJREUtil.java

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,26 @@
33
import static net.kdt.pojavlaunch.Architecture.archAsString;
44
import static net.kdt.pojavlaunch.Architecture.getDeviceArchitecture;
55
import static net.kdt.pojavlaunch.Tools.NATIVE_LIB_DIR;
6-
import static net.kdt.pojavlaunch.Tools.downloadFile;
76
import static net.kdt.pojavlaunch.Tools.isOnline;
87

98
import android.app.Activity;
9+
import android.content.Context;
1010
import android.content.res.AssetManager;
1111
import android.util.Log;
1212

13-
import androidx.appcompat.app.AlertDialog;
14-
1513
import com.kdt.mcgui.ProgressLayout;
1614

1715
import net.kdt.pojavlaunch.multirt.MultiRTUtils;
1816
import net.kdt.pojavlaunch.multirt.Runtime;
1917
import net.kdt.pojavlaunch.progresskeeper.DownloaderProgressWrapper;
20-
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
2118
import net.kdt.pojavlaunch.utils.DownloadUtils;
22-
import net.kdt.pojavlaunch.utils.JREUtils;
2319
import net.kdt.pojavlaunch.utils.MathUtils;
2420
import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles;
2521
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
2622

27-
import java.io.BufferedInputStream;
2823
import java.io.File;
2924
import java.io.FileInputStream;
3025
import java.io.IOException;
31-
import java.io.InputStream;
3226
import java.util.Arrays;
3327
import java.util.List;
3428

@@ -72,7 +66,7 @@ private static InternalRuntime getInternalRuntime(Runtime runtime) {
7266
}
7367

7468
private static MathUtils.RankedValue<Runtime> getNearestInstalledRuntime(int targetVersion) {
75-
List<Runtime> runtimes = MultiRTUtils.getRuntimes();
69+
List<Runtime> runtimes = MultiRTUtils.getInstalledRuntimes();
7670
return MathUtils.findNearestPositive(targetVersion, runtimes, (runtime)->runtime.javaVersion);
7771
}
7872

@@ -169,8 +163,8 @@ private static void showRuntimeFail(Activity activity, JMinecraftVersionList.Ver
169163
activity.getString(R.string.multirt_nocompatiblert, verInfo.javaVersion.majorVersion));
170164
}
171165

172-
public static boolean isValidJavaVersion(int version) {
173-
for (InternalRuntime javaVersion : InternalRuntime.values()) {
166+
public static boolean isJavaVersionAvailableForDownload(int version) {
167+
for (ExternalRuntime javaVersion : ExternalRuntime.values()) {
174168
if (javaVersion.majorVersion == version) {
175169
return true;
176170
}
@@ -179,34 +173,35 @@ public static boolean isValidJavaVersion(int version) {
179173
}
180174

181175
private static String getJreSource(int javaVersion, String arch){
182-
return String.format("https://github.com/AngelAuraMC/angelauramc-openjdk-build/releases/latest/download/jre%s-android-%s.tar.xz", javaVersion, arch);
176+
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);
183177
}
184178
/**
185179
* @return whether installation was successful or not
186180
*/
187-
private static boolean tryDownloadRuntime(Activity activity, int gameRequiredVersion){
188-
if (!isOnline(activity)) return false;
181+
private static void tryDownloadRuntime(Context activity, int javaVersion){
182+
if (!isOnline(activity)) throw new RuntimeException(activity.getString(R.string.multirt_no_internet));
189183
String arch = archAsString(getDeviceArchitecture());
190-
if (!isValidJavaVersion(gameRequiredVersion)) return false;
184+
// Checks for using this method
185+
if (!isJavaVersionAvailableForDownload(javaVersion)) throw new RuntimeException("This is not an available JRE version");
186+
if ((getDeviceArchitecture() == Architecture.ARCH_X86 && javaVersion >= 21)) throw new RuntimeException("x86 is not supported on Java"+javaVersion);
191187
try {
192-
File outputFile = new File(Tools.DIR_CACHE, String.format("jre%s-android-%s.tar.xz", gameRequiredVersion, arch));
188+
File outputFile = new File(Tools.DIR_CACHE, String.format("jre%s-android-%s.tar.xz", javaVersion, arch));
193189
DownloaderProgressWrapper monitor = new DownloaderProgressWrapper(R.string.newdl_downloading_jre_runtime,
194190
ProgressLayout.UNPACK_RUNTIME);
195-
monitor.extraString = Integer.toString(gameRequiredVersion);
191+
monitor.extraString = Integer.toString(javaVersion);
196192
DownloadUtils.downloadFileMonitored(
197-
getJreSource(gameRequiredVersion, arch),
193+
getJreSource(javaVersion, arch),
198194
outputFile,
199195
null,
200196
monitor
201197
);
202-
String jreName = "External-" + gameRequiredVersion;
198+
String jreName = "External-" + javaVersion;
203199
MultiRTUtils.installRuntimeNamed(NATIVE_LIB_DIR, new FileInputStream(outputFile), jreName);
204200
MultiRTUtils.postPrepare(jreName);
205201
outputFile.delete();
206202
} catch (IOException e) {
207-
throw new RuntimeException("Failed to download Java "+gameRequiredVersion+" for "+arch, e);
203+
throw new RuntimeException("Failed to download Java "+javaVersion+" for "+arch, e);
208204
}
209-
return true;
210205
}
211206

212207
private enum InternalRuntime {
@@ -223,4 +218,24 @@ private enum InternalRuntime {
223218
}
224219
}
225220

221+
public enum ExternalRuntime {
222+
JRE_8(8, "External-8"),
223+
JRE_17(17, "External-17"),
224+
JRE_21(21, "External-21"),
225+
JRE_25(25, "External-25");
226+
public final int majorVersion;
227+
public final String name;
228+
public final String downloadLink;
229+
public boolean isDownloading = false;
230+
231+
ExternalRuntime(int majorVersion, String name) {
232+
this.majorVersion = majorVersion;
233+
this.name = name;
234+
this.downloadLink = getJreSource(majorVersion, archAsString(getDeviceArchitecture()));
235+
}
236+
public void downloadRuntime(Context activity){
237+
tryDownloadRuntime(activity, majorVersion);
238+
}
239+
}
240+
226241
}

app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/ProfileEditorFragment.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import java.util.ArrayList;
4343
import java.util.Arrays;
4444
import java.util.List;
45-
import java.util.Objects;
4645

4746
public class ProfileEditorFragment extends Fragment implements CropperUtils.CropperListener{
4847
public static final String TAG = "ProfileEditorFragment";
@@ -173,7 +172,7 @@ private void loadValues(@NonNull String profile, @NonNull Context context){
173172
);
174173

175174
// Runtime spinner
176-
List<Runtime> runtimes = MultiRTUtils.getRuntimes();
175+
List<Runtime> runtimes = MultiRTUtils.getInstalledRuntimes();
177176
int jvmIndex = runtimes.indexOf(new Runtime("<Default>"));
178177
if (mTempProfile.javaDir != null) {
179178
String selectedRuntime = mTempProfile.javaDir.substring(Tools.LAUNCHERPROFILES_RTPREFIX.length());

app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTConfigDialog.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,16 @@ public void refresh() {
2727
if(adapter != null) adapter.notifyDataSetChanged();
2828
}
2929

30+
public MultiRTConfigDialog get() {
31+
return this;
32+
}
33+
3034
/** Build the dialog behavior and style */
3135
public void prepare(Context activity, ActivityResultLauncher<Object> installJvmLauncher) {
3236
mDialogView = new RecyclerView(activity);
3337
mDialogView.setLayoutManager(new LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false));
3438
RTRecyclerViewAdapter adapter = new RTRecyclerViewAdapter();
39+
adapter.setDialog(get());
3540
mDialogView.setAdapter(adapter);
3641

3742
mDialog = new AlertDialog.Builder(activity)

app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package net.kdt.pojavlaunch.multirt;
22

3+
import static net.kdt.pojavlaunch.Architecture.getDeviceArchitecture;
34
import static net.kdt.pojavlaunch.Tools.NATIVE_LIB_DIR;
45
import static org.apache.commons.io.FileUtils.listFiles;
56

@@ -8,6 +9,8 @@
89

910
import com.kdt.mcgui.ProgressLayout;
1011

12+
import net.kdt.pojavlaunch.Architecture;
13+
import net.kdt.pojavlaunch.NewJREUtil.ExternalRuntime;
1114
import net.kdt.pojavlaunch.R;
1215
import net.kdt.pojavlaunch.Tools;
1316
import net.kdt.pojavlaunch.utils.MathUtils;
@@ -36,7 +39,7 @@ public class MultiRTUtils {
3639
private static final String JAVA_VERSION_STR = "JAVA_VERSION=\"";
3740
private static final String OS_ARCH_STR = "OS_ARCH=\"";
3841

39-
public static List<Runtime> getRuntimes() {
42+
public static List<Runtime> getInstalledRuntimes() {
4043
if(!RUNTIME_FOLDER.exists() && !RUNTIME_FOLDER.mkdirs()) {
4144
throw new RuntimeException("Failed to create runtime directory");
4245
}
@@ -51,16 +54,33 @@ public static List<Runtime> getRuntimes() {
5154
return runtimes;
5255
}
5356

57+
/**
58+
*
59+
* @return Java versions which are not installed but are present in {@link ExternalRuntime}
60+
*/
61+
public static List<ExternalRuntime> getRuntimesToDownload() {
62+
List<ExternalRuntime> runtimesToDownload = new ArrayList<>();
63+
ExternalRuntime[] downloadableRuntimes = ExternalRuntime.values();
64+
for (ExternalRuntime downloadableruntime : downloadableRuntimes) {
65+
if(getExactJreName(downloadableruntime.majorVersion) == null){
66+
// x86 isn't supported anymore for JRE25
67+
if (!(getDeviceArchitecture() == Architecture.ARCH_X86 && downloadableruntime.majorVersion >= 21))
68+
runtimesToDownload.add(downloadableruntime);
69+
}
70+
}
71+
return runtimesToDownload;
72+
}
73+
5474
public static String getExactJreName(int majorVersion) {
55-
List<Runtime> runtimes = getRuntimes();
75+
List<Runtime> runtimes = getInstalledRuntimes();
5676
for(Runtime r : runtimes)
5777
if(r.javaVersion == majorVersion)return r.name;
5878

5979
return null;
6080
}
6181

6282
public static String getNearestJreName(int majorVersion) {
63-
List<Runtime> runtimes = getRuntimes();
83+
List<Runtime> runtimes = getInstalledRuntimes();
6484
MathUtils.RankedValue<Runtime> nearestRankedRuntime = MathUtils.findNearestPositive(majorVersion, runtimes, (runtime)->runtime.javaVersion);
6585
if(nearestRankedRuntime == null) return null;
6686
Runtime nearestRuntime = nearestRankedRuntime.value;

app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/RTRecyclerViewAdapter.java

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import androidx.recyclerview.widget.RecyclerView;
1919

2020
import net.kdt.pojavlaunch.Architecture;
21+
import net.kdt.pojavlaunch.NewJREUtil;
2122
import net.kdt.pojavlaunch.R;
2223
import net.kdt.pojavlaunch.Tools;
2324
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
@@ -28,6 +29,7 @@
2829
public class RTRecyclerViewAdapter extends RecyclerView.Adapter<RTRecyclerViewAdapter.RTViewHolder> {
2930

3031
private boolean mIsDeleting = false;
32+
private MultiRTConfigDialog dialog;
3133

3234
@NonNull
3335
@Override
@@ -38,13 +40,18 @@ public RTViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
3840

3941
@Override
4042
public void onBindViewHolder(@NonNull RTViewHolder holder, int position) {
41-
final List<Runtime> runtimes = MultiRTUtils.getRuntimes();
42-
holder.bindRuntime(runtimes.get(position),position);
43+
final List<Runtime> installedRuntimes = MultiRTUtils.getInstalledRuntimes();
44+
final List<NewJREUtil.ExternalRuntime> downloadableRuntimes = MultiRTUtils.getRuntimesToDownload();
45+
if (installedRuntimes.size() > position) {
46+
holder.bindInstalledRuntime(installedRuntimes.get(position),position);
47+
} else if (installedRuntimes.size() + downloadableRuntimes.size() > position) {
48+
holder.bindDownloadableRuntime(downloadableRuntimes.get(position - installedRuntimes.size()), position);
49+
}
4350
}
4451

4552
@Override
4653
public int getItemCount() {
47-
return MultiRTUtils.getRuntimes().size();
54+
return MultiRTUtils.getInstalledRuntimes().size() + MultiRTUtils.getRuntimesToDownload().size();
4855
}
4956

5057
public boolean isDefaultRuntime(Runtime rt) {
@@ -68,6 +75,10 @@ public boolean getIsEditing(){
6875
return mIsDeleting;
6976
}
7077

78+
public void setDialog(MultiRTConfigDialog multiRTConfigDialog) {
79+
this.dialog = multiRTConfigDialog;
80+
}
81+
7182

7283
public class RTViewHolder extends RecyclerView.ViewHolder {
7384
final TextView mJavaVersionTextView;
@@ -104,7 +115,7 @@ private void setupOnClickListeners(){
104115
mDeleteButton.setOnClickListener(v -> {
105116
if (mCurrentRuntime == null) return;
106117

107-
if(MultiRTUtils.getRuntimes().size() < 2) {
118+
if(MultiRTUtils.getInstalledRuntimes().size() < 2) {
108119
new AlertDialog.Builder(mContext)
109120
.setTitle(R.string.global_error)
110121
.setMessage(R.string.multirt_config_removeerror_last)
@@ -129,7 +140,7 @@ private void setupOnClickListeners(){
129140
});
130141
}
131142

132-
public void bindRuntime(Runtime runtime, int pos) {
143+
public void bindInstalledRuntime(Runtime runtime, int pos) {
133144
mCurrentRuntime = runtime;
134145
mCurrentPosition = pos;
135146
if(runtime.versionString != null && Tools.DEVICE_ARCHITECTURE == Architecture.archAsInt(runtime.arch)) {
@@ -159,6 +170,48 @@ public void bindRuntime(Runtime runtime, int pos) {
159170
mSetDefaultButton.setVisibility(View.GONE);
160171
}
161172

173+
@SuppressLint("NotifyDataSetChanged")
174+
public void bindDownloadableRuntime(NewJREUtil.ExternalRuntime runtime, int pos) {
175+
mCurrentPosition = pos;
176+
mJavaVersionTextView.setText(runtime.name
177+
.replace(".tar.xz", "")
178+
.replace("-", " "));
179+
mFullJavaVersionTextView.setText(R.string.global_not_installed);
180+
mFullJavaVersionTextView.setTextColor(mDefaultColors);
181+
mSetDefaultButton.setVisibility(View.VISIBLE);
182+
mDeleteButton.setVisibility(View.GONE);
183+
184+
if (runtime.isDownloading) {
185+
mSetDefaultButton.setEnabled(false);
186+
mSetDefaultButton.setText(R.string.global_installing);
187+
} else {
188+
mSetDefaultButton.setEnabled(true);
189+
mSetDefaultButton.setText(R.string.global_download);
190+
}
191+
192+
mSetDefaultButton.setOnClickListener(v -> {
193+
runtime.isDownloading = true;
194+
mSetDefaultButton.setEnabled(false);
195+
mSetDefaultButton.setText(R.string.global_download);
196+
sExecutorService.execute(() -> {
197+
mSetDefaultButton.setText(R.string.global_installing);
198+
try {
199+
runtime.downloadRuntime(v.getContext());
200+
} catch (RuntimeException e) {
201+
Tools.showErrorRemote(e);
202+
}
203+
v.post(() -> {
204+
// Reset the listener for this button so SET DEFAULT actually sets default
205+
setupOnClickListeners();
206+
// Update the UI so it knows it got installed
207+
notifyDataSetChanged();
208+
runtime.isDownloading = false;
209+
});
210+
});
211+
});
212+
213+
}
214+
162215
private void updateButtonsVisibility(){
163216
mSetDefaultButton.setVisibility(mIsDeleting ? View.GONE : View.VISIBLE);
164217
mDeleteButton.setVisibility(mIsDeleting ? View.VISIBLE : View.GONE);

app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,11 @@ public static void loadPreferences(Context ctx) {
133133
if(DEFAULT_PREF.contains("defaultRuntime")) {
134134
PREF_DEFAULT_RUNTIME = DEFAULT_PREF.getString("defaultRuntime","");
135135
}else{
136-
if(MultiRTUtils.getRuntimes().isEmpty()) {
136+
if(MultiRTUtils.getInstalledRuntimes().isEmpty()) {
137137
PREF_DEFAULT_RUNTIME = "";
138138
return;
139139
}
140-
PREF_DEFAULT_RUNTIME = MultiRTUtils.getRuntimes().get(0).name;
140+
PREF_DEFAULT_RUNTIME = MultiRTUtils.getInstalledRuntimes().get(0).name;
141141
LauncherPreferences.DEFAULT_PREF.edit().putString("defaultRuntime",LauncherPreferences.PREF_DEFAULT_RUNTIME).apply();
142142
}
143143
}

app_pojavlauncher/src/main/res/values/strings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,5 +502,9 @@
502502
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?
503503
</string>
504504
<string name="not_modpack_file">Not a modpack file!</string>
505+
<string name="global_not_installed">Not Installed</string>
506+
<string name="global_download">Download</string>
507+
<string name="multirt_no_internet">Failed to download, check your internet connection.</string>
508+
<string name="global_installing">Installing…</string>
505509

506510
</resources>

0 commit comments

Comments
 (0)