BlackBerry 应用程序开发者指南 第一卷:基础--第5章 支持的媒体内容(Media Content)...
作者: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日
转载于:https://www.cnblogs.com/confach/articles/387902.html
BlackBerry 应用程序开发者指南 第一卷:基础--第5章 支持的媒体内容(Media Content)...相关推荐
- BlackBerry 应用程序开发者指南 第一卷:基础--第9章 IT策略(Policy)
作者:Confach 发表于2006-04-28 21:44 版权信息:可以任意转载, 转载时请务必以超链接形式标明文章原始出处 和作者信息. http://www.cnblogs.com/confa ...
- BlackBerry 应用程序开发者指南 第一卷:基础--第7章 使用数据报(Datagram)连接...
作者:Confach 发表于2006-04-28 21:42 pm 版权信息:可以任意转载, 转载时请务必以超链接形式标明文章原始出处 和作者信息. http://www.cnblogs.com/co ...
- BlackBerry 应用程序开发者指南 第一卷:基础--第8章 本地化应用程序
作者:Confach 发表于2006-04-28 21:43 pm 版权信息:可以任意转载, 转载时请务必以超链接形式标明文章原始出处 和作者信息. http://www.cnblogs.com/co ...
- BlackBerry 应用程序开发者指南 第二卷:高级--第11章 管理通知(Notification)
作者:Confach 发表于 2006-04-29 20:28 pm 版权信息:可以任意转载, 转载时请务必以超链接形式标明文章原始出处 和作者信息. http://www.cnblogs.com/c ...
- BlackBerry 应用程序开发者指南 第二卷:高级--第7章 与BlackBerry应用程序通信
作者:Confach 发表于2006-04-28 22:22 pm 版权信息:可以任意转载, 转载时请务必以超链接形式标明文章原始出处 和作者信息. http://www.cnblogs.com/co ...
- BlackBerry 应用程序开发者指南 第二卷:高级--第13章 应用程序间共享运行时对象...
作者:Confach 发表于 2006-04-29 20:30 pm 版权信息:可以任意转载, 转载时请务必以超链接形式标明文章原始出处 和作者信息. http://www.cnblogs.com/c ...
- BlackBerry 应用程序开发者指南 第二卷:高级--第4章 增加设备选项
作者:Confach 发表于2006-04-28 22:18 pm 版权信息:可以任意转载, 转载时请务必以超链接形式标明文章原始出处 和作者信息. http://www.cnblogs.com/co ...
- 顶级c程序员之路 基础篇 - 第一章 关键字的深度理解 number-1
c语言有32个关键字,每个关键字你都理解吗? 今天出场的是: auto , register, static, extern 为什么他们会一起呢,说到这里不得不谈到c语言对变量的描述. c给每 ...
- 百度智能小程序搜索优化指南(基础版)
目录 一.为什么百度搜索喜欢智能小程序 二.开发前必读内容 2.1 必须了解的搜索知识 2.2 掌握常用工具 2.3 如何搭建智能小程序更友好 三.智能小程序资源如何进入搜索 3.1 接入自然搜索结 ...
最新文章
- 【洛谷】P1388 算式(dp)
- final,finally,finaliz的区别(Java)
- bzoj4013: [HNOI2015]实验比较
- ffplay.c学习-5-视频输出和尺⼨变换
- Angular应用里的tsconfig.app.json
- WebService客户端开发(Axis2 1.5)
- 三星笔记本进入BIOS后找不到U盘启动项/快速启动键F12没有反应
- java transient简单介绍
- 别再双塔了!谷歌提出DSI索引,检索效果吊打双塔,零样本超BM25!
- 关于PyTorch中的register_forward_hook()函数未能执行其中hook函数的问题
- IOT(3)---传感器厂家
- Flink : UnknownTaskExecutorException: No TaskExecutor registered under
- mysql一次运行多个SQL文件
- AutoResetEvent 与 ManualResetEvent
- 面对SDN,我们该怎么办?
- 安信可Ca-01 4G模块调试
- python3爬虫抓取链家上海租房信息
- 语义网络,语义网,链接数据和知识图谱
- Eric Berg:帮助你了解及根治痘痘痤疮的观点
- 电子发票电子化报销入账归档 给区块链领域带来了什么样的机遇