[Android] Use RenderEffect instead of RenderScript on API 31+

Nicolas Pomepuy git at videolan.org
Tue Nov 15 12:44:35 UTC 2022


vlc-android | branch: master | Nicolas Pomepuy <nicolas at videolabs.io> | Tue Nov 15 08:50:33 2022 +0100| [0f231358dc92c80e03fc0174ad5badcc373df1ae] | committer: Duncan McNamara

Use RenderEffect instead of RenderScript on API 31+

> https://code.videolan.org/videolan/vlc-android/commit/0f231358dc92c80e03fc0174ad5badcc373df1ae
---

 .../ui/audioplayer/AudioPlayerActivity.kt          |  4 +--
 .../videolan/vlc/gui/HeaderMediaListActivity.kt    |  6 +---
 .../videolan/vlc/gui/audio/AudioPlayerAnimator.kt  | 11 ++-----
 .../src/org/videolan/vlc/gui/helpers/UiTools.kt    | 36 ++++++++++++++++++++++
 4 files changed, 41 insertions(+), 16 deletions(-)

diff --git a/application/television/src/main/java/org/videolan/television/ui/audioplayer/AudioPlayerActivity.kt b/application/television/src/main/java/org/videolan/television/ui/audioplayer/AudioPlayerActivity.kt
index 0cb8d47353..1d385c61c0 100644
--- a/application/television/src/main/java/org/videolan/television/ui/audioplayer/AudioPlayerActivity.kt
+++ b/application/television/src/main/java/org/videolan/television/ui/audioplayer/AudioPlayerActivity.kt
@@ -208,15 +208,13 @@ class AudioPlayerActivity : BaseTvActivity(),KeycodeListener  {
     private fun updateBackground() = lifecycleScope.launchWhenStarted {
         val width = if (binding.albumCover.width > 0) binding.albumCover.width else this at AudioPlayerActivity.getScreenWidth()
         val cover = withContext(Dispatchers.IO) { AudioUtil.readCoverBitmap(Uri.decode(currentCoverArt), width) }
-        val blurredCover = if (cover != null) withContext(Dispatchers.Default) { UiTools.blurBitmap(cover) } else null
         if (cover == null) {
             binding.albumCover.setImageResource(R.drawable.ic_no_artwork_big)
             binding.background.clearColorFilter()
             binding.background.setImageResource(0)
         } else {
+            UiTools.blurView(binding.background, cover, 15F, UiTools.getColorFromAttribute(binding.background.context, R.attr.audio_player_background_tint))
             binding.albumCover.setImageBitmap(cover)
-            binding.background.setColorFilter(UiTools.getColorFromAttribute(binding.background.context, R.attr.audio_player_background_tint))
-            binding.background.setImageBitmap(blurredCover)
         }
     }
 
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/HeaderMediaListActivity.kt b/application/vlc-android/src/org/videolan/vlc/gui/HeaderMediaListActivity.kt
index 3c5636e102..d36bdf33ce 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/HeaderMediaListActivity.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/HeaderMediaListActivity.kt
@@ -171,11 +171,7 @@ open class HeaderMediaListActivity : AudioPlayerContainerActivity(), IEventsHand
                 binding.cover = BitmapDrawable(this at HeaderMediaListActivity.resources, cover)
                 binding.appbar.setExpanded(true, true)
                 val radius = if (isPlaylist) 25f else 15f
-                val blurredCover = UiTools.blurBitmap(cover, radius)
-                withContext(Dispatchers.Main) {
-                    binding.backgroundView.setColorFilter(UiTools.getColorFromAttribute(context, R.attr.audio_player_background_tint))
-                    binding.backgroundView.setImageBitmap(blurredCover)
-                }
+                UiTools.blurView(binding.backgroundView, cover, radius, UiTools.getColorFromAttribute(context, R.attr.audio_player_background_tint))
             }
         }
 
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayerAnimator.kt b/application/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayerAnimator.kt
index ebd53a98e6..11385f76dc 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayerAnimator.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayerAnimator.kt
@@ -214,7 +214,6 @@ internal class AudioPlayerAnimator : IAudioPlayerAnimator, LifecycleObserver {
     /**
      * Updates the player background with or without a blurred cover depending on the user setting
      */
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
     override suspend fun updateBackground() {
         if (Settings.getInstance(audioPlayer.requireActivity()).getBoolean("blurred_cover_background", true)) {
             val mw = audioPlayer.playlistModel.currentMediaWrapper ?: return
@@ -223,13 +222,9 @@ internal class AudioPlayerAnimator : IAudioPlayerAnimator, LifecycleObserver {
             if (mw.artworkMrl.isNullOrEmpty()) setDefaultBackground()
             else {
                 val width = if (binding.contentLayout.width > 0) binding.contentLayout.width else audioPlayer.activity?.getScreenWidth() ?: return
-                val blurredCover = withContext(Dispatchers.IO) { UiTools.blurBitmap(AudioUtil.readCoverBitmap(Uri.decode(mw.artworkMrl), width)) }
-                if (blurredCover !== null) {
-                    val activity = audioPlayer.activity as? AudioPlayerContainerActivity ?: return
-                    binding.backgroundView.setColorFilter(UiTools.getColorFromAttribute(activity, R.attr.audio_player_background_tint))
-                    binding.backgroundView.setImageBitmap(blurredCover)
-                    binding.backgroundView.visibility = View.VISIBLE
-                } else setDefaultBackground()
+                val activity = audioPlayer.activity as? AudioPlayerContainerActivity ?: return
+                val bitmap = AudioUtil.readCoverBitmap(Uri.decode(mw.artworkMrl), width)
+                bitmap?.let { UiTools.blurView(binding.backgroundView, bitmap, 15F, UiTools.getColorFromAttribute(activity, R.attr.audio_player_background_tint)) } ?:  setDefaultBackground()
             }
         } else {
             currentCoverArt = null
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt b/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt
index e686e9bac6..9259f2d915 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt
@@ -31,6 +31,8 @@ import android.content.Context
 import android.content.DialogInterface
 import android.content.Intent
 import android.graphics.Bitmap
+import android.graphics.RenderEffect
+import android.graphics.Shader
 import android.graphics.drawable.BitmapDrawable
 import android.media.MediaRouter
 import android.os.Build
@@ -540,6 +542,40 @@ object UiTools {
         }
     }
 
+    /**
+     * Set a blur effect on the whole [ImageView] using [RenderEffect]
+     * with a fallback on [RenderScript] if needed
+     *
+     * @param imageView the [ImageView] to blur
+     * @param bitmap the [Bitmap] to display
+     * @param radius the blur radius
+     * @param colorFilter the color filter to be used on the view depending on the theme
+     */
+    suspend fun blurView(imageView: ImageView, bitmap: Bitmap?, radius: Float, colorFilter: Int) {
+        imageView.setColorFilter(colorFilter)
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+            val blur = RenderEffect.createBlurEffect(radius, radius, Shader.TileMode.CLAMP)
+            imageView.setRenderEffect(blur)
+            imageView.setImageBitmap(bitmap)
+        } else {
+            val blurred = withContext(Dispatchers.IO) {
+                blurBitmap(bitmap, radius)
+            }
+            withContext(Dispatchers.Main) {
+                imageView.setImageBitmap(blurred)
+            }
+        }
+    }
+
+    /**
+     * Blur a [Bitmap]. it uses a deprecated API and therefore should not be used
+     * except for a fallback for API < 31
+     *
+     * @param bitmap the [Bitmap] to blur
+     * @param radius the bur radius
+     * @return a blurred bitmap
+     */
+    @Suppress("DEPRECATION")
     @JvmOverloads
     fun blurBitmap(bitmap: Bitmap?, radius: Float = 15.0f): Bitmap? {
         if (bitmap == null || bitmap.config == null) return null



More information about the Android mailing list