×

Discussion Board

Results 1 to 11 of 11
  1. #1
    Registered User
    Join Date
    Mar 2008
    Posts
    1

    N80: MIDlet crashes after recording short audio segments for 7-20 minutes

    Hi,

    I have a MIDlet that records short audio segments using RecordControl. Each segment is 1-8 seconds. It works fine for between 7 and 20 minutes, but then crashes.

    Usually it crashes with no exception (even though I tried to catch all exceptions and errors), sometimes RecordControl.commit() fails with an IOException that reports "commit failed: -4". But it never can record for more than about 20 minutes.

    I tried this with both a player and RecordControl that exist all the time but are started and stopped, and with new instances of Player and RecordControl for each recording. The MIDlet does not run out of memory; I call gc() after every recording and show free memory on the screen, and it is not going down.

    The recording is into a ByteArrayOutputStream. To test this failure, I removed all uses of the actual audio, but it still crashes.

    I do not get these crashes if I record for a few seconds, then let the MIDlet run forever in a loop.

    The recocrding is into 8000 samples/s PCM, 1 channel. I do get usable WAV files as long as the MIDlet is running.

    Thanks, Sivan

  2. #2
    Registered User
    Join Date
    Aug 2008
    Posts
    4

    Re: N80: MIDlet crashes after recording short audio segments for 7-20 minutes

    Well, I just wanted to say I have the same problem

    Ive also tried catching the IOException and then creating a new Player and RecordController, but I still get the same error.
    Even in a new Thread.

    Have you found a solution, Id be glad to hear it.

    By the way my phone is a Nokia 6220.

    Cheers

  3. #3
    Registered User
    Join Date
    Oct 2007
    Posts
    19

    Re: N80: MIDlet crashes after recording short audio segments for 7-20 minutes

    Hi Sivan,

    Each Player has upper limit for recording at once(in your case 20 min). Recording is not only thing going on behind the scene. In fact, 20 mins of recording is a huge amount of data. Though you have called gc(), it will not execute Garbage collector immediately. Ideally, GC is called whenever the processor is free. OutOfMemorryError seems to be the only culprit for the app crash.

    You should use multiple players for larger recording. You will observe minor glitches during player switching, but it will definitely solve the crash.

    Regards,
    Bharat.

  4. #4
    Registered User
    Join Date
    Aug 2008
    Posts
    4

    Re: N80: MIDlet crashes after recording short audio segments for 7-20 minutes

    Thank you for your answer Bahrat (even if it wasnt directly to me)

    I do use multiple players and still get the same error with ALOT of free memory
    600k of 800k total.

    Ive tried with gc() and Thread.yield() but it still produces the same error.

    The below loop works for some 20 minutes and then fails throwing
    java.io.IOException: failed -4

    After this, no recording can be made (Without commit giving the exception) until Midlet is restarted.
    /**
    * To allow for a certain amount of exceptions when recording.
    * So that this thread doesnt die to easily
    */
    int occurredNrExceptions = 0;

    try {

    while (true) {

    ByteArrayOutputStream baos;

    // Lets allow for n-time IOExceptions
    try {
    baos = new ByteArrayOutputStream();
    p = Manager.createPlayer("capture://audio);
    p.realize();
    p.prefetch();

    // Get the RecordControl, set the record stream,
    rc = (RecordControl) p.getControl("RecordControl");

    rc.setRecordStream(baos);
    rc.startRecord();
    p.start();
    Thread.sleep(3000);

    rc.stopRecord();
    rc.commit();
    p.stop();
    p.close();


    } catch (IOException ex) {
    if (occurredNrExceptions++ < allowedNrException) {
    try{
    p.deallocate();
    p.close();
    }catch(IllegalStateException ise){
    // player was allready closed, DO NOTHING
    }
    continue;
    } else
    throw ex;
    occurredNrExceptions = 0;

    // Use data in baos ...
    }

    Please help if you know this!

    Could this be devicespecefic bugs?
    Last edited by lud3e; 2008-09-09 at 14:10.

  5. #5
    Registered User
    Join Date
    Aug 2008
    Posts
    4

    Re: N80: MIDlet crashes after recording short audio segments for 7-20 minutes

    Dear Nokia.

    This issue has not been resolved and its also noted as "Audio capture crashes 6600" http://discussion.forum.nokia.com/fo...ad.php?t=51875 which means at least 3 phones, my "6220 Classic", N80 and 6600 are affected.

    Please if someone who works with Nokias java implementation could address this issue. (Or other who knows the answer)

    Is this a Nokia cross-model bug or is there a way of resetting Manager when this happens.

    Kind Regards
    Ludvig Derning

  6. #6
    Registered User
    Join Date
    Feb 2009
    Posts
    2

    Re: N80: MIDlet crashes after recording short audio segments for 7-20 minutes

    +1
    I have the same issue after several minutes while I record 1 second in a loop on a N95 8 Go.
    Help is clearly needed
    if someone has succeeded to fix that, I will be happy.

  7. #7
    Registered User
    Join Date
    Feb 2009
    Posts
    2

    Re: N80: MIDlet crashes after recording short audio segments for 7-20 minutes

    Quote Originally Posted by sivan.toledo@gmail.com View Post
    Hi,

    I have a MIDlet that records short audio segments using RecordControl. Each segment is 1-8 seconds. It works fine for between 7 and 20 minutes, but then crashes.

    Usually it crashes with no exception (even though I tried to catch all exceptions and errors), sometimes RecordControl.commit() fails with an IOException that reports "commit failed: -4". But it never can record for more than about 20 minutes.

    I tried this with both a player and RecordControl that exist all the time but are started and stopped, and with new instances of Player and RecordControl for each recording. The MIDlet does not run out of memory; I call gc() after every recording and show free memory on the screen, and it is not going down.

    The recording is into a ByteArrayOutputStream. To test this failure, I removed all uses of the actual audio, but it still crashes.

    I do not get these crashes if I record for a few seconds, then let the MIDlet run forever in a loop.

    The recocrding is into 8000 samples/s PCM, 1 channel. I do get usable WAV files as long as the MIDlet is running.

    Thanks, Sivan
    same problem

    Does someone find a solution to this pb?

  8. #8
    Registered User
    Join Date
    Jun 2008
    Posts
    25

    Lightbulb Re: N80: MIDlet crashes after recording short audio segments for 7-20 minutes

    Hello everyone,

    I found a solution.

    Well in fact, it's ,ot a real solution but a clever work-around: what I did is end the application BEFORE the crash happens but first let it schedule its own next execution.
    Scheduling a future execution of a MIDlet from within the Java code of the same (or another) MIDlet is possible using MIDP 2.0 Push Registry feature.

    Here is a more detailed explanation of how I worked around the memory leak problem:
    • I timed the approximate moment the application will crash or hang. Experimentation has shown that the timing is highly dependant on the sample rate of the recording. In the case of my application (tested on a Nokia 5230) the crash happens at approx. 23 minutes when recording at 16kHz and at 8-9 minutes when recording at 48kHz.
    • Next I introduced a timer in my code that gracefully exits the MIDlet BEFORE the crash happens (e.g. for recording at 48kHz I made a conservative guess and set the application to exit after 7 minutes of operation, safely before the occurance of the crash).
    • In the destroyApp() method of my MIDlet I check whether the reason for exiting the program is A) the user's intention (or a crash), or B) the timer running out of time.
    • In the case of A) I let the application terminate normally.
    • In the case of B) I use javax.microedition.io.PushRegistry.registerAlarm(String, long) to let the MIDlet schedule its own next execution in the near future. I chose to execute it 5 seconds later. This keeps the "gap" between executions to a minimum. To pass some program state values to the next execution of the MIDlet I also write a small "run state" file to the phone's memory (to be picked up by the next execution). After that I just end the MIDlet normally.


  9. Using this approach I have been able to avoid the crash completely, but at the cost of losing some recording time. However, since the gap between executions is <10 seconds this loss of audio data is minimal (with a running time of 7 minutes the gap is about 2%).

    Note 1: To be able to use the PushRegistry your MIDlet needs to be signed and be granted permission javax.microedition.io.PushRegistry.

    Note 2: On S60/Symbian (and possibly other platforms) this permission is mutually exclusive (by design) with the permissions that guard network access (unless you can have you MIDlet signed as coming from a manufacturer or an operator). In other words: if you want to solve the memory leak problem in the way I described your MIDlet cannot access the Internet.

    Note 3: As I said this is a work-around and not a real solution. A real solution is probably impossible on the "Java level" because to root of the problem seems to be in Nokia's Java Runtime for S60/Symbian implementation. I know to bug is present in both v1.3 (tested on Nokia N95-8GB and 6220 classic) and v1.4 (tested on Nokia 5230) of the runtime. I don't know if the problem is fixed in v2.1 which is now shipping on handsets running brand new Symbian^3 platform (e.g. the Nokia N8). I don't have access to such handsets so I cannot test it. If anyone has tested this, please report your findings.
