Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use helper class for Android version checks #1060

Merged
merged 2 commits into from
May 16, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/src/main/java/org/jellyfin/mobile/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -301,15 +302,15 @@ 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()
}
}

@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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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()
Expand Down
32 changes: 32 additions & 0 deletions app/src/main/java/org/jellyfin/mobile/utils/AndroidVersion.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.jellyfin.mobile.utils

import android.os.Build

object AndroidVersion {
Maxr1998 marked this conversation as resolved.
Show resolved Hide resolved
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
}
3 changes: 1 addition & 2 deletions app/src/main/java/org/jellyfin/mobile/utils/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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"
Expand Down
3 changes: 1 addition & 2 deletions app/src/main/java/org/jellyfin/mobile/utils/LocaleUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()
Expand Down Expand Up @@ -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
}
Expand Down
7 changes: 3 additions & 4 deletions app/src/main/java/org/jellyfin/mobile/utils/SystemUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 &&
Expand Down Expand Up @@ -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 ->
Expand Down Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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 {
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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()
Expand Down