فهرست منبع

lint checks solved

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>
parneet-guraya 9 ماه پیش
والد
کامیت
b9855e8a86

+ 2 - 1
app/src/main/AndroidManifest.xml

@@ -353,7 +353,8 @@
         <service
             android:name="com.nextcloud.client.media.BackgroundPlayerService"
             android:foregroundServiceType="mediaPlayback"
-            android:exported="true">
+            android:exported="true"
+            tools:ignore="ExportedService">
             <intent-filter>
                 <action android:name="androidx.media3.session.MediaSessionService"/>
             </intent-filter>

+ 4 - 0
app/src/main/java/com/nextcloud/client/di/AppComponent.java

@@ -28,6 +28,8 @@ import com.owncloud.android.ui.whatsnew.ProgressIndicator;
 
 import javax.inject.Singleton;
 
+import androidx.annotation.OptIn;
+import androidx.media3.common.util.UnstableApi;
 import dagger.BindsInstance;
 import dagger.Component;
 import dagger.android.support.AndroidSupportInjectionModule;
@@ -55,6 +57,8 @@ public interface AppComponent {
     void inject(MainApp app);
 
     void inject(MediaControlView mediaControlView);
+
+    @OptIn(markerClass = UnstableApi.class)
     void inject(BackgroundPlayerService backgroundPlayerService);
 
     void inject(ThemeableSwitchPreference switchPreference);

+ 3 - 0
app/src/main/java/com/nextcloud/client/di/ComponentsModule.java

@@ -124,6 +124,8 @@ import com.owncloud.android.ui.preview.PreviewTextStringFragment;
 import com.owncloud.android.ui.preview.pdf.PreviewPdfFragment;
 import com.owncloud.android.ui.trashbin.TrashbinActivity;
 
+import androidx.annotation.OptIn;
+import androidx.media3.common.util.UnstableApi;
 import dagger.Module;
 import dagger.android.ContributesAndroidInjector;
 
@@ -487,6 +489,7 @@ abstract class ComponentsModule {
     abstract InternalTwoWaySyncActivity internalTwoWaySyncActivity();
 
 
+    @OptIn(markerClass = UnstableApi.class)
     @ContributesAndroidInjector
     abstract BackgroundPlayerService backgroundPlayerService();
 

+ 21 - 16
app/src/main/java/com/nextcloud/client/media/BackgroundPlayerService.kt

@@ -13,6 +13,7 @@ import android.content.Context
 import android.content.Intent
 import android.content.IntentFilter
 import android.os.Bundle
+import androidx.annotation.OptIn
 import androidx.media3.common.Player
 import androidx.media3.common.Player.COMMAND_PLAY_PAUSE
 import androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT
@@ -46,7 +47,7 @@ import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.withContext
 import javax.inject.Inject
 
-@UnstableApi
+@OptIn(UnstableApi::class)
 class BackgroundPlayerService : MediaSessionService(), Injectable {
 
     private val seekBackSessionCommand = SessionCommand(SESSION_COMMAND_ACTION_SEEK_BACK, Bundle.EMPTY)
@@ -78,7 +79,7 @@ class BackgroundPlayerService : MediaSessionService(), Injectable {
 
     private val stopReceiver = object : BroadcastReceiver() {
         override fun onReceive(context: Context?, intent: Intent?) {
-            when(intent?.action){
+            when (intent?.action) {
                 RELEASE_MEDIA_SESSION_BROADCAST_ACTION -> release()
                 STOP_MEDIA_SESSION_BROADCAST_ACTION -> exoPlayer.stop()
             }
@@ -110,7 +111,15 @@ class BackgroundPlayerService : MediaSessionService(), Injectable {
                 val playPauseButton =
                     CommandButton.Builder()
                         .setDisplayName("PlayPause")
-                        .setIconResId(CommandButton.getIconResIdForIconConstant(if (mediaSession?.player?.isPlaying!!) CommandButton.ICON_PAUSE else CommandButton.ICON_PLAY))
+                        .setIconResId(
+                            CommandButton.getIconResIdForIconConstant(
+                                if (mediaSession?.player?.isPlaying!!) {
+                                    CommandButton.ICON_PAUSE
+                                } else {
+                                    CommandButton.ICON_PLAY
+                                }
+                            )
+                        )
                         .setPlayerCommand(COMMAND_PLAY_PAUSE)
                         .setExtras(Bundle().apply { putInt(COMMAND_KEY_COMPACT_VIEW_INDEX, 1) })
                         .build()
@@ -132,10 +141,9 @@ class BackgroundPlayerService : MediaSessionService(), Injectable {
                 exoPlayer = createNextcloudExoplayer(this@BackgroundPlayerService, nextcloudClient)
                 mediaSession =
                     MediaSession.Builder(applicationContext, exoPlayer)
-                        // set id to distinct this session to avoid crash (if not set every session has default token empty string i.e "")
-                        // in case we start another session (for eg. for video playback) since releasing the session take little bit of delay
-                        // which can cause conflict with newly created session if not set. But, make sure to release this session to avoid
-                        // multiple session instance being alive.
+                        // set id to distinct this session to avoid crash
+                        // in case session release delayed a bit and
+                        // we start another session for eg. video
                         .setId(BACKGROUND_MEDIA_SESSION_ID)
                         .setCustomLayout(listOf(seekBackward, seekForward))
                         .setCallback(object : MediaSession.Callback {
@@ -161,10 +169,7 @@ class BackgroundPlayerService : MediaSessionService(), Injectable {
                                     .build()
                             }
 
-                            override fun onPostConnect(
-                                session: MediaSession,
-                                controller: MediaSession.ControllerInfo
-                            ) {
+                            override fun onPostConnect(session: MediaSession, controller: MediaSession.ControllerInfo) {
                                 session.setCustomLayout(listOf(seekBackward, seekForward))
                             }
 
@@ -174,20 +179,19 @@ class BackgroundPlayerService : MediaSessionService(), Injectable {
                                 customCommand: SessionCommand,
                                 args: Bundle
                             ): ListenableFuture<SessionResult> {
-                                when (customCommand.customAction) {
+                                return when (customCommand.customAction) {
                                     SESSION_COMMAND_ACTION_SEEK_FORWARD -> {
                                         session.player.seekForward()
-                                        return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
+                                        Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
                                     }
 
                                     SESSION_COMMAND_ACTION_SEEK_BACK -> {
                                         session.player.seekBack()
-                                        return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
+                                        Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
                                     }
 
-                                    else -> {}
+                                    else -> super.onCustomCommand(session, controller, customCommand, args)
                                 }
-                                return super.onCustomCommand(session, controller, customCommand, args)
                             }
                         })
                         .build()
@@ -219,6 +223,7 @@ class BackgroundPlayerService : MediaSessionService(), Injectable {
         // that sometimes onTaskRemove() doesn't get called immediately
         // eventually gets called so the service stops but the notification doesn't clear out.
         // [WORKAROUND] So, explicitly removing the notification here.
+        // TODO revisit after bug solved!
         val nm = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
         nm.cancel(DefaultMediaNotificationProvider.DEFAULT_NOTIFICATION_ID)
         stopSelf()

+ 5 - 10
app/src/main/java/com/owncloud/android/media/MediaControlView.kt

@@ -72,10 +72,6 @@ class MediaControlView(context: Context, attrs: AttributeSet?) :
         }, 100)
     }
 
-    fun stopMediaPlayerMessages() {
-        handler.removeMessages(SHOW_PROGRESS)
-    }
-
     @Suppress("MagicNumber")
     private fun initControllerView() {
         binding.playBtn.requestFocus()
@@ -131,7 +127,7 @@ class MediaControlView(context: Context, attrs: AttributeSet?) :
                 val pos = setProgress()
 
                 if (!isDragging) {
-                    sendMessageDelayed(obtainMessage(SHOW_PROGRESS), (1000 - pos % 1000).toLong())
+                    sendMessageDelayed(obtainMessage(SHOW_PROGRESS), (1000 - pos % 1000))
                 }
             }
         }
@@ -229,9 +225,9 @@ class MediaControlView(context: Context, attrs: AttributeSet?) :
     fun updatePausePlay() {
         binding.playBtn.icon = ContextCompat.getDrawable(
             context,
-            // isPlaying reflects if the playback is actually moving forward, If the media is buffering and it will play when ready
-            // it would still return that it is not playing. So, in case of buffering it will show the pause icon which would show that
-            // media is loading, when user has not paused but moved the progress to a different position this works as a buffering signal.
+            // use isPlaying instead of playWhenReady
+            // it represents only the play/pause state
+            // which is needed to show play/pause icons
             if (playerControl?.isPlaying == true) {
                 R.drawable.ic_pause
             } else {
@@ -274,7 +270,6 @@ class MediaControlView(context: Context, attrs: AttributeSet?) :
 
     @Suppress("MagicNumber")
     override fun onClick(v: View) {
-
         playerControl?.let { playerControl ->
             val playing = playerControl.playWhenReady
             val id = v.id
@@ -316,7 +311,7 @@ class MediaControlView(context: Context, attrs: AttributeSet?) :
         }
 
         playerControl?.let { playerControl ->
-            val duration = playerControl.duration.toLong()
+            val duration = playerControl.duration
             val newPosition = duration * progress / 1000L
             playerControl.seekTo(newPosition)
             binding.currentTimeText.text = formatTime(newPosition)

+ 10 - 12
app/src/main/java/com/owncloud/android/ui/preview/PreviewMediaActivity.kt

@@ -64,7 +64,6 @@ import com.nextcloud.client.jobs.download.FileDownloadHelper
 import com.nextcloud.client.media.BackgroundPlayerService
 import com.nextcloud.client.media.ErrorFormat
 import com.nextcloud.client.media.ExoplayerListener
-import com.nextcloud.client.media.ExoplayerListener.Companion
 import com.nextcloud.client.media.NextcloudExoPlayer.createNextcloudExoplayer
 import com.nextcloud.client.network.ClientFactory
 import com.nextcloud.client.network.ClientFactory.CreationException
@@ -111,6 +110,7 @@ import javax.inject.Inject
  * instantiation too.
  */
 @Suppress("TooManyFunctions")
+@OptIn(UnstableApi::class)
 class PreviewMediaActivity :
     FileActivity(),
     FileFragment.ContainerActivity,
@@ -144,7 +144,6 @@ class PreviewMediaActivity :
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
 
-
         if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O) {
             setTheme(R.style.Theme_ownCloud_Toolbar)
         }
@@ -157,10 +156,10 @@ class PreviewMediaActivity :
         applyWindowInsets()
         initArguments(savedInstanceState)
 
-        if(MimeTypeUtil.isVideo(file)){
+        if (MimeTypeUtil.isVideo(file)) {
             // release any background media session if exists
             sendAudioSessionReleaseBroadcast()
-        }else if(MimeTypeUtil.isAudio(file)){
+        } else if (MimeTypeUtil.isAudio(file)) {
             val stopPlayer = Intent(BackgroundPlayerService.STOP_MEDIA_SESSION_BROADCAST_ACTION).apply {
                 setPackage(packageName)
             }
@@ -344,7 +343,7 @@ class PreviewMediaActivity :
                 nextcloudClient?.let { client ->
                     handler.post {
                         videoPlayer = createNextcloudExoplayer(this, client)
-                        videoMediaSession = MediaSession.Builder(this,videoPlayer as Player).build()
+                        videoMediaSession = MediaSession.Builder(this, videoPlayer as Player).build()
 
                         videoPlayer?.let { player ->
                             player.addListener(
@@ -386,13 +385,14 @@ class PreviewMediaActivity :
                     playAudio()
                     binding.audioControllerView.setMediaPlayer(audioMediaController)
                 } catch (e: Exception) {
-                    Log_OC.e(TAG,"exception raised while getting the media controller ${e.message}")
+                    Log_OC.e(TAG, "exception raised while getting the media controller ${e.message}")
                 }
             },
             MoreExecutors.directExecutor()
         )
     }
 
+    @Suppress("TooGenericExceptionCaught")
     private fun playAudio() {
         if (file.isDown) {
             prepareAudioPlayer(file.storageUri)
@@ -400,7 +400,7 @@ class PreviewMediaActivity :
             try {
                 LoadStreamUrl(this, user, clientFactory).execute(file.localId)
             } catch (e: Exception) {
-                Log_OC.e(TAG, "Loading stream url not possible: $e")
+                Log_OC.e(TAG, "Loading stream url for Audio not possible: $e")
             }
         }
     }
@@ -434,7 +434,7 @@ class PreviewMediaActivity :
                     MaterialAlertDialogBuilder(this@PreviewMediaActivity)
                         .setMessage(message)
                         .setPositiveButton(R.string.common_ok) { _: DialogInterface?, _: Int ->
-                           audioPlayer.seekToDefaultPosition()
+                            audioPlayer.seekToDefaultPosition()
                             audioPlayer.pause()
                         }
                         .setCancelable(false)
@@ -468,7 +468,6 @@ class PreviewMediaActivity :
         }
     }
 
-    @OptIn(markerClass = [UnstableApi::class])
     private fun applyWindowInsets() {
         val playerView = binding.exoplayerView
         val exoControls = playerView.findViewById<FrameLayout>(R.id.exo_bottom_bar)
@@ -497,7 +496,6 @@ class PreviewMediaActivity :
         }
     }
 
-    @OptIn(UnstableApi::class)
     private fun setupVideoView() {
         initWindowInsetsController()
         val type = WindowInsetsCompat.Type.systemBars()
@@ -692,7 +690,7 @@ class PreviewMediaActivity :
             try {
                 LoadStreamUrl(this, user, clientFactory).execute(file.localId)
             } catch (e: Exception) {
-                Log_OC.e(TAG, "Loading stream url not possible: $e")
+                Log_OC.e(TAG, "Loading stream url for Video not possible: $e")
             }
         }
     }
@@ -770,7 +768,7 @@ class PreviewMediaActivity :
     }
 
     override fun onDestroy() {
-        mediaControllerFuture?.let {MediaController.releaseFuture(it)}
+        mediaControllerFuture?.let { MediaController.releaseFuture(it) }
         super.onDestroy()
 
         Log_OC.v(TAG, "onDestroy")

+ 6 - 4
app/src/main/java/com/owncloud/android/ui/preview/PreviewMediaFragment.kt

@@ -120,11 +120,12 @@ class PreviewMediaFragment : FileFragment(), OnTouchListener, Injectable {
     private var mediaSession: MediaSession? = null
     private var nextcloudClient: NextcloudClient? = null
 
+    @OptIn(UnstableApi::class)
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
 
         // release any background media session if exists
-        val intent = Intent(BackgroundPlayerService.STOP_MEDIA_SESSION_BROADCAST_ACTION).apply {
+        val intent = Intent(BackgroundPlayerService.RELEASE_MEDIA_SESSION_BROADCAST_ACTION).apply {
             setPackage(requireActivity().packageName)
         }
         requireActivity().sendBroadcast(intent)
@@ -208,7 +209,6 @@ class PreviewMediaFragment : FileFragment(), OnTouchListener, Injectable {
             autoplay = exoPlayer?.isPlaying ?: false
             putLong(EXTRA_PLAY_POSITION, savedPlaybackPosition)
             putBoolean(EXTRA_PLAYING, autoplay)
-
         }
     }
 
@@ -254,7 +254,10 @@ class PreviewMediaFragment : FileFragment(), OnTouchListener, Injectable {
             it.addListener(listener)
         }
         // session id needs to be unique since this fragment is used in viewpager multiple fragments can exist at a time
-        mediaSession = MediaSession.Builder(requireContext(),exoPlayer as Player).setId(System.currentTimeMillis().toString()).build()
+        mediaSession = MediaSession.Builder(
+            requireContext(),
+            exoPlayer as Player
+        ).setId(System.currentTimeMillis().toString()).build()
     }
 
     private fun releaseVideoPlayer() {
@@ -545,7 +548,6 @@ class PreviewMediaFragment : FileFragment(), OnTouchListener, Injectable {
      * Opens the previewed file with an external application.
      */
     private fun openFile() {
-
         containerActivity.fileOperationsHelper.openFile(file)
     }