54
BlackBerry Java Development Environment Multimedia Development Guide

Multimedia_guide

Embed Size (px)

Citation preview

BlackBerry Java Development Environment

Multimedia Development Guide

BlackBerry Java Development Environment Multimedia Development Guide

Last modified: 14 July 2008

Part number: 13697641

At the time of publication, this documentation is based on the BlackBerry Java Development Environment version 4.3.1.

Send us your comments on product documentation: https://www.blackberry.com/DocsFeedback.

©2008 Research In Motion Limited. All Rights Reserved. The BlackBerry and RIM families of related marks, images, and symbols are the exclusive properties of Research In Motion Limited. RIM, Research In Motion, BlackBerry, “Always On, Always Connected” and the “envelope in motion” symbol are registered with the U.S. Patent and Trademark Office and may be pending or registered in other countries.

Bluetooth is a trademark of Bluetooth SIG. Java is a trademarks of Sun Microsystems, Inc. Plazmic is a trademark of Plazmic Inc. All other brands, product names, company names, trademarks and service marks are the properties of their respective owners.All other brands, product names, company names, trademarks and service marks are the properties of their respective owners.

The BlackBerry smartphone and other devices and/or associated software are protected by copyright, international treaties, and various patents, including one or more of the following U.S. patents: 6,278,442; 6,271,605; 6,219,694; 6,075,470; 6,073,318; D445,428; D433,460; D416,256. Other patents are registered or pending in the U.S. and in various countries around the world. Visit www.rim.com/patents for a list of RIM (as hereinafter defined) patents.

This documentation including all documentation incorporated by reference herein such as documentation provided or made available at www.blackberry.com/go/docs is provided or made accessible "AS IS" and "AS AVAILABLE" and without condition, endorsement, guarantee, representation, or warranty of any kind by Research In Motion Limited and its affiliated companies ("RIM") and RIM assumes no responsibility for any typographical, technical, or other inaccuracies, errors, or omissions in this documentation. In order to protect RIM proprietary and confidential information and/or trade secrets, this documentation may describe some aspects of RIM technology in generalized terms. RIM reserves the right to periodically change information that is contained in this documentation; however, RIM makes no commitment to provide any such changes, updates, enhancements, or other additions to this documentation to you in a timely manner or at all.

This documentation might contain references to third-party sources of information, hardware or software, products or services including components and content such as content protected by copyright and/or third-party web sites (collectively the "Third Party Products and Services"). RIM does not control, and is not responsible for, any Third Party Products and Services including, without limitation the content, accuracy, copyright compliance, compatibility, performance, trustworthiness, legality, decency, links, or any other aspect of Third Party Products and Services. The inclusion of a reference to Third Party Products and Services in this documentation does not imply endorsement by RIM of the Third Party Products and Services or the third party in any way.

EXCEPT TO THE EXTENT SPECIFICALLY PROHIBITED BY APPLICABLE LAW IN YOUR JURISDICTION, ALL CONDITIONS, ENDORSEMENTS, GUARANTEES, REPRESENTATIONS, OR WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY CONDITIONS, ENDORSEMENTS, GUARANTEES, REPRESENTATIONS OR WARRANTIES OF DURABILITY, FITNESS FOR A PARTICULAR PURPOSE OR USE, MERCHANTABILITY, MERCHANTABLE QUALITY, NON-INFRINGEMENT, SATISFACTORY QUALITY, OR TITLE, OR ARISING FROM A STATUTE OR CUSTOM OR A COURSE OF DEALING OR USAGE OF TRADE, OR RELATED TO THE DOCUMENTATION OR ITS USE, OR PERFORMANCE OR NON-PERFORMANCE OF ANY SOFTWARE, HARDWARE, SERVICE, OR ANY THIRD PARTY PRODUCTS AND SERVICES REFERENCED HEREIN, ARE HEREBY EXCLUDED. YOU MAY ALSO HAVE OTHER RIGHTS THAT VARY BY STATE OR PROVINCE. SOME JURISDICTIONS MAY NOT ALLOW THE EXCLUSION OR LIMITATION OF IMPLIED WARRANTIES AND CONDITIONS. TO THE EXTENT PERMITTED BY LAW, ANY IMPLIED WARRANTIES OR CONDITIONS RELATING TO THE DOCUMENTATION TO THE EXTENT THEY CANNOT BE EXCLUDED AS SET OUT ABOVE, BUT CAN BE LIMITED, ARE HEREBY LIMITED TO NINETY (90) DAYS FROM THE DATE YOU FIRST ACQUIRED THE DOCUMENTATION OR THE ITEM THAT IS THE SUBJECT OF THE CLAIM.

TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW IN YOUR JURISDICTION, IN NO EVENT SHALL RIM BE LIABLE FOR ANY TYPE OF DAMAGES RELATED TO THIS DOCUMENTATION OR ITS USE, OR PERFORMANCE OR NON-PERFORMANCE OF ANY SOFTWARE, HARDWARE, SERVICE, OR ANY THIRD PARTY PRODUCTS AND SERVICES REFERENCED HEREIN INCLUDING WITHOUT LIMITATION ANY OF THE FOLLOWING DAMAGES: DIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, INDIRECT, SPECIAL, PUNITIVE, OR AGGRAVATED DAMAGES, DAMAGES FOR LOSS OF PROFITS OR REVENUES, FAILURE TO REALIZE ANY EXPECTED SAVINGS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, LOSS OF BUSINESS OPPORTUNITY, OR CORRUPTION OR LOSS OF DATA, FAILURES TO TRANSMIT OR RECEIVE ANY DATA, PROBLEMS ASSOCIATED WITH ANY APPLICATIONS USED IN CONJUNCTION WITH RIM PRODUCTS OR SERVICES, DOWNTIME COSTS, LOSS OF THE USE OF RIM PRODUCTS OR SERVICES OR ANY PORTION THEREOF OR OF ANY AIRTIME SERVICES, COST OF SUBSTITUTE GOODS, COSTS OF COVER, FACILITIES OR SERVICES, COST OF CAPITAL, OR OTHER SIMILAR PECUNIARY LOSSES, WHETHER OR NOT SUCH DAMAGES WERE FORESEEN OR UNFORESEEN, AND EVEN IF RIM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW IN YOUR JURISDICTION, RIM SHALL HAVE NO OTHER OBLIGATION, DUTY, OR LIABILITY WHATSOEVER IN CONTRACT, TORT, OR OTHERWISE TO YOU INCLUDING ANY LIABILITY FOR NEGLIGENCE OR STRICT LIABILITY.

THE LIMITATIONS, EXCLUSIONS, AND DISCLAIMERS HEREIN SHALL APPLY: (A) IRRESPECTIVE OF THE NATURE OF THE CAUSE OF ACTION, DEMAND, OR ACTION BY YOU INCLUDING BUT NOT LIMITED TO BREACH OF CONTRACT, NEGLIGENCE, TORT, STRICT LIABILITY OR ANY OTHER LEGAL THEORY AND SHALL SURVIVE A FUNDAMENTAL BREACH OR BREACHES OR THE FAILURE OF THE ESSENTIAL PURPOSE OF THIS AGREEMENT OR OF ANY REMEDY CONTAINED HEREIN; AND (B) TO RIM AND ITS AFFILIATED COMPANIES, THEIR SUCCESSORS, ASSIGNS, AGENTS, SUPPLIERS (INCLUDING AIRTIME SERVICE PROVIDERS), AUTHORIZED RIM DISTRIBUTORS (ALSO INCLUDING AIRTIME SERVICE PROVIDERS) AND THEIR RESPECTIVE DIRECTORS, EMPLOYEES, AND INDEPENDENT CONTRACTORS.

IN ADDITION TO THE LIMITATIONS AND EXCLUSIONS SET OUT ABOVE, IN NO EVENT SHALL ANY DIRECTOR, EMPLOYEE, AGENT, DISTRIBUTOR, SUPPLIER, INDEPENDENT CONTRACTOR OF RIM OR ANY AFFILIATES OF RIM HAVE ANY LIABILITY ARISING FROM OR RELATED TO THE DOCUMENTATION.

Prior to subscribing for, installing, or using any Third Party Products and Services, it is your responsibility to ensure that your airtime service provider has agreed to support all of their features. Installation or use of Third Party Products and Services with RIM's products and services may require one or more patent, trademark, copyright, or other licenses in order to avoid infringement or violation of third party rights. You are solely responsible for determining whether to use Third Party Products and Services and if any third party licenses are required to do so. If required you are responsible for acquiring them. You should not install or use Third Party Products and Services until all necessary licenses have been acquired. Any Third Party Products and Services that are provided with RIM's products and services are provided as a convenience to you and are provided "AS IS" with no express or implied conditions, endorsements, guarantees, representations, or warranties of any kind by RIM and RIM assumes no liability whatsoever, in relation thereto. Your use of Third Party Products and Services shall be governed by and subject to you agreeing to the terms of separate licenses and other agreements applicable thereto with third parties, except to the extent expressly covered by a license or other agreement with RIM.

