- If the ROM import process cannot be calculated, it will display the extracted file size.
- The issue of slow ROM import caused by the inability to obtain the file path has been fixed.
- Bugs fixed.
This commit is contained in:
An Bui 2026-01-18 16:46:35 +07:00
parent 141b8468c9
commit 960e76f374
9 changed files with 114 additions and 66 deletions

View file

@ -12,8 +12,8 @@ android {
applicationId "com.vectras.vm"
minSdk minApi
targetSdk targetApi
versionCode 75
versionName "3.7.1"
versionCode 76
versionName "3.7.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true

View file

@ -1,24 +1,20 @@
package com.vectras.vm.Fragment;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Toast;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.R;
import com.vectras.vm.VectrasApp;
import com.vectras.vm.adapter.LogsAdapter;
@ -27,28 +23,25 @@ import com.vectras.vm.logger.VectrasStatus;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Objects;
import java.util.Timer;
import java.util.TimerTask;
public class LoggerDialogFragment extends DialogFragment {
private final String TAG = "LoggerDialogFragment";
private final Timer _timer = new Timer();
private boolean isReading;
private final String CREDENTIAL_SHARED_PREF = "settings_prefs";
private LogsAdapter mLogAdapter;
private RecyclerView logList;
private Timer _timer = new Timer();
private TimerTask t;
Activity activity;
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
activity = getActivity();
final Dialog alertDialog = new Dialog(getActivity(), R.style.MainDialogTheme);
final Dialog alertDialog = new Dialog(requireActivity(), R.style.MainDialogTheme);
alertDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
alertDialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
Objects.requireNonNull(alertDialog.getWindow()).setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
alertDialog.setContentView(R.layout.fragment_logs);
LinearLayoutManager layoutManager = new LinearLayoutManager(VectrasApp.getApp());
mLogAdapter = new LogsAdapter(layoutManager, VectrasApp.getApp());
logList = (RecyclerView) alertDialog.findViewById(R.id.recyclerLog);
LogsAdapter mLogAdapter = new LogsAdapter(layoutManager, VectrasApp.getApp());
RecyclerView logList = alertDialog.findViewById(R.id.recyclerLog);
logList.setAdapter(mLogAdapter);
logList.setLayoutManager(layoutManager);
mLogAdapter.scrollToLastPosition();
@ -60,32 +53,54 @@ public class LoggerDialogFragment extends DialogFragment {
BufferedReader bufferedReader2 = new BufferedReader(
new InputStreamReader(process2.getInputStream()));
t = new TimerTask() {
TimerTask t = new TimerTask() {
@Override
public void run() {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
try {
if (bufferedReader.readLine() != null || bufferedReader2.readLine() != null) {
String logLine = bufferedReader.readLine();
String logLine2 = bufferedReader2.readLine();
VectrasStatus.logError("<font color='red'>[E] "+logLine+"</font>");
VectrasStatus.logError("<font color='#FFC107'>[W] "+logLine2+"</font>");
}
} catch (IOException e) {
throw new RuntimeException(e);
new Thread(() -> {
if (isReading) return;
String logLine = "";
String logLine2 = "";
try {
isReading = true;
if (bufferedReader.readLine() != null || bufferedReader2.readLine() != null) {
logLine = bufferedReader.readLine();
logLine2 = bufferedReader2.readLine();
}
String finalLogLine = logLine;
String finalLogLine1 = logLine2;
if (!isAdded()) {
_timer.cancel();
return;
}
requireActivity().runOnUiThread(() -> {
if (!finalLogLine.isEmpty())
VectrasStatus.logError("<font color='red'>[E] " + finalLogLine + "</font>");
if (!finalLogLine1.isEmpty())
VectrasStatus.logError("<font color='#FFC107'>[W] " + finalLogLine1 + "</font>");
isReading = false;
});
} catch (IOException e) {
Log.e(TAG, "onCreateDialog: ", e);
} finally {
isReading = false;
}
});
}).start();
}
};
_timer.scheduleAtFixedRate(t, (int) (0), (int) (100));
_timer.schedule(t, 0, 1000);
} catch (IOException e) {
Toast.makeText(activity, "There was an error: " + Log.getStackTraceString(e), Toast.LENGTH_LONG).show();
e.printStackTrace();
if (isAdded())
Toast.makeText(requireActivity(), "There was an error: " + Log.getStackTraceString(e), Toast.LENGTH_LONG).show();
Log.e(TAG, "onCreateDialog: ", e);
}
alertDialog.show();
return alertDialog;
}
public void onDismiss(@NonNull DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
_timer.cancel();
}
}

View file

