v2.9.5.12-3dfx

- Improved settings.
- Changed shared file import folder location.
- Fixed VM ID in VM creator sometimes not refreshing.
- Added detection of shared folders that exceed size limit.
- Improved file import on home screen.
- Now when clicking Rom store icon in right corner in file importer or selecting architecture, it will go back to home screen and to Rom store.
- Added note about using X11 instead of VNC in VNC settings when X11 is in use.
- Added opening home folder in other file browser.
- Some changes to drawer.
This commit is contained in:
An Bui 2025-10-05 19:52:05 +07:00
parent 52006c425d
commit cb85f562fa
20 changed files with 520 additions and 465 deletions

View file

@ -10,8 +10,11 @@ import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import androidx.preference.PreferenceManager;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.Toolbar;
@ -28,13 +31,19 @@ import com.vectras.vm.SplashActivity;
import com.vectras.vm.VectrasApp;
import java.util.Locale;
import java.util.Objects;
public class MainSettingsManager extends AppCompatActivity
implements PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
public static final String TAG = "MainSettingsManager";
public static MainSettingsManager activity;
private static Handler mHandler;
public static SharedPreferences sp;
public static int goToXML = -1;
public static boolean isAllowFirstChangeSubtitle = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -47,7 +56,6 @@ public class MainSettingsManager extends AppCompatActivity
sp = PreferenceManager.getDefaultSharedPreferences(activity);
PreferenceFragmentCompat preference = new MainPreferencesFragment();
Intent intent = getIntent();
// add preference settings
getSupportFragmentManager().beginTransaction()
@ -55,18 +63,33 @@ public class MainSettingsManager extends AppCompatActivity
.commit();
// toolbar
Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
Toolbar mToolbar = findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
CollapsingToolbarLayout collapsingToolbarLayout = findViewById(R.id.collapsingToolbarLayout);
if (getIntent().hasExtra("goto")) {
isAllowFirstChangeSubtitle = false;
if (Objects.equals(getIntent().getStringExtra("goto"), "qemu")) {
goToXML = R.xml.qemu;
collapsingToolbarLayout.setSubtitle(getString(R.string.qemu));
}
}
}
@Override
public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) {
public boolean onPreferenceStartFragment(@NonNull PreferenceFragmentCompat caller, Preference pref) {
// Instantiate the new Fragment
final Bundle bundle = pref.getExtras();
final Fragment fragment = Fragment.instantiate(this, pref.getFragment(), bundle);
fragment.setTargetFragment(caller, 0);
assert pref.getFragment() != null;
Fragment fragment = getSupportFragmentManager()
.getFragmentFactory()
.instantiate(getClassLoader(), pref.getFragment());
fragment.setArguments(bundle);
// fragment.setTargetFragment(caller, 0);
// Replace the existing Fragment with the new Fragment
getSupportFragmentManager().beginTransaction()
@ -94,11 +117,13 @@ public class MainSettingsManager extends AppCompatActivity
@Override
public void onResume() {
super.onResume();
CollapsingToolbarLayout collapsingToolbarLayout =
requireActivity().findViewById(R.id.collapsingToolbarLayout);
if (MainSettingsManager.isAllowFirstChangeSubtitle) {
CollapsingToolbarLayout collapsingToolbarLayout =
requireActivity().findViewById(R.id.collapsingToolbarLayout);
if (collapsingToolbarLayout != null) {
collapsingToolbarLayout.setSubtitle(getString(R.string.general));
if (collapsingToolbarLayout != null) {
collapsingToolbarLayout.setSubtitle(getString(R.string.general));
}
}
}
@ -112,14 +137,12 @@ public class MainSettingsManager extends AppCompatActivity
@Override
public void onCreatePreferences(Bundle bundle, String root_key) {
// Load the Preferences from the XML file
setPreferencesFromResource(R.xml.headers_preference, root_key);
setPreferencesFromResource(MainSettingsManager.goToXML == -1 ? R.xml.headers_preference : MainSettingsManager.goToXML, root_key);
MainSettingsManager.goToXML = -1;
}
@Override
public boolean onPreferenceChange(Preference pref, Object newValue) {
if (pref.getKey().equals("app")) {
}
public boolean onPreferenceChange(@NonNull Preference pref, Object newValue) {
return true;
}
@ -162,26 +185,26 @@ public class MainSettingsManager extends AppCompatActivity
languagePref.setOnPreferenceChangeListener(this);
}
SwitchPreferenceCompat switchPreferenceCompat = findPreference("updateVersionPrompt");
assert switchPreferenceCompat != null;
SwitchPreferenceCompat switchJoinBetaChannel = findPreference("checkforupdatesfromthebetachannel");
assert switchJoinBetaChannel != null;
if (!switchPreferenceCompat.isChecked()) {
switchJoinBetaChannel.setEnabled(false);
}
switchPreferenceCompat.setOnPreferenceChangeListener((preference, newValue) -> {
if (!(Boolean) newValue) {
if (switchJoinBetaChannel.isEnabled())
switchJoinBetaChannel.setEnabled(false);
} else {
if (!switchJoinBetaChannel.isEnabled())
switchJoinBetaChannel.setEnabled(true);
}
return true;
});
// SwitchPreferenceCompat switchPreferenceCompat = findPreference("updateVersionPrompt");
// assert switchPreferenceCompat != null;
// SwitchPreferenceCompat switchJoinBetaChannel = findPreference("checkforupdatesfromthebetachannel");
// assert switchJoinBetaChannel != null;
//
// if (!switchPreferenceCompat.isChecked()) {
// switchJoinBetaChannel.setEnabled(false);
// }
//
// switchPreferenceCompat.setOnPreferenceChangeListener((preference, newValue) -> {
// if (!(Boolean) newValue) {
// if (switchJoinBetaChannel.isEnabled())
// switchJoinBetaChannel.setEnabled(false);
// } else {
// if (!switchJoinBetaChannel.isEnabled())
// switchJoinBetaChannel.setEnabled(true);
//
// }
// return true;
// });
}
@ -268,7 +291,7 @@ public class MainSettingsManager extends AppCompatActivity
}
@Override
public boolean onPreferenceChange(Preference pref, Object newValue) {
public boolean onPreferenceChange(@NonNull Preference pref, Object newValue) {
return true;
}
@ -284,9 +307,9 @@ public class MainSettingsManager extends AppCompatActivity
//Preference prefIfType = findPreference("ifType");
//if (getArch(activity).equals("ARM64"))
//if (prefIfType != null) {
//prefIfType.setVisible(false);
//}
//if (prefIfType != null) {
//prefIfType.setVisible(false);
//}
Preference pref = findPreference("vmArch");
if (pref != null) {
@ -359,12 +382,9 @@ public class MainSettingsManager extends AppCompatActivity
}
private void onArch() {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
activity.finish();
startActivity(new Intent(activity, SplashActivity.class));
}
mHandler.postDelayed(() -> {
activity.finish();
startActivity(new Intent(activity, SplashActivity.class));
}, 300);
}
@ -401,7 +421,7 @@ public class MainSettingsManager extends AppCompatActivity
}
@Override
public boolean onPreferenceChange(Preference pref, Object newValue) {
public boolean onPreferenceChange(@NonNull Preference pref, Object newValue) {
return true;
}
@ -442,10 +462,7 @@ public class MainSettingsManager extends AppCompatActivity
}
@Override
public boolean onPreferenceChange(Preference pref, Object newValue) {
if (pref.getKey().equals("app")) {
}
public boolean onPreferenceChange(@NonNull Preference pref, Object newValue) {
return true;
}
@ -490,9 +507,8 @@ public class MainSettingsManager extends AppCompatActivity
public static int getOrientationSetting(Activity activity) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
int orientation = prefs.getInt("orientation", 0);
// UIUtils.log("Getting First time: " + firstTime);
return orientation;
return prefs.getInt("orientation", 0);
}
public static void setOrientationSetting(Activity activity, int orientation) {
@ -571,42 +587,39 @@ public class MainSettingsManager extends AppCompatActivity
public static String getLastDir(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String imagesDir = prefs.getString("lastDir", null);
return imagesDir;
return prefs.getString("lastDir", null);
}
public static void setLastDir(Context context, String imagesPath) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("lastDir", imagesPath);
edit.commit();
edit.apply();
}
public static String getImagesDir(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String imagesDir = prefs.getString("imagesDir", null);
return imagesDir;
return prefs.getString("imagesDir", null);
}
public static void setImagesDir(Context context, String imagesPath) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("imagesDir", imagesPath);
edit.commit();
edit.apply();
}
public static String getExportDir(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String imagesDir = prefs.getString("exportDir", null);
return imagesDir;
return prefs.getString("exportDir", null);
}
public static void setExportDir(Context context, String imagesPath) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("exportDir", imagesPath);
edit.commit();
edit.apply();
}
@ -626,28 +639,26 @@ public class MainSettingsManager extends AppCompatActivity
public static int getExitCode(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
int exitCode = prefs.getInt("exitCode", 1);
return exitCode;
return prefs.getInt("exitCode", 1);
}
public static void setExitCode(Context context, int exitCode) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putInt("exitCode", exitCode);
edit.commit();
edit.apply();
}
public static String getControlMode(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String controlMode = prefs.getString("controlMode", "D");
return controlMode;
return prefs.getString("controlMode", "D");
}
public static void setControlMode(Context context, String controlMode) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("controlMode", controlMode);
edit.commit();
edit.apply();
}
@ -655,7 +666,7 @@ public class MainSettingsManager extends AppCompatActivity
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean("modeNight", nightMode);
edit.commit();
edit.apply();
}
public static Boolean getModeNight(Context context) {
@ -812,29 +823,30 @@ public class MainSettingsManager extends AppCompatActivity
PackageInfo pInfo = null;
try {
pInfo = activity.getPackageManager().getPackageInfo(activity.getClass().getPackage().getName(),
pInfo = activity.getPackageManager().getPackageInfo(Objects.requireNonNull(activity.getClass().getPackage()).getName(),
PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
Log.e(TAG, "isFirstLaunch", e);
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
boolean firstTime = prefs.getBoolean("firstTime" + pInfo.versionName, true);
return firstTime;
assert pInfo != null;
return prefs.getBoolean("firstTime" + pInfo.versionName, true);
}
public static void setFirstLaunch(Activity activity) {
PackageInfo pInfo = null;
try {
pInfo = activity.getPackageManager().getPackageInfo(activity.getClass().getPackage().getName(),
pInfo = activity.getPackageManager().getPackageInfo(Objects.requireNonNull(activity.getClass().getPackage()).getName(),
PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
Log.e(TAG, "setFirstLaunch", e);
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
SharedPreferences.Editor edit = prefs.edit();
assert pInfo != null;
edit.putBoolean("firstTime" + pInfo.versionName, false);
edit.commit();
edit.apply();
}
@ -870,7 +882,7 @@ public class MainSettingsManager extends AppCompatActivity
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean("setUpWithManualSetupBefore", _boolean);
edit.commit();
edit.apply();
}
public static Boolean getsetUpWithManualSetupBefore(Context context) {
@ -882,7 +894,7 @@ public class MainSettingsManager extends AppCompatActivity
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putInt("SelectedMirror", _int);
edit.commit();
edit.apply();
}
public static int getSelectedMirror(Context context) {
@ -894,7 +906,7 @@ public class MainSettingsManager extends AppCompatActivity
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean("dontShowAgainJoinBetaUpdateChannelDialog", _boolean);
edit.commit();
edit.apply();
}
public static Boolean getDontShowAgainJoinBetaUpdateChannelDialog(Context context) {
@ -906,7 +918,7 @@ public class MainSettingsManager extends AppCompatActivity
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean("useDefaultBios", _boolean);
edit.commit();
edit.apply();
}
public static Boolean getuseDefaultBios(Context context) {
@ -918,7 +930,7 @@ public class MainSettingsManager extends AppCompatActivity
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean("useUEFI", _boolean);
edit.commit();
edit.apply();
}
public static Boolean getuseUEFI(Context context) {
@ -930,7 +942,7 @@ public class MainSettingsManager extends AppCompatActivity
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("skipVersion", version);
edit.commit();
edit.apply();
}
public static String getSkipVersion(Context context) {
@ -942,7 +954,7 @@ public class MainSettingsManager extends AppCompatActivity
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putInt("vncScaleMode", mode);
edit.commit();
edit.apply();
}
public static int getVNCScaleMode(Context context) {
@ -954,7 +966,7 @@ public class MainSettingsManager extends AppCompatActivity
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean("forceRefeshVNCDisplay", _boolean);
edit.commit();
edit.apply();
}
public static Boolean getForceRefeshVNCDisplay(Context context) {

View file

@ -73,6 +73,7 @@ public class AppConfig {
public static String downloadsFolder = maindirpath + "Downloads/";
public static String romsdatajson = maindirpath + "roms-data.json";
public static String vmFolder = maindirpath + "roms/";
public static String importedDriveFolder = maindirpath + "drive/";
public static String pendingCommand = "";
public static String neededPkgs = "aria2 tar dwm xfce4-terminal libslirp libslirp-dev pulseaudio-dev glib-dev pixman-dev zlib-dev spice-dev" +

View file

@ -56,8 +56,8 @@ public class CustomRomActivity extends AppCompatActivity {
boolean iseditparams = false;
public String previousName = "";
public boolean addromnowdone = false;
public static String vmID = VMManager.idGenerator();
public int port = VMManager.startRandomPort();
private String vmID = VMManager.idGenerator();
private int port = VMManager.startRandomPort();
private boolean created = false;
private String thumbnailPath = "";
private final Timer _timer = new Timer();
@ -114,6 +114,7 @@ public class CustomRomActivity extends AppCompatActivity {
binding.driveField.setEndIconOnClickListener(v -> {
if (Objects.requireNonNull(binding.drive.getText()).toString().isEmpty()) {
CreateImageDialogFragment dialogFragment = new CreateImageDialogFragment();
dialogFragment.folder = AppConfig.vmFolder + vmID + "/";
dialogFragment.customRom = true;
dialogFragment.filename = Objects.requireNonNull(binding.title.getText()).toString();
dialogFragment.drive = binding.drive;
@ -244,7 +245,7 @@ public class CustomRomActivity extends AppCompatActivity {
thumbnailPath = current.itemIcon;
vmID = getIntent().getStringExtra("VMID");
if (vmID != null && vmID.isEmpty()) {
if (vmID == null || vmID.isEmpty()) {
vmID = VMManager.idGenerator();
}

View file

@ -30,7 +30,7 @@ public class CreateImageDialogFragment extends DialogFragment {
public boolean customRom = false;
public String folder = AppConfig.vmFolder + CustomRomActivity.vmID + "/";
public String folder = AppConfig.maindirpath;
public String filename = "disk";
public TextInputEditText drive;
public TextInputLayout driveLayout;

View file

@ -16,6 +16,7 @@ import androidx.appcompat.app.AppCompatActivity;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.databinding.ActivitySetArchBinding;
import com.vectras.vm.home.HomeActivity;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.UIUtils;
@ -50,9 +51,7 @@ public class SetArchActivity extends AppCompatActivity implements View.OnClickLi
binding.toolbar.setOnMenuItemClickListener(item -> {
if (item.getItemId() == R.id.roms_store) {
Intent intent = new Intent(this, RomsManagerActivity.class);
startActivity(intent);
HomeActivity.isOpenRomStore = true;
finish();
return true;
}

View file

@ -1,32 +1,28 @@
package com.vectras.vm.home;
import static android.content.Intent.ACTION_OPEN_DOCUMENT;
import static android.content.Intent.ACTION_VIEW;
import static android.os.Build.VERSION.SDK_INT;
import static com.vectras.vm.VectrasApp.getApp;
import static com.vectras.vm.utils.UIUtils.UIAlert;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.StrictMode;
import android.provider.DocumentsContract;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.activity.EdgeToEdge;
import androidx.activity.OnBackPressedCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog;
@ -39,6 +35,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.color.MaterialColors;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.gson.Gson;
import com.termux.app.TermuxActivity;
import com.vectras.qemu.Config;
@ -46,7 +43,6 @@ import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.AboutActivity;
import com.vectras.vm.AppConfig;
import com.vectras.vm.CustomRomActivity;
import com.vectras.vm.DataExplorerActivity;
import com.vectras.vm.Minitools;
import com.vectras.vm.R;
import com.vectras.vm.RequestNetwork;
@ -81,24 +77,23 @@ import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
public class HomeActivity extends AppCompatActivity implements RomStoreFragment.RomStoreCallToHomeListener, VmsFragment.VmsCallToHomeListener {
public static String curRomName;
private final String TAG = "HomeActivity";
public static boolean isActivate = false;
public static boolean isOpenRomStore = false;
private final ExecutorService executor = Executors.newSingleThreadExecutor();
ActivityHomeBinding binding;
ActivityHomeContentBinding bindingContent;
private RomStoreHomeAdapterSearch adapterRomStoreSearch;
@ -210,13 +205,10 @@ public class HomeActivity extends AppCompatActivity implements RomStoreFragment.
bindingContent.searchbar.setEnabled(false);
}
if (selectedFragment != null) {
getSupportFragmentManager().beginTransaction()
.replace(bindingContent.containerView.getId(), selectedFragment)
.commit();
return true;
}
return false;
getSupportFragmentManager().beginTransaction()
.replace(bindingContent.containerView.getId(), selectedFragment)
.commit();
return true;
});
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@ -308,178 +300,76 @@ public class HomeActivity extends AppCompatActivity implements RomStoreFragment.
DisplaySystem.reLaunchVNC(this);
PendingCommand.runNow(this);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent ReturnedIntent) {
super.onActivityResult(requestCode, resultCode, ReturnedIntent);
if (requestCode == 1004 && resultCode == RESULT_OK) {
Uri content_describer = ReturnedIntent.getData();
File selectedFilePath = new File(getPath(content_describer));
ProgressBar loading = findViewById(R.id.loading);
if (selectedFilePath.toString().endsWith(".iso")) {
loading.setVisibility(View.VISIBLE);
new Thread(() -> {
FileInputStream File;
try {
assert content_describer != null;
File = (FileInputStream) getContentResolver().openInputStream(content_describer);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
try {
try {
try (OutputStream out = new FileOutputStream(AppConfig.maindirpath + "/drive.iso")) {
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while (true) {
assert File != null;
if (!((len = File.read(buf)) > 0)) break;
out.write(buf, 0, len);
}
}
} finally {
Runnable runnable = () -> loading.setVisibility(View.GONE);
runOnUiThread(runnable);
assert File != null;
File.close();
}
} catch (IOException e) {
Runnable runnable = () -> {
loading.setVisibility(View.GONE);
UIAlert(this, e.toString(), "error");
};
runOnUiThread(runnable);
}
}).start();
} else
UIAlert(this, "please select iso file", "INVALID FILE");
} else if (requestCode == 1005 && resultCode == RESULT_OK) {
Uri content_describer = ReturnedIntent.getData();
ProgressBar loading = findViewById(R.id.loading);
loading.setVisibility(View.VISIBLE);
new Thread(() -> {
FileInputStream File;
try {
assert content_describer != null;
File = (FileInputStream) getContentResolver().openInputStream(content_describer);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
try {
try {
try (OutputStream out = new FileOutputStream(AppConfig.maindirpath + "/hdd1.qcow2")) {
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while (true) {
assert File != null;
if (!((len = File.read(buf)) > 0)) break;
out.write(buf, 0, len);
}
}
} finally {
Runnable runnable = () -> loading.setVisibility(View.GONE);
runOnUiThread(runnable);
assert File != null;
File.close();
}
} catch (IOException e) {
Runnable runnable = () -> {
loading.setVisibility(View.GONE);
UIAlert(this, e.toString(), "error");
};
runOnUiThread(runnable);
}
}).start();
} else if (requestCode == 1006 && resultCode == RESULT_OK) {
Uri content_describer = ReturnedIntent.getData();
ProgressBar loading = findViewById(R.id.loading);
loading.setVisibility(View.VISIBLE);
new Thread(() -> {
FileInputStream File;
try {
assert content_describer != null;
File = (FileInputStream) getContentResolver().openInputStream(content_describer);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
try {
try {
try (OutputStream out = new FileOutputStream(AppConfig.maindirpath + "/hdd2.qcow2")) {
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while (true) {
assert File != null;
if (!((len = File.read(buf)) > 0)) break;
out.write(buf, 0, len);
}
}
} finally {
Runnable runnable = () -> loading.setVisibility(View.GONE);
runOnUiThread(runnable);
assert File != null;
File.close();
}
} catch (IOException e) {
Runnable runnable = () -> {
loading.setVisibility(View.GONE);
UIAlert(this, e.toString(), "error");
};
runOnUiThread(runnable);
}
}).start();
} else if (requestCode == 122 && resultCode == RESULT_OK) {
Uri content_describer = ReturnedIntent.getData();
File selectedFilePath = new File(getPath(content_describer));
ProgressBar loading = findViewById(R.id.loading);
loading.setVisibility(View.VISIBLE);
new Thread(() -> {
FileInputStream File;
try {
assert content_describer != null;
File = (FileInputStream) getContentResolver().openInputStream(content_describer);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
try {
try {
File romDir = new File(AppConfig.maindirpath + curRomName + "/");
if (!romDir.exists()) {
if(!romDir.mkdirs()) return;
}
try (OutputStream out = new FileOutputStream(AppConfig.maindirpath + curRomName + "/" + "drv1-" + selectedFilePath.getName())) {
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while (true) {
assert File != null;
if (!((len = File.read(buf)) > 0)) break;
out.write(buf, 0, len);
}
}
} finally {
Runnable runnable = () -> loading.setVisibility(View.GONE);
runOnUiThread(runnable);
assert File != null;
File.close();
}
} catch (IOException e) {
Runnable runnable = () -> {
loading.setVisibility(View.GONE);
UIAlert(this, e.toString(), "error");
};
runOnUiThread(runnable);
}
}).start();
if (isOpenRomStore) {
isOpenRomStore = false;
bindingContent.bottomNavigation.setSelectedItemId(R.id.item_romstore);
}
}
public String getPath(Uri uri) {
return FileUtils.getPath(this, uri);
}
private final ActivityResultLauncher<String> isoPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri == null) return;
if (VMManager.isAISOFile(FileUtils.getFileNameFromUri(this, uri))) {
importFile(uri, AppConfig.importedDriveFolder + "/drive.iso");
} else {
DialogUtils.twoDialog(this,
getString(R.string.problem_has_been_detected),
getString(R.string.file_format_is_not_supported),
getResources().getString(R.string.continuetext),
getResources().getString(R.string.cancel),
true,
R.drawable.album_24px,
true,
() -> importFile(uri, AppConfig.importedDriveFolder + "/drive.iso"),
null,
null);
}
});
private final ActivityResultLauncher<String> hdd1Picker =
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri == null) return;
if (VMManager.isADiskFile(FileUtils.getFileNameFromUri(this, uri))) {
importFile(uri, AppConfig.importedDriveFolder + "/hdd1.qcow2");
} else {
DialogUtils.twoDialog(this,
getString(R.string.problem_has_been_detected),
getString(R.string.file_format_is_not_supported),
getResources().getString(R.string.continuetext),
getResources().getString(R.string.cancel),
true,
R.drawable.hard_drive_24px,
true,
() -> importFile(uri, AppConfig.importedDriveFolder + "/hdd1.qcow2"),
null,
null);
}
});
private final ActivityResultLauncher<String> hdd2Picker =
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri == null) return;
if (VMManager.isADiskFile(FileUtils.getFileNameFromUri(this, uri))) {
importFile(uri, AppConfig.importedDriveFolder + "/hdd2.qcow2");
} else {
DialogUtils.twoDialog(this,
getString(R.string.problem_has_been_detected),
getString(R.string.file_format_is_not_supported),
getResources().getString(R.string.continuetext),
getResources().getString(R.string.cancel),
true,
R.drawable.hard_drive_24px,
true,
() -> importFile(uri, AppConfig.importedDriveFolder + "/hdd2.qcow2"),
null,
null);
}
});
private void setupDrawer() {
binding.drawerLayout.setScrimColor(Color.parseColor("#40000000")); //25%
@ -506,157 +396,82 @@ public class HomeActivity extends AppCompatActivity implements RomStoreFragment.
w.setData(Uri.parse(tw));
startActivity(w);
} else if (id == R.id.navigation_item_import_iso) {
if (new File(AppConfig.maindirpath + "/drive.iso").exists()) {
AlertDialog ad;
ad = new AlertDialog.Builder(this, R.style.MainDialogTheme).create();
ad.setTitle("REPLACE ISO");
ad.setMessage("there is iso imported you want to replace it?");
ad.setButton(Dialog.BUTTON_POSITIVE, "REPLACE", (dialog, which) -> {
Intent intent = new Intent(ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
// Optionally, specify a URI for the file that should appear in the
// system file picker when it loads.
if (SDK_INT >= Build.VERSION_CODES.O) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOWNLOADS);
}
startActivityForResult(intent, 1004);
});
ad.setButton(Dialog.BUTTON_NEGATIVE, "REMOVE", (dialog, which) -> {
File isoFile = new File(AppConfig.maindirpath + "/drive.iso");
try {
if(!isoFile.delete()) Log.e(TAG, "Delete drive.iso failed!");
} catch (Exception e) {
Log.e(TAG, "Delete drive.iso: ", e);
}
});
ad.show();
if (new File(AppConfig.importedDriveFolder + "/drive.iso").exists()) {
DialogUtils.threeDialog(
this,
"Replace iso",
"There is iso imported you want to replace it?",
getString(R.string.replace),
getString(R.string.cancel),
getString(R.string.remove),
true,
R.drawable.album_24px,
true,
() -> isoPicker.launch("*/*"),
null,
() -> {
try {
File isoFile = new File(AppConfig.importedDriveFolder + "/drive.iso");
DialogUtils.fileDeletionResult(this, isoFile.delete());
} catch (Exception e) {
DialogUtils.fileDeletionResult(this, false);
}
},
null);
} else {
Intent intent = new Intent(ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
// Optionally, specify a URI for the file that should appear in the
// system file picker when it loads.
if (SDK_INT >= Build.VERSION_CODES.O) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOWNLOADS);
}
startActivityForResult(intent, 1004);
isoPicker.launch("*/*");
}
} else if (id == R.id.navigation_item_hdd1) {
if (new File(AppConfig.maindirpath + "/hdd1.qcow2").exists()) {
AlertDialog ad;
ad = new AlertDialog.Builder(this, R.style.MainDialogTheme).create();
ad.setTitle("REPLACE HDD1");
ad.setMessage("there is hdd1 imported you want to replace it?");
ad.setButton(Dialog.BUTTON_POSITIVE, "REPLACE", (dialog, which) -> {
Intent intent = new Intent(ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
// Optionally, specify a URI for the file that should appear in the
// system file picker when it loads.
if (SDK_INT >= Build.VERSION_CODES.O) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOWNLOADS);
}
startActivityForResult(intent, 1006);
});
ad.setButton(Dialog.BUTTON_NEGATIVE, "REMOVE", (dialog, which) -> {
File isoFile = new File(AppConfig.maindirpath + "/hdd1.qcow2");
try {
if(!isoFile.delete()) Log.e(TAG, "Delete hdd1.qcow2 failed!");
} catch (Exception e) {
Log.e(TAG, "Delete hdd1.qcow2: ", e);
}
});
ad.setButton(Dialog.BUTTON_NEUTRAL, "SHARE", (dialog, which) -> {
Intent intentShareFile = new Intent(Intent.ACTION_SEND);
File fileWithinMyDir = new File(AppConfig.maindirpath + "/hdd1.qcow2");
if (fileWithinMyDir.exists()) {
intentShareFile.setType("*/*");
intentShareFile.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + AppConfig.maindirpath + "/hdd1.qcow2"));
intentShareFile.putExtra(Intent.EXTRA_SUBJECT,
"Sharing File...");
intentShareFile.putExtra(Intent.EXTRA_TEXT, "Sharing File...");
startActivity(Intent.createChooser(intentShareFile, "Share File"));
}
});
ad.show();
if (new File(AppConfig.importedDriveFolder + "/hdd1.qcow2").exists()) {
DialogUtils.threeDialog(
this,
"Replace HDD1",
"There is HDD1 imported you want to replace it?",
getString(R.string.replace),
getString(R.string.cancel),
getString(R.string.remove),
true,
R.drawable.hard_drive_24px,
true,
() -> hdd1Picker.launch("*/*"),
null,
() -> {
try {
File hdd1File = new File(AppConfig.importedDriveFolder + "/hdd1.qcow2");
DialogUtils.fileDeletionResult(this, hdd1File.delete());
} catch (Exception e) {
DialogUtils.fileDeletionResult(this, false);
}
},
null);
} else {
Intent intent = new Intent(ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
// Optionally, specify a URI for the file that should appear in the
// system file picker when it loads.
if (SDK_INT >= Build.VERSION_CODES.O) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOWNLOADS);
}
startActivityForResult(intent, 1005);
hdd1Picker.launch("*/*");
}
} else if (id == R.id.navigation_item_hdd2) {
if (new File(AppConfig.maindirpath + "/hdd2.qcow2").exists()) {
AlertDialog ad;
ad = new AlertDialog.Builder(this, R.style.MainDialogTheme).create();
ad.setTitle("REPLACE HDD2");
ad.setMessage("there is hdd2 imported you want to replace it?");
ad.setButton(Dialog.BUTTON_POSITIVE, "REPLACE", (dialog, which) -> {
Intent intent = new Intent(ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
// Optionally, specify a URI for the file that should appear in the
// system file picker when it loads.
if (SDK_INT >= Build.VERSION_CODES.O) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOWNLOADS);
}
startActivityForResult(intent, 1006);
});
ad.setButton(Dialog.BUTTON_NEGATIVE, "REMOVE", (dialog, which) -> {
File isoFile = new File(AppConfig.maindirpath + "/hdd2.qcow2");
try {
if(!isoFile.delete()) Log.e(TAG, "Delete hdd2.qcow2 failed!");
} catch (Exception e) {
Log.e(TAG, "Delete hdd2.qcow2: ", e);
}
});
ad.setButton(Dialog.BUTTON_NEUTRAL, "SHARE", (dialog, which) -> {
Intent intentShareFile = new Intent(Intent.ACTION_SEND);
File fileWithinMyDir = new File(AppConfig.maindirpath + "/hdd2.qcow2");
if (fileWithinMyDir.exists()) {
intentShareFile.setType("*/*");
intentShareFile.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + AppConfig.maindirpath + "/hdd2.qcow2"));
intentShareFile.putExtra(Intent.EXTRA_SUBJECT,
"Sharing File...");
intentShareFile.putExtra(Intent.EXTRA_TEXT, "Sharing File...");
startActivity(Intent.createChooser(intentShareFile, "Share File"));
}
});
ad.show();
if (new File(AppConfig.importedDriveFolder + "/hdd2.qcow2").exists()) {
DialogUtils.threeDialog(
this,
"Replace HDD2",
"There is HDD2 imported you want to replace it?",
getString(R.string.replace),
getString(R.string.cancel),
getString(R.string.remove),
true,
R.drawable.hard_drive_24px,
true,
() -> hdd2Picker.launch("*/*"),
null,
() -> {
try {
File hdd1File = new File(AppConfig.importedDriveFolder + "/hdd2.qcow2");
DialogUtils.fileDeletionResult(this, hdd1File.delete());
} catch (Exception e) {
DialogUtils.fileDeletionResult(this, false);
}
},
null);
} else {
Intent intent = new Intent(ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
// Optionally, specify a URI for the file that should appear in the
// system file picker when it loads.
if (SDK_INT >= Build.VERSION_CODES.O) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOWNLOADS);
}
startActivityForResult(intent, 1006);
hdd2Picker.launch("*/*");
}
} else if (id == R.id.navigation_item_desktop) {
DisplaySystem.launchX11(this, true);
@ -714,7 +529,8 @@ public class HomeActivity extends AppCompatActivity implements RomStoreFragment.
} else if (id == R.id.navigation_item_store) {
startActivity(new Intent(this, StoreActivity.class));
} else if (id == R.id.navigation_data_explorer) {
startActivity(new Intent(this, DataExplorerActivity.class));
// startActivity(new Intent(this, DataExplorerActivity.class));
FileUtils.openFolder(this, AppConfig.maindirpath);
} else if (id == R.id.navigation_item_donate) {
String tw = "https://www.patreon.com/VectrasTeam";
Intent w = new Intent(ACTION_VIEW);
@ -803,7 +619,7 @@ public class HomeActivity extends AppCompatActivity implements RomStoreFragment.
}
};
requestNetwork.startRequestNetwork(RequestNetworkController.GET,AppConfig.updateJson,"maincheckupdate",requestNetworkListener);
requestNetwork.startRequestNetwork(RequestNetworkController.GET, AppConfig.updateJson, "maincheckupdate", requestNetworkListener);
}
@SuppressLint("NotifyDataSetChanged")
@ -845,4 +661,42 @@ public class HomeActivity extends AppCompatActivity implements RomStoreFragment.
adapterRomStoreSearch.notifyDataSetChanged();
}
private void importFile(Uri uri, String copyTo) {
if (uri == null) return;
View progressView = LayoutInflater.from(this).inflate(R.layout.dialog_progress_style, null);
TextView progress_text = progressView.findViewById(R.id.progress_text);
progress_text.setText(getString(R.string.importing_file));
AlertDialog progressDialog = new MaterialAlertDialogBuilder(this, R.style.CenteredDialogTheme)
.setView(progressView)
.setCancelable(false)
.create();
progressDialog.show();
AtomicBoolean isCompleted = new AtomicBoolean(false);
executor.execute(() -> {
try {
FileUtils.copyFileFromUri(this, uri, copyTo);
isCompleted.set(true);
} catch (Exception e) {
isCompleted.set(false);
} finally {
runOnUiThread(() -> {
progressDialog.dismiss();
DialogUtils.oneDialog(
this,
isCompleted.get() ? getString(R.string.imported) : getString(R.string.oops),
isCompleted.get() ? getString(R.string.file_imported_successfully) : getString(R.string.file_import_failed),
getString(R.string.ok),
true,
isCompleted.get() ? R.drawable.check_24px : R.drawable.error_96px,
true,
null,
null
);
});
}
});
}
}

