BlackBerry 应用程序开发者指南 第二卷:高级--第5章 BlackBerry浏览器
作者:Confach 发表于2006-04-28 22:20 pm
版权信息:可以任意转载, 转载时请务必以超链接形式标明文章原始出处 和作者信息.
http://www.cnblogs.com/confach/articles/387948.html
5
第5章 BlackBerry浏览器
浏览器API 在浏览器显示Web内容 在一个浏览器域里显示Web内容 支持附加的MIME类型 注册一个HTTP过滤器 |
浏览器API
API名和包 |
描述 |
浏览器应用程序API(net.rim.blackberry.api.browser) |
通过调用Blackberry浏览器,API允许应用程序显示web内容,包括支持的图片格式,HTML以及WML页面.也允许应用程序提供HTTP请求的一个Referrer,HTTP头,以及提交的内容.为获得更多信息,参看51页的”在浏览器显示Web内容”. |
浏览器域API (net.rim.blackberry.api.browser.field) |
此API允许一个应用程序获取web内容在一个浏览器域里的显示,此域包含在应用程序UI里.也允许应用程序配置浏览器域的表现形式,例如去除滚动条,或者指定仅显示屏幕一部分的浏览器域. |
浏览器页面API(net.rim.blackberry.api.browser.plugin) |
此API允许应用程序支持附加的MIME类型.当BlackBerry启动时,注册一个提交提供者,所有后发的浏览器对话将支持附加的MIME类型.为获取更多信息,参看66页的”支持附加的MIME类型”. |
HTTP过滤器API (net.rim.device.api.io.http) |
API允许应用程序向浏览器注册一个或多个URL的提供者.为获取更多信息,参看71页的”注册一个HTTP过滤器”. |
在浏览器里显示Web内容
为了在浏览器里显示web内容,使用浏览器应用程序API(net.rim.blackberry.api.browser).
获取一个浏览器对话(Session)
为了获取一个缺省的BrowserSession对象,调用静态方法Browser.getDefaultSession().本对象允许你访问正在BlackBerry设备上运行的浏览器.
为了新增一个约会,调用EventList.importEvent().
注:获取缺省的对话会覆写任何BlackBerry设备上已经打开的对话.
为获取一个不同的对话,调用getSession().此方法根据它的唯一ID(UID)获取一个浏览器配置服务记录.为获得更多信息,参见113页的”服务定制API”.
请求一个Web页面
为请求一个Web页面,调用BrowserSession.displayPage()方法.下面的实例使用了仅接受一个URL的displayPage()方法.为指定一个referrer,HTTP头,以及提交的数据,使用接受这些附加信息的方法.
代码实例
下面来自Restaurants.java实例的引用创建了一个菜单,此菜单会在浏览器中显示一个Web页面.
private MenuItem browserItem = new MenuItem( _resources.getString(MENUITEM_BROWSER), 110, 12) { public void run() { synchronized(store) { String websiteUrl = websitefield.getText(); if (websiteUrl.length == 0) { Dialog.alert(_resources.getString(ALERT_NO_WEBSITE)); } else { BrowserSession visit = Browser.getDefaultSession(); visit.displayPage(websiteUrl); } } } }; |
在浏览器域显示Web内容
为了在应用程序UI里包含一个浏览器域,使用浏览器域API (net.rim.device.api.browser.field).浏览器呈现(rendering)库为域处理web内容的描绘,然后返回一个BrowserField-在此域URL内容得到描绘-到你的应用程序显示.
RenderingApplication接口定义了一个描绘对话所需要的回调功能来帮助处理URL资源, RenderingApplication接口的实现在一个浏览器域里显示web内容.
为呈现创建一个独立的线程
当应用程序获取和显示浏览器域时,为阻止应用程序挂起,在一个独立线程上完成这些操作.
class CreationThread extends Thread { BrowserFieldHandlerApplication _callBackApplication; BasicRenderingApplication _renderingApplication; public CreationThread(BrowserFieldHandlerApplication callBackApplication) { _callBackApplication = callBackApplication; } public void run() { _renderingApplication = new BasicRenderingApplication(_callBackApplication); BrowserField field = _renderingApplication.getBrowserField("www.blackberry.com"); _callBackApplication.displayBrowserField(field); } } |
设置呈现选项
覆写getRenderingOptions().如果你没有覆写此方法, 将使用缺省的呈现选项.为获得更多信息,参看API参考的RenderingOptions.
处理事件
eventOccurred()的实现处理事件,例如一个URL请求.
public Object eventOccurred(Event event) { int eventId = event.getUID(); switch (eventId) { case Event.EVENT_URL_REQUESTED : { UrlRequestedEvent e = (UrlRequestedEvent) event; // This is a regular request. String absoluteUrl = e.getURL(); HttpConnection conn = null; OutputStream out = null; try { conn = (HttpConnection) Connector.open(absoluteUrl); FormData postData = e.getPostData(); if (postData == null) { conn.setRequestMethod(HttpConnection.GET); } else { conn.setRequestMethod(HttpConnection.POST); byte[] postBytes = postData.getBytes(); conn.setRequestProperty(HttpProtocolConstants.HEADER_CONTENT_LENGTH, String.valueOf(postBytes.length)); if (conn.getRequestProperty( HttpProtocolConstants.HEADER_CONTENT_TYPE) == null) { conn.setRequestProperty( HttpProtocolConstants.HEADER_CONTENT_TYPE, postData.getContentType()); } out = conn.openOutputStream(); out.write(postBytes); } HttpHeaders requestHeaders = e.getHeaders(); if (requestHeaders != null) { /* From http://www.w3.org/Protocols/rfc2616/rfc2616-sec15.html#sec15.1.3 * Clients SHOULD NOT include a Referer header field in a * (non-secure) HTTP request if the referring page was * transferred with a secure protocol.*/ String referer = requestHeaders.getPropertyValue("referer"); boolean sendReferrer = true; if (referer != null && referer.startsWith("https:") && !absoluteUrl.startsWith("https:")) { sendReferrer = false; } int size = requestHeaders.size(); for (int i = 0; i < size; i++) { String header = requestHeaders.getPropertyKey(i); // Remove refer header if needed. if ( !sendReferrer && header.equals("referer")) { requestHeaders.removeProperty(i); continue; } conn.setRequestProperty( header, requestHeaders.getPropertyValue( i ) ); } } } catch (IOException e1) { } finally { if (out != null) { try { out.close(); } catch (IOException e2) { } } } BrowserField browserField = getBrowserField(conn, e); _callbackApplication.displayBrowserField(browserField); break; } case Event.EVENT_BROWSER_FIELD_CHANGED : { // Browser field title might have changed. Update title. break; } case Event.EVENT_REDIRECT : { RedirectEvent e = (RedirectEvent) event; switch (e.getType()) { case RedirectEvent.TYPE_SINGLE_FRAME_REDIRECT : // Show redirect message. Application.getApplication().invokeAndWait(new Runnable() { public void run() { Status.show(""); } }); break; case RedirectEvent.TYPE_JAVASCRIPT : case RedirectEvent.TYPE_META : case RedirectEvent.TYPE_300_REDIRECT : } String absoluteUrl = e.getLocation(); HttpConnection conn = null; try { conn = (HttpConnection) Connector.open(absoluteUrl); } catch (IOException e1) { } BrowserField browserField = getBrowserField(conn, e.getOriginalEvent()); _callbackApplication.displayBrowserField(browserField); break; } case Event.EVENT_CLOSE : // Close the appication. break; case Event.EVENT_SET_HEADER :// no cache support case Event.EVENT_SET_HTTP_COOKIE : // no cookie support case Event.EVENT_HISTORY : // no history support case Event.EVENT_LOADING_IMAGES :// no progress bar is supported case Event.EVENT_EXECUTING_SCRIPT : // no progress bar is supported case Event.EVENT_FULL_WINDOW : // no full window support case Event.EVENT_STOP : // no stop loading support default : } return null; } |
为呈现获取浏览器内容
getBrowserField()的实现为呈现获取浏览器内容. getBrowserField()方法调用RenderingSession.getBrowserField()获取一个浏览器域.应用程序不能直接实例化BrowserField
public BrowserField getBrowserField (String absoluteUrl) { HttpConnection conn = null; try { conn = (HttpConnection) Connector.open(absoluteUrl); // Set transcode to true. conn.setRequestProperty( "x-rim-transcode-content", "*/*" ); } catch (IOException e1) { } return getBrowserField(conn, null); } private BrowserField getBrowserField(HttpConnection conn, Event e) { BrowserField field = null; try { field = _renderingSession.getBrowserField(conn, this, e); } catch (RenderingException re) { return null; } // Add to the event queue a thread that invokes finishLoading(). Application.getApplication().invokeLater(new RenderingThread(field)); return field; } |
描绘浏览器域
调用BrowserField.finishLoading().在下面的代码实例中, BrowserField.getBrowserField()将一个新的描绘线程加载到应用程序事件队列里来运行finishLoading().
class RenderingThread implements Runnable { BrowserField _browserField; RenderingThread(BrowserField field) { _browserField = field; } public void run() { try { _browserField.finishLoading(); } catch (RenderingException e) { // Handle exception. } } } |
显示浏览器域
displayBrowserField()的实现删除屏幕内容,然后增加浏览器域到屏幕.
public void displayBrowserField(BrowserField browserField) { synchronized (Application.getEventLock()) { _vfm.deleteAll(); _vfm.add(browserField); } } |
代码实例
下面的实例包含了3个文件: BasicRenderingApplication.java, BrowserFieldHandlerApplication.java, 以及 BrowserFieldSampleApp.java.
例:浏览器域实例
/**
* BasicRenderingApplication.java
* Copyright (C) 2002-2005 Research In Motion Limited.
*/
package com.rim.samples.docs.browser;
import java.io.IOException;
import java.io.OutputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import net.rim.device.api.browser.field.*;
import net.rim.device.api.io.http.HttpHeaders;
import net.rim.device.api.io.http.HttpProtocolConstants;
import net.rim.device.api.system.Application;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.component.Status;
import com.rim.samples.docs.browser.BrowserFieldHandlerApplication.*;
final public class BasicRenderingApplication implements RenderingApplication
{
RenderingSession _renderingSession;
BrowserFieldHandlerApplication _callbackApplication;
public BasicRenderingApplication(BrowserFieldHandlerApplication callBackApplication) {
_renderingSession = RenderingSession.getNewInstance();
_callbackApplication = callBackApplication;
}
/**
* * Simple method to get a browser field by specifying the URL.
* * This call blocks until the browser field is returned by RenderingSession.getBrowserField().
* * The browser field can continue to be rendered after the field is returned.
* *
* * @param absoluteUrl - absolute url of the page to render
* * @return rendered browser field
* */
public BrowserContent getBrowserField (String absoluteUrl) {
HttpConnection conn = null;
try {
conn = (HttpConnection) Connector.open(absoluteUrl);
// Set transcode to true.
conn.setRequestProperty( "x-rim-transcode-content", "*/*" );
}
catch (IOException e1) {
}
return getBrowserField(conn, null);
}
private BrowserContent getBrowserField(HttpConnection conn, Event e) {
BrowserContent field = null;
try {
field = _renderingSession.getBrowserContent(conn, this, e);
}
catch (RenderingException re) {
return null;
}
Application.getApplication().invokeLater(new RenderingThread(field));
return field;
}
/**
* * Invoked when an event occurs.
* */
public Object eventOccurred(Event event) {
int eventId = event.getUID();
switch (eventId) {
case Event.EVENT_URL_REQUESTED : {
UrlRequestedEvent e = (UrlRequestedEvent) event;
// this is a regular request
String absoluteUrl = e.getURL();
HttpConnection conn = null;
OutputStream out = null;
try {
conn = (HttpConnection) Connector.open(absoluteUrl);
byte[] postData = e.getPostData();
if (postData == null) {
conn.setRequestMethod(HttpConnection.GET);
}
else {
conn.setRequestMethod(HttpConnection.POST);
conn.setRequestProperty( HttpProtocolConstants.HEADER_CONTENT_LENGTH,
String.valueOf(postData.length));
out = conn.openOutputStream();
out.write(postData);
}
HttpHeaders requestHeaders = e.getHeaders();
if (requestHeaders != null) {
/* From http://www.w3.org/Protocols/rfc2616/rfc2616-sec15.html#sec15.1.3
* ...
* Clients SHOULD NOT include a Referer header field in a
* (non-secure) HTTP request if the referring page was
* transferred with a secure protocol.
* */
String referer = requestHeaders.getPropertyValue("referer");
boolean sendReferrer = true;
if (referer != null && referer.startsWith("https:") &&
!absoluteUrl.startsWith("https:")) {
sendReferrer = false;
}
int size = requestHeaders.size();
for (int i = 0; i < size; i++) {
String header = requestHeaders.getPropertyKey(i);
// Remove refer header if needed.
if ( !sendReferrer && header.equals("referrer")) {
requestHeaders.removeProperty(i);
continue;
}
conn.setRequestProperty( header,
requestHeaders.getPropertyValue( i ) );
}
}
}
catch (IOException e1) {
}
finally {
if (out != null) {
try {
out.close();
}
catch (IOException e2) {
}
}
}
BrowserContent browserField = getBrowserField(conn, e);
_callbackApplication.displayBrowserField(browserField);
break;
}
case Event.EVENT_BROWSER_CONTENT_CHANGED : {
// Browser field title might have changed. Update title.
break;
}
case Event.EVENT_REDIRECT : {
RedirectEvent e = (RedirectEvent) event;
switch (e.getType()) {
// Show redirect message.
Application.getApplication().invokeAndWait(new Runnable() {
public void run() {
Status.show("");
}
});
break;
case RedirectEvent.TYPE_JAVASCRIPT :
case RedirectEvent.TYPE_META :
case RedirectEvent.TYPE_300_REDIRECT :
}
String absoluteUrl = e.getLocation();
HttpConnection conn = null;
try {
conn = (HttpConnection) Connector.open(absoluteUrl);
}
catch (IOException e1) {
}
BrowserContent browserField = getBrowserField(conn, e.getOriginalEvent());
_callbackApplication.displayBrowserField(browserField);
break;
}
case Event.EVENT_CLOSE :
// Close the appication.
break;
case Event.EVENT_TICK_CONTENT_READ : // No progress bar is supported.
case Event.EVENT_SET_HEADER : // No cache support.
case Event.EVENT_SET_HTTP_COOKIE : // No cookie support.
case Event.EVENT_HISTORY : // No history support
case Event.EVENT_LOADING_IMAGES : // No progress bar is supported.
case Event.EVENT_EXECUTING_SCRIPT : // No progress bar is supported.
case Event.EVENT_FULL_WINDOW : // No full window support.
case Event.EVENT_STOP : // No stop loading support.
default :
}
return null;
}
/**
* * Retrieves the pixels of height available for provided browser content.
* * @param browserField Content for which to retrieve available pixels of height.
* * @return Height available.
* */
public int getAvailableHeight(BrowserContent browserField) {
// Field has full screen.
return Graphics.getScreenHeight();
}
/**
* * Retrieves the pixels of width available for provided browser content.
* */
public int getAvailableWidth(BrowserContent browserField) {
// Field has full screen.
return Graphics.getScreenWidth();
}
/**
* * Retrieves the history position for provided browser content.
* */
public int getHistoryPosition(BrowserContent browserField) {
// No history support.
return 0;
}
/**
* * Retrieves cookies associated with a provided URL.
* */
public String getHTTPCookie(String url) {
// No cookie support.
return null;
}
/**
* * Retrieves the specified resource.
*/
public HttpConnection getResource( RequestedResource resource, BrowserContent referrer)
{
if (resource == null) {
return null;
}
// Check if this is cache-only request.
if (resource.isCacheOnly()) {
// No cache support.
return null;
}
String url = resource.getUrl();
if (url == null) {
return null;
}
// If referrer is null, return the connection.
if (referrer == null) {
HttpConnection conn;
try {
return (HttpConnection) Connector.open(resource.getUrl());
}
catch (IOException e) {
return null;
}
}
else {
// If referrer is provided, set up the connection on a
// separate thread.
Application.getApplication().invokeLater(
new RetrieveThread(resource, referrer));
}
return null;
}
/**
* * Invokes the provided runnable object.
* */
public void invokeRunnable(Runnable runnable) {
(new Thread(runnable)).run();
}
}
class RenderingThread implements Runnable {
BrowserContent _browserField;
RenderingThread(BrowserContent field) {
_browserField = field;
}
public void run() {
try {
_browserField.finishLoading();
}
catch (RenderingException e) {
}
}
}
class RetrieveThread implements Runnable {
BrowserContent _browserField;
RequestedResource _resource;
RetrieveThread(RequestedResource resource, BrowserContent referrer) {
_browserField = referrer;
_resource = resource;
}
public void run() {
HttpConnection conn;
try {
conn = (HttpConnection) Connector.open(_resource.getUrl());
}
catch (IOException e) {
return;
}
_resource.setHttpConnection(conn);
_browserField.resourceReady(_resource);
}
}
/**
* BasicRenderingApplication.java
* Copyright (C) 2002-2005 Research In Motion Limited.
*/
package com.rim.samples.docs.browser;
import java.io.IOException;
import java.io.OutputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import net.rim.device.api.browser.field.*;
import net.rim.device.api.io.http.HttpHeaders;
import net.rim.device.api.io.http.HttpProtocolConstants;
import net.rim.device.api.system.Application;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.component.Status;
import com.rim.samples.docs.browser.BrowserFieldHandlerApplication.*;
final public class BasicRenderingApplication implements RenderingApplication {
RenderingSession _renderingSession;
BrowserFieldHandlerApplication _callbackApplication;
public BasicRenderingApplication(BrowserFieldHandlerApplication callBackApplication) {
_renderingSession = RenderingSession.getNewInstance();
_callbackApplication = callBackApplication;
}
/**
* * Simple method to get a browser field by specifying the URL.
* * This call blocks until the browser field is returned by RenderingSession.getBrowserField().
* * The browser field can continue to be rendered after the field is returned.
* *
* * @param absoluteUrl - absolute url of the page to render
* * @return rendered browser field
* */
public BrowserContent getBrowserField (String absoluteUrl) {
HttpConnection conn = null;
try {
conn = (HttpConnection) Connector.open(absoluteUrl);
// Set transcode to true.
conn.setRequestProperty("x-rim-transcode-content", "*/*" );
}
catch (IOException e1) {
}
return getBrowserField(conn, null);
}
private BrowserContent getBrowserField(HttpConnection conn, Event e) {
BrowserContent field = null;
try {
field = _renderingSession.getBrowserContent(conn, this, e);
}
catch (RenderingException re) {
return null;
}
Application.getApplication().invokeLater(new RenderingThread(field));
return field;
}
/**
* * Invoked when an event occurs.
* */
public Object eventOccurred(Event event) {
int eventId = event.getUID();
switch (eventId) {
case Event.EVENT_URL_REQUESTED : {
UrlRequestedEvent e = (UrlRequestedEvent) event;
// this is a regular request
String absoluteUrl = e.getURL();
HttpConnection conn = null;
OutputStream out = null;
try {
conn = (HttpConnection) Connector.open(absoluteUrl);
byte[] postData = e.getPostData();
if (postData == null) {
conn.setRequestMethod(HttpConnection.GET);
}
else {
conn.setRequestMethod(HttpConnection.POST);
conn.setRequestProperty( HttpProtocolConstants.HEADER_CONTENT_LENGTH,
String.valueOf(postData.length));
out = conn.openOutputStream();
out.write(postData);
}
HttpHeaders requestHeaders = e.getHeaders();
if (requestHeaders != null) {
/* From http://www.w3.org/Protocols/rfc2616/rfc2616-sec15.html#sec15.1.3
* ...
* Clients SHOULD NOT include a Referer header field in a
* (non-secure) HTTP request if the referring page was
* transferred with a secure protocol.*/
String referer = requestHeaders.getPropertyValue("referer");
boolean sendReferrer = true;
if (referer != null && referer.startsWith("https:")
&& !absoluteUrl.startsWith("https:")) {
sendReferrer = false;
}
int size = requestHeaders.size();
for (int i = 0; i < size; i++) {
String header = requestHeaders.getPropertyKey(i);
// Remove refer header if needed.
if ( !sendReferrer && header.equals("referrer")) {
requestHeaders.removeProperty(i);
continue;
}
conn.setRequestProperty( header, requestHeaders.getPropertyValue( i ) );
}
}
}
catch (IOException e1) {
}
finally {
if (out != null) {
try {
out.close();
}
catch (IOException e2) {
}
}
}
BrowserContent browserField = getBrowserField(conn, e);
_callbackApplication.displayBrowserField(browserField);
break;
}
case Event.EVENT_BROWSER_CONTENT_CHANGED : {
// Browser field title might have changed. Update title.
break;
}
case Event.EVENT_REDIRECT : {
RedirectEvent e = (RedirectEvent) event;
switch (e.getType()) {
case RedirectEvent.TYPE_SINGLE_FRAME_REDIRECT :
// Show redirect message.
Application.getApplication().invokeAndWait(new Runnable() {
public void run() {
Status.show("");
}
});
break;
case RedirectEvent.TYPE_JAVASCRIPT :
case RedirectEvent.TYPE_META :
case RedirectEvent.TYPE_300_REDIRECT :
}
String absoluteUrl = e.getLocation();
HttpConnection conn = null;
try {
conn = (HttpConnection) Connector.open(absoluteUrl);
}
catch (IOException e1) {
}
BrowserContent browserField = getBrowserField(conn, e.getOriginalEvent());
_callbackApplication.displayBrowserField(browserField);
break;
}
case Event.EVENT_CLOSE :
// Close the appication.
break;
case Event.EVENT_TICK_CONTENT_READ : // No progress bar is supported.
case Event.EVENT_SET_HEADER : // No cache support.
case Event.EVENT_SET_HTTP_COOKIE : // No cookie support.
case Event.EVENT_HISTORY : // No history support.
case Event.EVENT_LOADING_IMAGES : // No progress bar is supported.
case Event.EVENT_EXECUTING_SCRIPT : // No progress bar is supported
case Event.EVENT_FULL_WINDOW : // No full window support
case Event.EVENT_STOP : // No stop loading support.
default :
}
return null;
}
/**
* * Retrieves the pixels of height available for provided browser content.
* * @param browserField Content for which to retrieve available pixels of height.
* * @return Height available.
* */
public int getAvailableHeight(BrowserContent browserField) {
// Field has full screen.
return Graphics.getScreenHeight();
}
/**
* * Retrieves the pixels of width available for provided browser content.
* */
public int getAvailableWidth(BrowserContent browserField) {
// Field has full screen.
return Graphics.getScreenWidth();
}
/**
* * Retrieves the history position for provided browser content.
* */
public int getHistoryPosition(BrowserContent browserField) {
// No history support.
return 0;
}
/**
* * Retrieves cookies associated with a provided URL.
* */
public String getHTTPCookie(String url) {
// No cookie support.
return null;
}
/**
* * Retrieves the specified resource.
* */
public HttpConnection getResource( RequestedResource resource, BrowserContent referrer)
{
if (resource == null) {
return null;
}
// Check if this is cache-only request.
if (resource.isCacheOnly()) {
// No cache support.
return null;
}
String url = resource.getUrl();
if (url == null) {
return null;
}
// If referrer is null, return the connection.
if (referrer == null) {
HttpConnection conn;
try {
return (HttpConnection) Connector.open(resource.getUrl());
}
catch (IOException e) {
return null;
}
}
else {
// If referrer is provided, set up the connection on a
// separate thread.
Application.getApplication().invokeLater(
new RetrieveThread(resource, referrer));
}
return null;
}
/**
* * Invokes the provided runnable object.
* */
public void invokeRunnable(Runnable runnable) {
(new Thread(runnable)).run();
}
}
class RenderingThread implements Runnable {
BrowserContent _browserField;
RenderingThread(BrowserContent field) {
_browserField = field;
}
public void run() {
try {
browserField.finishLoading();
}
catch (RenderingException e) {
}
}
}
class RetrieveThread implements Runnable {
BrowserContent _browserField;
RequestedResource _resource;
RetrieveThread(RequestedResource resource, BrowserContent referrer) {
_browserField = referrer;
_resource = resource;
}
public void run() {
HttpConnection conn;
try {
conn = (HttpConnection) Connector.open(_resource.getUrl());
}
catch (IOException e) {
return;
}
_resource.setHttpConnection(conn);
_browserField.resourceReady(_resource);
}
}
支持附加MIME类型
浏览器页面API在net.rim.device.api.browser.plugin包中,它允许第三方应用程序向描绘库将它们自己注册为BlackBerry浏览器不支持的MIME类型的描绘提供者.
注册一个MIME类型的呈现提供者
为支持附加的MIME类型,需要扩展BrowserContentProvider抽象类.为了指定显示特性,例如没有滚动条显示或全屏显示,需要实现BrowserPageContext接口.
呈现的类库调用BrowserContentProvider.getAccept()和BrowserContentProvider.getSupportedMimeTypes()标志提供者呈现的MIME类型.
列出接受的MIME类型
getAccept()和getSupportedMimeTypes()的实现列出了提供者接受的MIME类型,它们给定了一组呈现的选项. getAccept()方法考虑到已经设置的呈现选项.这个例子假设没有设置呈现选项.为得到更多信息.参看API参考的RenderingOptions
public String[] getAccept(RenderingOptions context) { // Return subset of getSupportedMimeTypes() if accept depends on rendering // options. For example, HTML can be turned off in the rendering options. // This would cause HTMLConverter to remove HTML MIME types. return ACCEPT; } public String[] getSupportedMimeTypes() { return ACCEPT; } |
指定显示特征
BrowserPageContext接口的实现指定了显示的特征.如果没有实现此接口,将使用缺省的值.
在本例中,所有属性都是整型.一个带有Boolean,String,和Object属性的应用程序将实现对应的方法.
public boolean getPropertyWithBooleanValue(int id, boolean defaultValue) { // TODO Implement. return false; } public int getPropertyWithIntValue(int id, int defaultValue) { if (id == BrowserPageContext.DISPLAY_STYLE) { // Turn off the scroll bar. return BrowserPageContext.STYLE_NO_VERTICAL_SCROLLBAR; } return 0; } public Object getPropertyWithObjectValue(int id, Object defaultValue) { // TODO Implement. return null; } public String getPropertyWithStringValue(int id, String defaultValue) { // TODO Implement. return null; } |
获取一个域呈现内容
实现getBrowserContent(BrowserContentProviderContext)方法.
public BrowserContent getBrowserContent( BrowserContentProviderContext context) throws RenderingException { if (context == null) { throw new RenderingException("No Context is passed into Provider"); } BrowserContentBaseImpl browserContentBaseImpl = new BrowserContentBaseImpl(context.getHttpConnection().getURL(), null, context.getRenderingApplication(), context.getRenderingSession().getRenderingOptions(), context.getFlags()); VerticalFieldManager vfm = new VerticalFieldManager(Manager.VERTICAL_SCROLL); vfm.add(new LabelField("Mime type: ") ); vfm.add(new LabelField(ACCEPT[0])); vfm.add(new SeparatorField()); vfm.add(new LabelField("Content of the resource file: \n")); vfm.add(new SeparatorField()); try { HttpConnection conn = context.getHttpConnection(); InputStream in = conn.openInputStream(); byte[] data = IOUtilities.streamToBytes(in); vfm.add(new LabelField(new String(data))); } catch (IOException e) { // TODO Implement. e.printStackTrace(); } browserContentBaseImpl.setContent(vfm); browserContentBaseImpl.setTitle(ACCEPT[0]); // Set browser page context, this will tell the browser how to display this // field. browserContentBaseImpl.setBrowserPageContext(this); return browserContentBaseImpl; } |
在BlackBerry启动时注册
创建一个类库工程,将它的属性设置为启动时自动运行.在libMain()里,调用BrowserFieldProviderRegistry.getInstance()方法,然后再调用invoke register().
public static void libMain( String[] args ) { BrowserContentProviderRegistry converterRegistry = BrowserContentProviderRegistry.getInstance(); if (converterRegistry != null) { converterRegistry.register(new BrowserPlugin()); } } |
代码实例
下面的例子包含2个文件, LoaderApp.java和BrowserPlugin.java.当BlackBerry设备启动时LoaderApp.java增加一个新支持的MIME类型. BrowserPlugin.java包含了一个扩展了BrowserContentProvider的类.
例: BrowserPlugin.java和LoaderApp.java
/**
* LoaderApp.java
* Copyright (C) 2004-2005 Research In Motion Limited.
*/
package com.rim.samples.docs.browser;
import net.rim.device.api.browser.plugin.BrowserContentProviderRegistry;
final class LoaderApp {
public static void libMain( String[] args ) {
BrowserContentProviderRegistry converterRegistry =
BrowserContentProviderRegistry.getInstance();
if (converterRegistry != null) {
converterRegistry.register(new BrowserPlugin());
}
}
}
/**
* BrowserPlugin.java
* Copyright (C) 2004-2005 Research In Motion Limited.
*/
package com.rim.samples.docs.browser;
import java.io.IOException;
import java.io.InputStream;
import javax.microedition.io.HttpConnection;
import net.rim.device.api.browser.field.*;
import net.rim.device.api.browser.plugin.*;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.SeparatorField;
import net.rim.device.api.ui.container.VerticalFieldManager;
/**
* Create a file with xxtest extension and associate that type with
* application/x-vnd.rim.xxxtest mime type on any server.
*/
public final class BrowserPlugin extends BrowserContentProvider
implements BrowserPageContext {
private static final String[] ACCEPT = {"application/x-vnd.rim.xxxtest"};
/**
* Retrieves list of mime types this provider can accept given a set of rendering options.
* * @param context Rendering options in place this provider should consider.
* * @return Array of mime types this provider will accept, given the provided rendering
* options.
**/
public String[] getAccept(RenderingOptions context) {
// Return subset of getSupportedMimeTypes() if accept depends in rendering options.
// For example HTML can be disabled in the rendering options, and HTMLConverter would remove
// html MIME types.
return ACCEPT;
}
/**
* Retrieves a browser content capable of rendering the mime content this provider
* can handle.
* @param context Provider context object provided by rendering session.
* @return Browser content to render specialized content.
*/
public BrowserContent getBrowserContent( BrowserContentProviderContext context)
throws RenderingException {
if (context == null) {
throw new RenderingException("No Context is passed into Provider");
}
BrowserContentBaseImpl browserContentBaseImpl =
new BrowserContentBaseImpl(context.getHttpConnection().getURL(),
null, context.getRenderingApplication(),
context.getRenderingSession().getRenderingOptions(),
context.getFlags());
VerticalFieldManager vfm = new VerticalFieldManager(Manager.VERTICAL_SCROLL);
vfm.add(new LabelField("Mime type: ") );
vfm.add(new LabelField(ACCEPT[0]));
vfm.add(new SeparatorField());
vfm.add(new LabelField("Content of the resource file: \n"));
vfm.add(new SeparatorField());
try {
HttpConnection conn = context.getHttpConnection();
InputStream in = conn.openInputStream();
int numBytes = in.available();
byte[] data = new byte[numBytes];
in.read(data, 0, numBytes);
vfm.add(new LabelField(new String(data)));
}
catch (IOException e) {
e.printStackTrace();
}
browserContentBaseImpl.setContent(vfm);
browserContentBaseImpl.setTitle(ACCEPT[0]);
// Set browser page context. This tells the browser how to display this field.
browserContentBaseImpl.setBrowserPageContext(this);
return browserContentBaseImpl;
}
/**
* * Retrieves all the mime content types supported by this provider.
* * @return Mime types this converter supports.
* */
public String[] getSupportedMimeTypes() {
return ACCEPT;
}
/**
* * Retrieves value of specified property as a boolean value.
* * @param id ID of property to query.
* * @param defaultValue Expected default value of property.
* * @return Current value of property.
* */
public boolean getPropertyWithBooleanValue(int id, boolean defaultValue) {
return false;
}
/**
* Retrieves value of specified property as an int.
* @param id ID of property to query.
* @param defaultValue Expected default value of property.
* @return Current value of property.
*/
public int getPropertyWithIntValue(int id, int defaultValue) {
if (id == BrowserPageContext.DISPLAY_STYLE) {
// Disable the scroll bar.
return BrowserPageContext.STYLE_NO_VERTICAL_SCROLLBAR;
}
return 0;
}
/**
* Retrieves value of specified property as an object.
* @param id ID of property to query.
* @param defaultValue Expected default value of property.
* @return Current value of property.
*/
public Object getPropertyWithObjectValue(int id, Object defaultValue) {
return null;
}
/* Retrieves value of specified property as a String value.
* @param id - ID of property to query.
* @param defaultValue - Expected default value of property.
* @return Current value of property.
*/
public String getPropertyWithStringValue(int id, String defaultValue) {
return null;
}
}
<!--[endif]-->
注册一个HTTP过滤器
HTTP过滤器API(net.rim.device.api.io.http)允许应用程序向浏览器注册一个指定URL的提供者.当用户数输入指定的URL时,连接栈(connection stack)会重新路由到指定的应用程序.
注册一个HTTP 过滤器
调用HttpFilterRegistry.registerFilter().提供拦截的URL以及定义拦截行为的应用程序包名作为参数.
HttpFilterRegistry.registerFilter("content.blackberry.com", "com.rim.samples.device.httpfilterdemo.precanned"); |
启动时完成注册
创建一个类库工程,然后将它的属性设置为启动时自动运行.调用libMain()里的registerFilter().
代码实例
下面的实例包含2个文件: PackageManager.java,它在启动时注册过滤器,以及Protocol.java,它定义过滤器的行为.
<!--[endif]-->
例: HTTP 过滤器实例
/**
* PackageManager.java
* Copyright (C) 2004-2005 Research In Motion Limited. All rights reserved.
*/
package com.rim.samples.docs.httpfilterdemo;
import net.rim.device.api.io.http.HttpFilterRegistry;
/**
* This class runs on startup of the device and registers the necessary http filters.
*/
final class PackageManager
{
public static void libMain(String[] args) {
HttpFilterRegistry.registerFilter("www.blackberry.com",
"com.rim.samples.docs.httpfilterdemo.filter");
}
}
/**
* Protocol.java
* Copyright (C) 2004 Research In Motion Limited. All rights reserved.
*/
package com.rim.samples.docs.httpfilterdemo.filter;
import net.rim.device.api.io.FilterBaseInterface;
import java.io.*;
import javax.microedition.io.*;
/**
* This class implements a simple pass through mechanism that writes out the http response headers to System.out.
*/
public final class Protocol implements FilterBaseInterface, HttpConnection {
private HttpConnection _subConnection;
/**
* Defined by FilterBaseInterface.
* This method opens a filtered Http Connection.
*/
public Connection openFilter( String name, int mode, boolean timeouts )
throws IOException {
_subConnection = (HttpConnection)Connector.open("http:" + name +
";usefilter=false", mode, timeouts);
if (_subConnection != null) {
return this;
}
// Filed to open the sub connection; so let us fail too.
return null;
}
// Return a string representation of the URL for this connection.
public String getURL() {
return _subConnection.getURL();
}
// Returns the protocol name of the URL of this HttpConnection. e.g., http or https.
public String getProtocol() {
return _subConnection.getProtocol();
}
// Returns the host information of the URL of this HttpConnection.
//e.g. host name or IPv4 address.
public String getHost() {
return _subConnection.getHost();
}
// Returns the file portion of the URL of this HttpConnection.
public String getFile() {
return _subConnection.getFile();
}
/**
* Returns the ref portion of the URL of this HttpConnection.
* RFC2396 specifies the optional fragment identifier as the the text after the crosshatch (#)
* character in the URL. This information may be used by the user agent as additional
* reference information after the resource is successfully retrieved. The format and
* interpretation of the fragment identifier is dependent on the media type[RFC2046] of
* the retrieved information.
*/
public String getRef() {
return _subConnection.getRef();
}
// Returns the network port number of the URL for this HttpConnection.
public int getPort() {
return _subConnection.getPort();
}
// Returns the query portion of the URL of this HttpConnection.
// RFC2396 defines the query component as the text after the first
// question-mark (?) character in the URL.
public String getQuery() {
return _subConnection.getQuery();
}
// Get the current request method. e.g. HEAD, GET, POST The default value is GET.
public String getRequestMethod() {
return _subConnection.getRequestMethod();
}
// Set the method for the URL request, one of: GET, POST, HEAD,
//subject to protocol restrictions. The default method is GET.
public void setRequestMethod(String method) throws IOException {
_subConnection.setRequestMethod(method);
}
// Returns the value of the named general request property for this connection.
public String getRequestProperty(String key) {
return _subConnection.getRequestProperty(key);
}
// Sets the general request property. If a property with the key already exists, overwrite its value with the new value.
// Note: HTTP requires all request properties which can legally have multiple instances with the
// same key to use a comma-separated list syntax which enables multiple properties to be appended into a single property.
public void setRequestProperty(String key, String value) throws IOException {
System.out.println("Request property <key, value>: " + key + ", " + value );
_subConnection.setRequestProperty(key, value);
}
// Returns the HTTP response status code.
public int getResponseCode() throws IOException {
return _subConnection.getResponseCode();
}
// Gets the HTTP response message, if any, returned along with
//the response code from a server.
public String getResponseMessage() throws IOException {
return _subConnection.getResponseMessage();
}
// Returns the value of the expires header field.
public long getExpiration() throws IOException {
return _subConnection.getExpiration();
}
// Returns the value of the date header field.
public long getDate() throws IOException {
return _subConnection.getDate();
}
// Returns the value of the last-modified header field.
//The result is the number of milliseconds since January 1, 1970 GMT.
public long getLastModified() throws IOException {
return _subConnection.getLastModified();
}
// Returns the value of the named header field.
public String getHeaderField(String name) throws IOException
{
String value = _subConnection.getHeaderField(name);
System.out.println("Response property <key, value>: " + name + ", " + value );
return value;
}
// Returns the value of the named field parsed as a number.
public int getHeaderFieldInt(String name, int def)
throws IOException {
return _subConnection.getHeaderFieldInt(name, def);
}
// Returns the value of the named field parsed as date. The result is the
// number of milliseconds since January 1, 1970 GMT represented by the named field.
public long getHeaderFieldDate(String name, long def) throws IOException {
return _subConnection.getHeaderFieldDate(name, def);
}
// Gets a header field value by index.
public String getHeaderField(int n) throws IOException {
return _subConnection.getHeaderField(n);
}
// Gets a header field key by index.
public String getHeaderFieldKey(int n) throws IOException {
return _subConnection.getHeaderFieldKey(n);
}
// Returns the type of content that the resource connected to is providing.
public String getType() {
return _subConnection.getType();
}
// Returns a string describing the encoding of the content
//which the resource connected to is providing.
public String getEncoding() {
return _subConnection.getEncoding();
}
// Returns the length of the content which is being provided.
public long getLength() {
return _subConnection.getLength();
}
// Opens and returns an input stream for a connection.
public InputStream openInputStream() throws IOException {
return _subConnection.openInputStream();
}
// Opens and returns a data input stream for a connection.
public DataInputStream openDataInputStream() throws IOException {
return _subConnection.openDataInputStream();
}
// Opens and returns an output stream for a connection.
public OutputStream openOutputStream() throws IOException {
return _subConnection.openOutputStream();
}
// Opens and returns a data output stream for a connection.
public DataOutputStream openDataOutputStream() throws IOException {
return _subConnection.openDataOutputStream();
}
// Closes the connection.
public void close() throws IOException {
_subConnection.close();
}
Last Updated:2007年1月30日