invokeLater's run() method being called twice - blackberry

In order to determine which screen to display next in my BlackBerry app I'm using the code below. For some strange reason, however, the code within run() gets executed twice when a menu item is selected by tapping onscreen yet only once when using the phone's keypad instead.
Any ideas what might be causing this?
protected boolean navigationClick(int status, int time)
{
switch (mainMenu.getSelectedIndex())
{
case 0:
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
UiApplication.getUiApplication().pushScreen(new PollListScreen());
}
});
break;
case 1:
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
UiApplication.getUiApplication().pushScreen(new UpdateProfileScreen());
}
});
break;
// Etc.
default:
break;
}
return true;
}

I can't see exactly where you've placed the code that you're showing, but I don't think too many things can be going wrong here.
If run() is being called multiple times, then I think navigationClick() is getting called multiple times.
navigationClick() can get called differently depending on the source of the click (e.g. touch vs. trackwheel). You should, however, be able to sort this out by inspecting the status parameter. Something like this might do for you:
protected boolean navigationClick(int status, int time)
{
if (status != 0) // <-- NOTICE THIS CHECK!!!
{
switch (mainMenu.getSelectedIndex())
{
case 0:
// your code cut out here for clarity
}
}
return true;
}
If you use invokeAndWait(), you're probably blocking the UI thread, which might cause problems for the second invocation of navigationClick(). That would be using two wrongs to make a right, though. invokeLater() should usually be preferred.

Related

Handling Touch EventListener in presence of navigationClick()

In application, Whenever i move bewteen tabs a full menu, copy, switch application pop up open.
To prevent this i override navigationClick method.
Now pop is not shown. In my second tab i have implemented drop down list. Because i have override navigationClick method when i click on drop down list it is not showing me list of items.
Any idea will be apperciated.
Update:
Here is navigationClick implementation:
public boolean navigationClick(int status, int time) {
return true;
}
Make sure while selecting a tab, no errors occur which probably could be the reason for the menu options to pop up. if this is fixed i guess the subsequent problem will be dissolved!
Out of my experience i have observed the menu pops up in blackberry when a NullPointerException event occurs.
Just check the logs or debug to make sure no exception occurs when you navigate between tabs
If you want to click the labelfield then:
LabelField labelField=new LabelField("Click")
{
protected boolean navigationClick(int status, int time)
{
doLabelFieldClicked();
return true;
}
}
and if Menu option is highlighted then override this:
public boolean onMenu(int instance)
{
return true; //It doesn't show the Menu option.
}
If I am thinking wrong let me know.
I solved this problem by implementing navigationClick() while creating lablelField
tab5 = new LabelField("News", LabelField.FOCUSABLE | LabelField.HIGHLIGHT_SELECT)
{
public boolean navigationClick(int status, int time)
{
return true;
}
};

how to disable the button using bitmapbuttonfield in advanced ui examples in blackberry

