Blackberry simple progressbar for BrowserField2 - blackberry

In my app I have a BrowserField2 loading different pages and I want to show a simple spinning progressbar/indicator. As simple as possible really, without percent etc. - just a small animation to indicate to the user that something is happening.
I come from Android development and there such a thing is called Progressbar, though for Blackberry it maybe is called something completely different? (Progressbar for Blackberry seems to always include calculating the progress made).
What should I be looking for?

I solved it in a rather unorthodox way, something I probably wouldn't recommend ANYONE but I'll write it anyway since maybe it will help someone who's in a hurry to get it done. Just remember this is a bad way of doing it.
My app basically consists of 4 buttons and a browserfield.
To display a spinning "load animation" I use alishaik786's tip (see his comments) of the custom PopupScreen triggered by a browserfieldlistener:
// BrowserFieldListener to catch when a page started loading and when it is finished
BrowserFieldListener listener = new BrowserFieldListener() {
public void documentCreated(BrowserField browserField, ScriptEngine scriptEngine, Document document) throws Exception{
displayLoadAnimation();
// see method below
}
public void documentLoaded(BrowserField browserField, Document document) throws Exception{
try{
popUp.close();
}catch(IllegalStateException es){
es.printStackTrace();
}
}
};
// The method for showing the popup
private void displayLoadAnimation(){
popUp = new LoadingPopupScreen();
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(popUp);
}
});
}
Then in my custom PopupScreen I check where the user is clicking in "protected boolean touchEvent(TouchEvent event)" by checking event.getGlobalY() & event.getGlobalX() of the touch and comparing it to the positions of the buttons. If the user presses within the X&Y of a button then the popup screen is closed and I trigger the button being pressed.
As I said this is a bad way of doing it (many things need to be static), but it works if you want a quick and dirty sollution.

Related

JavaFX WebEngine timeout handling

I'm wondering if anyone has figured out a way to properly handle timeouts in the JavaFX 8 (jdk 1.8.0_31) WebView. The problem is the following:
Consider you have an instance of WebView and you tell it to load a specific URL. Furthermore, you want to process the document once it's loaded, so you attach a listener to the stateProperty of the LoadWorker of the WebEngine powering the web view. However, a certain website times out during loading, which causes the stateProperty to transition into Worker.State.RUNNING and remain stuck there.
The web engine is then completely stuck. I want to implement a system that detects a timeout and cancels the load. To that end, I was thinking of adding a listener to the progressProperty and using some form of Timer. The idea is the following:
We start a load request on the web view. A timeout timer starts running immediately. On every progress update, the timer is reset. If the progress reaches 100%, the timer is invalidated and stopped. However, if the timer finishes (because there are no progress updates in a certain time frame we assume a time out), the load request is cancelled and an error is thrown.
Does anyone know the best way to implement this?
Kind regards
UPDATE
I've produced a code snippet with behavior described in the question. The only thing still troubling me is that I can't cancel the LoadWorker: calling LoadWorker#cancel hangs (the function never returns).
public class TimeOutWebEngine implements Runnable{
private final WebEngine engine = new WebEngine();
private ScheduledExecutorService exec;
private ScheduledFuture<?> future;
private long timeOutPeriod;
private TimeUnit timeOutTimeUnit;
public TimeOutWebEngine() {
engine.getLoadWorker().progressProperty().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
if (future != null) future.cancel(false);
if (newValue.doubleValue() < 1.0) scheduleTimer();
else cleanUp();
});
}
public void load(String s, long timeOutPeriod, TimeUnit timeOutTimeUnit){
this.timeOutPeriod = timeOutPeriod;
this.timeOutTimeUnit = timeOutTimeUnit;
exec = Executors.newSingleThreadScheduledExecutor();
engine.load(s);
}
private void scheduleTimer(){
future = exec.schedule(TimeOutWebEngine.this, timeOutPeriod, timeOutTimeUnit);
}
private void cleanUp(){
future = null;
exec.shutdownNow();
}
#Override
public void run() {
System.err.println("TIMED OUT");
// This function call stalls...
// engine.getLoadWorker().cancel();
cleanUp();
}
}
I don't think that you can handle timeouts properly now. Looks at this method. As you can see it has hardcoded value for setReadTimeout method. Is it mean that SocketTimeoutException exception will be raised after one hour of loading site. And state will be changed to FAILED only after that event.
So, you have only one way now: try to hack this problem use Timers as you described above.
P.S.
Try to create issue in JavaFX issue tracker. May be anyone fixed it after 5 years...
I have the same problem and used a simple PauseTransition. Same behavior, not so complicated. =)

BlackBerry JDE 5 Application Slowing Down

