IV.Hỗ Trợ Các Kiểu MIME Bổ Xung

Để thiết lập các kiểu MIME bổ xung cho Browser, bạn sử dụng gói net.rim.device.api.browser.plugin, cho phép các ứng dụng của bên thứ 3 đăng ký chúng với thư viện rendering như là một provider rendering cho các kiểu MIME không được browser trên thiết bị Blackberry hỗ trợ.

Lưu ý Phương thức BrowserFieldProviderRegistry.registry() sẽ ném ra một exception nếu bạn cố gắng đăng ký một kiểu MIME mà đã được thiết bị Blackberry hỗ trợ. Để nhận biết được danh sách các kiểu MIME được thiết bị Blackberry hỗ trợ, gọi phương thức RenderingSession.getSupportMimeType().

1.Đăng ký provider rendering cho một kiểu MIME

Để hỗ trợ các kiểu MIME bổ xung, kế thừa lớp abstract BrowserContentProvider. Để xác định các đặc tính hiển thị như: không có srollbar hay full màn hình, bạn thực thi giao diện BrowserPageContext. Thư viện rendering gọi phương thức BrowserContentProvider.accept() và BrowserContentProvider.getSupportedMimeTypes() để xác định các kiểu MIME cho provider rendering.

1.1.List danh sách các kiểu MIME chấp nhận

Cài đặt phương thức getAccept() và getSupportedMimeTypes() để list ra danh sách các các kiểu MIME mà provider có thể chấp nhận như là một tập hợp các tùy chọn rendering. Phương thức getAccept() xem xét các tùy chọn rendering được thiết lập.

Ví dụ 7:

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;

}

1.2.Xác định các đặc tính hiển thị

Thực thi giao diện BrowserPageContext để xác định các đặc tính hiển thị. Nếu bạn không thực thi giao diện này, các giá trị mặc định sẽ được sử dụng.

Ví dụ 8:

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;

}

1.3.Nhận một field để trình diễn nội dung

Cài đặt phương thức getBrowserContent().

Ví dụ 9:

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;

}

1.4.Đăng kí khi thiết bị Blackberry bắt đầu

Tạo một project library và thiết lập các thuộc tính của nó để auto-run khi bắt đầu. Trong phương thức libMain(String[] args) bạn cài đặt như sau:

public static void libMain( String[] args ) {

BrowserContentProviderRegistry converterRegistry =

BrowserContentProviderRegistry.getInstance();

if (converterRegistry != null) {

converterRegistry.register(new BrowserPlugin());

}

}

2.Ví dụ:

Ví dụ này gồm 3 file: BrowserFieldSampleApplication.java, Utilities.java và SecondaryResourceFetchThread.

package blog.mobilesprogramming;

import java.io.IOException;

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.system.Application;

import net.rim.device.api.ui.*;

import net.rim.device.api.ui.component.Status;

import net.rim.device.api.ui.container.MainScreen;

/**

*

*/