View file

@ -27,6 +27,7 @@ import com.vectras.vm.VMManager;
import com.vectras.vm.logger.VectrasStatus;
import com.vectras.vm.settings.ExternalVNCSettingsActivity;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.NetworkUtils;
import com.vectras.vm.utils.ServiceUtils;
@ -59,6 +60,25 @@ public class HomeStartVM {
return;
}
if (MainSettingsManager.getSharedFolder(activity)
&& !MainSettingsManager.getArch(activity).equals("I386")
&& FileUtils.getFolderSize(FileUtils.getExternalFilesDirectory(activity).getPath() + "/SharedFolder") / Math.pow(10, 2) > 516) {
DialogUtils.twoDialog(
activity,
activity.getString(R.string.problem_has_been_detected),
activity.getString(R.string.shared_folder_is_too_large_content),
activity.getString(R.string.open_shared_folder),
activity.getString(R.string.close),
true,
R.drawable.warning_48px,
true,
() -> FileUtils.openFolder(activity, FileUtils.getExternalFilesDirectory(activity).getPath() + "/SharedFolder"),
null,
null
);
return;
}
VMManager.lastQemuCommand = env;
if (VMManager.isThisVMRunning(activity, itemExtra, itemPath)) {

View file

@ -2,6 +2,7 @@ package com.vectras.vm.settings;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
@ -25,10 +26,16 @@ public class VNCSettingsActivity extends AppCompatActivity {
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
binding.toolbar.setNavigationOnClickListener(view -> onBackPressed());
binding.toolbar.setNavigationOnClickListener(view -> finish());
initialize();
}
@Override
public void onResume() {
super.onResume();
binding.cvNotusingvnc.setVisibility(MainSettingsManager.getVmUi(this).equals("VNC") ? View.GONE : View.VISIBLE);
}
private void initialize() {
binding.swForcerefesh.setOnCheckedChangeListener((buttonView, isChecked) -> MainSettingsManager.setForceRefeshVNCDisplay(this, isChecked));
binding.lnForcerefesh.setOnClickListener(v -> binding.swForcerefesh.toggle());
@ -38,5 +45,12 @@ public class VNCSettingsActivity extends AppCompatActivity {
binding.swForcerefesh.setChecked(MainSettingsManager.getForceRefeshVNCDisplay(this));
binding.swExternal.setChecked(MainSettingsManager.getVncExternal(this));
binding.lnNotusingvnc.setOnClickListener(v -> {
Intent intent = new Intent();
intent.putExtra("goto", "qemu");
intent.setClass(this, MainSettingsManager.class);
startActivity(intent);
});
}
}

View file

@ -60,6 +60,7 @@ public class DialogUtils {
});
dialog.show();
}
public static void twoDialog(Activity _context, String _title, String _message, String _textPositiveButton, String _textNegativeButton, boolean _isicon, int _iconid, boolean _cancel, Runnable _onPositive, Runnable _onNegative, Runnable _onDismiss) {
View buttonsView = LayoutInflater.from(_context).inflate(R.layout.dialog_layout, null);
@ -111,7 +112,7 @@ public class DialogUtils {
dialog.show();
}
public static void threeDialog(Activity _context, String _title, String _message, String _textPositiveButton, String _textNegativeButton, String _textNeutralButton ,boolean _isicon, int _iconid, boolean _cancel, Runnable _onPositive, Runnable _onNegative, Runnable _onNeutral, Runnable _onDismiss) {
public static void threeDialog(Activity _context, String _title, String _message, String _textPositiveButton, String _textNegativeButton, String _textNeutralButton, boolean _isicon, int _iconid, boolean _cancel, Runnable _onPositive, Runnable _onNegative, Runnable _onNeutral, Runnable _onDismiss) {
View buttonsView = LayoutInflater.from(_context).inflate(R.layout.dialog_layout, null);
AlertDialog dialog = new AlertDialog.Builder(_context).create();
@ -191,4 +192,32 @@ public class DialogUtils {
}, null);
}
}
public static void fileDeletionResult(Activity activity, boolean isCompleted) {
if (isCompleted) {
DialogUtils.oneDialog(
activity,
activity.getString(R.string.done),
activity.getString(R.string.file_deleted),
activity.getString(R.string.ok),
true,
R.drawable.check_24px,
true,
null,
null
);
} else {
DialogUtils.oneDialog(
activity,
activity.getString(R.string.oops),
activity.getString(R.string.delete_file_failed_content),
activity.getString(R.string.ok),
true,
R.drawable.error_96px,
true,
null,
null
);
}
}
}

