Я хотел бы повторно захватывать фрагменты звука на мобильном телефоне Nokia с помощью мидлета Java. Мой текущий опыт заключается в том, что использование кода в документации Sun (см .: http://java.sun.com/javame/reference/apis/jsr135/javax/microedition/media/control/RecordControl.html) и перенос его в цикл while (true)) работает, но приложение медленно потребляет всю память на телефоне, и программа в конечном итоге выдает исключение и не может инициировать дальнейшие записи.
Используемая память не является кучей памяти Java - мой пример программы (ниже) показывает, что память Java остается примерно статической, около 185 000 байт, - но есть некоторая утечка памяти в базовой вспомогательной библиотеке, предоставляемой Nokia; Я полагаю, что утечка памяти происходит, потому что если вы попытаетесь запустить другое (не Java) приложение (например, веб-браузер) после некоторого запуска приложения Java, телефон убивает это приложение с предупреждением о нехватке памяти.
Я попробовал несколько различных подходов, чем тот, который использовался каноническим примером Sun в документации (инициализируйте все каждый раз вокруг цикла, инициализируйте столько раз, сколько возможно, только один раз, вызовите столько функций в стиле deallocate, которые не должны строго необходимо и т. д.). Ни один из них не выглядит успешным. Ниже приведен простой пример программы, которая, на мой взгляд, должна работать, но дает сбой после запуска в течение 15 минут или около того как на N80 (несмотря на обновление прошивки), так и на N95. Другие форумы также сообщают об этой проблеме, но представленные там решения не работают (например, см .: http://discussion.forum.nokia.com/forum/showthread.php?t=129876).
import javax.microedition.media.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.io.*;
public class Standalone extends MIDlet {
protected void startApp() {
final Form form = new Form("Test audio recording");
final StringItem status = new StringItem("Status","");
form.append(status);
final Command exit = new Command("Exit", Command.EXIT, 1);
form.addCommand(exit);
form.setCommandListener(new CommandListener() {
public void commandAction(Command cmd, Displayable disp) {
if (cmd == exit) {
destroyApp(false);
notifyDestroyed();
}
}
});
Thread t = new Thread(){
public void run() {
int counter = 0;
while(true) {
//Code cut 'n' paste from Sun JSR135 javadocs for RecordControl:
try {
Player p = Manager.createPlayer("capture://audio");
p.realize();
RecordControl rc = (RecordControl)p.getControl("RecordControl");
ByteArrayOutputStream output = new ByteArrayOutputStream();
rc.setRecordStream(output);
rc.startRecord();
p.start();
Thread.currentThread().sleep(5000);
rc.commit();
p.close();
} catch (Exception e) {
status.setText("completed "+counter+
" T="+Runtime.getRuntime().totalMemory()+
" F="+Runtime.getRuntime().freeMemory()+
": Error: "+e);
break;
}
counter++;
status.setText("completed "+counter+
" T="+Runtime.getRuntime().totalMemory()+
" F="+Runtime.getRuntime().freeMemory());
System.gc(); //One forum post suggests this, but doesn't help
this.yield();
}
}
};
t.start();
final Display display = Display.getDisplay(this);
display.setCurrent(form);
}
protected void pauseApp() {}
protected void destroyApp(boolean bool) {}
}