Archive for the ‘Fu’ Category

Using the BlackBerry Notifications Manager

Creative Commons Licence

This work is licenced under a Creative Commons Licence.

Quite often we want to be able to notify the user that some event has happened. It is nice to be able to allow the user to configure what form that notification takes depending on the profile in use (Normal, Silent, Vibrate, etc.). The procedure to do this is quite simple, although when I first tackled this problem the documentation was confusing. I like to have a state class that keeps the data used to trigger the notification. This can become important if you application has a complex notification system. In this example it isn’t really necessary, but here is my storage class Notify:

/*
 * Notify.java
 *
 * © Richard Buckley www.hrbuckley.net, 2011
 *
 * This work is licenced under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 * To view a copy of this licence, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
 * Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
 */

package src.notify;

import net.rim.device.api.notification.NotificationsManager;
import net.rim.device.api.notification.NotificationsEngineListener;

// The Notify class is just a helper to keep track of the data needed to invoke and
// cancel the notification. Mainly they keep track of the _eventId so the notification
// can be canceled, if you want to implement that, it is not used here and this
// could be rolled into the main program if simplification is more important.

final class Notify
{
    long _sourceId;
    long _eventId;
    int _priority;
    int _triggerIndex;
    long _timeout;

    public Notify(long sourceid, long eventid, int priority, long timeout, int triggerIndex) {
        _sourceId = sourceid;
        _eventId = eventid;
        _priority = _priority;
        _triggerIndex = triggerIndex;
        _timeout = timeout;
    }

    // invoke the event
    public void fire() {
        // triggerImmediateEvent causes non-interactable events to fire, such as Tunes, Vibrations and LED flashing
        NotificationsManager.triggerImmediateEvent(_sourceId, 0, this, null);
    }

    // cancel the event
    public void cancel() {
        NotificationsManager.cancelImmediateEvent(_sourceId, 0, this, null);
    }

}

Somewhere in the initialization of your code you must register a UID, Name and level with the OS. This will cause the name you have chosen to appear in the profiles where the user can get creative. Then it is a simple matter of firing the appropriate notification at the right time.

/*
 * Notify.java
 *
 * © Richard Buckley www.hrbuckley.net, 2011
 *
 * This work is licenced under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 * To view a copy of this licence, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
 * Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
 */

package src.notify;

import net.rim.device.api.notification.NotificationsConstants;
import net.rim.device.api.notification.NotificationsManager;

// A skeleton class that will fire notifications.
//
class MyNotifierClass {
    public static final long NOTIFY1 0x6deb32addca8d89aL; // src.notify.Notify1
    public static final long NOTIFY2 0xd8759a3149fe119L; // src.notify.Notify2

    private Notify        _notify1, _notify2;
    private long          _EVENT_ID;

    public MyNotifierClass() {
        _EVENT_ID = 0L;

        //New Notifications Sources - these will show up as editable configurations in the Profiles application
        NotificationsManager.registerSource( NOTIFY1, "Notify 1", NotificationsConstants.IMPORTANT );
        NotificationsManager.registerSource( NOTIFY2, "Notify 2", NotificationsConstants.IMPORTANT );
    }

    public void someMethod() {
        _notify1 = new Notify(NOTIFY1, ++_EVENT_ID, 500, -1, NotificationConstants.MANUAL_TRIGGER);
        _notify1.fire();
    }

    public void someOtherMethod() {
        _notify2 = new Notify(NOTIFY2, ++_EVENT_ID, 500, -1, NotificationConstants.MANUAL_TRIGGER);
        _notify2.fire();
    }
}

Fun With Text Filters

Creative Commons Licence

This work is licenced under a Creative Commons Licence.

In the Blackberry API the TextFilter, and its subclasses (EmailAddressTextFilter, FilenameTextFilter, HexadecimalTextFilter, IPTextFilter, LowercaseTextFilter, NumericTextFilter, PhoneTextFilter, URLTextFilter, and UppercaseTextFilter) provide useful input filtering for Blackberry programmers. Sometimes we want to quickly combine the function of two existing text filters into one. I have a project where I want the user to be able to input groups of upercase letters and numbers separated by spaces. Here is the quick hack I came up with:

import net.rim.device.api.ui.text.TextFilter;
import net.rim.device.api.system.Characters;

    /**
     * A TextFilter class to filter for station identifiers
     */
    private static class StationFilter extends TextFilter {

        // Order of the supporting filters is important, NUMERIC will convert
        // letters to numbers if it gets them first.
        private static TextFilter[]      _tf = {
            TextFilter.get(TextFilter.NUMERIC),
            TextFilter.get(TextFilter.UPPERCASE)
        };

        // Convert using the first supporting filter that has a conversion
        public char convert( char character, int status) {
            char c = 0;

            for (int i = _tf.length - 1; i >= 0; i--) {
                c = _tf[i].convert(character, status);
                if (c != 0) {
                    return c;
                }
            }

            return 0;
        }

        // Validate a space for separator, then by supporting filter
        public boolean validate(char character) {
            if (character == Characters.SPACE) {
                return true;
            }

            for (int i = _tf.length - 1; i >= 0; i--) {
                boolean b = _tf[i].validate(character);
                if (b) {
                    return true;
                }
            }

            return false;
        }
    }

Getting Input from a Custom Dialog

Creative Commons Licence

This work is licenced under a Creative Commons Licence.

Quite often we want to be able to get some information from the user but don’t want to use the MainScreen interface. Instead we would rather use a Dialog. The built in Dialog API has some nice static functions that suspend the program execution until the user responds, then allows execution to continue. They handle all the tedious issues with the event thread for us. Wouldn’t it be nice to have a dialog that we could call to get some text, a phone number, or some other piece of information from the user? Well here is how you can do that:

/*
 * BasicTextDialog.java
 *
 * © Richard Buckley www.hrbuckley.net, 2010
 *
 * This work is licenced under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 * To view a copy of this licence, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
 * Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
 */

package src.dialog;

import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.DialogClosedListener;
import net.rim.device.api.ui.component.BasicEditField;
import net.rim.device.api.system.Bitmap;

//
//  Create a dialog with a BasicEditField to accept user input. This example sets the field style to
//  allow only uppercase input.
//
//
public class BasicTextDialog extends Dialog implements DialogClosedListener {
    private BasicEditField      _text;
    private int                 _choice;

    public BasicTextDialog()  {
        super(Dialog.D_OK_CANCEL, "Eenter Some Text.", Dialog.D_OK, Bitmap.getPredefinedBitmap(Bitmap.QUESTION), 0L);
        _text = new BasicEditField("Only Uppercase: ", null, BasicEditField.DEFAULT_MAXCHARS, BasicEditField.FILTER_UPPERCASE);
        add(_text);
        setDialogClosedListener(this);
    }

    //
    //   The dialogClosed listener is called when the user closes the dialog, we can get the selection made at this point.
    //
    public void dialogClosed(Dialog dialog, int choice) {
        _choice = choice;
    }

    //
    //   A static convenience function that takes care of creating the dialog, posting it as a modal window (this blocks
    //   our execution and gives the event thread back to the OS so the user can interact with our dialog).
    //
    public static String askForText() {
        BasicTextDialog nsd = new BasicTextDialog();
        nsd.doModal();

        //
        //    If the user selected OK return the content of the BasicEditField, otherwise return null
        //
        if (nsd._choice == Dialog.OK) {
            return nsd._text.getText();
        } else {
            return null;
        }
    }

    //
    //    This function move the focus to the BasicEditField when the dialog is attached to the UiEngine. If you don't
    //    do this the focus will go to the default button.
    //
    protected void onUiEngineAttached(boolean attached) {
        if (attached) {
            _text.setFocus();
        }
    }
}

Using the new dialog is very easy:

    String sometext = BasicEditDialog.askForText();

Blackberry UI, What’s on the Menu

Creative Commons Licence
This work is licenced under a Creative Commons Licence.

Often one of the first things we want to do is add a menu to our Screen. The MainScreen we learned of last time makes this quite easy but also flexible. First as always we need to import the new Classes we are going to use:

import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.ContextMenu;
import net.rim.device.api.ui.component.Menu;

To post a menu we over ride the base Class (MainScreen in this case) implementation of makeMenu(). Since, for the moment at least, we are only providing a single menu we can ignore instance.

First we find out which Field, if any, has focus. We can then get the contextMenu for that Field, if any, and include it in our menu. The context menu contains items like Copy and Paste or other actions that make sense in the context of the Field with focus.

In many programs and tutorials you will find line 47 written using the UiApplication Class:

        Field focus = UiApplication.getUiApplication().getActiveScreen().getLeafFieldWithFocus();

This is of course perfectly good coding, arguable better than what I’ve done here. The way I’ve coded it demonstrates that our main Class BasicGUI is a sub-Class of UiApplication so we can use it anyplace we would use UiApplication. This saves us from having to import the definition of UiApplication into the BasicGUIScreen file because the definition of BasicGUI is autmatically shared with all classes in the package src.lessonOn. So why is using UiApplication better? Well, if we decide we want to use BasicGUIScreen in an application with a different main Class that isn’t named BasicGUI, we will have a problem. Something to keep in mind.

With the potential context menu taken care of we can add our own MenuItem screen2 which we will define in a moment. Finally if we want to include the default menu items, Close and Switch Application we simply call the Super Class implementation of makeMenu(). If we leave that call out, then we can eliminate those options from the menu, if we so chose.

    protected void makeMenu(Menu menu, int instance) {

        Field focus = BasicGUI.getUiApplication().getActiveScreen().getLeafFieldWithFocus();
        if (focus != null) {
            ContextMenu context = focus.getContextMenu();
            if (!context.isEmpty()) {
                menu.add(context);
                menu.addSeparator();
            }
        }

        menu.add(screen2);

        super.makeMenu(menu, instance);
    }

One way to create a MenuItem is as an instance variable. This is no different than declaring and initializing a simple type, like an int, but a bit more complex because a MenuItem is a complex type. The three arguments to the MenuItem constructor are: the text to display in the menu; the ordinal, which is used to sort the MenuItems on the menu; and the priority which is used to dynamically select the MenuItem that is selected when the menu is first posted. When the MenuItem is selected, the run() method is executed on the Event Thread. So you must remember the priviledges and restrictions that go along with running on the Event Thread: no long processing, but you may alter the UI. In this case we create an instance of MainScreen, set the title and add a LabelField, and finally push the Screen onto the screen stack.

    private MenuItem screen2 = new MenuItem("Screen 2", 200, 200) {
        public void run() {
            MainScreen s2 = new MainScreen();
            s2.setTitle("Screen 2");
            s2.add(new LabelField("This is screen number 2"));
            BasicGUI.getUiApplication().pushScreen(s2);
        }
    };

And here is the new BasicGUIScreen.java source file:

/*
 * BasicGUIScreen.java
 *
 * © Richard Buckley www.hrbuckley.net, 2010
 *
 * This work is licenced under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 * To view a copy of this licence, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
 * Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
 */

package src.lessonOne;

import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.ContextMenu;
import net.rim.device.api.ui.component.Menu;

//
//
//
public class BasicGUIScreen extends MainScreen {
    BasicGUIScreen() {
        setTitle("Hello World");
        add(new LabelField("Hello World"));
    }

    private MenuItem screen2 = new MenuItem("Screen 2", 200, 200) {
        public void run() {
            MainScreen s2 = new MainScreen();
            s2.setTitle("Screen 2");
            s2.add(new LabelField("This is screen number 2"));
            BasicGUI.getUiApplication().pushScreen(s2);
        }
    };

    //
    // Populate the screen menu
    // @param menu the menu to populate
    // @param instance the instance, allows different menus to be posted depending
    // on user interaction. It will be 0 if the menu is posted by pressing the BB
    // button, non-zero if it was posted by a trackball click.
    //
    protected void makeMenu(Menu menu, int instance) {

        Field focus = BasicGUI.getUiApplication().getActiveScreen().getLeafFieldWithFocus();
        if (focus != null) {
            ContextMenu context = focus.getContextMenu();
            if (!context.isEmpty()) {
                menu.add(context);
                menu.addSeparator();
            }
        }

        menu.add(screen2);

        super.makeMenu(menu, instance);
    }
}

We could have created this screen in a number of ways. The most flexible would have been to create a new sub-Class of MainScreen. We could also reuse BasicGUIScreen. Similarly the MenuItem could be created when makeMenu is run if and when it is needed rather that when BasicGUIScreen is instantiated as screen2 is:

        menu.add(new MenuItem("Screen 3", 200, 300) {
            public void run() {
                BasicGUIScreen bgs = new BasicGUIScreen();
                bgs.setTitle("Screen 3");
                BasicGUI.getUiApplication().pushScreen(bgs);
            }
        });

