/* * SendMediaDemo.java * * Copyright � 1998-2011 Research In Motion Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Note: For the sake of simplicity, this sample application may not leverage * resource bundles and resource strings. However, it is STRONGLY recommended * that application developers make use of the localization features available * within the BlackBerry development platform to ensure a seamless application * experience across a variety of languages and geographies. For more information * on localizing your application, please refer to the BlackBerry Java Development * Environment Development Guide associated with this release. */ package com.rim.samples.device.sendmediademo; import java.io.IOException; import java.io.InputStream; import javax.microedition.content.ActionNameMap; import javax.microedition.content.ContentHandler; import javax.microedition.content.ContentHandlerException; import javax.microedition.content.ContentHandlerServer; import javax.microedition.content.Invocation; import javax.microedition.content.Registry; import javax.microedition.content.RequestListener; import javax.microedition.io.Connector; import javax.microedition.io.file.FileConnection; import javax.microedition.media.MediaException; import javax.microedition.media.Player; import javax.microedition.media.PlayerListener; import javax.microedition.media.control.GUIControl; import javax.microedition.media.control.VideoControl; import javax.microedition.media.control.VolumeControl; import net.rim.device.api.media.MediaActionHandler; import net.rim.device.api.media.control.StreamingBufferControl; import net.rim.device.api.system.Bitmap; import net.rim.device.api.system.Display; import net.rim.device.api.ui.Field; import net.rim.device.api.ui.Screen; import net.rim.device.api.ui.UiApplication; import net.rim.device.api.ui.component.BitmapField; import net.rim.device.api.ui.component.Dialog; import net.rim.device.api.ui.component.LabelField; import net.rim.device.api.ui.container.MainScreen; /** * This sample shows how registering an application as a content handler for * various mime types results in menu items and/or dialog buttons being * available within various screens to invoke the application as a handler for * send actions. * * In the case of image types, this application creates an input stream using * the URL associated with the Invocation object obtained from the * ContentHandlerServer and reads the image data which it then uses to display * the image on the BlackBerry screen. Similarly, when encountering a video mime * type, the application creates a video player to render the file pointed to by * the URL. In the case of audio types, the application prompts the user to play * the specified file. If the user chooses to play the file, the application * plays the audio in the background and responds to media key presses. */ public final class SendMediaDemo extends UiApplication implements RequestListener, PlayerListener, MediaActionHandler { private static final String ID = "com.rim.samples.device.sendmediademo"; private static final String CLASSNAME = "com.rim.samples.device.sendmediademo.SendMediaDemo"; private Player _videoPlayer; private Player _audioPlayer; private VolumeControl _audioVolumeControl; private Field _videoField; private VideoControl _vc; /** * Entry point for application * * @param args * Command line arguments */ public static void main(final String[] args) { if (args != null && args.length > 0) { if (args[0].equals("startup")) { // Register this application as a content handler on startup register(); } } else { // Create a new instance of the application and make the currently // running thread the application's event dispatch thread. final SendMediaDemo app = new SendMediaDemo(); app.enterEventDispatcher(); } } /** * Registers this application as a content handler for image, video, and * audio files */ private static void register() { final String[] types = { "image/bmp", "image/png", "image/jpeg", "video/3gpp", "video/mp4", "audio/mp4", "audio/amr", "audio/mpeg" }; final String[] suffixes = { "bmp", "png", "jpg", "3GP", "mp4", "m4A", "amr", "mp3" }; final String[] actions = { ContentHandler.ACTION_SEND }; final String[] actionNames = { "Send to demo app" }; final ActionNameMap[] actionNameMaps = { new ActionNameMap(actions, actionNames, "en") }; // Get access to the registry final Registry registry = Registry.getRegistry(CLASSNAME); try { // Register as a content handler registry.register(CLASSNAME, types, suffixes, actions, actionNameMaps, ID, null); } catch (final ContentHandlerException che) { System.out.println("Registry#register() threw " + che.toString()); } catch (final ClassNotFoundException cnfe) { System.out.println("Registry#register() threw " + cnfe.toString()); } } /** * Creates a new SendMediaDemo object */ public SendMediaDemo() { try { // Get access to the ContentHandlerServer for this application and // register as a listener. final ContentHandlerServer contentHandlerServer = Registry.getServer(CLASSNAME); contentHandlerServer.setListener(this); } catch (final ContentHandlerException che) { errorDialog("Registry.getServer(String) threw " + che.toString()); } } /** * RequestListener implementation * * @param server * The content handler server from which to request Invocation * objects * * @see javax.microedition.content.RequestListener#invocationRequestNotify(ContentHandlerServer) */ public void invocationRequestNotify(final ContentHandlerServer server) { final Invocation invoc = server.getRequest(false); if (invoc != null) { if (getActiveScreen() == null) { final String type = invoc.getType(); final DemoMainScreen screen = new DemoMainScreen(); screen.setTitle("Send Media Demo"); if (type.equals("audio/mp4") || type.equals("audio/amr") || type.equals("audio/mpeg")) { screen.setType(DemoMainScreen.AUDIO_TYPE); // Play an audio file if (_audioPlayer == null) { final String url = invoc.getURL(); screen.add(new LabelField("Playing audio file: " + url)); initAudio(url); } } if (type.equals("image/bmp") || type.equals("image/png") || type.equals("image/jpeg")) { screen.setType(DemoMainScreen.IMAGE_TYPE); // Get data from URL final byte[] data = getData(invoc.getURL()); // Create image field final Bitmap image = Bitmap.createBitmapFromBytes(data, 0, -1, 5); final BitmapField imageField = new BitmapField(image, Field.FIELD_HCENTER); screen.add(imageField); } else if (type.equals("video/3gpp") || type.equals("video/mp4")) { screen.setType(DemoMainScreen.VIDEO_TYPE); // Play a video initVideo(invoc.getURL()); if (_videoField != null) { screen.add(_videoField); try { // Start video player _videoPlayer.start(); } catch (final MediaException pe) { errorDialog("Player#start() threw " + pe.toString()); } } } pushScreen(screen); } server.finish(invoc, Invocation.OK); } } /** * PlayerListener implementation * * @see javax.microedition.media.PlayerListener#playerUpdate(Player,String,Object) */ public void playerUpdate(final Player player, final String event, final Object eventData) { if (event.equals(PlayerListener.END_OF_MEDIA)) { if (player == _audioPlayer) { // We've finished playing the audio file, close the player and // update screen _audioPlayer.close(); } final Screen screen = getActiveScreen(); if (screen instanceof MainScreen) { final Field field = screen.getField(0); if (field instanceof LabelField) { final LabelField labelField = (LabelField) field; invokeLater(new Runnable() { public void run() { labelField.setText("End of media reached."); } }); } } } } /** * Creates and initializes an audio player * * @param url * The URL of the audio file to play */ private void initAudio(final String url) { // Register this class as a MediaActionHandler so we can respond // to media key presses. addMediaActionHandler(this); final Thread thread = new Thread(new Runnable() { public void run() { try { // Create and start an audio player _audioPlayer = javax.microedition.media.Manager.createPlayer(url); _audioPlayer.addPlayerListener(SendMediaDemo.this); _audioPlayer.realize(); // Cause playback to begin as soon as possible once start() // is called on the Player. final StreamingBufferControl sbc = (StreamingBufferControl) _audioPlayer .getControl("net.rim.device.api.media.control.StreamingBufferControl"); sbc.setBufferTime(0); _audioPlayer.start(); // Create a volume control _audioVolumeControl = (VolumeControl) _audioPlayer .getControl("VolumeControl"); } catch (final MediaException me) { errorDialog(me.toString()); } catch (final IOException ioe) { errorDialog("Manager.createPlayer(String) threw" + ioe.toString()); } } }); thread.start(); } /** * MediaActionHandler implementation * * @see net.rim.device.api.media.MediaActionHandler#mediaAction(int, int, * Object) */ public boolean mediaAction(final int action, final int source, final Object context) { if (_audioVolumeControl != null) { final int volumeLevel = _audioVolumeControl.getLevel(); // Respond to media key presses. Here we will allow the user to // adjust the volume or mute the audio entirely. switch (action) { case MediaActionHandler.MEDIA_ACTION_VOLUME_UP: _audioVolumeControl.setLevel(volumeLevel + 10); break; case MediaActionHandler.MEDIA_ACTION_VOLUME_DOWN: _audioVolumeControl.setLevel(volumeLevel - 10); break; case MediaActionHandler.MEDIA_ACTION_PLAYPAUSE_TOGGLE: if (_audioVolumeControl.isMuted()) { _audioVolumeControl.setMute(false); } else { _audioVolumeControl.setMute(true); } break; } } return true; } /** * Creates and initializes a video player * * @param url * The URL of the video file to play */ private void initVideo(final String url) { try { // Create a video player _videoPlayer = javax.microedition.media.Manager.createPlayer(url); _videoPlayer.realize(); // Cause playback to begin as soon as possible once start() // is called on the Player. final StreamingBufferControl sbc = (StreamingBufferControl) _videoPlayer .getControl("net.rim.device.api.media.control.StreamingBufferControl"); sbc.setBufferTime(0); _vc = (VideoControl) _videoPlayer.getControl("VideoControl"); if (_vc != null) { _videoField = (Field) _vc.initDisplayMode( GUIControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field"); _vc.setVisible(true); } } catch (final MediaException me) { errorDialog(me.toString()); } catch (final IOException ioe) { errorDialog("Manager#createPlayer(String) threw " + ioe.toString()); } } /** * Sets the size of the video * * @param width * Width of the video display * @param height * Height of the video display */ private void setVideoSize(final int width, final int height) { try { if (_vc != null) { _vc.setDisplaySize(width, height); } } catch (final MediaException pe) { errorDialog("VideoControl#setDisplaySize(int, int) threw " + pe.toString()); } } /** * Returns a byte array containing data representing the image at the * specified URL * * @param url * The location of the image to display * @return The image data */ private byte[] getData(final String url) { byte[] data = new byte[0]; try { final FileConnection file = (FileConnection) Connector.open(url); final int fileSize = (int) file.fileSize(); data = new byte[fileSize]; final InputStream inputStream = file.openInputStream(); inputStream.read(data); } catch (final Exception e) { errorDialog(e.toString()); } return data; } /** * Presents a dialog to the user with a given message * * @param message * The text to display */ public static void errorDialog(final String message) { UiApplication.getUiApplication().invokeLater(new Runnable() { public void run() { Dialog.alert(message); } }); } /** * A MainScreen subclass for displaying either an image, a video, or a * status field to indicate an audio file is being played. */ final private class DemoMainScreen extends MainScreen { public final static int AUDIO_TYPE = 0; public final static int VIDEO_TYPE = 1; public final static int IMAGE_TYPE = 2; private int _mediaType = -1; /** * Creates a new DemoMainScreen object */ DemoMainScreen() { super(net.rim.device.api.ui.Manager.NO_VERTICAL_SCROLL); } /** * Sets the media type for this screen * * @param mediaType * The media type of which to associate this screen */ public void setType(final int mediaType) { _mediaType = mediaType; } /** * @see net.rim.device.api.ui.Manager#sublayout(int,int) */ protected void sublayout(final int width, final int height) { if (_mediaType == VIDEO_TYPE) { setVideoSize(Display.getWidth(), Display.getHeight()); } super.sublayout(width, height); } /** * @see net.rim.device.api.ui.Screen#onClose() */ public boolean onClose() { try { // Deregister this application as a listener final ContentHandlerServer contentHandlerServer = Registry.getServer(CLASSNAME); contentHandlerServer.setListener(null); } catch (final ContentHandlerException che) { errorDialog(che.toString()); } if (_videoPlayer != null) { _videoPlayer.close(); } if (_audioPlayer != null) { _audioPlayer.close(); } return super.onClose(); } } }