Browse Source

Merge pull request #11069 from nextcloud/fix/video-fullscreen-stuck

Misc fixes for video player
Álvaro Brey 2 năm trước cách đây
mục cha
commit
eaae4a0f9c

+ 31 - 0
app/src/main/java/com/nextcloud/client/media/ErrorFormat.kt

@@ -25,6 +25,7 @@ package com.nextcloud.client.media
 
 import android.content.Context
 import android.media.MediaPlayer
+import com.google.android.exoplayer2.PlaybackException
 import com.owncloud.android.R
 
 /**
@@ -91,4 +92,34 @@ object ErrorFormat {
         }
         return context?.getString(messageId) ?: "Media error"
     }
+
+    fun toString(context: Context, exception: PlaybackException): String {
+        val messageId = when (exception.errorCode) {
+            PlaybackException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED,
+            PlaybackException.ERROR_CODE_DECODING_FORMAT_EXCEEDS_CAPABILITIES -> {
+                R.string.media_err_unsupported
+            }
+            PlaybackException.ERROR_CODE_IO_UNSPECIFIED,
+            PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED,
+            PlaybackException.ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE,
+            PlaybackException.ERROR_CODE_IO_BAD_HTTP_STATUS,
+            PlaybackException.ERROR_CODE_IO_FILE_NOT_FOUND,
+            PlaybackException.ERROR_CODE_IO_NO_PERMISSION,
+            PlaybackException.ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED,
+            PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE -> {
+                R.string.media_err_io
+            }
+            PlaybackException.ERROR_CODE_TIMEOUT -> {
+                R.string.media_err_timeout
+            }
+            PlaybackException.ERROR_CODE_PARSING_CONTAINER_MALFORMED,
+            PlaybackException.ERROR_CODE_PARSING_MANIFEST_MALFORMED -> {
+                R.string.media_err_malformed
+            }
+            else -> {
+                R.string.media_err_invalid_progressive_playback
+            }
+        }
+        return context.getString(messageId)
+    }
 }

+ 74 - 0
app/src/main/java/com/nextcloud/client/media/ExoplayerListener.kt

@@ -0,0 +1,74 @@
+/*
+ * Nextcloud Android client application
+ *
+ *  @author Álvaro Brey
+ *  Copyright (C) 2022 Álvaro Brey
+ *  Copyright (C) 2022 Nextcloud GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.nextcloud.client.media
+
+import android.content.Context
+import android.content.DialogInterface
+import android.view.View
+import com.google.android.exoplayer2.ExoPlayer
+import com.google.android.exoplayer2.PlaybackException
+import com.google.android.exoplayer2.Player
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.owncloud.android.R
+import com.owncloud.android.lib.common.utils.Log_OC
+
+class ExoplayerListener(private val context: Context, private val playerView: View, private val exoPlayer: ExoPlayer) :
+    Player.Listener {
+
+    override fun onPlaybackStateChanged(playbackState: Int) {
+        super.onPlaybackStateChanged(playbackState)
+        if (playbackState == Player.STATE_ENDED) {
+            onCompletion()
+        }
+    }
+
+    override fun onIsPlayingChanged(isPlaying: Boolean) {
+        super.onIsPlayingChanged(isPlaying)
+        Log_OC.d(TAG, "Exoplayer keep screen on: $isPlaying")
+        playerView.keepScreenOn = isPlaying
+    }
+
+    private fun onCompletion() {
+        exoPlayer.let {
+            it.seekToDefaultPosition()
+            it.pause()
+        }
+    }
+
+    override fun onPlayerError(error: PlaybackException) {
+        super.onPlayerError(error)
+        Log_OC.e(TAG, "Exoplayer error", error)
+        val message = ErrorFormat.toString(context, error)
+        MaterialAlertDialogBuilder(context)
+            .setMessage(message)
+            .setPositiveButton(R.string.common_ok) { _: DialogInterface?, _: Int ->
+                onCompletion()
+            }
+            .setCancelable(false)
+            .show()
+    }
+
+    companion object {
+        private const val TAG = "ExoplayerListener"
+    }
+}

+ 2 - 0
app/src/main/java/com/owncloud/android/ui/preview/PreviewMediaFragment.java

@@ -53,6 +53,7 @@ import com.nextcloud.client.account.User;
 import com.nextcloud.client.account.UserAccountManager;
 import com.nextcloud.client.di.Injectable;
 import com.nextcloud.client.jobs.BackgroundJobManager;
+import com.nextcloud.client.media.ExoplayerListener;
 import com.nextcloud.client.media.NextcloudExoPlayer;
 import com.nextcloud.client.media.PlayerServiceConnection;
 import com.nextcloud.client.network.ClientFactory;
@@ -330,6 +331,7 @@ public class PreviewMediaFragment extends FileFragment implements OnTouchListene
                             final NextcloudClient client = clientFactory.createNextcloudClient(accountManager.getUser());
                             handler.post(() ->{
                                 exoPlayer = NextcloudExoPlayer.createNextcloudExoplayer(requireContext(), client);
+                                exoPlayer.addListener(new ExoplayerListener(requireContext(), binding.exoplayerView, exoPlayer));
                                 playVideo();
                             });
                         } catch (ClientFactory.CreationException e) {

+ 4 - 57
app/src/main/java/com/owncloud/android/ui/preview/PreviewVideoActivity.kt

@@ -19,21 +19,16 @@
  */
 package com.owncloud.android.ui.preview
 
