Search code examples
androidmedia-playerexoplayerforegroundnotificationandroid-media3

How to Play the next and previous song on the media3 player view


I am implementing a audio app, where I have displayed all the songs in the home fragment with recyclerview and on click of that item a details fragment will open and the audio will start. I am using the media3 playerview on the layout to play the audio. In the player view there is default play , pause , seek and previous and next button is present by default . I want to implement that when the play next or play previous icon is clicked on that player view next and previous song should play from that song list . How can I implement that?


Solution

  • When you get the list of songs, First create a MediaItem:

    val mediaItems = list.map { 
        MediaItem.fromUri(Uri.parse(it))
    }
    

    Then, Add mediaItems to the player:

    player.addMediaItems(mediaItems)
    

    Now, Define a ClickListener on RecyclerView item and pass the index of the clicked item to the player to play.

    player.seekToDefaultPosition(index)
    

    Finally, when the user clicks on the next/previous buttons, The player will play the next/previous item from the media items we added.

    Additionally, You can use a custom Controller Layout for customization and place everything wherever you want. But you need to use Media3 defaults id's to make ExoPlayer set the needed values to them:

    <androidx.media3.ui.PlayerView
        android:id="@+id/player_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:resize_mode="fixed_width"
        app:surface_type="texture_view"
        app:use_controller="true"
        app:auto_show="true"
        app:hide_on_touch="false"
        app:animation_enabled="false"
        app:controller_layout_id="@layout/music_video_player_controllers"
        app:show_buffering="always"/>
    

    You can get the idea with this layout example:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        xmlns:tool="http://schemas.android.com/tools"
        android:id="@+id/controller_layout"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_gravity="bottom"
        app:cardUseCompatPadding="true"
        app:cardBackgroundColor="@color/charade"
        app:cardCornerRadius="10dp"
        android:forceDarkAllowed="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent">
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingVertical="@dimen/_15sdp">
    
            <androidx.media3.ui.DefaultTimeBar
                android:id="@+id/exo_progress"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginHorizontal="@dimen/_24sdp"
                android:layout_weight="1"
                app:buffered_color="@color/white"
                app:played_color="@color/red"
                app:scrubber_color="@color/red"
                app:unplayed_color="@color/white1"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"/>
    
            <TextView
                android:id="@id/exo_position"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:minWidth="@dimen/_39sdp"
                android:textColor="@color/white"
                android:textSize="14sp"
                app:layout_constraintTop_toBottomOf="@+id/exo_progress"
                app:layout_constraintStart_toStartOf="@id/exo_progress"
                tool:text="00:00" />
    
            <TextView
                android:id="@id/exo_duration"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:gravity="center"
                android:minWidth="@dimen/_39sdp"
                android:textColor="@color/white"
                android:textSize="14sp"
                app:layout_constraintEnd_toEndOf="@id/exo_progress"
                app:layout_constraintTop_toBottomOf="@+id/exo_progress"
                tool:text="00:00" />
    
            <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/_15sdp"
                app:layout_constraintTop_toBottomOf="@id/exo_progress"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent">
    
                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="@dimen/_28sdp"
                    android:layout_height="@dimen/_28sdp"
                    android:id="@+id/exo_ffwd"
                    android:layout_marginStart="@dimen/_12sdp"
                    app:layout_constraintStart_toEndOf="@+id/play_pause_container"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintBottom_toBottomOf="parent">
    
                    <androidx.appcompat.widget.AppCompatImageView
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:padding="1dp"
                        app:srcCompat="@drawable/ic_baseline_seek_forward_24" />
    
                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:textSize="8sp"
                        android:paddingEnd="1dp"
                        android:paddingTop="@dimen/_6sdp"
                        android:text="15"
                        android:textColor="@color/white"
                        android:gravity="center"/>
    
                </androidx.constraintlayout.widget.ConstraintLayout>
    
                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/play_pause_container"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintEnd_toEndOf="parent">
    
                    <ImageView
                        android:layout_width="@dimen/_31sdp"
                        android:layout_height="@dimen/_31sdp"
                        android:id="@+id/exo_play_pause"
                        app:srcCompat="@drawable/ic_pause_24"
                        app:layout_constraintTop_toTopOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintBottom_toBottomOf="parent"/>
    
                </androidx.constraintlayout.widget.ConstraintLayout>
    
                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="@dimen/_28sdp"
                    android:layout_height="@dimen/_28sdp"
                    android:id="@+id/exo_rew"
                    android:layout_marginEnd="@dimen/_12sdp"
                    app:layout_constraintEnd_toStartOf="@+id/play_pause_container"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintBottom_toBottomOf="parent">
    
                    <androidx.appcompat.widget.AppCompatImageView
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:padding="1dp"
                        app:srcCompat="@drawable/ic_baseline_seek_backward_24" />
    
                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:textSize="8sp"
                        android:paddingEnd="1dp"
                        android:paddingTop="@dimen/_6sdp"
                        android:text="15"
                        android:textColor="@color/white"
                        android:gravity="center"/>
    
                </androidx.constraintlayout.widget.ConstraintLayout>
    
            </androidx.constraintlayout.widget.ConstraintLayout>
    
        </androidx.constraintlayout.widget.ConstraintLayout>
    
    </androidx.cardview.widget.CardView>
    

    PS: Pay attention to the id's like exo_position, exo_duration. Press ctrl and click on them to see all of the id's you can use.