- Added floppy disk drive B.
- Added feature to prevent reusing a file in multiple locations within the virtual machine.
- Fixed issue preventing the creation and editing of virtual machines from Param Notebook.
This commit is contained in:
An Bui 2026-05-19 12:51:55 +07:00
parent 5238d11df1
commit d53c40b926
14 changed files with 210 additions and 48 deletions

View file

@ -12,8 +12,8 @@ android {
applicationId "com.vectras.vm"
minSdk minApi
targetSdk targetApi
versionCode 122
versionName "4.1.8"
versionCode 123
versionName "4.1.9"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true

View file

@ -0,0 +1,42 @@
package com.anbui.elephant.vm;
import com.vectras.vm.AppConfig;
import com.vectras.vm.VMManager;
import com.vectras.vm.main.core.PendingCommand;
import com.vectras.vm.manager.VmFileManager;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.JSONUtils;
public class VmEditor {
public static boolean handle() {
if (
PendingCommand.vmId == null ||
PendingCommand.vmConfig == null ||
PendingCommand.paramsNotebookConfig == null
) return false;
return handle(PendingCommand.vmId, PendingCommand.vmConfig, PendingCommand.paramsNotebookConfig, PendingCommand.forceCreate);
}
public static boolean handle(String vmId, String vmConfig, String paramsNotebookConfig, boolean forceCreate) {
if (!FileUtils.isFileExists(AppConfig.romsdatajson))
if (!FileUtils.writeToFile(AppConfig.maindirpath, "roms-data.json", "[]")) return false;
if (!JSONUtils.isValidFromFile(AppConfig.romsdatajson)) return false;
String vmIdReady = vmId.isEmpty() ? VMManager.idGenerator() : vmId;
if (!forceCreate && VMManager.isVMExist(vmIdReady)) {
if (!VMManager.replaceToVMList(-1, vmIdReady , vmConfig)) return false;
} else {
if (!FileUtils.isEmpty(VmFileManager.quickGetPath(vmIdReady ))) vmIdReady = VMManager.idGenerator();
if (!VMManager.addToVMList(vmConfig, vmIdReady )) return false;
PendingCommand.forceCreate = true;
}
FileUtils.writeToFile(VmFileManager.getPath(vmIdReady), VmFileManager.CREATE_COMMAND_CONFIG_FILE_NAME, paramsNotebookConfig);
return true;
}
}

View file

@ -64,9 +64,6 @@ public class CqcmActivity extends AppCompatActivity {
}
private void startAdd() {
HashMap<String, Object> mapForCreateNewVM;
String _map;
if (!FileUtils.isFileExists(AppConfig.romsdatajson)) {
FileUtils.writeToFile(AppConfig.maindirpath, "roms-data.json", "[]");
}
@ -74,28 +71,15 @@ public class CqcmActivity extends AppCompatActivity {
if (JSONUtils.isValidFromFile(AppConfig.romsdatajson)) {
if (getIntent().hasExtra("content")) {
if (getIntent().hasExtra("cqcmcontent")) {
if (JSONUtils.isValidFromString(getIntent().getStringExtra("content"))) {
String vmId = Objects.requireNonNull(getIntent().getStringExtra("vmId")).isEmpty() ? VMManager.idGenerator() : getIntent().getStringExtra("vmId");
boolean isForceCreateNew = getIntent().hasExtra("forceCreateNew") && getIntent().getBooleanExtra("forceCreateNew", false);
if (!isForceCreateNew && VMManager.isVMExist(getIntent().getStringExtra("vmId"))) {
if (VMManager.replaceToVMList(-1, getIntent().getStringExtra("vmId"), getIntent().getStringExtra("content"))) {
Toast.makeText(getApplicationContext(), getString(R.string.vm_has_been_edited), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), getString(R.string.an_error_occurred_and_vm_was_not_modified), Toast.LENGTH_LONG).show();
}
} else {
vmId = VmFileManager.isInUse(getIntent().getStringExtra("vmId")) ? VMManager.idGenerator() : getIntent().getStringExtra("vmId");
if (VMManager.addToVMList(getIntent().getStringExtra("content"), vmId)) {
Toast.makeText(getApplicationContext(), getString(R.string.vm_has_been_created), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), getString(R.string.an_error_occurred_and_vm_was_not_created), Toast.LENGTH_LONG).show();
}
}
FileUtils.writeToFile(VmFileManager.getPath(vmId), VmFileManager.CREATE_COMMAND_CONFIG_FILE_NAME, getIntent().getStringExtra("cqcmcontent"));
} else {
Toast.makeText(getApplicationContext(), "An error occurred and it was not possible to create or edit a virtual machine.", Toast.LENGTH_LONG).show();
}
PendingCommand.vmId = getIntent().getStringExtra("vmId");
PendingCommand.vmConfig = getIntent().getStringExtra("content");
PendingCommand.paramsNotebookConfig = getIntent().getStringExtra("cqcmcontent");
PendingCommand.forceCreate = getIntent().getBooleanExtra("forceCreateNew", false);
} else {
HashMap<String, Object> mapForCreateNewVM;
String _map;
if (Objects.requireNonNull(getIntent().getStringExtra("content")).endsWith("}]")) {
_map = Objects.requireNonNull(getIntent().getStringExtra("content")).substring(0, Objects.requireNonNull(getIntent().getStringExtra("content")).length() - 1);
} else {

View file

@ -154,6 +154,12 @@ public class ExportRomActivity extends AppCompatActivity {
vmConfigMap.put("fda", "");
}
if (FileUtils.isFileExists(current.fdb)) {
vmConfigMap.put("fdb", new File(Objects.requireNonNull(Uri.parse(current.fdb).getPath())).getName());
} else {
vmConfigMap.put("fdb", "");
}
vmConfigMap.put("sharedFolder", current.sharedFolder);
vmConfigMap.put("bootFrom", current.bootFrom);
vmConfigMap.put("isShowBootMenu", current.isShowBootMenu);

View file

@ -226,6 +226,24 @@ public class StartVM {
}
}
if (!vmConfigs.fdb.isEmpty() && !MainSettingsManager.getArch(activity).equals("ARM64")) {
if (vmConfigs.fda.isEmpty()) {
if (extras.contains("-fda ")) {
params.add("-drive if=floppy,file='" + vmConfigs.fdb + "'");
} else {
params.add("-fda");
params.add("'" + vmConfigs.fdb + "'");
}
} else {
if (extras.contains("-fdb ")) {
params.add("-drive if=floppy,file='" + vmConfigs.fdb + "'");
} else {
params.add("-fdb");
params.add("'" + vmConfigs.fdb + "'");
}
}
}
if (vmConfigs.sharedFolder) {
String driveParams = "-drive ";
driveParams += "file=fat:rw:'"; //Disk Drives are always Read/Write

View file

@ -538,6 +538,10 @@ public class VMCreatorActivity extends AppCompatActivity {
if (current.fda!= null && !current.fda.isEmpty()) {
setDrive(SELECT_FLOPPY_A_FILE_MODE, (current.fda.contains("/") ? "" : VmFileManager.getPath(vmID)).concat(current.fda));
}
if (current.fdb!= null && !current.fdb.isEmpty()) {
setDrive(SELECT_FLOPPY_B_FILE_MODE, (current.fdb.contains("/") ? "" : VmFileManager.getPath(vmID)).concat(current.fdb));
}
}
if (current.imgCdrom != null && !current.imgCdrom.isEmpty()) {
@ -660,7 +664,7 @@ public class VMCreatorActivity extends AppCompatActivity {
_contentDialog = getResources().getString(R.string.qemu_params_is_empty);
}
if ((Objects.requireNonNull(binding.drive.getText()).toString().isEmpty()) && (Objects.requireNonNull(binding.tieHd1.getText()).toString().isEmpty()) && (Objects.requireNonNull(binding.cdrom.getText()).toString().isEmpty())) {
if (isAllDriveEmpty()) {
if (!VMManager.isHaveADisk(Objects.requireNonNull(binding.qemu.getText()).toString())) {
if (!_contentDialog.isEmpty()) {
_contentDialog += "\n\n";
@ -729,24 +733,40 @@ public class VMCreatorActivity extends AppCompatActivity {
}
private DataMainRoms finalVmConfig() {
current.vmID = vmID;
current.itemArch = MainSettingsManager.getArch(this);
current.itemName = Objects.requireNonNull(binding.title.getText()).toString();
current.itemIcon = thumbnailPath;
current.cpu = cpu;
current.cores = cores;
current.threads = threads;
current.itemPath = Objects.requireNonNull(binding.drive.getText()).toString();
current.hd1 = Objects.requireNonNull(binding.tieHd1.getText()).toString();
current.fda = Objects.requireNonNull(binding.tieFda.getText()).toString();
current.fdb = Objects.requireNonNull(binding.tieFdb.getText()).toString();
current.imgCdrom = Objects.requireNonNull(binding.cdrom.getText()).toString();
current.sharedFolder = sharedFolder;
current.itemExtra = Objects.requireNonNull(binding.qemu.getText()).toString();
current.itemArch = MainSettingsManager.getArch(this);
current.bootFrom = bootFrom;
current.isShowBootMenu = isShowBootMenu;
current.isUseLocalTime = isUseLocalTime;
current.isUseUefi = isUseUefi;
current.isUseDefaultBios = isUseDefaultBios;
current.isUseLocalTime = isUseLocalTime;
current.vmID = vmID;
current.itemExtra = Objects.requireNonNull(binding.qemu.getText()).toString();
current.qmpPort = 8080;
return current;
@ -1139,7 +1159,11 @@ public class VMCreatorActivity extends AppCompatActivity {
private void markDelete(String path) {
VmFileManager.markPendingDelete(path);
VmFileManager.removeTemp(this, vmID, peddingTempFolder + new File(path).getName());
deleteTemp(new File(path).getName());
}
private void deleteTemp(String fileName) {
VmFileManager.removeTemp(this, vmID, peddingTempFolder + fileName);
}
public void moveAllFromTemp() {
@ -1191,6 +1215,9 @@ public class VMCreatorActivity extends AppCompatActivity {
binding.tilFda.setOnClickListener(v -> pickStorageFile(SELECT_FLOPPY_A_FILE_MODE));
binding.tilFda.setEndIconOnClickListener(v -> setDrive(SELECT_FLOPPY_A_FILE_MODE, null));
binding.tieFdb.setOnClickListener(v -> pickStorageFile(SELECT_FLOPPY_B_FILE_MODE));
binding.tilFdb.setOnClickListener(v -> pickStorageFile(SELECT_FLOPPY_B_FILE_MODE));
binding.tilFdb.setEndIconOnClickListener(v -> setDrive(SELECT_FLOPPY_B_FILE_MODE, null));
binding.cdrom.setOnClickListener(v -> pickStorageFile(SELECT_CDROM_0_FILE_MODE));
@ -1207,6 +1234,7 @@ public class VMCreatorActivity extends AppCompatActivity {
private final int SELECT_DISK_1_FILE_MODE = 1;
public final int SELECT_CDROM_0_FILE_MODE = 2;
public final int SELECT_FLOPPY_A_FILE_MODE = 3;
public final int SELECT_FLOPPY_B_FILE_MODE = 4;
private int PENDING_SELECT_FILE_MODE = 0;
private String PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE = "";
@ -1217,7 +1245,7 @@ public class VMCreatorActivity extends AppCompatActivity {
try {
if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE) {
isoPicker.launch("*/*");
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE) {
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
floppyPicker.launch("*/*");
} else {
diskPicker.launch("*/*");
@ -1287,6 +1315,12 @@ public class VMCreatorActivity extends AppCompatActivity {
}
private void setDrive(Integer mode, String path) {
if (isFileReadyinUse(path)) {
DialogUtils.oopsDialog(this, getString(R.string.vm_creator_this_file_is_already_in_use_content));
deleteTemp(new File(path).getName());
return;
}
if (mode != null) PENDING_SELECT_FILE_MODE = mode;
TextInputLayout peddingTextInputLayout = getPeddingStorageInputLayout();
@ -1295,13 +1329,13 @@ public class VMCreatorActivity extends AppCompatActivity {
peddingTextInputEditText.setText(path != null ? path : "");
if (path == null || path.isEmpty()) {
if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE) {
if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
peddingTextInputLayout.setEndIconMode(TextInputLayout.END_ICON_NONE);
} else {
peddingTextInputLayout.setEndIconDrawable(R.drawable.add_24px);
}
} else {
if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE) {
if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
peddingTextInputLayout.setEndIconMode(TextInputLayout.END_ICON_CUSTOM);
peddingTextInputLayout.setEndIconDrawable(R.drawable.close_24px);
setRemovableDriveEndIconOnClickListener(PENDING_SELECT_FILE_MODE, peddingTextInputLayout);
@ -1323,6 +1357,8 @@ public class VMCreatorActivity extends AppCompatActivity {
return binding.cdromField;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE) {
return binding.tilFda;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
return binding.tilFdb;
} else {
return binding.driveField;
}
@ -1335,11 +1371,34 @@ public class VMCreatorActivity extends AppCompatActivity {
return binding.cdrom;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE) {
return binding.tieFda;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
return binding.tieFdb;
} else {
return binding.drive;
}
}
private boolean isAllDriveEmpty() {
return (Objects.requireNonNull(binding.drive.getText()).toString().isEmpty()) &&
(Objects.requireNonNull(binding.tieHd1.getText()).toString().isEmpty()) &&
(Objects.requireNonNull(binding.cdrom.getText()).toString().isEmpty()) &&
(Objects.requireNonNull(binding.tieFda.getText()).toString().isEmpty()) &&
(Objects.requireNonNull(binding.tieFdb.getText()).toString().isEmpty());
}
private boolean isFileReadyinUse(String path) {
if (path == null || path.trim().isEmpty()) return false;
String paramCollection = Objects.requireNonNull(binding.drive.getText()).toString();
paramCollection += "\n" + Objects.requireNonNull(binding.tieHd1.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.cdrom.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.tieFda.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.tieFdb.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.qemu.getText());
return paramCollection.contains(path);
}
private void checkCreateCommandConfig() {
if (PackageUtils.getVersionCode("com.anbui.cqcm.app", this) < 735 || !FileUtils.isFileExists(VmFileManager.getCreateCommandConfigFile(vmID))) {
binding.opencqcm.setVisibility(View.GONE);

View file

@ -4,6 +4,7 @@ import static android.content.Intent.ACTION_VIEW;
import static com.vectras.vm.VectrasApp.getApp;
import android.annotation.SuppressLint;
import android.app.admin.PreferentialNetworkServiceConfig;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
@ -17,6 +18,7 @@ import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.activity.OnBackPressedCallback;
@ -32,6 +34,7 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.anbui.elephant.retrofit2utils.Retrofit2Utils;
import com.anbui.elephant.vm.VmEditor;
import com.google.android.material.behavior.HideViewOnScrollBehavior;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.bottomsheet.BottomSheetDialog;
@ -425,6 +428,22 @@ public class MainActivity extends AppCompatActivity implements RomStoreFragment.
DisplaySystem.reLaunchVNC(this);
PendingCommand.runNow(this);
if (
PendingCommand.vmId != null &&
PendingCommand.vmConfig != null &&
PendingCommand.paramsNotebookConfig != null
) {
if (VmEditor.handle()) {
Toast.makeText(this, getString(PendingCommand.forceCreate ? R.string.vm_has_been_created : R.string.vm_has_been_edited), Toast.LENGTH_LONG).show();
} else {
DialogUtils.oopsDialog(this, getString(PendingCommand.forceCreate ? R.string.an_error_occurred_and_vm_was_not_created : R.string.an_error_occurred_and_vm_was_not_modified));
}
PendingCommand.vmId = null;
PendingCommand.vmConfig = null;
PendingCommand.paramsNotebookConfig = null;
}
if (isOpenRomStore) {
isOpenRomStore = false;
bindingContent.bottomNavigation.setSelectedItemId(R.id.item_romstore);

View file

@ -71,4 +71,9 @@ public class PendingCommand {
}
}
}
public static String vmId;
public static String vmConfig;
public static String paramsNotebookConfig;
public static boolean forceCreate;
}

View file

@ -47,6 +47,8 @@ public class DataMainRoms {
public String fda = "";
public String fdb = "";
public boolean sharedFolder = false;
public String vmID = "";

View file

@ -344,7 +344,7 @@
android:paddingHorizontal="16dp"
android:clickable="true"
android:focusable="true"
android:hint="@string/floppy_drive"
android:hint="@string/floppy_drive_a"
android:theme="@style/AppTheme.TextInput"
app:endIconDrawable="@drawable/close_24px"
app:startIconDrawable="@drawable/save_24px">
@ -361,6 +361,31 @@
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_fdb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:paddingHorizontal="16dp"
android:clickable="true"
android:focusable="true"
android:hint="@string/floppy_drive_b"
android:theme="@style/AppTheme.TextInput"
app:endIconDrawable="@drawable/close_24px"
app:startIconDrawable="@drawable/save_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/tie_fdb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<com.google.android.material.divider.MaterialDivider

View file

@ -299,7 +299,7 @@
<string name="note_for_selecting_ppc">Bạn có thể chạy các phiên bản Mac OS cũ hơn và các hệ điều hành khác được thiết kế cho kiến trúc PowerPC.</string>
<string name="note_for_selecting_import">Bạn có thể nhập ngay bằng cách chọn tệp ở định dạng cvbi.</string>
<string name="note_for_selecting_qemu">Tìm hiểu thêm về trình giả lập mã nguồn mở này.</string>
<string name="create_command">Create command</string>
<string name="create_command">Param Notebook</string>
<string name="note_for_selecting_create_command">Tạo máy ảo mới cho Vectras VM với khả năng tùy chỉnh dễ dàng hơn.</string>
<string name="import_or_choose_an_architecture_to_start_creating">Nhập hoặc chọn một kiến trúc để bắt đầu tạo.</string>
<string name="set_arch_universal_note">Bạn nghĩ ở đây có kéo thả? Thử kéo và thả tệp cvbi vào thẻ Nhập thử đi.</string>
@ -579,6 +579,7 @@
<string name="hard_drive_0">Ổ cứng 0</string>
<string name="hard_drive_1">Ổ cứng 1</string>
<string name="optical_drive">Ổ quang</string>
<string name="vm_creator_this_file_is_already_in_use_content">Tệp này đã được đùng ở một nơi khác của máy ảo. Bạn cần tìm và loại bỏ hoặc đổi tên nó và chọn lại.</string>
<!--======================TERMUX STRINGS====================-->
<string name="application_name" translatable="false">Vterm</string>

View file

@ -310,7 +310,7 @@
<string name="note_for_selecting_ppc">You can run older versions of Mac OS and other operating systems intended for the PowerPC architecture.</string>
<string name="note_for_selecting_import">You can import now by selecting the file in cvbi format.</string>
<string name="note_for_selecting_qemu">Learn more about this open source emulator.</string>
<string name="create_command">Create command</string>
<string name="create_command">Param Notebook</string>
<string name="note_for_selecting_create_command">Create new virtual machines for Vectras VM with easier customization.</string>
<string name="import_or_choose_an_architecture_to_start_creating">Import or choose an architecture to start creating.</string>
<string name="set_arch_universal_note">You can drag and drop cvbi file to Import card to import.</string>
@ -506,8 +506,8 @@
<string name="vm_has_been_edited">VM has been edited.</string>
<string name="an_error_occurred_and_vm_was_not_created">An error occurred and VM was not created.</string>
<string name="an_error_occurred_and_vm_was_not_modified">An error occurred and VM was not modified.</string>
<string name="edit_with_create_command">Edit with Create command</string>
<string name="edit_with_create_command_content">You can edit this VM with Create command app.</string>
<string name="edit_with_create_command">Edit with Param Notebook</string>
<string name="edit_with_create_command_content">You can edit this VM with Param Notebook app.</string>
<string name="unable_to_save_please_try_again_later">Unable to save, please try again later.</string>
<string name="advanced">Advanced</string>
<string name="boot">Boot</string>
@ -590,6 +590,7 @@
<string name="hard_drive_0">Hard drive 0</string>
<string name="hard_drive_1">Hard drive 1</string>
<string name="optical_drive">Optical drive</string>
<string name="vm_creator_this_file_is_already_in_use_content">This file is already in use elsewhere on the virtual machine. You need to find and remove or rename it and select it again.</string>
<!--======================TERMUX STRINGS====================-->

View file

@ -1,6 +1,6 @@
[versions]
activityKtx = "1.13.0"
agp = "9.2.0"
agp = "9.2.1"
annotation = "1.10.0"
appcompat = "1.7.1"
comGoogleFirebase = "firebase-crashlytics"
@ -11,9 +11,9 @@ coreKtx = "1.18.0"
documentfile = "1.1.0"
drawerlayout = "1.2.0"
espressoCore = "3.7.0"
firebaseBom = "34.12.0"
firebaseBom = "34.13.0"
firebaseCrashlyticsGradle = "3.0.7"
firebaseMessaging = "25.0.1"
firebaseMessaging = "25.0.2"
glide = "5.0.7"
googleFirebase = "firebase-analytics"
googleFirebaseCrashlytics = "3.0.7"
@ -27,7 +27,7 @@ junit = "4.13.2"
junitVersion = "1.3.0"
kotlinGradlePlugin = "2.3.21"
lottie = "6.7.1"
material = "1.14.0-rc01"
material = "1.14.0"
preferenceKtx = "1.2.1"
retrofit2 = "3.0.0"
swiperefreshlayout = "1.2.0"

View file

@ -5,11 +5,11 @@
"url": "https://github.com/xoureldeen/Vectras-VM-Android/releases",
"Message": "<h2>4.1.0</h2>\nBugs fixed.",
"cancellable": true,
"versionCodeBeta":"122",
"versionNameBeta":"4.1.8",
"versionNameBetas":"4.0.0,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.0,4.1.1,4.1.2,4.1.3,4.1.4,4.1.5,4.1.6,4.1.7,4.1.8",
"versionCodeBeta":"123",
"versionNameBeta":"4.1.9",
"versionNameBetas":"4.0.0,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.0,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",
"sizeBeta": "45 MB",
"urlBeta": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases",
"MessageBeta": "<h2>4.1.8</h2>Bugs fixed.",
"MessageBeta": "<h2>4.1.9</h2>Bugs fixed.",
"cancellableBeta": true
}