summaryrefslogtreecommitdiff
path: root/Source/Android/app/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Android/app/src/main/java')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.kt165
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/UserDataActivity.kt78
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/infinitybase/ui/FigureSlotAdapter.kt31
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/DirectoryPicker.kt19
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FilePicker.kt6
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.kt9
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.kt45
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityResultLaunchers.kt60
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.kt9
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt42
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt30
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentView.kt5
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/FilePickerViewHolder.kt3
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/skylanders/ui/SkylanderSlotAdapter.kt31
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/ConvertFragment.kt21
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.kt66
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.kt98
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainView.kt4
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.kt59
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/FileBrowserHelper.java6
20 files changed, 374 insertions, 413 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.kt
index 5e6c8af9e9..184392f75f 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.kt
@@ -2,10 +2,10 @@
package org.dolphinemu.dolphinemu.activities
-import android.annotation.SuppressLint
import android.content.DialogInterface
import android.content.Intent
import android.graphics.Rect
+import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.util.SparseIntArray
@@ -16,6 +16,7 @@ import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import android.view.WindowManager
import android.widget.Toast
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.PopupMenu
import androidx.core.view.ViewCompat
@@ -87,6 +88,92 @@ class EmulationActivity : AppCompatActivity(), ThemeProvider {
private lateinit var binding: ActivityEmulationBinding
+ private val requestChangeDisc = registerForActivityResult(
+ ActivityResultContracts.GetContent()
+ ) { uri: Uri? ->
+ if (uri != null) {
+ NativeLibrary.ChangeDisc(uri.toString())
+ }
+ }
+
+ val requestSkylanderFile = registerForActivityResult(
+ ActivityResultContracts.GetContent()
+ ) { uri: Uri? ->
+ if (uri != null) {
+ val slot = SkylanderConfig.loadSkylander(
+ skylanderSlots[skylanderSlot].portalSlot,
+ uri.toString()
+ )!!
+ clearSkylander(skylanderSlot)
+ skylanderSlots[skylanderSlot].portalSlot = slot.first!!
+ skylanderSlots[skylanderSlot].label = slot.second!!
+ skylandersBinding.figureManager.adapter!!.notifyItemChanged(skylanderSlot)
+ skylanderSlot = -1
+ skylanderData = Skylander.BLANK_SKYLANDER
+ }
+ }
+
+ val requestCreateSkylander = registerForActivityResult(
+ ActivityResultContracts.CreateDocument("*/*")
+ ) { uri: Uri? ->
+ if (uri != null) {
+ if (skylanderData.id != -1 && skylanderData.variant != -1) {
+ val slot = SkylanderConfig.createSkylander(
+ skylanderData.id,
+ skylanderData.variant,
+ uri.toString(),
+ skylanderSlots[skylanderSlot].portalSlot
+ )
+ clearSkylander(skylanderSlot)
+ skylanderSlots[skylanderSlot].portalSlot = slot.first
+ skylanderSlots[skylanderSlot].label = slot.second
+ skylandersBinding.figureManager.adapter?.notifyItemChanged(skylanderSlot)
+ skylanderSlot = -1
+ skylanderData = Skylander.BLANK_SKYLANDER
+ }
+ }
+ }
+
+ val requestInfinityFigureFile = registerForActivityResult(
+ ActivityResultContracts.GetContent()
+ ) { uri: Uri? ->
+ if (uri != null) {
+ val label = InfinityConfig.loadFigure(infinityPosition, uri.toString())
+ if (label != null && label != "Unknown Figure") {
+ clearInfinityFigure(infinityPosition)
+ infinityFigures[infinityPosition].label = label
+ infinityBinding.figureManager.adapter?.notifyItemChanged(infinityPosition)
+ infinityPosition = -1
+ infinityFigureData = Figure.BLANK_FIGURE
+ } else {
+ MaterialAlertDialogBuilder(this)
+ .setTitle(R.string.incompatible_figure_selected)
+ .setMessage(R.string.select_compatible_figure)
+ .setPositiveButton(android.R.string.ok, null)
+ .show()
+ }
+ }
+ }
+
+ val requestCreateInfinityFigure = registerForActivityResult(
+ ActivityResultContracts.CreateDocument("*/*")
+ ) { uri: Uri? ->
+ if (uri != null) {
+ if (infinityFigureData.number != -1L) {
+ val label = InfinityConfig.createFigure(
+ infinityFigureData.number,
+ uri.toString(),
+ infinityPosition
+ )
+ clearInfinityFigure(infinityPosition)
+ infinityFigures[infinityPosition].label = label!!
+ infinityBinding.figureManager.adapter?.notifyItemChanged(infinityPosition)
+ infinityPosition = -1
+ infinityFigureData = Figure.BLANK_FIGURE
+ }
+ }
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
ThemeHelper.setTheme(this)
@@ -263,70 +350,6 @@ class EmulationActivity : AppCompatActivity(), ThemeProvider {
return super.onKeyLongPress(keyCode, event)
}
- override fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) {
- super.onActivityResult(requestCode, resultCode, result)
- // If the user picked a file, as opposed to just backing out.
- if (resultCode == RESULT_OK) {
- if (requestCode == REQUEST_CHANGE_DISC) {
- NativeLibrary.ChangeDisc(result!!.data.toString())
- } else if (requestCode == REQUEST_SKYLANDER_FILE) {
- val slot = SkylanderConfig.loadSkylander(
- skylanderSlots[skylanderSlot].portalSlot,
- result!!.data.toString()
- )!!
- clearSkylander(skylanderSlot)
- skylanderSlots[skylanderSlot].portalSlot = slot.first!!
- skylanderSlots[skylanderSlot].label = slot.second!!
- skylandersBinding.figureManager.adapter!!.notifyItemChanged(skylanderSlot)
- skylanderSlot = -1
- skylanderData = Skylander.BLANK_SKYLANDER
- } else if (requestCode == REQUEST_CREATE_SKYLANDER) {
- if (skylanderData.id != -1 && skylanderData.variant != -1) {
- val slot = SkylanderConfig.createSkylander(
- skylanderData.id,
- skylanderData.variant,
- result!!.data.toString(),
- skylanderSlots[skylanderSlot].portalSlot
- )
- clearSkylander(skylanderSlot)
- skylanderSlots[skylanderSlot].portalSlot = slot.first
- skylanderSlots[skylanderSlot].label = slot.second
- skylandersBinding.figureManager.adapter?.notifyItemChanged(skylanderSlot)
- skylanderSlot = -1
- skylanderData = Skylander.BLANK_SKYLANDER
- }
- } else if (requestCode == REQUEST_INFINITY_FIGURE_FILE) {
- val label = InfinityConfig.loadFigure(infinityPosition, result!!.data.toString())
- if (label != null && label != "Unknown Figure") {
- clearInfinityFigure(infinityPosition)
- infinityFigures[infinityPosition].label = label
- infinityBinding.figureManager.adapter?.notifyItemChanged(infinityPosition)
- infinityPosition = -1
- infinityFigureData = Figure.BLANK_FIGURE
- } else {
- MaterialAlertDialogBuilder(this)
- .setTitle(R.string.incompatible_figure_selected)
- .setMessage(R.string.select_compatible_figure)
- .setPositiveButton(android.R.string.ok, null)
- .show()
- }
- } else if (requestCode == REQUEST_CREATE_INFINITY_FIGURE) {
- if (infinityFigureData.number != -1L) {
- val label = InfinityConfig.createFigure(
- infinityFigureData.number,
- result!!.data.toString(),
- infinityPosition
- )
- clearInfinityFigure(infinityPosition)
- infinityFigures[infinityPosition].label = label!!
- infinityBinding.figureManager.adapter?.notifyItemChanged(infinityPosition)
- infinityPosition = -1
- infinityFigureData = Figure.BLANK_FIGURE
- }
- }
- }
- }
-
private fun enableFullscreenImmersive() {
WindowCompat.setDecorFitsSystemWindows(window, false)
WindowInsetsControllerCompat(window, window.decorView).let { controller ->
@@ -480,12 +503,7 @@ class EmulationActivity : AppCompatActivity(), ThemeProvider {
MENU_ACTION_LOAD_SLOT4 -> NativeLibrary.LoadState(3)
MENU_ACTION_LOAD_SLOT5 -> NativeLibrary.LoadState(4)
MENU_ACTION_LOAD_SLOT6 -> NativeLibrary.LoadState(5)
- MENU_ACTION_CHANGE_DISC -> {
- val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
- intent.addCategory(Intent.CATEGORY_OPENABLE)
- intent.type = "*/*"
- startActivityForResult(intent, REQUEST_CHANGE_DISC)
- }
+ MENU_ACTION_CHANGE_DISC -> requestChangeDisc.launch("*/*")
MENU_SET_IR_MODE -> setIRMode()
MENU_ACTION_CHOOSE_DOUBLETAP -> chooseDoubleTapButton()
@@ -997,11 +1015,6 @@ class EmulationActivity : AppCompatActivity(), ThemeProvider {
companion object {
private const val BACKSTACK_NAME_MENU = "menu"
private const val BACKSTACK_NAME_SUBMENU = "submenu"
- const val REQUEST_CHANGE_DISC = 1
- const val REQUEST_SKYLANDER_FILE = 2
- const val REQUEST_CREATE_SKYLANDER = 3
- const val REQUEST_INFINITY_FIGURE_FILE = 4
- const val REQUEST_CREATE_INFINITY_FIGURE = 5
private var ignoreLaunchRequests = false
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/UserDataActivity.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/UserDataActivity.kt
index 4639da2839..c111c99adf 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/UserDataActivity.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/UserDataActivity.kt
@@ -11,6 +11,8 @@ import android.os.Bundle
import android.provider.DocumentsContract
import android.view.View
import androidx.activity.enableEdgeToEdge
+import androidx.activity.result.ActivityResult
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
@@ -44,6 +46,39 @@ class UserDataActivity : AppCompatActivity(), ThemeProvider {
private lateinit var mBinding: ActivityUserDataBinding
override var themeId: Int = 0
+ private val requestImport = registerForActivityResult(
+ ActivityResultContracts.OpenDocument()
+ ) { uri: Uri? ->
+ if (uri != null) {
+ val arguments = Bundle()
+ arguments.putString(
+ UserDataImportWarningDialog.KEY_URI_RESULT,
+ uri.toString()
+ )
+
+ val dialog = UserDataImportWarningDialog()
+ dialog.arguments = arguments
+ dialog.show(supportFragmentManager, UserDataImportWarningDialog.TAG)
+ }
+ }
+
+ private val requestExport = registerForActivityResult(
+ ActivityResultContracts.CreateDocument("application/zip")
+ ) { uri: Uri? ->
+ if (uri != null) {
+ taskViewModel.clear()
+ taskViewModel.task = { exportUserData(uri) }
+
+ val arguments = Bundle()
+ arguments.putInt(TaskDialog.KEY_TITLE, R.string.export_in_progress)
+ arguments.putInt(TaskDialog.KEY_MESSAGE, 0)
+ arguments.putBoolean(TaskDialog.KEY_CANCELLABLE, true)
+
+ val dialog = TaskDialog()
+ dialog.arguments = arguments
+ dialog.show(supportFragmentManager, TaskDialog.TAG)
+ }
+ }
override fun onCreate(savedInstanceState: Bundle?) {
taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java]
@@ -108,34 +143,6 @@ class UserDataActivity : AppCompatActivity(), ThemeProvider {
this.themeId = themeId
}
- public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- super.onActivityResult(requestCode, resultCode, data)
-
- if (requestCode == REQUEST_CODE_IMPORT && resultCode == RESULT_OK) {
- val arguments = Bundle()
- arguments.putString(
- UserDataImportWarningDialog.KEY_URI_RESULT,
- data!!.data!!.toString()
- )
-
- val dialog = UserDataImportWarningDialog()
- dialog.arguments = arguments
- dialog.show(supportFragmentManager, UserDataImportWarningDialog.TAG)
- } else if (requestCode == REQUEST_CODE_EXPORT && resultCode == RESULT_OK) {
- taskViewModel.clear()
- taskViewModel.task = { exportUserData(data!!.data!!) }
-
- val arguments = Bundle()
- arguments.putInt(TaskDialog.KEY_TITLE, R.string.export_in_progress)
- arguments.putInt(TaskDialog.KEY_MESSAGE, 0)
- arguments.putBoolean(TaskDialog.KEY_CANCELLABLE, true)
-
- val dialog = TaskDialog()
- dialog.arguments = arguments
- dialog.show(supportFragmentManager, TaskDialog.TAG)
- }
- }
-
private fun confirmResetSettings() {
MaterialAlertDialogBuilder(this)
.setTitle(R.string.reset_dolphin_settings)
@@ -216,15 +223,14 @@ class UserDataActivity : AppCompatActivity(), ThemeProvider {
}
private fun importUserData() {
- val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
- intent.type = "application/zip"
- startActivityForResult(intent, REQUEST_CODE_IMPORT)
+ requestImport.launch(arrayOf("application/zip"))
}
fun importUserData(source: Uri): Int {
try {
- if (!isDolphinUserDataBackup(source))
+ if (!isDolphinUserDataBackup(source)) {
return R.string.user_data_import_invalid_file
+ }
taskViewModel.onResultDismiss = {
// Restart the app to apply the imported user data.
@@ -319,10 +325,7 @@ class UserDataActivity : AppCompatActivity(), ThemeProvider {
}
private fun exportUserData() {
- val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
- intent.type = "application/zip"
- intent.putExtra(Intent.EXTRA_TITLE, "dolphin-emu.zip")
- startActivityForResult(intent, REQUEST_CODE_EXPORT)
+ requestExport.launch("dolphin-emu.zip")
}
private fun exportUserData(destination: Uri): Int {
@@ -385,9 +388,6 @@ class UserDataActivity : AppCompatActivity(), ThemeProvider {
}
companion object {
- private const val REQUEST_CODE_IMPORT = 0
- private const val REQUEST_CODE_EXPORT = 1
-
private const val BUFFER_SIZE = 64 * 1024
@JvmStatic
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/infinitybase/ui/FigureSlotAdapter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/infinitybase/ui/FigureSlotAdapter.kt
index 512019388c..0613274c30 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/infinitybase/ui/FigureSlotAdapter.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/infinitybase/ui/FigureSlotAdapter.kt
@@ -50,14 +50,8 @@ class FigureSlotAdapter(
}
holder.binding.buttonLoadFigure.setOnClickListener {
- val loadFigure = Intent(Intent.ACTION_OPEN_DOCUMENT)
- loadFigure.addCategory(Intent.CATEGORY_OPENABLE)
- loadFigure.type = "*/*"
activity.setInfinityFigureData(0, "", figure.position, position)
- activity.startActivityForResult(
- loadFigure,
- EmulationActivity.REQUEST_INFINITY_FIGURE_FILE
- )
+ activity.requestInfinityFigureFile.launch("*/*")
}
val inflater = LayoutInflater.from(activity)
@@ -110,28 +104,11 @@ class FigureSlotAdapter(
.show()
createDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
if (binding.infinityNum.text.toString().isNotBlank()) {
- val createFigure = Intent(Intent.ACTION_CREATE_DOCUMENT)
- createFigure.addCategory(Intent.CATEGORY_OPENABLE)
- createFigure.type = "*/*"
val num = binding.infinityNum.text.toString().toLong()
val name = InfinityConfig.LIST_FIGURES[num]
- if (name != null) {
- createFigure.putExtra(
- Intent.EXTRA_TITLE,
- "$name.bin"
- )
- activity.setInfinityFigureData(num, name, figure.position, position)
- } else {
- createFigure.putExtra(
- Intent.EXTRA_TITLE,
- "Unknown(Number: $num).bin"
- )
- activity.setInfinityFigureData(num, "Unknown", figure.position, position)
- }
- activity.startActivityForResult(
- createFigure,
- EmulationActivity.REQUEST_CREATE_INFINITY_FIGURE
- )
+ val title = if (name != null) "$name.bin" else "Unknown(Number: $num).bin"
+ activity.setInfinityFigureData(num, name ?: "Unknown", figure.position, position)
+ activity.requestCreateInfinityFigure.launch(title)
createDialog.dismiss()
} else {
Toast.makeText(
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/DirectoryPicker.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/DirectoryPicker.kt
new file mode 100644
index 0000000000..415241e38c
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/DirectoryPicker.kt
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+import android.content.Intent
+import androidx.activity.result.ActivityResultLauncher
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting
+
+class DirectoryPicker(
+ context: Context,
+ setting: AbstractStringSetting,
+ titleId: Int,
+ descriptionId: Int,
+ launcher: ActivityResultLauncher<Intent>,
+ defaultPathRelativeToUserDirectory: String?
+) : FilePicker(context, setting, titleId, descriptionId, launcher, defaultPathRelativeToUserDirectory) {
+ override val type: Int = TYPE_DIRECTORY_PICKER
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FilePicker.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FilePicker.kt
index 2b5bd70162..e85cc7dc0b 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FilePicker.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FilePicker.kt
@@ -3,15 +3,17 @@
package org.dolphinemu.dolphinemu.features.settings.model.view
import android.content.Context
+import android.content.Intent
+import androidx.activity.result.ActivityResultLauncher
import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting
import org.dolphinemu.dolphinemu.features.settings.model.Settings
-class FilePicker(
+open class FilePicker(
context: Context,
override var setting: AbstractStringSetting,
titleId: Int,
descriptionId: Int,
- val requestType: Int,
+ val launcher: ActivityResultLauncher<Intent>,
val defaultPathRelativeToUserDirectory: String?
) : SettingsItem(context, titleId, descriptionId) {
override val type: Int = TYPE_FILE_PICKER
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.kt
index 01c4796e68..4d41676a14 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.kt
@@ -81,9 +81,10 @@ abstract class SettingsItem {
const val TYPE_STRING_SINGLE_CHOICE = 6
const val TYPE_SINGLE_CHOICE_DYNAMIC_DESCRIPTIONS = 8
const val TYPE_FILE_PICKER = 9
- const val TYPE_RUN_RUNNABLE = 10
- const val TYPE_STRING = 11
- const val TYPE_HYPERLINK_HEADER = 12
- const val TYPE_DATETIME_CHOICE = 13
+ const val TYPE_DIRECTORY_PICKER = 10
+ const val TYPE_RUN_RUNNABLE = 11
+ const val TYPE_STRING = 12
+ const val TYPE_HYPERLINK_HEADER = 13
+ const val TYPE_DATETIME_CHOICE = 14
}
}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.kt
index 9b252b5cdd..68f957a626 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.kt
@@ -1,15 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-or-later
-// GPU driver implementation partially based on:
-// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
package org.dolphinemu.dolphinemu.features.settings.ui
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
-import android.net.Uri
import android.os.Bundle
import android.view.KeyEvent
import android.view.Menu
@@ -33,7 +28,6 @@ import org.dolphinemu.dolphinemu.features.settings.model.Settings
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsFragment.Companion.newInstance
import org.dolphinemu.dolphinemu.ui.main.MainPresenter
import org.dolphinemu.dolphinemu.ui.main.ThemeProvider
-import org.dolphinemu.dolphinemu.utils.FileBrowserHelper
import org.dolphinemu.dolphinemu.utils.InsetsHelper
import org.dolphinemu.dolphinemu.utils.SerializableHelper.serializable
import org.dolphinemu.dolphinemu.utils.ThemeHelper.enableScrollTint
@@ -177,40 +171,6 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView, ThemeProvide
return duration != 0f && transition != 0f
}
- override fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) {
- super.onActivityResult(requestCode, resultCode, result)
-
- // If the user picked a file, as opposed to just backing out.
- if (resultCode != RESULT_OK) {
- return
- }
-
- when (requestCode) {
- MainPresenter.REQUEST_DIRECTORY -> {
- val path = FileBrowserHelper.getSelectedPath(result)
- fragment!!.adapter!!.onFilePickerConfirmation(path!!)
- }
-
- MainPresenter.REQUEST_GAME_FILE,
- MainPresenter.REQUEST_SD_FILE,
- MainPresenter.REQUEST_WAD_FILE,
- MainPresenter.REQUEST_WII_SAVE_FILE,
- MainPresenter.REQUEST_NAND_BIN_FILE -> {
- val uri = canonicalizeIfPossible(result!!.data!!)
- val validExtensions: Set<String> =
- if (requestCode == MainPresenter.REQUEST_GAME_FILE) FileBrowserHelper.GAME_EXTENSIONS else FileBrowserHelper.RAW_EXTENSION
- var flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
- if (requestCode != MainPresenter.REQUEST_GAME_FILE) flags =
- flags or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
- val takeFlags = flags and result.flags
- FileBrowserHelper.runAfterExtensionCheck(this, uri, validExtensions) {
- contentResolver.takePersistableUriPermission(uri, takeFlags)
- fragment!!.adapter!!.onFilePickerConfirmation(uri.toString())
- }
- }
- }
- }
-
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
ControllerInterface.dispatchKeyEvent(event)
return super.dispatchKeyEvent(event)
@@ -221,11 +181,6 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView, ThemeProvide
return super.dispatchGenericMotionEvent(event)
}
- private fun canonicalizeIfPossible(uri: Uri): Uri {
- val canonicalizedUri = contentResolver.canonicalize(uri)
- return canonicalizedUri ?: uri
- }
-
override fun showLoading() {
if (dialog == null) {
dialog = MaterialAlertDialogBuilder(this)
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityResultLaunchers.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityResultLaunchers.kt
new file mode 100644
index 0000000000..9c13be1b19
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityResultLaunchers.kt
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui
+
+import android.app.Activity
+import android.content.Intent
+import androidx.activity.result.ActivityResult
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.fragment.app.Fragment
+import org.dolphinemu.dolphinemu.utils.FileBrowserHelper
+
+class SettingsActivityResultLaunchers(
+ private val fragment: Fragment, private val getAdapter: () -> SettingsAdapter?
+) {
+ val requestDirectory = fragment.registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult()
+ ) { result: ActivityResult ->
+ val intent = result.data
+ if (result.resultCode == Activity.RESULT_OK && intent != null) {
+ val path = FileBrowserHelper.getSelectedPath(intent)
+ if (path != null) {
+ getAdapter()?.onFilePickerConfirmation(path)
+ }
+ }
+ }
+
+ val requestGameFile = fragment.registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult()
+ ) { result: ActivityResult ->
+ onFileResult(
+ result,
+ FileBrowserHelper.GAME_EXTENSIONS,
+ Intent.FLAG_GRANT_READ_URI_PERMISSION
+ )
+ }
+
+ val requestRawFile = fragment.registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult()
+ ) { result: ActivityResult ->
+ onFileResult(
+ result,
+ FileBrowserHelper.RAW_EXTENSION,
+ Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ )
+ }
+
+ private fun onFileResult(result: ActivityResult, validExtensions: Set<String>, flags: Int) {
+ val intent = result.data
+ val uri = intent?.data
+ val context = fragment.requireContext()
+ if (result.resultCode == Activity.RESULT_OK && uri != null) {
+ val canonicalizedUri = context.contentResolver.canonicalize(uri) ?: uri
+ val takeFlags = flags and intent.flags
+ FileBrowserHelper.runAfterExtensionCheck(context, canonicalizedUri, validExtensions) {
+ context.contentResolver.takePersistableUriPermission(canonicalizedUri, takeFlags)
+ getAdapter()?.onFilePickerConfirmation(canonicalizedUri.toString())
+ }
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.kt
index 3ce937e6ab..ae236d3764 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.kt
@@ -94,7 +94,8 @@ class SettingsAdapter(
ListItemMappingBinding.inflate(inflater, parent, false),
this
)
- SettingsItem.TYPE_FILE_PICKER -> FilePickerViewHolder(
+ SettingsItem.TYPE_FILE_PICKER,
+ SettingsItem.TYPE_DIRECTORY_PICKER -> FilePickerViewHolder(
ListItemSettingBinding.inflate(inflater, parent, false),
this
)
@@ -357,6 +358,7 @@ class SettingsAdapter(
fun onFilePickerDirectoryClick(item: SettingsItem, position: Int) {
clickedItem = item
clickedPosition = position
+ val directoryPicker = item as DirectoryPicker
if (!PermissionsHandler.isExternalStorageLegacy()) {
MaterialAlertDialogBuilder(context)
@@ -364,10 +366,11 @@ class SettingsAdapter(
.setPositiveButton(R.string.ok) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
.show()
} else {
- FileBrowserHelper.openDirectoryPicker(
+ val intent = FileBrowserHelper.createDirectoryPickerIntent(
fragmentView.fragmentActivity,
FileBrowserHelper.GAME_EXTENSIONS
)
+ directoryPicker.launcher.launch(intent)
}
}
@@ -383,7 +386,7 @@ class SettingsAdapter(
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, filePicker.getSelectedValue())
}
- fragmentView.fragmentActivity.startActivityForResult(intent, filePicker.requestType)
+ filePicker.launcher.launch(intent)
}
fun onDateTimeClick(item: DateTimeChoiceSetting, position: Int) {
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt
index 991d3c3c2b..2992dd3211 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt
@@ -1,17 +1,22 @@
// SPDX-License-Identifier: GPL-2.0-or-later
+// GPU driver implementation partially based on:
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
package org.dolphinemu.dolphinemu.features.settings.ui
+import android.app.Activity
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
-import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
-import androidx.appcompat.app.AppCompatActivity
+import androidx.activity.result.ActivityResult
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
@@ -26,7 +31,6 @@ import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.databinding.FragmentSettingsBinding
import org.dolphinemu.dolphinemu.features.settings.model.Settings
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
-import org.dolphinemu.dolphinemu.ui.main.MainPresenter
import org.dolphinemu.dolphinemu.utils.GpuDriverInstallResult
import org.dolphinemu.dolphinemu.utils.SerializableHelper.serializable
import java.util.*
@@ -43,10 +47,22 @@ class SettingsFragment : Fragment(), SettingsFragmentView {
override var adapter: SettingsAdapter? = null
+ override val activityResultLaunchers: SettingsActivityResultLaunchers =
+ SettingsActivityResultLaunchers(this) { adapter }
+
private var oldControllerSettingsWarningHeight = 0
private var binding: FragmentSettingsBinding? = null
+ private val requestGpuDriver = registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult()
+ ) { result: ActivityResult ->
+ val uri = result.data?.data
+ if (result.resultCode == Activity.RESULT_OK && uri != null) {
+ presenter.installDriver(uri)
+ }
+ }
+
override fun onAttach(context: Context) {
super.onAttach(context)
@@ -185,7 +201,7 @@ class SettingsFragment : Fragment(), SettingsFragmentView {
if (presenter.gpuDriver == null) {
return
}
- val msg = "${presenter!!.gpuDriver!!.name} ${presenter!!.gpuDriver!!.driverVersion}"
+ val msg = "${presenter.gpuDriver!!.name} ${presenter.gpuDriver!!.driverVersion}"
MaterialAlertDialogBuilder(requireContext())
.setTitle(getString(R.string.gpu_driver_dialog_title))
@@ -209,23 +225,7 @@ class SettingsFragment : Fragment(), SettingsFragmentView {
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
type = "application/zip"
}
- startActivityForResult(intent, MainPresenter.REQUEST_GPU_DRIVER)
- }
-
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- super.onActivityResult(requestCode, resultCode, data)
-
- // If the user picked a file, as opposed to just backing out.
- if (resultCode != AppCompatActivity.RESULT_OK) {
- return
- }
-
- if (requestCode != MainPresenter.REQUEST_GPU_DRIVER) {
- return
- }
-
- val uri = data?.data ?: return
- presenter.installDriver(uri)
+ requestGpuDriver.launch(intent)
}
override fun onDriverInstallDone(result: GpuDriverInstallResult) {
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt
index 25acccb2fc..977f2aeff6 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt
@@ -32,9 +32,7 @@ import org.dolphinemu.dolphinemu.features.input.ui.ProfileDialogPresenter
import org.dolphinemu.dolphinemu.features.settings.model.*
import org.dolphinemu.dolphinemu.features.settings.model.view.*
import org.dolphinemu.dolphinemu.model.GpuDriverMetadata
-import org.dolphinemu.dolphinemu.ui.main.MainPresenter
import org.dolphinemu.dolphinemu.utils.*
-import java.util.*
import kotlin.collections.ArrayList
import kotlin.math.ceil
import kotlin.math.floor
@@ -584,57 +582,57 @@ class SettingsFragmentPresenter(
StringSetting.MAIN_DEFAULT_ISO,
R.string.default_ISO,
0,
- MainPresenter.REQUEST_GAME_FILE,
+ fragmentView.activityResultLaunchers.requestGameFile,
null
)
)
sl.add(
- FilePicker(
+ DirectoryPicker(
context,
StringSetting.MAIN_FS_PATH,
R.string.wii_NAND_root,
0,
- MainPresenter.REQUEST_DIRECTORY,
+ fragmentView.activityResultLaunchers.requestDirectory,
"/Wii"
)
)
sl.add(
- FilePicker(
+ DirectoryPicker(
context,
StringSetting.MAIN_DUMP_PATH,
R.string.dump_path,
0,
- MainPresenter.REQUEST_DIRECTORY,
+ fragmentView.activityResultLaunchers.requestDirectory,
"/Dump"
)
)
sl.add(
- FilePicker(
+ DirectoryPicker(
context,
StringSetting.MAIN_LOAD_PATH,
R.string.load_path,
0,
- MainPresenter.REQUEST_DIRECTORY,
+ fragmentView.activityResultLaunchers.requestDirectory,
"/Load"
)
)
sl.add(
- FilePicker(
+ DirectoryPicker(
context,
StringSetting.MAIN_RESOURCEPACK_PATH,
R.string.resource_pack_path,
0,
- MainPresenter.REQUEST_DIRECTORY,
+ fragmentView.activityResultLaunchers.requestDirectory,
"/ResourcePacks"
)
)
sl.add(
- FilePicker(
+ DirectoryPicker(
context,
StringSetting.MAIN_WFS_PATH,
R.string.wfs_path,
0,
- MainPresenter.REQUEST_DIRECTORY,
+ fragmentView.activityResultLaunchers.requestDirectory,
"/WFS"
)
)
@@ -784,17 +782,17 @@ class SettingsFragmentPresenter(
StringSetting.MAIN_WII_SD_CARD_IMAGE_PATH,
R.string.wii_sd_card_path,
0,
- MainPresenter.REQUEST_SD_FILE,
+ fragmentView.activityResultLaunchers.requestRawFile,
"/Load/WiiSD.raw"
)
)
sl.add(
- FilePicker(
+ DirectoryPicker(
context,
StringSetting.MAIN_WII_SD_CARD_SYNC_FOLDER_PATH,
R.string.wii_sd_sync_folder,
0,
- MainPresenter.REQUEST_DIRECTORY,
+ fragmentView.activityResultLaunchers.requestDirectory,
"/Load/WiiSDSync/"
)
)
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentView.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentView.kt
index b0ad3e28b1..c0b39400a7 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentView.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentView.kt
@@ -39,6 +39,11 @@ interface SettingsFragmentView {
val adapter: SettingsAdapter?
/**
+ * The activity result launchers to use for asking the user to pick a directory or file.
+ */
+ val activityResultLaunchers: SettingsActivityResultLaunchers
+
+ /**
* Tell the Fragment to tell the containing Activity to show a new
* Fragment containing a submenu of settings.
*
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/FilePickerViewHolder.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/FilePickerViewHolder.kt
index ff6246d292..e4bf333831 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/FilePickerViewHolder.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/FilePickerViewHolder.kt
@@ -9,7 +9,6 @@ import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding
import org.dolphinemu.dolphinemu.features.settings.model.view.FilePicker
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
-import org.dolphinemu.dolphinemu.ui.main.MainPresenter
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper
@@ -57,7 +56,7 @@ class FilePickerViewHolder(
}
val position = bindingAdapterPosition
- if (setting.requestType == MainPresenter.REQUEST_DIRECTORY) {
+ if (setting.type == SettingsItem.TYPE_DIRECTORY_PICKER) {
adapter.onFilePickerDirectoryClick(setting, position)
} else {
adapter.onFilePickerFileClick(setting, position)
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/skylanders/ui/SkylanderSlotAdapter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/skylanders/ui/SkylanderSlotAdapter.kt
index 295d1abf1a..ed3dde3e40 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/skylanders/ui/SkylanderSlotAdapter.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/skylanders/ui/SkylanderSlotAdapter.kt
@@ -46,14 +46,8 @@ class SkylanderSlotAdapter(
}
holder.binding.buttonLoadFigure.setOnClickListener {
- val loadSkylander = Intent(Intent.ACTION_OPEN_DOCUMENT)
- loadSkylander.addCategory(Intent.CATEGORY_OPENABLE)
- loadSkylander.type = "*/*"
activity.setSkylanderData(0, 0, "", position)
- activity.startActivityForResult(
- loadSkylander,
- EmulationActivity.REQUEST_SKYLANDER_FILE
- )
+ activity.requestSkylanderFile.launch("*/*")
}
val inflater = LayoutInflater.from(activity)
@@ -85,29 +79,12 @@ class SkylanderSlotAdapter(
if (binding.skylanderId.text.toString().isNotBlank() &&
binding.skylanderVar.text.toString().isNotBlank()
) {
- val createSkylander = Intent(Intent.ACTION_CREATE_DOCUMENT)
- createSkylander.addCategory(Intent.CATEGORY_OPENABLE)
- createSkylander.type = "*/*"
val id = binding.skylanderId.text.toString().toInt()
val variant = binding.skylanderVar.text.toString().toInt()
val name = SkylanderConfig.LIST_SKYLANDERS[SkylanderPair(id, variant)]
- if (name != null) {
- createSkylander.putExtra(
- Intent.EXTRA_TITLE,
- "$name.sky"
- )
- activity.setSkylanderData(id, variant, name, position)
- } else {
- createSkylander.putExtra(
- Intent.EXTRA_TITLE,
- "Unknown(ID: " + id + "Variant: " + variant + ").sky"
- )
- activity.setSkylanderData(id, variant, "Unknown", position)
- }
- activity.startActivityForResult(
- createSkylander,
- EmulationActivity.REQUEST_CREATE_SKYLANDER
- )
+ val title = if (name != null) "$name.sky" else "Unknown(ID: $id Variant: $variant).sky"
+ activity.setSkylanderData(id, variant, name ?: "Unknown", position)
+ activity.requestCreateSkylander.launch(title)
createDialog.dismiss()
} else {
Toast.makeText(
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/ConvertFragment.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/ConvertFragment.kt
index 0f5760a210..5f171a872b 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/ConvertFragment.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/ConvertFragment.kt
@@ -15,6 +15,8 @@ import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.AdapterView.OnItemClickListener
import android.widget.ArrayAdapter
+import androidx.activity.result.ActivityResult
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -79,6 +81,15 @@ class ConvertFragment : Fragment(), View.OnClickListener {
private var _binding: FragmentConvertBinding? = null
val binding get() = _binding!!
+ private val requestSaveFile = registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult()
+ ) { result: ActivityResult ->
+ val uri = result.data?.data
+ if (result.resultCode == Activity.RESULT_OK && uri != null) {
+ convert(uri.toString())
+ }
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
gameFile = GameFileCacheManager.addOrGet(requireArguments().getString(ARG_GAME_PATH))
@@ -429,13 +440,7 @@ class ConvertFragment : Fragment(), View.OnClickListener {
DocumentsContract.EXTRA_INITIAL_URI,
originalPath
)
- startActivityForResult(intent, REQUEST_CODE_SAVE_FILE)
- }
-
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- if (requestCode == REQUEST_CODE_SAVE_FILE && resultCode == Activity.RESULT_OK) {
- convert(data!!.data.toString())
- }
+ requestSaveFile.launch(intent)
}
private fun convert(outPath: String) {
@@ -515,8 +520,6 @@ class ConvertFragment : Fragment(), View.OnClickListener {
private const val KEY_COMPRESSION_LEVEL = "convert_compression_level"
private const val KEY_REMOVE_JUNK_DATA = "remove_junk_data"
- private const val REQUEST_CODE_SAVE_FILE = 0
-
private const val BLOB_TYPE_ISO = 0
private const val BLOB_TYPE_GCZ = 3
private const val BLOB_TYPE_WIA = 7
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.kt
index a759ad2d14..761c6dbfef 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.kt
@@ -2,7 +2,6 @@
package org.dolphinemu.dolphinemu.ui.main
-import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.Menu
@@ -18,7 +17,6 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.tabs.TabLayout
import org.dolphinemu.dolphinemu.R
-import org.dolphinemu.dolphinemu.activities.EmulationActivity
import org.dolphinemu.dolphinemu.adapters.PlatformPagerAdapter
import org.dolphinemu.dolphinemu.databinding.ActivityMainBinding
import org.dolphinemu.dolphinemu.features.settings.model.IntSetting
@@ -31,7 +29,6 @@ import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesView
import org.dolphinemu.dolphinemu.ui.platform.PlatformTab
import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization
-import org.dolphinemu.dolphinemu.utils.FileBrowserHelper
import org.dolphinemu.dolphinemu.utils.InsetsHelper
import org.dolphinemu.dolphinemu.utils.PermissionsHandler
import org.dolphinemu.dolphinemu.utils.StartupHandler
@@ -65,7 +62,11 @@ class MainActivity : AppCompatActivity(), MainView, OnRefreshListener, ThemeProv
setSupportActionBar(binding.toolbarMain)
// Set up the FAB.
- binding.buttonAddDirectory.setOnClickListener { presenter.onFabClick() }
+ binding.buttonAddDirectory.setOnClickListener {
+ AfterDirectoryInitializationRunner().runWithLifecycle(this) {
+ presenter.launchFileListActivity()
+ }
+ }
binding.appbarMain.addOnOffsetChangedListener { appBarLayout: AppBarLayout, verticalOffset: Int ->
if (verticalOffset == 0) {
binding.buttonAddDirectory.extend()
@@ -145,63 +146,6 @@ class MainActivity : AppCompatActivity(), MainView, OnRefreshListener, ThemeProv
SettingsActivity.launch(this, menuTag)
}
- override fun launchFileListActivity() {
- if (DirectoryInitialization.preferOldFolderPicker(this)) {
- FileBrowserHelper.openDirectoryPicker(this, FileBrowserHelper.GAME_EXTENSIONS)
- } else {
- val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
- startActivityForResult(intent, MainPresenter.REQUEST_DIRECTORY)
- }
- }
-
- override fun launchOpenFileActivity(requestCode: Int) {
- val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
- intent.addCategory(Intent.CATEGORY_OPENABLE)
- intent.type = "*/*"
- startActivityForResult(intent, requestCode)
- }
-
- /**
- * @param requestCode An int describing whether the Activity that is returning did so successfully.
- * @param resultCode An int describing what Activity is giving us this callback.
- * @param result The information the returning Activity is providing us.
- */
- override fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) {
- super.onActivityResult(requestCode, resultCode, result)
-
- // If the user picked a file, as opposed to just backing out.
- if (resultCode == RESULT_OK) {
- val uri = result!!.data
- when (requestCode) {
- MainPresenter.REQUEST_DIRECTORY -> {
- if (DirectoryInitialization.preferOldFolderPicker(this)) {
- presenter.onDirectorySelected(FileBrowserHelper.getSelectedPath(result))
- } else {
- presenter.onDirectorySelected(result)
- }
- }
-
- MainPresenter.REQUEST_GAME_FILE -> FileBrowserHelper.runAfterExtensionCheck(
- this, uri, FileBrowserHelper.GAME_LIKE_EXTENSIONS
- ) { EmulationActivity.launch(this, result.data.toString(), false) }
-
- MainPresenter.REQUEST_WAD_FILE -> FileBrowserHelper.runAfterExtensionCheck(
- this, uri, FileBrowserHelper.WAD_EXTENSION
- ) { presenter.installWAD(result.data.toString()) }
-
- MainPresenter.REQUEST_WII_SAVE_FILE -> FileBrowserHelper.runAfterExtensionCheck(
- this, uri, FileBrowserHelper.BIN_EXTENSION
- ) { presenter.importWiiSave(result.data.toString()) }
-
- MainPresenter.REQUEST_NAND_BIN_FILE -> FileBrowserHelper.runAfterExtensionCheck(
- this, uri, FileBrowserHelper.BIN_EXTENSION
- ) { presenter.importNANDBin(result.data.toString()) }
- }
- } else {
- MainPresenter.skipRescanningLibrary()
- }
- }
-
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.kt
index e77b694096..cea17578d4 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.kt
@@ -2,9 +2,13 @@
package org.dolphinemu.dolphinemu.ui.main
+import android.app.Activity
import android.content.DialogInterface
import android.content.Intent
+import android.net.Uri
import androidx.activity.ComponentActivity
+import androidx.activity.result.ActivityResult
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
@@ -35,6 +39,69 @@ import java.util.concurrent.ExecutionException
class MainPresenter(private val mainView: MainView, private val activity: FragmentActivity) {
private var dirToAdd: String? = null
+ private val requestDirectory = activity.registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult()
+ ) { result: ActivityResult ->
+ val intent = result.data
+ if (result.resultCode == Activity.RESULT_OK && intent != null) {
+ if (DirectoryInitialization.preferOldFolderPicker(activity)) {
+ onDirectorySelected(FileBrowserHelper.getSelectedPath(intent))
+ } else {
+ onDirectorySelected(intent)
+ }
+ } else {
+ skipRescanningLibrary()
+ }
+ }
+
+ private val requestGameFile = activity.registerForActivityResult(
+ ActivityResultContracts.GetContent()
+ ) { uri: Uri? ->
+ if (uri != null) {
+ FileBrowserHelper.runAfterExtensionCheck(
+ activity, uri, FileBrowserHelper.GAME_LIKE_EXTENSIONS
+ ) { EmulationActivity.launch(activity, uri.toString(), false) }
+ } else {
+ skipRescanningLibrary()
+ }
+ }
+
+ private val requestWadFile = activity.registerForActivityResult(
+ ActivityResultContracts.GetContent()
+ ) { uri: Uri? ->
+ if (uri != null) {
+ FileBrowserHelper.runAfterExtensionCheck(
+ activity, uri, FileBrowserHelper.WAD_EXTENSION
+ ) { installWAD(uri.toString()) }
+ } else {
+ skipRescanningLibrary()
+ }
+ }
+
+ private val requestWiiSaveFile = activity.registerForActivityResult(
+ ActivityResultContracts.GetContent()
+ ) { uri: Uri? ->
+ if (uri != null) {
+ FileBrowserHelper.runAfterExtensionCheck(
+ activity, uri, FileBrowserHelper.BIN_EXTENSION
+ ) { importWiiSave(uri.toString()) }
+ } else {
+ skipRescanningLibrary()
+ }
+ }
+
+ private val requestNandBinFile = activity.registerForActivityResult(
+ ActivityResultContracts.GetContent()
+ ) { uri: Uri? ->
+ if (uri != null) {
+ FileBrowserHelper.runAfterExtensionCheck(
+ activity, uri, FileBrowserHelper.BIN_EXTENSION
+ ) { importNANDBin(uri.toString()) }
+ } else {
+ skipRescanningLibrary()
+ }
+ }
+
fun onCreate() {
// Ask the user to grant write permission if relevant and not already granted
if (DirectoryInitialization.isWaitingForWriteAccess(activity))
@@ -50,8 +117,17 @@ class MainPresenter(private val mainView: MainView, private val activity: Fragme
GameFileCacheManager.isRescanning().observe(activity, refreshObserver)
}
- fun onFabClick() {
- AfterDirectoryInitializationRunner().runWithLifecycle(activity) { mainView.launchFileListActivity() }
+ fun launchFileListActivity() {
+ val intent =
+ if (DirectoryInitialization.preferOldFolderPicker(activity)) {
+ FileBrowserHelper.createDirectoryPickerIntent(
+ activity,
+ FileBrowserHelper.GAME_EXTENSIONS,
+ )
+ } else {
+ Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
+ }
+ requestDirectory.launch(intent)
}
fun handleOptionSelection(itemId: Int, activity: ComponentActivity): Boolean =
@@ -73,12 +149,12 @@ class MainPresenter(private val mainView: MainView, private val activity: Fragme
}
R.id.button_add_directory -> {
- AfterDirectoryInitializationRunner().runWithLifecycle(activity) { mainView.launchFileListActivity() }
+ AfterDirectoryInitializationRunner().runWithLifecycle(activity) { launchFileListActivity() }
true
}
R.id.menu_open_file -> {
- mainView.launchOpenFileActivity(REQUEST_GAME_FILE)
+ requestGameFile.launch("*/*")
true
}
@@ -95,21 +171,21 @@ class MainPresenter(private val mainView: MainView, private val activity: Fragme
R.id.menu_install_wad -> {
AfterDirectoryInitializationRunner().runWithLifecycle(
activity
- ) { mainView.launchOpenFileActivity(REQUEST_WAD_FILE) }
+ ) { requestWadFile.launch("*/*") }
true
}
R.id.menu_import_wii_save -> {
AfterDirectoryInitializationRunner().runWithLifecycle(
activity
- ) { mainView.launchOpenFileActivity(REQUEST_WII_SAVE_FILE) }
+ ) { requestWiiSaveFile.launch("*/*") }
true
}
R.id.menu_import_nand_backup -> {
AfterDirectoryInitializationRunner().runWithLifecycle(
activity
- ) { mainView.launchOpenFileActivity(REQUEST_NAND_BIN_FILE) }
+ ) { requestNandBinFile.launch("*/*") }
true
}
@@ -280,14 +356,6 @@ class MainPresenter(private val mainView: MainView, private val activity: Fragme
}
companion object {
- const val REQUEST_DIRECTORY = 1
- const val REQUEST_GAME_FILE = 2
- const val REQUEST_SD_FILE = 3
- const val REQUEST_WAD_FILE = 4
- const val REQUEST_WII_SAVE_FILE = 5
- const val REQUEST_NAND_BIN_FILE = 6
- const val REQUEST_GPU_DRIVER = 7
-
private var shouldRescanLibrary = true
@JvmStatic
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainView.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainView.kt
index 3892ee7599..f43d2452fd 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainView.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainView.kt
@@ -20,10 +20,6 @@ interface MainView {
fun launchSettingsActivity(menuTag: MenuTag?)
- fun launchFileListActivity()
-
- fun launchOpenFileActivity(requestCode: Int)
-
/**
* Shows or hides the loading indicator.
*/
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.kt
index 945d474d72..09bacd201b 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.kt
@@ -125,22 +125,6 @@ class TvMainActivity : FragmentActivity(), MainView, OnRefreshListener {
SettingsActivity.launch(this, menuTag)
}
- override fun launchFileListActivity() {
- if (DirectoryInitialization.preferOldFolderPicker(this)) {
- FileBrowserHelper.openDirectoryPicker(this, FileBrowserHelper.GAME_EXTENSIONS)
- } else {
- val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
- startActivityForResult(intent, MainPresenter.REQUEST_DIRECTORY)
- }
- }
-
- override fun launchOpenFileActivity(requestCode: Int) {
- val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
- intent.addCategory(Intent.CATEGORY_OPENABLE)
- intent.type = "*/*"
- startActivityForResult(intent, requestCode)
- }
-
/**
* Shows or hides the loading indicator.
*/
@@ -165,49 +149,6 @@ class TvMainActivity : FragmentActivity(), MainView, OnRefreshListener {
GridOptionDialogFragment().show(supportFragmentManager, "gridOptions")
}
- /**
- * Callback from AddDirectoryActivity. Applies any changes necessary to the GameGridActivity.
- *
- * @param requestCode An int describing whether the Activity that is returning did so successfully.
- * @param resultCode An int describing what Activity is giving us this callback.
- * @param result The information the returning Activity is providing us.
- */
- override fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) {
- super.onActivityResult(requestCode, resultCode, result)
-
- // If the user picked a file, as opposed to just backing out.
- if (resultCode == RESULT_OK) {
- val uri = result!!.data
- when (requestCode) {
- MainPresenter.REQUEST_DIRECTORY -> {
- if (DirectoryInitialization.preferOldFolderPicker(this)) {
- presenter.onDirectorySelected(FileBrowserHelper.getSelectedPath(result))
- } else {
- presenter.onDirectorySelected(result)
- }
- }
-
- MainPresenter.REQUEST_GAME_FILE -> FileBrowserHelper.runAfterExtensionCheck(
- this, uri, FileBrowserHelper.GAME_LIKE_EXTENSIONS
- ) { EmulationActivity.launch(this, result.data.toString(), false) }
-
- MainPresenter.REQUEST_WAD_FILE -> FileBrowserHelper.runAfterExtensionCheck(
- this, uri, FileBrowserHelper.WAD_EXTENSION
- ) { presenter.installWAD(result.data.toString()) }
-
- MainPresenter.REQUEST_WII_SAVE_FILE -> FileBrowserHelper.runAfterExtensionCheck(
- this, uri, FileBrowserHelper.BIN_EXTENSION
- ) { presenter.importWiiSave(result.data.toString()) }
-
- MainPresenter.REQUEST_NAND_BIN_FILE -> FileBrowserHelper.runAfterExtensionCheck(
- this, uri, FileBrowserHelper.BIN_EXTENSION
- ) { presenter.importNANDBin(result.data.toString()) }
- }
- } else {
- MainPresenter.skipRescanningLibrary()
- }
- }
-
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/FileBrowserHelper.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/FileBrowserHelper.java
index f13578d7ae..061d102be8 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/FileBrowserHelper.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/FileBrowserHelper.java
@@ -17,7 +17,6 @@ import com.nononsenseapps.filepicker.Utils;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.activities.CustomFilePickerActivity;
import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
-import org.dolphinemu.dolphinemu.ui.main.MainPresenter;
import java.io.File;
import java.util.ArrayList;
@@ -49,7 +48,8 @@ public final class FileBrowserHelper
public static final HashSet<String> WAD_EXTENSION = new HashSet<>(Collections.singletonList(
"wad"));
- public static void openDirectoryPicker(FragmentActivity activity, HashSet<String> extensions)
+ public static Intent createDirectoryPickerIntent(FragmentActivity activity,
+ HashSet<String> extensions)
{
Intent i = new Intent(activity, CustomFilePickerActivity.class);
@@ -60,7 +60,7 @@ public final class FileBrowserHelper
Environment.getExternalStorageDirectory().getPath());
i.putExtra(CustomFilePickerActivity.EXTRA_EXTENSIONS, extensions);
- activity.startActivityForResult(i, MainPresenter.REQUEST_DIRECTORY);
+ return i;
}
@Nullable