blackberry

BlackBerry AMMS (Advanced Multimedia Supplement) API Support

The Advanced Multimedia Supplement (AMMS) API, also known as JSR-234, is used to access advanced camera features on the BlackBerry® platform.  As of BlackBerry® 6.0 none of the audio capabilities of AMMS has been implemented, with the exception of AudioFormatControl and VideoFormatControl which have been implemented only so far as to support their stated features for video and still image capture.  Conversely many of the camera capabilities have been implemented.

AMMS by definition allows implementers to implement only some of the API.  Specifically, only the relevant ‘parts’ to the destination platform need to be implemented, with each ‘part’ consisting of a set of classes to implement.  The guarantee AMMS makes however is that any part that is implemented must be fully implemented to the extent that the platform can support it.  This means that each class that must be implemented as a part will itself be only partially implemented enough to fulfill that part with what the device is capable of.  Still following?

To put it another way, within each class the level of implementation depends on what the device can actually do. When an AMMS class is implemented the BlackBerry platform will guarantee to support the invocation (meaning an application that attempts to call an unsupported feature will compile and, if properly written, will fail gracefully and not crash) but not necessarily the implementation.

This is why developers who have used the AMMS API classes have found that not every portion of a class is fully implemented.  For example, the CameraControl class is an implemented AMMS class on the BlackBerry platform.  If an application were to call its isShutterFeedbackEnabled() method, it would always return true since that feature is supported on all platforms (a ‘click’ sound is heard when a picture is taken).  However, if that same application called its enableShutterFeedback(boolean) method, a MediaException would be thrown with the message “Setting shutter feedback is not possible”. This is because although the feature is supported, the ability to toggle it is not – it is always on.

For most classes in the AMMS API there are built-in methods to query the level of support of that class, but this was not done consistently.  In some cases the AMMS JavaDoc™ will state the behaviour of the platform if the particular feature or method is not supported on the implementing platform.  For example, in the case of the MediaException mentioned in the example above, there is no method to query if toggling shutter feedback is supported but the documentation states that the method “throws javax.microedition.media.MediaException – if setting of the shutter feedback is not possible”.[1]

What’s Supported?

Once your application has created a player for still image capture or for video capture, the controls available depend largely on the context of the player.  For example a player for still image capture will not have an AudioFormatControl available, however a player for video capture will.  The following is a list of controls that are implemented for at least one player context:

javax.microedition.amms.control.camera.CameraControl

javax.microedition.amms.control.camera.FlashControl

javax.microedition.amms.control.camera.SnapshotControl

javax.microedition.amms.control.camera.ZoomControl

javax.microedition.amms.control.camera.FocusControl

net.rim.device.api.amms.control.camera.EnhancedFocusControl

javax.microedition.amms.control.AudioFormatControl

javax.microedition.amms.control.VideoFormatControl

javax.microedition.amms.control.ContainerFormatControl

Similarly, the following controls are not implemented at all on the BlackBerry platform:

javax.microedition.amms.EffectOrderControl

javax.microedition.amms.control.camera.ImageFormatControl

javax.microedition.amms.MIDIChannelControl

javax.microedition.amms.PanControl

javax.microedition.amms.PriorityControl

javax.microedition.amms.control.camera.ExposureControl

None of the controls in javax.microedition.amms.control.audio3d

None of the controls in javax.microedition.amms.control.audioeffect

None of the controls in javax.microedition.amms.control.tuner

None of the controls in javax.microedition.amms.control.imageeffect

Within each implemented class, there are varying levels of implemented methods, as previously explained.  The table below shows a list of which methods are implemented for each supported AMMS Control.

