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内容得到描绘-到你的应用程序显示.注:用来打开一个浏览器域的浏览器对话独立于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类型
浏览器页面API在net.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.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 过滤器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日
 
                    
                 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号