Merge pull request #611 from AnBui2004/master

4.0.1
This commit is contained in:
An Bui 2026-04-26 02:40:26 +07:00 committed by GitHub
commit 13bf9e8718
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 93 additions and 47 deletions

View file

@ -12,8 +12,8 @@ android {
applicationId "com.vectras.vm"
minSdk minApi
targetSdk targetApi
versionCode 104
versionName "4.0.0"
versionCode 105
versionName "4.0.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true

View file

@ -45,6 +45,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.appcompat.widget.Toolbar;
import com.vectras.vm.*;
@ -167,7 +168,7 @@ public class MainVNCActivity extends VncCanvasActivity {
binding.lnNosignal.setOnClickListener(v -> {
// In VNCCanvasActivity.
// Do not attempt to reconnect while connected.
reconnect();
tryReconnect();
});
ConnectionBean.useLocalCursor = MainSettingsManager.getShowVirtualMouse(this) || VMManager.isNeedUseVirtualMouse();
@ -768,7 +769,8 @@ public class MainVNCActivity extends VncCanvasActivity {
this.vncCanvas.setFocusableInTouchMode(true);
// syncCursorViewWithBitmap();
if (VmAudioManager.currentVmId.equals(Config.vmID) && VmAudioManager.streamAudio.isPlaying()) streamAudio.setCross(VmAudioManager.streamAudio);
if (VmAudioManager.currentVmId.equals(Config.vmID) && VmAudioManager.streamAudio.isPlaying())
streamAudio.setCross(VmAudioManager.streamAudio);
if (!streamAudio.isPlaying()) streamAudio.play();
});
}
@ -819,7 +821,12 @@ public class MainVNCActivity extends VncCanvasActivity {
}
}
private boolean isTrying;
private void tryReconnect() {
if (isTrying) return;
isTrying = true;
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
int count = 0;
@ -827,18 +834,29 @@ public class MainVNCActivity extends VncCanvasActivity {
public void run() {
count++;
if (!isFinishing() && !isDestroyed() && !isConnected && count < retryLimit) {
// Do not attempt to reconnect while connected.
if (Config.forceRefeshVNCDisplay) {
runOnUiThread(() -> {
startActivity(new Intent(MainVNCActivity.this, MainVNCActivity.class));
overridePendingTransition(0, 0);
finish();
});
} else {
if (!isFinishing() && !isDestroyed()) {
if (!isConnected && count < retryLimit) {
// Do not attempt to reconnect while connected.
binding.lnNosignal.setVisibility(View.GONE);
binding.lnConnecting.setVisibility(View.VISIBLE);
reconnect();
new Handler(Looper.getMainLooper()).postDelayed(this, 1000);
} else if (!isConnected) {
isTrying = false;
binding.lnNosignal.setVisibility(View.VISIBLE);
binding.lnConnecting.setVisibility(View.GONE);
} else {
isTrying = false;
if (Config.forceRefeshVNCDisplay) {
runOnUiThread(() -> {
startActivity(new Intent(MainVNCActivity.this, MainVNCActivity.class));
overridePendingTransition(0, 0);
finish();
});
}
}
new Handler(Looper.getMainLooper()).postDelayed(this, 1000);
}
}
}, 0);
@ -892,7 +910,8 @@ public class MainVNCActivity extends VncCanvasActivity {
DialogUtils.twoDialog(this, "Exit", "You will be left here but the virtual machine will continue to run.", "Exit", getString(R.string.cancel), true, R.drawable.exit_to_app_24px, true,
() -> {
started = false;
if (!VmAudioManager.currentVmId.equals(Config.vmID)) streamAudio.setCross(null);
if (!VmAudioManager.currentVmId.equals(Config.vmID))
streamAudio.setCross(null);
finish();
}, null, null);
return false;

View file

@ -98,7 +98,7 @@ public class ExportRomActivity extends AppCompatActivity {
@SuppressLint("SetTextI18n")
private void startCreate(Uri uri) {
String cvbiFolder = Objects.requireNonNull(getExternalCacheDir()).getAbsolutePath() + "/cvbi/";
/*String cvbiFolder = Objects.requireNonNull(getExternalCacheDir()).getAbsolutePath() + "/cvbi/";
File vDir = new File(cvbiFolder);
if (!vDir.exists()) {
if (!vDir.mkdirs()) {
@ -113,7 +113,7 @@ public class ExportRomActivity extends AppCompatActivity {
this::finish
);
}
}
}*/
String getRomPath = VmFileManager.getPath(current.vmID);
HashMap<String, Object> vmConfigMap = new HashMap<>();
@ -160,7 +160,7 @@ public class ExportRomActivity extends AppCompatActivity {
vmConfigMap.put("versioncode", PackageUtils.getThisVersionCode(getApplicationContext()));
String tempFolder = Objects.requireNonNull(getExternalCacheDir()).getAbsolutePath() + "/temp/";
String tempFolder = VmFileManager.getTempPath(this, current.vmID + "/export");
FileUtils.writeToFile(tempFolder, "rom-data.json", new Gson().toJson(vmConfigMap));
@ -214,7 +214,7 @@ public class ExportRomActivity extends AppCompatActivity {
new Thread(() -> {
isExporting = true;
String outputPath;
/*String outputPath;
String outputFileName = current.itemName + ".cvbi";
if (!FileUtils.isFileExists(cvbiFolder + current.itemName + ".cvbi")) {
outputPath = cvbiFolder + outputFileName;
@ -229,7 +229,7 @@ public class ExportRomActivity extends AppCompatActivity {
prefix++;
}
}
}
}*/
final boolean[] result = {ZipUtils.compress(
this,
@ -244,36 +244,37 @@ public class ExportRomActivity extends AppCompatActivity {
String finalOutputPath = "";
try {
FileUtils.delete(new File(outputPath));
FileUtils.delete(new File(tempFolder));
//FileUtils.delete(new File(outputPath));
VmFileManager.removeTemp(this, current.vmID);
finalOutputPath = FileUtils.getPath(this, uri);
} catch (Exception e) {
Log.e(TAG, "startCreate: ", e);
}
String finalOutputPath1 = finalOutputPath;
String finalOutputPath1 = finalOutputPath != null ? finalOutputPath : "";
String title;
String content;
if (result[0]) {
title = getString(R.string.done);
content = finalOutputPath1 == null || finalOutputPath1.isEmpty() ? getString(R.string.rom_successfully_exported) : getString(R.string.saved_in) + ": " + finalOutputPath1 + ".";
content = finalOutputPath1.isEmpty() ? getString(R.string.rom_successfully_exported) : getString(R.string.saved_in) + ": " + finalOutputPath1 + ".";
} else {
title = getString(R.string.oops);
content = getString(R.string.something_went_wrong) + ":\n\n" + ZipUtils.lastErrorContent;
}
File file = new File(finalOutputPath1);
boolean isShowInFolder = !finalOutputPath1.isEmpty() && result[0] && file.getParent() != null && FileUtils.isFileExists(file.getParent());
DialogUtils.twoDialog(this,
title,
content,
getString(result[0] ? R.string.show_in_folder : R.string.ok),
getString(result[0] ? R.string.close : R.string.exit),
getString(isShowInFolder ? R.string.show_in_folder : R.string.ok),
getString(isShowInFolder ? R.string.close : R.string.exit),
true,
result[0] ? R.drawable.check_24px : R.drawable.error_96px,
true,
() -> {
if (result[0]) {
assert finalOutputPath1 != null;
File file = new File(finalOutputPath1.isEmpty() ? outputPath : finalOutputPath1);
if (isShowInFolder) {
FileUtils.openFolder(this, file.getParent());
}
},

View file

@ -118,8 +118,6 @@ public class SplashActivity extends AppCompatActivity {
private void cleanUp() {
FileUtils.delete(AppConfig.vmFolder + "QuickRun");
VmFileManager.removeTemp(this, "");
FileUtils.delete(new File(getExternalCacheDir(), "logs"));
FileUtils.delete(new File(getExternalCacheDir(), "cvbi"));
}
private void finishSplash() {

View file

@ -449,7 +449,7 @@ public class VMCreatorActivity extends AppCompatActivity {
return;
}
File selectedFilePath = new File(getPath(uri));
if (selectedFilePath.getName().endsWith(".iso")) {
if (selectedFilePath.getName().toLowerCase().endsWith(".iso")) {
runOnUiThread(() -> binding.cdrom.setText(selectedFilePath.getPath()));
} else {
runOnUiThread(() -> DialogUtils.oneDialog(this,

View file

@ -72,6 +72,13 @@ public class MainStartVM {
if (pendingVMID.isEmpty()) return;
pendingVMID = "";
} else {
if (MainSettingsManager.getVmUi(context).equals("X11") && !DisplaySystem.isUseBuiltInX11()) {
if (!PackageUtils.isInstalled("com.termux.x11", context)) {
DialogUtils.needInstallTermuxX11(context);
return;
}
}
lastVMName = vmName;
lastEnv = env;
lastVMID = vmID;
@ -79,8 +86,8 @@ public class MainStartVM {
if (MainSettingsManager.getVmUi(context).equals("X11") && !VMManager.isVMRunning(context, vmID)) {
if (MainSettingsManager.getRunQemuWithXterm(context)) {
String logFilePath = VMManager.getVMLogFilePath(context, vmID);
runCommandFormat = String.format(runCommandFormat, "xterm -e bash -c \"%s 2>&1 | tee " + logFilePath + "\"; cat " + logFilePath + "; rm " + logFilePath);
String logFilePath = VmFileManager.getLog(context, vmID);
runCommandFormat = String.format(runCommandFormat, "mkdir -p \"" + new File(logFilePath).getParent() + "\"; xterm -e bash -c \"%s 2>&1 | tee " + logFilePath + "\"; cat " + logFilePath + "; rm " + logFilePath);
} else {
runCommandFormat = String.format(runCommandFormat, "bash -c \"%s\"");
}
@ -222,13 +229,6 @@ public class MainStartVM {
}
}
if (MainSettingsManager.getVmUi(context).equals("X11") && !DisplaySystem.isUseBuiltInX11()) {
if (!PackageUtils.isInstalled("com.termux.x11", context)) {
DialogUtils.needInstallTermuxX11(context);
return;
}
}
tickForLaunch = new Runnable() {
@Override
public void run() {
@ -403,7 +403,12 @@ public class MainStartVM {
ImageView ivStop = progressView.findViewById(R.id.ivStop);
ivStop.setOnClickListener(v -> {
isStopNow = true;
QmpSender.quickShutdown();
ivStop.setVisibility(View.GONE);
vmBootNote.setText(R.string.shutting_down);
new Thread(() -> {
QmpSender.shutdown();
new Handler(Looper.getMainLooper()).post(() -> progressDialog.dismiss());
}).start();
});
progressDialog = new MaterialAlertDialogBuilder(context, R.style.CenteredDialogTheme)

View file

@ -7,7 +7,6 @@ import com.vectras.vm.AppConfig;
import com.vectras.vm.utils.FileUtils;
import java.io.File;
import java.util.Objects;
public class VmFileManager {
private static final String TAG = "VmFileManager";
@ -19,6 +18,7 @@ public class VmFileManager {
public static final String SNAPSHOT_SH_FILE_NAME = "snapshot.sh";
public static final String SNAPSHOT_BIN_FILE_NAME = "snapshot.bin";
public static final String CREATE_COMMAND_CONFIG_FILE_NAME = "cqcm.json";
public static final String LOG_FILE_NAME = "vm.log";
public static final String TEXT_MARK_VM_PATH = "OhnoIjustrealizeditsmidnightandIstillhavetodothis";
public static final String HIDE_VM_SUFFIX = "_";
@ -170,6 +170,10 @@ public class VmFileManager {
return VmFileManager.getPath(vmId, SNAPSHOT_BIN_FILE_NAME);
}
public static String getLog(Context context, String vmId) {
return VmFileManager.getTempPath(context, vmId, LOG_FILE_NAME);
}
public static boolean isCreateCommandConfigFileExists(String vmId) {
return FileUtils.isFileExists(getCreateCommandConfigFile(vmId));
}

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -77,6 +78,22 @@
android:textColor="@android:color/white" />
</LinearLayout>
<LinearLayout
android:id="@+id/ln_connecting"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#E6000000"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<com.google.android.material.progressindicator.CircularProgressIndicator
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" />
</LinearLayout>
</RelativeLayout>
<RelativeLayout

View file

@ -554,6 +554,7 @@
<string name="locked_and_cannot_be_changed_content">Thiết bị đã bị khoá và không thể thay đổi ngay bây giờ. Hãy thử lại sau. Bạn có thể thử rút nó và thử thay đổi lại.</string>
<string name="manage">Quản lý</string>
<string name="connect">Kết nối</string>
<string name="shutting_down">Đang tắt…</string>
<!--======================TERMUX STRINGS====================-->
<string name="application_name" translatable="false">Vterm</string>

View file

@ -565,6 +565,7 @@
<string name="locked_and_cannot_be_changed_content">The device is locked and cannot be changed right now. Please try again later. You can try eject it and then trying to change it again.</string>
<string name="manage">Manage</string>
<string name="connect">Connect</string>
<string name="shutting_down">Shutting down…</string>
<!--======================TERMUX STRINGS====================-->

View file

@ -5,11 +5,11 @@
"url": "https://github.com/xoureldeen/Vectras-VM-Android/releases",
"Message": "<h2>4.0.0</h2>\nBugs fixed.",
"cancellable": true,
"versionCodeBeta":"104",
"versionNameBeta":"4.0.0",
"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.1,3.6.2,3.6.3,3.6.4,3.6.5,3.6.6,3.6.7,3.6.8,3.6.9,3.7.1,3.7.2,3.7.3,3.7.4,3.7.5,3.7.6,3.7.7,3.7.8,3.7.9,3.8.0,3.8.1,3.8.2,3.8.3,3.8.4,3.8.5,3.8.6,3.8.7,3.8.8,3.8.9,3.9.0,3.9.1,3.9.2,3.9.3,3.9.4,3.9.5,3.9.6,3.9.7,3.9.8,3.9.9,4.0.0",
"versionCodeBeta":"105",
"versionNameBeta":"4.0.1",
"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.1,3.6.2,3.6.3,3.6.4,3.6.5,3.6.6,3.6.7,3.6.8,3.6.9,3.7.1,3.7.2,3.7.3,3.7.4,3.7.5,3.7.6,3.7.7,3.7.8,3.7.9,3.8.0,3.8.1,3.8.2,3.8.3,3.8.4,3.8.5,3.8.6,3.8.7,3.8.8,3.8.9,3.9.0,3.9.1,3.9.2,3.9.3,3.9.4,3.9.5,3.9.6,3.9.7,3.9.8,3.9.9,4.0.0,4.0.1",
"sizeBeta": "45 MB",
"urlBeta": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases",
"MessageBeta": "<h2>4.0.0</h2>Bugs fixed.",
"MessageBeta": "<h2>4.0.1</h2>Bugs fixed.",
"cancellableBeta": true
}