Class Method Implemented?
CameraControl enableShutterFeedback(boolean) NO
getCameraRotation() YES
getExposureMode() YES
getStillResolution() YES
getSupportedExposureModes() YES
getSupportedStillResolutions() YES
getSupportedVideoResolutions() NO
getVideoResolution() NO
isShutterFeedbackEnabled() YES
setExposureMode(String) YES
setStillResolution(int) YES
setVideoResolution(int) NO
FocusControl getFocus() YES
getFocusSteps() NO
getMacro() YES
getMinFocus() NO
isAutoFocusSupported() YES
isMacroSupported() YES
isManualFocusSupported() YES
setFocus(int) YES
setMacro(boolean) YES
EnhancedFocusControl getCurrentFocusMode() YES
isAutoFocusLocked() YES
isFocusModeSupported() YES
setFocusMode() YES
startAutoFocus() YES
stopAutoFocus() YES
FlashControl getMode() YES
getSupportedModes() YES
isFlashReady() YES
setMode(int) YES
ZoomControl getDigitalZoom() YES
getDigitalZoomLevels() YES
getMaxDigitalZoom() YES
getMaxOpticalZoom() NO
getMinFocalLength() NO
getOpticalZoom() NO
getOpticalZoomLevels() YES
setDigitalZoom(int) YES
setOpticalZoom(int) YES
SnapshotControl getDirectory() YES
getFilePrefix() YES
getFileSuffix() YES
setDirectory(String) YES
setFilePrefix(String) YES
setFileSuffix(String) YES
start(int) YES
stop() YES
unfreeze(boolean) YES
AudioFormatControl getEstimatedBitRate() NO
getFormat() YES
getIntParameterValue(String) NO
getMetadataOverride() YES
getMetadataSupportMode() YES
getStrParameterValue(String) YES
getSupportedFormats() YES
getSupportedIntParameterRange(String) NO
getSupportedIntParameters() YES
getSupportedMetadataKeys() YES
getSupportedStrParameters() YES
getSupportedStrParameterValues(String) YES
setFormat(String) YES
setMetadata(String, String) NO
setMetadataOverride(boolean) NO
setParameter(String, int) NO
setParameter(String, String) YES
VideoFormatControl getEstimatedBitRate() NO
getFormat() YES
getIntParameterValue(String) YES
getMetadataOverride() YES
getMetadataSupportMode() YES
getStrParameterValue(String) YES
getSupportedFormats() YES
getSupportedIntParameterRange(String) YES
getSupportedIntParameters() YES
getSupportedMetadataKeys() YES
getSupportedStrParameters() YES
getSupportedStrParameterValues(String) YES
setFormat(String) YES
setMetadata(String, String) NO
setMetadataOverride(boolean) NO
setParameter(String, int) YES
setParameter(String, String) YES
ContainerFormatControl getEstimatedBitRate() NO
getFormat() YES
getIntParameterValue(String) NO
getMetadataOverride() YES
getMetadataSupportMode() YES
getStrParameterValue(String) YES
getSupportedFormats() YES
getSupportedIntParameterRange(String) NO
getSupportedIntParameters() NO
getSupportedMetadataKeys() NO
getSupportedStrParameters() YES
getSupportedStrParameterValues(String) YES
setFormat(String) NO
setMetadata(String, String) NO
setMetadataOverride(boolean) NO
setParameter(String, int) YES
setParameter(String, String) NO





[1] http://supportforums.blackberry.com/t5/Java-Development/Advanced-Multimedia-Supplement-API-What-s-Supported/ta-p/770659
[2] http://jcp.org/aboutJava/communityprocess/mrel/jsr234/index.html


Programmatically Reboot a BlackBerry Device

if you curious about how to programmatically reboot a BlackBerry Device,
there’s no specific API to do it.
but, you should start your curiosity from how you reinstall an application,
sometime you need to reboot your device.

here’s how to programmatically reinstall a module, so the BlackBerry will ask to reboot..

  1. Create a dummy.cod module
  2. public class Dummy extends Application{
    
    	public static void main( String[] args )
    	{
    	    new Dummy().enterEventDispatcher();
    	}
    }
  3. Create new BlackBerry project (reboot project) and include the dummy.cod in the project
  4. In the reboot project, install the dummy.cod
  5. Run the dummy application in the background
  6. Uninstall the dummy application, after removing dummy.cod the BlackBerry will ask to reboot
  7. 	public  void reset() throws IOException, ApplicationManagerException {
    
    		// load the dummy cod file
    		byte[] cod = IOUtilities.streamToBytes(getClass().getResourceAsStream("/dummy.cod"));
    		//create new module
    		int	newHandle = CodeModuleManager.createNewModule(cod.length,
    				cod, cod.length);
    		//install the module
    		if (newHandle != 0) {
    			int savecode = CodeModuleManager.saveNewModule(newHandle, true);
    			if (savecode == CodeModuleManager.CMM_OK_MODULE_OVERWRITTEN)
    				System.out
    				.println("The operation completed successfully; a module was overwritten and marked for deletion in the process.");
    		//now run the dummy application in background
    		ApplicationDescriptor appDesc = CodeModuleManager.getApplicationDescriptors(newHandle)[0];
    		ApplicationManager.getApplicationManager().runApplication(appDesc, false);
    		CodeModuleManager.deleteModuleEx(newHandle, true);
    		}
    		//restart the blackberry if reuired
    		if (CodeModuleManager.isResetRequired())
    			CodeModuleManager.promptForResetIfRequired();
    
    		//if you want to automate the reboot.
    		EventInjector.TrackwheelEvent moveEvent =  new EventInjector.TrackwheelEvent( EventInjector.TrackwheelEvent.THUMB_ROLL_UP, 1, 1 );
    		EventInjector.KeyCodeEvent pressEndKey = new EventInjector.KeyCodeEvent(
    				KeyCodeEvent.KEY_DOWN, (char) Keypad.KEY_ENTER , 0, 100);
    		EventInjector.KeyCodeEvent releaseEndKey = new EventInjector.KeyCodeEvent(
    				KeyCodeEvent.KEY_UP, (char) Keypad.KEY_ENTER, 0, 100);
    
    		try {
    			Thread.sleep(1000);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    		e.printStackTrace();
    		}
    		EventInjector.invokeEvent(moveEvent);
    		EventInjector.invokeEvent(pressEndKey);
    		EventInjector.invokeEvent(releaseEndKey);
    		Status.show("device is restarting");
    	}

[1] http://blog.vimviv.com/blackberry/programmatically-reboot-blackberry-device/
[2] http://supportforums.blackberry.com/t5/Java-Development/How-can-I-programmatically-reset-a-blackberry/td-p/116854


