mirror of
https://github.com/xoureldeen/Vectras-VM-Android.git
synced 2026-07-09 17:28:54 +00:00
4.2.4
- Faster return to virtual machine. - Fixed the frozen virtual machine startup dialog when using X11. - Added audio support for the built-in X11 display. - Improved notifications. - Qemu 7.2.22 has been improved and requires manual updating with the Upgrade tool using a command in the Terminal.
This commit is contained in:
parent
3b16fd8b7d
commit
09f9654ccd
13 changed files with 239 additions and 98 deletions
1
.github/ISSUE_TEMPLATE/bug.yaml
vendored
1
.github/ISSUE_TEMPLATE/bug.yaml
vendored
|
|
@ -32,6 +32,7 @@ body:
|
|||
options:
|
||||
- Latest
|
||||
- Beta
|
||||
- 4.2.0
|
||||
- 4.1.0
|
||||
- 4.0.0
|
||||
- 3.9.0
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ QEMU 8.2.0 - 3dfx (only for Vectras VM 2.9.5):
|
|||
- [See them at the Internet Archive](https://archive.org/details/vectras-vm-x86_64.tar_202603nbab)
|
||||
|
||||
QEMU 7.2.22 - 3dfx (for Vectras VM 4.2.2+):
|
||||
- [For Android ARM (64-bit)](https://archive.org/download/qemu-7-2-22-for-vectras-vm-nbab/base-vectras-vm-arm64-v8a.tar.gz)
|
||||
- [For Android ARM (64-bit)](https://archive.org/download/qemu-7-2-22-for-vectras-vm-nbab/base-june-2026-vectras-vm-arm64-v8a.tar.gz)
|
||||
- [See more at the Internet Archive](https://archive.org/details/qemu-7-2-22-for-vectras-vm-nbab)
|
||||
|
||||
### 💽 3Dfx Wrappers
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ android {
|
|||
applicationId "com.vectras.vm"
|
||||
minSdk minApi
|
||||
targetSdk targetApi
|
||||
versionCode 127
|
||||
versionName "4.2.3"
|
||||
versionCode 128
|
||||
versionName "4.2.4"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled true
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ public class StartVM {
|
|||
private static DataMainRoms vmConfigs;
|
||||
|
||||
public static String env(Activity activity, DataMainRoms vmData) {
|
||||
if (VMManager.isVMRunning(activity, vmData.vmID)) return "";
|
||||
|
||||
vmConfigs = vmData;
|
||||
|
||||
if (VMManager.isNeedLoadMigrate() && FileUtils.isFileExists(VmFileManager.getSnapshotSh(Config.vmID))) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import androidx.annotation.NonNull;
|
|||
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||
import com.google.firebase.messaging.RemoteMessage;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.settings.UpdaterActivity;
|
||||
import com.vectras.vm.utils.NotificationUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
|
@ -22,6 +23,12 @@ public class FCMService
|
|||
return;
|
||||
}
|
||||
|
||||
Class<?> activityClass = null;
|
||||
|
||||
if (data.get("activityClass") != null) {
|
||||
if (Objects.equals(data.get("activityClass"), "update")) activityClass = UpdaterActivity.class;
|
||||
}
|
||||
|
||||
NotificationUtils.pushNow(this,
|
||||
1,
|
||||
NotificationUtils.generalChannelId,
|
||||
|
|
@ -31,7 +38,7 @@ public class FCMService
|
|||
data.get("image") != null ? data.get("image") : null,
|
||||
-1,
|
||||
data.get("url") != null ? data.get("url") : null,
|
||||
null);
|
||||
activityClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import android.widget.Toast;
|
|||
import com.vectras.qemu.Config;
|
||||
import com.vectras.qemu.MainSettingsManager;
|
||||
import com.vectras.qemu.MainVNCActivity;
|
||||
import com.vectras.vm.AppConfig;
|
||||
import com.vectras.vm.MainService;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.StartVM;
|
||||
|
|
@ -55,6 +54,26 @@ public class MainStartVM {
|
|||
|
||||
private static StartVmDialog dialog;
|
||||
|
||||
public static final int PENDDING_EMPTY = -1;
|
||||
|
||||
public static final int STARTED_VM = 0;
|
||||
public static final int STARTED_VM_READY_RUNNING = 1;
|
||||
|
||||
public static final int ERROR_VM = 10;
|
||||
public static final int ERROR_BREAK = 11;
|
||||
public static final int ERROR_INVALID_VM_ID = 12;
|
||||
public static final int ERROR_MAKE_TEMP_FOLDER = 13;
|
||||
public static final int ERROR_UNSAFE_COMMAND = 14;
|
||||
public static final int ERROR_ACCEL = 15;
|
||||
public static final int ERROR_VNC_TCP_PORT = 16;
|
||||
public static final int ERROR_SHARED_FOLDER = 17;
|
||||
public static final int ERROR_RESUME = 18;
|
||||
|
||||
public interface MainStartVMCallback {
|
||||
void onStarted(int statusCode, String message);
|
||||
void onError(int errorCode, String message);
|
||||
}
|
||||
|
||||
public static void startNow(Activity activity, DataMainRoms vmConfig) {
|
||||
breakNow = false;
|
||||
|
||||
|
|
@ -62,7 +81,10 @@ public class MainStartVM {
|
|||
|
||||
VMManager.setArch(vmConfig.itemArch, activity);
|
||||
|
||||
if (!(MainSettingsManager.getVmUi(activity).equals("X11") && DisplaySystem.isUseBuiltInX11())) {
|
||||
if (
|
||||
MainSettingsManager.getVmUi(activity).equals("VNC") ||
|
||||
(MainSettingsManager.getVmUi(activity).equals("X11") && !DisplaySystem.isUseBuiltInX11())
|
||||
) {
|
||||
showDialog(activity, vmConfig.vmID, vmConfig.itemName, vmConfig.itemIcon, activity.getString(R.string.preparing));
|
||||
}
|
||||
|
||||
|
|
@ -82,9 +104,22 @@ public class MainStartVM {
|
|||
String thumbnailFile,
|
||||
StartVmDialog dialog
|
||||
) {
|
||||
startNow(context, vmName, env, vmID, thumbnailFile, dialog, null);
|
||||
}
|
||||
|
||||
public static void startNow(
|
||||
Context context,
|
||||
String vmName,
|
||||
String env,
|
||||
String vmID,
|
||||
String thumbnailFile,
|
||||
StartVmDialog dialog,
|
||||
MainStartVMCallback callback
|
||||
) {
|
||||
|
||||
if (breakNow) {
|
||||
breakNow = false;
|
||||
if (callback != null) callback.onError(PENDDING_EMPTY, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -92,7 +127,10 @@ public class MainStartVM {
|
|||
|
||||
if (isLaunchFromPending) {
|
||||
isLaunchFromPending = false;
|
||||
if (pendingVMID.isEmpty()) return;
|
||||
if (pendingVMID.isEmpty()) {
|
||||
if (callback != null) callback.onError(ERROR_INVALID_VM_ID, "");
|
||||
return;
|
||||
}
|
||||
pendingVMID = "";
|
||||
} else {
|
||||
if (MainSettingsManager.getVmUi(context).equals("X11") && !DisplaySystem.isUseBuiltInX11()) {
|
||||
|
|
@ -128,8 +166,6 @@ public class MainStartVM {
|
|||
|
||||
breakNow = false;
|
||||
|
||||
if (dialog == null || !dialog.isShowing()) showDialog((Activity) context, vmID, vmName, thumbnailFile, null);
|
||||
|
||||
String finalvmID;
|
||||
if (vmID == null || vmID.isEmpty()) {
|
||||
finalvmID = VMManager.startRamdomVMID();
|
||||
|
|
@ -140,14 +176,23 @@ public class MainStartVM {
|
|||
Config.vmID = finalvmID;
|
||||
|
||||
if (VMManager.isVMRunning(context, finalvmID)) {
|
||||
Toast.makeText(context, "This VM is already running.", Toast.LENGTH_LONG).show();
|
||||
DisplaySystem.launch(context);
|
||||
if (!MainSettingsManager.getVmUi(context).equals("VNC")) VmAudioManager.stream(vmID);
|
||||
|
||||
dismissDialog();
|
||||
|
||||
Toast.makeText(context, context.getString(R.string.this_vm_is_already_running), Toast.LENGTH_LONG).show();
|
||||
DisplaySystem.launch(context);
|
||||
if (
|
||||
!MainSettingsManager.getVmUi(context).equals("VNC") &&
|
||||
!DisplaySystem.isUseBuiltInX11()
|
||||
)
|
||||
VmAudioManager.stream(vmID);
|
||||
|
||||
if (callback != null) callback.onStarted(STARTED_VM_READY_RUNNING, "");
|
||||
return;
|
||||
}
|
||||
|
||||
// Place it here to avoid freezing when the dialog box appears upon returning to the virtual machine.
|
||||
if (dialog == null || !dialog.isShowing()) showDialog((Activity) context, vmID, vmName, thumbnailFile, null);
|
||||
|
||||
File romDir = new File(Config.getCacheDir() + "/" + finalvmID);
|
||||
if (!romDir.exists()) {
|
||||
if (!romDir.mkdirs()) {
|
||||
|
|
@ -159,6 +204,7 @@ public class MainStartVM {
|
|||
);
|
||||
|
||||
dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_MAKE_TEMP_FOLDER, "");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -172,6 +218,7 @@ public class MainStartVM {
|
|||
);
|
||||
|
||||
dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_UNSAFE_COMMAND, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -182,6 +229,7 @@ public class MainStartVM {
|
|||
() -> startNow(context, vmName, env.replace("tcg,thread=multi", "tcg,thread=single"), finalvmID, thumbnailFile, finalDialog1), null, null);
|
||||
|
||||
dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_ACCEL, "");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -198,6 +246,7 @@ public class MainStartVM {
|
|||
null);
|
||||
|
||||
dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_VNC_TCP_PORT, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -221,6 +270,7 @@ public class MainStartVM {
|
|||
);
|
||||
|
||||
dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_SHARED_FOLDER, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -228,10 +278,11 @@ public class MainStartVM {
|
|||
|
||||
if (breakNow) {
|
||||
dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_BREAK, "");
|
||||
return;
|
||||
}
|
||||
|
||||
startVm(context, vmName, env, finalvmID, thumbnailFile);
|
||||
startVm(context, vmName, env, finalvmID, thumbnailFile, callback);
|
||||
});
|
||||
}).start();
|
||||
}
|
||||
|
|
@ -241,7 +292,8 @@ public class MainStartVM {
|
|||
String vmName,
|
||||
String env,
|
||||
String vmID,
|
||||
String thumbnailFile
|
||||
String thumbnailFile,
|
||||
MainStartVMCallback callback
|
||||
) {
|
||||
VMManager.isQemuStopedWithError = false;
|
||||
|
||||
|
|
@ -257,6 +309,7 @@ public class MainStartVM {
|
|||
|
||||
if (breakNow) {
|
||||
dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_BREAK, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -332,6 +385,8 @@ public class MainStartVM {
|
|||
null,
|
||||
null
|
||||
);
|
||||
|
||||
if (callback != null) callback.onError(ERROR_RESUME, "");
|
||||
});
|
||||
|
||||
return;
|
||||
|
|
@ -372,12 +427,18 @@ public class MainStartVM {
|
|||
Log.i(TAG, "Virtual machine running.");
|
||||
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(MainStartVM::dismissDialog);
|
||||
activity.runOnUiThread(() -> {
|
||||
MainStartVM.dismissDialog();
|
||||
if (callback != null) callback.onStarted(STARTED_VM, "");
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
} else {
|
||||
assert activity != null;
|
||||
activity.runOnUiThread(MainStartVM::dismissDialog);
|
||||
activity.runOnUiThread(() -> {
|
||||
MainStartVM.dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_VM, "");
|
||||
});
|
||||
}
|
||||
|
||||
skipIDEwithARM64DialogInStartVM = false;
|
||||
|
|
@ -404,9 +465,9 @@ public class MainStartVM {
|
|||
VMManager.isTryAgain = false;
|
||||
}
|
||||
|
||||
public static void startPending(Context context) {
|
||||
public static void startPending(Context context, MainStartVMCallback callback) {
|
||||
isLaunchFromPending = true;
|
||||
startNow(context, pendingVMName, pendingEnv, pendingVMID, pendingThumbnailFile, null);
|
||||
startNow(context, pendingVMName, pendingEnv, pendingVMID, pendingThumbnailFile, null, callback);
|
||||
}
|
||||
|
||||
private static void showDialog(Activity activity, String vmId, String vmName, String thumbnailPath, String status) {
|
||||
|
|
|
|||
|
|
@ -3,18 +3,19 @@ package com.vectras.vm.x11;
|
|||
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
|
||||
|
||||
import android.app.Dialog;
|
||||
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Looper;
|
||||
|
||||
import static android.view.InputDevice.KEYBOARD_TYPE_ALPHABETIC;
|
||||
import static android.view.KeyEvent.*;
|
||||
import static android.view.WindowManager.LayoutParams.*;
|
||||
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
|
|
@ -28,6 +29,9 @@ import com.vectras.vm.databinding.DesktopControlsBinding;
|
|||
import com.vectras.vm.databinding.GameControlsBinding;
|
||||
import com.vectras.vm.main.core.MainStartVM;
|
||||
import com.vectras.vm.manager.QmpSender;
|
||||
import com.vectras.vm.manager.VmAudioManager;
|
||||
import com.vectras.vm.manager.VmFileManager;
|
||||
import com.vectras.vm.utils.StreamAudio;
|
||||
import com.vectras.vm.utils.UIUtils;
|
||||
|
||||
import static com.vectras.vm.x11.CmdEntryPoint.ACTION_START;
|
||||
|
|
@ -119,6 +123,8 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
public boolean ctrlClicked = false;
|
||||
public boolean altClicked = false;
|
||||
|
||||
private StreamAudio streamAudio;
|
||||
|
||||
ActivityX11Binding binding;
|
||||
ControlsFragmentBinding bindingControls;
|
||||
DesktopControlsBinding bindingDesktopControls;
|
||||
|
|
@ -688,13 +694,30 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
|
||||
bindingDesktopControls.ctrlaltdelBtn.setVisibility(View.GONE);
|
||||
|
||||
MainStartVM.startPending(this);
|
||||
MainStartVM.startPending(this, new MainStartVM.MainStartVMCallback() {
|
||||
@Override
|
||||
public void onStarted(int statusCode, String message) {
|
||||
MainStartVM.dismissDialog();
|
||||
setupSound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int errorCode, String message) {
|
||||
MainStartVM.dismissDialog();
|
||||
if (errorCode == MainStartVM.PENDDING_EMPTY) setupSound();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void onBack() {
|
||||
if (bindingControls.mainControl.getVisibility() == View.GONE) {
|
||||
bindingControls.mainControl.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
if (streamAudio != null) {
|
||||
if (!VmAudioManager.currentVmId.equals(Config.vmID)) streamAudio.setCross(null);
|
||||
if (streamAudio.isPlaying()) streamAudio.stop();
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
|
@ -713,6 +736,7 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
@Override
|
||||
protected void onDestroy() {
|
||||
unregisterReceiver(receiver);
|
||||
if (streamAudio != null) streamAudio.stop();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
|
|
@ -790,7 +814,8 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
v.startDragAndDrop(
|
||||
ClipData.newPlainText("", ""),
|
||||
new View.DragShadowBuilder(binding.buttonVisibility) {
|
||||
public void onDrawShadow(@NonNull Canvas canvas) {}
|
||||
public void onDrawShadow(@NonNull Canvas canvas) {
|
||||
}
|
||||
},
|
||||
null,
|
||||
View.DRAG_FLAG_GLOBAL);
|
||||
|
|
@ -927,8 +952,7 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
startTime = SystemClock.uptimeMillis();
|
||||
binding.mouseButtonsPosition.setPressed(true);
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
{
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
int[] offset = new int[2];
|
||||
int[] offset2 = new int[2];
|
||||
binding.mouseButtons.getLocationOnScreen(offset);
|
||||
|
|
@ -949,8 +973,7 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
- binding.mouseButtons.getHeight()));
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_UP:
|
||||
{
|
||||
case MotionEvent.ACTION_UP: {
|
||||
final int[] _pos = new int[2];
|
||||
binding.mouseButtons.getLocationOnScreen(_pos);
|
||||
int deltaX =
|
||||
|
|
@ -1433,6 +1456,31 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
return mInputHandler.shouldInterceptKeys();
|
||||
}
|
||||
|
||||
private void setupSound() {
|
||||
if (streamAudio == null) {
|
||||
streamAudio = new StreamAudio(X11Activity.this);
|
||||
streamAudio.setFile(VmFileManager.findAudioRaw(X11Activity.this, Config.vmID));
|
||||
|
||||
if (VmAudioManager.currentVmId.equals(Config.vmID) && VmAudioManager.streamAudio.isPlaying())
|
||||
streamAudio.setCross(VmAudioManager.streamAudio);
|
||||
|
||||
playSound();
|
||||
}
|
||||
}
|
||||
|
||||
int playSoundRequests;
|
||||
|
||||
private void playSound() {
|
||||
if (streamAudio == null || streamAudio.isPlaying() || playSoundRequests > 0) return;
|
||||
playSoundRequests++;
|
||||
|
||||
streamAudio.stop();
|
||||
new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
||||
if (!streamAudio.isPlaying()) streamAudio.play();
|
||||
playSoundRequests--;
|
||||
}, 100);
|
||||
}
|
||||
|
||||
private void shutdownthisvm() {
|
||||
QmpSender.quickShutdown();
|
||||
Config.setDefault();
|
||||
|
|
|
|||
|
|
@ -195,6 +195,25 @@
|
|||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:clickable="false"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="16dp" >
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="16dp"
|
||||
android:src="@drawable/info_24px" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/x11_general_setting_note" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
|
|
|
|||
|
|
@ -750,6 +750,7 @@
|
|||
<string name="use_external_x11_note">Dùng ứng dụng Termux:X11 thay vì màn hình có sẵn.</string>
|
||||
<string name="blur_effect">Hiệu ứng mờ</string>
|
||||
<string name="blur_effect_note">Làm mờ xung quanh để tăng khả năng tập trung vào một vùng cần được chú ý.</string>
|
||||
<string name="x11_general_setting_note">Bạn cần khởi động lại ứng dụng khi chuyển đổi giữa tích hợp sẵn và ngoài.</string>
|
||||
|
||||
<!-- CPUs -->
|
||||
|
||||
|
|
|
|||
|
|
@ -603,6 +603,7 @@
|
|||
<string name="in_system_settings">In system settings.</string>
|
||||
<string name="missing_packages">Missing packages</string>
|
||||
<string name="missing_packages_content">These are the missing packages that you should install:</string>
|
||||
<string name="x11_general_setting_note">You need to restart the app when switching between built-in and external.</string>
|
||||
|
||||
|
||||
<!--======================TERMUX STRINGS====================-->
|
||||
|
|
|
|||
|
|
@ -11,8 +11,9 @@ async function sendNotification() {
|
|||
title: "Vectras VM",
|
||||
message: "Welcome!",
|
||||
image: "https://github.com/xoureldeen/Vectras-VM-Android/blob/master/resources/vectrasvm.png",
|
||||
url : "https://github.com/xoureldeen/Vectras-VM-Android",
|
||||
//targetVersions: "3.9.0,3.9.1"
|
||||
url: "https://github.com/xoureldeen/Vectras-VM-Android",
|
||||
//activityClass: "update",
|
||||
//targetVersions: "4.1.0,4.2.0",
|
||||
targetVersions: ""
|
||||
},
|
||||
topic: "vectrasvmandroidgithub"
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ rm -rf /usr/share/qemu
|
|||
clear
|
||||
|
||||
echo -e "\e[1;37m[i] Downloading..."
|
||||
aria2c -x 4 --async-dns=false --disable-ipv6 --check-certificate=false -o setup.tar.gz https://archive.org/download/qemu-7-2-22-for-vectras-vm-nbab/base-vectras-vm-arm64-v8a.tar.gz
|
||||
aria2c -x 4 --async-dns=false --disable-ipv6 --check-certificate=false -o setup.tar.gz https://archive.org/download/qemu-7-2-22-for-vectras-vm-nbab/base-june-2026-vectras-vm-arm64-v8a.tar.gz
|
||||
clear
|
||||
|
||||
echo -e "\e[1;37m[i] Installing..."
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@
|
|||
"url": "https://github.com/xoureldeen/Vectras-VM-Android/releases",
|
||||
"Message": "<h2>4.1.0</h2>\nBugs fixed.",
|
||||
"cancellable": true,
|
||||
"versionCodeBeta":"127",
|
||||
"versionNameBeta":"4.2.3",
|
||||
"versionNameBetas":"4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,4.0.7,4.0.8,4.0.9,4.1.1,4.1.2,4.1.3,4.1.4,4.1.5,4.1.6,4.1.7,4.1.8,4.1.9,4.2.0,4.2.1,4.2.2,4.2.3",
|
||||
"versionCodeBeta":"128",
|
||||
"versionNameBeta":"4.2.4",
|
||||
"versionNameBetas":"4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,4.0.7,4.0.8,4.0.9,4.1.1,4.1.2,4.1.3,4.1.4,4.1.5,4.1.6,4.1.7,4.1.8,4.1.9,4.2.0,4.2.1,4.2.2,4.2.3,4.2.4",
|
||||
"sizeBeta": "45 MB",
|
||||
"urlBeta": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases",
|
||||
"MessageBeta": "<h2>4.2.3</h2>Bugs fixed.",
|
||||
"MessageBeta": "<h2>4.2.4</h2>Bugs fixed.",
|
||||
"cancellableBeta": true
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue