Problems with SimpleAudioEngine resume

Hi,

I’m writing a cross platform app (iOS and Android) using the 2.0.3 cocos2dx.

I’m using SimpleAudioEngine to play background music and sound effects.

In AppDelegate.cpp - applicationDidEnterBackground I pause
SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();

In AppDelegate.cpp - applicationWillEnterForeground I resume
SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();

In my destructor I stop all music and effects
SimpleAudioEngine::sharedEngine()->end();

I scheduled a function call to check if the current track has finished playing and start the next random one.
this->schedule(schedule_selector(GameScreen::playmusic), 1.0f);

In short the code in playmusic checks if the track is playing using
SimpleAudioEngine::sharedEngine()->isBackgroundMusicPlaying()
If not playing then I start a new track
SimpleAudioEngine::sharedEngine()->playBackgroundMusic("blah.mp3")

This is working ok.
Closing my app stops the music, starting the scene starts a new random track and when 1 track finishes, the next random one starts.
Pressing the home button, stops the music, reopening the app resumes the music and app correctly

I do have a problem (on Android at least) when I lock the phone (press power button) and unlock it again (press power button again).
The function applicationWillEnterForeground is called even though the phone is still on the lock screen.
This means that the music starts again (and I think the game itself) before I have unlocked the phone.

After unlocking the phone, the applicationDidEnterBackground and applicationWillEnterForeground are both called again.

My playmusic function is called again and isBackgroundMusicPlaying = false so I start a new track even though the old track is still playing.

Is there a way to make sure the app only starts when the phone is actually unlocked (i.e. the app is visible).
Also, is there a way to tell the difference between paused and finished the track?
In both cases isBackgroundMusicPlaying = false.

Thanks

Yep, it is an issue. Because android will trigger a resume message when the power menu is clicked though it is locked.
And there is not a message for unlocking the screen.

Thanks, I just tested Cut the Rope and it has the same issue (I don’t feel so bad now).

Is there any way to tell if a background music file has finished rather than just paused?

In my playmusic function, I start a playing a new file if !isBackgroundMusicPlaying()

After waking the phone, the music starts playing before the screen is unlocked (is the game logic running at this point?).
After its unlocked, the music stops playing again and is then resumed.
It looks like applicationDidEnterBackground and applicationWillEnterForeground are both called again after the unlock.

My playmusic function is called again and isBackgroundMusicPlaying() == false so I start a new playing a music file rather than just resuming the old one. This could just be a timing issue, maybe the playmusic schedule is fired before the applicationWillEnterForeground is finished.

I tried to resume the file again and check isBackgroundMusicPlaying(), it still returns false so starts a new file.

//double check its not a pause
SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();

if(SimpleAudioEngine::sharedEngine()->isBackgroundMusicPlaying())
return;

SimpleAudioEngine::sharedEngine()->playBackgroundMusic(………

Is there a delay between calling resumeBackgroundMusic and isBackgroundMusicPlaying() returning true?

I just noticed this in the log when unlocking the phone and after applicationWillEnterForeground is called.

MediaPlayer-JNI(8359): MediaPlayer finalized without being released

This is logged just before my isBackgroundMusicPlaying == false.

That’s probably why a new song is played.

Any ideas why this is being logged?

Edit libcocos for android like this, it helps us:

`
Cocos2dxActivity.java:

private boolean mToBeResumed = false;
private boolean mLostFocus = false;

@Override
protected void onResume() {
	super.onResume();
	
	mToBeResumed = mLostFocus;
	
	if (!mLostFocus) {
		this.mGLSurfaceView.onResume();
		Cocos2dxHelper.onResume();
	}
}

@Override
protected void onPause() {
	super.onPause();
	mLostFocus = true;
	
	Cocos2dxHelper.onPause();
	this.mGLSurfaceView.onPause();
}

@Override
public void onWindowFocusChanged(boolean hasFocus) {
	super.onWindowFocusChanged(hasFocus);
	
	mLostFocus = !hasFocus;
	if (mToBeResumed && hasFocus) {
		mToBeResumed = false;
		this.mGLSurfaceView.onResume();
		onResume();
	}
}

…`

[edit ] Atleast I can say that this solution doesnt work for kitkat…

I tried the solution above but it still doesnt work on cocos2d-x 2.2.3 and kitkat 4.4 … does this work for 4.1, 4.2 , etc???