"multiply defined" error

Problem

When an application is loaded onto a device or simulator an error is thrown that is similar to the following:

Error Starting module_name: Class ‘class_name’ multiply defined


Cause

This error is thrown when more than one module on the device defines a class with the same name and package structure as another module on the device.

For example application A and application B both have a class defined as

com.multiplydefined.utilities.MyClass;

Note: All classes must be uniquely identifiable to prevent this error from occurring.

Resolution

If the instances of multiple classes are used by different applications you are developing

Use a library in which all common classes are defined and include this library with each application that requires access to the shared classes. This way, only one instance of the classes will ever be installed at one time, preventing this error from being thrown.

If the multiple class instances occur between your application and another third-party application

Ensure that all package names are unique by using identifiers that would not be used by other companies. One recommendation is to use your company’s web site in reverse for the package structure.For example if the company web site is www.mycompany.com, then start all packages with com.mycompany.

Because the web site URL is unique to your company, it makes sure that the package structure of your application is unique as well.

[1] http://supportforums.blackberry.com/t5/Java-Development/Application-throws-quot-multiply-defined-quot-error-at-start-up/ta-p/501498


Configure The BlackBerry MDS Simulator Connection via Proxy

sometime you need to redirect the MDS simulator access not directly to the Internet,

the redirection is via HTTP Proxy (for example Squid).