I am using bitmap button field in advanced ui examples.
By default no method is working for disabling the button in 5.0 jre,
so i have added the below code for disabling and
then disabling functionality of the button is working but setchangelistener is not working
that is my problem
.. here is my code that i added for disabling the button..please check. do i need to change anything in invoke action method?
public boolean isDisable() {
return isDisable;
}
public void setDisable(boolean isDisable) {
this.isDisable = isDisable;
invalidate();
}
public boolean isFocusable() {
return isFocusable && !isDisable;
}
public void setFocusable(boolean isFocusable) {
this.isFocusable = isFocusable;
}
protected boolean invokeAction(int action) {
if (!isDisable){
fieldChangeNotify(0);
}
return true;
}
public boolean setEnabled() {
return false;
}
Here is a discussion on the BlackBerry forums about this.
What I've sometimes done is actually make use of the isEditable() property on Field objects, since editability and being enabled are somewhat similar concepts. If you really want to keep the separate isDisabled() code, that's fine. Just substitute that below where I use isEditable() (remembering to reverse the boolean ... that's one reason to always program in the affirmative ... make your method isEnabled() instead of isDisabled()).
So, instead of any of the code you posted above, I would just add this code to either BitmapButtonField, or BaseButtonField:
public boolean isFocusable() {
return isEditable() && super.isFocusable();
}
and this in BitmapButtonField:
protected void paint( Graphics g ) {
int oldAlpha = g.getGlobalAlpha();
int index = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ) ? FOCUS : NORMAL;
if (!isEditable()) {
g.setGlobalAlpha(100); // alpha is 0 to 255, so this is 100/255
}
g.drawBitmap( 0, 0, _bitmaps[index].getWidth(), _bitmaps[index].getHeight(), _bitmaps[index], 0, 0 );
g.setGlobalAlpha(oldAlpha);
}
And then, I can setup a change listener, or disable the button, like this in my manager class:
BitmapButtonField btn =
new BitmapButtonField(Bitmap.getBitmapResource("button.png"),
Bitmap.getBitmapResource("button-lit.png"));
btn.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
Dialog.alert("Button clicked!");
}
});
btn.setEditable(false); // this disables the button
add(btn);
But, understand, that if you disable a button, that means your change listener won't get called. That's kind of how it's supposed to work. The change listener is only called if the button's enabled and therefore clickable.
Also, note that in order to make the button look different when disabled (not editable), I override paint() to set a different alpha value when the button is disabled. You didn't mention that, so if you don't like it, you can certainly take it out.

How to push new screen from global screen in blackberry?

Here I am display push notification in globalscreen in blackberry, I need to push screen by clicking OK button of the dialog. I want to start app by clicking the ok button.
Please help me.
Thanks in advance!
I'm not 100% sure I understand what you want, but if this doesn't work, just add a comment and I'll try to give you a better answer.
First, read this on pushing global screens
and this on performing actions after receiving global alerts
Your code, if I'm understanding correctly, should be similar to the second link's example.
Then, if you implement the DialogClosedListener, like in the second link, you might have something like this:
called from the background when you get notified:
Dialog myDialog = new Dialog(Dialog.D_OK_CANCEL, "Hello", Dialog.OK, null, 0);
myDialog.setDialogClosedListener(new MyListener());
UiApplication.getUiApplication().pushGlobalScreen(myDialog, 1, true);
implementation of your dialog listener:
private class MyListener implements DialogClosedListener {
public void dialogClosed(Dialog dialog, int choice) {
switch (choice) {
case Dialog.OK:
// ok clicked
UiApplication.getUiApplication().requestForeground();
break;
case Dialog.CANCEL:
// cancel clicked. or escape pressed
break;
default:
break;
}
}
}
And, then in your UiApplication class, you can respond to activation, which will happen if the user selects Ok from the Dialog:
public class MyApp extends UiApplication {
private boolean _nextScreenShowing = false;
public void activate() {
super.activate();
if (!_nextScreenShowing) {
pushScreen(new NextScreen());
_nextScreenShowing = true;
}
}
}
I show the _nextScreenShowing variable, just to make sure you think about whether pushing the next screen is appropriate. It probably won't be every time activate is called. You may need to keep track of that boolean flag by responding to the Application.deactivate() method, or maybe Screen.onExposed() or Screen.onObscured(). All that depends on how your app works.

How to add Listener for PictureScrollField in Blackberry

I am implementing a PictureScrollField in my application. I do not know how to set Listener for images in PictureScrollField. I tried with navigationClick,navigationMovement, fieldChange,trackwheelclick and touchevent. But nothing is working properly. navigationClick,navigationMovement, fieldChange are not working at all , trackwheel working one after that it will not work and touchevent works for the whole PictureScrollField not for the specific image. Somebody help me please.
Thanks in Advance
NavigationClick is the way to go. However, you will need to check if the field is in focus and then get the selected index. Try the following code:
protected boolean navigationClick(int status, int time) {
// psf is the PictureScrollField //
if (psf.isFocus()) {
switch (psf.getCurrentImageIndex()) {
case 0:
// Action when image at index 0 is clicked
break;
case 1:
// Action when image at index 1 is clicked
break;
default:
break;
}
return true;
}
return super.navigationClick(status, time);
}