The terms of use of any RIM product or service are set out in a separate license or other agreement with RIM applicable thereto. NOTHING IN THIS DOCUMENTATION IS INTENDED TO SUPERSEDE ANY EXPRESS WRITTEN AGREEMENTS OR WARRANTIES PROVIDED BY RIM FOR PORTIONS OF ANY RIM PRODUCT OR SERVICE OTHER THAN THIS DOCUMENTATION.

Published in Canada

Research In Motion Limited 295 Phillip Street Waterloo, ON N2L 3W8 Canada

Research In Motion UK Limited 200 Bath Road Slough, Berkshire SL1 3XE United Kingdom

Contents1 Working with multimedia in a BlackBerry Application.................................................................................. 7

BlackBerry Applications and multimedia .......................................................................................................7

2 Using audio and video in a BlackBerry Application.......................................................................................9Accessing stored media ................................................................................................................................... 9

Access media on a BlackBerry smartphone........................................................................................... 9Access media on a microSD card ............................................................................................................ 9

Playing media in the BlackBerry Browser ..................................................................................................... 9Play audio in the BlackBerry Browser .................................................................................................... 9Play a video in the BlackBerry Browser.................................................................................................10

Playing media in the media application.......................................................................................................10Start the media application with or without content..........................................................................10Streaming data from a remote source to the media application .......................................................11

Creating a BlackBerry Application that plays media files .........................................................................15Change the state of a Player .................................................................................................................. 17Play media in a BlackBerry Application ................................................................................................ 17Receive and send media application events ........................................................................................19Create different kinds of players...........................................................................................................20

Record audio on a BlackBerry smartphone................................................................................................. 24Send audio to a Bluetooth enabled headset...............................................................................................26

3 Using SVG content in a BlackBerry Application...........................................................................................29Using SVG content .........................................................................................................................................29Download SVG content..................................................................................................................................29

Display SVG content from the Plazmic Media Engine version 4.2 ..................................................29Play SVG content.....................................................................................................................................30Listen for events related to SVG content..............................................................................................31Code sample: Manage events when an application downloads SVG content ............................... 32Create a custom connection to SVG content ...................................................................................... 33

4 Working with images from the camera...........................................................................................................35Creating an image with the camera............................................................................................................. 35

Start the camera from a BlackBerry Application ................................................................................ 35

Receive notification of file system events................................................................................................... 35Detect when an image is added or removed in the file system........................................................ 35

Retrieving an image from the file system ................................................................................................... 37Retrieve an image from memory on a BlackBerry device.................................................................. 37Retrieve an image from a microSD card .............................................................................................. 37

Moving an image in the file system ............................................................................................................. 37Move an image within the same directory of the file system ........................................................... 37Move an image to a different directory of the file system ................................................................ 37

Deleting an image from the file system ...................................................................................................... 38Delete an image from memory on a BlackBerry device..................................................................... 38Delete an image from a microSD card .................................................................................................39

5 Working with images ..........................................................................................................................................41Drawing and positioning images...................................................................................................................41Using images................................................................................................................................................... 43

Use unprocessed images........................................................................................................................ 43Use encoded images ............................................................................................................................... 43

6 Code samples ......................................................................................................................................................45Code sample: Retrieving and displaying SVG content .............................................................................45Code sample: Implementing a listener to download SVG content .........................................................46Code sample: Implementing a custom connection to SVG content .......................................................48Code sample: Using an unprocessed image to recreate an encoded image.........................................50Code sample: Drawing a new bitmap using an existing bitmap ..............................................................51

1

Working with multimedia in a BlackBerry Application

BlackBerry Applications and multimediaYou can create a BlackBerry® Application that plays media in the BlackBerry® Browser, or plays media in the media application on the BlackBerry smartphone. You can also create a BlackBerry Application that is a media application. You can create a BlackBerry Application that is a media application and plays binary SVG content. You can create an application that records audio or sends audio to a Bluetooth® enabled headset.

For more information about media types that the BlackBerry smartphone supports, visit www.blackberry.com/btsc/support to read knowledge base article KB05482.

BlackBerry Applications and multimedia

BlackBerry Java Development Environment Multimedia Development Guide

8

2

Using audio and video in a BlackBerry Application

Accessing stored mediaYou can create a BlackBerry® Application that uses the Connector class and FileConnection interface to access media stored on the BlackBerry smartphone or a microSD card.

Access media on a BlackBerry smartphone> Invoke Connector.open(). Pass the following parameters: the file protocol and the location of the media file

on the BlackBerry® smartphone.FileConnection fconn = (FileConnection)Connector.open("file:///store/home/user/audio/newfile.mp3");

Access media on a microSD card> Invoke Connector.open(). Pass the following parameters: the file protocol and the location of the media file

on the microSD card.FileConnection fconn = (FileConnection)Connector.open("file:///SDCard/music/newfile.mp3");

Playing media in the BlackBerry BrowserA BlackBerry® Application can use the methods of the Browser class and BrowserSession class to play media in the BlackBerry® Browser.

Play audio in the BlackBerry Browser1. Invoke Browser.getDefaultSession().

BrowserSession soundclip = Browser.getDefaultSession();

Accessing stored mediaPlaying media in the BlackBerry BrowserPlaying media in the media applicationCreating a BlackBerry Application that plays media filesRecord audio on a BlackBerry smartphoneSend audio to a Bluetooth enabled headset

BlackBerry Java Development Environment Multimedia Development Guide

2. Invoke BrowserSession.displaypage().

soundclip.displayPage("file:///SDCard/BlackBerry/music/yourFile.mp3");

Play a video in the BlackBerry Browser1. Invoke Browser.getDefaultSession().

BrowserSession soundclip = Browser.getDefaultSession();

2. Invoke BrowserSession.displaypage().

soundclip.displayPage("file:///SDCard/BlackBerry/Video/soccergame.avi");

Playing media in the media applicationOn the BlackBerry® smartphones that include the media application, a BlackBerry Application can use the javax.microedition.content and net.rim.device.api.content packages to start the media application with or without content.

Start the media application with or without content1. Import the javax.microedition.content package into your application code.

Import javax.microedition.content;

2. Invoke Registry.getRegistry(). Pass the following parameter: the classname parameter which is the name of the class in the application that extends javax.microedition.midlet.MIDlet, net.rim.device.api.system.Application, or net.rim.device.api.ui.UiApplication. Store a reference to the returned object in a Registry object.

Registry reg = Registry.getRegistry(String classname);

3. Perform one of the following tasks:

4. To start the media application, invoke Registry.invoke(Invocation invocation). Pass the following parameter: an Invocation object.

reg.invoke(invocation)

Task Steps

Start the media application with no content.

> Create a new instance of an Invocation object. Store a reference to the object in an Invocation object.

Invocation invocation = new Invocation(null, null, BlackBerryContentHandler.ID_MEDIA_CONTENT_HANDLER);

Start the media application with content.

> Create a new instance of an Invocation object. Use a media type supported by the media application as a parameter, and store a reference to the object in an Invocation object.

Invocation invocation = new Invocation(file://...);

10

2: Using audio and video in a BlackBerry Application

Streaming data from a remote source to the media applicationTo stream data from a remote source to the media application, you must buffer the source and control how the media application reads the data. Create a custom DataSource and SourceStream implementation that will send data to the media application.

Code sample: Opening a connection to a remote audio file and buffering the dataThe code sample opens a connection to a remote audio file and buffers some data, then starts to play the audio file. The media application cannot read data when the amount of data in the buffer is low. When a certain level of data, specified by an application, exists in the buffer, the media application can read the data from the buffer. To buffer data in the SourceStream, use SharedInputStreams. One thread reads from a connection to the remote source, and tracks how much data has been transfered into the stream.

private class ConnectionThread extends Thread {// The thread reads the InputStream from a server, downloads the data into memory on the BlackBerry smartphone.public void run() { try {

byte[] data = new byte[READ_CHUNK]; int len = 0; //start buffering the file.

while (-1 != (len = readAhead.read(data))) { totalRead += len;

11

BlackBerry Java Development Environment Multimedia Development Guide

// The bufferingComplete variable lets the application pause before play back of data from the buffer.if (!bufferingComplete && totalRead > getStartBuffer()) {bufferingComplete = true;System.out.println("Initial Buffering Complete"); // Buffering is complete

}

if (_stop) { return; } }

//The entire file is now in the InputStream and in memory on the BlackBerry smartphone.

System.out.println("Downloading Complete"); System.out.println("Total Read: " + totalRead);

// If the size of the downloaded file does not match the size of the file reported by the server, print a message.

if (totalRead != s.getLength()) {System.err.println("* Unable to Download entire file *");

}downloadComplete = true;

// Write the data the application downloads to the local file

readAhead.setCurrentPosition(0); while (-1 != (len = readAhead.read(data))) { saveStream.write(data); } } catch (Exception e) { System.err.println(e.toString()); } }}

Reading dataThe DataSource provides a SourceStream that handles the read requests that the media application makes. The SourceStream uses a SharedInputStream based on the stream the application reads. The SharedInputStream uses the available() method to determine how much of the stream the application reads.

