Sunday, September 4, 2011

Android - loadDataWithBaseURL

Today I was working on a project which had numerous HTML files in various folders. These HTML files were used in a webview interface to show the UI screen. In those HTML files, a couple of icons were referenced. The reference was relative ie the HTML expected the icons to be in the same folder as the HTML. However, the folders didn't have those icon files. So I was forced to look for workaround.

The only option which didn't require any changes in the HTML files and folders was to use "loadDataWithBaseURL". It basically allows you to specify a base folder against which the relative reference would be resolved.  The following is the javadoc for "loadDataWithBaseURL"-


public void loadDataWithBaseURL (String baseUrl, String data, String mimeType, String encoding, String historyUrl)

Since: API Level 1
Load the given data into the WebView, use the provided URL as the base URL for the content. The base URL is the URL that represents the page that is loaded through this interface. As such, it is used to resolve any relative URLs. The historyUrl is used for the history entry.
Note for post 1.0. Due to the change in the WebKit, the access to asset files through "file:///android_asset/" for the sub resources is more restricted. If you provide null or empty string as baseUrl, you won't be able to access asset files. If the baseUrl is anything other than http(s)/ftp(s)/about/javascript as scheme, you can access asset files for sub resources.
Parameters
baseUrlUrl to resolve relative paths with, if null defaults to "about:blank"
dataA String of data in the given encoding.
mimeTypeThe MIMEType of the data. i.e. text/html. If null, defaults to "text/html"
encodingThe encoding of the data. i.e. utf-8, us-ascii
historyUrlURL to use as the history entry. Can be null.

A typical usecase would be something like this-


WebView webview = (WebView)this.findViewById(R.id.webview);

String html = "<html><head><title>TITLE!!!</title></head>";
html += "<body><h1>Image?</h1><img src="icon.png" /></body></html>";

webview.loadDataWithBaseURL("file:///android_res/drawable/", html, "text/html", "UTF-8", null);


Ref: http://remotedroid.net/blog/2011/01/14/referencing-drawables-in-html-in-androids-webview/

The first parameter
baseUrl -- "file:///android_res/drawable/"
specifies the path where the "icon.png" is placed. In this case it is placed in the drawable folder under res of the eclipse project.

One important thing to note over here is that, this feature is supported only in SDK 2.2 and above.

This was an elegant option for resolving the problem I mentioned above; however I was not able to use it due to the version limitation.

The following code snippets shows how I used it-


String html = getHTMLDataBuffer(url);
webView.loadDataWithBaseURL("file:///android_asset/images/", html, "text/html", "UTF-8", null);

where the function getHTMLDataBuffer  was implemented as below-


private String getHTMLDataBuffer(String url) {
InputStream htmlStream;
try {
if (Utils.isReferExternalMemory() && url.contains("sdcard")) {
String tempPath = url.substring(7, url.length());//remove file:// from the url
File file = new File(tempPath);
htmlStream = new FileInputStream(file);
}else{
String tempPath = url.replace("file:///android_asset/", "");
htmlStream = getApplicationContext().getAssets().open(tempPath);
}
Reader is = null;
try {
is = new BufferedReader(new InputStreamReader(htmlStream, "UTF8"));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

// read string from reader
final char[] buffer = new char[1024];
StringBuilder out = new StringBuilder();
int read;
do {
 read = is.read(buffer, 0, buffer.length);
 if (read>0) {
   out.append(buffer, 0, read);
 }
} while (read>=0);

return out.toString();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}



Please note that this is for illustration only and lot of niceties of coding has been ignored here.

3 comments:

  1. Hey, i'm a beginner at android development. I ran into a problem can you help me out

    http://stackoverflow.com/questions/29852907/white-screen-when-pressed-back-in-webview

    ReplyDelete
  2. Hello Ramesh, thanks for this tutorial. Please i got confused with the line of code below:
    Utils.isReferExternalMemory()
    My compiler underline it as error. please how can i solve this.

    ReplyDelete
  3. Thanks Ramesh Prasad, This tutorial helped me to load images in WebView from APIs that have relative paths of images inside HTML tags. Thanks a lot!!!

    ReplyDelete