-import android.content.DialogInterface
 import android.content.Intent
-import android.media.MediaPlayer
-import android.media.MediaPlayer.OnCompletionListener
-import android.media.MediaPlayer.OnPreparedListener
 import android.net.Uri
 import android.os.Bundle
 import android.view.View
-import androidx.appcompat.app.AlertDialog
 import com.google.android.exoplayer2.ExoPlayer
 import com.google.android.exoplayer2.MediaItem
 import com.google.android.exoplayer2.Player
 import com.nextcloud.client.account.UserAccountManager
 import com.nextcloud.client.di.Injectable
-import com.nextcloud.client.media.ErrorFormat.toString
+import com.nextcloud.client.media.ExoplayerListener
 import com.nextcloud.client.media.NextcloudExoPlayer.createNextcloudExoplayer
 import com.nextcloud.client.network.ClientFactory
 import com.owncloud.android.R
@@ -50,14 +45,10 @@ import javax.inject.Inject
 /**
  * Activity implementing a basic video player.
  *
- * THIS CLASS NEEDS WORK; the old listeners (OnCompletion, OnPrepared; OnError) don't work with ExoPlayer
  */
 @Suppress("TooManyFunctions")
 class PreviewVideoActivity :
     FileActivity(),
-    OnCompletionListener,
-    OnPreparedListener,
-    MediaPlayer.OnErrorListener,
     Player.Listener,
     Injectable {
 
@@ -153,52 +144,6 @@ class PreviewVideoActivity :
     private fun isPlaying() = exoPlayer?.isPlaying ?: false
     private fun currentPosition() = exoPlayer?.currentPosition ?: 0
 
-    /**
-     * Called when the file is ready to be played.
-     *
-     * Just starts the playback.
-     *
-     * @param mp    [MediaPlayer] instance performing the playback.
-     */
-    override fun onPrepared(mp: MediaPlayer) {
-        Log_OC.v(TAG, "onPrepare")
-        exoPlayer?.seekTo(mSavedPlaybackPosition)
-        if (mAutoplay) {
-            exoPlayer?.play()
-        }
-    }
-
-    /**
-     * Called when the file is finished playing.
-     *
-     * Rewinds the video
-     *
-     * @param mp    [MediaPlayer] instance performing the playback.
-     */
-    override fun onCompletion(mp: MediaPlayer?) {
-        exoPlayer?.seekTo(0)
-    }
-
-    /**
-     * Called when an error in playback occurs.
-     *
-     * @param mp      [MediaPlayer] instance performing the playback.
-     * @param what    Type of error
-     * @param extra   Extra code specific to the error
-     */
-    override fun onError(mp: MediaPlayer, what: Int, extra: Int): Boolean {
-        Log_OC.e(TAG, "Error in video playback, what = $what, extra = $extra")
-        val message = toString(this, what, extra)
-        AlertDialog.Builder(this)
-            .setMessage(message)
-            .setPositiveButton(android.R.string.VideoView_error_button) { _: DialogInterface?, _: Int ->
-                onCompletion(null)
-            }
-            .setCancelable(false)
-            .show()
-        return true
-    }
-
     private fun play(item: MediaItem) {
         exoPlayer?.addMediaItem(item)
         exoPlayer?.prepare()
@@ -231,7 +176,9 @@ class PreviewVideoActivity :
                     CoroutineScope(Dispatchers.IO).launch {
                         val client = clientFactory.createNextcloudClient(accountManager.user)
                         CoroutineScope(Dispatchers.Main).launch {
-                            exoPlayer = createNextcloudExoplayer(context, client)
+                            exoPlayer = createNextcloudExoplayer(context, client).also {
+                                it.addListener(ExoplayerListener(context, binding.videoPlayer, it))
+                            }
                             setupPlayerView()
                             play(mediaItem)
                         }