Use helper class for Android version checks

This commit is contained in:
Maxr1998 2023-05-16 21:40:20 +02:00 committed by Niels van Velzen
parent d18c59779a
commit 2fdc30fadc
12 changed files with 58 additions and 29 deletions

View File

@ -4,7 +4,6 @@ import android.app.Service
import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.os.Build
import android.os.Bundle
import android.os.IBinder
import android.provider.Settings
@ -19,6 +18,7 @@ import org.jellyfin.mobile.player.cast.Chromecast
import org.jellyfin.mobile.player.cast.IChromecast
import org.jellyfin.mobile.player.ui.PlayerFragment
import org.jellyfin.mobile.setup.ConnectFragment
import org.jellyfin.mobile.utils.AndroidVersion
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.PermissionRequestHelper
import org.jellyfin.mobile.utils.SmartOrientationListener
@ -66,7 +66,7 @@ class MainActivity : AppCompatActivity() {
setTitle(R.string.dialog_web_view_not_supported)
setMessage(R.string.dialog_web_view_not_supported_message)
setCancelable(false)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
if (AndroidVersion.isAtLeastN) {
setNeutralButton(R.string.dialog_button_open_settings) { _, _ ->
startActivity(Intent(Settings.ACTION_WEBVIEW_SETTINGS))
Toast.makeText(context, R.string.toast_reopen_after_change, Toast.LENGTH_LONG).show()

View File

@ -9,7 +9,6 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Bitmap
import android.os.Build
import androidx.core.content.getSystemService
import androidx.core.graphics.drawable.toBitmap
import androidx.lifecycle.viewModelScope
@ -25,6 +24,7 @@ import org.jellyfin.mobile.R
import org.jellyfin.mobile.app.AppPreferences
import org.jellyfin.mobile.player.PlayerViewModel
import org.jellyfin.mobile.player.source.JellyfinMediaSource
import org.jellyfin.mobile.utils.AndroidVersion
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.Constants.VIDEO_PLAYER_NOTIFICATION_ID
import org.jellyfin.mobile.utils.createMediaNotificationChannel
@ -86,7 +86,7 @@ class PlayerNotificationHelper(private val viewModel: PlayerViewModel) : KoinCom
}
val notification = Notification.Builder(context).apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (AndroidVersion.isAtLeastO) {
setChannelId(Constants.MEDIA_NOTIFICATION_CHANNEL_ID) // Set Notification Channel on Android O and above
setColorized(true)
} else {

View File

@ -35,6 +35,7 @@ import org.jellyfin.mobile.databinding.FragmentPlayerBinding
import org.jellyfin.mobile.player.PlayerException
import org.jellyfin.mobile.player.PlayerViewModel
import org.jellyfin.mobile.player.interaction.PlayOptions
import org.jellyfin.mobile.utils.AndroidVersion
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.Constants.DEFAULT_CONTROLS_TIMEOUT_MS
import org.jellyfin.mobile.utils.Constants.PIP_MAX_RATIONAL
@ -220,7 +221,7 @@ class PlayerFragment : Fragment() {
*/
private fun updateFullscreenState(configuration: Configuration) {
// Do not handle any orientation changes while being in Picture-in-Picture mode
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && requireActivity().isInPictureInPictureMode) {
if (AndroidVersion.isAtLeastN && requireActivity().isInPictureInPictureMode) {
return
}
@ -301,7 +302,7 @@ class PlayerFragment : Fragment() {
}
fun onUserLeaveHint() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && viewModel.playerOrNull?.isPlaying == true) {
if (AndroidVersion.isAtLeastN && viewModel.playerOrNull?.isPlaying == true) {
requireActivity().enterPictureInPicture()
}
}
@ -309,7 +310,7 @@ class PlayerFragment : Fragment() {
@Suppress("NestedBlockDepth")
@RequiresApi(Build.VERSION_CODES.N)
private fun Activity.enterPictureInPicture() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (AndroidVersion.isAtLeastO) {
val params = PictureInPictureParams.Builder().apply {
val aspectRational = currentVideoStream?.aspectRational?.let { aspectRational ->
when {

View File

@ -1,12 +1,12 @@
package org.jellyfin.mobile.player.ui
import android.content.pm.ActivityInfo
import android.os.Build
import android.view.OrientationEventListener
import android.widget.ImageButton
import androidx.core.view.isVisible
import com.google.android.exoplayer2.ui.PlayerView
import org.jellyfin.mobile.databinding.FragmentPlayerBinding
import org.jellyfin.mobile.utils.AndroidVersion
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.extensions.lockOrientation
import org.jellyfin.mobile.utils.isAutoRotateOn
@ -47,7 +47,7 @@ class PlayerLockScreenHelper(
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
}
orientationListener.enable()
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N || !activity.isInPictureInPictureMode) {
if (!AndroidVersion.isAtLeastN || !activity.isInPictureInPictureMode) {
playerView.useController = true
playerView.apply {
if (!isControllerVisible) showController()

View File

@ -0,0 +1,32 @@
package org.jellyfin.mobile.utils
import android.os.Build
object AndroidVersion {
inline val isAtLeastM: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
inline val isAtLeastN: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
inline val isAtLeastNMR1: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1
inline val isAtLeastO: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
inline val isAtLeastP: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
inline val isAtLeastQ: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
inline val isAtLeastR: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
inline val isAtLeastS: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
inline val isAtLeastT: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
}

View File

@ -2,7 +2,6 @@ package org.jellyfin.mobile.utils
import android.app.PendingIntent
import android.media.session.PlaybackState
import android.os.Build
import android.util.Rational
import org.jellyfin.mobile.BuildConfig
@ -56,7 +55,7 @@ object Constants {
// Notification
val PENDING_INTENT_FLAGS = PendingIntent.FLAG_UPDATE_CURRENT or when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> PendingIntent.FLAG_IMMUTABLE
AndroidVersion.isAtLeastM -> PendingIntent.FLAG_IMMUTABLE
else -> 0
}
const val MEDIA_NOTIFICATION_CHANNEL_ID = "org.jellyfin.mobile.media.NOW_PLAYING"

View File

@ -2,7 +2,6 @@ package org.jellyfin.mobile.utils
import android.content.Context
import android.content.res.Configuration
import android.os.Build
import android.webkit.WebView
import org.json.JSONException
import org.json.JSONObject
@ -53,4 +52,4 @@ private fun Context.setLocale(localeString: String?): Boolean {
@Suppress("DEPRECATION")
private val Configuration.primaryLocale: Locale
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) locales[0] else locale
get() = if (AndroidVersion.isAtLeastN) locales[0] else locale

View File

@ -7,7 +7,6 @@ import android.media.AudioManager
import android.media.MediaMetadata
import android.media.session.MediaSession
import android.media.session.PlaybackState
import android.os.Build
import com.google.android.exoplayer2.C
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.Player
@ -20,7 +19,7 @@ inline fun MediaSession.applyDefaultLocalAudioAttributes(contentType: Int) {
val audioAttributes = AudioAttributes.Builder().apply {
setUsage(AudioAttributes.USAGE_MEDIA)
setContentType(contentType)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (AndroidVersion.isAtLeastQ) {
setAllowedCapturePolicy(AudioAttributes.ALLOW_CAPTURE_BY_ALL)
}
}.build()
@ -60,7 +59,7 @@ fun MediaSession.setPlaybackState(player: Player, playbackActions: Long) {
}
fun AudioManager.getVolumeRange(streamType: Int): IntRange {
val minVolume = (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) getStreamMinVolume(streamType) else 0)
val minVolume = (if (AndroidVersion.isAtLeastP) getStreamMinVolume(streamType) else 0)
val maxVolume = getStreamMaxVolume(streamType)
return minVolume..maxVolume
}

View File

@ -13,7 +13,6 @@ import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.os.PowerManager
import android.provider.Settings
@ -37,7 +36,7 @@ import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
fun WebViewFragment.requestNoBatteryOptimizations(rootView: CoordinatorLayout) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (AndroidVersion.isAtLeastM) {
val powerManager: PowerManager = requireContext().getSystemService(AppCompatActivity.POWER_SERVICE) as PowerManager
if (
!appPreferences.ignoreBatteryOptimizations &&
@ -65,7 +64,7 @@ suspend fun MainActivity.requestDownload(uri: Uri, title: String, filename: Stri
val appPreferences: AppPreferences = get()
// Storage permission for downloads isn't necessary from Android 10 onwards
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
if (!AndroidVersion.isAtLeastQ) {
@Suppress("MagicNumber")
val granted = withTimeout(2 * 60 * 1000 /* 2 minutes */) {
suspendCoroutine { continuation ->
@ -134,7 +133,7 @@ fun PackageManager.isPackageInstalled(@ExternalPlayerPackage packageName: String
}
fun Context.createMediaNotificationChannel(notificationManager: NotificationManager) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (AndroidVersion.isAtLeastO) {
val notificationChannel = NotificationChannel(
Constants.MEDIA_NOTIFICATION_CHANNEL_ID,
getString(R.string.app_name),

View File

@ -1,10 +1,10 @@
package org.jellyfin.mobile.utils.extensions
import android.os.Build
import android.os.Bundle
import org.jellyfin.mobile.utils.AndroidVersion
@Suppress("DEPRECATION")
inline fun <reified T> Bundle.getParcelableCompat(key: String?): T? = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getParcelable(key, T::class.java)
AndroidVersion.isAtLeastT -> getParcelable(key, T::class.java)
else -> getParcelable(key)
}

View File

@ -19,7 +19,6 @@ import android.media.session.MediaController
import android.media.session.MediaSession
import android.media.session.PlaybackState
import android.os.Binder
import android.os.Build
import android.os.IBinder
import android.os.PowerManager
import androidx.annotation.StringRes
@ -36,6 +35,7 @@ import kotlinx.coroutines.launch
import org.jellyfin.mobile.MainActivity
import org.jellyfin.mobile.R
import org.jellyfin.mobile.app.AppPreferences
import org.jellyfin.mobile.utils.AndroidVersion
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.Constants.EXTRA_ALBUM
import org.jellyfin.mobile.utils.Constants.EXTRA_ARTIST
@ -244,7 +244,7 @@ class RemotePlayerService : Service(), CoroutineScope {
mediaSession.setPlaybackToRemote(remoteVolumeProvider)
}
val supportsNativeSeek = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
val supportsNativeSeek = AndroidVersion.isAtLeastQ
val style = Notification.MediaStyle().apply {
setMediaSession(mediaSession.sessionToken)
@ -255,7 +255,7 @@ class RemotePlayerService : Service(), CoroutineScope {
@Suppress("DEPRECATION")
val notification = Notification.Builder(this@RemotePlayerService).apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (AndroidVersion.isAtLeastO) {
setChannelId(MEDIA_NOTIFICATION_CHANNEL_ID) // Set Notification Channel on Android O and above
setColorized(true) // Color notification based on cover art
} else {
@ -265,7 +265,7 @@ class RemotePlayerService : Service(), CoroutineScope {
setContentText(artist?.let { HtmlCompat.fromHtml(it, HtmlCompat.FROM_HTML_MODE_LEGACY) })
setSubText(album)
if (position != PlaybackState.PLAYBACK_POSITION_UNKNOWN) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
if (!AndroidVersion.isAtLeastN) {
// Show current position in "when" field pre-N
setShowWhen(!isPaused)
setUsesChronometer(!isPaused)

View File

@ -3,7 +3,6 @@ package org.jellyfin.mobile.webapp
import android.content.Intent
import android.graphics.Rect
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.view.LayoutInflater
@ -31,6 +30,7 @@ import org.jellyfin.mobile.bridge.NativePlayer
import org.jellyfin.mobile.data.entity.ServerEntity
import org.jellyfin.mobile.databinding.FragmentWebviewBinding
import org.jellyfin.mobile.setup.ConnectFragment
import org.jellyfin.mobile.utils.AndroidVersion
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.Constants.FRAGMENT_WEB_VIEW_EXTRA_SERVER
import org.jellyfin.mobile.utils.applyDefault
@ -126,7 +126,7 @@ class WebViewFragment : Fragment() {
ViewCompat.requestApplyInsets(webView)
// Setup exclusion rects for gestures
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (AndroidVersion.isAtLeastQ) {
@Suppress("MagicNumber")
webView.doOnNextLayout {
// Maximum allowed exclusion rect height is 200dp,
@ -220,7 +220,7 @@ class WebViewFragment : Fragment() {
}
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
if (AndroidVersion.isAtLeastN) {
setPositiveButton(R.string.dialog_button_open_settings) { _, _ ->
startActivity(Intent(Settings.ACTION_WEBVIEW_SETTINGS))
Toast.makeText(context, R.string.toast_reopen_after_change, Toast.LENGTH_LONG).show()