I am creating a Blackberry application to display a full-screen web view of a specific site. I have a working browser window that displays correctly, but moving from page to page is slower than with my own browser. It looks like there is no built-in cache in the browser field, which slows down loading time. When I add the following code to manage the cache, the site is no longer properly displayed.
BrowserFieldScreen.java:
import net.rim.device.api.browser.field2.*; import net.rim.device.api.script.ScriptEngine; import net.rim.device.api.system.*; import net.rim.device.api.ui.*; import net.rim.device.api.ui.component.*; import net.rim.device.api.ui.container.*; import org.w3c.dom.Document; class BrowserFieldScreen extends MainScreen { BrowserField browserField; LoadingScreen load = new LoadingScreen();; public BrowserFieldScreen() { browserField = new BrowserField(); browserField.getConfig().setProperty( BrowserFieldConfig.JAVASCRIPT_ENABLED, Boolean.TRUE); browserField.getConfig().setProperty( BrowserFieldConfig.NAVIGATION_MODE, BrowserFieldConfig.NAVIGATION_MODE_POINTER); browserField.getConfig().setProperty( BrowserFieldConfig.CONTROLLER, new CacheProtocolController(browserField)); browserField.requestContent("http://www.stackoverflow.com"); add(browserField); } }
CacheProtocolController.java:
import javax.microedition.io.HttpConnection; import javax.microedition.io.InputConnection; import net.rim.device.api.browser.field2.BrowserField; import net.rim.device.api.browser.field2.BrowserFieldRequest; import net.rim.device.api.browser.field2.ProtocolController; public class CacheProtocolController extends ProtocolController{ // The BrowserField instance private BrowserField browserField; // CacheManager will take care of cached resources private CacheManager cacheManager; public CacheProtocolController(BrowserField browserField) { super(browserField); this.browserField = browserField; } private CacheManager getCacheManager() { if ( cacheManager == null ) { cacheManager = new CacheManagerImpl(); } return cacheManager; } /** * Handle navigation requests (eg, link clicks) */ public void handleNavigationRequest(BrowserFieldRequest request) throws Exception { InputConnection ic = handleResourceRequest(request); browserField.displayContent(ic, request.getURL()); } /** * Handle resource request * (eg, images, external css/javascript resources) */ public InputConnection handleResourceRequest(BrowserFieldRequest request) throws Exception { // if requested resource is cacheable (eg, an "http" resource), // use the cache if (getCacheManager() != null && getCacheManager().isRequestCacheable(request)) { InputConnection ic = null; // if requested resource is cached, retrieve it from cache if (getCacheManager().hasCache(request.getURL()) && !getCacheManager().hasCacheExpired(request.getURL())) { ic = getCacheManager().getCache(request.getURL()); } // if requested resource is not cached yet, cache it else { ic = super.handleResourceRequest(request); if (ic instanceof HttpConnection) { HttpConnection response = (HttpConnection) ic; if (getCacheManager().isResponseCacheable(response)) { ic = getCacheManager().createCache(request.getURL(), response); } } } return ic; } // if requested resource is not cacheable, load it as usual return super.handleResourceRequest(request); } }
CacheManager.java:
import javax.microedition.io.HttpConnection; import javax.microedition.io.InputConnection; import net.rim.device.api.browser.field2.BrowserFieldRequest; public interface CacheManager { public boolean isRequestCacheable(BrowserFieldRequest request); public boolean isResponseCacheable(HttpConnection response); public boolean hasCache(String url); public boolean hasCacheExpired(String url); public InputConnection getCache(String url); public InputConnection createCache(String url, HttpConnection response); public void clearCache(String url); }
CacheManagerImpl.java:
import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.Hashtable; import javax.microedition.io.HttpConnection; import javax.microedition.io.InputConnection; import net.rim.device.api.browser.field2.BrowserFieldRequest; import net.rim.device.api.browser.field2.BrowserFieldResponse; import net.rim.device.api.io.http.HttpHeaders; public class CacheManagerImpl implements CacheManager { private static final int MAX_STANDARD_CACHE_AGE = 2592000; private Hashtable cacheTable; public CacheManagerImpl() { cacheTable = new Hashtable(); } public boolean isRequestCacheable(BrowserFieldRequest request) {
CacheItem.java:
import net.rim.device.api.io.http.HttpHeaders; public class CacheItem { private String url; private long expires; private byte[] data; private HttpHeaders httpHeaders; public CacheItem(String url, long expires, byte[] data, HttpHeaders httpHeaders) { this.url = url; this.expires = expires; this.data = data; this.httpHeaders = httpHeaders; } public String getUrl() { return url; } public long getExpires() { return expires; } public byte[] getData() { return data; } public HttpHeaders getHttpHeaders() { return httpHeaders; } }
Any help that could be directed at this would be greatly appreciated. It really puzzled me. Thank.
UPDATE: Caching seems to work only at a certain level of Blackberry libraries. I added logic to check the current Software level and enable caching if it is supported by the current device software level. This gives me a good job, but I would still like to know if there is a better way for caching to work with all devices.
UPDATE 2 Based on the comments: the site is no longer properly displayed for the site, without displaying the correct layouts, images and text. This basically gives a white background with links and displaying text as a bulleted list, all formatting is removed.