diff options
| author | 2023-05-28 22:52:36 -0400 | |
|---|---|---|
| committer | 2023-06-03 00:06:04 -0700 | |
| commit | 7de86266fd4e34501091dca934c6ad5719b2bdcb (patch) | |
| tree | af500ccb92d377f6256d5eb4ad09070bfbdd8e85 /src/android | |
| parent | android: DIsable FPS counter by default (diff) | |
| download | yuzu-7de86266fd4e34501091dca934c6ad5719b2bdcb.tar.gz yuzu-7de86266fd4e34501091dca934c6ad5719b2bdcb.tar.xz yuzu-7de86266fd4e34501091dca934c6ad5719b2bdcb.zip | |
android: Show notification permission page during setup
Diffstat (limited to 'src/android')
4 files changed, 151 insertions, 59 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/PermissionDeniedDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/PermissionDeniedDialogFragment.kt new file mode 100644 index 000000000..3478b9250 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/PermissionDeniedDialogFragment.kt | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.fragments | ||
| 5 | |||
| 6 | import android.app.Dialog | ||
| 7 | import android.content.DialogInterface | ||
| 8 | import android.content.Intent | ||
| 9 | import android.net.Uri | ||
| 10 | import android.os.Bundle | ||
| 11 | import android.provider.Settings | ||
| 12 | import androidx.fragment.app.DialogFragment | ||
| 13 | import com.google.android.material.dialog.MaterialAlertDialogBuilder | ||
| 14 | import org.yuzu.yuzu_emu.R | ||
| 15 | |||
| 16 | class PermissionDeniedDialogFragment : DialogFragment() { | ||
| 17 | override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { | ||
| 18 | return MaterialAlertDialogBuilder(requireContext()) | ||
| 19 | .setPositiveButton(R.string.home_settings) { _: DialogInterface?, _: Int -> | ||
| 20 | openSettings() | ||
| 21 | } | ||
| 22 | .setNegativeButton(android.R.string.cancel, null) | ||
| 23 | .setTitle(R.string.permission_denied) | ||
| 24 | .setMessage(R.string.permission_denied_description) | ||
| 25 | .show() | ||
| 26 | } | ||
| 27 | |||
| 28 | private fun openSettings() { | ||
| 29 | val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) | ||
| 30 | val uri = Uri.fromParts("package", requireActivity().packageName, null) | ||
| 31 | intent.data = uri | ||
| 32 | startActivity(intent) | ||
| 33 | } | ||
| 34 | |||
| 35 | companion object { | ||
| 36 | const val TAG = "PermissionDeniedDialogFragment" | ||
| 37 | } | ||
| 38 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt index 153622072..258773380 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.fragments | 4 | package org.yuzu.yuzu_emu.fragments |
| 5 | 5 | ||
| 6 | import android.Manifest | ||
| 6 | import android.content.Intent | 7 | import android.content.Intent |
| 7 | import android.os.Build | 8 | import android.os.Build |
| 8 | import android.os.Bundle | 9 | import android.os.Bundle |
| @@ -11,7 +12,9 @@ import android.view.View | |||
| 11 | import android.view.ViewGroup | 12 | import android.view.ViewGroup |
| 12 | import androidx.activity.OnBackPressedCallback | 13 | import androidx.activity.OnBackPressedCallback |
| 13 | import androidx.activity.result.contract.ActivityResultContracts | 14 | import androidx.activity.result.contract.ActivityResultContracts |
| 15 | import androidx.annotation.RequiresApi | ||
| 14 | import androidx.appcompat.app.AppCompatActivity | 16 | import androidx.appcompat.app.AppCompatActivity |
| 17 | import androidx.core.app.NotificationManagerCompat | ||
| 15 | import androidx.core.content.ContextCompat | 18 | import androidx.core.content.ContextCompat |
| 16 | import androidx.core.view.ViewCompat | 19 | import androidx.core.view.ViewCompat |
| 17 | import androidx.core.view.WindowInsetsCompat | 20 | import androidx.core.view.WindowInsetsCompat |
| @@ -65,10 +68,6 @@ class SetupFragment : Fragment() { | |||
| 65 | } | 68 | } |
| 66 | 69 | ||
| 67 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | 70 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
| 68 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { | ||
| 69 | pushNotificationPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS) | ||
| 70 | } | ||
| 71 | |||
| 72 | mainActivity = requireActivity() as MainActivity | 71 | mainActivity = requireActivity() as MainActivity |
| 73 | 72 | ||
| 74 | homeViewModel.setNavigationVisibility(visible = false, animated = false) | 73 | homeViewModel.setNavigationVisibility(visible = false, animated = false) |
| @@ -88,60 +87,93 @@ class SetupFragment : Fragment() { | |||
| 88 | requireActivity().window.navigationBarColor = | 87 | requireActivity().window.navigationBarColor = |
| 89 | ContextCompat.getColor(requireContext(), android.R.color.transparent) | 88 | ContextCompat.getColor(requireContext(), android.R.color.transparent) |
| 90 | 89 | ||
| 91 | val pages = listOf( | 90 | val pages = mutableListOf<SetupPage>() |
| 92 | SetupPage( | 91 | pages.apply { |
| 93 | R.drawable.ic_yuzu_title, | 92 | add( |
| 94 | R.string.welcome, | 93 | SetupPage( |
| 95 | R.string.welcome_description, | 94 | R.drawable.ic_yuzu_title, |
| 96 | 0, | 95 | R.string.welcome, |
| 97 | true, | 96 | R.string.welcome_description, |
| 98 | R.string.get_started, | 97 | 0, |
| 99 | { pageForward() }, | 98 | true, |
| 100 | false | 99 | R.string.get_started, |
| 101 | ), | 100 | { pageForward() }, |
| 102 | SetupPage( | 101 | false |
| 103 | R.drawable.ic_key, | 102 | ) |
| 104 | R.string.keys, | 103 | ) |
| 105 | R.string.keys_description, | 104 | |
| 106 | R.drawable.ic_add, | 105 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { |
| 107 | true, | 106 | add( |
| 108 | R.string.select_keys, | 107 | SetupPage( |
| 109 | { mainActivity.getProdKey.launch(arrayOf("*/*")) }, | 108 | R.drawable.ic_notification, |
| 110 | true, | 109 | R.string.notifications, |
| 111 | R.string.install_prod_keys_warning, | 110 | R.string.notifications_description, |
| 112 | R.string.install_prod_keys_warning_description, | 111 | 0, |
| 113 | R.string.install_prod_keys_warning_help, | 112 | false, |
| 114 | { File(DirectoryInitialization.userDirectory + "/keys/prod.keys").exists() } | 113 | R.string.give_permission, |
| 115 | ), | 114 | { permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) }, |
| 116 | SetupPage( | 115 | true, |
| 117 | R.drawable.ic_controller, | 116 | R.string.notification_warning, |
| 118 | R.string.games, | 117 | R.string.notification_warning_description, |
| 119 | R.string.games_description, | 118 | 0, |
| 120 | R.drawable.ic_add, | 119 | { |
| 121 | true, | 120 | NotificationManagerCompat.from(requireContext()) |
| 122 | R.string.add_games, | 121 | .areNotificationsEnabled() |
| 123 | { mainActivity.getGamesDirectory.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data) }, | 122 | } |
| 124 | true, | 123 | ) |
| 125 | R.string.add_games_warning, | 124 | ) |
| 126 | R.string.add_games_warning_description, | 125 | } |
| 127 | R.string.add_games_warning_help, | 126 | |
| 128 | { | 127 | add( |
| 129 | val preferences = | 128 | SetupPage( |
| 130 | PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | 129 | R.drawable.ic_key, |
| 131 | preferences.getString(GameHelper.KEY_GAME_PATH, "")!!.isNotEmpty() | 130 | R.string.keys, |
| 132 | } | 131 | R.string.keys_description, |
| 133 | ), | 132 | R.drawable.ic_add, |
| 134 | SetupPage( | 133 | true, |
| 135 | R.drawable.ic_check, | 134 | R.string.select_keys, |
| 136 | R.string.done, | 135 | { mainActivity.getProdKey.launch(arrayOf("*/*")) }, |
| 137 | R.string.done_description, | 136 | true, |
| 138 | R.drawable.ic_arrow_forward, | 137 | R.string.install_prod_keys_warning, |
| 139 | false, | 138 | R.string.install_prod_keys_warning_description, |
| 140 | R.string.text_continue, | 139 | R.string.install_prod_keys_warning_help, |
| 141 | { finishSetup() }, | 140 | { File(DirectoryInitialization.userDirectory + "/keys/prod.keys").exists() } |
| 142 | false | 141 | ) |
| 143 | ) | 142 | ) |
| 144 | ) | 143 | add( |
| 144 | SetupPage( | ||
| 145 | R.drawable.ic_controller, | ||
| 146 | R.string.games, | ||
| 147 | R.string.games_description, | ||
| 148 | R.drawable.ic_add, | ||
| 149 | true, | ||
| 150 | R.string.add_games, | ||
| 151 | { mainActivity.getGamesDirectory.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data) }, | ||
| 152 | true, | ||
| 153 | R.string.add_games_warning, | ||
| 154 | R.string.add_games_warning_description, | ||
| 155 | R.string.add_games_warning_help, | ||
| 156 | { | ||
| 157 | val preferences = | ||
| 158 | PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | ||
| 159 | preferences.getString(GameHelper.KEY_GAME_PATH, "")!!.isNotEmpty() | ||
| 160 | } | ||
| 161 | ) | ||
| 162 | ) | ||
| 163 | add( | ||
| 164 | SetupPage( | ||
| 165 | R.drawable.ic_check, | ||
| 166 | R.string.done, | ||
| 167 | R.string.done_description, | ||
| 168 | R.drawable.ic_arrow_forward, | ||
| 169 | false, | ||
| 170 | R.string.text_continue, | ||
| 171 | { finishSetup() }, | ||
| 172 | false | ||
| 173 | ) | ||
| 174 | ) | ||
| 175 | } | ||
| 176 | |||
| 145 | binding.viewPager2.apply { | 177 | binding.viewPager2.apply { |
| 146 | adapter = SetupAdapter(requireActivity() as AppCompatActivity, pages) | 178 | adapter = SetupAdapter(requireActivity() as AppCompatActivity, pages) |
| 147 | offscreenPageLimit = 2 | 179 | offscreenPageLimit = 2 |
| @@ -225,9 +257,15 @@ class SetupFragment : Fragment() { | |||
| 225 | _binding = null | 257 | _binding = null |
| 226 | } | 258 | } |
| 227 | 259 | ||
| 228 | private val pushNotificationPermissionLauncher = | 260 | @RequiresApi(Build.VERSION_CODES.TIRAMISU) |
| 261 | private val permissionLauncher = | ||
| 229 | registerForActivityResult(ActivityResultContracts.RequestPermission()) { | 262 | registerForActivityResult(ActivityResultContracts.RequestPermission()) { |
| 230 | // TODO: Show proper notification request reason and confirmation | 263 | if (!it && !shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) { |
| 264 | PermissionDeniedDialogFragment().show( | ||
| 265 | childFragmentManager, | ||
| 266 | PermissionDeniedDialogFragment.TAG | ||
| 267 | ) | ||
| 268 | } | ||
| 231 | } | 269 | } |
| 232 | 270 | ||
| 233 | private fun finishSetup() { | 271 | private fun finishSetup() { |
diff --git a/src/android/app/src/main/res/drawable/ic_notification.xml b/src/android/app/src/main/res/drawable/ic_notification.xml new file mode 100644 index 000000000..b413f7585 --- /dev/null +++ b/src/android/app/src/main/res/drawable/ic_notification.xml | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 2 | android:width="24dp" | ||
| 3 | android:height="24dp" | ||
| 4 | android:viewportWidth="24" | ||
| 5 | android:viewportHeight="24"> | ||
| 6 | <path | ||
| 7 | android:fillColor="?attr/colorOnSurface" | ||
| 8 | android:pathData="M7.58,4.08L6.15,2.65C3.75,4.48 2.17,7.3 2.03,10.5h2c0.15,-2.65 1.51,-4.97 3.55,-6.42zM19.97,10.5h2c-0.15,-3.2 -1.73,-6.02 -4.12,-7.85l-1.42,1.43c2.02,1.45 3.39,3.77 3.54,6.42zM18,11c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2v-5zM12,22c0.14,0 0.27,-0.01 0.4,-0.04 0.65,-0.14 1.18,-0.58 1.44,-1.18 0.1,-0.24 0.15,-0.5 0.15,-0.78h-4c0.01,1.1 0.9,2 2.01,2z" /> | ||
| 9 | </vector> | ||
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 09b95848f..dd1137b69 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml | |||
| @@ -48,6 +48,13 @@ | |||
| 48 | <string name="install_prod_keys_warning">Skip adding keys?</string> | 48 | <string name="install_prod_keys_warning">Skip adding keys?</string> |
| 49 | <string name="install_prod_keys_warning_description">Valid keys are required to emulate retail games. Only homebrew apps will function if you continue.</string> | 49 | <string name="install_prod_keys_warning_description">Valid keys are required to emulate retail games. Only homebrew apps will function if you continue.</string> |
| 50 | <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string> | 50 | <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string> |
| 51 | <string name="notifications">Notifications</string> | ||
| 52 | <string name="notifications_description">Grant the notification permission with the button below.</string> | ||
| 53 | <string name="give_permission">Grant permission</string> | ||
| 54 | <string name="notification_warning">Skip granting the notification permission?</string> | ||
| 55 | <string name="notification_warning_description">yuzu won\'t be able to notify you of important information.</string> | ||
| 56 | <string name="permission_denied">Permission denied</string> | ||
| 57 | <string name="permission_denied_description">You denied this permission too many times and now you have to manually grant it in system settings.</string> | ||
| 51 | <string name="about">About</string> | 58 | <string name="about">About</string> |
| 52 | <string name="about_description">Build version, credits, and more</string> | 59 | <string name="about_description">Build version, credits, and more</string> |
| 53 | <string name="warning_help">Help</string> | 60 | <string name="warning_help">Help</string> |