From 4fc232cc163be6ec05f57b0590380732aeaf6302 Mon Sep 17 00:00:00 2001 From: artdeell Date: Wed, 14 Jul 2021 20:32:29 +0300 Subject: [PATCH] Actual useful multi-runtime Note: it's not yet exposed in Per-Version-Config and doesn't select automatically for versions that require certain runtimes --- .../kdt/pojavlaunch/BaseLauncherActivity.java | 8 +- .../net/kdt/pojavlaunch/BaseMainActivity.java | 4 +- .../pojavlaunch/JavaGUILauncherActivity.java | 4 + .../net/kdt/pojavlaunch/PojavApplication.java | 2 +- .../kdt/pojavlaunch/PojavLoginActivity.java | 250 ++++-------------- .../multirt/MultiRTConfigDialog.java | 14 +- .../kdt/pojavlaunch/multirt/MultiRTUtils.java | 80 +++++- .../multirt/RTRecyclerViewAdapter.java | 39 ++- .../prefs/LauncherPreferences.java | 8 + .../prefs/UninstallJREDialogPreference.java | 53 ---- .../net/kdt/pojavlaunch/utils/JREUtils.java | 2 +- .../res/layout/multirt_recyclable_view.xml | 10 + .../src/main/res/values/strings.xml | 2 + .../src/main/res/xml/pref_main.xml | 4 - 14 files changed, 204 insertions(+), 276 deletions(-) delete mode 100644 app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/UninstallJREDialogPreference.java diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseLauncherActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseLauncherActivity.java index 4ef2846ec..13c7b1a54 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseLauncherActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseLauncherActivity.java @@ -234,10 +234,10 @@ public abstract class BaseLauncherActivity extends BaseActivity { } System.out.println("call to onResumeFragments; E"); } - public String getFileName(Uri uri) { + public static String getFileName(Context ctx, Uri uri) { String result = null; if (uri.getScheme().equals("content")) { - Cursor cursor = getContentResolver().query(uri, null, null, null, null); + Cursor cursor = ctx.getContentResolver().query(uri, null, null, null, null); try { if (cursor != null && cursor.moveToFirst()) { result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); @@ -268,9 +268,11 @@ public abstract class BaseLauncherActivity extends BaseActivity { barrier.show(); Thread t = new Thread(()->{ try { - MultiRTUtils.installRuntimeNamed(getContentResolver().openInputStream(uri), getFileName(uri), + String name = getFileName(this,uri); + MultiRTUtils.installRuntimeNamed(getContentResolver().openInputStream(uri), name, (resid, stuff) -> BaseLauncherActivity.this.runOnUiThread( () -> barrier.setMessage(BaseLauncherActivity.this.getString(resid,stuff)))); + MultiRTUtils.postPrepare(BaseLauncherActivity.this, name); }catch (IOException e) { Tools.showError(BaseLauncherActivity.this ,e); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java index 6265794ed..136ff644d 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java @@ -20,6 +20,7 @@ import java.nio.ByteBuffer; import java.nio.FloatBuffer; import java.util.*; import net.kdt.pojavlaunch.customcontrols.*; +import net.kdt.pojavlaunch.multirt.MultiRTUtils; import net.kdt.pojavlaunch.prefs.*; import net.kdt.pojavlaunch.utils.*; import net.kdt.pojavlaunch.value.*; @@ -128,7 +129,8 @@ public class BaseMainActivity extends LoggableActivity { try { // FIXME: is it safe fot multi thread? GLOBAL_CLIPBOARD = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); - + + MultiRTUtils.setRuntimeNamed(this,LauncherPreferences.PREF_DEFAULT_RUNTIME); logFile = new File(Tools.DIR_GAME_HOME, "latestlog.txt"); logFile.delete(); logFile.createNewFile(); 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 a57db0ba1..77308e4da 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/JavaGUILauncherActivity.java @@ -9,6 +9,8 @@ import android.widget.*; import java.io.*; import java.util.*; + +import net.kdt.pojavlaunch.multirt.MultiRTUtils; import net.kdt.pojavlaunch.prefs.*; import net.kdt.pojavlaunch.utils.*; import org.lwjgl.glfw.*; @@ -63,11 +65,13 @@ public class JavaGUILauncherActivity extends LoggableActivity implements View.On @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setContentView(R.layout.install_mod); Tools.updateWindowSize(this); try { + MultiRTUtils.setRuntimeNamed(this,LauncherPreferences.PREF_DEFAULT_RUNTIME); gestureDetector = new GestureDetector(this, new SingleTapConfirm()); findViewById(R.id.installmod_mouse_pri).setOnTouchListener(this); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavApplication.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavApplication.java index a16efaded..98a3ec4db 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavApplication.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavApplication.java @@ -55,7 +55,7 @@ public class PojavApplication extends Application Tools.APP_NAME = getResources().getString(R.string.app_short_name); Tools.DIR_DATA = getDir("files", MODE_PRIVATE).getParent(); - Tools.DIR_HOME_JRE = Tools.DIR_DATA + "/jre_runtime".replace("/data/user/0", "/data/data"); + //Tools.DIR_HOME_JRE = Tools.DIR_DATA + "/jre_runtime".replace("/data/user/0", "/data/data"); Tools.DIR_ACCOUNT_OLD = Tools.DIR_DATA + "/Users"; Tools.DIR_ACCOUNT_NEW = Tools.DIR_DATA + "/accounts"; // Tools.FILE_ACCOUNT_JSON = getFilesDir().getAbsolutePath() + "/account_profiles.json"; diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java index bf5202cc2..81d68df76 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavLoginActivity.java @@ -2,7 +2,10 @@ package net.kdt.pojavlaunch; import android.Manifest; import android.annotation.SuppressLint; +import android.app.Activity; import android.app.Dialog; +import android.app.ProgressDialog; +import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; @@ -40,6 +43,7 @@ import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; @@ -62,6 +66,8 @@ import net.kdt.pojavlaunch.authenticator.mojang.LoginTask; import net.kdt.pojavlaunch.authenticator.mojang.RefreshListener; import net.kdt.pojavlaunch.customcontrols.ControlData; import net.kdt.pojavlaunch.customcontrols.CustomControls; +import net.kdt.pojavlaunch.multirt.MultiRTConfigDialog; +import net.kdt.pojavlaunch.multirt.MultiRTUtils; import net.kdt.pojavlaunch.prefs.LauncherPreferences; import net.kdt.pojavlaunch.utils.JREUtils; import net.kdt.pojavlaunch.utils.LocaleUtils; @@ -278,17 +284,6 @@ public class PojavLoginActivity extends BaseActivity PojavProfile.setCurrentProfile(this, null); } - private boolean isJavaRuntimeInstalled(AssetManager am) { - boolean prefValue = firstLaunchPrefs.getBoolean(PREF_IS_INSTALLED_JAVARUNTIME, false); - try { - return prefValue && ( - am.open("components/jre/bin-" + Tools.CURRENT_ARCHITECTURE.split("/")[0] + ".tar.xz") == null || - Tools.read(new FileInputStream(Tools.DIR_HOME_JRE+"/version")).equals(Tools.read(am.open("components/jre/version")))); - } catch(IOException e) { - Log.e("JVMCtl","failed to read file",e); - return prefValue; - } - } private void unpackComponent(AssetManager am, String component) throws IOException { File versionFile = new File(Tools.DIR_GAME_HOME + "/" + component + "/version"); @@ -368,206 +363,67 @@ public class PojavLoginActivity extends BaseActivity unpackComponent(am, "caciocavallo"); unpackComponent(am, "lwjgl3"); - if (!isJavaRuntimeInstalled(am)) { - if(!installRuntimeAutomatically(am)) { - File jreTarFile = selectJreTarFile(); - uncompressTarXZ(jreTarFile, new File(Tools.DIR_HOME_JRE)); - } else { - Tools.copyAssetFile(this, "components/jre/version", Tools.DIR_HOME_JRE + "/","version", true); + if(!installRuntimeAutomatically(am,MultiRTUtils.getRuntimes().size() > 0)) { + MultiRTConfigDialog.openRuntimeSelector(this, MultiRTConfigDialog.MULTIRT_PICK_RUNTIME_STARTUP); + synchronized (mLockSelectJRE) { + mLockSelectJRE.wait(); } - firstLaunchPrefs.edit().putBoolean(PREF_IS_INSTALLED_JAVARUNTIME, true).commit(); } - - JREUtils.relocateLibPath(this); - - File ftIn = new File(Tools.DIR_HOME_JRE, Tools.DIRNAME_HOME_JRE + "/libfreetype.so.6"); - File ftOut = new File(Tools.DIR_HOME_JRE, Tools.DIRNAME_HOME_JRE + "/libfreetype.so"); - if (ftIn.exists() && (!ftOut.exists() || ftIn.length() != ftOut.length())) { - ftIn.renameTo(ftOut); - } - - // Refresh libraries - copyDummyNativeLib("libawt_xawt.so"); - // copyDummyNativeLib("libfontconfig.so"); } catch(Throwable e){ Tools.showError(this, e); } } - - private boolean installRuntimeAutomatically(AssetManager am) { + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if(requestCode == MultiRTConfigDialog.MULTIRT_PICK_RUNTIME_STARTUP && resultCode == Activity.RESULT_OK) { + if (data != null) { + final Uri uri = data.getData(); + Thread t = new Thread(()->{ + try { + MultiRTUtils.installRuntimeNamed(getContentResolver().openInputStream(uri), BaseLauncherActivity.getFileName(this,uri), + (resid, stuff) ->PojavLoginActivity.this.runOnUiThread( + () -> startupTextView.setText(PojavLoginActivity.this.getString(resid,stuff)))); + synchronized (mLockSelectJRE) { + mLockSelectJRE.notifyAll(); + } + }catch (IOException e) { + Tools.showError(PojavLoginActivity.this + ,e); + } + }); + t.start(); + } + } + } + private boolean installRuntimeAutomatically(AssetManager am, boolean otherRuntimesAvailable) { + /* Check if JRE is included */ + String rt_version = null; + String current_rt_version = MultiRTUtils.__internal__readBinpackVersion("Internal"); try { - am.open("components/jre/version"); + rt_version = Tools.read(am.open("components/jre/version")); } catch (IOException e) { Log.e("JREAuto", "JRE was not included on this APK.", e); - return false; } - - File rtUniversal = new File(Tools.DIR_HOME_JRE+"/universal.tar.xz"); - File rtPlatformDependent = new File(Tools.DIR_HOME_JRE+"/cust-bin.tar.xz"); - if(!new File(Tools.DIR_HOME_JRE).exists()) new File(Tools.DIR_HOME_JRE).mkdirs(); else { - //SANITY: remove the existing files - for (File f : new File(Tools.DIR_HOME_JRE).listFiles()) { - if (f.isDirectory()){ - try { - FileUtils.deleteDirectory(f); - } catch(IOException e1) { - Log.e("JREAuto","da fuq is wrong wit ur device? n2",e1); - } - } else{ - f.delete(); - } + if(current_rt_version == null && otherRuntimesAvailable) return true; //Assume user maintains his own runtime + if(rt_version == null) return false; + if(!current_rt_version.equals(rt_version)) { //If we already have an integrated one installed, check if it's up-to-date + try { + MultiRTUtils.installRuntimeNamedBinpack(am.open("components/jre/universal.tar.xz"), am.open("components/jre/bin-" + Tools.CURRENT_ARCHITECTURE.split("/")[0] + ".tar.xz"), "Internal", rt_version, + (resid, vararg) -> { + runOnUiThread(()->{startupTextView.setText(getString(resid,vararg));}); + }); + MultiRTUtils.postPrepare(PojavLoginActivity.this,"Internal"); + return true; + }catch (IOException e) { + Log.e("JREAuto", "Internal JRE unpack failed", e); + return false; } - } - InputStream is; - FileOutputStream os; - try { - is = am.open("components/jre/universal.tar.xz"); - os = new FileOutputStream(rtUniversal); - IOUtils.copy(is,os); - is.close(); - os.close(); - uncompressTarXZ(rtUniversal, new File(Tools.DIR_HOME_JRE)); - } catch (IOException e){ - Log.e("JREAuto","Failed to unpack universal. Custom embedded-less build?",e); - return false; - } - try { - is = am.open("components/jre/bin-" + Tools.CURRENT_ARCHITECTURE.split("/")[0] + ".tar.xz"); - os = new FileOutputStream(rtPlatformDependent); - IOUtils.copy(is, os); - is.close(); - os.close(); - uncompressTarXZ(rtPlatformDependent, new File(Tools.DIR_HOME_JRE)); - } catch (IOException e) { - // Something's very wrong, or user's using an unsupported arch (MIPS phone? ARMv6 phone?), - // in both cases, redirecting to manual install, and removing the universal stuff - for (File f : new File(Tools.DIR_HOME_JRE).listFiles()) { - if (f.isDirectory()){ - try { - FileUtils.deleteDirectory(f); - } catch(IOException e1) { - Log.e("JREAuto","da fuq is wrong wit ur device?",e1); - } - } else{ - f.delete(); - } - } - return false; - } - return true; - } - private void copyDummyNativeLib(String name) throws Throwable { - File fileLib = new File(Tools.DIR_HOME_JRE, Tools.DIRNAME_HOME_JRE + "/" + name); - fileLib.delete(); - FileInputStream is = new FileInputStream(new File(getApplicationInfo().nativeLibraryDir, name)); - FileOutputStream os = new FileOutputStream(fileLib); - IOUtils.copy(is, os); - is.close(); - os.close(); - } - - private File selectJreTarFile() throws InterruptedException { - final StringBuilder selectedFile = new StringBuilder(); - - runOnUiThread(new Runnable() { - @Override - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(PojavLoginActivity.this); - builder.setTitle(getString(R.string.alerttitle_install_jre, Tools.CURRENT_ARCHITECTURE)); - builder.setCancelable(false); - - final AlertDialog dialog = builder.create(); - FileListView flv = new FileListView(dialog, "tar.xz"); - flv.setFileSelectedListener(new FileSelectedListener(){ - - @Override - public void onFileSelected(File file, String path) { - selectedFile.append(path); - dialog.dismiss(); - - synchronized (mLockSelectJRE) { - mLockSelectJRE.notifyAll(); - } - - } - }); - dialog.setView(flv); - dialog.show(); - } - }); - - synchronized (mLockSelectJRE) { - mLockSelectJRE.wait(); - } - - return new File(selectedFile.toString()); + }else return true; // we have at least one runtime, and it's compartible, good to go } - private void uncompressTarXZ(final File tarFile, final File dest) throws IOException { - - dest.mkdirs(); - TarArchiveInputStream tarIn = null; - - tarIn = new TarArchiveInputStream( - new XZCompressorInputStream( - new BufferedInputStream( - new FileInputStream(tarFile) - ) - ) - ); - - TarArchiveEntry tarEntry = tarIn.getNextTarEntry(); - // tarIn is a TarArchiveInputStream - while (tarEntry != null) { - /* - * Unpacking very small files in short time cause - * application to ANR or out of memory, so delay - * a little if size is below than 20kb (20480 bytes) - */ - if (tarEntry.getSize() <= 20480) { - try { - // 40 small files per second - Thread.sleep(25); - } catch (InterruptedException e) {} - } - final String tarEntryName = tarEntry.getName(); - runOnUiThread(new Runnable(){ - @SuppressLint("StringFormatInvalid") - @Override - public void run() { - startupTextView.setText(getString(R.string.global_unpacking, tarEntryName)); - } - }); - // publishProgress(null, "Unpacking " + tarEntry.getName()); - File destPath = new File(dest, tarEntry.getName()); - if (tarEntry.isSymbolicLink()) { - destPath.getParentFile().mkdirs(); - try { - // android.system.Os - // Libcore one support all Android versions - Os.symlink(tarEntry.getName(), tarEntry.getLinkName()); - } catch (Throwable e) { - e.printStackTrace(); - } - - } else if (tarEntry.isDirectory()) { - destPath.mkdirs(); - destPath.setExecutable(true); - } else if (!destPath.exists() || destPath.length() != tarEntry.getSize()) { - destPath.getParentFile().mkdirs(); - destPath.createNewFile(); - - FileOutputStream os = new FileOutputStream(destPath); - IOUtils.copy(tarIn, os); - os.close(); - - } - tarEntry = tarIn.getNextTarEntry(); - } - tarIn.close(); - } - private static boolean mkdirs(String path) { File file = new File(path); 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 d1e9c1469..9ebe061e2 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 @@ -1,5 +1,6 @@ package net.kdt.pojavlaunch.multirt; +import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; @@ -13,7 +14,7 @@ import net.kdt.pojavlaunch.R; public class MultiRTConfigDialog { public static final int MULTIRT_PICK_RUNTIME = 2048; - public static final int MULTIRT_PICK_RUNTIME_NORETURN = 2049; + public static final int MULTIRT_PICK_RUNTIME_STARTUP = 2049; public AlertDialog dialog; public RecyclerView dialogView; public void prepare(BaseLauncherActivity ctx) { @@ -29,10 +30,7 @@ public class MultiRTConfigDialog { @Override public void onClick(DialogInterface dialog, int which) { /* Initialte import */ - Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); - intent.addCategory(Intent.CATEGORY_OPENABLE); - intent.setType("application/x-xz"); - ctx.startActivityForResult(intent,MULTIRT_PICK_RUNTIME); + openRuntimeSelector(ctx,MULTIRT_PICK_RUNTIME); } }); builder.setNegativeButton(R.string.mcn_exit_call, new DialogInterface.OnClickListener() { @@ -46,4 +44,10 @@ public class MultiRTConfigDialog { public void refresh() { dialogView.getAdapter().notifyDataSetChanged(); } + public static void openRuntimeSelector(Activity ctx, int code) { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("application/x-xz"); + ctx.startActivityForResult(intent,code); + } } 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 cde36117c..a9f54c4b8 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,11 +1,14 @@ package net.kdt.pojavlaunch.multirt; import android.annotation.SuppressLint; +import android.content.Context; import android.system.Os; import android.util.Log; +import net.kdt.pojavlaunch.PojavLoginActivity; import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.Tools; +import net.kdt.pojavlaunch.utils.JREUtils; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; @@ -31,6 +34,7 @@ public class MultiRTUtils { } public String name; public String versionString; + public String arch; public int javaVersion; } public static interface ProgressReporterThingy { @@ -38,6 +42,7 @@ public class MultiRTUtils { } private static File runtimeFolder = new File(Tools.MULTIRT_HOME); private static final String JAVA_VERSION_str = "JAVA_VERSION=\""; + private static final String OS_ARCH_str = "OS_ARCH=\""; public static List getRuntimes() { ArrayList ret = new ArrayList<>(); System.out.println("Fetch runtime list"); @@ -61,6 +66,67 @@ public class MultiRTUtils { tmp.delete(); return read(name); } + private static void __installRuntimeNamed__NoRM(InputStream runtimeInputStream, File dest, ProgressReporterThingy thingy) throws IOException { + File tmp = new File(dest,"temporary"); + FileOutputStream fos = new FileOutputStream(tmp); + thingy.reportStringProgress(R.string.multirt_progress_caching); + IOUtils.copy(runtimeInputStream,fos); + fos.close(); + runtimeInputStream.close(); + uncompressTarXZ(tmp,dest,thingy); + tmp.delete(); + } + public static void postPrepare(Context ctx, String name) throws IOException { + File dest = new File(runtimeFolder,"/"+name); + if(!dest.exists()) return; + Runtime r = read(name); + String libFolder = "lib"; + if(new File(dest,libFolder+"/"+r.arch).exists()) libFolder = libFolder+"/"+r.arch; + File ftIn = new File(dest, libFolder+ "/libfreetype.so.6"); + File ftOut = new File(dest, libFolder + "/libfreetype.so"); + if (ftIn.exists() && (!ftOut.exists() || ftIn.length() != ftOut.length())) { + ftIn.renameTo(ftOut); + } + + // Refresh libraries + copyDummyNativeLib(ctx,"libawt_xawt.so",libFolder); + } + private static void copyDummyNativeLib(Context ctx, String name, String libFolder) throws IOException { + + File fileLib = new File(MultiRTUtils.runtimeFolder, name+"/"+libFolder + "/" + name); + fileLib.delete(); + FileInputStream is = new FileInputStream(new File(ctx.getApplicationInfo().nativeLibraryDir, name)); + FileOutputStream os = new FileOutputStream(fileLib); + IOUtils.copy(is, os); + is.close(); + os.close(); + } + public static Runtime installRuntimeNamedBinpack(InputStream universalFileInputStream, InputStream platformBinsInputStream, String name, String binpackVersion, ProgressReporterThingy thingy) throws IOException { + File dest = new File(runtimeFolder,"/"+name); + if(dest.exists()) FileUtils.deleteDirectory(dest); + dest.mkdirs(); + __installRuntimeNamed__NoRM(universalFileInputStream,dest,thingy); + __installRuntimeNamed__NoRM(platformBinsInputStream,dest,thingy); + File binpack_verfile = new File(runtimeFolder,"/"+name+"/pojav_version"); + FileOutputStream fos = new FileOutputStream(binpack_verfile); + fos.write(binpackVersion.getBytes()); + fos.close(); + cache.remove(name); // Force reread + return read(name); + } + public static String __internal__readBinpackVersion(String name) { + File binpack_verfile = new File(runtimeFolder,"/"+name+"/pojav_version"); + try { + if (binpack_verfile.exists()) { + return Tools.read(binpack_verfile.getAbsolutePath()); + }else{ + return null; + } + }catch (IOException e) { + e.printStackTrace(); + return null; + } + } public static void removeRuntimeNamed(String name) throws IOException { File dest = new File(runtimeFolder,"/"+name); if(dest.exists()) { @@ -68,18 +134,27 @@ public class MultiRTUtils { cache.remove(name); } } + public static boolean setRuntimeNamed(Context ctx, String name) throws IOException { + File dest = new File(runtimeFolder,"/"+name); + if(!dest.exists()) return false; + Tools.DIR_HOME_JRE = dest.getAbsolutePath(); + JREUtils.relocateLibPath(ctx); + return true; + } private static Runtime read(String name) { if(cache.containsKey(name)) return cache.get(name); Runtime retur; File release = new File(runtimeFolder,"/"+name+"/release"); if(!release.exists()) { - return null; + return new Runtime(name); } try { String content = Tools.read(release.getAbsolutePath()); int _JAVA_VERSION_index = content.indexOf(JAVA_VERSION_str); - if(_JAVA_VERSION_index != -1) { + int _OS_ARCH_index = content.indexOf(OS_ARCH_str); + if(_JAVA_VERSION_index != -1 && _OS_ARCH_index != -1) { _JAVA_VERSION_index += JAVA_VERSION_str.length(); + _OS_ARCH_index += OS_ARCH_str.length(); String javaVersion = content.substring(_JAVA_VERSION_index,content.indexOf('"',_JAVA_VERSION_index)); String[] javaVersionSplit = javaVersion.split("\\."); int javaVersionInt; @@ -89,6 +164,7 @@ public class MultiRTUtils { javaVersionInt = Integer.parseInt(javaVersionSplit[0]); } Runtime r = new Runtime(name); + r.arch = content.substring(_OS_ARCH_index,content.indexOf('"',_OS_ARCH_index)); r.javaVersion = javaVersionInt; r.versionString = javaVersion; retur = r; 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 34f11796e..96dfeafbb 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 @@ -7,6 +7,7 @@ import android.graphics.Color; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; @@ -15,6 +16,7 @@ import androidx.recyclerview.widget.RecyclerView; import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.Tools; +import net.kdt.pojavlaunch.prefs.LauncherPreferences; import java.io.IOException; import java.util.List; @@ -34,9 +36,11 @@ public class RTRecyclerViewAdapter extends RecyclerView.Adapter { @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { final List runtimes = MultiRTUtils.getRuntimes(); - ((RTViewHolder)holder).bindRuntime(runtimes.get(position)); + ((RTViewHolder)holder).bindRuntime(runtimes.get(position),position); + } + public boolean isDefaultRuntime(MultiRTUtils.Runtime rt) { + return LauncherPreferences.PREF_DEFAULT_RUNTIME.equals(rt.name); } - @Override public int getItemCount() { return MultiRTUtils.getRuntimes().size(); @@ -45,52 +49,69 @@ public class RTRecyclerViewAdapter extends RecyclerView.Adapter { final TextView javaVersionView; final TextView fullJavaVersionView; final ColorStateList defaultColors; + final Button setDefaultButton; final Context ctx; MultiRTUtils.Runtime currentRuntime; + int currentPosition; public RTViewHolder(View itemView) { super(itemView); javaVersionView = itemView.findViewById(R.id.multirt_view_java_version); fullJavaVersionView = itemView.findViewById(R.id.multirt_view_java_version_full); itemView.findViewById(R.id.multirt_view_removebtn).setOnClickListener(this); + setDefaultButton = itemView.findViewById(R.id.multirt_view_setdefaultbtn); + setDefaultButton.setOnClickListener(this); defaultColors = fullJavaVersionView.getTextColors(); ctx = itemView.getContext(); } - public void bindRuntime(MultiRTUtils.Runtime rt) { + public void bindRuntime(MultiRTUtils.Runtime rt, int pos) { currentRuntime = rt; + currentPosition = pos; if(rt.versionString != null) { javaVersionView.setText(ctx.getString(R.string.multirt_java_ver, rt.name, rt.javaVersion)); fullJavaVersionView.setText(rt.versionString); fullJavaVersionView.setTextColor(defaultColors); - + setDefaultButton.setVisibility(View.VISIBLE); + boolean default_ = isDefaultRuntime(rt); + setDefaultButton.setEnabled(!default_); + setDefaultButton.setText(default_?R.string.multirt_config_setdefault_already:R.string.multirt_config_setdefault); }else{ javaVersionView.setText(rt.name); fullJavaVersionView.setText(R.string.multirt_runtime_corrupt); fullJavaVersionView.setTextColor(Color.RED); + setDefaultButton.setVisibility(View.GONE); } } @Override public void onClick(View v) { + if(v.getId() == R.id.multirt_view_removebtn) { if (currentRuntime != null) { final ProgressDialog barrier = new ProgressDialog(ctx); barrier.setMessage(ctx.getString(R.string.global_waiting)); barrier.setProgressStyle(barrier.STYLE_SPINNER); barrier.setCancelable(false); barrier.show(); - Thread t = new Thread(()->{ + Thread t = new Thread(() -> { try { MultiRTUtils.removeRuntimeNamed(currentRuntime.name); - }catch (IOException e) { - Tools.showError(itemView.getContext(),e); + } catch (IOException e) { + Tools.showError(itemView.getContext(), e); } - v.post(() ->{ + v.post(() -> { barrier.dismiss(); - RTRecyclerViewAdapter.this.notifyDataSetChanged(); + RTRecyclerViewAdapter.this.notifyItemRemoved(currentPosition); dialog.dialog.show(); }); }); t.start(); } + }else if(v.getId() == R.id.multirt_view_setdefaultbtn) { + if(currentRuntime != null) { + LauncherPreferences.PREF_DEFAULT_RUNTIME = currentRuntime.name; + LauncherPreferences.DEFAULT_PREF.edit().putString("defaultRuntime",LauncherPreferences.PREF_DEFAULT_RUNTIME).apply(); + RTRecyclerViewAdapter.this.notifyDataSetChanged(); + } + } } } } 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 3eaf74333..c141dff71 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 @@ -2,6 +2,7 @@ package net.kdt.pojavlaunch.prefs; import android.content.*; import net.kdt.pojavlaunch.*; +import net.kdt.pojavlaunch.multirt.MultiRTUtils; public class LauncherPreferences { @@ -29,6 +30,7 @@ public class LauncherPreferences public static boolean PREF_DISABLE_GESTURES = false; public static float PREF_MOUSESPEED = 1f; public static int PREF_RAM_ALLOCATION=300; + public static String PREF_DEFAULT_RUNTIME; public static void loadPreferences() { PREF_RENDERER = DEFAULT_PREF.getString("renderer", "opengles2"); PREF_BUTTONSIZE = DEFAULT_PREF.getInt("buttonscale", 100); @@ -108,5 +110,11 @@ public class LauncherPreferences PREF_CUSTOM_JAVA_ARGS.replace(arg, "")).commit(); } } + if(DEFAULT_PREF.contains("defaultRuntime")) { + PREF_DEFAULT_RUNTIME = DEFAULT_PREF.getString("defaultRuntime",""); + }else{ + PREF_DEFAULT_RUNTIME = MultiRTUtils.getRuntimes().get(0).name; + LauncherPreferences.DEFAULT_PREF.edit().putString("defaultRuntime",LauncherPreferences.PREF_DEFAULT_RUNTIME).apply(); + } } } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/UninstallJREDialogPreference.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/UninstallJREDialogPreference.java deleted file mode 100644 index cf43300d9..000000000 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/UninstallJREDialogPreference.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.kdt.pojavlaunch.prefs; - -import android.content.*; -import androidx.appcompat.app.*; -import androidx.preference.*; -import android.util.*; -import android.widget.*; -import java.io.*; -import net.kdt.pojavlaunch.*; - -import net.kdt.pojavlaunch.R; -import org.apache.commons.io.*; - -public class UninstallJREDialogPreference extends Preference implements DialogInterface.OnClickListener -{ - private AlertDialog mDialog; - public UninstallJREDialogPreference(Context ctx) { - this(ctx, null); - } - - public UninstallJREDialogPreference(Context ctx, AttributeSet attrs) { - super(ctx, attrs); - setPersistent(false); - - AlertDialog.Builder dialog = new AlertDialog.Builder(getContext()); - dialog.setMessage(R.string.mcl_setting_title_uninstalljre); - dialog.setPositiveButton(android.R.string.ok, this); - dialog.setNegativeButton(android.R.string.cancel, this); - mDialog = dialog.create(); - } - - @Override - protected void onClick() { - super.onClick(); - mDialog.show(); - } - - @Override - public void onClick(DialogInterface dialog, int which) { - if (which == DialogInterface.BUTTON_POSITIVE) { - try { - FileUtils.deleteDirectory(new File(Tools.DIR_HOME_JRE)); - - getContext().getSharedPreferences("pojav_extract", Context.MODE_PRIVATE) - .edit().putBoolean(PojavLoginActivity.PREF_IS_INSTALLED_JAVARUNTIME, false).commit(); - - Toast.makeText(getContext(), R.string.toast_uninstalljre_done, Toast.LENGTH_SHORT).show(); - } catch (IOException e) { - Tools.showError(getContext(), e); - } - } - } -} diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java index 4de79d9ad..abd31e295 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java @@ -168,7 +168,7 @@ public class JREUtils Log.i("jrelog-logcat","Logcat thread started"); } - public static void relocateLibPath(final Context ctx) throws Exception { + public static void relocateLibPath(final Context ctx) throws IOException { if (JRE_ARCHITECTURE == null) { JRE_ARCHITECTURE = readJREReleaseProperties().get("OS_ARCH"); if (JRE_ARCHITECTURE.startsWith("i") && JRE_ARCHITECTURE.endsWith("86") && Tools.CURRENT_ARCHITECTURE.contains("x86") && !Tools.CURRENT_ARCHITECTURE.contains("64")) { diff --git a/app_pojavlauncher/src/main/res/layout/multirt_recyclable_view.xml b/app_pojavlauncher/src/main/res/layout/multirt_recyclable_view.xml index d600bd198..168db968d 100644 --- a/app_pojavlauncher/src/main/res/layout/multirt_recyclable_view.xml +++ b/app_pojavlauncher/src/main/res/layout/multirt_recyclable_view.xml @@ -39,4 +39,14 @@ app:layout_constraintTop_toTopOf="@+id/multirt_view_java_version" app:srcCompat="@drawable/ic_remove" /> +