Blackberry Java SDK Development Guide 1249411 0803110230 001 6.0 US
Blackberry Java SDK Development Guide 1249411 0803110230 001 6.0 US
Version: 6.0
Development Guide
Contents
1 Working with audio on a BlackBerry device............................................................................................................................ Playing audio................................................................................................................................................................................... Play audio in a BlackBerry device application.................................................................................................................... Play audio in the BlackBerry Browser.................................................................................................................................. Code sample: Playing a sequence of tones......................................................................................................................... Recording audio.............................................................................................................................................................................. Record audio in a BlackBerry device application................................................................................................................ 2 2 2 5 5 6 7 17 17 17 22 22 34 34 41 41 41 48 49 50 51
2 Working with video on a BlackBerry device............................................................................................................................. Playing video................................................................................................................................................................................... Play a video in a UI field in a BlackBerry device application............................................................................................ Recording video............................................................................................................................................................................... Record video to a file in a BlackBerry device application.................................................................................................. RIMM streaming video file............................................................................................................................................................. RIM proprietary video format (RIMM streaming file)......................................................................................................... 3 Working with pictures on a BlackBerry device........................................................................................................................ Taking pictures................................................................................................................................................................................ Take a picture in a BlackBerry device application.............................................................................................................. 4 Find more information................................................................................................................................................................ 5 Provide feedback......................................................................................................................................................................... 6 Document revision history......................................................................................................................................................... 7 Legal notice..................................................................................................................................................................................
Development Guide
You can play audio on a BlackBerry device through the BlackBerry Browser, or by generating a series of discrete tones, by using the javax.microedition.media.Player class in your BlackBerry device application. You can use the Player class to open a file that is stored on the BlackBerry device's internal media storage or media card, by specifying a URL, or by specifying a location in your .cod file and using the format: cod:///path. Player provides access to the associated Control classes (for example, VolumeControl) that control the playback and recording functionality (for example, the volume). You can use the browser to play an audio file by creating a new BrowserSession object and opening the audio file as you would any URI. You can also create a series of tones to play in your application. For example, you can use these tones as a notification sounds in your application. You can define the frequencies and length of the discrete tones and play them in a sequence.
2.
Create the application framework by extending the UiApplication class. In main(), create an instance of the new class and invoke enterEventDispatcher() to enable the application to receive events. In the application constructor, invoke pushScreen() to display the custom screen for the application. The AudioPlaybackDemoScreen class, described in step 3, represents the custom screen.
public class AudioPlaybackDemo extends UiApplication { public static void main(String[] args) { AudioPlaybackDemo app = new AudioPlaybackDemo(); app.enterEventDispatcher(); } public AudioPlaybackDemo() {
Development Guide
Playing audio
pushScreen(new AudioPlaybackDemoScreen());
3.
Create the framework for the custom screen by extending the MainScreen class.
class AudioPlaybackDemoScreen extends MainScreen { public AudioPlaybackDemoScreen() { } }
4.
In the screen constructor, in a try/catch block, create an instance of the Player class by invoking Manager.createPlayer(String), and passing in the location of the audio file to play.
try { Player p = javax.microedition.media.Manager.createPlayer("http://abc .com/sounds/abc.wav");
5.
To control an aspect of playback, retrieve the appropriate Control object. Invoke the Player object's realize() method to access its associated Control object. The following code sample demonstrates how to retrieve the VolumeControl object and set the volume level of playback.
try { Player p = javax.microedition.media.Manager.createPlayer("http://abc .com/sounds/abc.wav"); p.realize(); VolumeControl volume = (VolumeControl) p.getControl("VolumeControl"); volume.setLevel(30);
Development Guide
Playing audio
6.
Invoke Player.start() to start playback. Invoking Player.start() implicitly performs all the necessary state transitions. In the following code sample, both realize() and prefetch() are invoked to demonstrate how to explicitly initialize the Player object before starting playback.
try { Player p = javax.microedition.media.Manager.createPlayer("http://abc .com/sounds/abc.wav"); p.realize(); VolumeControl volume = (VolumeControl)p.getControl("VolumeControl"); volume.setLevel(30); p.prefetch(); p.start();
public class AudioPlaybackDemo extends UiApplication { public static void main(String[] args) { AudioPlaybackDemo app = new AudioPlaybackDemo(); app.enterEventDispatcher(); } public AudioPlaybackDemo() { pushScreen(new AudioPlaybackDemoScreen()); } private class AudioPlaybackDemoScreen extends MainScreen { public AudioPlaybackDemoScreen() {
Development Guide
Playing audio
Player p = javax.microedition.media.Manager.createPlayer("http://abc .com/sounds/abc.wav"); p.realize(); VolumeControl volume = (VolumeControl)p.getControl("VolumeControl"); volume.setLevel(30); p.prefetch(); p.start(); } catch(MediaException me) { Dialog.alert(me.toString()); } catch(IOException ioe) { Dialog.alert(ioe.toString()); }
try {
2. 3.
Invoke Browser.getDefaultSession().
BrowserSession soundclip = Browser.getDefaultSession();
Invoke BrowserSession.displaypage().
soundclip.displayPage("file:///SDCard/BlackBerry/music/yourFile .mp3");
Development Guide
Recording audio
byte duration = 8; // Note length 8 (quaver) = 1/8th of a note duration // Notes are determined from ToneControl.C4 (Middle C), // which has a value of 60 and a frequency of 261.6 Hz. 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 1 ToneControl.TEMPO, tempo_mod, // // Start define "A" section ToneControl.BLOCK_START, 0, // // Content of "A" section E4, duration, D4, duration, C4, duration, E4, duration, E4, duration, E4, duration, E4, duration, rest, duration, // // End define "A" section ToneControl.BLOCK_END, 0, // end of block number 0 // // Play "A" section ToneControl.PLAY_BLOCK, 0, // // Play "B" section D4, duration, D4, duration, D4, duration, rest, duration, E4, duration, G4, duration, G4, duration, rest, duration, // // Repeat "A" section ToneControl.PLAY_BLOCK, 0, // // Play "C" section D4, 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) { }
Recording audio
You can record audio in a BlackBerry device application by using the javax.microedition.media.Player class and the associated RecordControl interface. The recording is saved to a file in built-in media storage, media card storage, or to a stream.
Development Guide
Recording audio
2.
Create the application framework by extending the UiApplication class. In main(), create an instance of the new class and invoke enterEventDispatcher() to enable the application to receive events. In the application constructor, invoke pushScreen() to display the custom screen for the application. The AudioRecordingDemoScreen class, which is described in step 3, represents the custom screen.
public class AudioRecordingDemo extends UiApplication { public static void main(String[] args) { AudioRecordingDemo app = new AudioRecordingDemo(); app.enterEventDispatcher(); } public AudioRecordingDemo() { pushScreen(new AudioRecordingDemoScreen()); }
3.
Create the framework for the custom screen by extending the MainScreen class. Declare an instance of the AudioRecorderThread class, which is described in step 5.
private class AudioRecordingDemoScreen extends MainScreen { private AudioRecorderThread _recorderThread; public AudioRecordingDemoScreen() { }
4.
In the AudioRecordingDemoScreen constructor, invoke setTitle() to specify the title for the screen. Invoke addMenuItem() twice to add the menu items to start and stop the recording. which is described in step 5.
Development Guide
Recording audio
5.
In the AudioRecordingDemoScreen class, define the menu items to start the recording and to stop recording by invoking the start() and stop() methods of the AudioRecorderThread class respectively, which is described in step 6. in the following code sample, Player starts in its own thread to increase the responsiveness of the menu items.
private class StartRecording extends MenuItem { public StartRecording() { super("Start recording", 0, 100); } public void run() { try { AudioRecorderThread newRecorderThread = new AudioRecorderThread(); newRecorderThread.start(); _recorderThread = newRecorderThread; } catch (Exception e) { Dialog.alert(e.toString()); } }
private class StopRecording extends MenuItem { public StopRecording() { super("Stop recording", 0, 100); } public void run() { try { if (_recorderThread != null) { _recorderThread.stop(); } }
Development Guide
Recording audio
6.
Inside the AudioRecordingDemo screen class, define an inner class that extends Thread and implements PlayerListener. In the inner class, create a variable of type Player and a variable of type RecordControl for recording media. Note: You are not required to record audio in a separate thread because recording operations are threaded by design.
private class AudioRecorderThread extends Thread implements javax.microedition.media.PlayerListener { private Player _player; private RecordControl _recordControl; AudioRecorderThread() { } }
7.
In the AudioRecorderThread class, implement the Thread interface's run() method. In run() create a try/catch block and invoke Manager.createPlayer(String locator) to create a Player object to record audio, using as a parameter a value that specifies the encoding to use.
public void run() { try { _player = javax.microedition.media.Manager .createPlayer("capture://audio?encoding=audio/amr"); } catch( IOException e ) { Dialog.alert(e.toString()); } catch( MediaException e ) { Dialog.alert(e.toString()); }
8.
Development Guide
Recording audio
public void run() { try { _player = javax.microedition.media.Manager .createPlayer("capture://audio?encoding=audio/amr"); _player.addPlayerListener(this); } catch( IOException e ) { Dialog.alert(e.toString()); } catch( MediaException e ) { Dialog.alert(e.toString()); }
9.
To record, invoke Player.realize() method to access the RecordControl object. Then, invoke Player.getControl(), passing in the string, RecordControl, to retrieve the RecordControl object.
public void run() { try { _player = javax.microedition.media.Manager .createPlayer("capture://audio?encoding=audio/amr"); _player.addPlayerListener(this); _player.realize(); _recordControl = (RecordControl) _player.getControl( "RecordControl" ); } catch( IOException e ) { Dialog.alert(e.toString()); } catch( MediaException e ) { Dialog.alert(e.toString()); }
10. Invoke RecordControl.setRecordLocation() to set the location on the device to save the audio recording.
public void run() { try {
10
Development Guide
Recording audio
_player = javax.microedition.media.Manager .createPlayer("capture://audio?encoding=audio/amr"); _player.addPlayerListener(this); _player.realize(); _recordControl = (RecordControl) _player.getControl( "RecordControl" ); _recordControl.setRecordLocation("file:///store/home/user/ AudioRecordingTest .amr" ); } catch( IOException e ) { Dialog.alert(e.toString()); } catch( MediaException e ) { Dialog.alert(e.toString()); } }
11.
Invoke RecordControl.startRecord() to start recording the audio and start playing the media. Invoke Player.start() to start Player.
public void run() { try { _player = javax.microedition.media.Manager .createPlayer("capture://audio?encoding=audio/amr"); _player.addPlayerListener(this); _player.realize(); _recordControl = (RecordControl) _player.getControl( "RecordControl" ); _recordControl.setRecordLocation("file:///store/home/user/ AudioRecordingTest .amr" ); _recordControl.startRecord(); _player.start(); } catch( IOException e ) { Dialog.alert(e.toString()); } catch( MediaException e ) {
11
Development Guide
Recording audio
Dialog.alert(e.toString());
12. In AudioRecorder, implement the Thread interface's stop() method. Check that Player is not null and invoke Player.close() to release the Player object's resources. Set Player to null.
public void stop() { if (_player != null) { _player.close(); _player = null; } }
13. Check that RecordControl is not null and invoke RecordControl.stopRecord() to stop recording. In a try/ catch block, invoke RecordControl.commit() to save the recording to a specified file. Set RecordControl to null.
public void stop() { if (_player != null) { _player.close(); _player = null; } if (_recordControl != null) { _recordControl.stopRecord(); try {
14. In AudioRecorderThread, implement the PlayerListener interface's playerUpdate() method which is invoked whenever the Player object generates an event. In the following code sample, the application outputs information about the event.
public void playerUpdate(Player player, String event, Object eventData) {
12
Development Guide
Recording audio
Dialog.alert("Player " + player.hashCode() + " got event " + event + ": " + eventData);
public class AudioRecordingDemo extends UiApplication { public static void main(String[] args) { AudioRecordingDemo app = new AudioRecordingDemo(); app.enterEventDispatcher(); } public AudioRecordingDemo() { pushScreen(new AudioRecordingDemoScreen()); } private class AudioRecordingDemoScreen extends MainScreen { private AudioRecorderThread _recorderThread; public AudioRecordingDemoScreen() { setTitle("Audio recording demo"); addMenuItem(new StartRecording()); addMenuItem(new StopRecording());
private class StartRecording extends MenuItem { public StartRecording() { super("Start recording", 0, 100); } public void run() { try {
13
Development Guide
Recording audio
AudioRecorderThread newRecorderThread = new AudioRecorderThread(); newRecorderThread.start(); _recorderThread = newRecorderThread; } catch (Exception e) { Dialog.alert(e.toString()); } } } private class StopRecording extends MenuItem { public StopRecording() { super("Stop recording", 0, 100); } public void run() { try { if (_recorderThread != null) { _recorderThread.stop(); } } catch (Exception e) { Dialog.alert(e.toString()); } }
private class AudioRecorderThread extends Thread implements javax.microedition.media.PlayerListener { private Player _player; private RecordControl _recordControl; AudioRecorderThread() { } public void run() { try { _player = javax.microedition.media.Manager .createPlayer("capture://audio?encoding=audio/amr");
14
Development Guide
Recording audio
_player.addPlayerListener(this); _player.realize(); _recordControl = (RecordControl) _player.getControl( "RecordControl" ); _recordControl .setRecordLocation("file:///store/home/user/AudioRecordingTest.amr"); _recordControl.startRecord(); _player.start(); } catch( IOException e ) { Dialog.alert(e.toString()); } catch( MediaException e ) { Dialog.alert(e.toString()); }
public void playerUpdate(Player player, String event, Object eventData) { Dialog.alert("Player " + player.hashCode() + " got event " + event + ": " + eventData); }
15
Development Guide
Recording audio
16
Development Guide
You can play video in your application on a BlackBerry device by using the javax.microedition.media.Player class. The Player class lets you open a file that is stored on the BlackBerry device's built-in media storage or media card storage, by specifying a URL, or by specifying a location in your .cod file using the format: cod:///path. Player can retrieve the associated Control classes that you can use to control various aspects of playback (for example, the volume of the audio track). To create a UI component that displays the video playback, you can invoke VideoControl.initDisplay() to retrieve a Field object that is added to your UI.
2.
Create the application framework by extending the UiApplication class. In main(), create an instance of the new class and invoke enterEventDispatcher() to enable the application to receive events. In the application constructor, invoke pushScreen() to display the custom screen for the application. The VideoPlaybackDemoScreen class, which is described in step 3, represents the custom screen.
public class VideoPlaybackDemo extends UiApplication { public static void main(String[] args) { VideoPlaybackDemo app = new VideoPlaybackDemo(); app.enterEventDispatcher(); } public VideoPlaybackDemo() { pushScreen(new VideoPlaybackDemoScreen()); }
3.
Create the framework for the custom screen by extending the MainScreen class.
17
Development Guide
Playing video
4.
In the screen constructor, in a try/catch block, create an instance of the Player class by invoking Manager.createPlayer(String), passing in the location of the video file to play.
try { Player player = javax.microedition.media.Manager .createPlayer("file:///SDCard/BlackBerry/videos/soccer1.avi");
5.
To control an aspect of playback, retrieve the appropriate Control object. First, invoke the Player object's realize () method to access its associated Control object. Next , invoke Player.getControl() passing in the string, VideoControl, to retrieve the VideoControl object that is associated with Player.
try { Player player = javax.microedition.media.Manager .createPlayer("file:///SDCard/BlackBerry/videos/soccer1.avi"); player.realize(); VideoControl videoControl = (VideoControl) player.getControl("VideoControl");
6.
Invoke VideoControl.initDisplayMode(int mode, Object arg) passing an arg parameter specifying the UI primitive that displays the video to initialize the mode that a video field uses. Cast the returned object as a Field object. Note: You can invoke initDisplayMode() in different ways to return a Field , an Item for use with MIDlets, or to display a video on a Canvas class.
18
Development Guide
Playing video
try {
Player player = javax.microedition.media.Manager .createPlayer("file:///SDCard/BlackBerry/videos/soccer1.avi"); player.realize(); VideoControl videoControl = (VideoControl) player.getControl("VideoControl"); Field videoField = (Field)videoControl.initDisplayMode( VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field" );
7.
Invoke add() to add the returned Field object to your Screen or Manager, as you would add any other component to your UI.
try { Player player = javax.microedition.media.Manager .createPlayer("file:///SDCard/BlackBerry/videos/soccer1.avi"); player.realize(); VideoControl videoControl = (VideoControl) player.getControl("VideoControl"); Field videoField = (Field)videoControl.initDisplayMode( VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field" );
8.
To set the volume of playback, invoke Player.getControl() passing in the string, VolumeControl, to retrieve the VolumeControl object that is associated with Player. Invoke VolumeControl.setLevel() to specify the volume of playback.
try { Player player = javax.microedition.media.Manager .createPlayer("file:///SDCard/BlackBerry/videos/soccer1.avi"); player.realize(); VideoControl videoControl = (VideoControl) player.getControl("VideoControl");
19
Development Guide
Playing video
Field videoField = (Field)videoControl.initDisplayMode( VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field" ); add(videoField); VolumeControl volume = (VolumeControl) player.getControl("VolumeControl"); volume.setLevel(30);
9.
20
Development Guide
import java.io.*; public class VideoPlaybackDemo extends UiApplication { public static void main(String[] args) { VideoPlaybackDemo app = new VideoPlaybackDemo(); app.enterEventDispatcher(); } public VideoPlaybackDemo() { pushScreen(new VideoPlaybackDemoScreen()); } private class VideoPlaybackDemoScreen extends MainScreen { public VideoPlaybackDemoScreen() { try { Player player = javax.microedition.media.Manager.createPlayer("file:/// SDCard/BlackBerry/videos/soccer1.avi"); player.realize(); VideoControl videoControl = (VideoControl) player.getControl ("VideoControl"); Field videoField = (Field)videoControl.initDisplayMode ( VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field" ); add(videoField); VolumeControl volume = (VolumeControl) player.getControl ("VolumeControl"); volume.setLevel(30); player.start(); } catch(MediaException me) { Dialog.alert(me.toString()); } catch(IOException ioe) { Dialog.alert(ioe.toString()); }
21
Development Guide
Recording video
Recording video
You can record video in BlackBerry device application by using the Player class and the associated RecordControl interface. The recording is saved to a file in built-in storage, media card storage, or to a stream. To create a viewfinder to monitor what the camera is recording, you can use the VideoControl.initDisplay() method to retrieve a Field object that is added to your UI.
2.
Create the application framework by extending the UiApplication class. In main(), create an instance of the new class and invoke enterEventDispatcher() to enable the application to receive events. In the application constructor, invoke pushScreen() to display the custom screen for the application. The VideoRecordingDemoScreen class, which is described in step 3, represents the custom screen.
public class VideoRecordingDemo extends UiApplication { public static void main(String[] args) { VideoRecordingDemo app = new VideoRecordingDemo(); app.enterEventDispatcher(); } public VideoPlaybackDemo() { pushScreen(new VideoRecordingDemoScreen()); }
3.
Create the framework for the custom screen by extending the MainScreen class. Declare an instance of the VideoRecorderThread class, which is described in step 5.
class VideoRecordingDemoScreen extends MainScreen { private VideoRecorderThread _recorderThread; public VideoRecordingDemoScreen()
22
Development Guide
Recording video
{ }
4.
In the VideoRecordingDemoScreen constructor, invoke setTitle() to specify the title for the screen. Invoke addMenuItem() twice to add the menu items to start and stop the recording, which is described in step 5.
public VideoRecordingDemoScreen() { setTitle("Video recording demo"); addMenuItem(new StartRecording()); addMenuItem(new StopRecording()); }
5.
In the VideoRecordingDemoScreen class, define the menu items to start recording and to stop recording by invoking the start() and stop() methods of the VideoRecorderThread class respectively, which is described in step 6.
private class StartRecording extends MenuItem { public StartRecording() { super("Start recording", 0, 100); } public void run() { try { VideoRecorderThread newRecorderThread = new VideoRecorderThread(); newRecorderThread.start(); _recorderThread = newRecorderThread; } catch (Exception e) { Dialog.alert(e.toString()); } }
private class StopRecording extends MenuItem { public StopRecording() { super("Stop recording", 0, 100); } public void run() { try {
23
Development Guide
Recording video
6.
Inside the VideoRecordingDemo screen class, define an inner class that extends Thread and implements PlayerListener. In the class, create a variable of type Player, and a variable of type RecordControl for recording media from Player. Note: You are not required to record video in a separate thread because recording operations are threaded by design.
private class VideoRecorderThread extends Thread implements javax.microedition.media.PlayerListener { private Player _player; private RecordControl _recordControl; VideoRecorderThread() { } }
7.
In the VideoRecorderThread class, implement run(). In run() create a try/catch block and invoke Manager.createPlayer(String locator) to create a Player object to capture video, using as a parameter a value that specifies the encoding to use to record video. Only the encoding video/3gpp is currently supported.
public void run() { try { _player = javax.microedition.media.Manager .createPlayer("capture://video?encoding=video/3gpp"); } catch( IOException e ) { Dialog.alert(e.toString()); } catch( MediaException e ) { Dialog.alert(e.toString()); }
24
Development Guide
Recording video
8.
Invoke Player.addPlayerListener() specifying this as a parameter because VideoRecorderThread implements the PlayerListener interface.
public void run() { try { _player = javax.microedition.media.Manager .createPlayer("capture://video?encoding=video/3gpp"); _player.addPlayerListener(this); } catch( IOException e ) { Dialog.alert(e.toString()); } catch( MediaException e ) { Dialog.alert(e.toString()); }
9.
Invoke Player.realize() to access the Control object. Then , invoke Player.getControl() passing in the string, VideoControl, to retrieve the VideoControl object that is associated with Player.
public void run() { try { _player = javax.microedition.media.Manager .createPlayer("capture://video?encoding=video/3gpp"); _player.addPlayerListener(this); _player.realize(); VideoControl videoControl = (VideoControl) _player.getControl("VideoControl"); } catch( IOException e ) { Dialog.alert(e.toString()); } catch( MediaException e ) { Dialog.alert(e.toString()); }
10. Invoke Player.getControl(), passing in the string, RecordControl, to retrieve the RecordControl object.
25
Development Guide
Recording video
public void run() { try { _player = javax.microedition.media.Manager .createPlayer("capture://video?encoding=video/3gpp"); _player.addPlayerListener(this); _player.realize(); VideoControl videoControl = (VideoControl) _player.getControl("VideoControl"); _recordControl = (RecordControl) _player.getControl( "RecordControl" ); } catch( IOException e ) { Dialog.alert(e.toString()); } catch( MediaException e ) { Dialog.alert(e.toString()); }
11.
Invoke VideoControl.initDisplayMode(int mode, Object arg) passing an arg parameter specifying the UI primitive that displays the video to initialize the mode that a video field uses. Cast the returned object as a Field object. Note: You can invoke initDisplayMode() in different ways to return a Field, an Item for use with MIDlets, or to display a video on a Canvas class.
public void run() { try { _player = javax.microedition.media.Manager .createPlayer("capture://video?encoding=video/3gpp"); _player.addPlayerListener(this); _player.realize(); VideoControl videoControl = (VideoControl) _player.getControl("VideoControl"); _recordControl = (RecordControl) _player.getControl( "RecordControl" ); Field videoField = (Field) videoControl.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field"); } catch( IOException e ) {
26
Development Guide
Recording video
12. In a try/catch block, invoke VideoControl.setDisplaySize() to set the size of the viewfinder to monitor your recording. In the following code sample, the size is set to the full screen of the device. Invoke add() to add the viewfinder to the screen.
public void run() { try { _player = javax.microedition.media.Manager .createPlayer("capture://video?encoding=video/3gpp"); _player.addPlayerListener(this); _player.realize(); VideoControl videoControl = (VideoControl) _player.getControl("VideoControl"); _recordControl = (RecordControl) _player.getControl( "RecordControl" ); Field videoField = (Field) videoControl.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field"); try {
videoControl.setDisplaySize( Display.getWidth(), Display.getHeight() ); } catch( MediaException me ) { // setDisplaySize is not supported } add(videoField); } catch( IOException e ) { Dialog.alert(e.toString()); } catch( MediaException e ) { Dialog.alert(e.toString()); }
13. Invoke RecordControl.setRecordLocation() to specify the location on the device to save the video recording.
27
Development Guide
Recording video
public void run() { try { _player = javax.microedition.media.Manager .createPlayer("capture://video?encoding=video/3gpp"); _player.addPlayerListener(this); _player.realize(); VideoControl videoControl = (VideoControl) _player.getControl("VideoControl"); _recordControl = (RecordControl) _player.getControl( "RecordControl" ); Field videoField = (Field) videoControl.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field"); try {
videoControl.setDisplaySize( Display.getWidth(), Display.getHeight() ); } catch( MediaException me ) { // setDisplaySize is not supported } add(videoField); _recordControl.setRecordLocation("file:///store/home/user/ VideoRecordingTest .3gpp" ); } catch( IOException e ) { Dialog.alert(e.toString()); } catch( MediaException e ) { Dialog.alert(e.toString()); } }
14. Invoke RecordControl.startRecord() to start recording the video and start playing the media from Player. Invoke Player.start() to start Player.
public void run() { try { _player = javax.microedition.media.Manager .createPlayer("capture://video?encoding=video/3gpp");
28
Development Guide
Recording video
_player.addPlayerListener(this); _player.realize(); VideoControl videoControl = (VideoControl) _player.getControl("VideoControl"); _recordControl = (RecordControl) _player.getControl( "RecordControl" ); Field videoField = (Field) videoControl.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field"); try {
videoControl.setDisplaySize( Display.getWidth(), Display.getHeight() ); } catch( MediaException me ) { // setDisplaySize is not supported } add(videoField); _recordControl.setRecordLocation("file:///store/home/user/ VideoRecordingTest .3gpp" ); _recordControl.startRecord(); _player.start(); } catch( IOException e ) { Dialog.alert(e.toString()); } catch( MediaException e ) { Dialog.alert(e.toString()); }
15. In VideoRecorderThread, implement the Thread interface's stop() method. Check that Player is not null and invoke Player.close() to release the Player object's resources. Set the Player to null.
public void stop() { if (_player != null) { _player.close(); _player = null; } }
29
Development Guide
Recording video
16. Check that RecordControl is not null and invoke RecordControl.stopRecord() to stop recording. In a try/ catch block, invoke RecordControl.commit() to save the recording to a specified file. Set RecordControl to null.
public void stop() { if (_player != null) { _player.close(); _player = null; } if (_recordControl != null) { _recordControl.stopRecord(); try {
17. In VideoRecorderThread, implement the PlayerListener interface's playerUpdate() method which is invoked when the Player object generates an event. In the following code sample, information about the event is displayed.
public void playerUpdate(Player player, String event, Object eventData) { Dialog.alert("Player " + player.hashCode() + " got event " + event + ": " + eventData); }
30
Development Guide
Recording video
public static void main(String[] args) { VideoRecordingDemo app = new VideoRecordingDemo(); app.enterEventDispatcher(); } public VideoRecordingDemo() { pushScreen(new VideoRecordingDemoScreen()); } private class VideoRecordingDemoScreen extends MainScreen { private VideoRecorderThread _recorderThread; public VideoRecordingDemoScreen() { setTitle("Video recording demo"); addMenuItem(new StartRecording()); addMenuItem(new StopRecording());
private class StartRecording extends MenuItem { public StartRecording() { super("Start recording", 0, 100); } public void run() { try { VideoRecorderThread newRecorderThread = new VideoRecorderThread(); newRecorderThread.start(); _recorderThread = newRecorderThread; } catch (Exception e) { Dialog.alert(e.toString()); } } } private class StopRecording extends MenuItem { public StopRecording() { super("Stop recording", 0, 100); }
31
Development Guide
Recording video
public void run() { try { if (_recorderThread != null) { _recorderThread.stop(); } } catch (Exception e) { Dialog.alert(e.toString()); } }
private class VideoRecorderThread extends Thread implements javax.microedition.media.PlayerListener { private Player _player; private RecordControl _recordControl; VideoRecorderThread() { } public void run() { try { _player = javax.microedition.media.Manager .createPlayer("capture://video?encoding=video/3gpp"); _player.addPlayerListener(this); _player.realize(); VideoControl videoControl = (VideoControl) _player.getControl("VideoControl"); _recordControl = (RecordControl) _player.getControl( "RecordControl" ); Field videoField = (Field) videoControl.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field"); try {
32
Development Guide
Recording video
{ }
add(videoField); _recordControl .setRecordLocation("file:///store/home/user/VideoRecordingTest.3gpp" ); _recordControl.startRecord(); _player.start(); } catch( IOException e ) { Dialog.alert(e.toString()); } catch( MediaException e ) { Dialog.alert(e.toString()); }
public void playerUpdate(Player player, String event, Object eventData) { Dialog.alert("Player " + player.hashCode() + " got event " + event + ": " + eventData); }
33
Development Guide
descriptor values
Frames Field stream type key frame config frame Value 0 if this is a frame of audio 1 if this is a frame of video 1 if this is a key frame 0 otherwise 1 if this is a config frame 0 otherwise Size 1B 1b 1b
34
Development Guide
Field size duration data stream type key frame config frame size duration
Value frame size, in bytes length of video, in milliseconds the actual frame data 0 if this is a frame of audio 1 if this is a frame of video 1 if this is a key frame 0 otherwise 1 if this is a config frame 0 otherwise
Size 30 b 2B <size> B 1B 1b 1b 30 b 2B
Note: The key frame, config frame, and size fields are stored in one 32-bit int with the key frame and config frame fields stored in the first two bits. Footer Field Descriptor Value descriptor values Size 75 bytes if recording to a stream 0 bytes if recording to a file
Descriptor Field audio frames video frames audio key frames video key frames audio frame rates video frame rates audio size video size Value number of audio frames number of video frames number of audio key frames number of video key frames number of audio frame rates (number of frame rate changes + 1) number of video frame rates (number of frame rate changes + 1) size of audio stream in bytes size of video stream in bytes Size 4B 4B 4B 4B 4B 4B 4B 4B
35
Development Guide
Field video frame rate video max frame size audio duration video duration RESERVED width height video codec
Value the initial video frame rate, in frames per second size of largest video frame, in bytes length of audio stream, in milliseconds length of video stream, in milliseconds undefined the width of the video, in pixels the height of the video, in pixels 2 if this video codec is mpeg4 5 if this video codec is H.263 6 if this video codec is H.264 0 if this audio codec is PCM 7 if this audio codec is AMR 0xA if this audio codec is AAC
Size 4B 4B 4B 4B 20 B 2B 2B 2B
audio codec
1B
/** * */ public class KeyFrameOutputStream extends OutputStream { // output locations on the sd card private static final String OUT_DIR = "file:///SDCard/securitycam/"; private static final String OUT_FILE = "output.frames"; // some size constants private static final int HEADER_SIZE = 8; private static final int CHUNK_INFO_SIZE = 7; // parsing states private static final private static final private static final private static final // member variables private int _state; int int int int STATE_HEADER STATE_CHUNK_INFO STATE_DATA STATE_WAIT_FOR_NEXT = = = = 0; 1; 2; 3;
36
Development Guide
int _pos; boolean _isVideoFrame; boolean _isKeyFrame; boolean _isConfigFrame; boolean _startSaving; boolean _saveFrame; int _dataSize; int _duration;
// temp buffer ref private byte[] _buf; private FileConnection _file; private OutputStream _out; private WriteThread _writer; private boolean _reading; public KeyFrameOutputStream() { _state = STATE_HEADER; _pos = 0; } public void open() { _reading = true; try { // create the file connection for our frame destination FileConnection dir = (FileConnection)Connector.open( OUT_DIR ); if( !dir.exists() ) { dir.mkdir(); } dir.close(); _file = (FileConnection)Connector.open( OUT_DIR + OUT_FILE ); if( !_file.exists() ) { _file.create(); } else { _file.truncate( 0L ); } _out = _file.openOutputStream(); } catch ( Exception e ) { } // start the write thread _writer = new WriteThread( _out ); _writer.start();
public void startClosing() { // shuts down the write thread _reading = false; if( _writer != null ) _writer.stop();
37
Development Guide
} public void write( int b ) throws IOException { if( _reading ) { switch( _state ) { case STATE_HEADER: // read the video stream header _pos++; if( _pos == HEADER_SIZE ) { _state = STATE_CHUNK_INFO; _buf = new byte[CHUNK_INFO_SIZE]; _pos = 0; } break; case STATE_CHUNK_INFO: // parse the information about the next chunk _buf[_pos] = (byte)b; _pos++; if( _pos == CHUNK_INFO_SIZE ) { // 1 indicates video frame, 0 indicates audio _isVideoFrame = (_buf[0] != 0); // // key frame and config frame flags are in the top two bits of the data size value _isKeyFrame = ((_buf[4] & 0x80) != 0); _isConfigFrame = ((_buf[4] & 0x40) != 0); _dataSize = ((int)(_buf[4] & 0x3f) << 24) | ((int)(_buf[3] & 0xff) << 16) | ((int)(_buf[2] & 0xff) << 8) | ((int)(_buf[1] & 0xff)); // duration is stored in the next two bytes _duration = ((int)(_buf[6] & 0xff) << 8) | ((int)(_buf[5] & 0xff)); // output file // we want the config frame to be the first frame in our if( !_startSaving ) { if( _isVideoFrame && _isConfigFrame ) { _startSaving = true; } }
// after that only save the key frames _saveFrame = _startSaving && _isVideoFrame && ( _isConfigFrame || _isKeyFrame ); _state = STATE_DATA; if( _saveFrame ) { _buf = new byte[_dataSize]; } _pos = 0;
38
Development Guide
} break; case STATE_DATA: // buffer the frame for writing to file if( _saveFrame ) _buf[_pos] = (byte)b; _pos++; if( _pos == _dataSize ) { if( _saveFrame ) { _writer.addFrame( _buf ); } _state = STATE_WAIT_FOR_NEXT; _buf = new byte[CHUNK_INFO_SIZE]; _pos = 0; } break; case STATE_WAIT_FOR_NEXT: // skip over the chunk footer _pos++; if( _pos == CHUNK_INFO_SIZE ) { _state = STATE_CHUNK_INFO; _buf = new byte[CHUNK_INFO_SIZE]; _pos = 0; } break;
public void close() throws IOException { // shut down the write thread and close our file try { _writer.join(); } catch ( InterruptedException ie ) { } _out.close(); _file.close(); } private static final class WriteThread extends Thread { // writes key frames to a file as they are found by our parser private Vector _frames; private boolean _running; private OutputStream _out; public WriteThread( OutputStream out ) { _frames = new Vector(); _running = true; _out = out; } public void run() { for( ;; ) {
39
Development Guide
ByteArray frame = null; synchronized( this ) { if( _frames.size() > 0 ) { frame = (ByteArray)_frames.elementAt( 0 ); if( frame == null ) break; _frames.removeElementAt( 0 ); } else { if( !_running ) break; try { wait(); if( _running ) continue; } catch ( InterruptedException ie ) { } } } if( frame == null ) break; try { byte[] bytes = frame.array; _out.write( bytes, 0, bytes.length ); _out.flush(); } catch ( Exception e ) { }
public synchronized void addFrame( byte[] frame ) { _frames.addElement( new ByteArray( frame ) ); notifyAll(); } public synchronized void stop() { _running = false; notifyAll(); }
private static final class ByteArray { public byte[] array; public ByteArray( byte[] array ) { this.array = array; } }
40
Development Guide
You can take a picture on a BlackBerry device by using the javax.microedition.media.Player class and the associated VideoControl interface in your BlackBerry device application. When you create an instance of the Player class, you can specify the appropriate file encoding and resolution of the picture. You can invoke VideoControl.getSnapshot() to take the picture. The image is returned as a byte array (the unprocessed image), which you can display on the device, save to a file, or process as required. To create a viewfinder to monitor the picture the camera is taking, you can invoke VideoControl.initDisplay() to retrieve a Field object that is added to your UI.
2.
Create the application framework by extending the UiApplication class. In main(), create an instance of the new class and invoke enterEventDispatcher() to enable the application to receive events. In the application constructor, invoke pushScreen() to display the custom screen for the application. The ImageCaptureDemoScreen class, which is described in step 3, represents the custom screen.
public class ImageCaptureDemo extends UiApplication { public static void main(String[] args) { ImageCaptureDemo app = new ImageCaptureDemo(); app.enterEventDispatcher(); } public ImageCaptureDemo() { pushScreen(new ImageCaptureDemoScreen()); }
41
Development Guide
Taking pictures
3.
Create the framework for the custom screen by extending the MainScreen class. Declare class variables for the Player and VideoControl classes that you create in the screen's constructor, which is described in step 4.
class ImageCaptureDemoScreen extends MainScreen { Player _p; VideoControl _videoControl; public ImageCaptureDemoScreen() { }
4.
In the screen constructor, initialize the camera. In a try/catch block, create an instance of the Player class by invoking Manager.createPlayer(String), passing in the encoding parameter. The jpeg and image/jpeg parameters are supported. If you do not specify the encoding parameter, by default the encoding parameter is image/jpeg.
try { _p = javax.microedition.media.Manager .createPlayer("capture://video?encoding=jpeg&width=1024&height=768");
} catch(Exception e) { Dialog.alert(e.toString()); }
5.
To control an aspect of taking the picture, retrieve the appropriate Control object. Invoke the Player object's realize () method to access the associated Control object. Next, invoke Player.getControl() to retrieve the Player object's VideoControl.
try { _p = javax.microedition.media.Manager .createPlayer("capture://video?encoding=jpeg&width=1024&height=768"); _p.realize(); _videoControl = (VideoControl) _p.getControl("VideoControl");
} catch(Exception e) { Dialog.alert(e.toString()); }
6.
Create a viewfinder in your application by invoking VideoControl.initDisplayMode(int mode, Object arg) and passing in a parameter specifying the UI primitive that displays the picture to initialize the mode that a video field uses. Cast the returned object as a Field object. Invoke VideoControl.setDisplayFullScreen() passing in true to set the viewfinder to take up the full screen of the device. Invoke VideoControl.setVisible() passing in true to display the viewfinder.
42
Development Guide
Taking pictures
try {
_p = javax.microedition.media.Manager .createPlayer("capture://video?encoding=jpeg&width=1024&height=768"); _p.realize(); _videoControl = (VideoControl) _p.getControl("VideoControl"); if (videoControl != null) { Field videoField = (Field) _videoControl.initDisplayMode (VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field"); _videoControl.setDisplayFullScreen(true); _videoControl.setVisible(true); }
} catch(Exception e) { Dialog.alert(e.toString()); }
7.
} catch(Exception e) { Dialog.alert(e.toString()); }
8.
To enable autofocus for the camera, invoke Player.getContol() to retrieve the Player object's EnhancedFocusControl interface. Iinvoke EnhancedFocusControl.startAutoFocus().
try { _p = javax.microedition.media.Manager
43
Development Guide
Taking pictures
.createPlayer("capture://video?encoding=jpeg&width=1024&height=768"); _p.realize(); _videoControl = (VideoControl) _p.getControl("VideoControl"); if (videoControl != null) { Field videoField = (Field) _videoControl.initDisplayMode (VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field"); _videoControl.setDisplayFullScreen(true); _videoControl.setVisible(true); _p.start(); EnhancedFocusControl efc = (EnhancedFocusControl)p.getControl("net.rim.device.api.amms.control.camera .EnhancedFocusControl"); efc.startAutoFocus(); }
} catch(Exception e) { Dialog.alert(e.toString()); }
9.
Check that videoField is not null and invoke add() to add the viewfinder to the screen.
try { _p = javax.microedition.media.Manager .createPlayer("capture://video?encoding=jpeg&width=1024&height=768"); _p.realize(); _videoControl = (VideoControl) _p.getControl("VideoControl"); if (videoControl != null) { Field videoField = (Field) _videoControl.initDisplayMode (VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field"); _videoControl.setDisplayFullScreen(true); _videoControl.setVisible(true); _p.start(); EnhancedFocusControl efc = (EnhancedFocusControl)p.getControl("net.rim.device.api.amms.control.camera .EnhancedFocusControl"); efc.startAutoFocus(); if(videoField != null) { add(videoField); }
44
Development Guide
Taking pictures
} catch(Exception e) { Dialog.alert(e.toString()); }
10. In ImageCaptureDemoScreen, invoke net.rim.device.api.ui.Screen.invokeAction(). This implementation takes the picture when the user clicks the trackpad, trackball, or touch screen. Return a boolean specifying if the action is consumed.
protected boolean invokeAction(int action) { boolean handled = super.invokeAction(action); if(!handled) { if(action == ACTION_INVOKE) { } } }
return handled;
11.
In the if(action == ACTION_INVOKE) statement, in a try/catch block, invoke VideoControl.getSnapshot () to take the picture, passing in null to use the encoding setting that you specified in step 4. The image is returned as a byte array.
protected boolean invokeAction(int action) { boolean handled = super.invokeAction(action); if(!handled) { if(action == ACTION_INVOKE) { try { byte[] rawImage = _videoControl.getSnapshot(null); } catch(Exception e) { Dialog.alert(e.toString()); } } } return handled;
45
Development Guide
Taking pictures
public class ImageCaptureDemo extends UiApplication { public static void main(String[] args) { ImageCaptureDemo app = new ImageCaptureDemo(); app.enterEventDispatcher(); } public ImageCaptureDemo() { pushScreen(new ImageCaptureDemoScreen()); } class ImageCaptureDemoScreen extends MainScreen { Player _p; VideoControl _videoControl; public ImageCaptureDemoScreen() { try { _p = javax.microedition.media.Manager .createPlayer("capture://video?encoding=jpeg&width=1024&height=768"); _p.realize(); _videoControl = (VideoControl) _p.getControl("VideoControl"); if (videoControl != null) { Field videoField = (Field) _videoControl.initDisplayMode (VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field"); _videoControl.setDisplayFullScreen(true); _videoControl.setVisible(true); _p.start(); EnhancedFocusControl efc = (EnhancedFocusControl)p.getControl("net.rim.device.api.amms.control.camera .EnhancedFocusControl"); efc.startAutoFocus(); if(videoField != null)
46
Development Guide
Taking pictures
{ }
add(videoField);
} } catch(Exception e) { Dialog.alert(e.toString()); }
protected boolean invokeAction(int action) { boolean handled = super.invokeAction(action); if(!handled) { if(action == ACTION_INVOKE) { try { byte[] rawImage = _videoControl.getSnapshot(null); } catch(Exception e); { Dialog.alert(e.toString()); } } } return handled;
47
Development Guide
www.blackberry.com/go/apiref: View the latest version of the API reference for the BlackBerry Java SDK. www.blackberry.com/go/devguides: Find development guides, release notes, and sample application overviews for the BlackBerry Java SDK. www.blackberry.com/developers: Visit the BlackBerry Developer Zone for resources on developing BlackBerry device applications. www.blackberry.com/go/developerkb: View knowledge base articles on the BlackBerry Development Knowledge Base. www.blackberry.com/developers/downloads: Find the latest development tools and downloads for developing BlackBerry device applications.
48
Development Guide
Provide feedback
Provide feedback
To provide feedback on this deliverable, visit www.blackberry.com/docsfeedback.
49
Development Guide
Moved the following topics to the BlackBerry Java SDK UI and Navigation Development Guide: Access an encoded image through an input stream Code sample: Displaying a row of images for scrolling Code sample: Displaying an image for zooming and panning Display a row of images for scrolling Display an encoded image Display an image for zooming and panning Displaying a row of images for scrolling Displaying an image for zooming and panning Encode an image Specify the decoding mode for an image Specify the display size of an encoded image Using encoded images
50
Development Guide
Legal notice
Legal notice
2010 Research In Motion Limited. All rights reserved. BlackBerry, RIM, Research In Motion, and related trademarks, names, and logos are the property of Research In Motion Limited and are registered and/or used in the U.S. and countries around the world. Bluetooth is a trademark of Bluetooth SIG. Java and Javadoc are trademarks of Oracle America, Inc. Plazmic is a trademark of Plazmic Inc. All other trademarks are the property of their respective owners. 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, NONINFRINGEMENT, 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 NONPERFORMANCE 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
51
Development Guide
Legal notice
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. Some airtime service providers might not offer Internet browsing functionality with a subscription to the BlackBerry Internet Service. Check with your service provider for availability, roaming arrangements, service plans and 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. Certain features outlined in this documentation require a minimum version of BlackBerry Enterprise Server, BlackBerry Desktop Software, and/or BlackBerry Device Software. 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.
52
Development Guide
Legal notice
Waterloo, ON N2L 3W8 Canada Research In Motion UK Limited Centrum House 36 Station Road Egham, Surrey TW20 9LF United Kingdom Published in Canada
53