From 076d3d3479361c2defd554beed358d37e1cd4e8b Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 24 Oct 2020 16:03:14 +1000 Subject: [PATCH] Android: Add Start File to main activity menu --- .../github/stenzek/duckstation/FileUtil.java | 38 +++++++++- .../stenzek/duckstation/MainActivity.java | 70 +++++++++++++++---- android/app/src/main/res/menu/menu_main.xml | 3 + 3 files changed, 98 insertions(+), 13 deletions(-) diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/FileUtil.java b/android/app/src/main/java/com/github/stenzek/duckstation/FileUtil.java index 5f1a098c6..853939c19 100644 --- a/android/app/src/main/java/com/github/stenzek/duckstation/FileUtil.java +++ b/android/app/src/main/java/com/github/stenzek/duckstation/FileUtil.java @@ -40,7 +40,6 @@ public final class FileUtil { } else return volumePath; } - @SuppressLint("ObsoleteSdkInt") private static String getVolumePath(final String volumeId, Context context) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return null; @@ -91,4 +90,41 @@ public final class FileUtil { if ((split.length >= 2) && (split[1] != null)) return split[1]; else return File.separator; } + + @Nullable + public static String getFullPathFromUri(@Nullable final Uri treeUri, Context con) { + if (treeUri == null) return null; + String volumePath = getVolumePath(getVolumeIdFromUri(treeUri), con); + if (volumePath == null) return File.separator; + if (volumePath.endsWith(File.separator)) + volumePath = volumePath.substring(0, volumePath.length() - 1); + + String documentPath = getDocumentPathFromUri(treeUri); + if (documentPath.endsWith(File.separator)) + documentPath = documentPath.substring(0, documentPath.length() - 1); + + if (documentPath.length() > 0) { + if (documentPath.startsWith(File.separator)) + return volumePath + documentPath; + else + return volumePath + File.separator + documentPath; + } else return volumePath; + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + private static String getVolumeIdFromUri(final Uri treeUri) { + final String docId = DocumentsContract.getDocumentId(treeUri); + final String[] split = docId.split(":"); + if (split.length > 0) return split[0]; + else return null; + } + + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + private static String getDocumentPathFromUri(final Uri treeUri) { + final String docId = DocumentsContract.getDocumentId(treeUri); + final String[] split = docId.split(":"); + if ((split.length >= 2) && (split[1] != null)) return split[1]; + else return File.separator; + } } \ No newline at end of file diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/MainActivity.java b/android/app/src/main/java/com/github/stenzek/duckstation/MainActivity.java index ce4324658..cb572ec17 100644 --- a/android/app/src/main/java/com/github/stenzek/duckstation/MainActivity.java +++ b/android/app/src/main/java/com/github/stenzek/duckstation/MainActivity.java @@ -49,6 +49,7 @@ public class MainActivity extends AppCompatActivity { private static final int REQUEST_EXTERNAL_STORAGE_PERMISSIONS = 1; private static final int REQUEST_ADD_DIRECTORY_TO_GAME_LIST = 2; private static final int REQUEST_IMPORT_BIOS_IMAGE = 3; + private static final int REQUEST_START_FILE = 4; private GameList mGameList; private ListView mGameListView; @@ -160,6 +161,8 @@ public class MainActivity extends AppCompatActivity { startEmulation(null, true); } else if (id == R.id.action_start_bios) { startEmulation(null, false); + } else if (id == R.id.action_start_file) { + startStartFile(); } else if (id == R.id.action_add_game_directory) { startAddGameDirectory(); } else if (id == R.id.action_scan_for_new_games) { @@ -177,6 +180,40 @@ public class MainActivity extends AppCompatActivity { return super.onOptionsItemSelected(item); } + private String getPathFromUri(Uri uri) { + String path = FileUtil.getFullPathFromUri(uri, this); + if (path.length() < 5) { + new AlertDialog.Builder(this) + .setTitle("Error") + .setMessage("Failed to get path for the selected file. Please make sure the file is in internal/external storage.\n\n" + + "Tap the overflow button in the directory selector.\nSelect \"Show Internal Storage\".\n" + + "Tap the menu button and select your device name or SD card.") + .setPositiveButton("OK", (dialog, button) -> {}) + .create() + .show(); + return null; + } + + return path; + } + + private String getPathFromTreeUri(Uri treeUri) { + String path = FileUtil.getFullPathFromTreeUri(treeUri, this); + if (path.length() < 5) { + new AlertDialog.Builder(this) + .setTitle("Error") + .setMessage("Failed to get path for the selected directory. Please make sure the directory is in internal/external storage.\n\n" + + "Tap the overflow button in the directory selector.\nSelect \"Show Internal Storage\".\n" + + "Tap the menu button and select your device name or SD card.") + .setPositiveButton("OK", (dialog, button) -> {}) + .create() + .show(); + return null; + } + + return path; + } + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); @@ -186,19 +223,9 @@ public class MainActivity extends AppCompatActivity { if (resultCode != RESULT_OK) return; - Uri treeUri = data.getData(); - String path = FileUtil.getFullPathFromTreeUri(treeUri, this); - if (path.length() < 5) { - new AlertDialog.Builder(this) - .setTitle("Error") - .setMessage("Failed to get path for the selected directory. Please make sure the directory is in internal/external storage.\n\n" + - "Tap the overflow button in the directory selector.\nSelect \"Show Internal Storage\".\n" + - "Tap the menu button and select your device name or SD card.") - .setPositiveButton("OK", (dialog, button) -> {}) - .create() - .show(); + String path = getPathFromTreeUri(data.getData()); + if (path == null) return; - } SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); Set currentValues = prefs.getStringSet("GameList/RecursivePaths", null); @@ -221,6 +248,18 @@ public class MainActivity extends AppCompatActivity { onImportBIOSImageResult(data.getData()); } break; + + case REQUEST_START_FILE: { + if (resultCode != RESULT_OK) + return; + + String path = getPathFromUri(data.getData()); + if (path == null) + return; + + startEmulation(path, shouldResumeStateByDefault()); + } + break; } } @@ -269,6 +308,13 @@ public class MainActivity extends AppCompatActivity { return true; } + private void startStartFile() { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("*/*"); + intent.addCategory(Intent.CATEGORY_OPENABLE); + startActivityForResult(Intent.createChooser(intent, "Choose Disc Image"), REQUEST_START_FILE); + } + private boolean doBIOSCheck() { if (AndroidHostInterface.getInstance().hasAnyBIOSImages()) return true; diff --git a/android/app/src/main/res/menu/menu_main.xml b/android/app/src/main/res/menu/menu_main.xml index d29b74200..9f2dda4ca 100644 --- a/android/app/src/main/res/menu/menu_main.xml +++ b/android/app/src/main/res/menu/menu_main.xml @@ -6,6 +6,9 @@ +