I'm fairly new to writing BlackBerry applications, so maybe this is a stupid thing I'm overlooking. I have to use JDE 5 (client requirement) to support the older BlackBerry Curve 8520 phones.
What I am experiencing is that as soon as I place a DateField on my interface, the application slows down considerably, causing the UI to stutter. Even a simple layout that only has a single DateField and a button has the same effect. Then, as soon as I move on to the next layout, everything is fine again.
One of the layouts are created as follows (please comment if this is the incorrect way of doing it):
public void displaySomeLayout() {
final ButtonField okButton = new ButtonField("OK");
final DateField dobField = new DateField("Birthday", System.currentTimeMillis(), DateField.DATE);
/* some other non-ui code */
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
applicationFieldManager.addAll(new Field[] {
dobField,
okButton
});
}
});
}
The application then just slows down a lot. Sometimes, after a minute of so it starts responding normally again, sometimes not.
The displaySomeLayout() method is called from the contructor of the Screen extending class. And then applicationFieldManager is a private VerticalFieldManager which is instantiated during class construction.
I'm not sure the problem is in the code that you've shown us. I think it's somewhere else.
However, here are a couple recommendations to improve the code you've shown:
Threading
First of all, the code you show essentially is being run in the Screen subclass constructor. There is almost no difference between this code:
public MyScreen() {
Field f = new ButtonField("Hello", ButtonField.CONSUME_CLICK);
add(f);
}
and this:
public MyScreen() {
addField();
}
private void addField() {
Field f = new ButtonField("Hello", ButtonField.CONSUME_CLICK);
add(f);
}
So, because your code is being run in the screen class's constructor, it should already be running on the UI thread. Therefore, there's no reason to use UiApplication.getUiApplication().invokeLater() here. Instead, just use this:
public void displaySomeLayout() {
final ButtonField okButton = new ButtonField("OK");
final DateField dobField = new DateField("Birthday", System.currentTimeMillis(), DateField.DATE);
/* some other non-ui code */
applicationFieldManager.add(dobField);
applicationFieldManager.add(okButton);
}
Sometimes, you do need to use invokeLater() to run UI code, even when you're already on the UI thread. For example, if your code is inside the Manager#sublayout() method, which runs on the UI thread, adding new fields directly will trigger sublayout() to be called recursively, until you get a stack overflow. Using invokeLater() can help there, by deferring the running of a block of code until sublayout() has completed. But, from the constructor of your screen class, you don't need to do that.
ObjectChoiceField
I'm also worried about the ObjectChoiceField you said you were using with 250 choices. You might try testing this field with only 10 or 20 choices, and see if that makes a difference.
But, even if the 250 choice ObjectChoiceField isn't the cause of your performance problems, I would still suggest a different UI.
On BlackBerry Java, you can use the AutoCompleteField. This field can be given all the country choices that you are now using. The user starts typing the first couple letters of a country, and quickly, the list narrows to just those which match. I personally think this is a better way to get through a very large list of choices.

Blackberry Thread Exception

how to kill a thread in blackberry.
I am using below code in which i want to kill a thread when dialog popup.
On first time login failed it is working properly but on second time login failed it returns RunTimeException.
public void onAuthFailed(String message) {
//this.invokeAndWait(new NotifyDialog("Please enter correct username and password"));
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run(){
Dialog.alert("Please enter correct username and password.");
UiApplication.getUiApplication().pushScreen(loginscreen);
}
});
}
Code you posted is not dedicated to kill a thread. It will display a new screen. And I thing you are trying to display a screen object, that is already displayed. I. e loginscreen instance is already displayed. If loginscreen is not displayed, then there's confict (event lock) between new dialog box and screen to be displayed. Display dialog box and screen in different threads.
Check this tutorial: http://www.javabeginner.com/learn-java/java-threads-tutorial
I think it will help.

Help - Blackberrry BrowserField2, Media Player and Threads

In my application, I have BrowserField2 added to MainScreen and Media player based on Streaming media - Start to finish. I am trying to open media player from Browser using extended javascript. My plan is that when user clicks on some links in web page, I call extended javascript function with some parameters like url of the video to stream. This function in turn pushes media player screen with the url passed. Media player works very well and streams video when used stand alone. But it doesn't play video when coupled with BrowserField using extended javascript.
I suspect that the issue is synchronizing with Event thread or related to threading. I push screen containing media player using runnable. The screen is displayed. But when I click on play button (which starts some threads to fetch video and play it), nothing happens and my application freezes. I am not able to figure out exact problem. Will appreciate if someone can pin point the problem.
Thank you.
Some relevant code listings as below:
public void extendJavaScript() throws Exception
{
ScriptableFunction playVideo = new ScriptableFunction()
{
public Object invoke(Object thiz, Object[] args) throws Exception
{
openMediaPlayer(args[0].toString());
return Boolean.FALSE;
}
};
_bf2.extendScriptEngine("bb.playVideo", playVideo);
}
private void openMediaPlayer(final String url){
UiApplication.getUiApplication().invokeAndWait(new Runnable() {
public void run() {
PlayerScreen _playerScreen = new PlayerScreen(url + ";deviceside=true");
UiApplication.getUiApplication().pushScreen(_playerScreen);
}
});
}
Never mind. Got it resolved. It turned out that the video that I was trying to access from the web page was in incompatible format and hence throwing an error and freezing the media player.

Blackberry JDE GPS getLocation() LocationException

I need to add GPS functionality to an existing Blackberry Application that I've written. I write a stand alone class called CurrentLocation, and include a method to set the various location variables I care about by using the blackberry GPS in conjunction with google's reverse geocoding webservices. Everything is working beautifully, that is, until I try to instantiate my new class in my main application.
No matter what I do, I get a LocationException! .getLocation() doesn't work!
It really confuses me, because if I instantiate my class in a test hello world app, it works just fine.
Are there limits to where you can instantiate classes? I've not encountered any with previous classes I've written. In this case, I'm instantiating my CurrentLocation class in a listener (so the user only makes the lengthy gps and web calls when they want to). I've tried instantiating it in screens, as well. I've tried just gutting the class and using the method call, but that doesn't work either.
Is there something I'm missing entirely here?
http://pastie.org/639545
There's a link to the class I'm making,
And here's the listener I"m trying to instantiate from. I'm in an event thread because I thought it might help (but I get the same exception whether or not I do this).
FieldChangeListener listenerGPS = new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
CurrentLocation loc = new CurrentLocation();
if (loc != null){
country = loc.getCountry();
city = loc.getCity();
state = loc.getState();
road = loc.getRoad();
zip = loc.getZip();
}
}
});
}
};
What am I missing here?
Okay, I got it. Apparently you can't call getLocation() in the eventThread (not just invokeLater, but any listener). So now what I'm doing is getting the coordinates in a thread outside of the event, and worrying about google separately.

Resources