Search code examples
androidkotlinsoundpool

SoundPool with ImageView Usage Like Switch


im stuck while coding my app and i couldn't find any source for solve that problem.

Problem : I want to use an imageview as switch. When i click to imageView i want to start my SoundPool.Player and if i click again to imageView then it should be stop.

I can start sounds when i click to imageView but i can't stop it.

class PlayerPool() {

lateinit var poolPlayer : SoundPool
var playerId : Int = 0

companion object {

    const val pageTag = "PlayerPool"
    var instance: PlayerPool? = null

    fun getInstance(context:Context): PlayerPool? {
        if(instance == null)
            instance = PlayerPool()
        return instance
    }

}

fun poolStarter(ctx : Context, position: Int){

    poolPlayer = SoundPool.Builder().setMaxStreams(10).build()
    val poolSounds = poolPlayer.load(ctx,position,1)

    poolPlayer.setOnLoadCompleteListener { soundPool, sampleId, status ->

        playerId = poolPlayer.play(poolSounds, 0.1f, 0.1f, 1, 0, 1f)

    }

}

fun poolPausePlayer(){

        poolPlayer.stop(playerId)

}

}

class MixFragmentAdapter(
val mixList: ArrayList<SoundModel>,
val mixListener:RowClickListener<SoundModel>
) : BaseRecyclerAdapter<SoundModel,RowFragmentMixBinding>() {

override val layoutRes: Int
    get() = R.layout.row_fragment_mix
override val arrayList: ArrayList<SoundModel>
    get() = mixList

override fun bindView(
    binding: RowFragmentMixBinding,
    currentData: SoundModel,
    position: Int
) {

    binding.ivMixCardImages.setImageResource(mixList[position].soundImage)
    binding.root.setOnClickListener {

        mixListener.onClick(position, item = mixList[position])

        binding.switchMusicControl.setOnCheckedChangeListener { buttonView, isChecked ->

            if (isChecked){

                PlayerPool.getInstance(binding.ivMixCardImages.context)!!.poolStarter(binding.ivMixCardImages.context,position)

            }
            else{

                PlayerPool.getInstance(binding.ivMixCardImages.context)!!.poolPausePlayer()

            }


        }


    }
}

}

<androidx.cardview.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="6dp"
    app:cardCornerRadius="20dp"
    app:cardBackgroundColor="#7E57C2"
    app:cardElevation="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/tvMixSounds" >
    
    <androidx.constraintlayout.widget.ConstraintLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageView
            android:id="@+id/ivMixCardImages"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:padding="10dp"
            android:backgroundTint="@android:color/white"
            app:layout_constraintDimensionRatio="1:1"
            app:layout_constraintBottom_toTopOf="@+id/tvCardInformation"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tvMixCardInformation"
            app:layout_constraintTop_toTopOf="parent"
            android:src="@drawable/ic_fire" />


        <TextView
            android:id="@+id/tvMixCardInformation"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:textSize="16sp"
            android:textStyle="bold"
            android:gravity="center"
            android:visibility="gone"
            android:text="Ateş!"
            app:layout_constraintTop_toBottomOf="@id/ivMixCardImages"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />

        <Switch
            android:id="@+id/switchMusicControl"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

Solution

  • this is a common issue for those using soundpool for the first time. if you look carefully at the docs for soundpool, play uses the parameter "soundID", while stop uses the parameter "streamID". it's easy to overlook this and use the soundID returned from the load function for both commands, as your code does. i've even seen android tutorial examples get this wrong. instead use these commands:

    s1 = sound.load(Main.this, R.raw.mosq1, 1);  
    if (l1==true){p1=sound.play(s1, 1, 1, 0, rep, 1);     
    sound.stop(p1);
    

    must ensure p1 is right.

    About your code :

        fun poolStarter(ctx : Context, position: Int){
        ....
        poolPlayer.setOnLoadCompleteListener { soundPool, sampleId, status ->
    
            playerId = poolPlayer.play(poolSounds, 0.1f, 0.1f, 1, 0, 1f)
    
        }}
    
        fun poolPausePlayer(){
                poolPlayer.stop(playerId)
        }
    

    when you use , must ensure playerId is the same.

    try change your code in MixFragmentAdapter:

        lateinit var p:PlayerPool
        override fun bindView(
            binding: RowFragmentMixBinding,
            currentData: SoundModel,
            position: Int
        ) {
    
            var context = binding.ivMixCardImages.context
            p =PlayerPool.getInstance(context)!!
            binding.ivMixCardImages.setImageResource(mixList[position].soundImage)
            binding.root.setOnClickListener {
                mixListener.onClick(position, item = mixList[position])
                binding.switchMusicControl.setOnCheckedChangeListener { buttonView, isChecked ->
                    if (isChecked){
                        p.poolStarter(context, position )
                    }
                    else{
                        p.poolPausePlayer()
                    }
                }
    
            }
        }