Java allows all kinds of shortcuts like this. Sometimes they are very handy and improve readability, sometimes not.

As always, the Blackberry JDE project files are available from the Lesson1 Git repository. Enjoy.

Blackberry UI: Events, Screens and Threads

Creative Commons Licence
This work is licenced under a Creative Commons Licence.

There are several things that you must always bear in mind when writting BlackBerry applications: the device is event driven on a single Java Virtual Machine (JVM); the user interface is implemented using screens which are held on a screen stack; and the OS is multi-threaded, some threads have special requirements and capabilities which must be respected.

Driven by Events

Event driven software is not a new concept, especially where graphical user interfaces (GUIs) are concerned. When the user interacts with part of the interface, that interaction is presented to the appropriate software as an event. As programmers our job becomes writing little code fragments that are all related but each one takes care of some element of the user interface. This is a very powerful concept and has allowed much of what we take for granted on our digital devices to be developed. It does mean that we are no longer able to say ahead of time which order our bits of code will be executed in. That power is given over to the user.

On the BlackBerry platform, events are delivered to Listeners. A Listener is simply an object that implements a particular interface, a method or group of methods that provide the object with a specified behaviour. We don’t need to concern ourselves too much with the details of how the event delivery mechanism works, but we do need to keep certain things in mind. The operating system collects the very low level events: key presses and releases, track ball movement, data input/output etc. and delivers them to applications by placing the events in an event queue. When an application gets a turn to execute, a waiting event is taken off the queue and delivered to any listeners registered for that event. The listener may be provided by the OS or the API and it may combine many low level events into one or more higher level events. For example track ball movement and clicks may be combined into a drop down list item selection. These higher level events are then dilivered to their listeners in turn. All this event delivery is done by the Event Thread, and there is only one Event Thread. So if your program receives an event and starts a process that will take a long time (like computing Pi to thousands of decimal places) or that may block waiting for something external to the device (like downloading a web page) no other applications will receive events while your greedy program hogs the Event Thread. This will cause the device to appear to freeze. If this goes on too long, the event queue will fill up and the OS will terminate your program. So, keep your listeners short and quick. If you need to do long computation or IO start a new thread to handle those tasks.

The Event Thread, or more precicely the thread that is holding the user interface event lock is the only thread that can manipulate user interface elements. There are ways of arranging for your code to be executed on the Event Thread, or to grab the event lock, so that non-Event Threads can still have their results displayed to the user. We will look at those a little later.

Stack those Screens

Within a UiApplication Screens are held on a stack. The topmost screen is displayed to the user and receives events directed to the application. To display a Screen an Object that is a sub-class of net.rim.device.api.ui.Screen is created and pushed onto the Screen stack with pushScreen() (or one of its variants). To un-display a Screen, it can be popped off the stack manually with popScreen(), or it can be closed by calling the Screen’s close() method. This is what happens to some Screen implementations (like the MainScreen) when the user presses the escape key. When the last Screen is popped off the Screen stack, the application will exit, though it is possable to change this behaviour to put the application in the background.

Unraveling Threads

We have alread discussed threads in enough detail for the moment when we discussed Events. So lets get on with programming.

Adding a MainScreen

There are many ways to add a new Class or Object to an existing project. We will be talking about each when we need to use it, for now let’s use the traditional way of putting each Class in its own file so we create a BasicGUIScreen.java file and start typing. We will put it in the same package as our main object:

package src.lessonOne;

We also need to import the classes we will be using:

import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.component.LabelField;

And we can provide the universal program greeting:

public class BasicGUIScreen extends MainScreen {
    BasicGUIScreen() {
        setTitle("Hello World");
        add(new LabelField("Hello World"));
    }
}

To have our Screen displayed we simply modify the constructor of our main Class to create an instance of our Screen and push it onto the stack. We now have a program that does something we can see. Sitll not particularly useful, but it is a begining we can build on.

    BasicGUI() {
        pushScreen(new BasicGUIScreen());
    }

Here are the complete files, first BasicGUI.java:

/*
 * BasicGUI.java
 *
 * © Richard Buckley www.hrbuckley.net, 2010
 *
 * This work is licenced under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 * To view a copy of this licence, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
 * Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
 */

package src.lessonOne;

