mirror of
https://github.com/jellyfin/jellyfin-android.git
synced 2024-12-04 03:51:47 +00:00
Use helper class for Android version checks
This commit is contained in:
parent
d18c59779a
commit
2fdc30fadc
@ -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()
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
}
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user