@ -351,7 +351,7 @@ public class VMCreatorActivity extends AppCompatActivity {
if (isImportingCVBI) return;
if (!created && !modify) {
new Thread(() -> FileUtils.deleteDirectory(AppConfig.vmFolder + vmID)).start();
new Thread(() -> FileUtils.delete(new File (AppConfig.vmFolder + vmID))).start();
}
modify = false;
finish();
@ -466,7 +466,7 @@ public class VMCreatorActivity extends AppCompatActivity {
String filePath;
try {
File selectedFilePath = new File(getPath(uri));
filePath = selectedFilePath.getPath();
filePath = selectedFilePath.getAbsolutePath();
} catch (Exception e) {
filePath = "";
}
@ -930,7 +930,7 @@ public class VMCreatorActivity extends AppCompatActivity {
progressDialog.show();
Log.i(TAG, "importRom: Extracting from " + filePath + " to " + AppConfig.vmFolder + vmID);
Log.i(TAG, "importRom: Extracting with " + (isUseUri ? "uri" : "path") + " from " + filePath + " to " + AppConfig.vmFolder + vmID);
new Thread(() -> {
boolean result = isUseUri ? ZipUtils.extract(

View file

@ -752,25 +752,32 @@ public class FileUtils {
return true;
}
@Deprecated
public static void deleteDirectory(String _pathToDelete) {
File _dir = new File(_pathToDelete);
if (_dir.isDirectory()) {
String[] children = _dir.list();
delete(new File(_pathToDelete));
}
public static boolean delete(File file) {
if (!file.exists()) return true;
if (file.isDirectory()) {
String[] children = file.list();
if (children == null) {
Log.e("ERROR", "Deletion failed. " + _dir);
return;
Log.e(TAG, "delete: Failed:" + file);
return false;
}
for (int i = 0; i < children.length; i++) {
File temp = new File(_dir, children[i]);
deleteDirectory(String.valueOf(temp));
File temp = new File(file, children[i]);
delete(temp);
}
}
boolean success = _dir.delete();
boolean success = file.delete();
if (!success) {
Log.e("ERROR", "Deletion failed. " + _dir);
Log.e(TAG, "delete: Failed: " + file);
}
return success;
}
public static boolean canRead(String filePath) {

View file

@ -1,5 +1,7 @@
package com.vectras.vm.utils;
import java.util.Locale;
public class NumberUtils {
public static int safeLongToInt(long l) {
if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
@ -7,4 +9,14 @@ public class NumberUtils {
}
return (int) l;
}
public static String getFormatSizeFromMB(long mb) {
if (mb < 1024) {
return mb + " MB";
} else {
double gb = mb / 1024.0;
return String.format(Locale.US, "%.2f GB", gb);
}
}
}

View file

@ -1,5 +1,7 @@
package com.vectras.vm.utils;
import static android.os.Build.VERSION.SDK_INT;
import android.app.Activity;
import android.content.Context;
import android.net.Uri;
@ -14,7 +16,6 @@ import com.vectras.vm.R;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@ -138,12 +139,12 @@ public class ZipUtils {
if (MainSettingsManager.getSmartSizeCalculation(context)) {
// >7GB
sizeCalculation = DeviceUtils.totalMemoryCapacity(context) > 7L * 1024 * 1024 * 1024;
sizeCalculation = SDK_INT < 31 && DeviceUtils.totalMemoryCapacity(context) > 7L * 1024 * 1024 * 1024;
} else {
sizeCalculation = true;
sizeCalculation = false;
}
//Can be skipped as it may not get the size and is time consuming.
//Can be skipped as it may not get the size and is time-consuming.
if (sizeCalculation) {
InputStream inputStream = context.getContentResolver().openInputStream(fileZip);
@ -190,12 +191,10 @@ public class ZipUtils {
long lastProgress = -1;
while ((len = zin.read(buffer)) > 0) {
fos.write(buffer, 0, len);
if (totalSize < 0) {
fileExtracted += len;
extractedSize += len;
long progress = (totalSize > 0) ? (extractedSize * 100 / totalSize) : 0;
fileExtracted += len;
extractedSize += len;
if (totalSize > 0) {
long progress = extractedSize * 100 / totalSize;
if (progress > lastProgress) {
lastProgress = progress;
@ -209,6 +208,20 @@ public class ZipUtils {
(int) progress
);
}
} else {
if (extractedSize > lastProgress + (1024 * 1024) || lastProgress < 1) {
lastProgress = extractedSize;
long mb = extractedSize / (1024 * 1024);
updateStatus(
statusTextView,
progressBar,
(mb == 0 ?
context.getString(R.string.importing) :
context.getString(R.string.completed) + " " + NumberUtils.getFormatSizeFromMB(mb))
+ "\n" + context.getString(R.string.please_stay_here),
0
);
}
}
}
fos.close();
@ -369,7 +382,7 @@ public class ZipUtils {
if (progressbar.getMax() != 100) progressbar.setMax(100);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
if (SDK_INT >= Build.VERSION_CODES.N) {
progressbar.setProgress(progress, true);
} else {
progressbar.setProgress(progress);

View file

@ -201,7 +201,6 @@ public class LorieView extends SurfaceView implements InputStub {
@Override
public void sendMouseWheelEvent(float deltaX, float deltaY) {
if (!PackageUtils.isClassAvailable("com.termux.x11.CmdEntryPoint")) return;
sendMouseEvent(deltaX, deltaY, BUTTON_SCROLL, false, true);
}

View file

@ -14,6 +14,7 @@ import android.graphics.PointF;
import android.view.KeyEvent;
import android.view.MotionEvent;
import com.vectras.vm.utils.PackageUtils;
import com.vectras.vm.x11.X11Activity;
import java.util.List;
@ -75,6 +76,7 @@ public final class InputEventSender {
}
public void sendCursorMove(float x, float y, boolean relative) {
if (!PackageUtils.isClassAvailable("com.termux.x11.CmdEntryPoint")) return;
mInjector.sendMouseEvent(x, y, BUTTON_UNDEFINED, false, relative);
}

View file

@ -5,11 +5,11 @@
"url": "https://github.com/xoureldeen/Vectras-VM-Android/releases",
"Message": "<h2>3.7.0</h2>\nBugs fixed.",
"cancellable": true,
"versionCodeBeta":"75",
"versionNameBeta":"3.7.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.0,3.7.1",
"versionCodeBeta":"76",
"versionNameBeta":"3.7.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.0,3.7.1,3.7.2",
"sizeBeta": "45 MB",
"urlBeta": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases",
"MessageBeta": "<h2>3.7.1</h2>Bugs fixed.",
"MessageBeta": "<h2>3.7.2</h2>Bugs fixed.",
"cancellableBeta": true
}