import net.rim.device.api.ui.UiApplication;

/**
 *
 */
public class BasicGUI extends UiApplication {
    public static void main(String[] args) {
        BasicGUI basicGUI = new BasicGUI();
        basicGUI.enterEventDispatcher();
    }

    BasicGUI() {
        pushScreen(new BasicGUIScreen());
    }
}

And BasicGUIScreen.java:

/*
 * BasicGUIScreen.java
 *
 * © Richard Buckley www.hrbuckley.net, 2010
 *
 * This work is licenced under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 * To view a copy of this licence, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
 * Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
 */

package src.lessonOne;

import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.component.LabelField;

/**
 *
 */
public class BasicGUIScreen extends MainScreen {
    BasicGUIScreen() {
        setTitle("Hello World");
        add(new LabelField("Hello World"));
    }
}
BasicGUI running on the simulator

BasicGUI running on the simulator

Basic Blackberry UI Program

Creative Commons Licence
This work is licenced under a Creative Commons Licence.

The Blackberry JDE workspace for this program can be obtained using Git: git clone git://git.hrbuckley.net/BB/Lesson1/

Every Java source must be part of a package. Membership in a package has an impact on class scoping rules and permissions. Objects belonging to the same package will have different access rules applied with respect to each other than objects belonging to different packages. For this reason, a standard Blackberry device will not load modules with Classes declared in restricted packages. This prevents a malicious programmer from using the scoping and access rules of package membership to bypass Blackberry security. It is traditional that the file structure of a Java project reflect the package structure, but this is not enforced by RIM’s Java Development Environment (JDE). So the first decison we need to make is what Package we want out Class to belong to, and declare it in the source code:

package src.lessonOne;

Next we must import the declarations of all the classes we are going to use. Some classes seem to be automatically imported by the JDE, String for example, and need not be explicitly imported. It is probably a bad habit not to import these, but perhaps not my worst bad habit. A Blackberry program implementing a user interface must have at least one object that extends net.rim.device.api.ui.UiApplication so:

import net.rim.device.api.ui.UiApplication;

We can now declare our Class:

public class BasicGUI extends UiApplication {
}

Next we must tell the compiler how to start our program. The RIM compiler/linker will look for an object with a method called main declared public static void and taking a single String array as an argument. It will arrange for this method to be called when our program is launched. A minimal main method will instantiate our sub-class of UiApplication and call the inherited method enterEventDispatcher which will not normally return:

    public static void main(String[] args) {
        BasicGUI basicGUI = new BasicGUI();
        basicGUI.enterEventDispatcher();
    }

Add a simple constructor (which we will embelish later) and we have a complete, if not very useful Blackberry program:

/*
 * BasicGUI.java
 *
 * © Richard Buckley www.hrbuckley.net, 2010
 *
 * This work is licenced under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 * To view a copy of this licence, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
 * Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
 */

package src.lessonOne;

import net.rim.device.api.ui.UiApplication;

/**
 *
 */
public class BasicGUI extends UiApplication {
    public static void main(String[] args) {
        BasicGUI basicGUI = new BasicGUI();
        basicGUI.enterEventDispatcher();
    }

    BasicGUI() {    }
}

The reason this program is not very useful is that, one of the things that enterEventDispatcher does, is monitor the number of Screens a UiApplication has pushed to the screen stack. We haven’t create any screens at all, so the program will exit directly. In my next post we will add a simple screen to our program.

Scripts for Building BlackBerry Programs Automatically

Creative Commons Licence
This work is licenced under a Creative Commons Licence.

These scripts are a work in progress. I’m still working on them so check back periodically and be aware that there may be bugs. Download the Git repository with git clone git://git.hrbuckley.net/BB/bin/. Or if you have already cloned the repositiory merge in any updates with git pull git://git.hrbuckley.net/BB/bin/

I have been using Git as my version control system of choice for nearly a year now. One of the benefits of using Git on Windows is that you get a Unix like environment for free. This gives rise to the ability to write Bash scripts to compile JDE projects automatically. We need to add some files and set up the environment. I’m using Windows 7 so in %USERPROFILE% I have created a bin directory and a .bashrc file:

# %USERPROFILE%\.bashrc
ifsave=$IFS
IFS=$(echo -en "\n\b")
export MYPROGRAMFILES_X86="/g/Program Files (x86)"
IFS=$ifsave

