diff --git a/app/build.gradle b/app/build.gradle index c60a7c6..36564db 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,8 +15,8 @@ android { applicationId "com.vectras.vm" minSdk minApi targetSdk targetApi - versionCode 68 - versionName "3.6.4" + versionCode 69 + versionName "3.6.5" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled true diff --git a/app/src/main/java/com/vectras/qemu/MainSettingsManager.java b/app/src/main/java/com/vectras/qemu/MainSettingsManager.java index 5cd262d..b2741a6 100644 --- a/app/src/main/java/com/vectras/qemu/MainSettingsManager.java +++ b/app/src/main/java/com/vectras/qemu/MainSettingsManager.java @@ -9,6 +9,8 @@ import android.content.res.Configuration; import android.os.Bundle; import android.os.Environment; import android.os.Handler; +import android.text.InputFilter; +import android.text.InputType; import android.util.Log; import androidx.preference.PreferenceManager; @@ -424,6 +426,13 @@ public class MainSettingsManager extends AppCompatActivity EditTextPreference memory = findPreference("memory"); assert memory != null; + memory.setOnBindEditTextListener(editText -> { + editText.setInputType(InputType.TYPE_CLASS_NUMBER); + editText.setFilters(new InputFilter[]{ + new InputFilter.LengthFilter(4) + }); + }); + if (!customMemory.isChecked()) { memory.setEnabled(false); } diff --git a/app/src/main/java/com/vectras/qemu/utils/RamInfo.java b/app/src/main/java/com/vectras/qemu/utils/RamInfo.java index ebdb6e0..d43940a 100644 --- a/app/src/main/java/com/vectras/qemu/utils/RamInfo.java +++ b/app/src/main/java/com/vectras/qemu/utils/RamInfo.java @@ -8,6 +8,7 @@ import android.content.SharedPreferences; import android.preference.PreferenceManager; import com.vectras.qemu.MainSettingsManager; +import com.vectras.vm.utils.TextUtils; public class RamInfo { public static Activity activity; @@ -29,7 +30,7 @@ public class RamInfo { int freeRamInt = safeLongToInt(freeMem); int totalRamInt = safeLongToInt(totalMem); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity); - if (prefs.getBoolean("customMemory", false)) { + if (prefs.getBoolean("customMemory", false) && TextUtils.isNumberOnly(prefs.getString("memory", String.valueOf(256)))) { return Integer.parseInt(prefs.getString("memory", String.valueOf(256))); } else { return freeRamInt - 100; diff --git a/app/src/main/java/com/vectras/vm/Fragment/ControlersOptionsFragment.java b/app/src/main/java/com/vectras/vm/Fragment/ControlersOptionsFragment.java index cf8d93d..8c238be 100644 --- a/app/src/main/java/com/vectras/vm/Fragment/ControlersOptionsFragment.java +++ b/app/src/main/java/com/vectras/vm/Fragment/ControlersOptionsFragment.java @@ -27,8 +27,8 @@ public class ControlersOptionsFragment extends DialogFragment { public void onClick(View v) { MainSettingsManager.setControlMode(getActivity(), "G"); if (MainSettingsManager.getVmUi(getActivity()).equals("X11")) { - X11Activity.desktop.setVisibility(View.GONE); - X11Activity.gamepad.setVisibility(View.VISIBLE); + if (X11Activity.desktop != null ) X11Activity.desktop.setVisibility(View.GONE); + if (X11Activity.gamepad != null ) X11Activity.gamepad.setVisibility(View.VISIBLE); } else if (MainSettingsManager.getVmUi(getActivity()).equals("VNC")) { MainVNCActivity.desktop.setVisibility(View.GONE); MainVNCActivity.gamepad.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/com/vectras/vm/VMCreatorActivity.java b/app/src/main/java/com/vectras/vm/VMCreatorActivity.java index 8e11460..2dca1e0 100644 --- a/app/src/main/java/com/vectras/vm/VMCreatorActivity.java +++ b/app/src/main/java/com/vectras/vm/VMCreatorActivity.java @@ -3,7 +3,6 @@ package com.vectras.vm; import android.annotation.SuppressLint; import android.content.ComponentName; import android.content.Intent; -import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.text.Editable; @@ -35,7 +34,6 @@ import com.vectras.vm.utils.DeviceUtils; import com.vectras.vm.utils.DialogUtils; import com.vectras.vm.utils.FileUtils; import com.vectras.vm.utils.ImageUtils; -import com.vectras.vm.utils.JSONUtils; import com.vectras.vm.utils.PackageUtils; import com.vectras.vm.utils.UIUtils; @@ -219,19 +217,13 @@ public class VMCreatorActivity extends AppCompatActivity { created = true; binding.addRomBtn.setText(R.string.save_changes); - if (binding != null && current.itemName != null) { - binding.title.setText(current.itemName); + if (binding != null && current != null) { + if (current.itemName != null) binding.title.setText(current.itemName); + if (current.itemPath != null) binding.drive.setText(current.itemPath); + if (current.imgCdrom != null) binding.cdrom.setText(current.imgCdrom); + if (current.itemIcon != null) thumbnailPath = current.itemIcon; } - if (binding != null && current.itemPath != null) { - binding.drive.setText(current.itemPath); - } - - if (binding != null && current.imgCdrom != null) { - binding.cdrom.setText(current.imgCdrom); - } - - thumbnailPath = current.itemIcon; vmID = getIntent().getStringExtra("VMID"); if (vmID == null || vmID.isEmpty()) { @@ -669,13 +661,17 @@ public class VMCreatorActivity extends AppCompatActivity { private void selectedDiskFile(Uri _content_describer, boolean _addtodrive) { if (FileUtils.isValidFilePath(this, FileUtils.getPath(this, _content_describer), false)) { - File selectedFilePath = new File(getPath(_content_describer)); - if (VMManager.isADiskFile(selectedFilePath.getPath())) { - startProcessingHardDriveFile(_content_describer, _addtodrive); - } else { - DialogUtils.twoDialog(this, getString(R.string.problem_has_been_detected), getString(R.string.file_format_is_not_supported), getResources().getString(R.string.continuetext), getResources().getString(R.string.cancel), true, R.drawable.hard_drive_24px, true, - () -> startProcessingHardDriveFile(_content_describer, _addtodrive), null, null); - } + new Thread(() -> { + File selectedFilePath = new File(getPath(_content_describer)); + runOnUiThread(() -> { + if (VMManager.isADiskFile(selectedFilePath.getPath())) { + startProcessingHardDriveFile(_content_describer, _addtodrive); + } else { + DialogUtils.twoDialog(this, getString(R.string.problem_has_been_detected), getString(R.string.file_format_is_not_supported), getResources().getString(R.string.continuetext), getResources().getString(R.string.cancel), true, R.drawable.hard_drive_24px, true, + () -> startProcessingHardDriveFile(_content_describer, _addtodrive), null, null); + } + }); + }).start(); } else { startProcessingHardDriveFile(_content_describer, _addtodrive); } diff --git a/app/src/main/java/com/vectras/vm/VMManager.java b/app/src/main/java/com/vectras/vm/VMManager.java index 29c0502..0aab4f3 100644 --- a/app/src/main/java/com/vectras/vm/VMManager.java +++ b/app/src/main/java/com/vectras/vm/VMManager.java @@ -79,6 +79,8 @@ public class VMManager { ArrayList> vmList = new Gson().fromJson(vmJsonListContent, new TypeToken>>() { }.getType()); + if (vmList == null) return false; + for (int _repeat = 0; _repeat < vmList.size(); _repeat++) { if (vmList.get(_repeat).containsKey("vmID") && Objects.requireNonNull(vmList.get(_repeat).get("vmID")).toString().equals(vmId)) { @@ -97,6 +99,9 @@ public class VMManager { ArrayList> vmList = new Gson().fromJson(vmListJson, new TypeToken>>() { }.getType()); + + if (vmList == null) return false; + HashMap vmConfigMap = new Gson().fromJson(vmConfigJson, new TypeToken>() { }.getType()); @@ -117,6 +122,8 @@ public class VMManager { ArrayList> vmList = new Gson().fromJson(vmListJson, new TypeToken>>() { }.getType()); + if (vmList == null) return false; + if (!vmID.isEmpty()) { generatedVMId = vmID; vmConfigMap.put("vmID", generatedVMId); @@ -134,6 +141,9 @@ public class VMManager { int finalPosition = postion; ArrayList> vmList = new Gson().fromJson(vmListJson, new TypeToken>>() { }.getType()); + + if (vmList == null) return false; + HashMap vmConfigMap = new Gson().fromJson(vmConfigJson, new TypeToken>() { }.getType()); @@ -165,6 +175,8 @@ public class VMManager { ArrayList> vmList = new Gson().fromJson(vmListJson, new TypeToken>>() { }.getType()); + if (vmList == null) return false; + if (postion == -1) { for (int _repeat = 0; _repeat < vmList.size(); _repeat++) { if (vmList.get(_repeat).containsKey("vmID") diff --git a/app/src/main/java/com/vectras/vm/logger/LogItem.java b/app/src/main/java/com/vectras/vm/logger/LogItem.java index 35da020..7885d2d 100644 --- a/app/src/main/java/com/vectras/vm/logger/LogItem.java +++ b/app/src/main/java/com/vectras/vm/logger/LogItem.java @@ -9,19 +9,29 @@ import android.os.Parcel; import android.os.Parcelable; import com.vectras.vm.R; + import android.content.Context; + import java.util.Locale; import java.util.UnknownFormatConversionException; import java.util.FormatFlagsConversionMismatchException; + import android.annotation.SuppressLint; + import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; + import android.content.pm.PackageManager; + import java.io.ByteArrayInputStream; + import android.content.pm.Signature; + import java.security.MessageDigest; import java.util.Arrays; + import android.content.pm.PackageInfo; + import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; @@ -29,33 +39,33 @@ import java.security.cert.CertificateException; * Created by arne on 24.04.16. */ public class LogItem implements Parcelable { - - private Object[] mArgs = null; + + private Object[] mArgs = null; private String mMessage = null; - private int mResourceId; + private int mResourceId; // Default log priority VectrasStatus.LogLevel mLevel = VectrasStatus.LogLevel.INFO; private long logtime = System.currentTimeMillis(); private int mVerbosityLevel = -1; - - public LogItem(int resId, Object... args) { + + public LogItem(int resId, Object... args) { mResourceId = resId; - mArgs = args; + mArgs = args; } - - public LogItem(VectrasStatus.LogLevel loglevel, int verblevel, String msg) { + + public LogItem(VectrasStatus.LogLevel loglevel, int verblevel, String msg) { mLevel = loglevel; mMessage = msg; - mVerbosityLevel = verblevel; + mVerbosityLevel = verblevel; } public LogItem(VectrasStatus.LogLevel level, int resId, Object... args) { mLevel = level; - mResourceId = resId; - mArgs = args; + mResourceId = resId; + mArgs = args; } - - public LogItem(VectrasStatus.LogLevel loglevel, String msg) { + + public LogItem(VectrasStatus.LogLevel loglevel, String msg) { mLevel = loglevel; mMessage = msg; } @@ -65,8 +75,8 @@ public class LogItem implements Parcelable { mResourceId = ressourceId; mLevel = loglevel; } - - @Override + + @Override public String toString() { return getString(null); } @@ -80,16 +90,16 @@ public class LogItem implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeArray(mArgs); dest.writeString(mMessage); - dest.writeInt(mResourceId); + dest.writeInt(mResourceId); dest.writeInt(mLevel.getInt()); - + dest.writeLong(logtime); } public LogItem(Parcel in) { mArgs = in.readArray(Object.class.getClassLoader()); mMessage = in.readString(); - mResourceId = in.readInt(); + mResourceId = in.readInt(); mLevel = VectrasStatus.LogLevel.getEnumByValue(in.readInt()); logtime = in.readLong(); } @@ -112,18 +122,18 @@ public class LogItem implements Parcelable { public long getLogtime() { return logtime; } - - public String getMessage() { - return mMessage; - } - public String getString(Context c) { + public String getMessage() { + return mMessage; + } + + public String getString(Context c) { try { if (mMessage != null) { return mMessage; } else { if (c != null) { - if (mResourceId == R.string.app_name) + if (mResourceId == R.string.app_name) return getAppInfoString(c); else if (mArgs == null) return c.getString(mResourceId); @@ -149,10 +159,10 @@ public class LogItem implements Parcelable { throw e; } } - - //private String listb = ""; - - // The lint is wrong here + + //private String listb = ""; + + // The lint is wrong here @SuppressLint("StringFormatMatches") private String getAppInfoString(Context c) { c.getPackageManager(); @@ -161,7 +171,7 @@ public class LogItem implements Parcelable { String version = "error getting version"; try { @SuppressLint("PackageManagerGetSignatures") - Signature raw = c.getPackageManager().getPackageInfo(c.getPackageName(), PackageManager.GET_SIGNATURES).signatures[0]; + Signature raw = c.getPackageManager().getPackageInfo(c.getPackageName(), PackageManager.GET_SIGNATURES).signatures[0]; CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray())); MessageDigest md = MessageDigest.getInstance("SHA-1"); @@ -174,7 +184,7 @@ public class LogItem implements Parcelable { version = String.format("%s Projeto %d", packageinfo.versionName, packageinfo.versionCode); } catch (PackageManager.NameNotFoundException | CertificateException | - NoSuchAlgorithmException ignored) { + NoSuchAlgorithmException ignored) { } /* Object[] argsext = Arrays.copyOf(mArgs, mArgs.length); @@ -184,8 +194,8 @@ public class LogItem implements Parcelable { return c.getString(R.string.app_name, version, apksign); } - - // TextUtils.join will cause not macked exeception in tests .... + + // TextUtils.join will cause not macked exeception in tests .... public static String join(CharSequence delimiter, Object[] tokens) { StringBuilder sb = new StringBuilder(); boolean firstTime = true; @@ -199,8 +209,8 @@ public class LogItem implements Parcelable { } return sb.toString(); } - - public int getVerbosityLevel() { + + public int getVerbosityLevel() { if (mVerbosityLevel == -1) { // Hack: // For message not from OpenVPN, report the status level as log level diff --git a/app/src/main/java/com/vectras/vm/main/monitor/SystemMonitorFragment.java b/app/src/main/java/com/vectras/vm/main/monitor/SystemMonitorFragment.java index b867dc4..8e4c0d3 100644 --- a/app/src/main/java/com/vectras/vm/main/monitor/SystemMonitorFragment.java +++ b/app/src/main/java/com/vectras/vm/main/monitor/SystemMonitorFragment.java @@ -209,7 +209,7 @@ public class SystemMonitorFragment extends Fragment { if (!isAdded()) return; String result = Terminal.executeShellCommandWithResult("ps -e command && echo \"psendhere\" && cat /proc/cpuinfo", requireActivity()); requireActivity().runOnUiThread(() -> { - binding.tvProcesses.setText(result.isEmpty() ? getString(R.string.nothing_here) : result.substring(0, result.indexOf("\npsendhere"))); + binding.tvProcesses.setText(result.isEmpty() && !result.contains("\npsendhere") ? getString(R.string.nothing_here) : result.substring(0, result.indexOf("\npsendhere"))); binding.tvQemuversion.setText(getString(R.string.version) + " " + (qemuVersionName.isEmpty() ? getString(R.string.unknow) : qemuVersionName) + "."); if (!result.isEmpty()) { diff --git a/app/src/main/java/com/vectras/vm/utils/DialogUtils.java b/app/src/main/java/com/vectras/vm/utils/DialogUtils.java index 32dfb78..5706cd1 100644 --- a/app/src/main/java/com/vectras/vm/utils/DialogUtils.java +++ b/app/src/main/java/com/vectras/vm/utils/DialogUtils.java @@ -23,6 +23,7 @@ import android.widget.TextView; import androidx.preference.PreferenceManager; import com.google.android.material.color.MaterialColors; +import com.vectras.vm.AppConfig; import com.vectras.vm.R; public class DialogUtils { @@ -254,10 +255,10 @@ public class DialogUtils { _context.getResources().getString(R.string.join), _context.getResources().getString(R.string.cancel), _context.getResources().getString(R.string.dont_show_again), true, R.drawable.send_24px, true, () -> { - String tg = "https://t.me/vectras_os"; - Intent f = new Intent(ACTION_VIEW); - f.setData(Uri.parse(tg)); - _context.startActivity(f); + Intent intent = new Intent(ACTION_VIEW); + intent.addCategory(Intent.CATEGORY_BROWSABLE); + intent.setData(Uri.parse(AppConfig.telegramLink)); + _context.startActivity(intent); }, null, () -> { SharedPreferences.Editor edit = prefs.edit(); diff --git a/app/src/main/java/com/vectras/vm/utils/NetworkUtils.java b/app/src/main/java/com/vectras/vm/utils/NetworkUtils.java index 75d66cc..6b20494 100644 --- a/app/src/main/java/com/vectras/vm/utils/NetworkUtils.java +++ b/app/src/main/java/com/vectras/vm/utils/NetworkUtils.java @@ -5,8 +5,13 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import java.io.IOException; +import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.NetworkInterface; import java.net.Socket; +import java.net.SocketException; +import java.util.Enumeration; +import java.util.Objects; public class NetworkUtils { public static boolean isPortOpen(String host, int port, int timeout) { @@ -46,4 +51,21 @@ public class NetworkUtils { } return false; } + + public static String getLocalIpAddress() { + try { + for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) { + NetworkInterface intf = en.nextElement(); + for (Enumeration enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) { + InetAddress inetAddress = enumIpAddr.nextElement(); + if (!inetAddress.isLoopbackAddress() && Objects.requireNonNull(inetAddress.getHostAddress()).contains(".")) { + return inetAddress.getHostAddress(); + } + } + } + } catch (SocketException ex) { + ex.printStackTrace(); + } + return null; + } } diff --git a/app/src/main/java/com/vectras/vm/utils/TextUtils.java b/app/src/main/java/com/vectras/vm/utils/TextUtils.java index 012abc9..589a954 100644 --- a/app/src/main/java/com/vectras/vm/utils/TextUtils.java +++ b/app/src/main/java/com/vectras/vm/utils/TextUtils.java @@ -3,6 +3,10 @@ package com.vectras.vm.utils; import java.util.Random; public class TextUtils { + public static boolean isNumberOnly(String content) { + return content.matches("\\d+"); + } + public static String randomALetter() { String addAdb; Random random = new Random(); diff --git a/app/src/main/java/com/vectras/vm/view/GithubUserView.java b/app/src/main/java/com/vectras/vm/view/GithubUserView.java index 7fc6844..b2f5fe3 100644 --- a/app/src/main/java/com/vectras/vm/view/GithubUserView.java +++ b/app/src/main/java/com/vectras/vm/view/GithubUserView.java @@ -1,5 +1,6 @@ package com.vectras.vm.view; +import android.app.Activity; import android.content.Context; import android.content.Intent; import android.net.Uri; @@ -79,7 +80,10 @@ public class GithubUserView extends LinearLayout { userName.setText(!user.getLogin().isEmpty() ? user.getLogin() : getContext().getString(R.string.unknow)); userDescription.setText(!user.getBio().isEmpty() ? user.getBio() : getContext().getString(R.string.unknow)); if (!user.getAvatarUrl().isEmpty()) { - Glide.with(getContext()).load(user.getAvatarUrl()).placeholder(R.drawable.account_circle_24px).error(R.drawable.account_circle_24px).into(profileImage); + if (getContext() instanceof Activity activity) { + if (!activity.isFinishing() && !activity.isDestroyed()) + Glide.with(getContext()).load(user.getAvatarUrl()).placeholder(R.drawable.account_circle_24px).error(R.drawable.account_circle_24px).into(profileImage); + } } else { profileImage.setImageResource(R.drawable.account_circle_24px); } diff --git a/app/src/main/java/com/vectras/vterm/Terminal.java b/app/src/main/java/com/vectras/vterm/Terminal.java index 5fe2dbd..1b26a27 100644 --- a/app/src/main/java/com/vectras/vterm/Terminal.java +++ b/app/src/main/java/com/vectras/vterm/Terminal.java @@ -24,6 +24,7 @@ import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; import com.vectras.vm.R; import com.vectras.vm.VMManager; @@ -35,8 +36,8 @@ import com.vectras.vm.utils.NotificationUtils; public class Terminal { private static final String TAG = "Vterm"; - private Context context; - private static String user = "root"; + private final Context context; + private static final String user = "root"; public static Process qemuProcess; public static String DISPLAY = ":0"; @@ -45,24 +46,6 @@ public class Terminal { this.context = context; } - - private String getLocalIpAddress() { - try { - for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) { - NetworkInterface intf = en.nextElement(); - for (Enumeration enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) { - InetAddress inetAddress = enumIpAddr.nextElement(); - if (!inetAddress.isLoopbackAddress() && Objects.requireNonNull(inetAddress.getHostAddress()).contains(".")) { - return inetAddress.getHostAddress(); - } - } - } - } catch (SocketException ex) { - ex.printStackTrace(); - } - return null; - } - private void showDialog(String message, Context context, String usercommand) { if (VMManager.isExecutedCommandError(usercommand, message, context)) return; @@ -77,7 +60,7 @@ public class Terminal { } public void executeShellCommand(String userCommand, boolean showResultDialog, boolean showProgressDialog, String progressDialogMessage, Context dialogActivity) { - StringBuilder output = new StringBuilder(); + AtomicReference output = new AtomicReference<>(new StringBuilder()); StringBuilder errors = new StringBuilder(); Log.d(TAG, userCommand); com.vectras.vm.logger.VectrasStatus.logError("VTERM: >" + userCommand + ""); @@ -131,35 +114,10 @@ public class Terminal { processBuilder.command(prootCommand); qemuProcess = processBuilder.start(); - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(qemuProcess.getOutputStream())); - BufferedReader reader = new BufferedReader(new InputStreamReader(qemuProcess.getInputStream())); - BufferedReader errorReader = new BufferedReader(new InputStreamReader(qemuProcess.getErrorStream())); - - writer.write(userCommand); - writer.newLine(); - writer.flush(); - writer.close(); - - String line; - while ((line = reader.readLine()) != null) { -// Log.d(TAG, line); - com.vectras.vm.logger.VectrasStatus.logError("VTERM: >" + line + ""); - output.append(line).append("\n"); - } - - while ((line = errorReader.readLine()) != null) { - Log.w(TAG, line); - com.vectras.vm.logger.VectrasStatus.logError("VTERM ERROR: >" + line + ""); - output.append(line).append("\n"); - } - - int exitCode = qemuProcess.waitFor(); - if (exitCode != 0) { - output.append("Execution finished with exit code: ").append(exitCode).append("\n"); - } - } catch (IOException | InterruptedException e) { + output.set(streamLog(userCommand, qemuProcess, false)); + } catch (IOException e) { progressDialog.dismiss(); // Dismiss ProgressDialog - output.append(e.getMessage()); + output.get().append(e.getMessage()); errors.append(Log.getStackTraceString(e)); } finally { new Handler(Looper.getMainLooper()).post(() -> { @@ -176,7 +134,7 @@ public class Terminal { } public void executeShellCommand2(String userCommand, boolean showResultDialog, Context dialogActivity) { - StringBuilder output = new StringBuilder(); + AtomicReference output = new AtomicReference<>(new StringBuilder()); StringBuilder errors = new StringBuilder(); Log.d(TAG, userCommand); com.vectras.vm.logger.VectrasStatus.logError("VTERM: >" + userCommand + ""); @@ -226,46 +184,10 @@ public class Terminal { processBuilder.command(prootCommand); qemuProcess = processBuilder.start(); - // Get the input and output streams of the qemuProcess - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(qemuProcess.getOutputStream())); - BufferedReader reader = new BufferedReader(new InputStreamReader(qemuProcess.getInputStream())); - BufferedReader errorReader = new BufferedReader(new InputStreamReader(qemuProcess.getErrorStream())); - // Send user command to PRoot - writer.write(userCommand); - writer.newLine(); - writer.flush(); - writer.close(); - - // Read the input stream for the output of the command - String line; - while (qemuProcess.isAlive() && (line = reader.readLine()) != null) { -// Log.d(TAG, line); - com.vectras.vm.logger.VectrasStatus.logError("VTERM: >" + line + ""); - output.append(line).append("\n"); - } - - // Read any errors from the error stream - while (qemuProcess.isAlive() && (line = errorReader.readLine()) != null) { - Log.w(TAG, line); - com.vectras.vm.logger.VectrasStatus.logError("VTERM ERROR: >" + line + ""); - output.append(line).append("\n"); - } - - // Clean up - reader.close(); - errorReader.close(); - - int exitCode = qemuProcess.waitFor(); // Wait for the process to finish - if (exitCode == 0) { - output.append("Execution finished successfully.\n"); - } else { - output.append("Execution finished with exit code: ").append(exitCode).append("\n"); - } - output.append(reader.readLine()).append("\n"); - Log.i(TAG, reader.readLine()); - } catch (IOException | InterruptedException e) { - output.append(e.getMessage()); + output.set(streamLog(userCommand, qemuProcess, false)); + } catch (IOException e) { + output.get().append(e.getMessage()); errors.append(Log.getStackTraceString(e)); NotificationUtils.clearAll(VectrasApp.getContext()); } finally { @@ -327,33 +249,8 @@ public class Terminal { processBuilder.command(prootCommand); qemuProcess = processBuilder.start(); - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(qemuProcess.getOutputStream())); - BufferedReader reader = new BufferedReader(new InputStreamReader(qemuProcess.getInputStream())); - BufferedReader errorReader = new BufferedReader(new InputStreamReader(qemuProcess.getErrorStream())); - - writer.write(userCommand); - writer.newLine(); - writer.flush(); - writer.close(); - - String line; - while ((line = reader.readLine()) != null) { -// Log.d(TAG, line); - com.vectras.vm.logger.VectrasStatus.logError("VTERM: >" + line + ""); - output.append(line).append("\n"); - } - - while ((line = errorReader.readLine()) != null) { - Log.w(TAG, line); - com.vectras.vm.logger.VectrasStatus.logError("VTERM ERROR: >" + line + ""); - output.append(line).append("\n"); - } - - int exitCode = qemuProcess.waitFor(); - if (exitCode != 0) { - output.append("Execution finished with exit code: ").append(exitCode).append("\n"); - } - } catch (IOException | InterruptedException e) { + output = streamLog(userCommand, qemuProcess, false); + } catch (IOException e) { output.append(e.getMessage()); errors.append(Log.getStackTraceString(e)); } @@ -365,7 +262,7 @@ public class Terminal { } public String executeShellCommand(String userCommand, Context dialogActivity, boolean isShowProgressDialog, CommandCallback callback) { - StringBuilder output = new StringBuilder(); + AtomicReference output = new AtomicReference<>(new StringBuilder()); StringBuilder errors = new StringBuilder(); Log.d(TAG, userCommand); com.vectras.vm.logger.VectrasStatus.logError("VTERM: >" + userCommand + ""); @@ -420,46 +317,17 @@ public class Terminal { processBuilder.command(prootCommand); qemuProcess = processBuilder.start(); - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(qemuProcess.getOutputStream())); - BufferedReader reader = new BufferedReader(new InputStreamReader(qemuProcess.getInputStream())); - BufferedReader errorReader = new BufferedReader(new InputStreamReader(qemuProcess.getErrorStream())); + output.set(streamLog(userCommand, qemuProcess, true)); - writer.write(userCommand); - writer.newLine(); - writer.flush(); - writer.close(); - - String line; - while ((line = reader.readLine()) != null) { -// Log.d(TAG, line); - com.vectras.vm.logger.VectrasStatus.logError("VTERM: >" + line + ""); - output.append(line).append("\n"); - } - - while ((line = errorReader.readLine()) != null) { - Log.w(TAG, line); - com.vectras.vm.logger.VectrasStatus.logError("VTERM ERROR: >" + line + ""); - errors.append(line).append("\n"); - } - - int exitCode = qemuProcess.waitFor(); - if (exitCode != 0) { - output.append("Execution finished with exit code: ").append(exitCode).append("\n"); - } - - } catch (IOException | InterruptedException e) { - output.append(e.getMessage()); + } catch (IOException e) { + output.get().append(e.getMessage()); errors.append(Log.getStackTraceString(e)); } finally { // Dismiss ProgressDialog on the main thread new Handler(Looper.getMainLooper()).post(progressDialog::dismiss); - // Return the output and errors via callback on the main thread - String finalOutput = output.toString(); - String finalErrors = errors.toString(); - // Use callback to return both output and errors - new Handler(Looper.getMainLooper()).post(() -> callback.onCommandCompleted(finalOutput, finalErrors)); + new Handler(Looper.getMainLooper()).post(() -> callback.onCommandCompleted(output.toString(), errors.toString())); } }).start(); @@ -489,6 +357,48 @@ public class Terminal { return false; } + public static StringBuilder streamLog(String command, Process process, boolean isShortProcess) { + StringBuilder output = new StringBuilder(); + try { + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream())); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + + writer.write(command); + writer.newLine(); + writer.flush(); + writer.close(); + + String line; + while ((line = reader.readLine()) != null) { + com.vectras.vm.logger.VectrasStatus.logError("VTERM: >" + line + ""); + output.append(line).append("\n"); + } + + while ((line = errorReader.readLine()) != null) { + Log.w(TAG, line); + com.vectras.vm.logger.VectrasStatus.logError("VTERM ERROR: >" + line + ""); + output.append(line).append("\n"); + } + + if (isShortProcess) { + int exitCode = process.waitFor(); + if (exitCode == 0) { + output.append("Execution finished successfully.\n"); + } else { + output.append("Execution finished with exit code: ").append(exitCode).append("\n"); + } + } + + reader.close(); + errorReader.close(); + } catch (Exception e) { + output.append(e.getMessage()); + Log.e(TAG, "streamLog: ", e); + } + return output; + } + private Context getContext() { if (context == null) { return VectrasApp.getContext(); diff --git a/web/data/UpdateConfig.json b/web/data/UpdateConfig.json index 66ca83f..75430aa 100644 --- a/web/data/UpdateConfig.json +++ b/web/data/UpdateConfig.json @@ -5,11 +5,11 @@ "url": "https://github.com/xoureldeen/Vectras-VM-Android/releases", "Message": "

3.6.0

\nBugs fixed.", "cancellable": true, - "versionCodeBeta":"68", - "versionNameBeta":"3.6.4", - "versionNameBetas":"3.0.0,3.1.0,3.2.1,3.2.2,3.2.3,3.2.4,3.2.5,3.2.6,3.2.7,3.2.8,3.2.9,3.2.10,3.3.1,3.3.2,3.3.3,3.3.4,3.3.5,3.3.6,3.3.7,3.3.8,3.3.9,3.4.1,3.4.2,3.4.3,3.4.4,3.4.5,3.4.6,3.4.7,3.4.8,3.4.9,3.5.1,3.5.2,3.5.3,3.5.4,3.5.5,3.5.6,3.5.7,3.5.8,3.5.9,3.6.0,3.6.1,3.6.2,3.6.3,3.6.4", + "versionCodeBeta":"69", + "versionNameBeta":"3.6.5", + "versionNameBetas":"3.0.0,3.1.0,3.2.1,3.2.2,3.2.3,3.2.4,3.2.5,3.2.6,3.2.7,3.2.8,3.2.9,3.2.10,3.3.1,3.3.2,3.3.3,3.3.4,3.3.5,3.3.6,3.3.7,3.3.8,3.3.9,3.4.1,3.4.2,3.4.3,3.4.4,3.4.5,3.4.6,3.4.7,3.4.8,3.4.9,3.5.1,3.5.2,3.5.3,3.5.4,3.5.5,3.5.6,3.5.7,3.5.8,3.5.9,3.6.0,3.6.1,3.6.2,3.6.3,3.6.4,3.6.5", "sizeBeta": "43 MB", "urlBeta": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases", - "MessageBeta": "

3.6.4

Bugs fixed.", + "MessageBeta": "

3.6.5

Bugs fixed.", "cancellableBeta": true }