Titanium JIRA Archive
Appcelerator Community (AC)

[AC-897] Android: Creating/playing Sound objects can cause app to crash on exit

GitHub Issuen/a
TypeBug
Priorityn/a
StatusResolved
ResolutionDuplicate
Resolution Date2014-06-09T17:38:27.000+0000
Affected Version/sn/a
Fix Version/sn/a
ComponentsTitanium SDK & CLI
Labelsn/a
ReporterDavid Psenicka
AssigneeRitu Agrawal
Created2014-06-09T17:11:28.000+0000
Updated2016-03-08T07:37:12.000+0000

Description

Problem

An app that creates a Titanium.Media.Sound object and calls the the play method on it can cause a java.lang.IllegalStateException exception to occur when the main window closes and the app exits. The exception seems to rarely occur in apps that are light on resources, but an app using a lot of memory/resources might crash 1 out of 4 or 5 times it is executed. Output during the crash is:
05-10 17:47:20.445: W/dalvikvm(2004): threadid=28: thread exiting with uncaught exception (group=0xb1a18ba8)
05-10 17:47:20.475: E/TiApplication(2004): (Timer-28) [46093,46093] Sending event: exception on thread: Timer-28 msg:java.lang.IllegalStateException; Titanium 3.2.3,2014/04/22 10:17,b958a70
05-10 17:47:20.475: E/TiApplication(2004): java.lang.IllegalStateException
05-10 17:47:20.475: E/TiApplication(2004): 	at android.media.MediaPlayer.isPlaying(Native Method)
05-10 17:47:20.475: E/TiApplication(2004): 	at ti.modules.titanium.media.TiSound$2.run(TiSound.java:516)
05-10 17:47:20.475: E/TiApplication(2004): 	at java.util.Timer$TimerImpl.run(Timer.java:284)
05-10 17:47:20.495: E/AndroidRuntime(2004): FATAL EXCEPTION: Timer-28
05-10 17:47:20.495: E/AndroidRuntime(2004): Process: com.plezzus.magnoids, PID: 2004
05-10 17:47:20.495: E/AndroidRuntime(2004): java.lang.IllegalStateException
05-10 17:47:20.495: E/AndroidRuntime(2004): 	at android.media.MediaPlayer.isPlaying(Native Method)
05-10 17:47:20.495: E/AndroidRuntime(2004): 	at ti.modules.titanium.media.TiSound$2.run(TiSound.java:516)
05-10 17:47:20.495: E/AndroidRuntime(2004): 	at java.util.Timer$TimerImpl.run(Timer.java:284)

Test case

The exception seems to be caused by a race condition that's hard to reproduce... I've located the source of the problem at the onDestroy() method at line 534 in TiSound.java as the cause of the error. To make a reliable test case, I patched TiSound.java by adding a delay after mp.release() at line 537. The delay makes it easier for the race condition to happen. I changed onDestroy at line 534 in TiSound.java to read:
	public void onDestroy()
	{
		if (mp != null) {
			mp.release();
			Log.d(TAG, "begin delay");
			for (int i = 0; i < 1000000000; ++i) {} // delay-causing no-op loop to help race condition to occur
			Log.d(TAG, "end delay");
			mp = null;
		}
		// TitaniumMedia clears out the references after onDestroy.
	}
The test case app.js is:
var win = Titanium.UI.createWindow({  
    title:'Sound Bug',
    fullscreen: true,
    exitOnClose: true    
});
var bell = Ti.Media.createSound({url: 'bell.mp3', preload: true, volume: 1});
win.addEventListener('open', function() {
    setTimeout(function() {
	bell.play();
	setTimeout(function() {
	    win.close();
	}, 100);
    }, 1000);
});
win.open();
The test might have to be run multiple times to produce the exception. Also, bell.mp3 is attached.

Logs

Output of test case:
[DEBUG] TiSound: (main) [1985,1985] begin delay
[WARN]  dalvikvm: threadid=14: thread exiting with uncaught exception (group=0xb1a77ba8)
[ERROR] TiApplication: (Timer-0) [870,2855] Sending event: exception on thread: Timer-0 msg:java.lang.IllegalStateException; Titanium 3.2.3,2014/06/09 10:38,b958a70
[ERROR] TiApplication: java.lang.IllegalStateException
[ERROR] TiApplication: 	at android.media.MediaPlayer.isPlaying(Native Method)
[ERROR] TiApplication: 	at ti.modules.titanium.media.TiSound$2.run(TiSound.java:516)
[ERROR] TiApplication: 	at java.util.Timer$TimerImpl.run(Timer.java:284)
[INFO]  Process: Sending signal. PID: 1938 SIG: 9

Discussions

Q/A Link: http://developer.appcelerator.com/question/174077/using-sound-objects-in-android-app-causes-java-exception-and-crash-on-app-exit Current workaround: I've modifed the onDestroy() method in TiSound.java to read:
	public void onDestroy()
	{
		stopProgressTimer(); // stop the timer so it won't cause exception
		if (mp != null) {
			mp.release();
			mp = null;
		}
		// TitaniumMedia clears out the references after onDestroy.
	}

Attachments

FileDateSize
bell.mp32014-06-09T17:11:28.000+000039287

Comments

  1. Ritu Agrawal 2014-06-09

    David - Excellent description and great writeup. Much appreciated. Thanks for the workaround. However, this is a duplicate of TIMOB-16134. Please watch TIMOB-16134 for latest updates.

JSON Source