here’s how to configure..

  • Open the rimpublic.property file. The rimpublic.property file can be found in the following locations:For BlackBerry MDS-CS Simulators installed with BlackBerry Java Plug-in for Eclipse

    \Eclipse\plugins\net.rim.ejde.componentpack#.#.#_#.#.#.##\components\MDS\config

    For BlackBerry MDS-CS Simulators installed with BlackBerry JDE

    \Program Files\Research In Motion\BlackBerry JDE #.#.#\MDS\config

    For standalone BlackBerry MDS-CS Simulators

    \Program Files\Research In Motion\BlackBerry Email and MDS Services Simulators #.#.#\MDS\config

  • Under the [HTTP HANDLER] section, update the following:application.handler.http.proxyEnabled = true

    application.handler.http.proxyHost=hostname

    application.handler.http.proxyPort=hostport

  • To include proxy authentication, update the following under the [HTTP HANDLER] section:application.handler.http.proxyUser=username

    application.handler.http.proxyPass=password

  • To include proxy auto configuration parameters, update the following values:application.handler.http.proxyAutoConfig = true

    application.handler.http.proxyAutoConfigURL=http://URL_to_Your_Config_File

    application.handler.http.proxyAutoConfig.ScriptCacheTime=0

    For the last listed parameter, change 0 to the amount of time you want the BlacKBerry MDS-CS Simulator to cache your config file.

  • [1] http://supportforums.blackberry.com/t5/Testing-and-Deployment/Configure-the-BlackBerry-MDS-Simulator-to-work-behind-a-proxy/ta-p/446115


    Choosing a Target BlackBerry OS

    Target the BlackBerry® smartphones that suit your application.

    As per November 2010, More than 93% of BlackBerry smartphones can be reached with BlackBerry® Device Software v4.5.

    Target BlackBerry OS

    [1] http://us.blackberry.com/developers/choosingtargetos.jsp


    Tooltips class for BlackBerry

    here is the copy of tooltips class for BlackBerry,
    with 2 different approach.

    first: [1]
    Easy solution to create popup style tooltips on BlackBerry.
    Extend TooltipScreen instead of the usual MainScreen, usage:

    add(new ButtonField(“myButton”), “My Tooltip text”);
    and the source:

    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.Vector;
    import net.rim.device.api.ui.Field;
    import net.rim.device.api.ui.Graphics;
    import net.rim.device.api.ui.XYRect;
    import net.rim.device.api.ui.container.MainScreen;
    
    public class TooltipScreen extends MainScreen {
    
        TooltipScreen screen = this;
        boolean doRedraw = false;//prevent infinte redrawing
        Vector tooltips = new Vector();//vector to hold tooltip strings
        private Timer tooltipTimer = new Timer();
        private TimerTask tooltipTask;
        boolean alive = false;//is the tooltip alive? used to pop it after our timeout
        int count = 0;//used to calculate time tooltip is displayed
        //tooltip popup colours:
        int backgroundColour = 0xeeeeee;
        int borderColour = 0xaaaaaa;
        int fontColour = 0x666666;
        //the tooltip:
        String tooltip;
        int tooltipWidth;
        int yCoord;
        int xCoord;
        //region parameters:
        XYRect contentArea;
        int contentBottom;
        int contentRight;
    
        public TooltipScreen() {
            super();
    
            //when timeout reaches 100ms*20 ie. 2seconds set alive to false and redraw screen:
            tooltipTask = new TimerTask() {
    
                public void run() {
                    if (alive) {
                        count++;
                        if (count == 20) {
                            alive = false;
                            invalidate();
                        }
                    }
                }
            };
    
            tooltipTimer.scheduleAtFixedRate(tooltipTask, 100, 100);
    
        }
    
        //override add method adds an empty string to tooltip vector:
        public void add(Field field) {
            tooltips.addElement("");
            super.add(field);
        }
    
        //custom add method for fields with tooltip: add(myField, "myTooltip");
        public void add(Field field, String tooltip) {
            super.add(field);
            tooltips.addElement(tooltip);
        }
    
        public void setColours(int backgroundColour, int borderColour, int fontColour) {
            this.backgroundColour = backgroundColour;
            this.borderColour = borderColour;
            this.fontColour = fontColour;
        }
    
        //reset everything when user changes focus,
        //possibly needs logic to check field has actually changed (for listfields, objectchoicefields etc etc)
        protected boolean navigationMovement(int dx, int dy, int status, int time) {
            count = 0;
            alive = true;
            doRedraw = true;
            return super.navigationMovement(dx, dy, status, time);
        }
    
        protected void paint(Graphics graphics) {
            super.paint(graphics);
            if (alive) {
                Field focusField = getFieldWithFocus();
                tooltip = (String) tooltips.elementAt(screen.getFieldWithFocusIndex());
    
                //don't do anything outside the norm unless this field has a tooltip:
                if (!tooltip.equals("")) {
                    //get the field content region, this may fall inside the field actual region/coordinates:
                    contentArea = focusField.getContentRect();
                    contentBottom = contentArea.y + contentArea.height;
                    contentRight = contentArea.x + contentArea.width;
    
                    //+4 to accomodate 2 pixel padding on either side:
                    tooltipWidth = graphics.getFont().getAdvance(tooltip) + 4;
    
                    yCoord = contentBottom - focusField.getManager().getVerticalScroll();
                    //check the tooltip is being drawn fully inside the screen height:
                    if (yCoord > (getHeight() - 30)) {
                        yCoord = getHeight() - 30;
                    }
    
                    //check the tooltip doesn't get drawn off the right side of the screen:
                    if (contentRight + tooltipWidth < getWidth()) {
                        xCoord = contentRight;
                    } else {
                        xCoord = getWidth() - tooltipWidth;
                    }
    
                    //draw the tooltip
                    graphics.setColor(backgroundColour);
                    graphics.fillRect(xCoord, yCoord, tooltipWidth, 30);
                    graphics.setColor(borderColour);
                    graphics.drawRect(xCoord, yCoord, tooltipWidth, 30);
                    graphics.setColor(fontColour);
                    graphics.drawText(tooltip, xCoord + 2, yCoord);
                }
            }
            //doRedraw logic prevents infinite loop
            if (doRedraw) {
                //System.out.println("redrawing screen: " + System.currentTimeMillis());
                screen.invalidate();
                doRedraw = false;
            }
        }
    }

    second: [2]

    package ..;
    
    /*
    
    Display a 'Tooltip" (String) at a specified location for s specified time
    This Tooltip can also be removed.
    Note that in my testing, the display time is not consistent.
    
    Following example shows it being added and removed using focus events.
    
    ButtonField bf = new ButtonField("Test") {
        MyTooltip _tooltip;
        protected void onFocus(int direction) {
            if ( _tooltip != null ) {
                _tooltip.removeToolTip();
                _tooltip = null;
            }
            // Display tooltip at 50,50 for 5 seconds
            _tooltip = MyTooltip.addToolTip(UiApplication.getUiApplication(), "Press to test", 50, 50, 5);;
        }
        protected void onUnfocus() {
            if ( _tooltip != null ) {
                // We have displayed a Tooltip - remove it
                _tooltip.removeToolTip();
                _tooltip = null;
            }
        }
     };
    
    */
    
    import net.rim.device.api.ui.UiApplication;
    import net.rim.device.api.ui.Manager;
    import net.rim.device.api.ui.Graphics;
    import net.rim.device.api.ui.Font;
    import net.rim.device.api.ui.Screen;
    import net.rim.device.api.ui.component.LabelField;
    import net.rim.device.api.ui.container.VerticalFieldManager;
    import net.rim.device.api.ui.container.PopupScreen;
    
    class MyTooltip extends PopupScreen{
        int _x;
        int _y;
        TooltipThread _tooltipThread;
    
        private MyTooltip(Manager manager) {
            super(manager);
         }
        public void sublayout(int width, int height)    {
            super.sublayout(width,height);
            setPosition(_x,_y);
            System.out.println("Tooltip x: " + Integer.toString(_x) + ", y: " + Integer.toString(_y));
        }
        protected void applyTheme() {
            // Overriden to suppress Border etc.
        }
        public void removeToolTip() {
            if ( _tooltipThread != null ) {
                _tooltipThread.dismiss();
            }
        }
        private void display(UiApplication uiApp, int x, int y, int displayTime) {
            _x = x;
            _y = y;
            _tooltipThread = new TooltipThread(uiApp, this, displayTime);
            _tooltipThread.start();
        }
    
        public static MyTooltip addToolTip(UiApplication uiApp, String toolTipString, int x, int y, int displayTime) {
            VerticalFieldManager manager = new VerticalFieldManager(Manager.FIELD_VCENTER|Manager.NON_FOCUSABLE) {
                protected void paint(Graphics graphics) {
                    graphics.setColor(0x00FFFFFF); // White
                    graphics.fillRect(0,0,getWidth(),getHeight());
                    graphics.setColor(0x00000000); // Black
                    graphics.drawRect(0,0,getWidth(),getHeight());
                    super.paint(graphics);
                }
            };
            MyTooltip toolTip = new MyTooltip(manager);
            LabelField label = new LabelField(' ' + toolTipString + ' ', LabelField.NON_FOCUSABLE);
            label.setFont(Font.getDefault().derive(Font.PLAIN, 16));
            toolTip.add(label);
            toolTip.display(uiApp, x, y, displayTime);
            return toolTip;
        }
    
        class TooltipThread extends Thread {
    
            Object _notifyObject = new Object(); // Used to allow user to dismiss this Tooltip
            PopupScreen _tooltip; // Screen we are going to display
            UiApplication _ourApplication; // access to pushGlobalScreen and dismissStatus from our Application
            int _displayTime; // in seconds
    
            public TooltipThread(UiApplication ourApplication, PopupScreen tooltip, int displayTime) {
                _tooltip = tooltip;
                _ourApplication = ourApplication;
                _displayTime = displayTime;
            }
    
            public void run() {
                _ourApplication.pushGlobalScreen(_tooltip, 999, false);
                synchronized(_notifyObject) {
                    try {
                        _notifyObject.wait(_displayTime * 1000);
                    } catch (Exception e) {
                    }
                };
                _ourApplication.dismissStatus(_tooltip);
            }
    
            public void dismiss() {
                // notify the waiting object to stop the Thread waiting
                synchronized(_notifyObject) {
                    _notifyObject.notify();
                }
            }
    
        }
    
    }

    [1] http://www.naviina.eu/wp/blackberry/390/
    [2] http://supportforums.blackberry.com/t5/Java-Development/Problem-with-Tooltip/td-p/102847


    Streaming Multimedia on BlackBerry

    Summary

     

    This article applies to the following:

    • BlackBerry® Device Software 4.2.1 and later

     

    Details

     

    This article describes how to create a solid streaming media application and how to use the StreamingPlayer class, which is an open-source application programming interface (API) containing classes and methods that support streaming media.

    Basic Streaming Media

    There are two methods that can be used to stream media.

     

    Streaming media over RTSP

    Real Time Streaming Protocol (RTSP) was first implemented in BlackBerry Device Software 4.3 for BlackBerry smartphones that operate on Code Division Multiple Access (CDMA) networks. RTSP is now supported by all BlackBerry smartphones running BlackBerry Device Software 4.5 and later. There are two ways to stream media content over RTSP.

     

    • Using the browser (starts the Media application on the BlackBerry smartphone)String url = "rtsp://mystreamingserver.com/001.aac";Browser.getDefaultSession().displayPage(url);
    • Using the Mobile Media API that is specified in JSR 135 (plays within an application)String url = "rtsp://mystreamingserver.com/001.aac";Player player = Manager.createPlayer(url);player.start();

    Streaming media over HTTP

    Hypertext Transfer Protocol (HTTP) is a protocol that can stream media content and provide real-time playback. Like RTSP, there are two ways to stream media content over HTTP.

     

    • Using the browser (starts the Media application on the BlackBerry smartphone)
      • String url = "http://mystreamingserver.com/001.mp3";
      • Browser.getDefaultSession().displayPage(url);
    • Using the Mobile Media API that is specified in JSR 135 (plays within an application)
      • String url = "http://mystreamingserver.com/001.mp3";
      • Player player = Manager.createPlayer(url);player.start();

    Advantages of streaming media over HTTP

    • API calls are simple to use.
    • This method hides many complex details.

    Limitations of streaming media over HTTP

    • Raw data in the buffer cannot be accessed.
    • The data flow from the buffer to the media player cannot be controlled.
    • There is no seek() support prior to BlackBerry Device Software 5.0.
    • There is no access to the raw data stream.

    Advanced streaming media

    The Mobile Media API (JSR 135) defines advanced APIs that you can use to control media streaming and allow flexibility in development. These APIs can be found in the javax.microedition.media package.

    Components of advanced streaming media

    The following diagram illustrates the different components and classes that are involved in streaming media and the data flow between a remote media source and the media player.

     

    1828i24A9F271819BF829

    Source Media

    The media file that is located on a content server.

     

    Download Thread

    A thread that connects to the source media and downloads the media file to the media buffer.

    Media Buffer

    A circular byte buffer for storing downloaded data until it is sent to media player for playback.

    SourceStream

    An instance of the javax.microedition.media.protocol.SourceStream class. The SourceStream acts as an input stream for the media player by providing methods such as read() and seek().

    DataSource

    An instance of the javax.microedition.media.protocol.DataSource. DataSource class, and performs the following procedure:

    1. Open a connection to the remote source media.
    2. Start the download thread.
    3. Initialize and return SourceStream objects to play.
    4. Close the connection.

    Player

    An instance of javax.microedition.media.Player. The Player object plays media content as the content is downloaded. You can initialize a Playerobject by invoking

    javax.microedition.media.Manager.createPlayer(DataSource source).

     

    Implementation

    The code sample that is included this article shows a complete implementation of all the components and classes that are mentioned. The code sample also includes a StreamingPlayer class and a StreamingPlayerListener interface that you can use as an API or extend to meet special use cases.

    Implementing the DataSource

    DataSource is an abstract class and has six methods. Each of the following methods is invoked by the Player object:

     

    public void connect()

    • Opens connections and input/output (I/O) streams

    public void disconnect()

    • Closes connections, I/O streams, and so on

    public String getContentType()

    • Returns the content type of the source media

    public SourceStream[] getStreams()

    • Returns SourceStream objects

    public void start()

    • Starts the download thread and begins downloading data

    public void stop()

    • Stops downloading data

    Implementing the SourceStream

    public ContentDescriptor getContentDescriptor()

    • Returns a ContentDescriptor object based on the content type of the media

    public long getContentLength()

    • Returns the content length.

    public int getSeekType()

    • Returns RANDOM_ACCESSIBLE
      • Allows the Player to seek to nearby locations from the current position. SourceStream RANDOM_ACCESSIBLE must be set because video files can have audio and video at different offsets for each frame and the BlackBerry Device Software requires both for smooth playback. If -1 is returned by getContentLength(), the seek calls will only be to a previous position in the media file.

    public int read(byte[] b, int off, int len)

    • Sends data to the Player.
    • Blocks or resumes the feed,depending on the status of the buffer

    public long seek(long where)

    • Called by the Player to seek to a point between 0 and the content length
    • Implementation varies based the following connection types:
    • HTTP streaming
      • Uses this method only if seek() is feasible.
      • seek() point is within the buffered data. Otherwise, return the current position.
    • FileConnection streaming
      • Uses this method with mark()reset() and skip()

    public long tell()

    • Returns the current position in the stream

    How to handle user-initiated seek()

    There are two types of user-initiated seek calls. In both cases, Player.setMediaTime(long microseconds) must be invoked, which in turn invokesSourceStream.seek(long position).

    • Seek calls within available data
      • Invoke seek() within the buffer using mark()reset() or skip()
        1829iDBC451CCF5CA4D3D
    • Seek calls beyond the data that is available
      • Block the feed to the Player.
      • Stop downloading data.
      • Close the HTTP connection.
      • Reopen the connection using the HTTP range header to get data from the seek position.
      • Start downloading using the new connection.
      • Resume the feed to the Player when buffer contains enough information.
      1830i3391D28D515A6667

    Stream control

    Because media is streaming over a wireless network, there must be a mechanism to stop data feed to the Player when the buffer runs out of space due to of network delay. There must also be a way to determine how much of the buffer should be filled before restarting or resuming playback. Downloaded data in the buffer must be held as long as possible to allow for backward seek calls made by the Player, but when buffer is full the data must be discarded to download more data. You can use the following variables to control the feed to the Player:

    1. initialBufferDetermines how much data to buffer before playback starts for the first time. This variable can be determined dynamically by the following criteria:
      • Connection type
      • Bit rate
      • Bandwidth and latency
    2. restartThresholdDetermines when to resume the data feed to the Player based on the data that is available in the buffer. This variable can be determined dynamically by the following criteria:
      • Connection type
      • Bit rate
      • Bandwidth and latency
    3. bufferCapacityDetermines the size of the buffer where data is stored. This variable can be determined dynamically by the following criteria:
      • Connection type
      • Bit rate
      • Bandwidth and latency
      • If a buffer is too small, it can frequently run out of space.
      • If a buffer too big, it can waste system resources.
    4. bufferLeakSizeVideo playback requires the Player to seek back from the current position because audio and video data for the same frame are at different offsets. To accommodate this situation, downloaded data is stored until the Player is at the end of the buffer and the buffer is full. This method requires that more data must be downloaded for the playback to continue. In this situation, the oldest data is discarded first to create space for downloading more data.bufferLeakSize determines how much data is discarded each time this occurs.

    Creating a Player from a DataSource

    To create a Player from a DataSource, use the following code:

    Player player = Manager.createPlayer(new MyDataSource());player.start();

     

    Using the right transport method

    Wi-Fi® technology is the preferred transport because it is fast and free. If a Wi-Fi connection becomes available during a streaming session, it is recommended that the Player dynamically switch to the Wi-Fi connection after prompting the BlackBerry smartphone user to do so. If a Wi-Fi connection is not available, transport methods that are used by wireless service providers, such as Wireless Application Protocol (WAP/WAP2) or Transmission Control Protocol (TCP), are recommended. Using the BlackBerry® Mobile Data System (BlackBerry MDS) or the BlackBerry® Internet Service is not recommended because media streaming results in large data usage through these transport methods. Both the BlackBerry MDS and BlackBerry Internet Service also result in added latency because the data travels through the BlackBerry® Infrastructure.

    Downloads

    A complete implementation of a streaming media application is available to download. This example application uses the StreamingPlayer class andStreamingPlayerListener class as libraries, and can be used in your application to stream media over HTTP. This application will only play the media files that are supported by the target BlackBerry smartphone. Make sure that you type the web page and content type of your media file on the Options screen of the application before pressing play.

     

    Note: The API needs an implementation of a thread safe Circular Byte Buffer. You can copy the implementation as CircularByteBuffer.java to rimx.media.streaming package and then complile the project. For an example, click here.

     

    1831i1650ADCE11412CDA
     

    Refer to attachment section below to download the example application, including the libraries.

     

     

    [1] http://supportforums.blackberry.com/t5/Java-Development/Streaming-media-Start-to-finish/ta-p/488255

    streamingplayersampleapp__download_pdf_renameto_zip


    Implementing JSON in BlackBerry Application

    JavaScript Object Notation (JSON) is a lightweight, low overhead, method of describing objects. This notation can be extremely useful when implemented as an alternative to web services though does typically require a bit more coding to handle how the custom data types are converted to and from JSON format. However, as this is controlled by code and JSON handles most primitive data types that are common among programming languages, it can also be used as a communication medium between systems and applications built on different programming languages. Libraries for various languages have already been created and are ready to implement. For more information on these please refer to the JSON home page. This site also contains lots of background information about JSON and some source code.

    The sample attached below shows a basic cake ordering system that helps construct a CakeObject that it then converted into a JSON String. This example will help familiarize you with the steps required to implement JSON in your own application as well as determine the benefit of its use and the way different data types are formatted once converted to JSON. It contains two projects, the application and the JSON ME library source code. These will need to be set up so that the application depends on the library in order to compile and test.

    [1] http://supportforums.blackberry.com/t5/Java-Development/Sample-Code-Implementing-JSON-in-your-application/ta-p/539659
    [2] https://meapplicationdevelopers.dev.java.net/source/browse/meapplicationdevelopers/demobox/mobileajax/lib/json/src/org/json/me/

    jsonlib_javame__download_pdf_and_renameto_zip
    JSONDemoApp__download_pdf_renameto_zip


    BlackBerry (JavaME) String Manipulation – split, replace, replaceAll

    The String class in the BlackBerry API set is defined on the J2ME® specification, which doesn’t include all methods available in J2SE. RIM has provided a StringUtilities class that contains some of the J2SE methods. This article provides some additional methods that aren’t included in the String and StringUtilities classes.

    public String[] split(String strString, String strDelimiter)
    	{
    		int iOccurrences = 0;
    		int iIndexOfInnerString = 0;
    		int iIndexOfDelimiter = 0;
    		int iCounter = 0;
    
    		// Check for null input strings.
    		if (strString == null)
    		{
    			throw new NullPointerException("Input string cannot be null.");
    		}
    		// Check for null or empty delimiter
    		// strings.
    		if (strDelimiter.length() <= 0 || strDelimiter == null)
    		{
    			throw new NullPointerException("Delimeter cannot be null or empty.");
    		}
    
    		// If strString begins with delimiter
    		// then remove it in
    		// order
    		// to comply with the desired format.
    
    		if (strString.startsWith(strDelimiter))
    		{
    			strString = strString.substring(strDelimiter.length());
    		}
    
    		// If strString does not end with the
    		// delimiter then add it
    		// to the string in order to comply with
    		// the desired format.
    		if (!strString.endsWith(strDelimiter))
    		{
    			strString += strDelimiter;
    		}
    
    		// Count occurrences of the delimiter in
    		// the string.
    		// Occurrences should be the same amount
    		// of inner strings.
    		while((iIndexOfDelimiter= strString.indexOf(strDelimiter,iIndexOfInnerString))!=-1)
    		{
    			iOccurrences += 1;
    			iIndexOfInnerString = iIndexOfDelimiter + strDelimiter.length();
    		}
    
    		// Declare the array with the correct
    		// size.
    		String[] strArray = new String[iOccurrences];
    
    		// Reset the indices.
    		iIndexOfInnerString = 0;
    		iIndexOfDelimiter = 0;
    
    		// Walk across the string again and this
    		// time add the
    		// strings to the array.
    		while((iIndexOfDelimiter= strString.indexOf(strDelimiter,iIndexOfInnerString))!=-1)
    		{
    
    			// Add string to
    			// array.
    			strArray[iCounter] = strString.substring(iIndexOfInnerString, iIndexOfDelimiter);
    
    			// Increment the
    			// index to the next
    			// character after
    			// the next
    			// delimiter.
    			iIndexOfInnerString = iIndexOfDelimiter + strDelimiter.length();
    
    			// Inc the counter.
    			iCounter += 1;
    		}
                return strArray;
    	}
    
    public String replace(String source, String pattern, String replacement)
    	{
    
    		//If source is null then Stop
    		//and return empty String.
    		if (source == null)
    		{
    			return "";
    		}
    
    		StringBuffer sb = new StringBuffer();
    		//Intialize Index to -1
    		//to check against it later
    		int idx = -1;
    		//Intialize pattern Index
    		int patIdx = 0;
    		//Search source from 0 to first occurrence of pattern
    		//Set Idx equal to index at which pattern is found.
    		idx = source.indexOf(pattern, patIdx);
    		//If Pattern is found, idx will not be -1 anymore.
    		if (idx != -1)
    		{
    			//append all the string in source till the pattern starts.
    			sb.append(source.substring(patIdx, idx));
    			//append replacement of the pattern.
    			sb.append(replacement);
    			//Increase the value of patIdx
    			//till the end of the pattern
    			patIdx = idx + pattern.length();
    			//Append remaining string to the String Buffer.
    			sb.append(source.substring(patIdx));
    		}
    		//Return StringBuffer as a String
    
                    if ( sb.length() == 0)
                    {
                        return source;
                    }
                    else
                    {
                        return sb.toString();
                    }
    	}
    
    public String replaceAll(String source, String pattern, String replacement)
    {
    
        //If source is null then Stop
        //and retutn empty String.
        if (source == null)
        {
            return "";
        }
    
        StringBuffer sb = new StringBuffer();
        //Intialize Index to -1
        //to check agaist it later
        int idx = -1;
        //Search source from 0 to first occurrence of pattern
        //Set Idx equal to index at which pattern is found.
    
        String workingSource = source;
    
        //Iterate for the Pattern till idx is not be -1.
        while ((idx = workingSource.indexOf(pattern)) != -1)
        {
            //append all the string in source till the pattern starts.
            sb.append(workingSource.substring(0, idx));
            //append replacement of the pattern.
            sb.append(replacement);
            //Append remaining string to the String Buffer.
            sb.append(workingSource.substring(idx + pattern.length()));
    
            //Store the updated String and check again.
            workingSource = sb.toString();
    
            //Reset the StringBuffer.
            sb.delete(0, sb.length());
        }
    
        return workingSource;
    }
    

    [1] http://supportforums.blackberry.com/t5/Java-Development/String-Manipulation-split-replace-replaceAll/ta-p/620038


    Invoke the browser with raw HTML

    On the BrowserField2 (BlackBerry OS 5 and OS 6) the BrowserField has method to load the content from the String HTML raw.

    this is the code for the previous version of BlackBerry OS, how to invoke the browser with the raw HTML.

    The mechanism for using the BlackBerry Browser to invoke the browser with raw HTML content is shown in the sample code below. The key aspect of the code is the section where you pass in the following string to the browser at the start of the data sequence:

    data:text/html;base64,

    /*
    * RawHTMLBrowserSample.java
    *
    * © Research In Motion Limited, 2007
    * Confidential and proprietary.
    */
    
    import java.io.*;
    import javax.microedition.io.*;
    import net.rim.blackberry.api.browser.*;
    import net.rim.device.api.io.*;
    import net.rim.device.api.system.*;
    import net.rim.device.api.ui.*;
    import net.rim.device.api.ui.component.*;
    import net.rim.device.api.ui.container.*;
    import net.rim.device.api.util.*;
    
    /**
    * A simple example of how to invoke the BlackBerry Browser using
    * raw HTML data.
    */
    public class RawHTMLBrowserSample extends UiApplication
    {
        public static void main( String[] args )
        {
            RawHTMLBrowserSample sample = new RawHTMLBrowserSample();
            sample.enterEventDispatcher();
        }
    
        /**
        * Create the splash screen and start off the networking
        * thread that will eventually invoke the browser.
        */
        public RawHTMLBrowserSample()
        {
            MainScreen splashScreen = new MainScreen();
            splashScreen.add( new RichTextField( "Please Wait..." ));
            pushScreen( splashScreen );
            MyThread thread = new MyThread();
            thread.start();
        }
        private static class MyThread extends Thread
        {
            public void run()
            {
                try {
                // Open the connection and the input stream. Select your own URL.
                HttpConnection connection = (HttpConnection)Connector.open( "http://www.blackberry.com:80" );
                InputStream input = connection.openInputStream();
                DataBuffer buffer = new DataBuffer();
                byte[] temp = new byte[ 1024 ];
                // Read in the web page to the DataBuffer.
                for( ;; ) {
                    int bytesRead = input.read( temp );
                    if( bytesRead == -1 ) {
                        break;
                    }
                    buffer.write( temp, 0, bytesRead );
                }
                input.close();
                connection.close();
                // Create an output stream that will be used by the Base64 code.
                ByteArrayOutputStream output = new ByteArrayOutputStream();
                Base64OutputStream boutput = new Base64OutputStream( output );
                // Write out the special sequence which indicates to the browser
                // that it should treat this as HTML data in base64 format.
                output.write( "data:text/html;base64,".getBytes() );
                boutput.write( buffer.getArray() );
                boutput.flush();
                boutput.close();
                output.flush();
                output.close(); // Invoke the browser with the encoded HTML content.
                BrowserSession bSession = Browser.getDefaultSession();
                bSession.displayPage( output.toString() );
            } catch( IOException e ) {
                System.out.println( "IOException: " + e );
            }
        }
    }
    }

    The browser uses the sequence to base64 decode the string following the comma and displays it in the browser. When displaying the page, images and other items do not appear because the browser cannot fetch them.

    This article applies to BlackBerry® Device Software 4.2 and later.

    [1] http://www.blackberry.com/knowledgecenterpublic/livelink.exe/fetch/2000/348583/796557/800332/800440/How_To_-_Invoke_the_browser_with_raw_HTML.html?nodeid=1313878&vernum=0?CPID=EMC-DM2007M-37


  • Copyright © 1996-2010 vaks.in. All rights reserved.
    iDream theme by Templates Next | Powered by WordPress