11package net .kdt .pojavlaunch ;
22
33import static net .kdt .pojavlaunch .Architecture .archAsString ;
4+ import static net .kdt .pojavlaunch .Architecture .getDeviceArchitecture ;
5+ import static net .kdt .pojavlaunch .Tools .NATIVE_LIB_DIR ;
6+ import static net .kdt .pojavlaunch .Tools .downloadFile ;
7+ import static net .kdt .pojavlaunch .Tools .isOnline ;
48
59import android .app .Activity ;
610import android .content .res .AssetManager ;
711import android .util .Log ;
812
13+ import androidx .appcompat .app .AlertDialog ;
14+
15+ import com .kdt .mcgui .ProgressLayout ;
16+
917import net .kdt .pojavlaunch .multirt .MultiRTUtils ;
1018import net .kdt .pojavlaunch .multirt .Runtime ;
19+ import net .kdt .pojavlaunch .progresskeeper .DownloaderProgressWrapper ;
20+ import net .kdt .pojavlaunch .progresskeeper .ProgressKeeper ;
21+ import net .kdt .pojavlaunch .utils .DownloadUtils ;
22+ import net .kdt .pojavlaunch .utils .JREUtils ;
1123import net .kdt .pojavlaunch .utils .MathUtils ;
1224import net .kdt .pojavlaunch .value .launcherprofiles .LauncherProfiles ;
1325import net .kdt .pojavlaunch .value .launcherprofiles .MinecraftProfile ;
1426
27+ import java .io .BufferedInputStream ;
28+ import java .io .File ;
29+ import java .io .FileInputStream ;
1530import java .io .IOException ;
31+ import java .io .InputStream ;
1632import java .util .Arrays ;
1733import java .util .List ;
1834
@@ -84,7 +100,7 @@ public static boolean installNewJreIfNeeded(Activity activity, JMinecraftVersion
84100 // Check whether the selection is an internal runtime
85101 InternalRuntime internalRuntime = getInternalRuntime (runtime );
86102 // If it is, check if updates are available from the APK file
87- if (internalRuntime != null ) {
103+ if (internalRuntime != null ) {
88104 // Not calling showRuntimeFail on failure here because we did, technically, find the compatible runtime
89105 return checkInternalRuntime (assetManager , internalRuntime );
90106 }
@@ -100,6 +116,18 @@ public static boolean installNewJreIfNeeded(Activity activity, JMinecraftVersion
100116 nearestInternalRuntime , nearestInstalledRuntime , (value )->value .rank
101117 );
102118
119+ // Check if the selected runtime actually exists in the APK, else download it
120+ // If it isn't InternalRuntime then it wasn't in the apk in the first place!
121+ if (selectedRankedRuntime .value instanceof InternalRuntime )
122+ if (!checkInternalRuntime (assetManager , (InternalRuntime ) selectedRankedRuntime .value )) {
123+ if (nearestInstalledRuntime == null ) // If this was non-null then it would be a valid runtime and we can leave it be
124+ tryDownloadRuntime (activity , gameRequiredVersion );
125+ // This means the internal runtime didn't extract so let's use installed instead
126+ // This also refreshes it so after the runtime download, it can find the new runtime
127+ selectedRankedRuntime = getNearestInstalledRuntime (gameRequiredVersion );
128+ }
129+
130+
103131 // No possible selections
104132 if (selectedRankedRuntime == null ) {
105133 showRuntimeFail (activity , versionInfo );
@@ -141,6 +169,46 @@ private static void showRuntimeFail(Activity activity, JMinecraftVersionList.Ver
141169 activity .getString (R .string .multirt_nocompatiblert , verInfo .javaVersion .majorVersion ));
142170 }
143171
172+ public static boolean isValidJavaVersion (int version ) {
173+ for (InternalRuntime javaVersion : InternalRuntime .values ()) {
174+ if (javaVersion .majorVersion == version ) {
175+ return true ;
176+ }
177+ }
178+ return false ;
179+ }
180+
181+ 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 );
183+ }
184+ /**
185+ * @return whether installation was successful or not
186+ */
187+ private static boolean tryDownloadRuntime (Activity activity , int gameRequiredVersion ){
188+ if (!isOnline (activity )) return false ;
189+ String arch = archAsString (getDeviceArchitecture ());
190+ if (!isValidJavaVersion (gameRequiredVersion )) return false ;
191+ try {
192+ File outputFile = new File (Tools .DIR_CACHE , String .format ("jre%s-android-%s.tar.xz" , gameRequiredVersion , arch ));
193+ DownloaderProgressWrapper monitor = new DownloaderProgressWrapper (R .string .newdl_downloading_jre_runtime ,
194+ ProgressLayout .UNPACK_RUNTIME );
195+ monitor .extraString = Integer .toString (gameRequiredVersion );
196+ DownloadUtils .downloadFileMonitored (
197+ getJreSource (gameRequiredVersion , arch ),
198+ outputFile ,
199+ null ,
200+ monitor
201+ );
202+ String jreName = "External-" + gameRequiredVersion ;
203+ MultiRTUtils .installRuntimeNamed (NATIVE_LIB_DIR , new FileInputStream (outputFile ), jreName );
204+ MultiRTUtils .postPrepare (jreName );
205+ outputFile .delete ();
206+ } catch (IOException e ) {
207+ throw new RuntimeException ("Failed to download Java " +gameRequiredVersion +" for " +arch , e );
208+ }
209+ return true ;
210+ }
211+
144212 private enum InternalRuntime {
145213 JRE_17 (17 , "Internal-17" , "components/jre-new" ),
146214 JRE_21 (21 , "Internal-21" , "components/jre-21" ),
0 commit comments