Last edited by MatthiasStevens; 2010-07-07 at 16:34.
Reply With Quote Reply With Quote

  • #9
    Registered User
    Join Date
    Jun 2008
    Posts
    25

    Lightbulb Re: N80: MIDlet crashes after recording short audio segments for 7-20 minutes

    Here is some example code for my work-around.

    For the MIDlet:
    Code:
    package example;
    
    import java.io.IOException;
    import java.util.Date;
    
    import javax.microedition.io.PushRegistry;
    import javax.microedition.midlet.MIDlet;
    
    import com.sun.lwuit.Command;
    import com.sun.lwuit.Display;
    import com.sun.lwuit.Form;;
    import com.sun.lwuit.events.ActionListener;
    
    import example.RunState;
    import example.Engine;
    
    
    public class MainMidlet extends MIDlet implements ActionListener
    {
    
    	// STATICS-------------------------------------------------------	
    	static public RunState runState = new RunState(); //default for first run
    	static public boolean FIRST_RUN = true;
    	static public boolean LAST_RUN = false; //!!!loop by default, is overridden when user exits or when a crash happens
    	static public int TIME_TO_LIVE = 7*60*1000; //in ms! (7')
    	static public int RESTART_DELAY = 5*1000; //5"
    
    	// DYNAMICS------------------------------------------------------
    	private Form current_form;
    	private Engine engine;
    
    	private Logger log = Logger.getInstance();
    	private Thread mainThread;
    
    	public void startApp()
    	{		
    		
    		try
    		{
    			//Initialize RunState:
    			checkPreviousRun();
    			
    			//initialize & show GUI
    			//...
    			
    			//do stuff:
    			engine.start(runState); //does the actual work (records and processes audio) and uses runState to initialize itself
    		}
    		catch(Exception e)
    		{
    			log.error(e.getMessage());
    			LAST_RUN = true; //the program crashed: don't restart
    		}
    		
    		countDown(); //!!! program should end after TIME_TO_LIVE
    	}
    	
    	public void actionPerformed(ActionEvent actionEvent) //event handler for GUI
    	{
    		if(cmdExit.equals(actionEvent.getCommand())) //exit command
    		{
    			LAST_RUN = true; //!!! user wants to exit, so don't restart
    			midlet.destroyApp(true);
    		}
    		//...
    	}
    	
    	public void destroyApp(boolean unconditional)
    	{
    		engine.stop(); //!!! will update the runstate
    		if(LAST_RUN)
    		{
    			log.debug("Exit: User"); //(or crash)
    			undoRescheduling(); //user chose to exit (or there was a crash), so don't reschedule
    			synchronized(mainThread)
    			{
    				mainThread.interrupt(); //interrupt waiting thread so MIDlet can exit immediately
    			}
    		}
    		else //not the last run: reschedule & keep state
    		{
    			log.debug("Exit: Time-up");
    			log.debug("Writing runstate...");
    			runState.save(); //saves a small file to memory that contains run state information for the next execution
    			scheduleNextRun(); //!!!
    		}
    		notifyDestroyed(); //really exit
    	}
    	
    	private void checkPreviousRun()
    	{
    		log.debug("Reading previous runstate...");
    		RunState previousState = RunState.load();
    		if(previousState != null)
    			log.debug("Previous runstate: " + previousState.prettyPrint());
    		else
    			log.debug("No previous runstate found");
    		if(	previousState != null && 		//there IS a previous runstate (loaded from file)
    			previousState.getStopTime() > -1 &&	//the previous runstate has a valid stopTime
    			previousState.getStopTime() + MainMidlet.RESTART_DELAY + 30*1000 >= runState.getStartTime()) //previous state is too old, discard, treat this execution as a first run
    		{
    			FIRST_RUN = false;
    			runState = previousState;
    			runState.incrementRunCount();
    		}
    		log.debug("The current execution is" + (FIRST_RUN ? "" : " not") + " the first run");
    	}
    	
    	public void countDown()
    	{
    		try
    		{
    			mainThread = Thread.currentThread();
    			synchronized(mainThread)
    			{
    				mainThread.wait(TIME_TO_LIVE);
    			}
    		}
    		catch(InterruptedException e)
    		{
    			log.debug("Waiting thread interruped");
    			return; //!!! skip code below
    		}
    		
    		//Time up...
    		LAST_RUN = false; //(just to be sure)
    		destroyApp(true);
    	}
    	
    	public void scheduleNextRun()
    	{
    		if(!LAST_RUN)
    		{
    			log.debug("Scheduling next run");
    			long previousRun = 0;
    			try
    			{
    				previousRun = PushRegistry.registerAlarm(this.getClass().getName(), (new Date()).getTime() + TIME_TO_LIVE + RESTART_DELAY); //5 seconds in between runs
    				//Note: new Date()).getTime() = current time as a long timestamp (in milliseconds)
    			}
    			catch(ClassNotFoundException cnf)
    			{
    				log.error("Error scheduling next run (class not found): " + cnf.getMessage());
    			}
    			catch(javax.microedition.io.ConnectionNotFoundException connnf)
    			{
    				log.error("Error scheduling next run (connection not found): " + connnf.getMessage());
    			}
    			if(previousRun > 0 && previousRun < System.currentTimeMillis())
    			{
    				log.debug("Time of previous run: " + StringUtils.formatDateTime(previousRun, "/", ":", " ")); //this does not always seem to be correct so I use my RunState class/file instead
    			}
    		}
    	}
    
    	public static RunState getRunState()
    	{
    		return runState;
    	}
    }
    Here is some example code for the RunState class which I created to pass state information between MIDlet executions:
    Code:
    package example;
    
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    
    import javax.microedition.io.Connector;
    import javax.microedition.io.file.FileConnection;
    
    import example.MainMidlet;
    
    
    public class RunState
    {
    	
    	private static final String STATE_FILE_NAME = "running";
    	private static final char separator = '|';
    
    	private int runCount = 1;
    	private long startTime;
    	private long stopTime = -1; //running
    	//...add additional state fields here
    	
    	public RunState() //default constructor, for first run
    	{
    		this.startTime = System.currentTimeMillis();
    		this.runCount = 1;
    		//initialize additional state fields here
    	}
    
    	public RunState(String state) //constructor that initializes from a String (contents of run state file)
    	{
    		String[] parts = StringUtils.split(state, separator); //uses a string splitting function I made
    		this.runCount = Integer.parseInt(parts[0]);
    		this.startTime = Long.parseLong(parts[1]);
    		this.stopTime = Long.parseLong(parts[2]);
    		//parse additional state fields here
    	}
    	
    	public String toString() //serialize run state to write to file
    	{
    		return 	Integer.toString(runCount) + separator +
    				Long.toString(startTime) + separator +
    				Long.toString(stopTime)
    				//serialise additional state fields here, adding a separator in front of each additional one
    				;
    	}
    
    	public static RunState load()
    	{
    		RunState runState = null;
    		String filePath = MainMidlet.getInstance().getPreferences().getDataFolderPath() + STATE_FILE_NAME;
    		try
    		{
    			FileConnection fc = (FileConnection) Connector.open(filePath, Connector.READ_WRITE);
    			if(fc.exists())
    			{
    				InputStreamReader reader = new InputStreamReader(fc.openInputStream());
    				StringBuffer bff = new StringBuffer();
    				for(int c = reader.read(); c != -1; c = reader.read())
    					bff.append((char) c);
    				if(bff.length() > 0)
    					runState = new RunState(bff.toString()); //initialize runstate
    				reader.close();
    				fc.delete(); //delete the file! (so it is not accidently re-used)
    				fc.close();
    			}
    		}
    		catch(Exception e)
    		{
    			(Logger.getInstance()).debug("Could not load runstate: " + e.getMessage());
    		}
    		return runState;
    	}
    	
    	public void save() //shorthand for static method
    	{
    		RunState.save(this);
    	}
    	
    	public static void save(RunState runState)
    	{
    		String filePath = MainMidlet.getInstance().getPreferences().getDataFolderPath() + STATE_FILE_NAME;
    		try
    		{
    			FileConnection fc = (FileConnection) Connector.open(filePath, Connector.READ_WRITE);
    			if(fc.exists())
    				fc.truncate(0); //empty out the existing file
    			else
    				fc.create(); //create file
    			OutputStreamWriter writer = new OutputStreamWriter(fc.openOutputStream());
    			writer.write(runState.toString()); //serialize
    			writer.flush();
    			writer.close();
    		}
    		catch(Exception e)
    		{
    			(Logger.getInstance()).debug("Could not save run state: " + e.getMessage());
    		}		
    	}
    
    	public int getRunCount()
    	{
    		return runCount;
    	}
    
    	public void incrementRunCount()
    	{
    		this.runCount++;
    	}
    
    	public long getStopTime()
    	{
    		return stopTime;
    	}
    
    	public void setStopTime(long stopTime)
    	{
    		this.stopTime = stopTime;
    	}
    
    	public long getStartTime()
    	{
    		return startTime;
    	}
    	
    	//add getters & setters for additional state fields here
    	
    }
    Good luck!
    Last edited by MatthiasStevens; 2010-07-07 at 16:40.

  • #10
    Registered User
    Join Date
    Jun 2008
    Posts
    25

    Re: N80: MIDlet crashes after recording short audio segments for 7-20 minutes

    *Bump*

    Does anyone know if this problem still occurs on the latest Nokia handsets (with Symbian^3)?

    -M.

  • #11
    Registered User
    Join Date
    Jun 2008
    Posts
    25

    Re: N80: MIDlet crashes after recording short audio segments for 7-20 minutes

    *Bump*

    Many other people have reported this problem on different handsets:
    http://discussion.forum.nokia.com/fo...crashes-on-N70
    http://discussion.forum.nokia.com/fo...-on-nokia-6630
    http://discussion.forum.nokia.com/fo...e-crashes-6600

    I've seen the problem on the N95_8GB and the 5230.

    I'm wondering if anyone would be will to help me test if the problem is still present on handsets with Symbian^3 and/or Nokia Java Runtime v2.1.
    Anyone?

  • Similar Threads

    1. Audio capture crashes 6600
      By cforstner in forum Mobile Java Media (Graphics & Sounds)
      Replies: 3
      Last Post: 2010-07-07, 17:48
    2. N80 midlet icon problem revisited... questions
      By kounapuu in forum Mobile Java General
      Replies: 1
      Last Post: 2006-10-07, 20:15
    3. N80 MIDlet installation problem
      By klapio in forum General Development Questions
      Replies: 3
      Last Post: 2006-08-29, 14:53
    4. REcording Audio with 3650
      By derdasser in forum Mobile Java Media (Graphics & Sounds)
      Replies: 0
      Last Post: 2005-02-23, 20:01
    5. Audio in VIDEO PLAYING in midlet
      By rossottom in forum Mobile Java Media (Graphics & Sounds)
      Replies: 0
      Last Post: 2003-05-13, 17:08

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •  
    ×