BlackBerry java detecting screen foreground event

In my BlackBerry application, I have a home screen. The user can then navigate to a settings screen. When the user goes back to the home screen, is there no method that is called on the home screen indicating that the screen has come to the foreground?
I have tried onFocus() with no avail.
Thanks!
Unfortunately, hooking on the onExposed is not enough. I found that in Blackberry dialogs are also screens and even context menus are screens too. They are pushed on top of your screen so you receive onExposed callback when they are dismissed.
Though it's OK in many cases, in other cases it poses a problem - e.g. if I must refresh the screen's content only when the user returns to it, but not after menus/dialogs, then how do I do that? My case is, unfortunately, one of those.
I found no documented way of detecting "covered"/"uncovered" events. Here is my approach. onCovered/onUncovered callbacks are called when the current screen is covered/uncovered by another screen of the app, but not by dialogs/menus/virtual keyboard:
public class MyAppScreen extends MainScreen {
private boolean isCovered;
protected void onExposed() {
Log.d("onExposed");
super.onExposed();
if (isCovered) {
onUncovered();
isCovered = false;
}
}
protected void onObscured() {
Log.d("onObscured");
super.onObscured();
final Screen above = getScreenAbove();
if (above != null) {
if (isMyAppScreen(above)) {
isCovered = true;
onCovered();
}
}
}
private boolean isMyAppScreen(final Screen above) {
return (above instanceof MyAppScreen);
}
protected void onUncovered() {
Log.d("onUncovered");
}
protected void onCovered() {
Log.d("onCovered");
}
protected void onUiEngineAttached(final boolean attached) {
if (attached) {
Log.d("UI Engine ATTACHED");
} else {
Log.d("UI Engine DETACHED");
}
super.onUiEngineAttached(attached);
}
protected void onFocusNotify(final boolean focus) {
if(focus){
Log.d("focus GAINED");
} else {
Log.d("focus LOST");
}
super.onFocusNotify(focus);
}
}
And a test. Try various combinations and see what events you receive in the log.
public class TestLifecycle extends MyAppScreen implements FieldChangeListener {
private final ABNTextEdit txt1;
private final ButtonField btn1;
private final ButtonField btn2;
public TestLifecycle() {
final Manager manager = getMainManager();
txt1 = new ABNTextEdit();
manager.add(txt1);
btn1 = new ButtonField("Dialog", ButtonField.CONSUME_CLICK);
btn1.setChangeListener(this);
manager.add(btn1);
btn2 = new ButtonField("Screen", ButtonField.CONSUME_CLICK);
btn2.setChangeListener(this);
manager.add(btn2);
}
public void fieldChanged(final Field field, final int context) {
if (field == btn1) {
Dialog.alert("Example alert");
} else if (field == btn2) {
UiApplication.getUiApplication().pushScreen(new TestLifecycle());
}
}
}
Update:
This method has a limitation: if a new screen is pushed when a dialog or the soft keyboard has focus your current screen will not receive onCovered/onUncovered notification.
Example A: if you have an input field of fixed size and you push a new screen when the user completes it, your current screen will not receive the notification if the user types very quickly. This happens because in the moment between you call push(newScreen) and it is actually pushed the user clicks on a letter on soft KB and it grabs the focus. So only onObscured is called, but not onCovered.
Solution: explicitly hide the soft keyboard before the push(newScreen).
Example B: if you have a customized dialog which pushes new screen and then dismisses itself, your current screen will not receive the notification. This happens because your customized dialog is not recognized as a screen, so only onObscured is called, but not onCovered.
Solution: dismiss the dialog in the first place returning a result value, and let your screen push the new screen based on that value. -OR- override isMyAppScreen() to return true also for your customized dialog.
You should be able to use protected void onExposed() to detect when it is displayed again.

Resources