View file

@ -3,6 +3,7 @@ package com.vectras.vm.utils;
import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
@ -31,6 +32,7 @@ import android.os.Looper;
import android.os.ParcelFileDescriptor;
import androidx.annotation.NonNull;
import androidx.core.content.FileProvider;
import com.vectras.vm.R;
@ -49,6 +51,8 @@ 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");
@ -793,7 +797,7 @@ public class FileUtils {
}
}
public static int getFolderSize(String _path) {
public static long getFolderSize(String _path) {
try {
File file;
file = new File(_path);
@ -822,7 +826,7 @@ public class FileUtils {
}
}
}
return (int) result;
return result;
} catch (Exception _e) {
return 0;
}
@ -832,19 +836,14 @@ public class FileUtils {
String filePath = null;
if ("content".equalsIgnoreCase(uri.getScheme())) {
String[] projection = {MediaStore.Files.FileColumns.DATA};
Cursor cursor = null;
try {
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) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
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);
}
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
filePath = uri.getPath();
}
@ -868,4 +867,53 @@ public class FileUtils {
}
return true;
}
public static void openFolder(Activity activity, String folderPath) {
File folder = new File(folderPath);
if (!folder.exists() || !folder.isDirectory()) {
DialogUtils.oneDialog(
activity,
activity.getString(R.string.oops),
activity.getString(R.string.directory_does_not_exist),
activity.getString(R.string.ok),
true,
R.drawable.error_96px,
true,
null,
null
);
Log.e(TAG, "openFolder: Folder not found!");
return;
}
Uri uri = FileProvider.getUriForFile(
activity,
activity.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);
try {
activity.startActivity(intent);
} catch (Exception e) {
DialogUtils.oneDialog(
activity,
activity.getString(R.string.oops),
activity.getString(R.string.there_is_no_app_to_perform_this_action),
activity.getString(R.string.ok),
true,
R.drawable.error_96px,
true,
null,
null
);
Log.e(TAG, "openFolder: " + e.getMessage());
}
}
}