When the media application reads all of the data in the buffer, the application can block read requests that the media application makes until more data is buffered.The goal is to support playback as soon as possible and to stop only when necessary. Pause read operations to make sure the specified amount of audio data exists in the buffer for playback. For more information, visit www.blackberry.com/support to read DB00612.

12

2: Using audio and video in a BlackBerry Application

Specify the following four parameters in the DataSource to define how an application buffers data:

Code sample: Reading data from a bufferThe Reading data from a buffer code sample displays the read method of the StreamingSource implementation and lets the four parameters in the buffering scheme be manually adjusted.

public int read(byte[] b, int off, int len) throws IOException {// Read from a SharedInputStream that is shared with the same Stream that the //ConnectionThread is downloading to. Although both streams handle the same data, each //stream has a separate read location. The ConnectionThread works to keep its read location //as far ahead of the current playback position as possible.

System.out.println("Read Request for: " + len + " bytes"); // limit bytes read to our readLimit. int readLength = len; if (readLength > getReadLimit()) { readLength = getReadLimit(); } int available; boolean restart_pause = false; for (;;) {

//A read action is be restricted by the amount of data available for a read operation.//The application needs to download a specific amount of data before the application can start to playback audio.//enough data must be available to perform a full read operation. In this sample, the application configures the amount of data that is required to start the playback of audio and to perform a read operation. //The application uses the ReadLimit value to control the amount of data the second reader //reads during a read operation.

//The application uses the PauseBytes setting to determine when the second reader has read //all the data currently provided by the first variable reader. When this occurs, the //application pauses until there is enough data in the buffer for a read operation.

//The application uses the RestartBytes setting to define when there is enough data in the //buffer to perform a read operation

available = _baseSharedStream.available(); if (downloadComplete) { // Ignore all restrictions if downloading is complete System.out.println("Complete, Reading: " + len + " - Available: " + available); return _baseSharedStream.read(b, off, len); } else if (bufferingComplete) { if (restart_pause && available > getRestartBytes()) {

//Perform a read operation as there is now enough data in the buffer. System.out.println("Restarting - Available: " + available);

Item Description

Initial buffer the amount of audio data that the application downloads before it starts to play the data

Pause mark determines when the application’s attempts to read data from the buffer are blocked

Restart mark determines when the application can read data from the buffer

Limit determines the amount of data that the application can read from the buffer

13

BlackBerry Java Development Environment Multimedia Development Guide

restart_pause = false; return _baseSharedStream.read(b, off, readLength); } else if (!restart_pause && (available > getPauseBytes() || available > readLength)) {

//Determine if a previous read operation was paused and if there is enough data in the buffer to perform a read operation.

if (available < getPauseBytes()) {/* Perform a read operation, setting the pause flag so that future reads will pause until enough data for a read operation is loaded into the buffer*/ restart_pause = true;

} System.out.println("Reading: " + readLength + " - Available: " + available); return _baseSharedStream.read(b, off, readLength); } else if (!restart_pause) {

// The buffer does not contain enough data for a read operation. Pause the read operation until enough data is loaded into the buffer.

restart_pause = true;

} } else {// Pause the thread to allow the data to download before performing another read operation. try { Thread.sleep(100); } catch (Exception e) { System.err.println(e.getMessage()); } } }}

Code sample: Downloading a media file

public void connect() throws IOException { System.out.println("Loading: " + getLocator());

//Open a connection to the remote file s = (ContentConnection) Connector.open(getLocator(), Connector.READ);

//Get the length of the remote file. System.out.println("Size: " + s.getLength());

//Get the name of the remote file. int filenameStart = getLocator().lastIndexOf('/'); int paramStart = getLocator().indexOf(';'); if (paramStart < 0) { paramStart = getLocator().length(); } String filename = getLocator().substring(filenameStart, paramStart); System.out.println("Filename: " + filename);

//Open a connection to the file on the local file system.

14

2: Using audio and video in a BlackBerry Application

saveFile = (FileConnection) Connector.open("file:///SDCard/blackberry/music" + filename, Connector.READ_WRITE);

//If a file with the same name as the remote file doesn't exist on the local system, download the file again.

if (!saveFile.exists()) { saveFile.create(); }

//Configure the local file to be readable. saveFile.setReadable(true);

//Create a shared input stream using the an input stream from the local file.SharedInputStream fileStream = SharedInputStream.getSharedInputStream(saveFile.openInputStream());

fileStream.setCurrentPosition(0);

//If the file on the local file system is smaller than the remote file, download the file again.

if (saveFile.fileSize() < s.getLength()) { // didn't get it all before, download again saveFile.setWritable(true); saveStream = saveFile.openOutputStream(); readAhead = SharedInputStream.getSharedInputStream(s.openInputStream()); } else { downloadComplete = true; readAhead = fileStream; s.close(); } if (forcedContentType != null) { feedToPlayer = new LimitedRateSourceStream(readAhead, forcedContentType); } else { feedToPlayer = new LimitedRateSourceStream(readAhead, s.getType()); }}

Creating a BlackBerry Application that plays media filesYou can create a BlackBerry® Application that uses the Player interface and the javax.microedition.media (JSR 135) package to play media. The Player interface provides the methods to manage the different states of a media application and control the playback of media files. An object of a class that implements the Player interface can be in one of five states.

State Description

UNREALIZED an instance of a class that implements the Player interface is constructed.

REALIZED An instance of a class that implements the Player interface can locate and get resources on a server or file system.

15

BlackBerry Java Development Environment Multimedia Development Guide

PREFETCHED An instance of a class that implements the Player interface can perform tasks that are required to play media.

STARTED An instance of a class that implements the Player interface can start playing media.

CLOSED An instance of a class that implements the Player interface can release the resources it is using.

State Description

16

2: Using audio and video in a BlackBerry Application

Change the state of a Player

Play media in a BlackBerry Application

Task Step

Change the state of a Player from UNREALIZED to REALIZED. Invoke Player.realize().

Change the state of a Player from REALIZED to PREFETCHED. Invoke Player.prefetch().

Change the state of a Player from PREFETCHED to STARTED. Invoke Player.start().

Change the state of a Player from STARTED to CLOSED. Invoke Player.close().

Task Steps

Prepare the media application.

1. Invoke Player.realize().

2. Invoke Player.prefetch().

Start the media application. > Invoke Player.start(). An instance of a class that implements the Player interface returns to the PREFETCHED state when you invoke Player.stop() or when it reaches the end of the media file.

try { Player p = Manager.createPlayer("www.test.rim.net/abc.wav"); p.start(); } catch (MediaException pe) { } catch (IOException ioe) { }

Determine the controls that a media application supports.

You can use one object to access multiple controls. For example, one object can be both a VolumeControl and a ToneControl. The javax.microedition.media package contains a number of Control interfaces. For more information about the javax.microedition.media package, see the API Reference for the BlackBerry® Java® Development Environment.

1. Invoke Player.getControls().

2. To provide additional functionality for a media application, use one or more of the controls that the media application supports.

17

BlackBerry Java Development Environment Multimedia Development Guide

Allow video playback support. 1. To download a VideoControl object, invoke Player.getControls().

2. Open a file connection to a video file.

FileConnection con = (FileConnection) Connector.open("file:///SDCard/BlackBerry/videos/myvid.mp4", Connector.READ);

3. Open and return an input stream for a connection.

InputStream is = con.openInputStream();

4. Initialize and prepare a Player.

Player player = Manager.createPlayer(is, "video/mp4");player.realize();

5. Get the video control.

VideoControl videoControl = (VideoControl) player.getControl("VideoControl");videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, this);

6. To embed the video control in the canvas, specify the properties of the video control.

videoControl.setDisplayLocation(20, 30);videoControl.setDisplaySize(160, 90);videoControl.setVisible(true);

7. Implement the methods of the VideoControl interface to give a BlackBerry® Java® Application a variety of video playback support features. Perform one of the following actions:

• control the mode of video display through the use of USE_GUI_PRIMITIVE or USE_DIRECT_VIDEO

• control the location of the video with respect to the canvas that displays the video

• access the x-coordinate and the y-coordinate of the video with respect to the GUI object that displays the video

• display or hide video

• resize the video image

Adjust the volume of the media application.

1. Specify the volume of the media application.

VolumeControl volume = (VolumeControl) player.getControl("VolumeControl");

volume.setLevel(80);

2. Perform one of the following actions:

• Capture volume key events in an MIDP application.

Canvas.keyPressed():

protected void keyPressed(int keycode) {

if(keycode == -150) { //volume up

} else if(keycode == -151) {} //volume down

}

• Capture volume key events in a RIM® UI application.

Screen.keyControl():

protected boolean keyControl(char c, int status, int time) {

if(c == Characters.CONTROL_VOLUME_UP) {

} else if(c == Characters.CONTROL_VOLUME_DOWN) {}

}

Task Steps

18

2: Using audio and video in a BlackBerry Application

Receive and send media application eventsTo create a BlackBerry® Java® Application that listens for and sends media application events, you can use the API items in the javax.microedition.media (JSR 135) package.

Record changes to the volume key.

1. Override Screen.keyControl().

protected boolean keyControl(char c, int status, int time) {

2. Identify the volume key that the BlackBerry user changed.

if(c == Characters.CONTROL_VOLUME_UP) {//perform tasks

} else if(c == Characters.CONTROL_VOLUME_DOWN) {//perform tasks

}

}

Close the media application. 1. Invoke Player.stop().

2. Invoke Player.close().

Task Steps

Listen for changes to the state of the media application.

1. Implement PlayerListener.

2. To register the PlayerListener, invoke addPlayerListener.

private void doPlay()throws IOException, MediaException

{Player p = Manager.createPlayer("www.rim.com/rim.mp3");p.addPlayerListener(this);p.realize();p.prefetch();p.start();

}

Send the media application event to the registered PlayerListener.

> Invoke playerUpdate(Player player, String event, Object eventData).

{//Release resources when end of media event is receivedif ( event == PlayerListener.END_OF_MEDIA ){// Add code for actions if the end of media is reached.player.close();}

}

Task Steps

19

BlackBerry Java Development Environment Multimedia Development Guide

Create different kinds of playersTo play audio on a BlackBerry® smartphone, you can use the API items in the javax.microedition.media (JSR 135) package. You must create a media application and then add functionality to it.

Task Steps

Create a player for a sequence of tones.

> Implement ToneControl to allow playback of a BlackBerry® smartphone user-defined sequence of tones in an unvarying pitch. For more information about media application controls, see “Access media player functionality” on page 89.

Tempo is the beats per minute with 1 beat equal to 1/4 note. You determine the tempo by multiplying the tempo modifier by 4 to keep it within the byte range of 1 to 127. Tempos in the range of 20 bpm to 508 bpm equate to a tempo modifier range of 5 to 127.

Create a player for media from a URI.

> Invoke Manager.createPlayer(String locator). Pass the following parameter: a String with URI syntax that describes the media content.

Create a player for media from an input stream.

1. Invoke Manager.createPlayer(InputStream stream, String type).

The type parameter represents the type of input media content.

2. Check for a MediaException if the content type is null.

RecordStore recSt;int recId;

try {InputStream inpStr = newByteArrayInputStream((store.getRecord(recId));Player p = Manager.createPlayer(inpStr, "audio/mpeg");p.start();} catch (IOException ioEx) {} catch (MediaException meEx) {}

Create a player for streaming media.

The BlackBerry smartphones with BlackBerry Device Software version 4.3.0 or later that support EVDO will support Real Time Streaming Protocol (RTSP) functionality.

> Invoke Manager.createPlayer(String locator). Pass the following parameter: A String that represents an RTSP locator.

Manager.createPlayer("rtsp://streaming.rim.com/streaming_video.3gp");

20

2: Using audio and video in a BlackBerry Application

Create a player that displays a video in a field.

1. Create the Player, VideoControl, and Field variables.

Player _videoPlayer ;VideoControl _videoControl ;Field videoField;

2. Start a try block.

try {

3. Invoke Manager.createPlayer(String locator). Pass the following parameter: a String with URI syntax that describes the video content. Store a reference to the Player object that the call to createPlayer(String locator)returns.

_videoPlayer = Manager.createPlayer("file:///SDCard/BlackBerry/videos/soccer1.avi");

4. To allow a Player to get the information that it requires to get media resources, invoke Player.realize().

_videoPlayer.realize();

5. Invoke Player.getControl().Pass the following parameter: a String that represents the VideoControl class. Cast the returned object as a VideoControl object.

_videoControl = (VideoControl)_videoPlayer.getControl( "javax.microedition.media.control.VideoControl");

6. To initialize the mode that a videoField uses to display the video, invoke VideoControl.initDisplayMode(int mode, Object arg). Pass the following parameter: an arg value that specifies the UI primitive that displays the video. For example, in a BlackBerry® Application, use "net.rim.device.api.ui.Field" as the arg parameter, casting the object that this method returns as a Field object. For more information, see the API Reference for the BlackBerry® Java® Development Environment.

videoField = (Field)_videoControl.initDisplayMode( VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field" );

7. Check for any exceptions that might have occurred within the try block.

} catch ( Exception e ) {System.out.println( "Exception: " + e.toString() ); }

Create a player that displays an image from the camera viewFinder.

1. Invoke Manager.createPlayer(String locator). Pass the following parameter: a String with URI syntax that describes the image content.

Player cameraPlayer = Manager.createPlayer( "capture://video?encoding=jpeg" );

2. To allow a Player to get the information that it requires to get media resources, invoke Player.realize().

cameraPlayer.realize();

3. Invoke Player.getControl(). Pass the following parameter: a String that represents the VideoControl class. Cast the returned object as a VideoControl object.

VideoControl videoControl = (VideoControl)cameraPlayer.getControl( "javax.microedition.media.control.VideoControl");

4. To initialize the mode that a videoField uses to display the video, invoke VideoControl.initDisplayMode(int mode, Object arg).

Field VideoField = (Field)_videoControl.initDisplayMode( VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field" );

5. To take a snap shot of the image from the camera view, invoke VideoControl.getSnapshot().

int[] imageByte = videoControl.getSnapshot(null);

Task Steps

21

BlackBerry Java Development Environment Multimedia Development Guide

Code sample: Playing a sequence of tones

// "Mary Had A Little Lamb" has "ABAC" structure// Use block to repeat "A" section

byte tempo = 30; // 30 x 4 = tempo of 120 bpmbyte duration = 8; // Note length 8 (quaver) = 1/8th of a note duration

byte C4 = ToneControl.C4; // C note value = 60 (middle C)byte D4 = (byte)(C4 + 2); // D note value = 62 (a whole step)byte E4 = (byte)(C4 + 4); // E note value = 64 (a major third)byte G4 = (byte)(C4 + 7); // G note value = 67 (a fifth)byte rest = ToneControl.SILENCE; // rest

byte[] mySequence = {ToneControl.VERSION, 1, // version 1ToneControl.TEMPO, tempo, // configure tempo//// Start define "A" sectionToneControl.BLOCK_START, 0,//// Content of "A" sectionE4, duration, D4, duration, C4, duration, E4, duration,E4, duration, E4, duration, E4, duration, rest, duration,//// End define "A" sectionToneControl.BLOCK_END, 0,//// Play "A" sectionToneControl.PLAY_BLOCK, 0,//// Play "B" sectionD4, duration, D4, duration, D4, duration, rest, duration,E4, duration, G4, duration, G4, duration, rest, duration,//// Repeat "A" sectionToneControl.PLAY_BLOCK, 0,//// Play "C" sectionD4, duration, D4, duration, E4, duration, D4, duration, C4, duration

};

try{ Player p = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR); p.realize(); ToneControl c = (ToneControl)p.getControl("ToneControl"); c.setSequence(mySequence); p.start();

} catch (IOException ioe) { } catch (MediaException me) { }

22

2: Using audio and video in a BlackBerry Application

Code sample: Playing media from an input stream

//First we determine the supported content types String types[] = Manager.getSupportedContentTypes(null); for (int cnt = types.length - 1; cnt >= 0; --cnt) {

if (types[cnt].equals("audio/mpeg")) {

try { //Download the MP3 file Class clazz = Class.forName("com.rim.samples.AudioDemo"); InputStream is = clazz.getResourceAsStream("/jungleYell.mp3"); //Create an instance of the player from the InputStream Player player = javax.microedition.media.Manager.createPlayer (is, "audio/mpeg"); player.realize(); player.prefetch(); //start the player player.start(); } catch (Exception ex) { }

}

else if (types[cnt].equals("audio/x-wav ")) { //this is where you would play wav files}

else if (types[cnt].equals("audio/midi ")) {//this is where you would play midi files}

}

}

23

BlackBerry Java Development Environment Multimedia Development Guide

Record audio on a BlackBerry smartphoneThe BlackBerry® smartphone uses two formats to record audio: Adaptive Multi-Rate (AMR) and 8 kHz mono-16-bit pulse code modulation (PCM). By default, the format is AMR.

1. In a class that extends Thread, create a variable of type Player, a variable of type RecordControl for recording media from a Player, a variable of type ByteArrayOutputStream for the audio stream, and a byte array variable to store the OutputStream data.

final class VoiceNotesRecorderThread extends Thread

{

private Player _player;

private RecordControl _rcontrol;

private ByteArrayOutputStream _output;

private byte _data[];

2. Create a constructor for the class.

VoiceNotesRecorderThread(){}

3. Create a method that returns the size of the output stream buffer.

private int getSize()

{ return (_output != null ? _output.size() : 0); }

4. Create a method that returns an array that contains the contents of the output stream buffer.

private byte[] getVoiceNote()

{ return _data; }

5. In a try block in your implementation of the run method, create a Player that records audio. Specify the encoding to use as a parameter to the Manager.createPlayer(String locator) method. You can use the following supported locator strings:

public void run() {

try {

_player = Manager.createPlayer("capture://audio");

6. Change the Player to the REALIZED state.

_player.realize();

7. Get a control to record media from a Player.

_rcontrol = (RecordControl)_player.getControl("RecordControl");

8. Create a ByteArrayOutputStream to record the audio stream.

_output = new ByteArrayOutputStream();

Format String

AMR capture://audio

AMR capture://audio?encoding=amr or capture://audio?encoding=audio/amr

PCM capture://audio?encoding=pcm or capture://audio?encoding=audio/basic

24

2: Using audio and video in a BlackBerry Application

9. Configure the output stream to which the application records data.

_rcontrol.setRecordStream(_output);

10. Start recording the audio and start playing the media from the Player.

_rcontrol.startRecord();

_player.start();

11. In a catch block, specify that a notification dialog displays with a message about an exception, if one occurs.

} catch (final Exception e){

UiApplication.getUiApplication().invokeAndWait(new Runnable() {

public void run() {

Dialog.inform(e.toString());

} }

};

}

}

12. In a try block in your implementation of the stop method, perform the following tasks:

13. In a catch block, specify that a notification dialog displays with a message about an exception, if one occurs.

} catch (Exception e) {

synchronized (UiApplication.getEventLock()) {

Dialog.inform(e.toString());

}

}

}

}

Code sample: Recording audio from a player

final class VoiceNotesRecorderThread extends Thread{ private Player _player; private RecordControl _rcontrol;

Task Steps

Stop recording audio. > Invoke RecordControl.commit().

_rcontrol.commit()

Write the audio data from the OutputStream to an array.

> Invoke ByteArrayOutputStream.toByteArray(). Store the value that ByteArrayOutputStream.toByteArray() returns inside the byte array.

_data = _output.toByteArray();

Close the OutputStream and Player.

> Invoke ByteArrayOutputStream.close() and Player.close().

_output.close();

_player.close();

25

BlackBerry Java Development Environment Multimedia Development Guide

private ByteArrayOutputStream _output; private byte _data[]; VoiceNotesRecorderThread() {} private int getSize() { return (_output != null ? _output.size() : 0); } private byte[] getVoiceNote() { return _data; }

public void run() { try { // Create a Player that records live audio. _player = Manager.createPlayer("capture://audio"); _player.realize(); // Get the RecordControl, configure the record stream, _rcontrol = (RecordControl)_player.getControl("RecordControl"); //Create a ByteArrayOutputStream to record the audio stream. _output = new ByteArrayOutputStream(); _rcontrol.setRecordStream(_output); _rcontrol.startRecord(); _player.start(); } catch (final Exception e) { UiApplication.getUiApplication().invokeAndWait(new Runnable() { public void run() { Dialog.inform(e.toString()); } }); } }

public void stop() { try { //Stop recording, record data from the OutputStream, //close the OutputStream and player. _rcontrol.commit(); _data = _output.toByteArray(); _output.close(); _player.close();

} catch (Exception e) { synchronized (UiApplication.getEventLock()) { Dialog.inform(e.toString()); } } }} }

Send audio to a Bluetooth enabled headset1. Invoke Manager.createPlayer(String locator). Pass the following parameter: a String with the

location of an audio file.

Player p = javax.microedition.media.Manager.createPlayer("http://mycompany/test.mp3");

26

2: Using audio and video in a BlackBerry Application

2. To allow a Player to get media resources, invoke Player.realize().

p.realize();

3. Invoke Player.prefetch().p.prefetch();

4. To get the controls that a Player supports, invoke Player.getControls().

Control[] c = player.getControls();

5. Loop through the controls of the Player.

for(int i=c.length-1; i>=0; --i) {

6. If you find an instance of an AudioPathControl object, store a reference to the object in a variable of type AudioPathControl.

if(c[i] instanceof AudioPathControl) {

AudioPathControl apc = (AudioPathControl)c[i];

7. Perform one of the following tasks:

Task Steps

If the Bluetooth® device supports voice calls, change the audio path for the media stream to Bluetooth Synchronous Connection-Oriented Link (SCO).

> Invoke AudioPathControl.setAudioPath(int). Pass the following parameter: the AudioPathControl.AUDIO_PATH_BLUETOOTH attribute.

try{//Send the audio to Bluetooth. apc.setAudioPath(AudioPathControl.AUDIO_PATH_BLUETOOTH); } catch(Exception e) { System.err.println(e.toString()); } }

If the Bluetooth® device supports a Bluetooth enabled device like a Bluetooth stereo headset for listening to music, change the audio path for the media stream to Advanced Audio Distribution Profile (A2DP)

> Invoke AudioPathControl.setAudioPath(int). Pass the following parameter: the AudioPathControl.AUDIO_ BLUETOOTH_A2DP attribute.

try{//Send the audio to Bluetooth. apc.setAudioPath(AudioPathControl.AUDIO_PATH_BLUETOOTH_A2DP); } catch(Exception e) { System.err.println(e.toString()); } }

27

BlackBerry Java Development Environment Multimedia Development Guide

28

3

Using SVG content in a BlackBerry Application

Using SVG contentThe BlackBerry® smartphone supports a binary representation of Scalable Vector Graphics (SVG) content in the form of a .pme file.

You can use the Plazmic® Composer to create a .pme file or use the Plazmic SVG Transcoding Utility to convert a .svg file to a .pme file. The Plazmic Composer and the Plazmic SVG Transcoding Utility are included in the Plazmic® Content Developer’s Kit.

You can create a BlackBerry Application that uses methods from the MediaManager class to access a .pme file stored on the BlackBerry smartphone or a network location. You can create a BlackBerry Application that uses the methods from the MediaPlayer class to play a .pme file. For more information, visit www.blackberry.com/developers.

Download SVG content1. Create a MediaManager object.

2. Invoke MediaManager.createMedia().

The first time you invoke MediaManager.createMedia(), the URI must be absolute, unless you first invoke MediaManager.setProperty(“URI_BASE”, base_url) to configure a base URL. When you invoke createMedia() subsequently, the URL that the method used previously is the base URL.

MediaManager manager = new MediaManager();try {Object media = manager.createMedia("http://webserver/sample.pme");} catch (IOException ioe) {System.out.println("Error: requested content was not downloaded.");} catch (MediaException me) {System.out.println("Error: “ + me.getCode()); }

Display SVG content from the Plazmic Media Engine version 4.2> Create a screen that does not support scrolling.

For more information, see ‘Allow a screen to display a .pme file that the Plazmic Media Engine version 4.2 creates.’.

Using SVG content

BlackBerry Java Development Environment Multimedia Development Guide

Play SVG contentSee “Code sample: Retrieving and displaying SVG content” on page 45 for more information.

Task Steps

Configure the MediaPlayer for playback.

> Invoke MediaPlayer.setMedia().

MediaPlayer player = new MediaPlayer();try {player.setMedia(media);} catch (MediaException me) {System.out.println("Error: requested content type is not supported.”);

}

Allow a screen to display a .pme file that the Plazmic® Media Engine Version 4.2 creates.

The screen of the BlackBerry® Application must not support scrolling.

> Create an instance of a screen object using the NO_VERTICAL_SCROLL and NO_HORIZONTAL_SCROLL fields (inherited from the Manager class).

Screen screen = new Screen(Screen.NO_VERTICAL_SCROLL | Screen.NO_HORIZONTAL_SCROLL);

Download a UI object that displays a .pme file.

1. Invoke MediaPlayer.getUI().

2. Cast the object that getUI() returns to a Field type, and add it to a Screen to display.

screen.add((Field)player.getUI());

Play a .pme file. 1. Check the state of the media player.

2. Invoke MediaPlayer.start().

if(player.getState() == MediaPlayer.REALIZED) {try {player.start();} catch(MediaException me) {System.out.println("Error occurred during media playback: " + me.getCode() + me.getMessage()); }}

30

3: Using SVG content in a BlackBerry Application

Listen for events related to SVG contentSee “Code sample: Implementing a listener to download SVG content” on page 46 for more information.

Task Steps

Listen for media engine events.

1. Implement the MediaListener interface to let your BlackBerry® Application listen for media engine events.

2. Implement mediaEvent() to handle all possible media events.

public final class MediaListenerImpl implements MediaListener {public void mediaEvent(Object sender, int event, int eventParam, Object data) {switch(event) { case MEDIA_REQUESTED: // Perform action.break;case MEDIA_COMPLETE: // Perform action.break;case MEDIA_REALIZED: // Perform action.break;case MEDIA_IO: // Perform action.break;}} }

Register the listener. > Invoke addMediaListener() on the MediaPlayer and MediaManager objects.

private MediaListenerImpl _listener = new MediaListenerImpl();private MediaPlayer player = new MediaPlayer();private MediaManager manager = new MediaManager();player.addMediaListener(_listener);manager.addMediaListener(_listener);

31

BlackBerry Java Development Environment Multimedia Development Guide

Code sample: Manage events when an application downloads SVG content

public void mediaEvent(Object sender, int event, int eventParam, Object data) {switch(event) {

...case MEDIA_IO: {

LoadingStatus s = (LoadingStatus)data;}...break;

}break;...switch(s.getStatus()) {

case LoadingStatus.LOADING_STARTED:System.out.println("Loading in progress");

After downloading a .pme file, load the file in the background, and play it.

1. Invoke MediaManager.createMediaLater().

2. In MediaListener.mediaEvent(), add code to manage the MEDIA_REALIZED event that occurs when the application finishes loading a .pme file to the BlackBerry® smartphone.

3. To register the content, invoke MediaPlayer.setMedia(data).

4. To start playback, invoke MediaPlayer.start().

manager.createMediaLater("http://webserver/sample.pme");public void mediaEvent(Object sender, int event, int eventParam, Object data) {switch(event) {...case MEDIA_REALIZED:try {player.setMedia(data);player.start();} catch(MediaException me) {System.out.println("Error playing media” + me.getCode() + me.getMessage()); }break;}}

Track the progress of a .pme file an application is downloading.

1. Extend the net.rim.plazmic.mediaengine.io.LoadingStatus class.

2. In your implementation of mediaEvent(), when the MEDIA_IO event occurs, cast the Object in the data parameter to a LoadingStatus object.

3. To download content and manage the status of the .pme file that the application is downloading, invoke LoadingStatus.getStatus().

4. For each normal status, print a message to the console.

Manage the unsuccessful transfer of data.

For the LOADING_FAILED status, perform the following actions:

1. To retrieve the error code, invoke LoadingStatus.getCode().

2. To retrieve the detailed message, invoke LoadingStatus.getMessage().

3. To retrieve the URL string of the content, invoke LoadingStatus.getSource().

Task Steps

32

3: Using SVG content in a BlackBerry Application

break;case LoadingStatus.LOADING_READING:

System.out.println("Parsing in progress");break;case LoadingStatus.LOADING_FINISHED:

System.out.println("Loading completed");break;case LoadingStatus.LOADING_FAILED:

String errorName = null;int code = s.getCode();switch (code) {

case MediaException.INVALID_HEADER:errorName = "Invalid header" + "\n" + s.getSource();break;case MediaException.REQUEST_TIMED_OUT:errorName = "Request timed out" + "\n" + s.getSource();break;case MediaException.INTERRUPTED_DOWNLOAD:break;case MediaException.UNSUPPORTED_TYPE:errorName = "Unsupported type" + s.getMessage() + "\n" + s.getSource();break;default: {if (code > 200) {// A code > 200 indicates an HTTP errorerrorName = "URL not found";} else {// default unidentified errorerrorName = "Loading Failed";}errorName += "\n" + s.getSource() + "\n" + s.getCode() + ": " + s.getMessage();break;

}}System.out.println(errorName); break;

} // End switch s.getStatus().break;

}

Create a custom connection to SVG contentYou can create a BlackBerry® Application that can download SVG content from the Internet or from local storage using a connection that supports a custom protocol or has functionality that the MediaManager does not support or provide.

1. To implement a custom connector, implement the net.rim.plazmic.mediaengine.io.Connector interface.

2. To return an input stream to read content from a URI, implement getInputStream(String, ConnectionInfo).

3. To configure custom connector properties, implement setProperty(String, String).

33

BlackBerry Java Development Environment Multimedia Development Guide

4. To release the custom connection, implement releaseConnection(ConnectionInfo).

5. To register a custom connector, implement releaseConnection(ConnectionInfo).

34

4

Working with images from the camera

Creating an image with the camera

Start the camera from a BlackBerry ApplicationYou can create an application that uses the Invoke class to start the camera so a BlackBerry device user can take a picture.

> Invoke Invoke.invokeApplication(Invoke.APP_TYPE_CAMERA, new CameraArguments()).Invoke.invokeApplication(Invoke.APP_TYPE_CAMERA, new CameraArguments());

Receive notification of file system eventsYou can create an application that uses the FileSystemJournal class, the FileSystemJournalListener interface, and the FileSystemJournalEntry class to detect when an image is added to or removed from a file system for a BlackBerry device. The FileSystemJournal class acts as a journal that tracks changes to file systems. An application can query this journal to obtain information about file system events.

Detect when an image is added or removed in the file system1. Create a class that implements the FileSystemJournalListener interface.

class FileExplorerDemoJournalListener implements FileSystemJournalListener {

2. Create an instance variable that represents the last update sequence number.

private long _lastUSN = 0;

3. To receive notification when a new file system event occurs, implement FileSystemJournalListener.fileJournalChanged().

/**

* Notified when FileSystem event occurs.

*/

public void fileJournalChanged() {

Creating an image with the cameraReceive notification of file system eventsRetrieving an image from the file systemMoving an image in the file systemDeleting an image from the file system

BlackBerry Java Development Environment Multimedia Development Guide

4. Within your implementation of fileJournalChanged(), obtain the next USN that the journal will use.

long nextUSN = FileSystemJournal.getNextUSN();

5. Create a for loop that iterates backwards from the next USN that the journal will use to the last USN that the journal will use. A best practice is to stop the iteration once the application retrieves a journal entry.

for (long lookUSN = nextUSN-1; lookUSN >= _lastUSN; lookUSN--) {

6. In the for-loop, retrieve the journal entry that corresponds to the current USN.

FileSystemJournalEntry entry = FileSystemJournal.getEntry(lookUSN);

7. Create an IF clause that checks if the journal entry is null. If it is, a new file system journal entry does not exist.

if (entry == null) { // we didn't find an entry.

break;

8. If a journal entry does exist, obtain the path associated with the entry.

String path = entry.getPath();

9. Create an IF clause that checks if the path for the entry is not null.

if (path != null) {

10. Create an IF clause that checks if the file system event involves an image file. “

if (path.endsWith(“png”) |path.endsWith(“jpg”) | path.endsWith(“bmp”) | path.endsWith(“gif”) ){

11. Perform actions if a file was added or deleted from the file system.

switch (entry.getEvent()) {

case FileSystemJournalEntry.FILE_ADDED:

//either a picture was taken or a or a picture was added to the BlackBerry device

break;

case FileSystemJournalEntry.FILE_DELETED:

//a picture was removed from the BlackBerry device;

break;

12. To add the listener to the application, invoke Application.addFileSystemJournalListener(). In this example, FileExplorerDemo extends UIApplication which extends Application. Add the listener to the application in the FileExplorerDemo class.

this.addFileSystemJournalListener(new FileExplorerDemoJournalListener());

36

4: Working with images from the camera

Retrieving an image from the file system

Retrieve an image from memory on a BlackBerry device> Invoke Connector.open() with the file protocol and the location of the image on the BlackBerry device as

parameters.

FileConnection fconn = (FileConnection)Connector.open("file:///store/home/user/pictures/newfile.jpg");

Retrieve an image from a microSD card> Invoke Connector.open() with the file protocol and the location of the image on a microSD card as

parameters.

FileConnection fconn = (FileConnection)Connector.open("file:///SDCard/pictures/newfile.jpg")

Moving an image in the file system

Move an image within the same directory of the file systemRename() will not overwrite an existing file with the same name in the current directory.

1. Invoke Connector.open() with the file protocol and the location of the image on a microSD card as parameters.

FileConnection fconn = (FileConnection)Connector.open("file:///SDCard/pictures/newfile.jpg")

2. Invoke FileConnection.rename().

fconn.rename(“newfile.jpg”);

Move an image to a different directory of the file system1. Store the name and location of the old file and the new file.

String oldFile = "file:///store/home/user/pictures/newfile.jpg";

String newFile= "file:///SDCard/pictures/newfile.jpg";

2. Create a file connection for the old and the new location of the file.

FileConnection source = (FileConnection) Connector.open(oldFile);

FileConnection dest = (FileConnection) Connector.open(newFile);

37

BlackBerry Java Development Environment Multimedia Development Guide

3. If the file does not exist in the destination directory, create it.

if (!dest.exists()) {

dest.create();

}

4. Make the file in the destination directory writable.

dest.setWritable(true);

5. Open an output stream to the destination location of the file.

OutputStream outStream = dest.openOutputStream();

6. Open an input stream to the source location of the file.

InputStream inStream = source.openInputStream();

7. Create a Byte array the represents the size of the buffer for the FileInputStream.

byte[] Buffer = new byte[1024];

8. Create a While loop that reads data from the InputStream and into the OutputStream.int length = -1;while ((length = inStream.read(buffer)) > 0) {outStream.write(buffer, 0 , length);}

9. Close the input stream and the output stream connections.

inStream.close();

outStream.close();

Deleting an image from the file system

Delete an image from memory on a BlackBerry device1. Invoke Connector.open() with the file protocol and the location of the image on the BlackBerry device as

parameters.

FileConnection fconn = (FileConnection)Connector.open("file:///store/home/user/pictures/newfile.jpg");

2. Invoke FileConnection.delete().

fconn.delete();

3. Since invoking FileConnection.delete() automatically flushes and closes all open input and output streams, invoke FileConnection.close() to prevent exceptions from occurring.

fconn.close();

38

4: Working with images from the camera

Delete an image from a microSD card1. Invoke Connector.open() with the file protocol and the location of the image on the microSD card as

parameters.

FileConnection fconn = (FileConnection)Connector.open("file:///SDCard/pictures/newfile.jpg");

2. Invoke FileConnection.delete().

fconn.delete();

3. Since invoking FileConnection.delete() automatically flushes and closes all open input and output streams, invoke FileConnection.close() to prevent exceptions from occurring.

fconn.close();

39

BlackBerry Java Development Environment Multimedia Development Guide

40

5

Working with images

Drawing and positioning imagesPosition an image

Draw an image in color

Drawing and positioning imagesUsing images

Task Steps

Use a field. 1. Invoke the Graphics() constructor.

Bitmap surface = new Bitmap(100, 100);BitmapField surfaceField = new BitmapField(surface);Graphics graphics = new Graphics(surface);

2. Add the BitmapField to the screen.

mainScreen.add(surfaceField);

Use the whole screen. 1. Invoke the Screen.getGraphics()method.

Graphics graphics = Screen.getGraphics();

2. Specify that the methods perform the drawing functions within the boundaries of the screen.

graphics.fillRect(10, 10, 30, 30);graphics.drawRect(15, 15, 30, 30);

Task Steps

Determine whether the BlackBerry® smartphone supports a color screen.

> Invoke Graphics.isColor().

Determine the number of colors that the BlackBerry smartphone screen supports.

> Invoke Graphics.getNumColors().

Configure the pixel transparency in the drawing area.

1. Invoke one of the following methods:

• Graphics.setGlobalApha()

• Graphics.getGlobalAlpha()

2. Define a global alpha value within the following range:

• 0 (0x0000): completely transparent

• 255 (0x00FF): fully opaque

BlackBerry Java Development Environment Multimedia Development Guide

Determine the raster operations that the BlackBerry® Java® Application supports.

1. Invoke Graphics.isRopSupported(int).

2. Provide one of the following constants as a parameter:

• ROP_CONST_GLOBALALPHA: blends the constant foreground color using a constant global alpha value with destination pixels

• ROP_SRC_GLOBALALPHA: blends a source bitmap using a constant global alpha value with destination pixels

Draw shaded, filled paths. > Invoke Graphics.drawShadedFilledPath():

public void drawShadedFilledPath(int[] xPts, int[] yPts, byte[] pointTypes, int[] colors, int[] offsets);

Example: Drawing a path that blends from blue to red

Bitmap surface = new Bitmap(240, 160);BitmapField surfaceField = new BitmapField(surface);add(surfaceField);Graphics graphics = new Graphics(surface); int[] X_PTS = { 0, 0, 240, 240 };int[] Y_PTS = { 20, 50, 50, 20 };int[] drawColors = { 0x0000CC, 0x0000CC, 0xCC0000, 0xCC0000 };try {graphics.drawShadedFilledPath(X_PTS, Y_PTS, null, drawColors, null);} catch (IllegalArgumentException iae) {System.out.println("Bad arguments.");}

Turn a drawing style on. > Invoke Graphics.setDrawingStyle(int drawStyle, boolean on).

Turn a drawing style off. > Invoke Graphics.setDrawingStyle(int drawStyle, boolean off).

Determine if a drawing style is configured.

> Invoke Graphics.isDrawingStyleSet(int drawStyle).

Use a monochrome bitmap as a stamp.

> Create an object using the STAMP_MONOCHROME parameter. This parameter allows the BlackBerry® Java® Application to use monochrome bitmaps as stamps by rendering the non-transparent region in color. This parameter applies to bitmaps that are 1 bit and have alpha defined.

BitmapField field = new BitmapField(original, BitmapField.STAMP_MONOCHROME);

Set the color of a rectangular region of a bitmap

This method only works on color bitmaps of type ROWWISE_16BIT_COLORRowwise. For more information, see the API Reference. The destination region must be fully contained within the current bitmap.

> Invoke Bitmap.setRGB565(byte[] rgbData, int offset, int scanLength, int x, int y, int width, int height).

Draw an image on an empty bitmap.

1. Create an empty bitmap, copying the type and size from an existing bitmap.

2. Create a Graphics object and use the empty bitmap as the drawing surface.

3. To draw a new image using raw data retrieved from the original image, invoke Graphics.rawRGB().

Bitmap restored = new Bitmap(original.getType(), original.getWidth(), original.getHeight());Graphics graphics = new Graphics(restored);try {graphics.drawRGB(argb, 0, restored.getWidth(), 0, 0, restored.getWidth(), restored.getHeight());} catch(Exception e) {System.out.println("Error occurred during drawing: " + e);}

Task Steps

42

5: Working with images

See “Code sample: Drawing a new bitmap using an existing bitmap” on page 51 for more information.

Using images

Use unprocessed images

Use encoded images

Task Steps

Allow the BlackBerry® Java® Application to use unprocessed image data.

> To retrieve the unprocessed image data from a region of a bitmap and store the data in an integer array, invoke Bitmap.getARGB().

void getARGB(int[] argbData, int offset, int scanLength, int x, int y, int width, int height);

Store image data. 1. Initialize an integer array.

2. To store the unprocessed image data from a new or predefined bitmap in an integer array, invoke Bitmap.getARGB().

Bitmap original = Bitmap.getPredefinedBitmap(Bitmap.INFORMATION);int[] argb = new int[original.getWidth() * original.getHeight()];original.getARGB(argb, 0, original.getWidth(), 0, 0, original.getWidth(), original.getHeight());

Compare two images to see if they are identical.

> Invoke Bitmap.equals().

if(restored.equals(original)) {System.out.println("Success! Bitmap renders correctly with RGB data.");} else if(!restored.equals(original)) {System.out.println("Bitmap rendered incorrectly with RGB data.");}

Task Steps

Access an image. 1. Save the image to the project folder or subfolder.

2. Add the image to the project in the BlackBerry® Integrated Development Environment.

3. Invoke Class.getResourceAsStream() to retrieve the image as an input stream of bytes.

private InputStream input;...try {input = Class.forName("com.rim.samples.docs.imagedemo.ImageDemo").getResourceAsStream("/images/example.png");} catch (ClassNotFoundException e) {System.out.println("Class not found");}

43

BlackBerry Java Development Environment Multimedia Development Guide

See “Code sample: Using an unprocessed image to recreate an encoded image” on page 50 for more information.

Encode an image. 1. Invoke EncodedImage.createEncodedImage(). This method uses the unprocessed image data in the byte array to create an instance of EncodedImage.

2. Check for an IllegalArgumentException, which EncodedImage.createEncodedImage() throws if the byte array that you provide as a parameter does not contain a recognized image format.

private byte[] data = new byte[2430]; // Store the contents of the image file.try {input.read(data); // Read the image data into the byte array.} catch (IOException e) {// Handle exception.}try {EncodedImage image = EncodedImage.createEncodedImage(data, 0, data.length);} catch (IllegalArgumentException iae) {System.out.println("Image format not recognized.");}

Display an encoded image. 1. To assign the encoded image to a BitmapField, invoke BitmapField.setImage().

2. To add the BitmapField to the screen, invoke add().

BitmapField field = new BitmapField();field.setImage(image);add(field);

Configure the decoding mode.

1. Invoke EncodedImage.setDecodeMode().

2. Provide one of the following modes as a parameter to the method:

• DECODE_ALPHA: decodes an alpha channel, if one exists (this is the default mode)

• DECODE_NATIVE: forces the BlackBerry® Java® Application to decode the bitmap to the native bitmap type of the BlackBerry® Device Software

• DECODE_READONLY: marks the decoded bitmap as read-only

Configure the image display size.

> Invoke EncodedImage.setScale().

The inverse of the integer specified by the scaling factor scales the image. For example, if you configure the scaling factor to 2, the image decodes at 50% of its original size.

Task Steps

44

6

Code samples

Code sample: Retrieving and displaying SVG contentThe MediaSample.java sample downloads a .pme file from a content server and displays it on the BlackBerry® smartphone.

/** * MediaSample.java * Copyright (C) 2001-2007 Research In Motion Limited. All rights reserved. */

package com.rim.samples.docs.mediasample;

import java.io.*;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.system.*;

import net.rim.plazmic.mediaengine.*;

public class MediaSample extends UiApplication { public static void main(String[] args) { MediaSample app = new MediaSample(); app.enterEventDispatcher(); } public MediaSample() { pushScreen(new MediaSampleScreen()); } final static class MediaSampleScreen extends MainScreen { public MediaSampleScreen() { super(); LabelField title = new LabelField(“Media Sample”, LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH); setTitle(title); MediaPlayer player = new MediaPlayer(); MediaManager manager = new MediaManager();

Code sample: Retrieving and displaying SVG contentCode sample: Implementing a listener to download SVG contentCode sample: Implementing a custom connection to SVG contentCode sample: Using an unprocessed image to recreate an encoded imageCode sample: Drawing a new bitmap using an existing bitmap

BlackBerry Java Development Environment Multimedia Development Guide

try { Object media = manager.createMedia(“http://webserver/SVGFILE.pme”); player.setMedia(media); } catch (IOException ioe) { } catch (MediaException me) { System.out.println(“Error during media loading: “); System.out.println(me.getCode()); System.out.println(me.getMessage()); } add((Field)player.getUI()); try { player.start(); } catch(MediaException me) { System.out.println(“Error occured during media playback: “); System.out.println(me.getCode()); System.out.println(me.getMessage()); } } }}

Code sample: Implementing a listener to download SVG contentThe MediaSample2.java sample implements a listener to download a .pme file in the background and display information on the status of the downloading process on the console.

/** * MediaSample2.java * Copyright (C) 2001-2007 Research In Motion Limited. All rights reserved. */

package com.rim.samples.docs.mediasample;

import java.io.*;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.system.*;

import net.rim.plazmic.mediaengine.*;import net.rim.plazmic.mediaengine.io.*;

public class MediaSample2 extends UiApplication { private MediaPlayer player = new MediaPlayer(); private MediaManager manager = new MediaManager(); private MediaListenerImpl _listener = new MediaListenerImpl();

private MediaSample2Screen _screen; public static void main(String[] args) { MediaSample2 app = new MediaSample2(); app.enterEventDispatcher(); }

46

6: Code samples

public MediaSample2() { _screen = new MediaSample2Screen(); pushScreen(_screen); } public final class MediaListenerImpl implements MediaListener { public void mediaEvent(Object sender, int event, int eventParam, Object data) { switch(event) { case MEDIA_REQUESTED: System.out.println(“Media requested”); break; case MEDIA_COMPLETE: System.out.println(“Media completed”); break; case MEDIA_REALIZED: try { player.setMedia(data); player.start(); } catch(MediaException me) { System.out.println(“Error during media loading: “ + me.getCode() + me.getMessage()); } break; case MEDIA_IO: { LoadingStatus s = (LoadingStatus)data; switch(s.getStatus()) { case LoadingStatus.LOADING_STARTED: System.out.println(“Loading in progress”); break; case LoadingStatus.LOADING_READING: System.out.println(“Parsing in progress”); break; case LoadingStatus.LOADING_FINISHED: System.out.println(“Loading completed”); break; case LoadingStatus.LOADING_FAILED: String errorName = null; int code = s.getCode(); switch (code) { case MediaException.INVALID_HEADER: errorName = “Invalid header” + “\n” + s.getSource(); break; case MediaException.REQUEST_TIMED_OUT: errorName = “Request timed out” + “\n” + s.getSource(); break; case MediaException.INTERRUPTED_DOWNLOAD: break; case MediaException.UNSUPPORTED_TYPE: errorName = “Unsupported type” + s.getMessage() + “\n” + s.getSource(); break;

default: {

47

BlackBerry Java Development Environment Multimedia Development Guide

if (code > 200) { // A code > 200 indicates an HTTP error. errorName = “URL not found”; } else { // Default unidentified error. errorName = “Loading Failed”; } errorName += “\n” + s.getSource() + “\n” + s.getCode() + “: “ + s.getMessage(); break; }

} System.out.println(errorName); break; } // End switch s.getStatus(). break; } } } } final class MediaSample2Screen extends MainScreen { public MediaSample2Screen() { super(); LabelField title = new LabelField(“Media Sample”, LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH); setTitle(title);

player.addMediaListener(_listener); manager.addMediaListener(_listener);

// Change this to the location of a test .pme file. manager.createMediaLater(“http://test.rim.com/SVGBS0001.pme”); add((Field)player.getUI()); } }}

Code sample: Implementing a custom connection to SVG contentThe CustomPMEConnector.java sample provides a framework for implementing a custom connector.

/* * CustomPMEConnector.java * Copyright (C) 2003-2007 Research In Motion Limited. All rights reserved. */

package com.rim.samples.docs.mediasample;

import java.io.*;import net.rim.plazmic.mediaengine.*;

48

6: Code samples

import net.rim.plazmic.mediaengine.io.*;

public class CustomPMEConnector implements Connector {

private Connector delegate; private InputStream input; CustomPMEConnector(Connector delegate) { this.delegate = delegate; } public InputStream getInputStream(String uri, ConnectionInfo info) throws IOException, MediaException { if (uri.startsWith(“myprotocol://”)) { // Perform special tasks. info.setConnection(new MyProtocolConnection()); info.setContentType(“application/x-vnd.rim.pme”); // OpenMyInputStream() is a custom method that opens //stream for “myprotocol://” input = openMyInputStream(uri); } else { input = delegate.getInputStream(uri, info); } return input; } private InputStream openMyInputStream(String uri) { InputStream input = null; // @todo: open stream here return input; } public void releaseConnection(ConnectionInfo info) throws IOException, MediaException { Object o = info.getConnection(); if (o instanceof MyProtocolConnection) { ((MyProtocolConnection)o).close(); // Perform cleanup. } else { delegate.releaseConnection(info); } } public void setProperty(String property, String value) { delegate.setProperty(property, value); } // Inner class that defines the connection class. public static class MyProtocolConnection { public MyProtocolConnection() { // ... } public void close() { // ... } }}

49

BlackBerry Java Development Environment Multimedia Development Guide

Code sample: Using an unprocessed image to recreate an encoded image/** * ImageDemo.java * Copyright (C) 2001-2007 Research In Motion Limited. All rights reserved. */package com.rim.samples.docs.imagedemo;

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.system.*;import java.io.*;

/* The ImageDemo.java sample retrieves raw data from an image that is included in its project, and then uses that raw data to recreate an EncodedImage. */public class ImageDemo extends UiApplication { public static void main(String[] args) { ImageDemo app = new ImageDemo(); app.enterEventDispatcher(); } public ImageDemo() { pushScreen(new ImageDemoScreen()); } }

final class ImageDemoScreen extends MainScreen { private static final int IMAGE_SIZE = 2430; private InputStream input; private byte[] data = new byte[IMAGE_SIZE]; public ImageDemoScreen() { super(); setTitle(new LabelField(“Image Demo Sample”)); try { input = Class.forName(“com.rim.samples.docs.imagedemo.ImageDemo”).getResourceAsStream(“/images/picture.png”); } catch (ClassNotFoundException e) { System.out.println(“Class not found”); } if(input == null) { System.out.println(“Error: input stream is not initialized.”); } else if (input != null) { System.out.println(“OK: input stream is initialized.”); try { int code = input.read(data); System.out.println(“Total number of bytes read into buffer: “ + code + “ .”); } catch (IOException e) { // Handle exception.

50

6: Code samples

} try { EncodedImage image = EncodedImage.createEncodedImage(data, 0, data.length); add(new BitmapField(image.getBitmap())); } catch (IllegalArgumentException iae) { System.out.println(“Image format not recognized.”); } } }}

Code sample: Drawing a new bitmap using an existing bitmapTo draw a new bitmap image, the DrawDemo.java sample downloads unprocessed data from a predefined bitmap image. It then displays the original and restored images.

/* * DrawDemo.java * Copyright (C) 2002-2007 Research In Motion Limited. */ package com.rim.samples.docs.drawing; 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.*;

/* The DrawDemo.java sample retrieves raw data from a predefined bitmap image, and then draws a new bitmap using the data. It then displays the original and restored images. */public class DrawDemo extends UiApplication { public static void main(String[] args) { DrawDemo app = new DrawDemo(); app.enterEventDispatcher(); } public DrawDemo() { pushScreen(new DrawDemoScreen()); } }

final class DrawDemoScreen extends MainScreen { public DrawDemoScreen() { super();

LabelField title = new LabelField(“UI Demo”, LabelField.USE_ALL_WIDTH); setTitle(title);

51

BlackBerry Java Development Environment Multimedia Development Guide

Bitmap original = Bitmap.getPredefinedBitmap(Bitmap.INFORMATION); Bitmap restored = new Bitmap(original.getType(), original.getWidth(), original.getHeight());

Graphics graphics = new Graphics(restored);

// Retrieve raw data from original image. int[] argb = new int[original.getWidth() * original.getHeight()]; original.getARGB(argb, 0, original.getWidth(), 0, 0, original.getWidth(), original.getHeight()); // Draw new image using raw data retrieved from original image. try { graphics.drawRGB(argb, 0, restored.getWidth(), 0, 0, restored.getWidth(), restored.getHeight()); } catch(Exception e) { System.out.println(“Error occurred during drawing: “ + e); } if(restored.equals(original)) { System.out.println(“Success! Bitmap renders correctly with RGB data.”); } else if(!restored.equals(original)) { System.out.println(“Bitmap rendered incorrectly with RGB data.”); } BitmapField field1 = new BitmapField(original, BitmapField.STAMP_MONOCHROME); BitmapField field2 = new BitmapField(restored); add(new LabelField(“Original bitmap: “)); add(field1); add(new LabelField(“Restored bitmap: “)); add(field2); }}

52

©2008 Research In Motion Limited

Published in Canada.