I am working on an application for blackberry that will be downloading a file. I would like to show a progress bar during this download. I have tried every combination of GaugeField and ProgressIndicatorView that I can come up with but I am getting nothing. My download is going but the progress bar is never getting updated on the screen. In fact before I started trying for the progress bar I was trying to simply use a TextField and update it with the current percentage completed of the download, and I had no luck that way either.
This is inside my Screen:
view = new ProgressIndicatorView(0);
model = new ProgressIndicatorModel(0, 100, 0);
controller = new ProgressIndicatorController();
model.setController(controller);
view.setModel(model);
view.setController(controller);
controller.setModel(model);
controller.setView(view);
view.setLabel("Percent completion");
view.createProgressBar(Field.FIELD_HCENTER);
add(view);
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
downloadVideo();
initializeMedia();
// If initialization was successful...
if(_videoField != null)
{
createUI();
updateVideoSize();
try {
_player.start();
} catch (MediaException e) {
// TODO Auto-generated catch block
e.printStackTrace();
ScreenSaverActivity.errorDialog("MEDIA EXCEPTION: "+e.toString());
}
}
else
{
_statusField.setText("Error: Could not load media");
}
}
});
downloadVideo() method:
private void downloadVideo(){
DownloadThread _dlThread = new DownloadThread();
_dlThread.start();
}
DownloadThread class:
class DownloadThread extends Thread {
public void run(){
try {
HttpConnection httpConn;
httpConn = (HttpConnection)Connector.open("http://url/to/myMovie.mp4");
InputStream is = httpConn.openInputStream();
String fName = "file:///store/BlackBerry/videos/myMovie.mp4";
FileConnection fconn = (FileConnection) Connector.open(fName, Connector.READ_WRITE);
if (!fconn.exists())
fconn.create();
OutputStream os = fconn.openOutputStream();
long lengthOfFile = httpConn.getLength();
int total = 0;
int count;
byte data[] = new byte[1024];
while ((count = is.read(data)) != -1) {
//I have tried this line outside of synchronized too, with no luck
synchronized(Application.getEventLock()) {
EmbeddedMediaScreen.this.model.setValue((int)(total*100/lengthOfFile));
}
total += count;
//write this chunk
os.write(data, 0, count);
}
os.flush();
os.close();
} catch (IOException e) {
ScreenSaverActivity.errorDialog(e.toString());
e.printStackTrace();
}
}
}
While my application is doing the download the device becomes unresponsive, so I am guess that my trouble is the download work is happing on the main(UI) thread for some reason and that this has something to do with why I can’t get the screen to update with the progress. Any help would be greatly appreciated.
P.S. Android is generally my home, not blackberry, sorry if I have overlooked something that should be obvious =/
I see a few issues. It looks like the code after ‘downloadVideo()’ assumes the download happened synchronously. Since you want the download to happen in the background, you need to setup a separate method to handle the completion of the download. Right now your video playback code executes just after the download thread is started.
Also, you are acquiring the UI event lock every 1k of download. Since this is a video, I’m assuming a multi-megabyte download, meaning you are acquiring and releasing that lock thousands of times. This doesn’t make much sense, in part because the download meter only has 100 different values, so you are mostly updating it with the same value. The easiest fix is to keep track of the last value sent to the model. if it is unchanged, then don’t acquire or update the value.
In general, I don’t like to acquire the UI lock directly, because there is no queue management. So I use invokeLater for all code that needs to update the UI. This has the nice property that the invokeLater code happens sequentially. You can overrun the queue, as this code would do if you directly change it to invokeLater. To avoid that problem, you have to setup another variable to track whether you’ve got a progress meter update queued. If so, don’t queue any more work.