BraveSentry
BraveSentry

Reputation: 349

Keep sound playing within the App but stop it when App goes to the background

So I have a Sound I want to play continuously throughout the whole of my App. But as soon as the App goes to background, the sound should stop. I´m trying to do this during onStop(). The problem is that onStop() is called every time the activity is stopped, regardless of whether I stay within the app or not. Is there a way to differentiate between those cases? Something like this:

override fun onStop() {
    if [App is left but not destroyed] {
        super.onStop()
        mediaLength = mediaPlayer.currentPosition
        mediaPlayer.pause()
    }
    else { //i.e. activity is left but the new activity is from the same app.
        super.onStop()
    }
}

EDIT:

I tried to implement this answer, but had to translate it to kotlin. I think I did everything right, but I get an unresolved reference: mediaPlayer in the Lifecycleobserver.

Here´s the Observer:

package com.example.asdasd.soulfetch

import android.app.Application
import android.arch.lifecycle.Lifecycle
import android.arch.lifecycle.LifecycleObserver
import android.arch.lifecycle.OnLifecycleEvent
import android.arch.lifecycle.ProcessLifecycleOwner


class CheckLifeCycle: Application(), LifecycleObserver {
override fun onCreate() {
    super.onCreate()
    ProcessLifecycleOwner.get().getLifecycle().addObserver(this)
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onAppBackground() {
    MainActivity.mediaPlayer.pause()
}
}

And here are the relevant parts of MainActivity

class MainActivity : AppCompatActivity() {

lateinit var mediaPlayer: MediaPlayer

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    mediaPlayer = MediaPlayer()

    fun playBordun() {
        mediaPlayer = MediaPlayer.create(this, R.raw.cbordun)
        mediaPlayer.isLooping = true
        mediaPlayer.start()
        }
    playBordun()
    }
override fun onDestroy() {
    super.onDestroy()
    mediaPlayer.stop()
    mediaPlayer.reset()
    mediaPlayer.release()
    }

Any idea what I am missing here?

Upvotes: 0

Views: 2266

Answers (4)

chumyuenlaw
chumyuenlaw

Reputation: 1

Based on @Elam parithi 's answer, I made some modifications. This method can keep playing background music while switching activities within the app, and the music will be stopped when the BACK/HOME/MENU button is pressed or use gesture navigation (swipe from bottom to top) to go back HOME.

I create another class BackgroundMusicService using Service to play the background music.

import android.app.Service
import android.content.Intent
import android.media.MediaPlayer
import android.os.Build
import android.os.IBinder
import androidx.annotation.RequiresApi


class BackgroundMusicService : Service() {

    private lateinit var player: MediaPlayer

    val ACTION_STOP = "stop_music_service"
    val ACTION_START = "start_music_service"

    override fun onBind(p0: Intent?): IBinder? {
        return null
    }

    @RequiresApi(Build.VERSION_CODES.N)
    override fun onCreate() {
        super.onCreate()

        player = MediaPlayer.create(this, R.raw.bgm)
        player.isLooping = true // Set looping
        player.setVolume(50f, 50f)
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        if(intent.action == ACTION_STOP)
            player.stop()
        else
            player.start()
        return startId
    }

    override fun onStart(intent: Intent, startId: Int) {
        // TO DO
    }

    fun onUnBind(arg0: Intent): IBinder? {
        // TO DO Auto-generated method
        return null
    }

    fun onStop() {
        player.stop()
    }

    fun onPause() {

    }

    override fun onDestroy() {
        player.stop()
        player.release()
    }

    override fun onLowMemory() {

    }
}

In the onAppBackground() function, I use the code below to stop the background music. Switching the activities within the app doesn't stop the BGM. However, when exiting the app, the BGM will be stopped.

@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onAppBackground() {
    val musicIntent = Intent(this, BackgroundMusicService::class.java)
    musicIntent.action = "stop_music_service"
    stopService(musicIntent)
}

BTW, the including library should be the androidx package, because the android.arch package will cause conflict.

implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'

I hope this help.

Upvotes: 0

Elam parithi
Elam parithi

Reputation: 98

You can use the LifecycleObserver to check whether the application in background or not.

public class CheckLifeCycle extends Application implements LifecycleObserver {

@Override
public void onCreate() 
{
    super.onCreate();
    ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}

@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onAppBackground()
{
    MainActivity.mediaPlayer.pause();
}

}

and add the class name CheckLifeCycle in a manifest

<manifest >
    ....
    <application
        android:name=".CheckLifeCycle"
        ......
    </application>

</manifest>

don't forget to include the basic Support library in gradle.

implementation "android.arch.lifecycle:extensions:1.1.1"
annotationProcessor "android.arch.lifecycle:compiler:1.1.1"

Upvotes: 0

touhid udoy
touhid udoy

Reputation: 4442

You can't gain such functionality using activity. Activity is highly prone to be destroyed, recreated. You should use Service to attain such functionality, as the service will persist, whether your activity is destroyed or not.

This article is old and out of date, but can still learn using service with music from it

Upvotes: 1

Antoine El Murr
Antoine El Murr

Reputation: 317

You can create a custom Application class (extends Application) and implement it with LifecycleObserver interface, and create a function within the CustomApplication class and annotate it with @OnLifecycleEvent(Lifecycle.Event.ON_STOP) so when the app is in background the function will be triggered and inside it you will put the logic to stop the mediaPlayer (make it global to access it from different place whiting the app)

In order to use the LifecycleObserver you need to add LifeCycle to your app (it's an Android architecture component) here is the link: https://developer.android.com/topic/libraries/architecture/adding-components

Upvotes: 1

Related Questions