diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/MessageDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/MessageDialogFragment.kt
new file mode 100644
index 0000000000..2db38fdc2e
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/MessageDialogFragment.kt
@@ -0,0 +1,62 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.yuzu.yuzu_emu.fragments
+
+import android.app.Dialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import androidx.fragment.app.DialogFragment
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import org.yuzu.yuzu_emu.R
+
+class MessageDialogFragment : DialogFragment() {
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val titleId = requireArguments().getInt(TITLE)
+ val descriptionId = requireArguments().getInt(DESCRIPTION)
+ val helpLinkId = requireArguments().getInt(HELP_LINK)
+
+ val dialog = MaterialAlertDialogBuilder(requireContext())
+ .setPositiveButton(R.string.close, null)
+ .setTitle(titleId)
+ .setMessage(descriptionId)
+
+ if (helpLinkId != 0) {
+ dialog.setNeutralButton(R.string.learn_more) { _, _ ->
+ openLink(getString(helpLinkId))
+ }
+ }
+
+ return dialog.show()
+ }
+
+ private fun openLink(link: String) {
+ val intent = Intent(Intent.ACTION_VIEW, Uri.parse(link))
+ startActivity(intent)
+ }
+
+ companion object {
+ const val TAG = "MessageDialogFragment"
+
+ private const val TITLE = "Title"
+ private const val DESCRIPTION = "Description"
+ private const val HELP_LINK = "Link"
+
+ fun newInstance(
+ titleId: Int,
+ descriptionId: Int,
+ helpLinkId: Int = 0
+ ): MessageDialogFragment {
+ val dialog = MessageDialogFragment()
+ val bundle = Bundle()
+ bundle.apply {
+ putInt(TITLE, titleId)
+ putInt(DESCRIPTION, descriptionId)
+ putInt(HELP_LINK, helpLinkId)
+ }
+ dialog.arguments = bundle
+ return dialog
+ }
+ }
+}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
index b1329db74c..f8bca11bb6 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
@@ -37,6 +37,7 @@ import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding
import org.yuzu.yuzu_emu.features.settings.model.Settings
import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
+import org.yuzu.yuzu_emu.fragments.MessageDialogFragment
import org.yuzu.yuzu_emu.model.GamesViewModel
import org.yuzu.yuzu_emu.model.HomeViewModel
import org.yuzu.yuzu_emu.utils.*
@@ -251,11 +252,9 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
if (result == null)
return@registerForActivityResult
- val takeFlags =
- Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
contentResolver.takePersistableUriPermission(
result,
- takeFlags
+ Intent.FLAG_GRANT_READ_URI_PERMISSION
)
// When a new directory is picked, we currently will reset the existing games
@@ -279,19 +278,16 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
return@registerForActivityResult
if (!FileUtil.hasExtension(result.toString(), "keys")) {
- Toast.makeText(
- applicationContext,
- R.string.invalid_keys_file,
- Toast.LENGTH_SHORT
- ).show()
+ MessageDialogFragment.newInstance(
+ R.string.reading_keys_failure,
+ R.string.install_keys_failure_extension_description
+ ).show(supportFragmentManager, MessageDialogFragment.TAG)
return@registerForActivityResult
}
- val takeFlags =
- Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
contentResolver.takePersistableUriPermission(
result,
- takeFlags
+ Intent.FLAG_GRANT_READ_URI_PERMISSION
)
val dstPath = DirectoryInitialization.userDirectory + "/keys/"
@@ -310,11 +306,11 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
).show()
gamesViewModel.reloadGames(true)
} else {
- Toast.makeText(
- applicationContext,
- R.string.install_keys_failure,
- Toast.LENGTH_LONG
- ).show()
+ MessageDialogFragment.newInstance(
+ R.string.invalid_keys_error,
+ R.string.install_keys_failure_description,
+ R.string.dumping_keys_quickstart_link
+ ).show(supportFragmentManager, MessageDialogFragment.TAG)
}
}
}
@@ -325,19 +321,16 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
return@registerForActivityResult
if (!FileUtil.hasExtension(result.toString(), "bin")) {
- Toast.makeText(
- applicationContext,
- R.string.invalid_keys_file,
- Toast.LENGTH_SHORT
- ).show()
+ MessageDialogFragment.newInstance(
+ R.string.reading_keys_failure,
+ R.string.install_keys_failure_extension_description
+ ).show(supportFragmentManager, MessageDialogFragment.TAG)
return@registerForActivityResult
}
- val takeFlags =
- Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
contentResolver.takePersistableUriPermission(
result,
- takeFlags
+ Intent.FLAG_GRANT_READ_URI_PERMISSION
)
val dstPath = DirectoryInitialization.userDirectory + "/keys/"
@@ -355,11 +348,11 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
Toast.LENGTH_SHORT
).show()
} else {
- Toast.makeText(
- applicationContext,
- R.string.install_amiibo_keys_failure,
- Toast.LENGTH_LONG
- ).show()
+ MessageDialogFragment.newInstance(
+ R.string.invalid_keys_error,
+ R.string.install_keys_failure_description,
+ R.string.dumping_keys_quickstart_link
+ ).show(supportFragmentManager, MessageDialogFragment.TAG)
}
}
}
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 5e44551ad0..afc681feda 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -64,8 +64,15 @@
Required to use Amiibo in game
Invalid keys file selected
Keys successfully installed
- Keys file (prod.keys) is invalid
- Keys file (key_retail.bin) is invalid
+ Error reading encryption keys
+
+ 1. Verify your keys have the .keys extension.\n\n
+ 2. Keys must not be stored in the Downloads folder.\n\n
+ Resolve the issue(s) and try again.
+
+ Invalid encryption keys
+ https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys
+ The selected file is incorrect or corrupt. Please redump your keys.
Install GPU driver
Install alternative drivers for potentially better performance or accuracy
Advanced settings
@@ -164,6 +171,8 @@
Reset all settings?
All Advanced Settings will be reset to their default configuration. This can not be undone.
Settings reset
+ Close
+ Learn More
Select GPU driver