作者:Confach 发表于April 23,2006 15:02 pm
版权信息:可以任意转载, 转载时请务必以超链接形式标明文章原始出处 和作者信息.
http://www.cnblogs.com/confach/articles/387902.html
5
第5章 支持的媒体内容(Media Content)
PME内容
播放媒体内容
监听媒体内容事件
创建定制的连接 |
PME内容
BlackBerry设备支持PME格式的富(rich)媒体内容。
开发者可以使用Plazmic Content Developer’s Kit for BlackBerry来创建PME内容。这个工具,以及附带的文档可以在Plazmic网站(www.plazmic.com)找到。
Media Engine API(在net.rim.plazmic.mediaengine 和 net.rim.plazmic.mediaengine.io包中)允许应用程序获取和播放存储在BlackBerry设备上或网络上的PME内容.
Media Engine API支持媒体格式application/x-vnd.rim.pme. Web服务器必须为application/x-vnd.rim.pme设置MIME类型。
PME API概览
下面3个主要类(在net.rim.plazmic.mediaengine包里)提供了加载和播放PME媒体内容的能力。
类 | 描述 |
MediaManager | 提供从本地或网络上加载媒体内容的方法。 |
MediaPlayer | 提供播放PME媒体的方法。 |
MediaException | 为获取或播放媒体的错误提供异常代码。 |
媒体加载
Media Engine API允许应用程序使用下面4种协议种的一种加载媒体内容:
协议 | 描述 |
http:// | http协议从一个使用HTTP连接网络Web服务器下载内容。这个协议需要一个带有BlackBerry MDS服务的BES(BlackBerry Enterprise Server,BlackBerry企业服务器). |
https:// | https协议从一个使用HTTPS连接网络Web服务器下载内容。这个协议需要一个带有BlackBerry MDS服务的BES(BlackBerry Enterprise Server,BlackBerry企业服务器). |
Jar:///<pme_file> | jar协议加载存储在本地BlackBerry设备上的jar文件。 jar:///sample.pme 注意:开始的斜线(/)是需要的。 在BlackBerry IDE中,.jar文件必须加入到调用应用程序或应用程序依赖的库的相同项目中。 |
cod://<module><pme_file> | cod协议加载存储在本地BlackBerry设备上的cod文件。 cod://mediasample/sample.pme |
为使用其他协议,实现定制的Connector。为获得更多信息,参看91页的“创建定制的Connector”.
播放状态(Playback states)
为了获取MediaPlayer的当前状态,调用MediaPlayer.getState().
状态 | 描述 |
UNREALIZED | MediaPlayer未准备播放媒体。为了转到REALIZED状态,调用MediaPlayer.setMedia(). |
REALIZED | MediaPlayer准备好播放媒体。为了开始播放,并转到STARTED状态,调用MediaPlayer.start(). |
STARTED | MediaPlayer正在播放媒体。为了停止播放和返回到REALIZED状态,调用MediaPlayer.stop(). |
异常
MediaEngine和MediaManager类的方法抛出一个MediaException异常,这个异常包含了一个标准的HTTP响应代码或者下面异常代码之一。为了获取与异常相联系的错误代码,调用MediaException.getCode().
异常代码 | 描述 |
INVALID_HEADER | 媒体格式无效。 |
REQUEST_TIMED_OUT | 请求超时。 |
INTERRUPTED_DOWNLOAD | 应用程序调用MediaManager.cancel()来取消下载。 |
UNSUPPORTED_TYPE | 媒体类型(MIME类型)不支持。 |
UPGRADE_PALYER | 媒体引擎的版本和请求的内容不兼容。 |
UPGRADE_MEDIA | 媒体引擎的版本不在支持请求的内容。 |
CHECKSUM_MISMACTH | 求和校验失败,因此媒体内容不能读取。 |
OUT_OF_BOUNDS | 数组出界,或应用程序试图访问一个文件结尾后的输入流。 |
事件
MediaListener接口允许应用程序接受或响应下面的事件:
事件 | 描述 |
MEDIA_REQUEST | 媒体已请求加载,当animation自动请求新内容或当用户点击媒体内容的超连接时,事件发生。 |
MEDIA_REALIZED | 媒体已经创建播放了。当MediaManager.createMediaManager()已经调用时发生。 |
MEDIA_COMPLETE | 媒体已经加载,并成功播放。 |
MEDIA_TO | 媒体正在加载。 |
为获得更多信息,参考85页的“监听Media Engine事件”.
播放媒体内容
为了获取BlackBerry设备或网络上的PME内容,使用MediaManager的方法。为了播放已经下载到BlackBerry设备的PME内容,使用MediaPlayer类的方法。
下载内容
为下载PME内容,创建一个MediaManager对象,然后调用MediaManager.createMedia().
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()); } |
注:下面缺省的协议会被支持:http://,https://.jar://,和cod://.为获得更多信息,参看81页的“媒体加载”。
第一次调用MediaManager.createMedia(),URL必须是绝对路径,除非首先调用MediaManager.setProperty(“URI_BASE”,<base_url>)设置基URL路径。当你之后调用createMedia()时,前面的URL作为基URL。
播放PME内容
为播放设置PME对象
调用MedialPlayer.setMedia().
MediaPlayer player = new MediaPlayer(); try { player.setMedia(media); } catch (MediaException me) { System.out.println("Error: requested content type is not supported.”); }
|
获取一个显示PME内容的UI对象
调用MediaPlayer.getUI()。转化getUI()返回的一个作为Field的对象,然后将之加入到屏幕来显示。
add((Field)player.getUI()); |
开始播放下载的PME内容
调用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()); } } |
注:在调用MediaPlayer.start()前检查MediaPlayer的状态,如果媒体播放器不是REALIZED状态,start()方法抛出一个异常。
代码实例
MediaSample.java实例从一个Web服务器获取一个PME文件,然后显示它。
例:MediaSample.java
/**
* MediaSample.java
* Copyright (C) 2001-2005 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();
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());
}
}
}
}
监听媒体引擎事件
MediaListener接口允许应用程序注册接收媒体引擎事件。应用程序可以在注册MediaPlayer和MediaEngine对象上注册监听者。
当应用程序实现监听者时,它可以完成以下的动作:
- 提供内容下载状态的信息。
- 在后台下载内容,当完成时播放它。
- 下载一个animation自动请求的内容。
MediaListener接口包含一个方法,listen方法。
public void mediaEvent(Object sender,
int event,
int eventParam,
Object data);
参数 | 描述 |
sender | 本参数引用了发送事件的对象,如MediaPlayer或MediaManager对象。 |
event | 参数可以是下列事件之一:
|
eventParam | 不要使用这个参数,因为它可能接收一个任意值。它存在是为了为额外的事件提供一个一致的接口。 |
data | 当data参数是MEDIA_REQUESTED,data把请求的URL作为一个String对象。 当data参数是MEDIA_REALIZED,data引用了创建的媒体对象。 当data参数是MEDIA_IO,data引用了一个net.rim.plazmic.mediaengine.io.LoadingStatus对象。 |
监听媒体引擎事件
MediaListener接口的实现允许你的应用程序监听一个媒体引擎事件。mediaEvent()的实现应该处理所有可能的媒体事件。下面的例子使用了一个switch语句来处理可能媒体事件。
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; } } } |
注册监听者
为了注册你的监听者,调用MediaPlayer和MediaManager对象上的addMediaListener()方法。
private MediaListenerImpl _listener = new MediaListenerImpl(); private MediaPlayer player = new MediaPlayer(); private MediaManager manager = new MediaManager(); player.addMediaListener(_listener); manager.addMediaListener(_listener); |
在后台加载内容
当实现MediaListener时,你可以在背后下载PME内容,并且当下载完成后播放内容。
调用MediaManager.createMediaListener()为将来的播放下载内容。
注:和createMedia()不一样,createMediaLater()不返回一个媒体内容的对象。
在MediaListener.mediaEvent()中,当请求的内容下载时,加入代码来处理MEDIA_REALIZED事件。为了注册在data参数里指定的内容,调用MediaPlayer.setMedia(data)。为了开始播放,调用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; } }
|
跟踪下载进度
为得到下载进度的信息,使用net.rim.plazmic.mediaengine.io.LoadingStatus类。这个类包含了一些方法来允许你获得媒体内容类型,字节总数,字节读取数,以及内容的源URL。
状态 | 描述 |
LOADING_STARTED | 加载开始。 |
LOADING_READING | 数据流正在解析。 |
LOADING_FINISHED | 加载媒体成功。 |
LOADING_FAILED | 媒体记载失败.
|
在mediaEvent()的实现里,当MEDIA_IO事件发生时,将data参数里的Object转化为一个LoadingStatus对象。
调用LoadingStatus.getStatus()来获取下载的状态,然后处理每个状态。
对每个正常的状态,打印一个消息到控制台。
对LOADING_FAILED状态,完成下面的动作:
- 调用LoadingStatus.getCode()获得错误代码。
- 调用LoadingStatus.getMessage()获得详细的消息。
- 调用LoadingStatus.getSource()获得内容的URL字符串。
public void mediaEvent(Object sender, int event, int eventParam, Object data) { switch(event) { ... case MEDIA_IO: { } ... break; } break; ...
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: { 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; } |
代码实例
MediaSample2.java 实例实现了一个监听者在后台下载媒体内容,并显示下载的状态到控制台。
例:MediaSample2.java
/**
* MediaSample2.java
* Copyright (C) 2001-2005 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();
}
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: {
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);
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());
}
}
}
创建一个定制的连接
MediaManager使用一个Connector对象加载媒体,并打开输入流。缺省的Connector支持下列协议:http://.https://,jar://,以及cod://。为了增加支持一个定制的协议或者为了覆写缺省的行为,通过实现net.rim.plazmic.mediaengine.io.Connector接口创建一个定制的Connector
方法签名 | 实现 |
InputStream getInputStream(String, ConnectionInfo) | 实现本方法返回一个输入流从指定URI读取内容。 |
void releaseConnection(ConnectionInfo) | 实现本方法释放连接。MediaManager调用本方法来通知Connector可以释放连接了。 |
void setProperty(String, String) | 实现本方法设置连接指定的属性。 |
实现一个定制的connector
为了完成处理一个定制的协议,实现Connector接口,包含getInputStream()。为了处理一个标准的协议,调用缺省的Connector。
setProperty(String name, String value)的实现设置了指定的属性。在本例中,connector不必设置任何指定的属性,因此setProperty()的实现调用了Connector上的setProperty()。
public class SampleConnector implements Connector {
Connector delegate; // The default Connector.
SampleConnector(Connector delegate) {
this.delegate = delegate;
}
public InputStream getInputStream(String uri, ConnectionInfo info)
throws IOException, MediaException {
InputStream input = null;
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;
}
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);
}
}
注册一个定制的连接器
在你的主要方法里,调用MediaManager.setConnector()注册你的定制的连接器。
MediaManager manager = new MediaManager(); manager.setConnector(new CustomPMEConnector(manager.getDefaultConnector())); |
代码实例
CustomPMEConnector.java实例为实现一个定制的连接器提供了一个框架。
例:CustomPMEConnector.java
/*
* CustomPMEConnector.java
* Copyright (C) 2003-2005 Research In Motion Limited. All rights reserved.
*/
package com.rim.samples.docs.mediasample;
import java.io.*;
import net.rim.plazmic.mediaengine.*;
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()
{
// ...
}
}
}
- Last Updated:2008年4月18日
- Last Updated:2007年1月10日
Last Updated:2006年4月28日