final public class BrowserFieldSampleApplication extends UiApplication implements RenderingApplication {

private static final String REFERER = “referer”;

private RenderingSession _renderingSession;

private MainScreen _mainScreen;

private HttpConnection  _currentConnection;

/***************************************************************************

* Main.

**************************************************************************/

public static void main(String[] args) {

BrowserFieldSampleApplication app = new BrowserFieldSampleApplication();

app.enterEventDispatcher();

}

private BrowserFieldSampleApplication() {

_mainScreen = new MainScreen();

pushScreen(_mainScreen);

_renderingSession = RenderingSession.getNewInstance();

// enable javascript

//_renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.JAVASCRIPT_ENABLED, true);

PrimaryResourceFetchThread thread = new PrimaryResourceFetchThread(“http://www.google.com”, null, null, null, this);

thread.start();

}

public void processConnection(HttpConnection connection, Event e) {

// cancel previous request

if (_currentConnection != null) {

try {

_currentConnection.close();

} catch (IOException e1) {

}

}

_currentConnection = connection;

BrowserContent browserContent = null;

try {

browserContent = _renderingSession.getBrowserContent(connection, this, e);

if (browserContent != null) {

Field field = browserContent.getDisplayableContent();

if (field != null) {

synchronized (Application.getEventLock()) {

_mainScreen.deleteAll();

_mainScreen.add(field);

}

}

browserContent.finishLoading();

}

} catch (RenderingException re) {

} finally {

SecondaryResourceFetchThread.doneAddingImages();

}

}

/**

* @see net.rim.device.api.browser.RenderingApplication#eventOccurred(net.rim.device.api.browser.Event)

*/

public Object eventOccurred(Event event) {

int eventId = event.getUID();

switch (eventId) {

case Event.EVENT_URL_REQUESTED : {

UrlRequestedEvent urlRequestedEvent = (UrlRequestedEvent) event;

String absoluteUrl = urlRequestedEvent.getURL();

HttpConnection conn = null;

PrimaryResourceFetchThread thread = new PrimaryResourceFetchThread(urlRequestedEvent.getURL(),

urlRequestedEvent.getHeaders(),

urlRequestedEvent.getPostData(),

event, this);

thread.start();

break;

} case Event.EVENT_BROWSER_CONTENT_CHANGED: {

// browser field title might have changed update title

BrowserContentChangedEvent browserContentChangedEvent = (BrowserContentChangedEvent) event;

if (browserContentChangedEvent.getSource() instanceof BrowserContent) {

BrowserContent browserField = (BrowserContent) browserContentChangedEvent.getSource();

String newTitle = browserField.getTitle();

if (newTitle != null) {

_mainScreen.setTitle(newTitle);

}

}

break;

} case Event.EVENT_REDIRECT : {

RedirectEvent e = (RedirectEvent) event;

String referrer = e.getSourceURL();

switch (e.getType()) {

case RedirectEvent.TYPE_SINGLE_FRAME_REDIRECT :

// show redirect message

Application.getApplication().invokeAndWait(new Runnable() {

public void run() {

Status.show(“You are being redirected to a different page…”);

}

});

break;

case RedirectEvent.TYPE_JAVASCRIPT :

break;

case RedirectEvent.TYPE_META :

// MSIE and Mozilla don’t send a Referer for META Refresh.

referrer = null;

break;

case RedirectEvent.TYPE_300_REDIRECT :

// MSIE, Mozilla, and Opera all send the original

// request’s Referer as the Referer for the new

// request.

Object eventSource = e.getSource();

if (eventSource instanceof HttpConnection) {

referrer = ((HttpConnection)eventSource).getRequestProperty(REFERER);

}

break;

}

HttpHeaders requestHeaders = new HttpHeaders();

requestHeaders.setProperty(REFERER, referrer);

PrimaryResourceFetchThread thread = new PrimaryResourceFetchThread(e.getLocation(), requestHeaders,null, event, this);

thread.start();

break;

} case Event.EVENT_CLOSE :

// TODO: 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_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;

}

/**

* @see net.rim.device.api.browser.RenderingApplication#getAvailableHeight(net.rim.device.api.browser.BrowserContent)

*/

public int getAvailableHeight(BrowserContent browserField) {

// field has full screen

return Graphics.getScreenHeight();

}

/**

* @see net.rim.device.api.browser.RenderingApplication#getAvailableWidth(net.rim.device.api.browser.BrowserContent)

*/

public int getAvailableWidth(BrowserContent browserField) {

// field has full screen

return Graphics.getScreenWidth();

}

/**

* @see net.rim.device.api.browser.RenderingApplication#getHistoryPosition(net.rim.device.api.browser.BrowserContent)

*/

public int getHistoryPosition(BrowserContent browserField) {

// no history support

return 0;

}

/**

* @see net.rim.device.api.browser.RenderingApplication#getHTTPCookie(java.lang.String)

*/

public String getHTTPCookie(String url) {

// no cookie support

return null;

}

/**

* @see net.rim.device.api.browser.RenderingApplication#getResource(net.rim.device.api.browser.RequestedResource,

*      net.rim.device.api.browser.BrowserContent)

*/

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 we must return the connection

if (referrer == null) {

HttpConnection connection = Utilities.makeConnection(resource.getUrl(), resource.getRequestHeaders(), null);

return connection;

} else {

// if referrer is provided we can set up the connection on a separate thread

SecondaryResourceFetchThread.enqueue(resource, referrer);

}

return null;

}

/**

* @see net.rim.device.api.browser.RenderingApplication#invokeRunnable(java.lang.Runnable)

*/

public void invokeRunnable(Runnable runnable) {

(new Thread(runnable)).run();

}

}

class PrimaryResourceFetchThread extends Thread {

private BrowserFieldSampleApplication _application;

private Event _event;

private byte[] _postData;

private HttpHeaders _requestHeaders;

private String _url;

PrimaryResourceFetchThread(String url, HttpHeaders requestHeaders, byte[] postData,

Event event, BrowserFieldSampleApplication application) {

_url = url;

_requestHeaders = requestHeaders;

_postData = postData;

_application = application;

_event = event;

}

public void run() {

HttpConnection connection = Utilities.makeConnection(_url, _requestHeaders, _postData);

_application.processConnection(connection, _event);

}

}

package blog.mobilesprogramming;

import java.util.Vector;

import javax.microedition.io.HttpConnection;

import net.rim.device.api.browser.field.BrowserContent;

import net.rim.device.api.browser.field.RequestedResource;

/**

*

*/

class SecondaryResourceFetchThread extends Thread {

/**

* Callback browser field

*/

private BrowserContent    _browserField;

/**

* Images to retrieve

*/

private Vector            _imageQueue;

/**

* True is all images have been enqueued

*/

private boolean _done;

/**

* Sync object

*/

private static Object     _syncObject = new Object();

/**

* Secondary thread

*/

private static SecondaryResourceFetchThread _currentThread;

/**

* Enqueues secondary resource for a browser field.

*

* @param resource – resource to retrieve

* @param referrer – call back browsr field

*/

public static void enqueue(RequestedResource resource, BrowserContent referrer) {

if (resource == null) {

return;

}

synchronized( _syncObject ) {

// create new thread

if (_currentThread == null) {

_currentThread = new SecondaryResourceFetchThread();

_currentThread.start();

} else {

// if thread alread is running, check that we are adding images for the same browser field

if (referrer != _currentThread._browserField) {

synchronized( _currentThread._imageQueue) {

// if the request is for a different browser field,

// clear old elements

_currentThread._imageQueue.removeAllElements();

}

}

}

synchronized( _currentThread._imageQueue) {

_currentThread._imageQueue.addElement(resource);

}

_currentThread._browserField = referrer;

}

}

/**

* Constructor

*

*/

private SecondaryResourceFetchThread() {

_imageQueue = new Vector();

}

/**

* Indicate that all images have been enqueued for this browser field

*/

public static void doneAddingImages() {

synchronized( _syncObject ) {

if (_currentThread != null) {

_currentThread._done = true;

}

}

}

public void run() {

while (true) {

if (_done) {

// check if we are done requesting images

synchronized( _syncObject ) {

synchronized( _imageQueue ) {

if (_imageQueue.size() == 0) {

_currentThread = null;

break;

}

}

}

}

RequestedResource resource = null;

// request next image

synchronized( _imageQueue ) {

if (_imageQueue.size() > 0) {

resource = (RequestedResource)_imageQueue.elementAt(0);

_imageQueue.removeElementAt(0);

}

}

if (resource != null) {

HttpConnection connection = Utilities.makeConnection(resource.getUrl(), resource.getRequestHeaders(), null);

resource.setHttpConnection(connection);

// signal to the browser field that resource is ready

if (_browserField != null) {

_browserField.resourceReady(resource);

}

}

}

}

}

package blog.mobilesprogramming;

import java.io.IOException;

import java.io.OutputStream;

import javax.microedition.io.Connector;

import javax.microedition.io.HttpConnection;

import net.rim.device.api.io.http.HttpHeaders;

import net.rim.device.api.io.http.HttpProtocolConstants;

import net.rim.device.api.util.StringUtilities;

/**

*

*/

public class Utilities {

public static HttpConnection makeConnection(String url, HttpHeaders requestHeaders, byte[] postData) {

HttpConnection conn = null;

OutputStream out = null;

try {

conn = (HttpConnection) Connector.open(url);

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 && StringUtilities.startsWithIgnoreCase(referer, “https:”) && !StringUtilities.startsWithIgnoreCase(url, “https:”)) {

sendReferrer = false;

}

int size = requestHeaders.size();

for (int i = 0; i < size;) {

String header = requestHeaders.getPropertyKey(i);

// remove referer header if needed

if ( !sendReferrer && header.equals(“referer”)) {

requestHeaders.removeProperty(i);

–size;

continue;

}

String value = requestHeaders.getPropertyValue( i++ );

if (value != null) {

conn.setRequestProperty( header, value);

}

}

}

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);

}

} catch (IOException e1) {

} finally {

if (out != null) {

try {

out.close();

} catch (IOException e2) {

}

}

}

return conn;

}

}

Các bài liên quan:
Blackberry Browser API – Phần 1