summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2023-06-14 12:47:14 -0700
committerGravatar GitHub2023-06-14 12:47:14 -0700
commita10a0919287072cb384df944fc19bb3574b0cc17 (patch)
tree8b9ebe471e65e6d801417b980b650f3b2372e66a
parentMerge pull request #10773 from 8bitDream/vcpkg (diff)
parentandroid: Adapt EmulationActivity to navigation component (diff)
downloadyuzu-a10a0919287072cb384df944fc19bb3574b0cc17.tar.gz
yuzu-a10a0919287072cb384df944fc19bb3574b0cc17.tar.xz
yuzu-a10a0919287072cb384df944fc19bb3574b0cc17.zip
Merge pull request #10726 from t895/emulation-nav-component
android: Adapt EmulationActivity to navigation component
-rw-r--r--src/android/app/build.gradle.kts1
-rw-r--r--src/android/app/src/main/AndroidManifest.xml1
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt64
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt5
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt32
-rw-r--r--src/android/app/src/main/res/layout/activity_emulation.xml16
-rw-r--r--src/android/app/src/main/res/navigation/emulation_navigation.xml18
-rw-r--r--src/android/app/src/main/res/navigation/home_navigation.xml14
-rw-r--r--src/android/build.gradle.kts9
9 files changed, 86 insertions, 74 deletions
diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts
index fe613d339..a637db78a 100644
--- a/src/android/app/build.gradle.kts
+++ b/src/android/app/build.gradle.kts
@@ -9,6 +9,7 @@ plugins {
9 id("org.jetbrains.kotlin.android") 9 id("org.jetbrains.kotlin.android")
10 id("kotlin-parcelize") 10 id("kotlin-parcelize")
11 kotlin("plugin.serialization") version "1.8.21" 11 kotlin("plugin.serialization") version "1.8.21"
12 id("androidx.navigation.safeargs.kotlin")
12} 13}
13 14
14/** 15/**
diff --git a/src/android/app/src/main/AndroidManifest.xml b/src/android/app/src/main/AndroidManifest.xml
index 55f62b4b9..b474ddb0b 100644
--- a/src/android/app/src/main/AndroidManifest.xml
+++ b/src/android/app/src/main/AndroidManifest.xml
@@ -53,7 +53,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
53 <activity 53 <activity
54 android:name="org.yuzu.yuzu_emu.activities.EmulationActivity" 54 android:name="org.yuzu.yuzu_emu.activities.EmulationActivity"
55 android:theme="@style/Theme.Yuzu.Main" 55 android:theme="@style/Theme.Yuzu.Main"
56 android:launchMode="singleTop"
57 android:screenOrientation="userLandscape" 56 android:screenOrientation="userLandscape"
58 android:exported="true"> 57 android:exported="true">
59 58
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
index 20a0394f5..caf660348 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
@@ -23,30 +23,25 @@ import androidx.appcompat.app.AppCompatActivity
23import androidx.core.view.WindowCompat 23import androidx.core.view.WindowCompat
24import androidx.core.view.WindowInsetsCompat 24import androidx.core.view.WindowInsetsCompat
25import androidx.core.view.WindowInsetsControllerCompat 25import androidx.core.view.WindowInsetsControllerCompat
26import androidx.lifecycle.Lifecycle 26import androidx.navigation.fragment.NavHostFragment
27import androidx.lifecycle.lifecycleScope
28import androidx.lifecycle.repeatOnLifecycle
29import androidx.window.layout.WindowInfoTracker
30import kotlinx.coroutines.Dispatchers
31import kotlinx.coroutines.launch
32import org.yuzu.yuzu_emu.NativeLibrary 27import org.yuzu.yuzu_emu.NativeLibrary
33import org.yuzu.yuzu_emu.R 28import org.yuzu.yuzu_emu.R
29import org.yuzu.yuzu_emu.databinding.ActivityEmulationBinding
34import org.yuzu.yuzu_emu.features.settings.model.SettingsViewModel 30import org.yuzu.yuzu_emu.features.settings.model.SettingsViewModel
35import org.yuzu.yuzu_emu.fragments.EmulationFragment
36import org.yuzu.yuzu_emu.model.Game 31import org.yuzu.yuzu_emu.model.Game
37import org.yuzu.yuzu_emu.utils.ControllerMappingHelper 32import org.yuzu.yuzu_emu.utils.ControllerMappingHelper
38import org.yuzu.yuzu_emu.utils.ForegroundService 33import org.yuzu.yuzu_emu.utils.ForegroundService
39import org.yuzu.yuzu_emu.utils.InputHandler 34import org.yuzu.yuzu_emu.utils.InputHandler
40import org.yuzu.yuzu_emu.utils.NfcReader 35import org.yuzu.yuzu_emu.utils.NfcReader
41import org.yuzu.yuzu_emu.utils.SerializableHelper.parcelable
42import org.yuzu.yuzu_emu.utils.ThemeHelper 36import org.yuzu.yuzu_emu.utils.ThemeHelper
43import kotlin.math.roundToInt 37import kotlin.math.roundToInt
44 38
45class EmulationActivity : AppCompatActivity(), SensorEventListener { 39class EmulationActivity : AppCompatActivity(), SensorEventListener {
40 private lateinit var binding: ActivityEmulationBinding
41
46 private var controllerMappingHelper: ControllerMappingHelper? = null 42 private var controllerMappingHelper: ControllerMappingHelper? = null
47 43
48 var isActivityRecreated = false 44 var isActivityRecreated = false
49 private var emulationFragment: EmulationFragment? = null
50 private lateinit var nfcReader: NfcReader 45 private lateinit var nfcReader: NfcReader
51 private lateinit var inputHandler: InputHandler 46 private lateinit var inputHandler: InputHandler
52 47
@@ -55,8 +50,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
55 private var motionTimestamp: Long = 0 50 private var motionTimestamp: Long = 0
56 private var flipMotionOrientation: Boolean = false 51 private var flipMotionOrientation: Boolean = false
57 52
58 private lateinit var game: Game
59
60 private val settingsViewModel: SettingsViewModel by viewModels() 53 private val settingsViewModel: SettingsViewModel by viewModels()
61 54
62 override fun onDestroy() { 55 override fun onDestroy() {
@@ -70,47 +63,31 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
70 settingsViewModel.settings.loadSettings() 63 settingsViewModel.settings.loadSettings()
71 64
72 super.onCreate(savedInstanceState) 65 super.onCreate(savedInstanceState)
73 if (savedInstanceState == null) { 66
74 // Get params we were passed 67 binding = ActivityEmulationBinding.inflate(layoutInflater)
75 game = intent.parcelable(EXTRA_SELECTED_GAME)!! 68 setContentView(binding.root)
76 isActivityRecreated = false 69
77 } else { 70 val navHostFragment =
78 isActivityRecreated = true 71 supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
79 restoreState(savedInstanceState) 72 val navController = navHostFragment.navController
80 } 73 navController
74 .setGraph(R.navigation.emulation_navigation, intent.extras)
75
76 isActivityRecreated = savedInstanceState != null
77
81 controllerMappingHelper = ControllerMappingHelper() 78 controllerMappingHelper = ControllerMappingHelper()
82 79
83 // Set these options now so that the SurfaceView the game renders into is the right size. 80 // Set these options now so that the SurfaceView the game renders into is the right size.
84 enableFullscreenImmersive() 81 enableFullscreenImmersive()
85 82
86 setContentView(R.layout.activity_emulation)
87 window.decorView.setBackgroundColor(getColor(android.R.color.black)) 83 window.decorView.setBackgroundColor(getColor(android.R.color.black))
88 84
89 // Find or create the EmulationFragment
90 emulationFragment =
91 supportFragmentManager.findFragmentById(R.id.frame_emulation_fragment) as EmulationFragment?
92 if (emulationFragment == null) {
93 emulationFragment = EmulationFragment.newInstance(game)
94 supportFragmentManager.beginTransaction()
95 .add(R.id.frame_emulation_fragment, emulationFragment!!)
96 .commit()
97 }
98 title = game.title
99
100 nfcReader = NfcReader(this) 85 nfcReader = NfcReader(this)
101 nfcReader.initialize() 86 nfcReader.initialize()
102 87
103 inputHandler = InputHandler() 88 inputHandler = InputHandler()
104 inputHandler.initialize() 89 inputHandler.initialize()
105 90
106 lifecycleScope.launch(Dispatchers.Main) {
107 lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
108 WindowInfoTracker.getOrCreate(this@EmulationActivity)
109 .windowLayoutInfo(this@EmulationActivity)
110 .collect { emulationFragment?.updateCurrentLayout(this@EmulationActivity, it) }
111 }
112 }
113
114 // Start a foreground service to prevent the app from getting killed in the background 91 // Start a foreground service to prevent the app from getting killed in the background
115 val startIntent = Intent(this, ForegroundService::class.java) 92 val startIntent = Intent(this, ForegroundService::class.java)
116 startForegroundService(startIntent) 93 startForegroundService(startIntent)
@@ -157,11 +134,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
157 nfcReader.onNewIntent(intent) 134 nfcReader.onNewIntent(intent)
158 } 135 }
159 136
160 override fun onSaveInstanceState(outState: Bundle) {
161 outState.putParcelable(EXTRA_SELECTED_GAME, game)
162 super.onSaveInstanceState(outState)
163 }
164
165 override fun dispatchKeyEvent(event: KeyEvent): Boolean { 137 override fun dispatchKeyEvent(event: KeyEvent): Boolean {
166 if (event.source and InputDevice.SOURCE_JOYSTICK != InputDevice.SOURCE_JOYSTICK && 138 if (event.source and InputDevice.SOURCE_JOYSTICK != InputDevice.SOURCE_JOYSTICK &&
167 event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD 139 event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD
@@ -248,10 +220,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
248 220
249 override fun onAccuracyChanged(sensor: Sensor, i: Int) {} 221 override fun onAccuracyChanged(sensor: Sensor, i: Int) {}
250 222
251 private fun restoreState(savedInstanceState: Bundle) {
252 game = savedInstanceState.parcelable(EXTRA_SELECTED_GAME)!!
253 }
254
255 private fun enableFullscreenImmersive() { 223 private fun enableFullscreenImmersive() {
256 WindowCompat.setDecorFitsSystemWindows(window, false) 224 WindowCompat.setDecorFitsSystemWindows(window, false)
257 225
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt
index 7f9e2e2d4..83d08841b 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt
@@ -16,6 +16,7 @@ import androidx.appcompat.app.AppCompatActivity
16import androidx.documentfile.provider.DocumentFile 16import androidx.documentfile.provider.DocumentFile
17import androidx.lifecycle.ViewModelProvider 17import androidx.lifecycle.ViewModelProvider
18import androidx.lifecycle.lifecycleScope 18import androidx.lifecycle.lifecycleScope
19import androidx.navigation.findNavController
19import androidx.preference.PreferenceManager 20import androidx.preference.PreferenceManager
20import androidx.recyclerview.widget.AsyncDifferConfig 21import androidx.recyclerview.widget.AsyncDifferConfig
21import androidx.recyclerview.widget.DiffUtil 22import androidx.recyclerview.widget.DiffUtil
@@ -23,6 +24,7 @@ import androidx.recyclerview.widget.ListAdapter
23import androidx.recyclerview.widget.RecyclerView 24import androidx.recyclerview.widget.RecyclerView
24import coil.load 25import coil.load
25import kotlinx.coroutines.launch 26import kotlinx.coroutines.launch
27import org.yuzu.yuzu_emu.HomeNavigationDirections
26import org.yuzu.yuzu_emu.NativeLibrary 28import org.yuzu.yuzu_emu.NativeLibrary
27import org.yuzu.yuzu_emu.R 29import org.yuzu.yuzu_emu.R
28import org.yuzu.yuzu_emu.YuzuApplication 30import org.yuzu.yuzu_emu.YuzuApplication
@@ -78,7 +80,8 @@ class GameAdapter(private val activity: AppCompatActivity) :
78 ) 80 )
79 .apply() 81 .apply()
80 82
81 EmulationActivity.launch(activity, holder.game) 83 val action = HomeNavigationDirections.actionGlobalEmulationActivity(holder.game)
84 view.findNavController().navigate(action)
82 } 85 }
83 86
84 inner class GameViewHolder(val binding: CardGameBinding) : 87 inner class GameViewHolder(val binding: CardGameBinding) :
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
index 9523381cd..02bfcdb1e 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
@@ -26,11 +26,18 @@ import androidx.core.view.ViewCompat
26import androidx.core.view.WindowInsetsCompat 26import androidx.core.view.WindowInsetsCompat
27import androidx.core.view.updatePadding 27import androidx.core.view.updatePadding
28import androidx.fragment.app.Fragment 28import androidx.fragment.app.Fragment
29import androidx.lifecycle.Lifecycle
30import androidx.lifecycle.lifecycleScope
31import androidx.lifecycle.repeatOnLifecycle
32import androidx.navigation.fragment.navArgs
29import androidx.preference.PreferenceManager 33import androidx.preference.PreferenceManager
30import androidx.window.layout.FoldingFeature 34import androidx.window.layout.FoldingFeature
35import androidx.window.layout.WindowInfoTracker
31import androidx.window.layout.WindowLayoutInfo 36import androidx.window.layout.WindowLayoutInfo
32import com.google.android.material.dialog.MaterialAlertDialogBuilder 37import com.google.android.material.dialog.MaterialAlertDialogBuilder
33import com.google.android.material.slider.Slider 38import com.google.android.material.slider.Slider
39import kotlinx.coroutines.Dispatchers
40import kotlinx.coroutines.launch
34import org.yuzu.yuzu_emu.NativeLibrary 41import org.yuzu.yuzu_emu.NativeLibrary
35import org.yuzu.yuzu_emu.R 42import org.yuzu.yuzu_emu.R
36import org.yuzu.yuzu_emu.YuzuApplication 43import org.yuzu.yuzu_emu.YuzuApplication
@@ -41,9 +48,7 @@ import org.yuzu.yuzu_emu.features.settings.model.IntSetting
41import org.yuzu.yuzu_emu.features.settings.model.Settings 48import org.yuzu.yuzu_emu.features.settings.model.Settings
42import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity 49import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity
43import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile 50import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
44import org.yuzu.yuzu_emu.model.Game
45import org.yuzu.yuzu_emu.utils.* 51import org.yuzu.yuzu_emu.utils.*
46import org.yuzu.yuzu_emu.utils.SerializableHelper.parcelable
47 52
48class EmulationFragment : Fragment(), SurfaceHolder.Callback { 53class EmulationFragment : Fragment(), SurfaceHolder.Callback {
49 private lateinit var preferences: SharedPreferences 54 private lateinit var preferences: SharedPreferences
@@ -54,7 +59,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
54 private var _binding: FragmentEmulationBinding? = null 59 private var _binding: FragmentEmulationBinding? = null
55 private val binding get() = _binding!! 60 private val binding get() = _binding!!
56 61
57 private lateinit var game: Game 62 val args by navArgs<EmulationFragmentArgs>()
58 63
59 override fun onAttach(context: Context) { 64 override fun onAttach(context: Context) {
60 super.onAttach(context) 65 super.onAttach(context)
@@ -75,8 +80,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
75 // So this fragment doesn't restart on configuration changes; i.e. rotation. 80 // So this fragment doesn't restart on configuration changes; i.e. rotation.
76 retainInstance = true 81 retainInstance = true
77 preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) 82 preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
78 game = requireArguments().parcelable(EmulationActivity.EXTRA_SELECTED_GAME)!! 83 emulationState = EmulationState(args.game.path)
79 emulationState = EmulationState(game.path)
80 } 84 }
81 85
82 /** 86 /**
@@ -100,7 +104,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
100 updateShowFpsOverlay() 104 updateShowFpsOverlay()
101 105
102 binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.text_game_title).text = 106 binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.text_game_title).text =
103 game.title 107 args.game.title
104 binding.inGameMenu.setNavigationItemSelectedListener { 108 binding.inGameMenu.setNavigationItemSelectedListener {
105 when (it.itemId) { 109 when (it.itemId) {
106 R.id.menu_pause_emulation -> { 110 R.id.menu_pause_emulation -> {
@@ -153,6 +157,14 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
153 if (binding.drawerLayout.isOpen) binding.drawerLayout.close() else binding.drawerLayout.open() 157 if (binding.drawerLayout.isOpen) binding.drawerLayout.close() else binding.drawerLayout.open()
154 } 158 }
155 }) 159 })
160
161 viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) {
162 lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
163 WindowInfoTracker.getOrCreate(requireContext())
164 .windowLayoutInfo(requireActivity())
165 .collect { updateCurrentLayout(requireActivity() as EmulationActivity, it) }
166 }
167 }
156 } 168 }
157 169
158 override fun onResume() { 170 override fun onResume() {
@@ -601,13 +613,5 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
601 613
602 companion object { 614 companion object {
603 private val perfStatsUpdateHandler = Handler(Looper.myLooper()!!) 615 private val perfStatsUpdateHandler = Handler(Looper.myLooper()!!)
604
605 fun newInstance(game: Game): EmulationFragment {
606 val args = Bundle()
607 args.putParcelable(EmulationActivity.EXTRA_SELECTED_GAME, game)
608 val fragment = EmulationFragment()
609 fragment.arguments = args
610 return fragment
611 }
612 } 616 }
613} 617}
diff --git a/src/android/app/src/main/res/layout/activity_emulation.xml b/src/android/app/src/main/res/layout/activity_emulation.xml
index f6360a65b..139065d3d 100644
--- a/src/android/app/src/main/res/layout/activity_emulation.xml
+++ b/src/android/app/src/main/res/layout/activity_emulation.xml
@@ -1,13 +1,9 @@
1<FrameLayout 1<androidx.fragment.app.FragmentContainerView
2 xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:android="http://schemas.android.com/apk/res/android"
3 android:id="@+id/frame_content" 3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 android:id="@+id/fragment_container"
5 android:name="androidx.navigation.fragment.NavHostFragment"
4 android:layout_width="match_parent" 6 android:layout_width="match_parent"
5 android:layout_height="match_parent" 7 android:layout_height="match_parent"
6 android:keepScreenOn="true"> 8 android:keepScreenOn="true"
7 9 app:defaultNavHost="true" />
8 <FrameLayout
9 android:id="@+id/frame_emulation_fragment"
10 android:layout_width="match_parent"
11 android:layout_height="match_parent" />
12
13</FrameLayout>
diff --git a/src/android/app/src/main/res/navigation/emulation_navigation.xml b/src/android/app/src/main/res/navigation/emulation_navigation.xml
new file mode 100644
index 000000000..8208f4c2c
--- /dev/null
+++ b/src/android/app/src/main/res/navigation/emulation_navigation.xml
@@ -0,0 +1,18 @@
1<?xml version="1.0" encoding="utf-8"?>
2<navigation xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools"
5 android:id="@+id/emulation_navigation"
6 app:startDestination="@id/emulationFragment">
7
8 <fragment
9 android:id="@+id/emulationFragment"
10 android:name="org.yuzu.yuzu_emu.fragments.EmulationFragment"
11 android:label="fragment_emulation"
12 tools:layout="@layout/fragment_emulation" >
13 <argument
14 android:name="game"
15 app:argType="org.yuzu.yuzu_emu.model.Game" />
16 </fragment>
17
18</navigation>
diff --git a/src/android/app/src/main/res/navigation/home_navigation.xml b/src/android/app/src/main/res/navigation/home_navigation.xml
index 48072683e..fcebba726 100644
--- a/src/android/app/src/main/res/navigation/home_navigation.xml
+++ b/src/android/app/src/main/res/navigation/home_navigation.xml
@@ -56,4 +56,18 @@
56 android:name="org.yuzu.yuzu_emu.fragments.LicensesFragment" 56 android:name="org.yuzu.yuzu_emu.fragments.LicensesFragment"
57 android:label="LicensesFragment" /> 57 android:label="LicensesFragment" />
58 58
59 <activity
60 android:id="@+id/emulationActivity"
61 android:name="org.yuzu.yuzu_emu.activities.EmulationActivity"
62 android:label="EmulationActivity">
63 <argument
64 android:name="game"
65 app:argType="org.yuzu.yuzu_emu.model.Game" />
66 </activity>
67
68 <action
69 android:id="@+id/action_global_emulationActivity"
70 app:destination="@id/emulationActivity"
71 app:launchSingleTop="true" />
72
59</navigation> 73</navigation>
diff --git a/src/android/build.gradle.kts b/src/android/build.gradle.kts
index e19e8ce58..80f370c16 100644
--- a/src/android/build.gradle.kts
+++ b/src/android/build.gradle.kts
@@ -11,3 +11,12 @@ plugins {
11tasks.register("clean").configure { 11tasks.register("clean").configure {
12 delete(rootProject.buildDir) 12 delete(rootProject.buildDir)
13} 13}
14
15buildscript {
16 repositories {
17 google()
18 }
19 dependencies {
20 classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.6.0")
21 }
22}