Fix previewing audio file

Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
alperozturk 2024-06-11 11:57:33 +02:00
parent ed252e5a55
commit 58cca587ca
No known key found for this signature in database
GPG key ID: 4E577DC593B59BDF
4 changed files with 102 additions and 42 deletions

View file

@ -16,6 +16,7 @@ import android.os.IBinder
import android.widget.MediaController
import android.widget.Toast
import androidx.core.app.NotificationCompat
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.nextcloud.client.account.User
import com.nextcloud.client.network.ClientFactory
import com.nextcloud.utils.ForegroundServiceHelper
@ -23,7 +24,9 @@ import com.nextcloud.utils.extensions.getParcelableArgument
import com.owncloud.android.R
import com.owncloud.android.datamodel.ForegroundServiceType
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.ui.notifications.NotificationUtils
import com.owncloud.android.ui.preview.PreviewMediaActivity
import com.owncloud.android.utils.theme.ViewThemeUtils
import dagger.android.AndroidInjection
import java.util.Locale
@ -32,6 +35,8 @@ import javax.inject.Inject
class PlayerService : Service() {
companion object {
private const val TAG = "PlayerService"
const val EXTRA_USER = "USER"
const val EXTRA_FILE = "FILE"
const val EXTRA_AUTO_PLAY = "EXTRA_AUTO_PLAY"
@ -40,6 +45,8 @@ class PlayerService : Service() {
const val ACTION_STOP = "STOP"
const val ACTION_TOGGLE = "TOGGLE"
const val ACTION_STOP_FILE = "STOP_FILE"
const val IS_MEDIA_CONTROL_LAYOUT_READY = "IS_MEDIA_CONTROL_LAYOUT_READY"
}
class Binder(val service: PlayerService) : android.os.Binder() {
@ -52,24 +59,34 @@ class PlayerService : Service() {
}
private val playerListener = object : Player.Listener {
override fun onRunning(file: OCFile) {
Log_OC.d(TAG,"PlayerService.onRunning()")
val intent = Intent(PreviewMediaActivity.MEDIA_CONTROL_READY_RECEIVER).apply {
putExtra(IS_MEDIA_CONTROL_LAYOUT_READY, false)
}
LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(intent)
startForeground(file)
}
override fun onStart() {
// empty
Log_OC.d(TAG,"PlayerService.onStart()")
val intent = Intent(PreviewMediaActivity.MEDIA_CONTROL_READY_RECEIVER).apply {
putExtra(IS_MEDIA_CONTROL_LAYOUT_READY, true)
}
LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(intent)
}
override fun onPause() {
// empty
Log_OC.d(TAG,"PlayerService.onPause()")
}
override fun onStop() {
Log_OC.d(TAG,"PlayerService.onStop()")
stopServiceAndRemoveNotification(null)
}
override fun onError(error: PlayerError) {
Log_OC.d(TAG,"PlayerService.onError()")
Toast.makeText(this@PlayerService, error.message, Toast.LENGTH_SHORT).show()
}
}
@ -89,18 +106,23 @@ class PlayerService : Service() {
override fun onCreate() {
super.onCreate()
AndroidInjection.inject(this)
player = Player(applicationContext, clientFactory, playerListener, audioManager)
notificationBuilder = NotificationCompat.Builder(this)
viewThemeUtils.androidx.themeNotificationCompatBuilder(this, notificationBuilder)
val stop = Intent(this, PlayerService::class.java)
stop.action = ACTION_STOP
val stop = Intent(this, PlayerService::class.java).apply {
action = ACTION_STOP
}
val pendingStop = PendingIntent.getService(this, 0, stop, PendingIntent.FLAG_IMMUTABLE)
notificationBuilder.addAction(0, getString(R.string.player_stop).toUpperCase(Locale.getDefault()), pendingStop)
val toggle = Intent(this, PlayerService::class.java)
toggle.action = ACTION_TOGGLE
val toggle = Intent(this, PlayerService::class.java).apply {
action = ACTION_TOGGLE
}
val pendingToggle = PendingIntent.getService(this, 0, toggle, PendingIntent.FLAG_IMMUTABLE)
notificationBuilder.addAction(
0,
@ -124,10 +146,12 @@ class PlayerService : Service() {
}
private fun onActionToggle() {
if (player.isPlaying) {
player.pause()
} else {
player.start()
player.run {
if (isPlaying) {
pause()
} else {
start()
}
}
}
@ -153,14 +177,17 @@ class PlayerService : Service() {
private fun startForeground(currentFile: OCFile) {
val ticker = String.format(getString(R.string.media_notif_ticker), getString(R.string.app_name))
val content = getString(R.string.media_state_playing, currentFile.getFileName())
notificationBuilder.setSmallIcon(R.drawable.ic_play_arrow)
notificationBuilder.setWhen(System.currentTimeMillis())
notificationBuilder.setOngoing(true)
notificationBuilder.setContentTitle(ticker)
notificationBuilder.setContentText(content)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_MEDIA)
notificationBuilder.run {
setSmallIcon(R.drawable.ic_play_arrow)
setWhen(System.currentTimeMillis())
setOngoing(true)
setContentTitle(ticker)
setContentText(content)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_MEDIA)
}
}
ForegroundServiceHelper.startService(

View file

@ -38,12 +38,14 @@ class PlayerServiceConnection(private val context: Context) : MediaController.Me
}
fun start(user: User, file: OCFile, playImmediately: Boolean, position: Long) {
val i = Intent(context, PlayerService::class.java)
i.putExtra(PlayerService.EXTRA_USER, user)
i.putExtra(PlayerService.EXTRA_FILE, file)
i.putExtra(PlayerService.EXTRA_AUTO_PLAY, playImmediately)
i.putExtra(PlayerService.EXTRA_START_POSITION_MS, position)
i.action = PlayerService.ACTION_PLAY
val i = Intent(context, PlayerService::class.java).apply {
putExtra(PlayerService.EXTRA_USER, user)
putExtra(PlayerService.EXTRA_FILE, file)
putExtra(PlayerService.EXTRA_AUTO_PLAY, playImmediately)
putExtra(PlayerService.EXTRA_START_POSITION_MS, position)
action = PlayerService.ACTION_PLAY
}
startForegroundService(i)
}

View file

@ -13,7 +13,10 @@
package com.owncloud.android.ui.preview
import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.BitmapFactory
@ -41,6 +44,7 @@ import androidx.core.view.WindowInsetsControllerCompat
import androidx.core.view.marginBottom
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.media3.common.MediaItem
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer
@ -53,6 +57,7 @@ import com.nextcloud.client.jobs.BackgroundJobManager
import com.nextcloud.client.jobs.download.FileDownloadHelper
import com.nextcloud.client.media.ExoplayerListener
import com.nextcloud.client.media.NextcloudExoPlayer.createNextcloudExoplayer
import com.nextcloud.client.media.PlayerService
import com.nextcloud.client.media.PlayerServiceConnection
import com.nextcloud.client.network.ClientFactory
import com.nextcloud.client.network.ClientFactory.CreationException
@ -146,9 +151,28 @@ class PreviewMediaActivity :
showMediaTypeViews()
configureSystemBars()
emptyListView = binding.emptyView.emptyListView
setLoadingView()
showProgressLayout()
}
private fun registerMediaControlReceiver() {
val filter = IntentFilter(MEDIA_CONTROL_READY_RECEIVER)
LocalBroadcastManager.getInstance(this).registerReceiver(mediaControlReceiver, filter)
}
private val mediaControlReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
intent.getBooleanExtra(PlayerService.IS_MEDIA_CONTROL_LAYOUT_READY, false).run {
if (this) {
hideProgressLayout()
recreate()
} else {
showProgressLayout()
}
}
}
}
private fun initArguments(savedInstanceState: Bundle?) {
intent?.let {
initWithIntent(it)
@ -160,6 +184,11 @@ class PreviewMediaActivity :
} else {
initWithBundle(savedInstanceState)
}
if (MimeTypeUtil.isAudio(file)) {
registerMediaControlReceiver()
requestForDownload(file)
}
}
private fun initWithIntent(intent: Intent) {
@ -206,11 +235,18 @@ class PreviewMediaActivity :
)
}
private fun setLoadingView() {
private fun showProgressLayout() {
binding.progress.visibility = View.VISIBLE
binding.mediaController.visibility = View.GONE
binding.emptyView.emptyListView.visibility = View.GONE
}
private fun hideProgressLayout() {
binding.progress.visibility = View.GONE
binding.mediaController.visibility = View.VISIBLE
binding.emptyView.emptyListView.visibility = View.VISIBLE
}
private fun setVideoErrorMessage(headline: String, @StringRes message: Int) {
binding.emptyView.run {
emptyListViewHeadline.text = headline
@ -218,8 +254,8 @@ class PreviewMediaActivity :
emptyListIcon.setImageResource(R.drawable.file_movie)
emptyListViewText.visibility = View.VISIBLE
emptyListIcon.visibility = View.VISIBLE
binding.progress.visibility = View.GONE
emptyListView.visibility = View.VISIBLE
hideProgressLayout()
}
}
@ -691,8 +727,9 @@ class PreviewMediaActivity :
override fun onDestroy() {
Log_OC.v(TAG, "onDestroy")
super.onDestroy()
LocalBroadcastManager.getInstance(this).unregisterReceiver(mediaControlReceiver)
super.onDestroy()
exoPlayer?.run {
stop()
release()
@ -783,6 +820,8 @@ class PreviewMediaActivity :
companion object {
private val TAG = PreviewMediaActivity::class.java.simpleName
const val MEDIA_CONTROL_READY_RECEIVER: String = "MEDIA_CONTROL_READY_RECEIVER"
const val EXTRA_FILE = "FILE"
const val EXTRA_USER = "USER"
const val EXTRA_AUTOPLAY = "AUTOPLAY"

View file

@ -51,24 +51,16 @@
<FrameLayout
android:id="@+id/progress"
android:background="@color/color_dark_transparent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.elyeproj.loaderviewlibrary.LoaderImageView
android:layout_width="@dimen/empty_list_icon_layout_width"
android:layout_height="@dimen/empty_list_icon_layout_width"
<com.google.android.material.progressindicator.CircularProgressIndicator
android:layout_width="wrap_content"
android:layout_gravity="center"
android:contentDescription="@null"
app:corners="24" />
android:layout_height="wrap_content"
android:indeterminate="true" />
<ImageView
android:layout_width="@dimen/empty_list_icon_layout_width"
android:layout_height="@dimen/empty_list_icon_layout_height"
android:layout_gravity="center"
android:contentDescription="@null"
android:padding="@dimen/standard_half_padding"
android:src="@drawable/file_movie"
app:tint="@color/bg_default" />
</FrameLayout>
<FrameLayout