if [ -d ~/bin ]
then
  if [ -e ~/bin/jderc ]
  then
    . ~/bin/jderc
  else
    echo "No jderc"
  fi
  if [ -e ~/bin/javarc ]
  then
    . ~/bin/javarc
  else
    echo "No javarc"
  fi
fi

The jderc file:

#
# Iterate through all installed RIM JDEs adding a JDExxx and JDELIBxxx environtment variables with the
# path to the bin and lib directories for that JDE, and add the OS version to the JDEVERSIONS
# environment variable. Set the last (highest OS version) to JDEMAIN and JDELIBMAIN.
#
export RIMPROGFILES="${MYPROGRAMFILES_X86}/Research In Motion"

IFSAVE=$IFS
IFS=$(echo -en "\n\b")

JDEVERSIONS=""
for rim in ${RIMPROGFILES}/*
do
  b=$(basename $rim);
  case $b in
    BlackBerry*)
      v=$(echo $b | sed -e "s/BlackBerry JDE //i" | sed -e "s/\.//g")
      JDEVERSIONS="${JDEVERSIONS} ${v}"
      eval "export JDE${v}=\"${rim}/bin\""
      eval "export JDELIB${v}=\"${rim}/lib\""
      export JDEMAIN="${rim}/bin"
      export JDELIBMAIN="${rim}/lib"
      ;;
  esac
done
export JDEVERSIONS

IFS=$IFSAVE

The javarc file:

#
# Set up path variables for the JDK and JRE
#
export JAVAPROGFILES="${MYPROGRAMFILES_X86}/Java"

IFSAVE=$IFS
IFS=$(echo -en "\n\b")

JDKPATH=""
for jdk in ${JAVAPROGFILES}/jdk*
do
  if [ -d ${jdk}/bin ]
  then
    JDKPATH="${jdk}/bin"
  fi
done

for jre in ${JAVAPROGFILES}/jre*
do
  if [ -d ${jre}/bin ]
  then
    JREPATH="${jre}/bin"
  fi
done

export PATH="${JDKPATH}":"${JREPATH}":"${PATH}"

IFS=$IFSAVE

Now we can build a JDE project with the build script:

#!/bin/sh
#
# Build the specified JDE project using the latest JDE instaled, or as optionally specified.
#
if [ $# -lt 1 ]
then
  echo "Usage: build <project> [ $JDEVERSIONS ]"
  exit 1
fi

DOSPWD=$(pwd | tr / \\\\ | sed -e "s/^.\(.\)/\1:/")

#
# Get the files and libraries from the project file
#
MOD=$1
if [ -e ${MOD}.jdp ]
then
   JDP="${MOD}.jdp"
   files=$(awk 'BEGIN { copy = 0 } /^\[Files/ { copy = 1; next } /^]/ { copy = 0; } copy { print }' $JDP)
   libs=$(awk 'BEGIN { copy = 0 } /^\[DependsOn/ { copy = 1; next } /^]/ { copy = 0; } copy { print }' $JDP)
fi

FILES=""
LIBS=""
jde="JDEMAIN"
lib="JDELIBMAIN"
if [ "${files}EMPTY" != "EMPTY" ]
then
  for f in $files
  do
    FILES="${FILES}\"$f\" "
  done

  for l in $libs
  do
    LIBS="${LIBS}\"${l}.jar\" "
  done

  shift

  if [ $# -ge 1 ]
  then
    jde="JDE${1}"
    lib="JDELIB${1}"
    if [ ! -d "${!jde}" ]
    then
      jde="JDEMAIN"
      lib="JDELIBMAIN"
    fi
  fi

  #
  # If we can find the appropriate rapc compiler, build the program
  #
  if [ -e "${!jde}/rapc.exe" ]
  then
    "${!jde}/rapc.exe" -quiet -define=PREPROCESSOR "import=${LIBS}${!lib}/net_rim_api.jar" "codename=${MOD}" ${MOD}.rapc $FILES
  else
    echo "Could not locate JDE compiler"
    exit 2
  fi
fi

Visitors

Site Links

  • Blackberry Forums
  • Blackberry Support Forums
  • FreshMeat
  • Radio Electronics
  • SlashDot
  • Smiths Falls Weather
  • Stack Overflow
  • XKCD
  • Yahoo Groups

Blogroll

Meta