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()方法.下面的实例使用了仅接受一个URLdisplayPage()方法.为指定一个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内容得到描绘-到你的应用程序显示.
:用来打开一个浏览器域的浏览器对话独立于BlackBerry设备上缺省的浏览器对话. 任何打开的浏览器对话则不受影响.

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().
 :HTML文件显示一个空白域,直到你调用BrowserField.finishLoading().在调用此方法前WML文件和图像可能加载 .在一个独立线程上运行finishLoading(),这样UI不会锁住.

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类型

浏览器页面APInet.rim.device.api.browser.plugin包中,它允许第三方应用程序向描绘库将它们自己注册为BlackBerry浏览器不支持的MIME类型的描绘提供者.
: 如果你试着注册一个BlackBerry浏览器已经支持的MIME类型,BrowserFieldProviderRegistry.register()方法会抛出一个异常.为得到支持的MIME类型列表,调用RenderingSession.getSupportedMimeType().

注册一个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.javaBrowserPlugin.java.BlackBerry设备启动时LoaderApp.java增加一个新支持的MIME类型. BrowserPlugin.java包含了一个扩展了BrowserContentProvider的类.


 

: BrowserPlugin.javaLoaderApp.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)会重新路由到指定的应用程序.
<!--[if !vml]--><!--[endif]-->: 当应用程序第一次访问HTTP 过滤器API,检查一个 NoClassDefFoundError.如果系统管理员通过应用程序控制限制访问HTTP过滤器API,将抛出此错误. 为获得更多信息,参看BlackBerry应用程序开发者指南 2:高级 1:基础.

注册一个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日
posted @ 2006-04-28 22:20  张太国  阅读(5372)  评论(1编辑  收藏  举报