mirror of
https://github.com/xoureldeen/Vectras-VM-Android.git
synced 2026-04-28 06:19:49 +00:00
4.0.2
- Improved VNC display. - Fixed crash issue when selecting files. - Bugs fixed.
This commit is contained in:
parent
13bf9e8718
commit
4f1f6bd802
13 changed files with 283 additions and 115 deletions
|
|
@ -12,8 +12,8 @@ android {
|
||||||
applicationId "com.vectras.vm"
|
applicationId "com.vectras.vm"
|
||||||
minSdk minApi
|
minSdk minApi
|
||||||
targetSdk targetApi
|
targetSdk targetApi
|
||||||
versionCode 105
|
versionCode 106
|
||||||
versionName "4.0.1"
|
versionName "4.0.2"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,7 @@
|
||||||
android:name="com.vectras.qemu.MainVNCActivity"
|
android:name="com.vectras.qemu.MainVNCActivity"
|
||||||
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize"
|
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:screenOrientation="landscape"
|
android:screenOrientation="sensorLandscape"
|
||||||
android:theme="@style/Theme.FullScreen"
|
android:theme="@style/Theme.FullScreen"
|
||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
<activity
|
<activity
|
||||||
|
|
@ -187,6 +187,11 @@
|
||||||
android:resizeableActivity="true"
|
android:resizeableActivity="true"
|
||||||
android:windowSoftInputMode="adjustResize|stateAlwaysVisible" />
|
android:windowSoftInputMode="adjustResize|stateAlwaysVisible" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="com.termux.app.TermuxHelpActivity"
|
||||||
|
android:configChanges="orientation|screenSize|keyboardHidden|smallestScreenSize|screenLayout"
|
||||||
|
android:exported="false" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name="com.termux.app.TermuxService"
|
android:name="com.termux.app.TermuxService"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
|
||||||
|
|
@ -303,22 +303,8 @@ public class VncCanvas extends AppCompatImageView {
|
||||||
Log.i(TAG, "Desktop name is " + rfb.desktopName);
|
Log.i(TAG, "Desktop name is " + rfb.desktopName);
|
||||||
Log.i(TAG, "Desktop size is " + rfb.framebufferWidth + " x " + rfb.framebufferHeight);
|
Log.i(TAG, "Desktop size is " + rfb.framebufferWidth + " x " + rfb.framebufferHeight);
|
||||||
|
|
||||||
boolean useFull = false;
|
initBitmapData(dx, dy);
|
||||||
int capacity = BCFactory.getInstance().getBCActivityManager()
|
|
||||||
.getMemoryClass(Utils.getActivityManager(getContext()));
|
|
||||||
if (connection.getForceFull() == BitmapImplHint.AUTO) {
|
|
||||||
if (rfb.framebufferWidth * rfb.framebufferHeight * FullBufferBitmapData.CAPACITY_MULTIPLIER <= capacity
|
|
||||||
* 1024 * 1024) {
|
|
||||||
useFull = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
useFull = (connection.getForceFull() == BitmapImplHint.FULL);
|
|
||||||
}
|
|
||||||
if (!useFull) {
|
|
||||||
bitmapData = new LargeBitmapData(rfb, this, dx, dy, capacity);
|
|
||||||
} else {
|
|
||||||
bitmapData = new FullBufferBitmapData(rfb, this, capacity);
|
|
||||||
}
|
|
||||||
mouseX = rfb.framebufferWidth / 2;
|
mouseX = rfb.framebufferWidth / 2;
|
||||||
mouseY = rfb.framebufferHeight / 2;
|
mouseY = rfb.framebufferHeight / 2;
|
||||||
|
|
||||||
|
|
@ -333,6 +319,29 @@ public class VncCanvas extends AppCompatImageView {
|
||||||
pendingColorModel = null;
|
pendingColorModel = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void initBitmapData(int dx, int dy) {
|
||||||
|
int capacity = BCFactory.getInstance().getBCActivityManager()
|
||||||
|
.getMemoryClass(Utils.getActivityManager(getContext()));
|
||||||
|
|
||||||
|
boolean useFull = false;
|
||||||
|
if (connection.getForceFull() == BitmapImplHint.AUTO) {
|
||||||
|
if (rfb.framebufferWidth * rfb.framebufferHeight * FullBufferBitmapData.CAPACITY_MULTIPLIER
|
||||||
|
<= capacity * 1024 * 1024) {
|
||||||
|
useFull = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
useFull = (connection.getForceFull() == BitmapImplHint.FULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bitmapData != null) bitmapData.dispose();
|
||||||
|
|
||||||
|
if (!useFull) {
|
||||||
|
bitmapData = new LargeBitmapData(rfb, this, dx, dy, capacity);
|
||||||
|
} else {
|
||||||
|
bitmapData = new FullBufferBitmapData(rfb, this, capacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setColorModel(COLORMODEL cm) {
|
public void setColorModel(COLORMODEL cm) {
|
||||||
// Only update if color model changes
|
// Only update if color model changes
|
||||||
if (colorModel == null || !colorModel.equals(cm)) {
|
if (colorModel == null || !colorModel.equals(cm)) {
|
||||||
|
|
@ -395,6 +404,11 @@ public class VncCanvas extends AppCompatImageView {
|
||||||
rfb.setFramebufferSize(rw, rh);
|
rfb.setFramebufferSize(rw, rh);
|
||||||
// - updateFramebufferSize();
|
// - updateFramebufferSize();
|
||||||
Log.v(TAG, "rfb.EncodingNewFBSize");
|
Log.v(TAG, "rfb.EncodingNewFBSize");
|
||||||
|
|
||||||
|
Point size = new Point();
|
||||||
|
VncCanvasActivity.display.getSize(size);
|
||||||
|
initBitmapData(size.x, size.y);
|
||||||
|
|
||||||
reload();
|
reload();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1821,6 +1821,12 @@ public abstract class VncCanvasActivity extends AppCompatActivity {
|
||||||
|
|
||||||
// Remove old canvas
|
// Remove old canvas
|
||||||
ViewGroup parent = findViewById(R.id.vnc_canvas_layout);
|
ViewGroup parent = findViewById(R.id.vnc_canvas_layout);
|
||||||
|
|
||||||
|
if (vncCanvas != null) {
|
||||||
|
vncCanvas.closeConnection();
|
||||||
|
vncCanvas.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
parent.removeView(vncCanvas);
|
parent.removeView(vncCanvas);
|
||||||
|
|
||||||
// Create new canvas
|
// Create new canvas
|
||||||
|
|
|
||||||
|
|
@ -1046,7 +1046,7 @@ public class MainSettingsManager extends AppCompatActivity
|
||||||
|
|
||||||
public static Boolean getForceRefeshVNCDisplay(Context context) {
|
public static Boolean getForceRefeshVNCDisplay(Context context) {
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
return prefs.getBoolean("forceRefeshVNCDisplay", true);
|
return prefs.getBoolean("forceRefeshVNCDisplay", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setQuickStart(Context context, Boolean _boolean) {
|
public static void setQuickStart(Context context, Boolean _boolean) {
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,8 @@ public class MainVNCActivity extends VncCanvasActivity {
|
||||||
super.onCreate(b);
|
super.onCreate(b);
|
||||||
|
|
||||||
getContext = this;
|
getContext = this;
|
||||||
|
UIUtils.edgeToEdge(this);
|
||||||
|
UIUtils.setOnApplyWindowInsetsListener(binding.vncMainLayout);
|
||||||
initializeControlFragment();
|
initializeControlFragment();
|
||||||
initializeDesktopControl();
|
initializeDesktopControl();
|
||||||
initializeGameControl();
|
initializeGameControl();
|
||||||
|
|
@ -175,6 +177,8 @@ public class MainVNCActivity extends VncCanvasActivity {
|
||||||
|
|
||||||
streamAudio = new StreamAudio(this);
|
streamAudio = new StreamAudio(this);
|
||||||
streamAudio.setFile(VmFileManager.findAudioRaw(this, Config.vmID));
|
streamAudio.setFile(VmFileManager.findAudioRaw(this, Config.vmID));
|
||||||
|
|
||||||
|
if (!isConnected) tryReconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setDefaulViewMode() {
|
private void setDefaulViewMode() {
|
||||||
|
|
@ -187,7 +191,7 @@ public class MainVNCActivity extends VncCanvasActivity {
|
||||||
// screenMode = VNCScreenMode.FitToScreen;
|
// screenMode = VNCScreenMode.FitToScreen;
|
||||||
setLayout(getResources().getConfiguration());
|
setLayout(getResources().getConfiguration());
|
||||||
|
|
||||||
UIUtils.setOrientation(this);
|
//UIUtils.setOrientation(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -766,12 +770,14 @@ public class MainVNCActivity extends VncCanvasActivity {
|
||||||
setUIModeMobile(screenMode == VNCScreenMode.FitToScreen);
|
setUIModeMobile(screenMode == VNCScreenMode.FitToScreen);
|
||||||
|
|
||||||
binding.lnNosignal.setVisibility(View.GONE);
|
binding.lnNosignal.setVisibility(View.GONE);
|
||||||
|
binding.lnConnecting.setVisibility(View.GONE);
|
||||||
this.vncCanvas.setFocusableInTouchMode(true);
|
this.vncCanvas.setFocusableInTouchMode(true);
|
||||||
// syncCursorViewWithBitmap();
|
// syncCursorViewWithBitmap();
|
||||||
|
|
||||||
if (VmAudioManager.currentVmId.equals(Config.vmID) && VmAudioManager.streamAudio.isPlaying())
|
if (VmAudioManager.currentVmId.equals(Config.vmID) && VmAudioManager.streamAudio.isPlaying())
|
||||||
streamAudio.setCross(VmAudioManager.streamAudio);
|
streamAudio.setCross(VmAudioManager.streamAudio);
|
||||||
if (!streamAudio.isPlaying()) streamAudio.play();
|
if (!streamAudio.isPlaying()) streamAudio.play();
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -847,14 +853,16 @@ public class MainVNCActivity extends VncCanvasActivity {
|
||||||
binding.lnNosignal.setVisibility(View.VISIBLE);
|
binding.lnNosignal.setVisibility(View.VISIBLE);
|
||||||
binding.lnConnecting.setVisibility(View.GONE);
|
binding.lnConnecting.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
isTrying = false;
|
|
||||||
|
|
||||||
if (Config.forceRefeshVNCDisplay) {
|
if (Config.forceRefeshVNCDisplay) {
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
startActivity(new Intent(MainVNCActivity.this, MainVNCActivity.class));
|
startActivity(new Intent(MainVNCActivity.this, MainVNCActivity.class));
|
||||||
overridePendingTransition(0, 0);
|
overridePendingTransition(0, 0);
|
||||||
finish();
|
finish();
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
isTrying = false;
|
||||||
|
binding.lnNosignal.setVisibility(View.GONE);
|
||||||
|
binding.lnConnecting.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import com.vectras.vm.databinding.ActivityRomInfoBinding;
|
||||||
import com.vectras.vm.utils.DialogUtils;
|
import com.vectras.vm.utils.DialogUtils;
|
||||||
import com.vectras.vm.utils.FileUtils;
|
import com.vectras.vm.utils.FileUtils;
|
||||||
import com.vectras.vm.utils.ImageUtils;
|
import com.vectras.vm.utils.ImageUtils;
|
||||||
|
import com.vectras.vm.utils.IntentUtils;
|
||||||
import com.vectras.vm.utils.PackageUtils;
|
import com.vectras.vm.utils.PackageUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
@ -165,7 +166,13 @@ public class RomInfo extends AppCompatActivity {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (getIntent().hasExtra("isRomInfo") && getIntent().getBooleanExtra("isRomInfo", false)) {
|
if (getIntent().hasExtra("isRomInfo") && getIntent().getBooleanExtra("isRomInfo", false)) {
|
||||||
binding.btnPick.setOnClickListener(v -> romPicker.launch("*/*"));
|
binding.btnPick.setOnClickListener(v -> {
|
||||||
|
try {
|
||||||
|
romPicker.launch("*/*");
|
||||||
|
} catch (Exception e) {
|
||||||
|
IntentUtils.showErrorDialog(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
binding.btnPick.setVisibility(View.GONE);
|
binding.btnPick.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
@ -326,7 +333,8 @@ public class RomInfo extends AppCompatActivity {
|
||||||
String likeContent = getString(R.string.like);
|
String likeContent = getString(R.string.like);
|
||||||
boolean isLiked = interaction.isLiked();
|
boolean isLiked = interaction.isLiked();
|
||||||
likeContent = (likes == 0) ? getString(R.string.like) : interaction.getFormatedLikeCount();
|
likeContent = (likes == 0) ? getString(R.string.like) : interaction.getFormatedLikeCount();
|
||||||
if (isLiked) binding.btnLike.setIcon(ContextCompat.getDrawable(RomInfo.this, R.drawable.thumb_up_filled_24px));
|
if (isLiked)
|
||||||
|
binding.btnLike.setIcon(ContextCompat.getDrawable(RomInfo.this, R.drawable.thumb_up_filled_24px));
|
||||||
binding.btnLike.setText(likeContent);
|
binding.btnLike.setText(likeContent);
|
||||||
|
|
||||||
binding.lnAllViews.setVisibility(View.VISIBLE);
|
binding.lnAllViews.setVisibility(View.VISIBLE);
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ import com.vectras.vm.utils.ImageUtils;
|
||||||
import com.vectras.vm.utils.IntentUtils;
|
import com.vectras.vm.utils.IntentUtils;
|
||||||
import com.vectras.vm.utils.JSONUtils;
|
import com.vectras.vm.utils.JSONUtils;
|
||||||
import com.vectras.vm.utils.PackageUtils;
|
import com.vectras.vm.utils.PackageUtils;
|
||||||
|
import com.vectras.vm.utils.ProgressDialog;
|
||||||
import com.vectras.vm.utils.UIUtils;
|
import com.vectras.vm.utils.UIUtils;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
|
@ -87,7 +88,11 @@ public class VMCreatorActivity extends AppCompatActivity {
|
||||||
finish();
|
finish();
|
||||||
return true;
|
return true;
|
||||||
} else if (id == R.id.add_file) {
|
} else if (id == R.id.add_file) {
|
||||||
|
try {
|
||||||
filePicker.launch("*/*");
|
filePicker.launch("*/*");
|
||||||
|
} catch (Exception e) {
|
||||||
|
IntentUtils.showErrorDialog(this);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (id == R.id.show_in_folder) {
|
} else if (id == R.id.show_in_folder) {
|
||||||
FileUtils.openFolder(this, VmFileManager.getPath(vmID));
|
FileUtils.openFolder(this, VmFileManager.getPath(vmID));
|
||||||
|
|
@ -126,8 +131,20 @@ public class VMCreatorActivity extends AppCompatActivity {
|
||||||
|
|
||||||
binding.btnCreate.setOnClickListener(v -> startCreateVM());
|
binding.btnCreate.setOnClickListener(v -> startCreateVM());
|
||||||
|
|
||||||
binding.drive.setOnClickListener(v -> diskPicker.launch("*/*"));
|
binding.drive.setOnClickListener(v -> {
|
||||||
binding.driveField.setOnClickListener(v -> diskPicker.launch("*/*"));
|
try {
|
||||||
|
diskPicker.launch("*/*");
|
||||||
|
} catch (Exception e) {
|
||||||
|
IntentUtils.showErrorDialog(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
binding.driveField.setOnClickListener(v -> {
|
||||||
|
try {
|
||||||
|
diskPicker.launch("*/*");
|
||||||
|
} catch (Exception e) {
|
||||||
|
IntentUtils.showErrorDialog(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
binding.driveField.setEndIconOnClickListener(v -> {
|
binding.driveField.setEndIconOnClickListener(v -> {
|
||||||
if (Objects.requireNonNull(binding.drive.getText()).toString().isEmpty()) {
|
if (Objects.requireNonNull(binding.drive.getText()).toString().isEmpty()) {
|
||||||
|
|
@ -147,10 +164,21 @@ public class VMCreatorActivity extends AppCompatActivity {
|
||||||
true,
|
true,
|
||||||
R.drawable.hard_drive_24px,
|
R.drawable.hard_drive_24px,
|
||||||
true,
|
true,
|
||||||
() -> diskPicker.launch("*/*"),
|
() -> {
|
||||||
|
try {
|
||||||
|
diskPicker.launch("*/*");
|
||||||
|
} catch (Exception e) {
|
||||||
|
IntentUtils.showErrorDialog(this);
|
||||||
|
}
|
||||||
|
},
|
||||||
() -> {
|
() -> {
|
||||||
if (binding.drive.getText().toString().contains(VmFileManager.quickGetPath(vmID))) {
|
if (binding.drive.getText().toString().contains(VmFileManager.quickGetPath(vmID))) {
|
||||||
FileUtils.delete(new File(Objects.requireNonNull(binding.drive.getText()).toString()));
|
ProgressDialog progressDialog1 = new ProgressDialog(this);
|
||||||
|
progressDialog1.show();
|
||||||
|
new Thread(() -> {
|
||||||
|
FileUtils.delete(new File(Objects.requireNonNull(binding.drive.getText()).toString()));
|
||||||
|
runOnUiThread(progressDialog1::reset);
|
||||||
|
}).start();
|
||||||
}
|
}
|
||||||
binding.drive.setText("");
|
binding.drive.setText("");
|
||||||
binding.driveField.setEndIconDrawable(R.drawable.add_24px);
|
binding.driveField.setEndIconDrawable(R.drawable.add_24px);
|
||||||
|
|
@ -168,7 +196,13 @@ public class VMCreatorActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
View.OnClickListener cdromClickListener = v -> isoPicker.launch("*/*");
|
View.OnClickListener cdromClickListener = v -> {
|
||||||
|
try {
|
||||||
|
isoPicker.launch("*/*");
|
||||||
|
} catch (Exception e) {
|
||||||
|
IntentUtils.showErrorDialog(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
binding.cdrom.setOnClickListener(cdromClickListener);
|
binding.cdrom.setOnClickListener(cdromClickListener);
|
||||||
binding.cdromField.setOnClickListener(cdromClickListener);
|
binding.cdromField.setOnClickListener(cdromClickListener);
|
||||||
|
|
@ -310,7 +344,11 @@ public class VMCreatorActivity extends AppCompatActivity {
|
||||||
|
|
||||||
} else if (getIntent().hasExtra("importcvbinow")) {
|
} else if (getIntent().hasExtra("importcvbinow")) {
|
||||||
setDefault();
|
setDefault();
|
||||||
cvbiPicker.launch("*/*");
|
try {
|
||||||
|
cvbiPicker.launch("*/*");
|
||||||
|
} catch (Exception e) {
|
||||||
|
IntentUtils.showErrorDialog(this);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setDefault();
|
setDefault();
|
||||||
if (MainSettingsManager.autoCreateDisk(this)) {
|
if (MainSettingsManager.autoCreateDisk(this)) {
|
||||||
|
|
@ -777,10 +815,14 @@ public class VMCreatorActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void selectedDiskFile(Uri _content_describer, boolean _addtodrive) {
|
private void selectedDiskFile(Uri _content_describer, boolean _addtodrive) {
|
||||||
|
ProgressDialog progressDialog1 = new ProgressDialog(this);
|
||||||
|
progressDialog1.show();
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
if (FileUtils.isValidFilePath(this, FileUtils.getPath(this, _content_describer), false)) {
|
if (FileUtils.isValidFilePath(this, FileUtils.getPath(this, _content_describer), false)) {
|
||||||
File selectedFilePath = new File(getPath(_content_describer));
|
File selectedFilePath = new File(getPath(_content_describer));
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
|
progressDialog1.reset();
|
||||||
|
|
||||||
if (VMManager.isADiskFile(selectedFilePath.getPath())) {
|
if (VMManager.isADiskFile(selectedFilePath.getPath())) {
|
||||||
startProcessingHardDriveFile(_content_describer, _addtodrive);
|
startProcessingHardDriveFile(_content_describer, _addtodrive);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -849,9 +891,17 @@ public class VMCreatorActivity extends AppCompatActivity {
|
||||||
null);
|
null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
File selectedFilePath = new File(getPath(_content_describer));
|
|
||||||
binding.drive.setText(selectedFilePath.getPath());
|
ProgressDialog progressDialog1 = new ProgressDialog(this);
|
||||||
binding.driveField.setEndIconDrawable(R.drawable.more_vert_24px);
|
progressDialog1.show();
|
||||||
|
new Thread(() -> {
|
||||||
|
File selectedFilePath = new File(getPath(_content_describer));
|
||||||
|
runOnUiThread(() -> {
|
||||||
|
progressDialog1.reset();
|
||||||
|
binding.drive.setText(selectedFilePath.getPath());
|
||||||
|
binding.driveField.setEndIconDrawable(R.drawable.more_vert_24px);
|
||||||
|
});
|
||||||
|
}).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1030,7 +1080,7 @@ public class VMCreatorActivity extends AppCompatActivity {
|
||||||
if (jObj.has("vmID")) {
|
if (jObj.has("vmID")) {
|
||||||
if (!jObj.isNull("vmID")) {
|
if (!jObj.isNull("vmID")) {
|
||||||
if (!jObj.getString("vmID").isEmpty()) {
|
if (!jObj.getString("vmID").isEmpty()) {
|
||||||
FileUtils.move(VmFileManager.getConfigFile(vmID), VmFileManager.getConfigFile( jObj.getString("vmID")));
|
FileUtils.move(VmFileManager.getConfigFile(vmID), VmFileManager.getConfigFile(jObj.getString("vmID")));
|
||||||
vmID = jObj.getString("vmID");
|
vmID = jObj.getString("vmID");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import android.widget.Toast;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
import com.vectras.qemu.Config;
|
import com.vectras.qemu.Config;
|
||||||
import com.vectras.qemu.MainSettingsManager;
|
import com.vectras.qemu.MainSettingsManager;
|
||||||
|
|
@ -388,12 +389,16 @@ public class MainStartVM {
|
||||||
.load(new File(thumbnailFile))
|
.load(new File(thumbnailFile))
|
||||||
.placeholder(R.drawable.ic_computer_180dp_with_padding)
|
.placeholder(R.drawable.ic_computer_180dp_with_padding)
|
||||||
.error(R.drawable.ic_computer_180dp_with_padding)
|
.error(R.drawable.ic_computer_180dp_with_padding)
|
||||||
|
.skipMemoryCache(true)
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.into(ivThumbnail);
|
.into(ivThumbnail);
|
||||||
} else if (VmFileManager.isScreenshotPngExists(vmID)) {
|
} else if (VmFileManager.isScreenshotPngExists(vmID)) {
|
||||||
Glide.with(context.getApplicationContext())
|
Glide.with(context.getApplicationContext())
|
||||||
.load(new File(VmFileManager.getScreenshotPng(vmID)))
|
.load(new File(VmFileManager.getScreenshotPng(vmID)))
|
||||||
.placeholder(R.drawable.ic_computer_180dp_with_padding)
|
.placeholder(R.drawable.ic_computer_180dp_with_padding)
|
||||||
.error(R.drawable.ic_computer_180dp_with_padding)
|
.error(R.drawable.ic_computer_180dp_with_padding)
|
||||||
|
.skipMemoryCache(true)
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.into(ivThumbnail);
|
.into(ivThumbnail);
|
||||||
} else {
|
} else {
|
||||||
VMManager.setIconWithName(ivThumbnail, _content);
|
VMManager.setIconWithName(ivThumbnail, _content);
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import com.vectras.qemu.VNCConfig;
|
||||||
import com.vectras.vm.AppConfig;
|
import com.vectras.vm.AppConfig;
|
||||||
import com.vectras.vm.R;
|
import com.vectras.vm.R;
|
||||||
import com.vectras.vm.VMManager;
|
import com.vectras.vm.VMManager;
|
||||||
|
import com.vectras.vm.VectrasApp;
|
||||||
import com.vectras.vm.creator.VMCreatorActivity;
|
import com.vectras.vm.creator.VMCreatorActivity;
|
||||||
import com.vectras.vm.databinding.DialogChangeRemovableDevicesBinding;
|
import com.vectras.vm.databinding.DialogChangeRemovableDevicesBinding;
|
||||||
import com.vectras.vm.main.core.DisplaySystem;
|
import com.vectras.vm.main.core.DisplaySystem;
|
||||||
|
|
@ -108,6 +109,7 @@ public class VmControllerDialog extends DialogFragment {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isAdded() && (!(requireActivity() instanceof MainVNCActivity))) {
|
if (isAdded() && (!(requireActivity() instanceof MainVNCActivity))) {
|
||||||
|
if (streamAudio == null) streamAudio = new StreamAudio(requireActivity().getApplicationContext());
|
||||||
if (!streamAudio.isPlaying()) VmAudioManager.set(Config.vmID);
|
if (!streamAudio.isPlaying()) VmAudioManager.set(Config.vmID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,7 +145,8 @@ public class VmControllerDialog extends DialogFragment {
|
||||||
dismiss();
|
dismiss();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!isHavingSecondaryOpticalDisc()) binding.tvCdrom.setText(R.string.cdrom);
|
if (!isHavingSecondaryOpticalDisc())
|
||||||
|
binding.tvCdrom.setText(R.string.cdrom);
|
||||||
} else {
|
} else {
|
||||||
binding.lnCdrom.setVisibility(View.GONE);
|
binding.lnCdrom.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
@ -156,7 +159,8 @@ public class VmControllerDialog extends DialogFragment {
|
||||||
dismiss();
|
dismiss();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!isHavingOpticalDisc()) binding.tvSecondaryCdrom.setText(R.string.cdrom);
|
if (!isHavingOpticalDisc())
|
||||||
|
binding.tvSecondaryCdrom.setText(R.string.cdrom);
|
||||||
} else {
|
} else {
|
||||||
binding.lnSecondaryCdrom.setVisibility(View.GONE);
|
binding.lnSecondaryCdrom.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
@ -351,13 +355,20 @@ public class VmControllerDialog extends DialogFragment {
|
||||||
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
|
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
try {
|
try {
|
||||||
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(requireActivity(), uri)));
|
new Thread(() -> {
|
||||||
QmpSender.changeOpticalDisc(requireActivity(), selectedFilePath.getAbsolutePath(), infoBlock);
|
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(getContext(), uri)));
|
||||||
|
|
||||||
|
if (isAdded()) {
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
QmpSender.changeOpticalDisc(requireActivity(), selectedFilePath.getAbsolutePath(), infoBlock);
|
||||||
|
dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
showErrorSelectedFileDialog();
|
showErrorSelectedFileDialog();
|
||||||
|
dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
dismiss();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -365,13 +376,20 @@ public class VmControllerDialog extends DialogFragment {
|
||||||
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
|
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
try {
|
try {
|
||||||
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(requireActivity(), uri)));
|
new Thread(() -> {
|
||||||
QmpSender.changeSecondaryOpticalDisc(requireActivity(), selectedFilePath.getAbsolutePath(), infoBlock);
|
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(getContext(), uri)));
|
||||||
|
|
||||||
|
if (isAdded()) {
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
QmpSender.changeSecondaryOpticalDisc(requireActivity(), selectedFilePath.getAbsolutePath(), infoBlock);
|
||||||
|
dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
showErrorSelectedFileDialog();
|
showErrorSelectedFileDialog();
|
||||||
|
dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
dismiss();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -379,13 +397,20 @@ public class VmControllerDialog extends DialogFragment {
|
||||||
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
|
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
try {
|
try {
|
||||||
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(requireActivity(), uri)));
|
new Thread(() -> {
|
||||||
QmpSender.changeFloppyDiskA(requireActivity(), selectedFilePath.getAbsolutePath());
|
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(getContext(), uri)));
|
||||||
|
|
||||||
|
if (isAdded()) {
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
QmpSender.changeFloppyDiskA(requireActivity(), selectedFilePath.getAbsolutePath());
|
||||||
|
dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
showErrorSelectedFileDialog();
|
showErrorSelectedFileDialog();
|
||||||
|
dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
dismiss();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -393,13 +418,20 @@ public class VmControllerDialog extends DialogFragment {
|
||||||
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
|
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
try {
|
try {
|
||||||
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(requireActivity(), uri)));
|
new Thread(() -> {
|
||||||
QmpSender.changeFloppyDiskB(requireActivity(), selectedFilePath.getAbsolutePath());
|
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(getContext(), uri)));
|
||||||
|
|
||||||
|
if (isAdded()) {
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
QmpSender.changeFloppyDiskB(requireActivity(), selectedFilePath.getAbsolutePath());
|
||||||
|
dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
showErrorSelectedFileDialog();
|
showErrorSelectedFileDialog();
|
||||||
|
dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
dismiss();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -407,13 +439,20 @@ public class VmControllerDialog extends DialogFragment {
|
||||||
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
|
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
try {
|
try {
|
||||||
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(requireActivity(), uri)));
|
new Thread(() -> {
|
||||||
QmpSender.changeMemoryCard(requireActivity(), selectedFilePath.getAbsolutePath());
|
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(getContext(), uri)));
|
||||||
|
|
||||||
|
if (isAdded()) {
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
QmpSender.changeMemoryCard(requireActivity(), selectedFilePath.getAbsolutePath());
|
||||||
|
dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
showErrorSelectedFileDialog();
|
showErrorSelectedFileDialog();
|
||||||
|
dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
dismiss();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,70 +30,103 @@
|
||||||
android:keepScreenOn="true" />
|
android:keepScreenOn="true" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<!-- <LinearLayout-->
|
<RelativeLayout
|
||||||
<!-- android:id="@+id/cursorViewContianer"-->
|
android:id="@+id/vnc_main_layout"
|
||||||
<!-- android:layout_width="match_parent"-->
|
android:layout_width="match_parent"
|
||||||
<!-- android:layout_height="match_parent"-->
|
android:layout_height="match_parent">
|
||||||
<!-- android:gravity="center">-->
|
|
||||||
<!-- <android.androidVNC.VncCursorView-->
|
|
||||||
<!-- android:id="@+id/cursorView"-->
|
|
||||||
<!-- android:layout_width="wrap_content"-->
|
|
||||||
<!-- android:layout_height="wrap_content"/>-->
|
|
||||||
<!-- </LinearLayout>-->
|
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/controlsfragment"
|
android:id="@+id/controlsfragment"
|
||||||
layout="@layout/controls_fragment" />
|
layout="@layout/controls_fragment" />
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/sendkeysdialog"
|
android:id="@+id/sendkeysdialog"
|
||||||
layout="@layout/send_key_dialog" />
|
layout="@layout/send_key_dialog" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- <LinearLayout-->
|
||||||
|
<!-- android:id="@+id/cursorViewContianer"-->
|
||||||
|
<!-- android:layout_width="match_parent"-->
|
||||||
|
<!-- android:layout_height="match_parent"-->
|
||||||
|
<!-- android:gravity="center">-->
|
||||||
|
<!-- <android.androidVNC.VncCursorView-->
|
||||||
|
<!-- android:id="@+id/cursorView"-->
|
||||||
|
<!-- android:layout_width="wrap_content"-->
|
||||||
|
<!-- android:layout_height="wrap_content"/>-->
|
||||||
|
<!-- </LinearLayout>-->
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/ln_nosignal"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="#E6000000"
|
android:animateLayoutChanges="true"
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<ImageView
|
<FrameLayout
|
||||||
android:layout_width="48dp"
|
android:id="@+id/ln_nosignal"
|
||||||
android:layout_height="48dp"
|
android:layout_width="match_parent"
|
||||||
android:src="@drawable/cast_warning_24px"
|
android:layout_height="match_parent">
|
||||||
app:tint="@android:color/white" />
|
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:padding="16dp"
|
android:alpha="0.8"
|
||||||
android:text="@string/no_signal"
|
android:background="?attr/colorSurfaceContainer" />
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="20sp" />
|
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:text="@string/tap_to_try_again"
|
android:gravity="center"
|
||||||
android:textColor="@android:color/white" />
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:src="@drawable/cast_warning_24px"
|
||||||
|
app:tint="?attr/colorOnSurface" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:text="@string/no_signal"
|
||||||
|
android:textColor="?attr/colorOnSurface"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/tap_to_try_again"
|
||||||
|
android:textColor="?attr/colorOnSurface" />
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/ln_connecting"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:alpha="0.8"
|
||||||
|
android:background="?attr/colorSurfaceContainer" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:indeterminate="true" />
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
</LinearLayout>
|
</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>
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ annotation = "1.10.0"
|
||||||
appcompat = "1.7.1"
|
appcompat = "1.7.1"
|
||||||
comGoogleFirebase = "firebase-crashlytics"
|
comGoogleFirebase = "firebase-crashlytics"
|
||||||
commonsCompress = "1.28.0"
|
commonsCompress = "1.28.0"
|
||||||
commonsIo = "2.21.0"
|
commonsIo = "2.22.0"
|
||||||
constraintlayout = "2.2.1"
|
constraintlayout = "2.2.1"
|
||||||
coreKtx = "1.18.0"
|
coreKtx = "1.18.0"
|
||||||
documentfile = "1.1.0"
|
documentfile = "1.1.0"
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@
|
||||||
"url": "https://github.com/xoureldeen/Vectras-VM-Android/releases",
|
"url": "https://github.com/xoureldeen/Vectras-VM-Android/releases",
|
||||||
"Message": "<h2>4.0.0</h2>\nBugs fixed.",
|
"Message": "<h2>4.0.0</h2>\nBugs fixed.",
|
||||||
"cancellable": true,
|
"cancellable": true,
|
||||||
"versionCodeBeta":"105",
|
"versionCodeBeta":"106",
|
||||||
"versionNameBeta":"4.0.1",
|
"versionNameBeta":"4.0.2",
|
||||||
"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",
|
"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,4.0.2",
|
||||||
"sizeBeta": "45 MB",
|
"sizeBeta": "45 MB",
|
||||||
"urlBeta": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases",
|
"urlBeta": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases",
|
||||||
"MessageBeta": "<h2>4.0.1</h2>Bugs fixed.",
|
"MessageBeta": "<h2>4.0.2</h2>Bugs fixed.",
|
||||||
"cancellableBeta": true
|
"cancellableBeta": true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue