diff --git a/app/build.gradle b/app/build.gradle
index 5e65ccc..9289d89 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -15,8 +15,8 @@ android {
applicationId "com.vectras.vm"
minSdk minApi
targetSdk targetApi
- versionCode 70
- versionName "3.6.6"
+ versionCode 71
+ versionName "3.6.7"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4d5446d..3eb2f99 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -130,7 +130,7 @@
android:exported="true"
android:hardwareAccelerated="true" />
diff --git a/app/src/main/java/com/vectras/vm/ExportRomActivity.java b/app/src/main/java/com/vectras/vm/ExportRomActivity.java
index 20bb87f..13492fd 100644
--- a/app/src/main/java/com/vectras/vm/ExportRomActivity.java
+++ b/app/src/main/java/com/vectras/vm/ExportRomActivity.java
@@ -5,19 +5,22 @@ import android.app.Activity;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.activity.OnBackPressedCallback;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
import com.vectras.vm.databinding.ActivityExportRomBinding;
+import com.vectras.vm.main.vms.DataMainRoms;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.PackageUtils;
@@ -31,16 +34,12 @@ import java.util.Objects;
public class ExportRomActivity extends AppCompatActivity {
+ private final String TAG = "ExportRomActivity";
ActivityExportRomBinding binding;
- public static int pendingPosition = 0;
- public static HashMap mapForGetData = new HashMap<>();
- public static ArrayList> listmapForGetData = new ArrayList<>();
private SharedPreferences data;
- public String getRomPath = "";
- public String iconfile = "";
- public String diskfile = "";
- public String cdromfile = "";
private boolean isExporting = false;
+ private ActivityResultLauncher folderPicker;
+ private DataMainRoms current;
@Override
@@ -59,7 +58,7 @@ public class ExportRomActivity extends AppCompatActivity {
binding.edContent.setEnabled(false);
binding.edAuthor.setEnabled(true);
binding.edContent.setEnabled(true);
- startCreate();
+ folderPicker.launch(current.itemName + ".cvbi");
});
data = getSharedPreferences("data", Activity.MODE_PRIVATE);
@@ -67,6 +66,16 @@ public class ExportRomActivity extends AppCompatActivity {
binding.edAuthor.setText(data.getString("author", ""));
binding.edContent.setText(data.getString("desc", ""));
+ current = VMManager.getVMConfig(getIntent().getIntExtra("POS", 0));
+
+ folderPicker = registerForActivityResult(
+ new ActivityResultContracts.CreateDocument("application/octet-stream"),
+ uri -> {
+ if (uri != null) {
+ startCreate(uri);
+ }
+ });
+
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
@@ -87,8 +96,9 @@ public class ExportRomActivity extends AppCompatActivity {
}
@SuppressLint("SetTextI18n")
- private void startCreate() {
- File vDir = new File(AppConfig.cvbiFolder);
+ private void startCreate(Uri uri) {
+ String cvbiFolder = Objects.requireNonNull(getExternalCacheDir()).getAbsolutePath() + "/cvbi/";
+ File vDir = new File(cvbiFolder);
if (!vDir.exists()) {
if (!vDir.mkdirs()) {
DialogUtils.oneDialog(this,
@@ -104,90 +114,53 @@ public class ExportRomActivity extends AppCompatActivity {
}
}
- listmapForGetData.clear();
- mapForGetData.clear();
+ String getRomPath = AppConfig.vmFolder + current.vmID + "/";
+ HashMap vmConfigMap = new HashMap<>();
- listmapForGetData = new Gson().fromJson(FileUtils.readAFile(AppConfig.romsdatajson), new TypeToken>>() {
- }.getType());
+ vmConfigMap.put("title", current.itemName);
- getRomPath = AppConfig.vmFolder + Objects.requireNonNull(listmapForGetData.get(pendingPosition).get("vmID")) + "/";
+ if (FileUtils.isFileExists(current.itemIcon)) {
+ vmConfigMap.put("icon", new File(Objects.requireNonNull(Uri.parse(current.itemIcon).getPath())).getName());
+ } else {
+ vmConfigMap.put("icon", current.itemIcon);
+ }
- if (listmapForGetData.get(pendingPosition).containsKey("imgName")) {
- mapForGetData.put("title", Objects.requireNonNull(listmapForGetData.get(pendingPosition).get("imgName")).toString());
+ if (FileUtils.isFileExists(current.itemPath)) {
+ vmConfigMap.put("drive", new File(Objects.requireNonNull(Uri.parse(current.itemPath).getPath())).getName());
} else {
- mapForGetData.put("title", "");
+ vmConfigMap.put("drive", VMManager.quickScanDiskFileInFolder(getRomPath));
}
- if (listmapForGetData.get(pendingPosition).containsKey("imgIcon")) {
- iconfile = Objects.requireNonNull(listmapForGetData.get(pendingPosition).get("imgIcon")).toString();
- try {
- mapForGetData.put("icon", Uri.parse(Objects.requireNonNull(listmapForGetData.get(pendingPosition).get("imgIcon")).toString()).getLastPathSegment());
- } catch (Exception _e) {
- mapForGetData.put("icon", Objects.requireNonNull(listmapForGetData.get(pendingPosition).get("imgIcon")).toString());
- }
+
+ if (FileUtils.isFileExists(current.imgCdrom)) {
+ vmConfigMap.put("cdrom", new File(Objects.requireNonNull(Uri.parse(current.imgCdrom).getPath())).getName());
} else {
- mapForGetData.put("icon", "");
- }
- if (listmapForGetData.get(pendingPosition).containsKey("imgPath")) {
- if (Objects.requireNonNull(listmapForGetData.get(pendingPosition).get("imgPath")).toString().isEmpty()) {
- diskfile = VMManager.quickScanDiskFileInFolder(getRomPath);
- } else {
- diskfile = Objects.requireNonNull(listmapForGetData.get(pendingPosition).get("imgPath")).toString();
- }
- mapForGetData.put("drive", Objects.requireNonNull(listmapForGetData.get(pendingPosition).get("imgPath")).toString().replaceAll(getRomPath, ""));
- } else {
- diskfile = VMManager.quickScanDiskFileInFolder(getRomPath);
- mapForGetData.put("drive", "");
- }
- if (listmapForGetData.get(pendingPosition).containsKey("imgCdrom")) {
- if (Objects.requireNonNull(listmapForGetData.get(pendingPosition).get("imgCdrom")).toString().isEmpty()) {
- cdromfile = VMManager.quickScanISOFileInFolder(getRomPath);
- } else {
- cdromfile = Objects.requireNonNull(listmapForGetData.get(pendingPosition).get("imgCdrom")).toString();
- }
- mapForGetData.put("cdrom", Objects.requireNonNull(listmapForGetData.get(pendingPosition).get("imgCdrom")).toString().replaceAll(getRomPath, ""));
- } else {
- cdromfile = VMManager.quickScanISOFileInFolder(getRomPath);
- mapForGetData.put("cdrom", "");
- }
- if (listmapForGetData.get(pendingPosition).containsKey("bootFrom")) {
- mapForGetData.put("bootFrom", listmapForGetData.get(pendingPosition).get("bootFrom"));
- } else {
- mapForGetData.put("bootFrom", "");
- }
- if (listmapForGetData.get(pendingPosition).containsKey("isShowBootMenu")) {
- mapForGetData.put("isShowBootMenu", listmapForGetData.get(pendingPosition).get("isShowBootMenu"));
- } else {
- mapForGetData.put("isShowBootMenu", "");
- }
- if (listmapForGetData.get(pendingPosition).containsKey("imgExtra")) {
- mapForGetData.put("qemu", Objects.requireNonNull(listmapForGetData.get(pendingPosition).get("imgExtra")).toString().replaceAll(getRomPath, "OhnoIjustrealizeditsmidnightandIstillhavetodothis"));
- } else {
- mapForGetData.put("qemu", "");
- }
- if (listmapForGetData.get(pendingPosition).containsKey("imgArch")) {
- mapForGetData.put("arch", Objects.requireNonNull(listmapForGetData.get(pendingPosition).get("imgArch")).toString());
- } else {
- mapForGetData.put("arch", "");
+ vmConfigMap.put("cdrom", VMManager.quickScanISOFileInFolder(getRomPath));
}
+
+ vmConfigMap.put("bootFrom", current.bootFrom);
+ vmConfigMap.put("isShowBootMenu", current.isShowBootMenu);
+ vmConfigMap.put("qemu", current.itemExtra);
+ vmConfigMap.put("arch", current.itemArch);
+
if (Objects.requireNonNull(binding.edAuthor.getText()).toString().isEmpty()) {
- mapForGetData.put("author", "Unknow");
+ vmConfigMap.put("author", "Unknow");
} else {
- mapForGetData.put("author", binding.edAuthor.getText().toString());
+ vmConfigMap.put("author", binding.edAuthor.getText().toString());
}
if (Objects.requireNonNull(binding.edContent.getText()).toString().isEmpty()) {
- mapForGetData.put("desc", "Empty.");
+ vmConfigMap.put("desc", "Empty.");
} else {
- mapForGetData.put("desc", binding.edContent.getText().toString());
+ vmConfigMap.put("desc", binding.edContent.getText().toString());
}
- mapForGetData.put("versioncode", PackageUtils.getThisVersionCode(getApplicationContext()));
+ vmConfigMap.put("versioncode", PackageUtils.getThisVersionCode(getApplicationContext()));
- FileUtils.writeToFile(new File(String.valueOf(getExternalFilesDir("data"))).getPath(), "rom-data.json", new Gson().toJson(mapForGetData));
+ FileUtils.writeToFile(new File(String.valueOf(getExternalFilesDir("data"))).getPath(), "rom-data.json", new Gson().toJson(vmConfigMap));
String[] filePaths = new String[0];
ArrayList _filelist = new ArrayList<>();
- FileUtils.getAListOfAllFilesAndFoldersInADirectory(AppConfig.vmFolder + Objects.requireNonNull(listmapForGetData.get(pendingPosition).get("vmID")), _filelist);
+ FileUtils.getAListOfAllFilesAndFoldersInADirectory(AppConfig.vmFolder + current.vmID, _filelist);
if (!_filelist.isEmpty()) {
for (int _repeat = 0; _repeat < _filelist.size(); _repeat++) {
if (!_filelist.get(_repeat).endsWith("vmID.txt") &&
@@ -215,14 +188,15 @@ public class ExportRomActivity extends AppCompatActivity {
isExporting = true;
String outputPath;
- if (!FileUtils.isFileExists(AppConfig.cvbiFolder + Objects.requireNonNull(mapForGetData.get("title")) + ".cvbi")) {
- outputPath = AppConfig.cvbiFolder + Objects.requireNonNull(mapForGetData.get("title")) + ".cvbi";
+ String outputFileName = current.itemName + ".cvbi";
+ if (!FileUtils.isFileExists(cvbiFolder + current.itemName + ".cvbi")) {
+ outputPath = cvbiFolder + outputFileName;
} else {
- String outputFileName = Objects.requireNonNull(mapForGetData.get("title")).toString();
int prefix = 0;
while (true) {
- if (!FileUtils.isFileExists(AppConfig.cvbiFolder + outputFileName + "_" + prefix + ".cvbi")) {
- outputPath = AppConfig.cvbiFolder + outputFileName + "_" + prefix + ".cvbi";
+ if (!FileUtils.isFileExists(cvbiFolder + current.itemName + "_" + prefix + ".cvbi")) {
+ outputFileName = current.itemName + "_" + prefix + ".cvbi";
+ outputPath = cvbiFolder + outputFileName;
break;
} else {
prefix++;
@@ -230,23 +204,31 @@ public class ExportRomActivity extends AppCompatActivity {
}
}
- boolean result = ZipUtils.compress(
+ final boolean[] result = {ZipUtils.compress(
this,
finalFilePaths,
- outputPath,
+ uri,
progressText,
progressBar
- );
-
+ )};
runOnUiThread(() -> {
isExporting = false;
progressDialog.dismiss();
+ String finalOutputPath = "";
+ try {
+ FileUtils.deleteDirectory(outputPath);
+ finalOutputPath = FileUtils.getPath(this, uri);
+ } catch (Exception e) {
+ Log.e(TAG, "startCreate: ", e);
+ }
+
+ String finalOutputPath1 = finalOutputPath;
String title;
String content;
- if (result) {
+ if (result[0]) {
title = getString(R.string.done);
- content = getString(R.string.saved_in) + ": " + outputPath + ".";
+ content = finalOutputPath1 == null || finalOutputPath1.isEmpty() ? getString(R.string.rom_successfully_exported) : getString(R.string.saved_in) + ": " + finalOutputPath1 + ".";
} else {
title = getString(R.string.oops);
content = getString(R.string.something_went_wrong) + ":\n\n" + ZipUtils.lastErrorContent;
@@ -255,19 +237,20 @@ public class ExportRomActivity extends AppCompatActivity {
DialogUtils.twoDialog(this,
title,
content,
- getString(result ? R.string.show_in_folder : R.string.ok),
- getString(result ? R.string.close : R.string.exit),
+ getString(result[0] ? R.string.show_in_folder : R.string.ok),
+ getString(result[0] ? R.string.close : R.string.exit),
true,
- result ? R.drawable.check_24px : R.drawable.error_96px,
+ result[0] ? R.drawable.check_24px : R.drawable.error_96px,
true,
() -> {
- if (result) {
- File file = new File(outputPath);
+ if (result[0]) {
+ assert finalOutputPath1 != null;
+ File file = new File(finalOutputPath1.isEmpty() ? outputPath : finalOutputPath1);
FileUtils.openFolder(this, file.getParent());
}
},
() -> {
- if (!result) {
+ if (!result[0]) {
finish();
}
},
diff --git a/app/src/main/java/com/vectras/vm/Minitools.java b/app/src/main/java/com/vectras/vm/Minitools.java
index 7ae8532..3501f78 100644
--- a/app/src/main/java/com/vectras/vm/Minitools.java
+++ b/app/src/main/java/com/vectras/vm/Minitools.java
@@ -310,30 +310,4 @@ public class Minitools extends AppCompatActivity {
});
}).start();
}
-
- public void extractLoaderApk() {
- String apkLoaderAssetPath = "bootstrap/loader.apk";
- String apkLoaderextractedFilePath = TermuxService.PREFIX_PATH + "/libexec/termux-x11/loader.apk";
-
- FileUtils.deleteDirectory(apkLoaderextractedFilePath);
- if (copyAssetToFile(apkLoaderAssetPath, apkLoaderextractedFilePath)) {
- FileUtils.copyAFile(TermuxService.PREFIX_PATH + "/libexec/termux-x11/loader.apk", AppConfig.maindirpath);
- }
- }
-
- private boolean copyAssetToFile(String assetPath, String outputPath) {
- try (InputStream in = getAssets().open(assetPath);
- OutputStream out = new FileOutputStream(outputPath)) {
- byte[] buffer = new byte[1024];
- int read;
- while ((read = in.read(buffer)) != -1) {
- out.write(buffer, 0, read);
- }
- out.flush();
- return true;
- } catch (IOException e) {
- Log.e(TAG, "copyAssetToFile: ", e);
- return false;
- }
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/vectras/vm/VMManager.java b/app/src/main/java/com/vectras/vm/VMManager.java
index 40739a9..9a00d52 100644
--- a/app/src/main/java/com/vectras/vm/VMManager.java
+++ b/app/src/main/java/com/vectras/vm/VMManager.java
@@ -983,10 +983,7 @@ public class VMManager {
public static void killallqemuprocesses(Context context) {
Terminal vterm = new Terminal(context);
- vterm.executeShellCommand2("killall -15 qemu-system-i386", false, null);
- vterm.executeShellCommand2("killall -15 qemu-system-x86_64", false, null);
- vterm.executeShellCommand2("killall -15 qemu-system-aarch64", false, null);
- vterm.executeShellCommand2("killall -15 qemu-system-ppc", false, null);
+ vterm.executeShellCommand2("killall -15 qemu-system-i386 && killall -15 qemu-system-x86_64 && killall -15 qemu-system-aarch64 && killall -15 qemu-system-ppc", false, null);
}
public static void shutdownCurrentVM() {
diff --git a/app/src/main/java/com/vectras/vm/QemuParamsEditorActivity.java b/app/src/main/java/com/vectras/vm/creator/QemuParamsEditorActivity.java
similarity index 96%
rename from app/src/main/java/com/vectras/vm/QemuParamsEditorActivity.java
rename to app/src/main/java/com/vectras/vm/creator/QemuParamsEditorActivity.java
index d60d75e..3daa9dd 100644
--- a/app/src/main/java/com/vectras/vm/QemuParamsEditorActivity.java
+++ b/app/src/main/java/com/vectras/vm/creator/QemuParamsEditorActivity.java
@@ -1,4 +1,4 @@
-package com.vectras.vm;
+package com.vectras.vm.creator;
import android.os.Bundle;
import android.os.Handler;
@@ -7,6 +7,7 @@ import android.view.inputmethod.InputMethodManager;
import androidx.appcompat.app.AppCompatActivity;
+import com.vectras.vm.R;
import com.vectras.vm.databinding.ActivityQemuParamsEditorBinding;
import com.vectras.vm.utils.UIUtils;
diff --git a/app/src/main/java/com/vectras/vm/SetArchActivity.java b/app/src/main/java/com/vectras/vm/creator/SetArchActivity.java
similarity index 96%
rename from app/src/main/java/com/vectras/vm/SetArchActivity.java
rename to app/src/main/java/com/vectras/vm/creator/SetArchActivity.java
index 5665791..3f42d75 100644
--- a/app/src/main/java/com/vectras/vm/SetArchActivity.java
+++ b/app/src/main/java/com/vectras/vm/creator/SetArchActivity.java
@@ -1,153 +1,153 @@
-package com.vectras.vm;
-
-import android.content.ClipData;
-import android.content.ClipDescription;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.DragEvent;
-import android.view.Menu;
-import android.view.View;
-
-import androidx.appcompat.app.AppCompatActivity;
-
-import com.vectras.qemu.MainSettingsManager;
-import com.vectras.vm.creator.VMCreatorActivity;
-import com.vectras.vm.databinding.ActivitySetArchBinding;
-import com.vectras.vm.main.MainActivity;
-import com.vectras.vm.utils.FileUtils;
-import com.vectras.vm.utils.UIUtils;
-
-import java.io.File;
-
-public class SetArchActivity extends AppCompatActivity implements View.OnClickListener {
-
- SetArchActivity activity;
- ActivitySetArchBinding binding;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- UIUtils.edgeToEdge(this);
- binding = ActivitySetArchBinding.inflate(getLayoutInflater());
- setContentView(binding.getRoot());
-// UIUtils.setOnApplyWindowInsetsListener(findViewById(R.id.main));
- activity = this;
- binding.archi386.setOnClickListener(this);
- binding.archx8664.setOnClickListener(this);
- binding.archarm64.setOnClickListener(this);
- binding.archppc.setOnClickListener(this);
- binding.webBtn.setOnClickListener(this);
- binding.buttongetcm.setOnClickListener(this);
- binding.bntimport.setOnClickListener(this);
-
- setSupportActionBar(binding.toolbar);
- binding.toolbar.setNavigationOnClickListener(v -> finish());
-
- binding.toolbar.setOnMenuItemClickListener(item -> {
- if (item.getItemId() == R.id.roms_store) {
- MainActivity.isOpenRomStore = true;
- finish();
- return true;
- }
- return false;
- });
-
-// if (PackageUtils.isInstalled("com.anbui.cqcm.app", this)) {
-// binding.buttongetcm.setText(getResources().getString(R.string.open));
-// }
-
- binding.bntimport.setOnDragListener((v, event) -> {
- Log.i("Drag", "onDrag: " + event.getAction());
- switch (event.getAction()) {
- case DragEvent.ACTION_DRAG_STARTED:
- ClipDescription description = event.getClipDescription();
- if (description != null) {
- Log.d("DRAG", "MIME: " + description.getMimeType(0));
- return true; // Accept to go to event DragEvent.ACTION_DROP
- }
- return false;
-
- case DragEvent.ACTION_DROP:
- ClipData clipData = event.getClipData();
- if (clipData != null && clipData.getItemCount() > 0) {
- Uri uri = clipData.getItemAt(0).getUri();
- String filePath = FileUtils.getFilePathFromUri(getApplicationContext(), uri);
-
- File file = new File(filePath);
-
- Intent intent = new Intent();
- intent.setClass(getApplicationContext(), VMCreatorActivity.class);
- intent.putExtra("addromnow", "");
- intent.putExtra("romextra", "");
- intent.putExtra("romname", "");
- intent.putExtra("romicon", "");
- intent.putExtra("rompath", filePath);
- intent.putExtra("romfilename", file.getName());
- startActivity(intent);
- finish();
- }
- return true;
- }
- return true;
- });
-
- }
-
- public void onClick(View v) {
- int id = v.getId();
- if (id == R.id.archi386) {
- MainSettingsManager.setArch(this, "I386");
-
- startActivity(new Intent(activity, VMCreatorActivity.class));
- finish();
- } else if (id == R.id.archx86_64) {
- MainSettingsManager.setArch(this, "X86_64");
-
- startActivity(new Intent(activity, VMCreatorActivity.class));
- finish();
- } else if (id == R.id.archarm64) {
- MainSettingsManager.setArch(this, "ARM64");
-
- startActivity(new Intent(activity, VMCreatorActivity.class));
- finish();
- } else if (id == R.id.archppc) {
- MainSettingsManager.setArch(this, "PPC");
-
- startActivity(new Intent(activity, VMCreatorActivity.class));
- finish();
- } else if (id == R.id.webBtn) {
- String qe = "https://www.qemu.org/";
- Intent q = new Intent(Intent.ACTION_VIEW);
- q.addCategory(Intent.CATEGORY_BROWSABLE);
- q.setData(Uri.parse(qe));
- startActivity(q);
- } else if (id == R.id.buttongetcm) {
- PackageManager pm = getPackageManager();
- Intent intent = pm.getLaunchIntentForPackage("com.anbui.cqcm.app");
-
- if (intent != null) {
- startActivity(intent);
- } else {
- Intent intenturl = new Intent();
- intenturl.setAction(Intent.ACTION_VIEW);
- intenturl.setData(Uri.parse("https://play.google.com/store/apps/details?id=com.anbui.cqcm.app"));
- startActivity(intenturl);
- }
- } else if (id == R.id.bntimport) {
- Intent intent = new Intent();
- intent.setClass(getApplicationContext(), VMCreatorActivity.class);
- intent.putExtra("importcvbinow", "");
- startActivity(intent);
- finish();
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.set_arch_toolbar_menu, menu);
- return true;
- }
+package com.vectras.vm.creator;
+
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.DragEvent;
+import android.view.Menu;
+import android.view.View;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.vectras.qemu.MainSettingsManager;
+import com.vectras.vm.R;
+import com.vectras.vm.databinding.ActivitySetArchBinding;
+import com.vectras.vm.main.MainActivity;
+import com.vectras.vm.utils.FileUtils;
+import com.vectras.vm.utils.UIUtils;
+
+import java.io.File;
+
+public class SetArchActivity extends AppCompatActivity implements View.OnClickListener {
+
+ SetArchActivity activity;
+ ActivitySetArchBinding binding;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ UIUtils.edgeToEdge(this);
+ binding = ActivitySetArchBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+// UIUtils.setOnApplyWindowInsetsListener(findViewById(R.id.main));
+ activity = this;
+ binding.archi386.setOnClickListener(this);
+ binding.archx8664.setOnClickListener(this);
+ binding.archarm64.setOnClickListener(this);
+ binding.archppc.setOnClickListener(this);
+ binding.webBtn.setOnClickListener(this);
+ binding.buttongetcm.setOnClickListener(this);
+ binding.bntimport.setOnClickListener(this);
+
+ setSupportActionBar(binding.toolbar);
+ binding.toolbar.setNavigationOnClickListener(v -> finish());
+
+ binding.toolbar.setOnMenuItemClickListener(item -> {
+ if (item.getItemId() == R.id.roms_store) {
+ MainActivity.isOpenRomStore = true;
+ finish();
+ return true;
+ }
+ return false;
+ });
+
+// if (PackageUtils.isInstalled("com.anbui.cqcm.app", this)) {
+// binding.buttongetcm.setText(getResources().getString(R.string.open));
+// }
+
+ binding.bntimport.setOnDragListener((v, event) -> {
+ Log.i("Drag", "onDrag: " + event.getAction());
+ switch (event.getAction()) {
+ case DragEvent.ACTION_DRAG_STARTED:
+ ClipDescription description = event.getClipDescription();
+ if (description != null) {
+ Log.d("DRAG", "MIME: " + description.getMimeType(0));
+ return true; // Accept to go to event DragEvent.ACTION_DROP
+ }
+ return false;
+
+ case DragEvent.ACTION_DROP:
+ ClipData clipData = event.getClipData();
+ if (clipData != null && clipData.getItemCount() > 0) {
+ Uri uri = clipData.getItemAt(0).getUri();
+ String filePath = FileUtils.getFilePathFromUri(getApplicationContext(), uri);
+
+ File file = new File(filePath);
+
+ Intent intent = new Intent();
+ intent.setClass(getApplicationContext(), VMCreatorActivity.class);
+ intent.putExtra("addromnow", "");
+ intent.putExtra("romextra", "");
+ intent.putExtra("romname", "");
+ intent.putExtra("romicon", "");
+ intent.putExtra("rompath", filePath);
+ intent.putExtra("romfilename", file.getName());
+ startActivity(intent);
+ finish();
+ }
+ return true;
+ }
+ return true;
+ });
+
+ }
+
+ public void onClick(View v) {
+ int id = v.getId();
+ if (id == R.id.archi386) {
+ MainSettingsManager.setArch(this, "I386");
+
+ startActivity(new Intent(activity, VMCreatorActivity.class));
+ finish();
+ } else if (id == R.id.archx86_64) {
+ MainSettingsManager.setArch(this, "X86_64");
+
+ startActivity(new Intent(activity, VMCreatorActivity.class));
+ finish();
+ } else if (id == R.id.archarm64) {
+ MainSettingsManager.setArch(this, "ARM64");
+
+ startActivity(new Intent(activity, VMCreatorActivity.class));
+ finish();
+ } else if (id == R.id.archppc) {
+ MainSettingsManager.setArch(this, "PPC");
+
+ startActivity(new Intent(activity, VMCreatorActivity.class));
+ finish();
+ } else if (id == R.id.webBtn) {
+ String qe = "https://www.qemu.org/";
+ Intent q = new Intent(Intent.ACTION_VIEW);
+ q.addCategory(Intent.CATEGORY_BROWSABLE);
+ q.setData(Uri.parse(qe));
+ startActivity(q);
+ } else if (id == R.id.buttongetcm) {
+ PackageManager pm = getPackageManager();
+ Intent intent = pm.getLaunchIntentForPackage("com.anbui.cqcm.app");
+
+ if (intent != null) {
+ startActivity(intent);
+ } else {
+ Intent intenturl = new Intent();
+ intenturl.setAction(Intent.ACTION_VIEW);
+ intenturl.setData(Uri.parse("https://play.google.com/store/apps/details?id=com.anbui.cqcm.app"));
+ startActivity(intenturl);
+ }
+ } else if (id == R.id.bntimport) {
+ Intent intent = new Intent();
+ intent.setClass(getApplicationContext(), VMCreatorActivity.class);
+ intent.putExtra("importcvbinow", "");
+ startActivity(intent);
+ finish();
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.set_arch_toolbar_menu, menu);
+ return true;
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/vectras/vm/creator/VMCreatorActivity.java b/app/src/main/java/com/vectras/vm/creator/VMCreatorActivity.java
index cfccaaf..aa9e0fc 100644
--- a/app/src/main/java/com/vectras/vm/creator/VMCreatorActivity.java
+++ b/app/src/main/java/com/vectras/vm/creator/VMCreatorActivity.java
@@ -28,7 +28,6 @@ import com.google.gson.Gson;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.AppConfig;
import com.vectras.vm.Fragment.CreateImageDialogFragment;
-import com.vectras.vm.QemuParamsEditorActivity;
import com.vectras.vm.R;
import com.vectras.vm.RomInfo;
import com.vectras.vm.SplashActivity;
@@ -674,7 +673,7 @@ public class VMCreatorActivity extends AppCompatActivity {
null));
} finally {
runOnUiThread(() -> {
- if (!isImportingCVBI && !isFinishing() && !isDestroyed())
+ if (!isImportingCVBI && progressDialog.isShowing() && !isFinishing() && !isDestroyed())
progressDialog.dismiss();
});
}
@@ -879,13 +878,14 @@ public class VMCreatorActivity extends AppCompatActivity {
);
runOnUiThread(() -> {
+ if (progressDialog.isShowing() && !isFinishing() && !isDestroyed())
+ progressDialog.dismiss();
+
if (isFinishing() || isDestroyed()) {
new Thread(() -> FileUtils.deleteDirectory(AppConfig.vmFolder + vmID)).start();
return;
}
- progressDialog.dismiss();
-
if (result) {
afterExtractCVBIFile(fileName);
} else {
diff --git a/app/src/main/java/com/vectras/vm/creator/VMCreatorSelector.java b/app/src/main/java/com/vectras/vm/creator/VMCreatorSelector.java
index 5136827..be388ea 100644
--- a/app/src/main/java/com/vectras/vm/creator/VMCreatorSelector.java
+++ b/app/src/main/java/com/vectras/vm/creator/VMCreatorSelector.java
@@ -2,8 +2,6 @@ package com.vectras.vm.creator;
import android.app.Activity;
import android.content.Context;
-import android.content.DialogInterface;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -14,14 +12,10 @@ import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
-import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
import com.vectras.vm.R;
-import com.vectras.vm.databinding.RecyclerViewBinding;
+import com.vectras.vm.databinding.DialogListSelectorLayoutBinding;
import com.vectras.vm.databinding.SimpleLayoutListViewWithCheckBinding;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;
@@ -43,20 +37,31 @@ public class VMCreatorSelector {
public static void showDialog(Activity activity, ArrayList> list, int position,SelectorCallback callback, String title) {
LinearLayoutManager layoutmanager = new LinearLayoutManager(activity);
- RecyclerViewBinding binding = RecyclerViewBinding.inflate(activity.getLayoutInflater());
+ DialogListSelectorLayoutBinding binding = DialogListSelectorLayoutBinding.inflate(activity.getLayoutInflater());
AlertDialog dialog = new AlertDialog.Builder(activity)
.setView(binding.getRoot())
.create();
- dialog.setTitle(title);
- dialog.setButton(AlertDialog.BUTTON_POSITIVE, activity.getString(R.string.close), (dialog1, which) -> dialog1.dismiss());
+ binding.tvTitle.setText(title);
+ binding.btnClose.setOnClickListener(v -> dialog.dismiss());
binding.list.setAdapter(new RecyclerviewAdapter(activity, dialog, list, position, callback));
binding.list.setLayoutManager(layoutmanager);
dialog.show();
+ binding.list.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrolled(@NonNull RecyclerView rv, int dx, int dy) {
+ boolean canScrollUp = rv.canScrollVertically(-1);
+ boolean canScrollDown = rv.canScrollVertically(1);
+
+ binding.dvTop.setVisibility(canScrollUp ? View.VISIBLE : View.INVISIBLE);
+ binding.dvBottom.setVisibility(canScrollDown ? View.VISIBLE : View.INVISIBLE);
+ }
+ });
+
if (position > -1) binding.list.scrollToPosition(position);
}
@@ -90,7 +95,7 @@ public class VMCreatorSelector {
View view = holder.itemView;
TextView title = view.findViewById(R.id.textview);
title.setText(Objects.requireNonNull(data.get(position).get("name")).toString());
- view.findViewById(R.id.iv_check).setVisibility(position == currentPosition ? View.VISIBLE : View.GONE);
+ view.findViewById(R.id.iv_check).setVisibility(position == currentPosition ? View.VISIBLE : View.INVISIBLE);
view.findViewById(R.id.main).setOnClickListener(v -> {
callback.onSelected(
position,
diff --git a/app/src/main/java/com/vectras/vm/main/MainActivity.java b/app/src/main/java/com/vectras/vm/main/MainActivity.java
index c63a7f1..13bfead 100644
--- a/app/src/main/java/com/vectras/vm/main/MainActivity.java
+++ b/app/src/main/java/com/vectras/vm/main/MainActivity.java
@@ -54,7 +54,7 @@ import com.vectras.vm.databinding.BottomsheetdialogLoggerBinding;
import com.vectras.vm.databinding.UpdateBottomDialogLayoutBinding;
import com.vectras.vm.main.romstore.RomStoreHomeAdapterSearch;
import com.vectras.vm.main.romstore.DataRoms;
-import com.vectras.vm.SetArchActivity;
+import com.vectras.vm.creator.SetArchActivity;
import com.vectras.vm.VMManager;
import com.vectras.vm.adapter.LogsAdapter;
import com.vectras.vm.main.core.CallbackInterface;
@@ -69,6 +69,7 @@ import com.vectras.vm.settings.UpdaterActivity;
import com.vectras.vm.utils.DeviceUtils;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.FileUtils;
+import com.vectras.vm.utils.IntentUtils;
import com.vectras.vm.utils.LibraryChecker;
import com.vectras.vm.utils.NotificationUtils;
import com.vectras.vm.utils.PackageUtils;
@@ -423,10 +424,7 @@ public class MainActivity extends AppCompatActivity implements RomStoreFragment.
startActivity(new Intent(this, AboutActivity.class));
}
if (id == R.id.navigation_item_help) {
- String tw = AppConfig.vectrasHelp;
- Intent w = new Intent(ACTION_VIEW);
- w.setData(Uri.parse(tw));
- startActivity(w);
+ IntentUtils.openUrl(this, AppConfig.vectrasHelp, true);
} else if (id == R.id.navigation_item_website) {
String tw = AppConfig.vectrasWebsite;
Intent w = new Intent(ACTION_VIEW);
diff --git a/app/src/main/java/com/vectras/vm/main/core/RomOptionsDialog.java b/app/src/main/java/com/vectras/vm/main/core/RomOptionsDialog.java
index 232dd91..0b91e6f 100644
--- a/app/src/main/java/com/vectras/vm/main/core/RomOptionsDialog.java
+++ b/app/src/main/java/com/vectras/vm/main/core/RomOptionsDialog.java
@@ -28,9 +28,9 @@ public class RomOptionsDialog {
Button exportRomBtn = v.findViewById(R.id.exportRomBtn);
exportRomBtn.setOnClickListener(v2 -> {
- ExportRomActivity.pendingPosition = position;
Intent intent = new Intent();
intent.setClass(activity, ExportRomActivity.class);
+ intent.putExtra("POS", position);
activity.startActivity(intent);
bottomSheetDialog.cancel();
});
diff --git a/app/src/main/java/com/vectras/vm/setupwizard/SetupWizard2Activity.java b/app/src/main/java/com/vectras/vm/setupwizard/SetupWizard2Activity.java
index ecea5ed..a0f621f 100644
--- a/app/src/main/java/com/vectras/vm/setupwizard/SetupWizard2Activity.java
+++ b/app/src/main/java/com/vectras/vm/setupwizard/SetupWizard2Activity.java
@@ -44,6 +44,7 @@ import com.vectras.vm.main.MainActivity;
import com.vectras.vm.utils.DeviceUtils;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.FileUtils;
+import com.vectras.vm.utils.IntentUtils;
import com.vectras.vm.utils.JSONUtils;
import com.vectras.vm.utils.ListUtils;
import com.vectras.vm.utils.PermissionUtils;
@@ -193,10 +194,7 @@ public class SetupWizard2Activity extends AppCompatActivity {
uiController(STEP_SYSTEM_UPDATE);
binding.btnSkipSystemUpdate.setVisibility(View.GONE);
} else if (isLibProotError) {
- Intent intent = new Intent();
- intent.setAction(ACTION_VIEW);
- intent.setData(Uri.parse(AppConfig.telegramLink));
- startActivity(intent);
+ IntentUtils.openTelegramLink(this);
} else if (SetupFeatureCore.isInstalledSystemFiles(this)) {
getDataForStandardSetup();
} else {
@@ -210,8 +208,7 @@ public class SetupWizard2Activity extends AppCompatActivity {
bindingFinalSteps.btnContinue.setOnClickListener(v -> {
if (currentStep == STEP_JOIN_COMMUNITY) {
uiControllerFinalSteps(currentStep + 1);
- Intent intent = new Intent(ACTION_VIEW, Uri.parse(AppConfig.telegramLink));
- startActivity(intent);
+ IntentUtils.openTelegramLink(this);
//Don't show join Telegram dialog again
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor edit = prefs.edit();
@@ -772,7 +769,7 @@ public class SetupWizard2Activity extends AppCompatActivity {
// Assign data
HashMap item = data.get(position);
holder.simpleLayoutListViewWithCheckBinding.textview.setText(item.get("location"));
- holder.simpleLayoutListViewWithCheckBinding.ivCheck.setVisibility(position == selectedPosition ? View.VISIBLE : View.GONE);
+ holder.simpleLayoutListViewWithCheckBinding.ivCheck.setVisibility(position == selectedPosition ? View.VISIBLE : View.INVISIBLE);
return convertView;
diff --git a/app/src/main/java/com/vectras/vm/utils/DialogUtils.java b/app/src/main/java/com/vectras/vm/utils/DialogUtils.java
index 5706cd1..9e5ccb4 100644
--- a/app/src/main/java/com/vectras/vm/utils/DialogUtils.java
+++ b/app/src/main/java/com/vectras/vm/utils/DialogUtils.java
@@ -254,12 +254,7 @@ public class DialogUtils {
_context.getResources().getString(R.string.join_us_on_telegram_where_we_publish_all_the_news_and_updates_and_receive_your_opinions_and_bugs),
_context.getResources().getString(R.string.join), _context.getResources().getString(R.string.cancel), _context.getResources().getString(R.string.dont_show_again),
true, R.drawable.send_24px, true,
- () -> {
- Intent intent = new Intent(ACTION_VIEW);
- intent.addCategory(Intent.CATEGORY_BROWSABLE);
- intent.setData(Uri.parse(AppConfig.telegramLink));
- _context.startActivity(intent);
- }, null,
+ () -> IntentUtils.openTelegramLink(_context), null,
() -> {
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean("tgDialog", true);
diff --git a/app/src/main/java/com/vectras/vm/utils/FileUtils.java b/app/src/main/java/com/vectras/vm/utils/FileUtils.java
index 34f0944..13f7b0a 100644
--- a/app/src/main/java/com/vectras/vm/utils/FileUtils.java
+++ b/app/src/main/java/com/vectras/vm/utils/FileUtils.java
@@ -33,6 +33,7 @@ import android.os.ParcelFileDescriptor;
import androidx.annotation.NonNull;
import androidx.core.content.FileProvider;
+import androidx.documentfile.provider.DocumentFile;
import com.vectras.vm.R;
@@ -47,563 +48,553 @@ import java.util.HashMap;
import java.util.Objects;
/**
- *
+ *
* @author dev
*/
public class FileUtils {
- public static final String TAG = "FileUtils";
-
- @NonNull
- public static File getExternalFilesDirectory(Context context) {
- return new File(Environment.getExternalStorageDirectory(), "Documents/VectrasVM");
- }
-
- public static void chmod(File file, int mode) {
- try {
- Os.chmod(file.getAbsolutePath(), mode);
- }
- catch (ErrnoException e) {}
- }
-
- private static Uri contentUri = null;
-
- @SuppressLint("NewApi")
- public static String getPath(Context context, final Uri uri) {
- // check here to KITKAT or new version
- final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
- String selection = null;
- String[] selectionArgs = null;
- // DocumentProvider
- if (isKitKat ) {
- // ExternalStorageProvider
-
- if (isExternalStorageDocument(uri)) {
- final String docId = DocumentsContract.getDocumentId(uri);
- final String[] split = docId.split(":");
- final String type = split[0];
-
- String fullPath = getPathFromExtSD(split);
- if (fullPath != "") {
- return fullPath;
- } else {
- return null;
- }
- }
-
-
- // DownloadsProvider
-
- if (isDownloadsDocument(uri)) {
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- final String id;
- Cursor cursor = null;
- try {
- cursor = context.getContentResolver().query(uri, new String[]{MediaStore.MediaColumns.DISPLAY_NAME}, null, null, null);
- if (cursor != null && cursor.moveToFirst()) {
- String fileName = cursor.getString(0);
- String path = Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName;
- if (!TextUtils.isEmpty(path)) {
- return path;
- }
- }
- }
- finally {
- if (cursor != null)
- cursor.close();
- }
- id = DocumentsContract.getDocumentId(uri);
- if (!TextUtils.isEmpty(id)) {
- if (id.startsWith("raw:")) {
- return id.replaceFirst("raw:", "");
- }
- String[] contentUriPrefixesToTry = new String[]{
- "content://downloads/public_downloads",
- "content://downloads/my_downloads"
- };
- for (String contentUriPrefix : contentUriPrefixesToTry) {
- try {
- final Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id));
-
-
- return getDataColumn(context, contentUri, null, null);
- } catch (NumberFormatException e) {
- //In Android 8 and Android P the id is not a number
- return uri.getPath().replaceFirst("^/document/raw:", "").replaceFirst("^raw:", "");
- }
- }
-
-
- }
- }
- else {
- final String id = DocumentsContract.getDocumentId(uri);
-
- if (id.startsWith("raw:")) {
- return id.replaceFirst("raw:", "");
- }
- try {
- contentUri = ContentUris.withAppendedId(
- Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
- }
- catch (NumberFormatException e) {
- e.printStackTrace();
- }
- if (contentUri != null) {
-
- return getDataColumn(context, contentUri, null, null);
- }
- }
- }
-
-
- // MediaProvider
- if (isMediaDocument(uri)) {
- final String docId = DocumentsContract.getDocumentId(uri);
- final String[] split = docId.split(":");
- final String type = split[0];
-
- Uri contentUri = null;
-
- if ("image".equals(type)) {
- contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
- } else if ("video".equals(type)) {
- contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
- } else if ("audio".equals(type)) {
- contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
- }
- selection = "_id=?";
- selectionArgs = new String[]{split[1]};
-
-
- return getDataColumn(context, contentUri, selection,
- selectionArgs);
- }
-
- if (isGoogleDriveUri(uri)) {
- return getDriveFilePath(context, uri);
- }
-
- if(isWhatsAppFile(uri)){
- return getFilePathForWhatsApp(context, uri);
- }
-
-
- if ("content".equalsIgnoreCase(uri.getScheme())) {
-
- if (isGooglePhotosUri(uri)) {
- return uri.getLastPathSegment();
- }
- if (isGoogleDriveUri(uri)) {
- return getDriveFilePath(context, uri);
- }
- if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
- {
-
- // return getFilePathFromURI(context,uri);
- return copyFileToInternalStorage(context, uri,"userfiles");
- // return getRealPathFromURI(context,uri);
- }
- else
- {
- return getDataColumn(context, uri, null, null);
- }
-
- }
- if ("file".equalsIgnoreCase(uri.getScheme())) {
- return uri.getPath();
- }
- }
- else {
-
- if(isWhatsAppFile(uri)){
- return getFilePathForWhatsApp(context, uri);
- }
-
- if ("content".equalsIgnoreCase(uri.getScheme())) {
- String[] projection = {
- MediaStore.Images.Media.DATA
- };
- Cursor cursor = null;
- try {
- cursor = context.getContentResolver()
- .query(uri, projection, selection, selectionArgs, null);
- int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
- if (cursor.moveToFirst()) {
- return cursor.getString(column_index);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- return null;
- }
-
- private static boolean fileExists(String filePath) {
- File file = new File(filePath);
-
- return file.exists();
- }
-
- private static String getPathFromExtSD(String[] pathData) {
- final String type = pathData[0];
- final String relativePath = "/" + pathData[1];
- String fullPath = "";
-
- // on my Sony devices (4.4.4 & 5.1.1), `type` is a dynamic string
- // something like "71F8-2C0A", some kind of unique id per storage
- // don't know any API that can get the root path of that storage based on its id.
- //
- // so no "primary" type, but let the check here for other devices
- if ("primary".equalsIgnoreCase(type)) {
- fullPath = Environment.getExternalStorageDirectory() + relativePath;
- if (fileExists(fullPath)) {
- return fullPath;
- }
- }
-
- // Environment.isExternalStorageRemovable() is `true` for external and internal storage
- // so we cannot relay on it.
- //
- // instead, for each possible path, check if file exists
- // we'll start with secondary storage as this could be our (physically) removable sd card
- fullPath = System.getenv("SECONDARY_STORAGE") + relativePath;
- if (fileExists(fullPath)) {
- return fullPath;
- }
-
- fullPath = System.getenv("EXTERNAL_STORAGE") + relativePath;
- if (fileExists(fullPath)) {
- return fullPath;
- }
-
- return fullPath;
- }
-
- private static String getDriveFilePath(Context context, Uri uri) {
- Uri returnUri = uri;
- Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);
- /*
- * Get the column indexes of the data in the Cursor,
- * * move to the first row in the Cursor, get the data,
- * * and display it.
- * */
- int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
- int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
- returnCursor.moveToFirst();
- String name = (returnCursor.getString(nameIndex));
- String size = (Long.toString(returnCursor.getLong(sizeIndex)));
- File file = new File(context.getCacheDir(), name);
- try {
- InputStream inputStream = context.getContentResolver().openInputStream(uri);
- FileOutputStream outputStream = new FileOutputStream(file);
- int read = 0;
- int maxBufferSize = 1 * 1024 * 1024;
- int bytesAvailable = inputStream.available();
-
- //int bufferSize = 1024;
- int bufferSize = Math.min(bytesAvailable, maxBufferSize);
-
- final byte[] buffers = new byte[bufferSize];
- while ((read = inputStream.read(buffers)) != -1) {
- outputStream.write(buffers, 0, read);
- }
- Log.e("File Size", "Size " + file.length());
- inputStream.close();
- outputStream.close();
- Log.e("File Path", "Path " + file.getPath());
- Log.e("File Size", "Size " + file.length());
- } catch (Exception e) {
- Log.e("Exception", e.getMessage());
- }
- return file.getPath();
- }
-
- /***
- * Used for Android Q+
- * @param uri
- * @param newDirName if you want to create a directory, you can set this variable
- * @return
- */
- private static String copyFileToInternalStorage(Context context, Uri uri, String newDirName) {
- Uri returnUri = uri;
-
- Cursor returnCursor = context.getContentResolver().query(returnUri, new String[]{
- OpenableColumns.DISPLAY_NAME,OpenableColumns.SIZE
- }, null, null, null);
-
-
- /*
- * Get the column indexes of the data in the Cursor,
- * * move to the first row in the Cursor, get the data,
- * * and display it.
- * */
- int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
- int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
- returnCursor.moveToFirst();
- String name = (returnCursor.getString(nameIndex));
- String size = (Long.toString(returnCursor.getLong(sizeIndex)));
-
- File output;
- if(!newDirName.equals("")) {
- File dir = new File(context.getFilesDir() + "/" + newDirName);
- if (!dir.exists()) {
- dir.mkdir();
- }
- output = new File(context.getFilesDir() + "/" + newDirName + "/" + name);
- }
- else{
- output = new File(context.getFilesDir() + "/" + name);
- }
- try {
- InputStream inputStream = context.getContentResolver().openInputStream(uri);
- FileOutputStream outputStream = new FileOutputStream(output);
- int read = 0;
- int bufferSize = 1024;
- final byte[] buffers = new byte[bufferSize];
- while ((read = inputStream.read(buffers)) != -1) {
- outputStream.write(buffers, 0, read);
- }
-
- inputStream.close();
- outputStream.close();
-
- }
- catch (Exception e) {
-
- Log.e("Exception", e.getMessage());
- }
-
- return output.getPath();
- }
-
- private static String getFilePathForWhatsApp(Context context, Uri uri){
- return copyFileToInternalStorage(context, uri,"whatsapp");
- }
-
- private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
- if (uri == null) return null;
-
- Cursor cursor = null;
- final String column = "_data";
- final String[] projection = {column};
-
- try {
- cursor = context.getContentResolver().query(uri, projection,
- selection, selectionArgs, null);
-
- if (cursor != null && cursor.moveToFirst()) {
- final int index = cursor.getColumnIndexOrThrow(column);
- return cursor.getString(index);
- }
- }
- finally {
- if (cursor != null)
- cursor.close();
- }
-
- return null;
- }
-
- private static boolean isExternalStorageDocument(Uri uri) {
- return "com.android.externalstorage.documents".equals(uri.getAuthority());
- }
-
- private static boolean isDownloadsDocument(Uri uri) {
- return "com.android.providers.downloads.documents".equals(uri.getAuthority());
- }
-
- private static boolean isMediaDocument(Uri uri) {
- return "com.android.providers.media.documents".equals(uri.getAuthority());
- }
-
- private static boolean isGooglePhotosUri(Uri uri) {
- return "com.google.android.apps.photos.content".equals(uri.getAuthority());
- }
-
- public static boolean isWhatsAppFile(Uri uri){
- return "com.whatsapp.provider.media".equals(uri.getAuthority());
- }
-
- private static boolean isGoogleDriveUri(Uri uri) {
- return "com.google.android.apps.docs.storage".equals(uri.getAuthority()) || "com.google.android.apps.docs.storage.legacy".equals(uri.getAuthority());
- }
-
-
- public String LoadFile(Activity activity, String fileName, boolean loadFromRawFolder) throws IOException {
- // Create a InputStream to read the file into
- InputStream iS;
- if (loadFromRawFolder) {
- // get the resource id from the file name
- int rID = activity.getResources().getIdentifier(getClass().getPackage().getName() + ":raw/" + fileName,
- null, null);
- // get the file as a stream
- iS = activity.getResources().openRawResource(rID);
- } else {
- // get the file as a stream
- iS = activity.getResources().getAssets().open(fileName);
- }
-
- ByteArrayOutputStream oS = new ByteArrayOutputStream();
- byte[] buffer = new byte[iS.available()];
- int bytesRead = 0;
- while ((bytesRead = iS.read(buffer)) > 0) {
- oS.write(buffer);
- }
- oS.close();
- iS.close();
-
- // return the output stream as a String
- return oS.toString();
- }
-
- public static void saveFileContents(String dBFile, String machinesToExport) {
- // TODO Auto-generated method stub
- byteArrayToFile(machinesToExport.getBytes(), new File(dBFile));
- }
-
- public static void byteArrayToFile(byte[] byteData, File filePath) {
-
- try {
- FileOutputStream fos = new FileOutputStream(filePath);
- fos.write(byteData);
- fos.close();
-
- } catch (FileNotFoundException ex) {
- System.out.println("FileNotFoundException : " + ex);
- } catch (IOException ioe) {
- System.out.println("IOException : " + ioe);
- }
-
- }
-
- public static String getDataDir(Context context) {
-
- String dataDir = context.getApplicationInfo().dataDir;
- PackageManager m = context.getPackageManager();
- String packageName = context.getPackageName();
- Log.v("VMExecutor", "Found packageName: " + packageName);
-
- if (dataDir == null) {
- dataDir = "/data/data/" + packageName;
- }
- return dataDir;
- }
-
- public static boolean fileValid(Context context, String path) {
-
- if (path == null || path.equals(""))
- return true;
- if (path.startsWith("content://") || path.startsWith("/content/")) {
- int fd = get_fd(context, path);
- if (fd <= 0)
- return false;
- } else {
- File file = new File(path);
- return file.exists();
- }
- return true;
- }
-
- public static HashMap fds = new HashMap();
-
- public static int get_fd(final Context context, String path) {
- int fd = 0;
- if (path == null)
- return 0;
-
- if (path.startsWith("/content") || path.startsWith("content://")) {
- path = path.replaceFirst("/content", "content:");
-
- try {
- ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(Uri.parse(path), "rw");
- fd = pfd.getFd();
- fds.put(fd, pfd);
- } catch (final FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- new Handler(Looper.getMainLooper()).post(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(context, "Error: " + e, Toast.LENGTH_SHORT).show();
- }
- });
- }
- } else {
- try {
- File file = new File(path);
- if (!file.exists())
- file.createNewFile();
- ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_WRITE_ONLY);
- fd = pfd.getFd();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- }
- return fd;
- }
-
- public static int close_fd(int fd) {
-
- if (FileUtils.fds.containsKey(fd)) {
- ParcelFileDescriptor pfd = FileUtils.fds.get(fd);
- try {
- pfd.close();
- FileUtils.fds.remove(fd);
- return 0; // success for Native side
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
- return -1;
- }
-
- public static void writeToFile(String data, File file, Context context) {
- try {
- FileOutputStream fileOutStream = new FileOutputStream(file);
- OutputStreamWriter outputWriter = new OutputStreamWriter(fileOutStream);
- outputWriter.write(data);
- outputWriter.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public static String readFromFile(Context context, File file) {
- String contents = null;
- try {
- int length = (int) file.length();
-
- byte[] bytes = new byte[length];
-
- FileInputStream in = new FileInputStream(file);
- try {
- in.read(bytes);
- } finally {
- in.close();
- }
-
- contents = new String(bytes);
- } catch (Exception e) {
- UIUtils.toastLong(context, e.toString());
- return "error";
- }
- return contents;
- }
-
- public static boolean moveFile(String oldfilename, String newFolderPath, String newFilename) {
- File folder = new File(newFolderPath);
- if (!folder.exists())
- folder.mkdirs();
-
- File oldfile = new File(oldfilename);
- File newFile = new File(newFolderPath, newFilename);
-
- if (!newFile.exists()) {
+ public static final String TAG = "FileUtils";
+
+ @NonNull
+ public static File getExternalFilesDirectory(Context context) {
+ return new File(Environment.getExternalStorageDirectory(), "Documents/VectrasVM");
+ }
+
+ public static void chmod(File file, int mode) {
+ try {
+ Os.chmod(file.getAbsolutePath(), mode);
+ } catch (ErrnoException e) {
+ }
+ }
+
+ private static Uri contentUri = null;
+
+ @SuppressLint("NewApi")
+ public static String getPath(Context context, final Uri uri) {
+ // check here to KITKAT or new version
+ final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
+ String selection = null;
+ String[] selectionArgs = null;
+ // DocumentProvider
+ if (isKitKat) {
+ // ExternalStorageProvider
+
+ if (isExternalStorageDocument(uri)) {
+ final String docId = DocumentsContract.getDocumentId(uri);
+ final String[] split = docId.split(":");
+ final String type = split[0];
+
+ String fullPath = getPathFromExtSD(split);
+ if (fullPath != "") {
+ return fullPath;
+ } else {
+ return null;
+ }
+ }
+
+
+ // DownloadsProvider
+
+ if (isDownloadsDocument(uri)) {
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ final String id;
+ Cursor cursor = null;
+ try {
+ cursor = context.getContentResolver().query(uri, new String[]{MediaStore.MediaColumns.DISPLAY_NAME}, null, null, null);
+ if (cursor != null && cursor.moveToFirst()) {
+ String fileName = cursor.getString(0);
+ String path = Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName;
+ if (!TextUtils.isEmpty(path)) {
+ return path;
+ }
+ }
+ } finally {
+ if (cursor != null)
+ cursor.close();
+ }
+ id = DocumentsContract.getDocumentId(uri);
+ if (!TextUtils.isEmpty(id)) {
+ if (id.startsWith("raw:")) {
+ return id.replaceFirst("raw:", "");
+ }
+ String[] contentUriPrefixesToTry = new String[]{
+ "content://downloads/public_downloads",
+ "content://downloads/my_downloads"
+ };
+ for (String contentUriPrefix : contentUriPrefixesToTry) {
+ try {
+ final Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id));
+
+
+ return getDataColumn(context, contentUri, null, null);
+ } catch (NumberFormatException e) {
+ //In Android 8 and Android P the id is not a number
+ return uri.getPath().replaceFirst("^/document/raw:", "").replaceFirst("^raw:", "");
+ }
+ }
+
+
+ }
+ } else {
+ final String id = DocumentsContract.getDocumentId(uri);
+
+ if (id.startsWith("raw:")) {
+ return id.replaceFirst("raw:", "");
+ }
+ try {
+ contentUri = ContentUris.withAppendedId(
+ Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+ if (contentUri != null) {
+
+ return getDataColumn(context, contentUri, null, null);
+ }
+ }
+ }
+
+
+ // MediaProvider
+ if (isMediaDocument(uri)) {
+ final String docId = DocumentsContract.getDocumentId(uri);
+ final String[] split = docId.split(":");
+ final String type = split[0];
+
+ Uri contentUri = null;
+
+ if ("image".equals(type)) {
+ contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+ } else if ("video".equals(type)) {
+ contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
+ } else if ("audio".equals(type)) {
+ contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+ }
+ selection = "_id=?";
+ selectionArgs = new String[]{split[1]};
+
+
+ return getDataColumn(context, contentUri, selection,
+ selectionArgs);
+ }
+
+ if (isGoogleDriveUri(uri)) {
+ return getDriveFilePath(context, uri);
+ }
+
+ if (isWhatsAppFile(uri)) {
+ return getFilePathForWhatsApp(context, uri);
+ }
+
+
+ if ("content".equalsIgnoreCase(uri.getScheme())) {
+
+ if (isGooglePhotosUri(uri)) {
+ return uri.getLastPathSegment();
+ }
+ if (isGoogleDriveUri(uri)) {
+ return getDriveFilePath(context, uri);
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+
+ // return getFilePathFromURI(context,uri);
+ return copyFileToInternalStorage(context, uri, "userfiles");
+ // return getRealPathFromURI(context,uri);
+ } else {
+ return getDataColumn(context, uri, null, null);
+ }
+
+ }
+ if ("file".equalsIgnoreCase(uri.getScheme())) {
+ return uri.getPath();
+ }
+ } else {
+
+ if (isWhatsAppFile(uri)) {
+ return getFilePathForWhatsApp(context, uri);
+ }
+
+ if ("content".equalsIgnoreCase(uri.getScheme())) {
+ String[] projection = {
+ MediaStore.Images.Media.DATA
+ };
+ Cursor cursor = null;
+ try {
+ cursor = context.getContentResolver()
+ .query(uri, projection, selection, selectionArgs, null);
+ int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
+ if (cursor.moveToFirst()) {
+ return cursor.getString(column_index);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return null;
+ }
+
+ private static boolean fileExists(String filePath) {
+ File file = new File(filePath);
+
+ return file.exists();
+ }
+
+ private static String getPathFromExtSD(String[] pathData) {
+ final String type = pathData[0];
+ final String relativePath = "/" + pathData[1];
+ String fullPath = "";
+
+ // on my Sony devices (4.4.4 & 5.1.1), `type` is a dynamic string
+ // something like "71F8-2C0A", some kind of unique id per storage
+ // don't know any API that can get the root path of that storage based on its id.
+ //
+ // so no "primary" type, but let the check here for other devices
+ if ("primary".equalsIgnoreCase(type)) {
+ fullPath = Environment.getExternalStorageDirectory() + relativePath;
+ if (fileExists(fullPath)) {
+ return fullPath;
+ }
+ }
+
+ // Environment.isExternalStorageRemovable() is `true` for external and internal storage
+ // so we cannot relay on it.
+ //
+ // instead, for each possible path, check if file exists
+ // we'll start with secondary storage as this could be our (physically) removable sd card
+ fullPath = System.getenv("SECONDARY_STORAGE") + relativePath;
+ if (fileExists(fullPath)) {
+ return fullPath;
+ }
+
+ fullPath = System.getenv("EXTERNAL_STORAGE") + relativePath;
+ if (fileExists(fullPath)) {
+ return fullPath;
+ }
+
+ return fullPath;
+ }
+
+ private static String getDriveFilePath(Context context, Uri uri) {
+ Uri returnUri = uri;
+ Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);
+ /*
+ * Get the column indexes of the data in the Cursor,
+ * * move to the first row in the Cursor, get the data,
+ * * and display it.
+ * */
+ int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
+ int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
+ returnCursor.moveToFirst();
+ String name = (returnCursor.getString(nameIndex));
+ String size = (Long.toString(returnCursor.getLong(sizeIndex)));
+ File file = new File(context.getCacheDir(), name);
+ try {
+ InputStream inputStream = context.getContentResolver().openInputStream(uri);
+ FileOutputStream outputStream = new FileOutputStream(file);
+ int read = 0;
+ int maxBufferSize = 1 * 1024 * 1024;
+ int bytesAvailable = inputStream.available();
+
+ //int bufferSize = 1024;
+ int bufferSize = Math.min(bytesAvailable, maxBufferSize);
+
+ final byte[] buffers = new byte[bufferSize];
+ while ((read = inputStream.read(buffers)) != -1) {
+ outputStream.write(buffers, 0, read);
+ }
+ Log.e("File Size", "Size " + file.length());
+ inputStream.close();
+ outputStream.close();
+ Log.e("File Path", "Path " + file.getPath());
+ Log.e("File Size", "Size " + file.length());
+ } catch (Exception e) {
+ Log.e("Exception", e.getMessage());
+ }
+ return file.getPath();
+ }
+
+ /***
+ * Used for Android Q+
+ * @param uri
+ * @param newDirName if you want to create a directory, you can set this variable
+ * @return
+ */
+ private static String copyFileToInternalStorage(Context context, Uri uri, String newDirName) {
+ Uri returnUri = uri;
+
+ Cursor returnCursor = context.getContentResolver().query(returnUri, new String[]{
+ OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE
+ }, null, null, null);
+
+
+ /*
+ * Get the column indexes of the data in the Cursor,
+ * * move to the first row in the Cursor, get the data,
+ * * and display it.
+ * */
+ int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
+ int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
+ returnCursor.moveToFirst();
+ String name = (returnCursor.getString(nameIndex));
+ String size = (Long.toString(returnCursor.getLong(sizeIndex)));
+
+ File output;
+ if (!newDirName.equals("")) {
+ File dir = new File(context.getFilesDir() + "/" + newDirName);
+ if (!dir.exists()) {
+ dir.mkdir();
+ }
+ output = new File(context.getFilesDir() + "/" + newDirName + "/" + name);
+ } else {
+ output = new File(context.getFilesDir() + "/" + name);
+ }
+ try {
+ InputStream inputStream = context.getContentResolver().openInputStream(uri);
+ FileOutputStream outputStream = new FileOutputStream(output);
+ int read = 0;
+ int bufferSize = 1024;
+ final byte[] buffers = new byte[bufferSize];
+ while ((read = inputStream.read(buffers)) != -1) {
+ outputStream.write(buffers, 0, read);
+ }
+
+ inputStream.close();
+ outputStream.close();
+
+ } catch (Exception e) {
+
+ Log.e("Exception", e.getMessage());
+ }
+
+ return output.getPath();
+ }
+
+ private static String getFilePathForWhatsApp(Context context, Uri uri) {
+ return copyFileToInternalStorage(context, uri, "whatsapp");
+ }
+
+ private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
+ if (uri == null) return null;
+
+ Cursor cursor = null;
+ final String column = "_data";
+ final String[] projection = {column};
+
+ try {
+ cursor = context.getContentResolver().query(uri, projection,
+ selection, selectionArgs, null);
+
+ if (cursor != null && cursor.moveToFirst()) {
+ final int index = cursor.getColumnIndexOrThrow(column);
+ return cursor.getString(index);
+ }
+ } finally {
+ if (cursor != null)
+ cursor.close();
+ }
+
+ return null;
+ }
+
+ private static boolean isExternalStorageDocument(Uri uri) {
+ return "com.android.externalstorage.documents".equals(uri.getAuthority());
+ }
+
+ private static boolean isDownloadsDocument(Uri uri) {
+ return "com.android.providers.downloads.documents".equals(uri.getAuthority());
+ }
+
+ private static boolean isMediaDocument(Uri uri) {
+ return "com.android.providers.media.documents".equals(uri.getAuthority());
+ }
+
+ private static boolean isGooglePhotosUri(Uri uri) {
+ return "com.google.android.apps.photos.content".equals(uri.getAuthority());
+ }
+
+ public static boolean isWhatsAppFile(Uri uri) {
+ return "com.whatsapp.provider.media".equals(uri.getAuthority());
+ }
+
+ private static boolean isGoogleDriveUri(Uri uri) {
+ return "com.google.android.apps.docs.storage".equals(uri.getAuthority()) || "com.google.android.apps.docs.storage.legacy".equals(uri.getAuthority());
+ }
+
+
+ public String LoadFile(Activity activity, String fileName, boolean loadFromRawFolder) throws IOException {
+ // Create a InputStream to read the file into
+ InputStream iS;
+ if (loadFromRawFolder) {
+ // get the resource id from the file name
+ int rID = activity.getResources().getIdentifier(getClass().getPackage().getName() + ":raw/" + fileName,
+ null, null);
+ // get the file as a stream
+ iS = activity.getResources().openRawResource(rID);
+ } else {
+ // get the file as a stream
+ iS = activity.getResources().getAssets().open(fileName);
+ }
+
+ ByteArrayOutputStream oS = new ByteArrayOutputStream();
+ byte[] buffer = new byte[iS.available()];
+ int bytesRead = 0;
+ while ((bytesRead = iS.read(buffer)) > 0) {
+ oS.write(buffer);
+ }
+ oS.close();
+ iS.close();
+
+ // return the output stream as a String
+ return oS.toString();
+ }
+
+ public static void saveFileContents(String dBFile, String machinesToExport) {
+ // TODO Auto-generated method stub
+ byteArrayToFile(machinesToExport.getBytes(), new File(dBFile));
+ }
+
+ public static void byteArrayToFile(byte[] byteData, File filePath) {
+
+ try {
+ FileOutputStream fos = new FileOutputStream(filePath);
+ fos.write(byteData);
+ fos.close();
+
+ } catch (FileNotFoundException ex) {
+ System.out.println("FileNotFoundException : " + ex);
+ } catch (IOException ioe) {
+ System.out.println("IOException : " + ioe);
+ }
+
+ }
+
+ public static String getDataDir(Context context) {
+
+ String dataDir = context.getApplicationInfo().dataDir;
+ PackageManager m = context.getPackageManager();
+ String packageName = context.getPackageName();
+ Log.v("VMExecutor", "Found packageName: " + packageName);
+
+ if (dataDir == null) {
+ dataDir = "/data/data/" + packageName;
+ }
+ return dataDir;
+ }
+
+ public static boolean fileValid(Context context, String path) {
+
+ if (path == null || path.equals(""))
+ return true;
+ if (path.startsWith("content://") || path.startsWith("/content/")) {
+ int fd = get_fd(context, path);
+ if (fd <= 0)
+ return false;
+ } else {
+ File file = new File(path);
+ return file.exists();
+ }
+ return true;
+ }
+
+ public static HashMap fds = new HashMap();
+
+ public static int get_fd(final Context context, String path) {
+ int fd = 0;
+ if (path == null)
+ return 0;
+
+ if (path.startsWith("/content") || path.startsWith("content://")) {
+ path = path.replaceFirst("/content", "content:");
+
+ try {
+ ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(Uri.parse(path), "rw");
+ fd = pfd.getFd();
+ fds.put(fd, pfd);
+ } catch (final FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ new Handler(Looper.getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(context, "Error: " + e, Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ } else {
+ try {
+ File file = new File(path);
+ if (!file.exists())
+ file.createNewFile();
+ ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_WRITE_ONLY);
+ fd = pfd.getFd();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+ return fd;
+ }
+
+ public static int close_fd(int fd) {
+
+ if (FileUtils.fds.containsKey(fd)) {
+ ParcelFileDescriptor pfd = FileUtils.fds.get(fd);
+ try {
+ pfd.close();
+ FileUtils.fds.remove(fd);
+ return 0; // success for Native side
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+ return -1;
+ }
+
+ public static void writeToFile(String data, File file, Context context) {
+ try {
+ FileOutputStream fileOutStream = new FileOutputStream(file);
+ OutputStreamWriter outputWriter = new OutputStreamWriter(fileOutStream);
+ outputWriter.write(data);
+ outputWriter.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static String readFromFile(Context context, File file) {
+ String contents = null;
+ try {
+ int length = (int) file.length();
+
+ byte[] bytes = new byte[length];
+
+ FileInputStream in = new FileInputStream(file);
+ try {
+ in.read(bytes);
+ } finally {
+ in.close();
+ }
+
+ contents = new String(bytes);
+ } catch (Exception e) {
+ UIUtils.toastLong(context, e.toString());
+ return "error";
+ }
+ return contents;
+ }
+
+ public static boolean moveFile(String oldfilename, String newFolderPath, String newFilename) {
+ File folder = new File(newFolderPath);
+ if (!folder.exists())
+ folder.mkdirs();
+
+ File oldfile = new File(oldfilename);
+ File newFile = new File(newFolderPath, newFilename);
+
+ if (!newFile.exists()) {
try {
newFile.createNewFile();
} catch (IOException e) {
@@ -611,74 +602,74 @@ public class FileUtils {
e.printStackTrace();
}
}
- return oldfile.renameTo(newFile);
- }
+ return oldfile.renameTo(newFile);
+ }
- public static boolean isFileExists(String filePath) {
- File file = new File(filePath.replaceAll("\n", ""));
- return file.exists();
- }
+ public static boolean isFileExists(String filePath) {
+ File file = new File(filePath.replaceAll("\n", ""));
+ return file.exists();
+ }
- public static void moveAFile(String _from, String _to) {
- File oldFile = new File(_from);
- File newFile = new File(_to);
+ public static void moveAFile(String _from, String _to) {
+ File oldFile = new File(_from);
+ File newFile = new File(_to);
- boolean success = oldFile.renameTo(newFile);
- if (success) {
- Log.d("File", "Done!");
- } else {
- Log.e("File", "Failed!");
- }
- }
+ boolean success = oldFile.renameTo(newFile);
+ if (success) {
+ Log.d("File", "Done!");
+ } else {
+ Log.e("File", "Failed!");
+ }
+ }
- public static void copyAFile(String _sourceFile, String _destFile) {
- File vDir = new File(_destFile.substring((int)0, (int)(_destFile.lastIndexOf("/"))));
- if (!vDir.exists()) {
- vDir.mkdirs();
- }
- try {
- File source = new File(_sourceFile);
- File dest = new File(_destFile);
+ public static boolean copyFile(String _sourceFile, String _destFile) {
+ File vDir = new File(_destFile.substring(0, _destFile.lastIndexOf("/")));
+ if (!vDir.exists() && vDir.mkdirs()) {
+ return false;
+ }
+ try {
+ File source = new File(_sourceFile);
+ File dest = new File(_destFile);
- if (!source.exists())
- {
- throw new IOException("Source file not found");
- }
+ if (!source.exists()) {
+ return false;
+ }
- FileInputStream inStream = new FileInputStream(source);
- FileOutputStream outStream = new FileOutputStream(dest);
+ FileInputStream inStream = new FileInputStream(source);
+ FileOutputStream outStream = new FileOutputStream(dest);
- byte[] buffer = new byte[1024];
- int length;
- while ((length = inStream.read(buffer))
- > 0) {
- outStream.write(buffer, 0, length);
- }
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = inStream.read(buffer))
+ > 0) {
+ outStream.write(buffer, 0, length);
+ }
- inStream.close();
- outStream.close();
- } catch (IOException e) {
+ inStream.close();
+ outStream.close();
+ } catch (IOException e) {
+ return false;
+ }
+ return true;
+ }
- }
+ public static void copyFileFromUri(Context context, Uri sourceUri, String destFile) throws IOException {
- }
-
- public static void copyFileFromUri(Context context, Uri sourceUri, String destFile) throws IOException {
-
- File file = new File(destFile);
- if (!Objects.requireNonNull(file.getParentFile()).exists()) {
- file.getParentFile().mkdirs();
- }
+ File file = new File(destFile);
+ if (!Objects.requireNonNull(file.getParentFile()).exists()) {
+ if (!file.getParentFile().mkdirs())
+ throw new IOException("Failed to create directory: " + file.getParentFile().getAbsolutePath());
+ }
try (InputStream inputStream = context.getContentResolver().openInputStream(sourceUri); OutputStream outputStream = new FileOutputStream(destFile)) {
- byte[] buffer = new byte[32 * 1024];
- if (DeviceUtils.totalMemoryCapacity(context) < 3L * 1024 * 1024 * 1024) {
- buffer = new byte[4 * 1024];
- } else if (DeviceUtils.totalMemoryCapacity(context) < 5L * 1024 * 1024 * 1024) {
- buffer = new byte[8 * 1024];
- } else if (DeviceUtils.totalMemoryCapacity(context) < 7L * 1024 * 1024 * 1024) {
- buffer = new byte[16 * 1024];
- }
+ byte[] buffer = new byte[32 * 1024];
+ if (DeviceUtils.totalMemoryCapacity(context) < 3L * 1024 * 1024 * 1024) {
+ buffer = new byte[4 * 1024];
+ } else if (DeviceUtils.totalMemoryCapacity(context) < 5L * 1024 * 1024 * 1024) {
+ buffer = new byte[8 * 1024];
+ } else if (DeviceUtils.totalMemoryCapacity(context) < 7L * 1024 * 1024 * 1024) {
+ buffer = new byte[16 * 1024];
+ }
int bytesRead;
while (true) {
assert inputStream != null;
@@ -688,240 +679,265 @@ public class FileUtils {
outputStream.flush();
}
- }
+ }
- public static String getFileNameFromUri(Context context, Uri uri) {
- String result = null;
+ public static void copyFileToUri(
+ Context context,
+ String sourcePath,
+ Uri uri
+ ) throws Exception {
- Cursor cursor = context.getContentResolver().query(
- uri,
- null,
- null,
- null,
- null
- );
+ InputStream in = new FileInputStream(sourcePath);
+ OutputStream out = context.getContentResolver().openOutputStream(uri);
+ byte[] buffer = new byte[32 * 1024];
+ if (DeviceUtils.totalMemoryCapacity(context) < 3L * 1024 * 1024 * 1024) {
+ buffer = new byte[4 * 1024];
+ } else if (DeviceUtils.totalMemoryCapacity(context) < 5L * 1024 * 1024 * 1024) {
+ buffer = new byte[8 * 1024];
+ } else if (DeviceUtils.totalMemoryCapacity(context) < 7L * 1024 * 1024 * 1024) {
+ buffer = new byte[16 * 1024];
+ }
+ int len;
+ while ((len = in.read(buffer)) != -1) {
+ out.write(buffer, 0, len);
+ }
+ }
- try {
- if (cursor != null && cursor.moveToFirst()) {
- int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
- result = cursor.getString(nameIndex);
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- if (result == null) {
- result = uri.getLastPathSegment();
- }
+ public static String getFileNameFromUri(Context context, Uri uri) {
+ String result = null;
- return result;
- }
+ Cursor cursor = context.getContentResolver().query(
+ uri,
+ null,
+ null,
+ null,
+ null
+ );
- public static void deleteDirectory(String _pathToDelete) {
- File _dir = new File(_pathToDelete);
- if (_dir.isDirectory()) {
- String[] children = _dir.list();
+ try {
+ if (cursor != null && cursor.moveToFirst()) {
+ int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
+ result = cursor.getString(nameIndex);
+ }
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
- if (children == null) {
- Log.e("ERROR", "Deletion failed. " + _dir);
- return;
- }
+ if (result == null) {
+ result = uri.getLastPathSegment();
+ }
- for (int i = 0; i < children.length; i++) {
- File temp = new File(_dir, children[i]);
- deleteDirectory(String.valueOf(temp));
- }
- }
- boolean success = _dir.delete();
- if (!success) {
- Log.e("ERROR", "Deletion failed. " + _dir);
- }
- }
+ return result;
+ }
+
+ public static void deleteDirectory(String _pathToDelete) {
+ File _dir = new File(_pathToDelete);
+ if (_dir.isDirectory()) {
+ String[] children = _dir.list();
+
+ if (children == null) {
+ Log.e("ERROR", "Deletion failed. " + _dir);
+ return;
+ }
+
+ for (int i = 0; i < children.length; i++) {
+ File temp = new File(_dir, children[i]);
+ deleteDirectory(String.valueOf(temp));
+ }
+ }
+ boolean success = _dir.delete();
+ if (!success) {
+ Log.e("ERROR", "Deletion failed. " + _dir);
+ }
+ }
public static boolean canRead(String filePath) {
File file = new File(filePath);
return file.canRead();
}
- public static String readAFile(String filePath) {
- StringBuilder content = new StringBuilder();
- try (FileInputStream inputStream = new FileInputStream(filePath);
- BufferedReader reader = new BufferedReader(new
- InputStreamReader(inputStream))) {
- String line;
- while ((line = reader.readLine()) != null) {
- content.append(line).append("\n");
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- return content.toString();
+ public static String readAFile(String filePath) {
+ if (!FileUtils.isFileExists(filePath)) return "";
- }
+ StringBuilder content = new StringBuilder();
+ try (FileInputStream inputStream = new FileInputStream(filePath);
+ BufferedReader reader = new BufferedReader(new
+ InputStreamReader(inputStream))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ content.append(line).append("\n");
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return content.toString();
- public static boolean writeToFile(String folderPath, String fileName, String content) {
- File vDir = new File(folderPath);
- if (!vDir.exists()) {
- if (!vDir.mkdirs()) return false;
- }
- File file = new File(folderPath, fileName);
- FileOutputStream outputStream;
- try {
- outputStream = new FileOutputStream(file);
- outputStream.write(content.getBytes());
- outputStream.close();
- } catch (IOException e) {
- Log.e(TAG, "writeToFile: ", e);
- return false;
- }
- return true;
- }
+ }
- public static void getAListOfAllFilesAndFoldersInADirectory(String path, ArrayList list) {
- File dir = new File(path);
- if (!dir.exists() || dir.isFile()) return;
+ public static boolean writeToFile(String folderPath, String fileName, String content) {
+ File vDir = new File(folderPath);
+ if (!vDir.exists()) {
+ if (!vDir.mkdirs()) return false;
+ }
+ File file = new File(folderPath, fileName);
+ FileOutputStream outputStream;
+ try {
+ outputStream = new FileOutputStream(file);
+ outputStream.write(content.getBytes());
+ outputStream.close();
+ } catch (IOException e) {
+ Log.e(TAG, "writeToFile: ", e);
+ return false;
+ }
+ return true;
+ }
- File[] listFiles = dir.listFiles();
- if (listFiles == null || listFiles.length <= 0) return;
+ public static void getAListOfAllFilesAndFoldersInADirectory(String path, ArrayList list) {
+ File dir = new File(path);
+ if (!dir.exists() || dir.isFile()) return;
- if (list == null) return;
- list.clear();
- for (File file : listFiles) {
- list.add(file.getAbsolutePath());
- }
- }
+ File[] listFiles = dir.listFiles();
+ if (listFiles == null || listFiles.length <= 0) return;
- public static int getFileSize(String _path) {
- try {
- File file = new File(_path);
- if (!file.exists()) {
- return 0;
- }
- return (int) file.length();
- } catch (Exception _e) {
- return 0;
- }
- }
+ if (list == null) return;
+ list.clear();
+ for (File file : listFiles) {
+ list.add(file.getAbsolutePath());
+ }
+ }
- public static long getFolderSize(String _path) {
- try {
- File file;
- file = new File(_path);
- if (file == null || !file.exists()) {
- return 0;
- }
- if (!file.isDirectory()) {
- return (int) file.length();
- }
- final List dirs = new LinkedList<>();
- dirs.add(file);
- long result = 0;
- while (!dirs.isEmpty()) {
- final File dir = dirs.remove(0);
- if (!dir.exists()) {
- continue;
- }
- final File[] listFiles = dir.listFiles();
- if (listFiles == null || listFiles.length == 0) {
- continue;
- }
- for (final File child : listFiles) {
- result += child.length();
- if (child.isDirectory()) {
- dirs.add(child);
- }
- }
- }
- return result;
- } catch (Exception _e) {
- return 0;
- }
- }
+ public static int getFileSize(String _path) {
+ try {
+ File file = new File(_path);
+ if (!file.exists()) {
+ return 0;
+ }
+ return (int) file.length();
+ } catch (Exception _e) {
+ return 0;
+ }
+ }
- public static String getFilePathFromUri(Context context, Uri uri) {
- String filePath = null;
- if ("content".equalsIgnoreCase(uri.getScheme())) {
- String[] projection = {MediaStore.Files.FileColumns.DATA};
+ public static long getFolderSize(String _path) {
+ try {
+ File file;
+ file = new File(_path);
+ if (file == null || !file.exists()) {
+ return 0;
+ }
+ if (!file.isDirectory()) {
+ return (int) file.length();
+ }
+ final List dirs = new LinkedList<>();
+ dirs.add(file);
+ long result = 0;
+ while (!dirs.isEmpty()) {
+ final File dir = dirs.remove(0);
+ if (!dir.exists()) {
+ continue;
+ }
+ final File[] listFiles = dir.listFiles();
+ if (listFiles == null || listFiles.length == 0) {
+ continue;
+ }
+ for (final File child : listFiles) {
+ result += child.length();
+ if (child.isDirectory()) {
+ dirs.add(child);
+ }
+ }
+ }
+ return result;
+ } catch (Exception _e) {
+ return 0;
+ }
+ }
+
+ public static String getFilePathFromUri(Context context, Uri uri) {
+ String filePath = null;
+ if ("content".equalsIgnoreCase(uri.getScheme())) {
+ String[] projection = {MediaStore.Files.FileColumns.DATA};
try (Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
int index = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA);
filePath = cursor.getString(index);
}
} catch (Exception e) {
- Log.e(TAG, "getFilePathFromUri: ", e);
+ Log.e(TAG, "getFilePathFromUri: ", e);
}
- } else if ("file".equalsIgnoreCase(uri.getScheme())) {
- filePath = uri.getPath();
- }
- return filePath;
- }
+ } else if ("file".equalsIgnoreCase(uri.getScheme())) {
+ filePath = uri.getPath();
+ }
+ return filePath;
+ }
- public static boolean isValidFilePath(Activity activity, String filePath, boolean isShowDialog) {
- if (filePath == null || filePath.isEmpty()) {
- if (isShowDialog) {
- DialogUtils.oneDialog(activity,
- activity.getString(R.string.problem_has_been_detected),
- activity.getString(R.string.invalid_file_path_content),
- activity.getString(R.string.ok),
- true,
- R.drawable.folder_24px,
- true,
- null,
- null);
- }
- return false;
- }
- return true;
- }
+ public static boolean isValidFilePath(Activity activity, String filePath, boolean isShowDialog) {
+ if (filePath == null || filePath.isEmpty()) {
+ if (isShowDialog) {
+ DialogUtils.oneDialog(activity,
+ activity.getString(R.string.problem_has_been_detected),
+ activity.getString(R.string.invalid_file_path_content),
+ activity.getString(R.string.ok),
+ true,
+ R.drawable.folder_24px,
+ true,
+ null,
+ null);
+ }
+ return false;
+ }
+ return true;
+ }
- public static void openFolder(Context context, String folderPath) {
- File folder = new File(folderPath);
+ public static void openFolder(Context context, String folderPath) {
+ File folder = new File(folderPath);
- if (!folder.exists() || !folder.isDirectory()) {
- DialogUtils.oneDialog(
- context,
- context.getString(R.string.oops),
- context.getString(R.string.directory_does_not_exist),
- context.getString(R.string.ok),
- true,
- R.drawable.error_96px,
- true,
- null,
- null
- );
- Log.e(TAG, "openFolder: Folder not found!");
- return;
- }
+ if (!folder.exists() || !folder.isDirectory()) {
+ DialogUtils.oneDialog(
+ context,
+ context.getString(R.string.oops),
+ context.getString(R.string.directory_does_not_exist),
+ context.getString(R.string.ok),
+ true,
+ R.drawable.error_96px,
+ true,
+ null,
+ null
+ );
+ Log.e(TAG, "openFolder: Folder not found!");
+ return;
+ }
- Uri uri = FileProvider.getUriForFile(
- context,
- context.getPackageName() + ".provider",
- folder
- );
+ Uri uri = FileProvider.getUriForFile(
+ context,
+ context.getPackageName() + ".provider",
+ folder
+ );
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(uri, "resource/folder");
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setDataAndType(uri, "resource/folder");
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try {
- context.startActivity(intent);
- } catch (Exception e) {
- DialogUtils.oneDialog(
- context,
- context.getString(R.string.oops),
- context.getString(R.string.there_is_no_app_to_perform_this_action),
- context.getString(R.string.ok),
- true,
- R.drawable.error_96px,
- true,
- null,
- null
- );
- Log.e(TAG, "openFolder: " + e.getMessage());
- }
- }
+ try {
+ context.startActivity(intent);
+ } catch (Exception e) {
+ DialogUtils.oneDialog(
+ context,
+ context.getString(R.string.oops),
+ context.getString(R.string.there_is_no_app_to_perform_this_action),
+ context.getString(R.string.ok),
+ true,
+ R.drawable.error_96px,
+ true,
+ null,
+ null
+ );
+ Log.e(TAG, "openFolder: " + e.getMessage());
+ }
+ }
}
diff --git a/app/src/main/java/com/vectras/vm/utils/IntentUtils.java b/app/src/main/java/com/vectras/vm/utils/IntentUtils.java
new file mode 100644
index 0000000..19a0d50
--- /dev/null
+++ b/app/src/main/java/com/vectras/vm/utils/IntentUtils.java
@@ -0,0 +1,44 @@
+package com.vectras.vm.utils;
+
+import static android.content.Intent.ACTION_VIEW;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+
+import com.vectras.vm.AppConfig;
+import com.vectras.vm.R;
+
+public class IntentUtils {
+ public static boolean openTelegramLink(Context context) {
+ return openUrl(context, AppConfig.telegramLink, true);
+ }
+
+ public static boolean openUrl(Context context, String url, boolean isShowErrorDialog) {
+ boolean result = openUrl(context, url);
+ if (isShowErrorDialog && !result) {
+ DialogUtils.oneDialog(
+ context,
+ context.getString(R.string.oops),
+ context.getString(R.string.there_is_no_app_to_perform_this_action),
+ R.drawable.error_96px
+ );
+ }
+ return result;
+ }
+
+ public static boolean openUrl(Context context, String url) {
+ Intent intent = new Intent(ACTION_VIEW);
+ intent.addCategory(Intent.CATEGORY_BROWSABLE);
+ intent.setData(Uri.parse(url));
+
+ PackageManager packagemanager = context.getPackageManager();
+ if (intent.resolveActivity(packagemanager) != null) {
+ context.startActivity(intent);
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/app/src/main/java/com/vectras/vm/utils/ZipUtils.java b/app/src/main/java/com/vectras/vm/utils/ZipUtils.java
index 946dc8d..444e2e6 100644
--- a/app/src/main/java/com/vectras/vm/utils/ZipUtils.java
+++ b/app/src/main/java/com/vectras/vm/utils/ZipUtils.java
@@ -14,9 +14,11 @@ 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;
+import java.io.OutputStream;
import java.util.Enumeration;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
@@ -258,64 +260,10 @@ public class ZipUtils {
ProgressBar progressBar
) {
try {
- long totalBytes = 0;
- for (String path : filePaths) {
- File f = new File(path);
- if (f.isFile()) totalBytes += f.length();
- }
-
- long bytesWritten = 0;
- byte[] buffer;
-
try (FileOutputStream fos = new FileOutputStream(outputZip);
ZipOutputStream zos = new ZipOutputStream(fos)) {
- for (String filePath : filePaths) {
- File file = new File(filePath);
- long size = file.length();
- long crc = calculateCrc(context, file);
-
- try (FileInputStream fis = new FileInputStream(file)) {
- ZipEntry entry = new ZipEntry(file.getName());
-
- entry.setMethod(ZipEntry.DEFLATED);
- entry.setSize(size);
-
- if (MainSettingsManager.getCyclicRedundancyCheck(context))
- entry.setCrc(crc);
-
- zos.putNextEntry(entry);
-
- if (DeviceUtils.totalMemoryCapacity(context) < 4L * 1024 * 1024 * 1024)
- buffer = new byte[64 * 1024];
- else
- buffer = new byte[128 * 1024];
-
- int len;
- long lastProgress = -1;
- while ((len = fis.read(buffer)) != -1) {
- zos.write(buffer, 0, len);
- bytesWritten += len;
-
- final int progress = (int) ((bytesWritten * 100L) / totalBytes);
-
- if (progress > lastProgress) {
- lastProgress = progress;
- updateStatus(
- statusTextView,
- progressBar,
- (progress == 0 || progress > 100 ?
- context.getString(R.string.exporting) :
- context.getString(R.string.completed) + " " + progress + "%")
- + "\n" + context.getString(R.string.please_stay_here),
- progress
- );
- }
- }
-
- zos.closeEntry();
- }
- }
+ compressCore(context, filePaths, zos, statusTextView, progressBar);
}
return true;
} catch (Exception e) {
@@ -325,6 +273,91 @@ public class ZipUtils {
}
}
+ public static boolean compress(
+ Context context,
+ String[] filePaths,
+ Uri outputZip,
+ TextView statusTextView,
+ ProgressBar progressBar
+ ) {
+ try {
+ try (OutputStream os = context.getContentResolver().openOutputStream(outputZip);
+ ZipOutputStream zos = new ZipOutputStream(os)) {
+
+ compressCore(context, filePaths, zos, statusTextView, progressBar);
+ }
+ return true;
+ } catch (Exception e) {
+ Log.e(TAG, "compress: ", e);
+ lastErrorContent = e.toString();
+ return false;
+ }
+ }
+
+ public static void compressCore(
+ Context context,
+ String[] filePaths,
+ ZipOutputStream zos,
+ TextView statusTextView,
+ ProgressBar progressBar) throws Exception {
+
+ long totalBytes = 0;
+ for (String path : filePaths) {
+ File f = new File(path);
+ if (f.isFile()) totalBytes += f.length();
+ }
+
+ long bytesWritten = 0;
+ byte[] buffer;
+
+ for (String filePath : filePaths) {
+ File file = new File(filePath);
+ long size = file.length();
+ long crc = calculateCrc(context, file);
+
+ try (FileInputStream fis = new FileInputStream(file)) {
+ ZipEntry entry = new ZipEntry(file.getName());
+
+ entry.setMethod(ZipEntry.DEFLATED);
+ entry.setSize(size);
+
+ if (MainSettingsManager.getCyclicRedundancyCheck(context))
+ entry.setCrc(crc);
+
+ zos.putNextEntry(entry);
+
+ if (DeviceUtils.totalMemoryCapacity(context) < 4L * 1024 * 1024 * 1024)
+ buffer = new byte[64 * 1024];
+ else
+ buffer = new byte[128 * 1024];
+
+ int len;
+ long lastProgress = -1;
+ while ((len = fis.read(buffer)) != -1) {
+ zos.write(buffer, 0, len);
+ bytesWritten += len;
+
+ final int progress = (int) ((bytesWritten * 100L) / totalBytes);
+
+ if (progress > lastProgress) {
+ lastProgress = progress;
+ updateStatus(
+ statusTextView,
+ progressBar,
+ (totalBytes > 0 && (progress == 0 || progress > 100) ?
+ context.getString(R.string.exporting) :
+ context.getString(R.string.completed) + " " + progress + "%")
+ + "\n" + context.getString(R.string.please_stay_here),
+ progress
+ );
+ }
+ }
+
+ zos.closeEntry();
+ }
+ }
+ }
+
private static void updateStatus(TextView statusTextView, ProgressBar progressbar, String msg, int progress) {
if (!(statusTextView == null || statusTextView.getContext() == null)) {
((Activity) statusTextView.getContext()).runOnUiThread(() -> statusTextView.setText(msg));
diff --git a/app/src/main/java/com/vectras/vm/view/GithubUserView.java b/app/src/main/java/com/vectras/vm/view/GithubUserView.java
index b2f5fe3..1f6bdb9 100644
--- a/app/src/main/java/com/vectras/vm/view/GithubUserView.java
+++ b/app/src/main/java/com/vectras/vm/view/GithubUserView.java
@@ -2,22 +2,20 @@ package com.vectras.vm.view;
import android.app.Activity;
import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.LayoutInflater;
-import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
-import android.widget.Button;
+
+import androidx.annotation.NonNull;
import com.bumptech.glide.Glide;
import com.vectras.vm.R;
import com.vectras.vm.model.GithubUser;
import com.vectras.vm.network.GithubApiService;
+import com.vectras.vm.utils.IntentUtils;
import retrofit2.Call;
import retrofit2.Callback;
@@ -73,7 +71,7 @@ public class GithubUserView extends LinearLayout {
Call call = service.getUser(username);
call.enqueue(new Callback() {
@Override
- public void onResponse(Call call, Response response) {
+ public void onResponse(@NonNull Call call, @NonNull Response response) {
if (response.isSuccessful() && response.body() != null) {
GithubUser user = response.body();
thisUserNameGitHub = user.getLogin();
@@ -95,7 +93,7 @@ public class GithubUserView extends LinearLayout {
}
@Override
- public void onFailure(Call call, Throwable t) {
+ public void onFailure(@NonNull Call call, @NonNull Throwable t) {
userName.setText(getContext().getString(R.string.unknow));
userDescription.setText(getContext().getString(R.string.unknow));
profileImage.setImageResource(R.drawable.account_circle_24px);
@@ -104,8 +102,6 @@ public class GithubUserView extends LinearLayout {
}
private void openGithubProfile(Context context) {
- String url = "https://github.com/" + thisUserNameGitHub;
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
- context.startActivity(intent);
+ IntentUtils.openUrl(context, "https://github.com/" + thisUserNameGitHub, true);
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/vectras/vterm/Terminal.java b/app/src/main/java/com/vectras/vterm/Terminal.java
index 1b26a27..c97dc0b 100644
--- a/app/src/main/java/com/vectras/vterm/Terminal.java
+++ b/app/src/main/java/com/vectras/vterm/Terminal.java
@@ -19,10 +19,6 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.Enumeration;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
@@ -30,6 +26,7 @@ import com.vectras.vm.R;
import com.vectras.vm.VMManager;
import com.vectras.vm.AppConfig;
import com.vectras.vm.VectrasApp;
+import com.vectras.vm.logger.VectrasStatus;
import com.vectras.vm.utils.ClipboardUltils;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.NotificationUtils;
@@ -63,18 +60,23 @@ public class Terminal {
AtomicReference output = new AtomicReference<>(new StringBuilder());
StringBuilder errors = new StringBuilder();
Log.d(TAG, userCommand);
- com.vectras.vm.logger.VectrasStatus.logError("VTERM: >" + userCommand + "");
+ VectrasStatus.logError("VTERM: >" + userCommand + "");
// Show ProgressDialog
- View progressView = LayoutInflater.from(dialogActivity).inflate(R.layout.dialog_progress_style, null);
- TextView progress_text = progressView.findViewById(R.id.progress_text);
- progress_text.setText(progressDialogMessage);
- AlertDialog progressDialog = new MaterialAlertDialogBuilder(dialogActivity, R.style.CenteredDialogTheme)
- .setView(progressView)
- .setCancelable(false)
- .create();
+ AlertDialog progressDialog;
+ if (dialogActivity != null) {
+ View progressView = LayoutInflater.from(dialogActivity).inflate(R.layout.dialog_progress_style, null);
+ TextView progress_text = progressView.findViewById(R.id.progress_text);
+ progress_text.setText(progressDialogMessage);
+ progressDialog = new MaterialAlertDialogBuilder(dialogActivity, R.style.CenteredDialogTheme)
+ .setView(progressView)
+ .setCancelable(false)
+ .create();
- if (showProgressDialog) progressDialog.show();
+ if (showProgressDialog) progressDialog.show();
+ } else {
+ progressDialog = null;
+ }
new Thread(() -> {
try {
@@ -116,17 +118,18 @@ public class Terminal {
output.set(streamLog(userCommand, qemuProcess, false));
} catch (IOException e) {
- progressDialog.dismiss(); // Dismiss ProgressDialog
output.get().append(e.getMessage());
errors.append(Log.getStackTraceString(e));
} finally {
new Handler(Looper.getMainLooper()).post(() -> {
- progressDialog.dismiss(); // Dismiss ProgressDialog
AppConfig.temporaryLastedTerminalOutput = output.toString();
- if (showResultDialog) {
- String finalOutput = output.toString();
- String finalErrors = errors.toString();
- showDialog(finalOutput.isEmpty() ? finalErrors : finalOutput.replace("read interrupted", "Done!"), dialogActivity, userCommand);
+ if (dialogActivity != null) {
+ progressDialog.dismiss(); // Dismiss ProgressDialog
+ if (showResultDialog) {
+ String finalOutput = output.toString();
+ String finalErrors = errors.toString();
+ showDialog(finalOutput.isEmpty() ? finalErrors : finalOutput.replace("read interrupted", "Done!"), dialogActivity, userCommand);
+ }
}
});
}
@@ -137,7 +140,7 @@ public class Terminal {
AtomicReference output = new AtomicReference<>(new StringBuilder());
StringBuilder errors = new StringBuilder();
Log.d(TAG, userCommand);
- com.vectras.vm.logger.VectrasStatus.logError("VTERM: >" + userCommand + "");
+ VectrasStatus.logError("VTERM: >" + userCommand + "");
new Thread(() -> {
try {
// Set up the qemuProcess builder to start PRoot with environmental variables and commands
@@ -185,7 +188,7 @@ public class Terminal {
processBuilder.command(prootCommand);
qemuProcess = processBuilder.start();
- output.set(streamLog(userCommand, qemuProcess, false));
+ output.set(streamLog(userCommand, qemuProcess, true));
} catch (IOException e) {
output.get().append(e.getMessage());
errors.append(Log.getStackTraceString(e));
@@ -210,7 +213,7 @@ public class Terminal {
StringBuilder output = new StringBuilder();
StringBuilder errors = new StringBuilder();
Log.d(TAG, userCommand);
- com.vectras.vm.logger.VectrasStatus.logError("VTERM: >" + userCommand + "");
+ VectrasStatus.logError("VTERM: >" + userCommand + "");
try {
ProcessBuilder processBuilder = new ProcessBuilder();
@@ -261,11 +264,11 @@ public class Terminal {
void onCommandCompleted(String output, String errors);
}
- public String executeShellCommand(String userCommand, Context dialogActivity, boolean isShowProgressDialog, CommandCallback callback) {
+ public void executeShellCommand(String userCommand, Context dialogActivity, boolean isShowProgressDialog, CommandCallback callback) {
AtomicReference output = new AtomicReference<>(new StringBuilder());
StringBuilder errors = new StringBuilder();
Log.d(TAG, userCommand);
- com.vectras.vm.logger.VectrasStatus.logError("VTERM: >" + userCommand + "");
+ VectrasStatus.logError("VTERM: >" + userCommand + "");
// Show ProgressDialog on the main thread
View progressView = LayoutInflater.from(dialogActivity).inflate(R.layout.dialog_progress_style, null);
@@ -330,8 +333,6 @@ public class Terminal {
new Handler(Looper.getMainLooper()).post(() -> callback.onCommandCompleted(output.toString(), errors.toString()));
}
}).start();
-
- return "Execution is in progress..."; // Returning a message indicating the command execution is ongoing
}
/**
@@ -357,7 +358,7 @@ public class Terminal {
return false;
}
- public static StringBuilder streamLog(String command, Process process, boolean isShortProcess) {
+ public static StringBuilder streamLog(String command, Process process, boolean isShowResultCode) {
StringBuilder output = new StringBuilder();
try {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
@@ -371,23 +372,29 @@ public class Terminal {
String line;
while ((line = reader.readLine()) != null) {
- com.vectras.vm.logger.VectrasStatus.logError("VTERM: >" + line + "");
+ VectrasStatus.logError("VTERM: >" + line + "");
output.append(line).append("\n");
}
while ((line = errorReader.readLine()) != null) {
Log.w(TAG, line);
- com.vectras.vm.logger.VectrasStatus.logError("VTERM ERROR: >" + line + "");
+ VectrasStatus.logError("VTERM ERROR: >" + line + "");
output.append(line).append("\n");
}
- if (isShortProcess) {
- int exitCode = process.waitFor();
- if (exitCode == 0) {
- output.append("Execution finished successfully.\n");
- } else {
- output.append("Execution finished with exit code: ").append(exitCode).append("\n");
+ if (isShowResultCode) {
+ new Thread(() -> {
+ int exitCode;
+ try {
+ exitCode = process.waitFor();
+ if (exitCode == 0) {
+ output.append("\nExecution finished successfully.\n");
+ } else {
+ output.append("\nExecution finished with exit code: ").append(exitCode).append("\n");
+ }
+ } catch (Exception ignored) {
}
+ }).start();
}
reader.close();
diff --git a/app/src/main/res/layout/activity_qemu_params_editor.xml b/app/src/main/res/layout/activity_qemu_params_editor.xml
index 460cbe4..508e062 100644
--- a/app/src/main/res/layout/activity_qemu_params_editor.xml
+++ b/app/src/main/res/layout/activity_qemu_params_editor.xml
@@ -6,7 +6,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:fitsSystemWindows="true"
android:id="@+id/main"
- tools:context=".QemuParamsEditorActivity">
+ tools:context=".creator.QemuParamsEditorActivity">
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/recycler_view.xml b/app/src/main/res/layout/recycler_view.xml
deleted file mode 100644
index 017a005..0000000
--- a/app/src/main/res/layout/recycler_view.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/simple_layout_list_view_with_check.xml b/app/src/main/res/layout/simple_layout_list_view_with_check.xml
index beb9771..80e6ba9 100644
--- a/app/src/main/res/layout/simple_layout_list_view_with_check.xml
+++ b/app/src/main/res/layout/simple_layout_list_view_with_check.xml
@@ -3,22 +3,20 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
- android:paddingVertical="16dp"
- android:paddingHorizontal="24dp"
+ android:padding="16dp"
android:id="@+id/main"
android:background="?attr/selectableItemBackground">
-
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 9d79145..d7c8095 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -508,6 +508,8 @@
Hard disk
Floppy disk
Network
+ Rom successfully exported.
+ Options
diff --git a/web/data/UpdateConfig.json b/web/data/UpdateConfig.json
index 8fb8892..87f5791 100644
--- a/web/data/UpdateConfig.json
+++ b/web/data/UpdateConfig.json
@@ -5,11 +5,11 @@
"url": "https://github.com/xoureldeen/Vectras-VM-Android/releases",
"Message": "3.6.0
\nBugs fixed.",
"cancellable": true,
- "versionCodeBeta":"70",
- "versionNameBeta":"3.6.6",
- "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",
+ "versionCodeBeta":"71",
+ "versionNameBeta":"3.6.7",
+ "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",
"sizeBeta": "43 MB",
"urlBeta": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases",
- "MessageBeta": "3.6.6
Bugs fixed.",
+ "MessageBeta": "3.6.7
Bugs fixed.",
"cancellableBeta": true
}