mirror of
https://github.com/xoureldeen/Vectras-VM-Android.git
synced 2026-07-09 17:28:54 +00:00
4.1.5
- Added quick switching between running virtual machines to the VNC screen. - Removed the option button from the virtual machine list, replaced by a long press. - Fixed issues where other virtual machines would unexpectedly shut down when the first one was shut down. - Improved the interface. - Bugs fixed.
This commit is contained in:
parent
aeff4a5a4b
commit
6c73672230
21 changed files with 262 additions and 32 deletions
|
|
@ -12,8 +12,8 @@ android {
|
|||
applicationId "com.vectras.vm"
|
||||
minSdk minApi
|
||||
targetSdk targetApi
|
||||
versionCode 118
|
||||
versionName "4.1.4"
|
||||
versionCode 119
|
||||
versionName "4.1.5"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled true
|
||||
|
||||
|
|
|
|||
|
|
@ -157,6 +157,10 @@ public class Config {
|
|||
return Config.getCacheDir()+ "/" + vmID + "/vncsocket";
|
||||
}
|
||||
|
||||
public static String getLocalVNCSocketPath(String vmId) {
|
||||
return Config.getCacheDir()+ "/" + vmId + "/vncsocket";
|
||||
}
|
||||
|
||||
public static String getCacheVMPath() {
|
||||
return Config.getCacheDir()+ "/" + vmID + "/";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -864,7 +864,6 @@ public class MainVNCActivity extends VncCanvasActivity {
|
|||
bindingSendKey.sendtextEdittext.setEnabled(false);
|
||||
QmpSender.quickShutdown();
|
||||
Config.setDefault();
|
||||
MainService.stopService();
|
||||
finish();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import com.vectras.vm.main.vms.DataMainRoms;
|
|||
import com.vectras.vm.manager.QmpSender;
|
||||
import com.vectras.vm.manager.VmFileManager;
|
||||
import com.vectras.vm.manager.VmActions;
|
||||
import com.vectras.vm.manager.VmServiceManager;
|
||||
import com.vectras.vm.settings.X11DisplaySettingsActivity;
|
||||
import com.vectras.vm.utils.DialogUtils;
|
||||
import com.vectras.vm.utils.FileUtils;
|
||||
|
|
@ -657,6 +658,8 @@ public class VMManager {
|
|||
return false;
|
||||
}
|
||||
|
||||
VmServiceManager.stopService(_activity);
|
||||
|
||||
if (_command.contains("qemu-system") && _result.contains("Killed")) {
|
||||
isQemuStopedWithError = true;
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import com.vectras.vm.manager.VmAudioManager;
|
|||
import com.vectras.vm.manager.VmControllerDialog;
|
||||
|
||||
public class RomOptionsDialog {
|
||||
public static void showNow(Activity activity, int position, String vmID, String vmName) {
|
||||
public static void show(Activity activity, int position, String vmID, String vmName) {
|
||||
if (VMManager.isVMRunning(activity, vmID)) {
|
||||
VmControllerDialog vmControllerDialog = new VmControllerDialog();
|
||||
vmControllerDialog.streamAudio = VmAudioManager.streamAudio;
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ public class SoftwareStoreHomeAdapter extends RecyclerView.Adapter<RecyclerView.
|
|||
// Get current position of item in recyclerview to bind data and assign values from list
|
||||
final MyHolder myHolder = (MyHolder) holder;
|
||||
final DataRoms current = displayList.get(position);
|
||||
Glide.with(context).load(current.romIcon).override(180, 180).placeholder(R.drawable.ic_computer_180dp_with_padding).error(R.drawable.ic_computer_180dp_with_padding).into(myHolder.ivIcon);
|
||||
Glide.with(context).load(current.romIcon).override(180, 180).placeholder(R.drawable.ic_deployed_code_180px_with_padding).error(R.drawable.ic_deployed_code_180px_with_padding).into(myHolder.ivIcon);
|
||||
myHolder.textName.setText(current.romName);
|
||||
myHolder.textSize.setText(current.romSize);
|
||||
if (current.romAvail) {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.vectras.qemu.Config;
|
||||
import com.vectras.vm.AppConfig;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.StartVM;
|
||||
import com.vectras.vm.VMManager;
|
||||
|
|
@ -78,7 +77,6 @@ public class VmsHomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
|||
} else {
|
||||
VMManager.setIconWithName(myHolder.ivIcon, current.itemName);
|
||||
}
|
||||
myHolder.optionsBtn.setOnClickListener(view -> RomOptionsDialog.showNow(activity, position, current.vmID, current.itemName));
|
||||
|
||||
myHolder.cdRoms.setOnClickListener(view -> {
|
||||
VMManager.setArch(current.itemArch, activity);
|
||||
|
|
@ -96,8 +94,8 @@ public class VmsHomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
|||
});
|
||||
|
||||
myHolder.cdRoms.setOnLongClickListener(v -> {
|
||||
VMManager.deleteVMDialog(current.itemName, position, activity);
|
||||
return false;
|
||||
RomOptionsDialog.show(activity, position, current.vmID, current.itemName);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.vectras.vm.manager;
|
|||
|
||||
import android.androidVNC.ConnectionBean;
|
||||
import android.androidVNC.VncCanvas;
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
|
|
@ -36,6 +37,8 @@ import com.vectras.vm.utils.ProgressDialog;
|
|||
import com.vectras.vm.utils.StreamAudio;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
|
@ -109,6 +112,41 @@ public class VmControllerDialog extends DialogFragment {
|
|||
}
|
||||
dismiss();
|
||||
});
|
||||
|
||||
binding.lnSwitch.setVisibility(View.GONE);
|
||||
} else if (requireActivity() instanceof MainVNCActivity) {
|
||||
ArrayList<HashMap<String, Object>> list = VmListManager.getAllVmForPickRunningVncSocketOnly(requireActivity());
|
||||
|
||||
if (list.isEmpty() || (list.size() == 1 && Objects.requireNonNull(list.get(0).get("value")).toString().equals(Config.vmID))) {
|
||||
binding.lnManage.setVisibility(View.GONE);
|
||||
} else {
|
||||
binding.lnSwitch.setOnClickListener(v -> {
|
||||
if (isAdded()) {
|
||||
VmPicker vmPicker = new VmPicker(requireActivity());
|
||||
vmPicker.currentVmId= Config.vmID;
|
||||
vmPicker.listVm = list;
|
||||
vmPicker.pick((position, name, value) -> {
|
||||
if (Config.vmID.equals(value)) return;
|
||||
|
||||
if (position < 0) {
|
||||
DialogUtils.oopsDialog(requireActivity(), getString(R.string.no_vms_are_available));
|
||||
return;
|
||||
}
|
||||
|
||||
Config.vmID = value;
|
||||
streamAudio.setCross(null);
|
||||
streamAudio.stop();
|
||||
requireActivity().recreate();
|
||||
|
||||
dismiss();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
binding.lnConnect.setVisibility(View.GONE);
|
||||
binding.lnEdit.setVisibility(View.GONE);
|
||||
binding.lnRemove.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
binding.lnManage.setVisibility(View.GONE);
|
||||
}
|
||||
|
|
|
|||
67
app/src/main/java/com/vectras/vm/manager/VmListManager.java
Normal file
67
app/src/main/java/com/vectras/vm/manager/VmListManager.java
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
package com.vectras.vm.manager;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.vectras.qemu.Config;
|
||||
import com.vectras.vm.AppConfig;
|
||||
import com.vectras.vm.creator.ListManager;
|
||||
import com.vectras.vm.main.vms.DataMainRoms;
|
||||
import com.vectras.vm.utils.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class VmListManager {
|
||||
public static ArrayList<HashMap<String, Object>> getAllVmForPickRunningVncSocketOnly(Context context) {
|
||||
ArrayList<HashMap<String, Object>> listVm = getAllVmForPick(context);
|
||||
ArrayList<HashMap<String, Object>> list = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < listVm.size(); i++) {
|
||||
if (FileUtils.isFileExists(Config.getLocalVNCSocketPath(Objects.requireNonNull(listVm.get(i).get("value")).toString()))) {
|
||||
list.add(listVm.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static ArrayList<HashMap<String, Object>> getAllVmForPickRunningOnly(Context context) {
|
||||
ArrayList<HashMap<String, Object>> listVm = getAllVmForPick(context);
|
||||
ArrayList<HashMap<String, Object>> list = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < listVm.size(); i++) {
|
||||
if (FileUtils.isFileExists(Config.getLocalQMPSocketPath(Objects.requireNonNull(listVm.get(i).get("value")).toString()))) {
|
||||
list.add(listVm.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static ArrayList<HashMap<String, Object>> getAllVmForPick(Context context) {
|
||||
ArrayList<HashMap<String, Object>> list = new ArrayList<>();
|
||||
|
||||
List<DataMainRoms> data = getAllVm(context);
|
||||
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
ListManager.putToList(list, data.get(i).itemName, data.get(i).vmID);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static List<DataMainRoms> getAllVm(Context context) {
|
||||
Gson gson = new Gson();
|
||||
Type listType = new TypeToken<List<DataMainRoms>>(){}.getType();
|
||||
|
||||
String json = FileUtils.readFromFile(context, new File(AppConfig.romsdatajson));
|
||||
|
||||
return gson.fromJson(json, listType);
|
||||
}
|
||||
}
|
||||
49
app/src/main/java/com/vectras/vm/manager/VmPicker.java
Normal file
49
app/src/main/java/com/vectras/vm/manager/VmPicker.java
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
package com.vectras.vm.manager;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.creator.VMCreatorSelector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class VmPicker {
|
||||
public boolean isRunningOnly;
|
||||
public String currentVmId = "";
|
||||
private Activity activity;
|
||||
ArrayList<HashMap<String, Object>> listVm;
|
||||
|
||||
public interface VMPickerCallback {
|
||||
void onSelected(int position, String name, String vmId);
|
||||
}
|
||||
|
||||
public VmPicker(Activity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
public void pick(VMPickerCallback callback) {
|
||||
ArrayList<HashMap<String, Object>> list = listVm != null ? listVm : (isRunningOnly ? VmListManager.getAllVmForPickRunningOnly(activity) : VmListManager.getAllVmForPick(activity));
|
||||
|
||||
if (list.isEmpty()) callback.onSelected(-1, "", "");
|
||||
|
||||
int position = -1;
|
||||
|
||||
if (!currentVmId.isEmpty()) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (Objects.equals(list.get(i).get("value"), currentVmId)) {
|
||||
position = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VMCreatorSelector.showDialog(
|
||||
activity,
|
||||
list,
|
||||
position,
|
||||
(callback::onSelected),
|
||||
activity.getString(R.string.switch_to));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.vectras.vm.manager;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.vectras.vm.MainService;
|
||||
import com.vectras.vterm.Terminal;
|
||||
|
||||
public class VmServiceManager {
|
||||
public static void stopService(Context context) {
|
||||
new Thread(() -> {
|
||||
if (!Terminal.executeShellCommandWithResult("ps -e", context).contains("qemu-system-")) {
|
||||
new Handler(Looper.getMainLooper()).post(MainService::stopService);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
11
app/src/main/res/drawable/compare_arrows_24px.xml
Normal file
11
app/src/main/res/drawable/compare_arrows_24px.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:autoMirrored="true">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M320,800L264,743L367,640L80,640L80,560L367,560L264,457L320,400L520,600L320,800ZM640,560L440,360L640,160L696,217L593,320L880,320L880,400L593,400L696,503L640,560Z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/deployed_code_180px.xml
Normal file
10
app/src/main/res/drawable/deployed_code_180px.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="180dp"
|
||||
android:height="180dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M440,777L440,503L200,364L200,638Q200,638 200,638Q200,638 200,638L440,777ZM520,777L760,638Q760,638 760,638Q760,638 760,638L760,364L520,503L520,777ZM480,434L717,297L480,160Q480,160 480,160Q480,160 480,160L243,297L480,434ZM160,708Q141,697 130.5,679Q120,661 120,639L120,321Q120,299 130.5,281Q141,263 160,252L440,91Q459,80 480,80Q501,80 520,91L800,252Q819,263 829.5,281Q840,299 840,321L840,639Q840,661 829.5,679Q819,697 800,708L520,869Q501,880 480,880Q459,880 440,869L160,708ZM480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Z"/>
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<inset xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:drawable="@drawable/deployed_code_180px"
|
||||
android:inset="48dp" />
|
||||
|
|
@ -73,7 +73,9 @@
|
|||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/more_vert_24px" />
|
||||
android:src="@drawable/more_vert_24px"
|
||||
android:visibility="gone"
|
||||
tools:visibility="gone" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
|
@ -90,6 +90,26 @@
|
|||
android:textColor="?attr/colorError"
|
||||
android:text="@string/remove"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ln_switch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingVertical="8dp"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:background="?attr/selectableItemBackground">
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/compare_arrows_24px"/>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
android:textColor="?attr/colorControlNormal"
|
||||
android:text="@string/switchtext"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
|
|
|||
|
|
@ -569,6 +569,10 @@
|
|||
<string name="edge_to_edge">Tràn cạnh</string>
|
||||
<string name="disable_edge_to_edge">Tắt tràn cạnh</string>
|
||||
<string name="pinch_to_zoom">Chụm ngón tay để thu phóng</string>
|
||||
<string name="vm_picker">Trình chọn máy ảo</string>
|
||||
<string name="switchtext">Chuyển đổi</string>
|
||||
<string name="switch_to">Chuyển sang</string>
|
||||
<string name="no_vms_are_available">Không có máy ảo nào khả dụng.</string>
|
||||
|
||||
<!--======================TERMUX STRINGS====================-->
|
||||
<string name="application_name" translatable="false">Vterm</string>
|
||||
|
|
|
|||
|
|
@ -580,6 +580,10 @@
|
|||
<string name="edge_to_edge">Edge-to-edge</string>
|
||||
<string name="disable_edge_to_edge">Disable edge-to-edge</string>
|
||||
<string name="pinch_to_zoom">Pinch to zoom</string>
|
||||
<string name="vm_picker">VM picker</string>
|
||||
<string name="switchtext">Switch</string>
|
||||
<string name="switch_to">Switch to</string>
|
||||
<string name="no_vms_are_available">No virtual machines are available.</string>
|
||||
|
||||
|
||||
<!--======================TERMUX STRINGS====================-->
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue