Programming Java 2 Micro Edition for Symbian OS 2004 (779882), страница 35
Текст из файла (страница 35)
A STARTED eventis broadcast in response to the Player starting. The PlayerView ismade the current view, the ‘‘Back’’ Command is added to it and the statusof PlayerView is set appropriately.An END_OF_MEDIA event is generated when the Player reachesthe end of the audio file. The ‘‘Re-play’’ Command is added to thePlayerView and the status set accordingly.A VOLUME_CHANGED event is posted when the volume is changedusing the VolumeControl. The eventData object is cast to a VolumeControl and used to get the current volume setting.
The volumeindicator Gauge owned by the PlayerView is adjusted accordingly,ensuring it correctly reflects the volume level of the VolumeControl.The ItemStateChanged() method (listed below) is mandated by theItemStateListener and listens for requests by the user to change thevolume level via the interactive volume indicator Gauge of PlayerView.172MIDP 2.0 AND THE JTWIpublic void itemStateChanged(Item item){if (item instanceof Gauge){Gauge volumeIndicator = (Gauge)item;int level = volumeIndicator.getValue();audioPlayer.setVolume(level);}}The itemStateChanged() method obtains the value requested bythe user and invokes the setVolume() method to adjust the audioplayback volume via the Player’s VolumeControl.The showAlert() method (see below) is called by the AudioPlayerinstance in the event of an Exception being thrown at any stage of thePlayer lifecycle.public void showAlert(String title, String message){Alert alert = new Alert(title, message, null, AlertType.ERROR);display.setCurrent(alert, initialView);initialView.removeProgressGauge();initialView.addCommand(playCommand);}After displaying an error Alert, the current Displayable is set tothe InitialView allowing the user to try either the same URL again ora different URL.The MIDletController class also provides a couple of callbackmethods: updateProgressGauge and removeVolumeControl.
Thefirst updates the InitialView progress gauge as the Player progressesthrough its lifecycle. The second removes the interactive volume indicatorGauge from the PlayerView in the event that the implementation ofPlayer does not support a VolumeControl.The full source code and JAR and JAD files for the Audio PlayerMIDlet can be downloaded from the Symbian website at www.symbian.com/books.3.4.1.5 Working with VideoWe shall now illustrate how to play a video with code highlights takenfrom a simple Video Player MIDlet (see Figure 3.26).The architecture of the Video Player MIDlet (see Figure 3.27) is verysimilar to that of the Audio Player.The MIDlet contains four classes: MIDletController,InitialView, VideoPlayer and VideoCanvas.
The VideoCanvas is used for rendering the video playback as well as providingcontrols similar to those found in the PlayerView of the Audio PlayerMIDlet. The other classes fulfill very similar roles to their equivalents inthe Audio Player MIDlet.OPTIONAL J2ME APIS IN THE JTWIFigure 3.26The Video Player MIDlet running on a Nokia Series 60 phone.javax.microedition.lcdui.Formjavax.microedition.lcdui.CanvasInitialViewVideoCanvasMIDletControllerVideoPlayerjavax.microedition.media.control.VideoControljavax.microedition.media.PlayerFigure 3.27 UML class diagram of the Video Player MIDlet.The VideoPlayer ClassLet’s first take a look at the key methods of the VideoPlayer class:import javax.microedition.media.*;import javax.microedition.media.control.*;import java.io.*;// Acquires the video content and renders itpublic class VideoPlayer implements Runnable {private final static String THREE_GPP = "3gp";private final static String MPEG = "mpg";173174MIDP 2.0 AND THE JTWIprivate final static String MIME_3GPP = "video/3gpp";private final static String MIME_MPEG = "video/mpeg";privateprivateprivateprivateprivateprivateprivateMIDletController controller;VideoCanvas canvas;Player player;VideoControl videoControl;String resource;String mimeType = THREE_GPP;Thread initializer;public VideoPlayer(MIDletController controller,VideoCanvas canvas){...}public void initializeVideo(String resource){...}public void run(){...}public void startPlayer(){...}public void stopPlayer(){...}public void closePlayer(){...}}The constructor is shown below.public VideoPlayer(MIDletController controller, VideoCanvas canvas){this.controller = controller;this.canvas = canvas;}It simply initializes the controller and canvas attributes with references to the MIDletController and the VideoCanvas respectively.One difference between the Video Player and Audio Player MIDletsis that the Video Player obtains its content from resource files packagedin the MIDlet suite JAR file, rather than from a remote resource.
TheinitializeVideo() method takes the name of the video file asa parameter.public void initializeVideo(String resource){this.resource = resource;String fileExt =resource.substring(resource.lastIndexOf('.') + 1);if(fileExt.equals(THREE_GPP)) {mimeType = MIME_3GPP;}else if(fileExt.equals(MPEG)) {mimeType = MIME_MPEG;}initializer = new Thread(this);initializer.start();}OPTIONAL J2ME APIS IN THE JTWI175The resource file name is tested to ascertain its format (MPEG for theSun’s J2ME Wireless Toolkit 2.0 emulator and 3GPP for real phones) andthe appropriate MIME type set. A new thread is then launched to performthe essential initialization required to play the video content.The run() method, mandated by the Runnable interface, containsthe initialization of the Player.public void run(){try {InputStream in = getClass().getResourceAsStream("/"+ resource);player = Manager.createPlayer(in, mimeType);player.addPlayerListener(controller);player.realize();player.prefetch();videoControl =(VideoControl)player.getControl("VideoControl");if (videoControl != null) {videoControl.initDisplayMode(videoControl.USE_DIRECT_VIDEO, canvas);int cHeight = canvas.getHeight();int cWidth = canvas.getWidth();videoControl.setDisplaySize(cWidth, cHeight);videoControl.setVisible(true);startPlayer();}else{controller.showAlert("Error!","Unable to get Video Control");closePlayer();}} catch (IOException ioe) {controller.showAlert("Unable to access resource",ioe.getMessage());closePlayer();} catch (MediaException me) {controller.showAlert("Unable to create player",me.getMessage());closePlayer();}}An InputStream is obtained from the resource file and used tocreate the Player instance.
A PlayerListener (the controller) isregistered with the Player in order to receive callbacks. The prefetchand realize() methods are then called on the Player instance.Once the player is in the PREFETCHED state we are ready to renderthe video content. First we must obtain a VideoControl by callinggetControl on the Player, and casting it down appropriately.
Notethat the MMAPI specification requires that a player for video mediamust support a VideoControl, unlike the case of a player for audiocontent, where support for VolumeControl is only a recommendedpractice.176MIDP 2.0 AND THE JTWIThe initDisplayMode() method is used to initialize the videomode that determines how the video is displayed. This method takesan integer mode value as its first argument with one of two predefinedvalues: USE_GUI_PRIMITIVE or USE_DIRECT_VIDEO. In the case ofMIDP implementations (supporting the LCDUI), USE_GUI_PRIMITIVEwill result in an instance of a javax.microedition.lcdui.Itembeing returned:Item display = control.initDisplayMode(control.USE_GUI_PRIMITIVE, null);For CDC implementations supporting AWT, USE_GUI_PRIMITIVEwill return an instance of java.awt.Component.
For implementationsthat support both LCDUI and AWT, the required type must be specifiedby a String as the second argument:Item display = control.initDisplayMode(control.USE_GUI_PRIMITIVE,"javax.microedition.lcdui.Item");The USE_DIRECT_VIDEO mode can only be used with implementations that support the LCDUI (such as Symbian OS) and a second argumentof type javax.microedition.lcdui.Canvas (or a subclass) mustbe supplied. This is the approach adopted in the example code above.Methods of VideoControl can be used to manipulate the size and thelocation of the video with respect to the Canvas where it will be displayed.
Since we are using direct video as the display mode it is necessaryto call setVisible(true) in order for the video to be displayed. (Inthe case of USE_GUI_PRIMITIVE the video is shown by default whenthe GUI primitive is displayed.) Finally, we start the rendering of thevideo with the startPlayer() method. If at any stage an Exceptionis thrown the MIDletController.showAlert() method is calledand the resources acquired by the Player are released by calling theclosePlayer() method.The other methods of the VideoPlayer class are the same as theirnamesakes in the AudioPlayer class of the Audio Player MIDlet.The MIDletController ClassThe MIDletController class for the Video Player MIDlet is verysimilar to that of the Audio Player.
The method signatures of the class areshown below.import javax.microedition.midlet.*;import javax.microedition.lcdui.*;import javax.microedition.media.*;// A simple video player MIDlet using JSR 135 - Mobile Media APIpublic class MIDletController extends MIDlet implementsOPTIONAL J2ME APIS IN THE JTWI177CommandListener, PlayerListener {private Command exitCommand, playCommand, backCommand,replayCommand;private Display display;private InitialView initialView;private VideoCanvas videoCanvas;private VideoPlayer videoPlayer;public MIDletController() {...}public void startApp(){...}public void pauseApp(){...}public void destroyApp(boolean unconditional){...}public void commandAction(Command c, Displayable s){...}public void playerUpdate(Player p, String event,Object eventData) {...}public void showAlert(String title, String message){...}public void releaseResources(){...}}The constructor is listed below:public MIDletController() {int noOfVideos = Integer.parseInt(getAppProperty("number-of-videos"));String[] videoNames = new String[noOfVideos];for (int i = 1; i <= noOfVideos; i++){videoNames[i-1] = getAppProperty("video-" + i);}initialView = new InitialView(this, videoNames);exitCommand = new Command("Exit", Command.EXIT, 2);playCommand = new Command("Play", Command.SCREEN, 1);initialView.addCommand(exitCommand);videoCanvas = new VideoCanvas(this);backCommand = new Command("Back", Command.BACK, 1);videoCanvas.addCommand(backCommand);videoPlayer = new VideoPlayer(this, videoCanvas);display = Display.getDisplay(this);}It first uses the MIDlet getAppProperty() method to retrieve userdefined attributes from the JAD file, namely the number of video filespackaged in the JAR and their names.