转载:http://shareandopen.tumblr.com/post/24470630918/android-open-mult-lang-html-file-from-raw
一般来说读取html file可以从asset下手,之前也有介绍过相关的范例,如在自定义对话框中,开启html档案、于ICS开启asset文件夹下的html档案要注意的问题。
但假如要读取多国语系的html档案呢?因为asset是个单纯的档案文件夹,程序并不会依据所选择的语系,切换到对应的子文件夹。如此一来不就变成每新增一个语系支持,程序代码就要修改如果是繁体中文切换到asset/zh_tw、如果是日文切换到asset/js。这样子对于程序代码来说会变得又臭又长,又要判断。相当费功。
WebView web = (WebView) this.findViewById(R.id.web); web.loadUrl("file:///android_asset/index.html");
使用webview加载本地assets目录下的html文件:web.loadUrl("file:///android_asset/index.html") ;注意这个路径的写法,如果按照file:///assets/来写,反而找不到
所以我于是想到了android res的应用【locale】
The language is defined by a two-letter ISO639-1 language code, optionally followed by a two letter ISO 3166-1-alpha-2region code (preceded by lowercase “r”).
ex: res/layout-zh-rTW
有了android resource支持多国语系的概念后,因为需求为希望可以利用res多国语系支持的特性来读取不同语言下的html档案,所以我必须分多种语系来存放html档案,所以选择了raw
Arbitrary files to save in their raw form.To open these resources with a raw InputStream, callResources.openRawResource() with the resource ID, which is R.raw.filename.
到了这边,已经有了程序的雏型了,所以我们先准备好两份html档案,一个是英文,一个是繁体中文,分别放在raw和raw/zh-rTW
再来先来设计一个简单的UI,点击按钮后,读取raw下面index.html档案,所以layout上要有一个button和webview。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/btnOpenFile" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="open html file" /> <WebView android:id="@+id/wv_raw_html" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout>
设定完Layout后,就可以开始写程序了吗?等等哦!webview要读取档案的方式有许多种,像是loadData, loadDataWithBaseURL, loadUrl,那该怎么选择了呢?首先因为我们要读取raw的html,根据前文的引述有说到读取raw的档案要用到InputStream来取得Resource。所以以往读取asset的loadUrl就不适用了。所以只剩下loadData,loadDataWithBaseURL可以选择了。那这两者之间有何差异呢?来看看原文的说明,觉来看看loadData
public void loadData (String data, StringmimeType, String encoding)
Since: API Level 1
Load the given data into the WebView usinga ‘data’ scheme URL.
Note that JavaScript’s same origin policymeans that script running in a page loaded using this method will be unable toaccess content loaded using any scheme other than ‘data’, including ‘http(s)’.To avoid this restriction, use loadDataWithBaseURL() with an appropriate baseURL.
If the value of the encoding parameter is‘base64’, then the data must be encoded as base64. Otherwise, the data must useASCII encoding for octets inside the range of safe URL characters and use thestandard %xx hex encoding of URLs for octets outside that range. For example,‘#’, ‘%’, ‘', ‘?’ should be replaced by %23, %25, %27, %3f respectively.
The ‘data’ scheme URL formed by this methoduses the default US-ASCII charset. If you need need to set a different charset,you should form a ‘data’ scheme URL which explicitly specifies a charsetparameter in the mediatype portion of the URL and call loadUrl(String)instead.Note that the charset obtained from the mediatype portion of a data URL alwaysoverrides that specified in the HTML or XML document itself.
其中内容的重点是说明有些特殊符号要避开
再来看看loadDataWithBaseURL的说明
public void loadDataWithBaseURL (StringbaseUrl, String data, String mimeType, String encoding, String historyUrl)
Since: API Level 1
Load the given data into the WebView, usingbaseUrl as the base URL for the content. The base URL is used both to resolverelative URLs and when applying JavaScript’s same origin policy. The historyUrlis used for the history entry.
Note that content specified in this way canaccess local device files (via ‘file’ scheme URLs) only if baseUrl specifies ascheme other than ‘http’, ‘https’, ‘ftp’, ‘ftps’, ‘about’ or ‘javascript’.
If the base URL uses the data scheme, thismethod is equivalent to calling loadData() and the historyUrl is ignored.
Parameters
baseUrlURL to use as the page’s base URL.If null defaults to ‘about:blank’dataA String of data in the givenencoding.mimeTypeThe MIMEType of the data, e.g. ‘text/html’. If null, defaultsto ‘text/html’.encodingThe encoding of the data.historyUrlURL to use as thehistory entry, if null defaults to ‘about:blank’.
而loadDataWithBaseURL主要要注意的地方就和methods名称一样BaseURL,这个地方很重要,这关系于如果你的html档案当中有使用src卷标插入图片,而图片的设定的位置非绝对位置而是相对位置的话。如果BaseURL设定错的话,html里的图片就无法显示了。另外loadDataWithBaseURL也没有特殊符号的限制。所以两者比较下来看来loadDataWithBaseURL比loadData来的方便使用。那就选定使用loadDataWithBaseURL来读取raw的html档案吧。
网友最关心的还是程序代码怎么写吧?但知道解决问题的根本后,在写程序代码上应该会更显得得心应手才是,讲了这么长,废话不多说,来看程序代码啰!
package com.welee.rawhtml; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.webkit.WebView; import android.widget.Button; public class ReadRawHtmlFileActivity extends Activity { WebView wvHtml; Button btnOpenFile; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btnOpenFile = (Button) findViewById(R.id.btnOpenFile); wvHtml = (WebView) findViewById(R.id.wv_raw_html); btnOpenFile.setOnClickListener(btnReadRawFileOnClickListener); } /** * 從raw 讀取 raw file,以支援多國語系 */ private String readTextFromResource(int resourceID) { InputStream raw = getResources().openRawResource(resourceID); ByteArrayOutputStream stream = new ByteArrayOutputStream(); int i; try { i = raw.read(); while (i != -1) { stream.write(i); i = raw.read(); } raw.close(); } catch (IOException e) { e.printStackTrace(); } return stream.toString(); } /** * read file from raw file....... */ private Button.OnClickListener btnReadRawFileOnClickListener = new Button.OnClickListener() { @Override public void onClick(View v) { // 指定BaseURL為file:///android_res/raw/,如此一來,html的圖檔,才能正確顯示 wvHtml.loadDataWithBaseURL("file:///android_res/raw/", readTextFromResource(R.raw.index), "text/html", "UTF-8", null); } }; }
wvHtml.loadDataWithBaseURL(
"file:///android_res/raw/"
, readTextFromResource(R.raw.index),
"text/html"
,
"UTF-8"
,
null
);
这段代码可以直接使用:wvHtml.loadUrl("file:///android_res/raw/index.html"); 并且不需要readTextFromResource()这个方法