mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2026-04-20 17:47:03 -04:00
feat: Manual JRE downloads
Lets you decide if you wanna download the JREs in the runtime manager
This commit is contained in:
@@ -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<Runtime> getNearestInstalledRuntime(int targetVersion) {
|
||||
List<Runtime> runtimes = MultiRTUtils.getRuntimes();
|
||||
List<Runtime> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<Runtime> runtimes = MultiRTUtils.getRuntimes();
|
||||
List<Runtime> runtimes = MultiRTUtils.getInstalledRuntimes();
|
||||
int jvmIndex = runtimes.indexOf(new Runtime("<Default>"));
|
||||
if (mTempProfile.javaDir != null) {
|
||||
String selectedRuntime = mTempProfile.javaDir.substring(Tools.LAUNCHERPROFILES_RTPREFIX.length());
|
||||
|
||||
@@ -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<Object> 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)
|
||||
|
||||
@@ -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<Runtime> getRuntimes() {
|
||||
public static List<Runtime> 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<ExternalRuntime> getRuntimesToDownload() {
|
||||
List<ExternalRuntime> 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<Runtime> runtimes = getRuntimes();
|
||||
List<Runtime> 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<Runtime> runtimes = getRuntimes();
|
||||
List<Runtime> runtimes = getInstalledRuntimes();
|
||||
MathUtils.RankedValue<Runtime> nearestRankedRuntime = MathUtils.findNearestPositive(majorVersion, runtimes, (runtime)->runtime.javaVersion);
|
||||
if(nearestRankedRuntime == null) return null;
|
||||
Runtime nearestRuntime = nearestRankedRuntime.value;
|
||||
|
||||
@@ -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<RTRecyclerViewAdapter.RTViewHolder> {
|
||||
|
||||
private boolean mIsDeleting = false;
|
||||
private MultiRTConfigDialog dialog;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
@@ -38,13 +40,18 @@ public class RTRecyclerViewAdapter extends RecyclerView.Adapter<RTRecyclerViewAd
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RTViewHolder holder, int position) {
|
||||
final List<Runtime> runtimes = MultiRTUtils.getRuntimes();
|
||||
holder.bindRuntime(runtimes.get(position),position);
|
||||
final List<Runtime> installedRuntimes = MultiRTUtils.getInstalledRuntimes();
|
||||
final List<NewJREUtil.ExternalRuntime> 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<RTRecyclerViewAd
|
||||
return mIsDeleting;
|
||||
}
|
||||
|
||||
public void setDialog(MultiRTConfigDialog multiRTConfigDialog) {
|
||||
this.dialog = multiRTConfigDialog;
|
||||
}
|
||||
|
||||
|
||||
public class RTViewHolder extends RecyclerView.ViewHolder {
|
||||
final TextView mJavaVersionTextView;
|
||||
@@ -104,7 +115,7 @@ public class RTRecyclerViewAdapter extends RecyclerView.Adapter<RTRecyclerViewAd
|
||||
mDeleteButton.setOnClickListener(v -> {
|
||||
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<RTRecyclerViewAd
|
||||
});
|
||||
}
|
||||
|
||||
public void bindRuntime(Runtime runtime, int pos) {
|
||||
public void bindInstalledRuntime(Runtime runtime, int pos) {
|
||||
mCurrentRuntime = runtime;
|
||||
mCurrentPosition = pos;
|
||||
if(runtime.versionString != null && Tools.DEVICE_ARCHITECTURE == Architecture.archAsInt(runtime.arch)) {
|
||||
@@ -159,6 +170,48 @@ public class RTRecyclerViewAdapter extends RecyclerView.Adapter<RTRecyclerViewAd
|
||||
mSetDefaultButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
public void bindDownloadableRuntime(NewJREUtil.ExternalRuntime runtime, int pos) {
|
||||
mCurrentPosition = pos;
|
||||
mJavaVersionTextView.setText(runtime.name
|
||||
.replace(".tar.xz", "")
|
||||
.replace("-", " "));
|
||||
mFullJavaVersionTextView.setText(R.string.global_not_installed);
|
||||
mFullJavaVersionTextView.setTextColor(mDefaultColors);
|
||||
mSetDefaultButton.setVisibility(View.VISIBLE);
|
||||
mDeleteButton.setVisibility(View.GONE);
|
||||
|
||||
if (runtime.isDownloading) {
|
||||
mSetDefaultButton.setEnabled(false);
|
||||
mSetDefaultButton.setText(R.string.global_installing);
|
||||
} else {
|
||||
mSetDefaultButton.setEnabled(true);
|
||||
mSetDefaultButton.setText(R.string.global_download);
|
||||
}
|
||||
|
||||
mSetDefaultButton.setOnClickListener(v -> {
|
||||
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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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?
|
||||
</string>
|
||||
<string name="not_modpack_file">Not a modpack file!</string>
|
||||
<string name="global_not_installed">Not Installed</string>
|
||||
<string name="global_download">Download</string>
|
||||
<string name="multirt_no_internet">Failed to download, check your internet connection.</string>
|
||||
<string name="global_installing">Installing…</string>
|
||||
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user