mirror of
https://github.com/yuzu-mirror/yuzu
synced 2024-11-23 15:53:03 +00:00
android: Add user directory shortcut
This commit is contained in:
parent
265b9139e0
commit
912bf6a0c6
6 changed files with 140 additions and 25 deletions
|
@ -15,6 +15,7 @@
|
|||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
|
||||
<application
|
||||
android:name="org.yuzu.yuzu_emu.YuzuApplication"
|
||||
|
|
|
@ -15,23 +15,29 @@ import java.io.File
|
|||
fun Context.getPublicFilesDir() : File = getExternalFilesDir(null) ?: filesDir
|
||||
|
||||
class YuzuApplication : Application() {
|
||||
private fun createNotificationChannel() {
|
||||
// Create the NotificationChannel, but only on API 26+ because
|
||||
// the NotificationChannel class is new and not in the support library
|
||||
val name: CharSequence = getString(R.string.app_notification_channel_name)
|
||||
val description = getString(R.string.app_notification_channel_description)
|
||||
val channel = NotificationChannel(
|
||||
getString(R.string.app_notification_channel_id),
|
||||
name,
|
||||
private fun createNotificationChannels() {
|
||||
val emulationChannel = NotificationChannel(
|
||||
getString(R.string.emulation_notification_channel_id),
|
||||
getString(R.string.emulation_notification_channel_name),
|
||||
NotificationManager.IMPORTANCE_LOW
|
||||
)
|
||||
channel.description = description
|
||||
channel.setSound(null, null)
|
||||
channel.vibrationPattern = null
|
||||
emulationChannel.description = getString(R.string.emulation_notification_channel_description)
|
||||
emulationChannel.setSound(null, null)
|
||||
emulationChannel.vibrationPattern = null
|
||||
|
||||
val noticeChannel = NotificationChannel(
|
||||
getString(R.string.notice_notification_channel_id),
|
||||
getString(R.string.notice_notification_channel_name),
|
||||
NotificationManager.IMPORTANCE_HIGH
|
||||
)
|
||||
noticeChannel.description = getString(R.string.notice_notification_channel_description)
|
||||
noticeChannel.setSound(null, null)
|
||||
|
||||
// Register the channel with the system; you can't change the importance
|
||||
// or other notification behaviors after this
|
||||
val notificationManager = getSystemService(NotificationManager::class.java)
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
notificationManager.createNotificationChannel(emulationChannel)
|
||||
notificationManager.createNotificationChannel(noticeChannel)
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
|
@ -42,8 +48,7 @@ class YuzuApplication : Application() {
|
|||
GpuDriverHelper.initializeDriverParameters(applicationContext)
|
||||
NativeLibrary.logDeviceInfo()
|
||||
|
||||
// TODO(bunnei): Disable notifications until we support app suspension.
|
||||
//createNotificationChannel();
|
||||
createNotificationChannels();
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -3,14 +3,21 @@
|
|||
|
||||
package org.yuzu.yuzu_emu.fragments
|
||||
|
||||
import android.Manifest
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.provider.DocumentsContract
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
|
@ -19,6 +26,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter
|
||||
import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding
|
||||
import org.yuzu.yuzu_emu.features.DocumentProvider
|
||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity
|
||||
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
|
||||
import org.yuzu.yuzu_emu.model.HomeSetting
|
||||
|
@ -49,6 +57,11 @@ class HomeSettingsFragment : Fragment() {
|
|||
R.string.settings_description,
|
||||
R.drawable.ic_settings
|
||||
) { SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "") },
|
||||
HomeSetting(
|
||||
R.string.open_user_folder,
|
||||
R.string.open_user_folder_description,
|
||||
R.drawable.ic_folder
|
||||
) { openFileManager() },
|
||||
HomeSetting(
|
||||
R.string.install_gpu_driver,
|
||||
R.string.install_gpu_driver_description,
|
||||
|
@ -84,6 +97,82 @@ class HomeSettingsFragment : Fragment() {
|
|||
_binding = null
|
||||
}
|
||||
|
||||
private fun openFileManager() {
|
||||
// First, try to open the user data folder directly
|
||||
try {
|
||||
startActivity(getFileManagerIntentOnDocumentProvider(Intent.ACTION_VIEW))
|
||||
return
|
||||
} catch (_: ActivityNotFoundException) {}
|
||||
|
||||
try {
|
||||
startActivity(getFileManagerIntentOnDocumentProvider("android.provider.action.BROWSE"))
|
||||
return
|
||||
} catch (_: ActivityNotFoundException) {}
|
||||
|
||||
// Just try to open the file manager, try the package name used on "normal" phones
|
||||
try {
|
||||
startActivity(getFileManagerIntent("com.google.android.documentsui"))
|
||||
showNoLinkNotification()
|
||||
return
|
||||
} catch (_: ActivityNotFoundException) {}
|
||||
|
||||
try {
|
||||
// Next, try the AOSP package name
|
||||
startActivity(getFileManagerIntent("com.android.documentsui"))
|
||||
showNoLinkNotification()
|
||||
return
|
||||
} catch (_: ActivityNotFoundException) {}
|
||||
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
resources.getString(R.string.no_file_manager),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
|
||||
private fun getFileManagerIntent(packageName: String): Intent {
|
||||
// Fragile, but some phones don't expose the system file manager in any better way
|
||||
val intent = Intent(Intent.ACTION_MAIN)
|
||||
intent.setClassName(packageName, "com.android.documentsui.files.FilesActivity")
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
return intent
|
||||
}
|
||||
|
||||
private fun getFileManagerIntentOnDocumentProvider(action: String): Intent {
|
||||
val authority = "${requireContext().packageName}.user"
|
||||
val intent = Intent(action)
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT)
|
||||
intent.data = DocumentsContract.buildRootUri(authority, DocumentProvider.ROOT_ID)
|
||||
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or Intent.FLAG_GRANT_PREFIX_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
return intent
|
||||
}
|
||||
|
||||
private fun showNoLinkNotification() {
|
||||
val builder = NotificationCompat.Builder(requireContext(), getString(R.string.notice_notification_channel_id))
|
||||
.setSmallIcon(R.drawable.ic_stat_notification_logo)
|
||||
.setContentTitle(getString(R.string.notification_no_directory_link))
|
||||
.setContentText(getString(R.string.notification_no_directory_link_description))
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setAutoCancel(true)
|
||||
// TODO: Make the click action for this notification lead to a help article
|
||||
|
||||
with(NotificationManagerCompat.from(requireContext())) {
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
requireContext(),
|
||||
Manifest.permission.POST_NOTIFICATIONS
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
resources.getString(R.string.notification_permission_not_granted),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
return
|
||||
}
|
||||
notify(0, builder.build())
|
||||
}
|
||||
}
|
||||
|
||||
private fun driverInstaller() {
|
||||
// Get the driver name for the dialog message.
|
||||
var driverName = GpuDriverHelper.customDriverName
|
||||
|
|
|
@ -4,11 +4,13 @@
|
|||
package org.yuzu.yuzu_emu.fragments
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
|
@ -63,6 +65,10 @@ class SetupFragment : Fragment() {
|
|||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
pushNotificationPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS)
|
||||
}
|
||||
|
||||
mainActivity = requireActivity() as MainActivity
|
||||
|
||||
homeViewModel.setNavigationVisibility(false)
|
||||
|
@ -219,6 +225,11 @@ class SetupFragment : Fragment() {
|
|||
_binding = null
|
||||
}
|
||||
|
||||
private val pushNotificationPermissionLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
|
||||
// TODO: Show proper notification request reason and confirmation
|
||||
}
|
||||
|
||||
private fun finishSetup() {
|
||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit()
|
||||
.putBoolean(Settings.PREF_FIRST_APP_LAUNCH, false)
|
||||
|
|
|
@ -29,10 +29,10 @@ class ForegroundService : Service() {
|
|||
PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
val builder =
|
||||
NotificationCompat.Builder(this, getString(R.string.app_notification_channel_id))
|
||||
NotificationCompat.Builder(this, getString(R.string.emulation_notification_channel_id))
|
||||
.setSmallIcon(R.drawable.ic_stat_notification_logo)
|
||||
.setContentTitle(getString(R.string.app_name))
|
||||
.setContentText(getString(R.string.app_notification_running))
|
||||
.setContentText(getString(R.string.emulation_notification_running))
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
.setOngoing(true)
|
||||
.setVibrate(null)
|
||||
|
|
|
@ -4,10 +4,14 @@
|
|||
<!-- General application strings -->
|
||||
<string name="app_name" translatable="false">yuzu</string>
|
||||
<string name="app_disclaimer">This software will run games for the Nintendo Switch game console. No game titles or keys are included.<br /><br />Before you begin, please locate your <![CDATA[<b> prod.keys </b>]]> file on your device storage.<br /><br /><![CDATA[<a href="https://yuzu-emu.org/help/quickstart">Learn more</a>]]></string>
|
||||
<string name="app_notification_channel_name" translatable="false">yuzu</string>
|
||||
<string name="app_notification_channel_id" translatable="false">yuzu</string>
|
||||
<string name="app_notification_channel_description">yuzu Switch emulator notifications</string>
|
||||
<string name="app_notification_running">yuzu is running</string>
|
||||
<string name="emulation_notification_channel_name">Emulation is Active</string>
|
||||
<string name="emulation_notification_channel_id" translatable="false">emulationIsActive</string>
|
||||
<string name="emulation_notification_channel_description">Shows a persistent notification when emulation is running.</string>
|
||||
<string name="emulation_notification_running">yuzu is running</string>
|
||||
<string name="notice_notification_channel_name">Notices and errors</string>
|
||||
<string name="notice_notification_channel_id" translatable="false">noticesAndErrors</string>
|
||||
<string name="notice_notification_channel_description">Shows notifications when something goes wrong.</string>
|
||||
<string name="notification_permission_not_granted">Notification permission not granted!</string>
|
||||
|
||||
<!-- Setup strings -->
|
||||
<string name="welcome">Welcome!</string>
|
||||
|
@ -29,14 +33,14 @@
|
|||
<!-- Home strings -->
|
||||
<string name="home_games">Games</string>
|
||||
<string name="home_settings">Settings</string>
|
||||
<string name="select_games_folder">Select Games Folder</string>
|
||||
<string name="select_games_folder">Select games folder</string>
|
||||
<string name="select_games_folder_description">Allows yuzu to populate the games list</string>
|
||||
<string name="add_games_warning">Skip selecting games folder?</string>
|
||||
<string name="add_games_warning_description">Games won\'t be displayed in the Games list if a folder isn\'t selected.</string>
|
||||
<string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
|
||||
<string name="home_search_games">Search Games</string>
|
||||
<string name="games_dir_selected">Games directory selected</string>
|
||||
<string name="install_prod_keys">Install Prod.keys</string>
|
||||
<string name="install_prod_keys">Install prod.keys</string>
|
||||
<string name="install_prod_keys_description">Required to decrypt retail games</string>
|
||||
<string name="install_prod_keys_warning">Skip adding keys?</string>
|
||||
<string name="install_prod_keys_warning_description">Valid keys are required to emulate retail games. Only homebrew apps will function if you continue.</string>
|
||||
|
@ -44,16 +48,21 @@
|
|||
<string name="warning_help">Help</string>
|
||||
<string name="warning_skip">Skip</string>
|
||||
<string name="warning_cancel">Cancel</string>
|
||||
<string name="install_amiibo_keys">Install Amiibo Keys</string>
|
||||
<string name="install_amiibo_keys">Install Amiibo keys</string>
|
||||
<string name="install_amiibo_keys_description">Required to use Amiibo in game</string>
|
||||
<string name="invalid_keys_file">Invalid keys file selected</string>
|
||||
<string name="install_keys_success">Keys successfully installed</string>
|
||||
<string name="install_keys_failure">Keys file (prod.keys) is invalid</string>
|
||||
<string name="install_amiibo_keys_failure">Keys file (key_retail.bin) is invalid</string>
|
||||
<string name="install_gpu_driver">Install GPU Driver</string>
|
||||
<string name="install_gpu_driver">Install GPU driver</string>
|
||||
<string name="install_gpu_driver_description">Install alternative drivers for potentially better performance or accuracy</string>
|
||||
<string name="advanced_settings">Advanced Settings</string>
|
||||
<string name="advanced_settings">Advanced settings</string>
|
||||
<string name="settings_description">Configure emulator settings</string>
|
||||
<string name="open_user_folder">Open yuzu folder</string>
|
||||
<string name="open_user_folder_description">Manage yuzu\'s internal files</string>
|
||||
<string name="no_file_manager">No file manager found</string>
|
||||
<string name="notification_no_directory_link">Couldn\'t open yuzu directory</string>
|
||||
<string name="notification_no_directory_link_description">Please locate the user folder with the file manager\'s side panel manually.</string>
|
||||
|
||||
<!-- General settings strings -->
|
||||
<string name="frame_limit_enable">Enable limit speed</string>
|
||||
|
|
Loading…
Reference in a new issue