008.WebView加載本地js圖片的方式

Android中混合式開發(fā)的過程中丙笋,加載html頁面的時(shí)候,如果該頁面加載的資源比較多央勒,比如css不见,js,公用的圖片資源等崔步,就會(huì)導(dǎo)致該頁面加載緩慢稳吮,耗費(fèi)大量的流量,這對(duì)流量限制的客戶端來說井濒,用戶體驗(yàn)非常不好灶似,所以就需要將這些資源存放在APP中列林,待APP啟動(dòng)的時(shí)候,直接從本地加載這些公用的資源酪惭。(本方法只針對(duì)html文件從網(wǎng)絡(luò)上獲认3铡)

方式一:使用loadDataBaseUrl的方式

當(dāng)從網(wǎng)絡(luò)上加載的html頁面中包含“file:///……”或者“content://packagename/……”(content://……這種需要重寫Provider)這樣的路徑時(shí),可以直接使用loadDataWithBaseURL("file:///",htmlSource,"text/html;charset=utf-8",null,null)重新加載春感,其中htmlSource為網(wǎng)頁源代碼砌创。
參考"stackoverflow" Load HTML data into WebView, referencing local images?
activity中示例代碼

     /** 
     * 加載html文件
     * @param path 文件路徑
     */
    private void loadHtml(final String path){
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    URL url = new URL(path.trim());
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setDoInput(true); //允許輸入流,即允許下載
                    conn.setDoOutput(true); //允許輸出流鲫懒,即允許上傳
                    conn.setUseCaches(false); //不使用緩沖
                    conn.setRequestMethod("GET"); //使用get請(qǐng)求
                    if (conn.getResponseCode() == 200){
                        InputStream inputStream = conn.getInputStream();
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        byte[] buffer = new byte[1024];
                        int length = -1;
                        while((length = inputStream.read(buffer))!=-1){
                            baos.write(buffer,0,length);
                            baos.flush();
                        }
                        final String htmlSource = baos.toString();
                        runOnUiThread(new Runnable(){

                            @Override
                            public void run() {
                                //重寫
                                mWebView.loadDataWithBaseURL("file:///",htmlSource,"text/html;charset=utf-8",null,null);
                            }
                        });

                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();

    }


H5示例代碼(該h5頁面是放在服務(wù)器上面的)


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>H5調(diào)用Native“獲取地理位置”與“拍照上傳“的功能</title>
    <link  rel="stylesheet">
    <!--放在assets目錄下面的css.css文件-->
    <link href="file:///android_asset/css.css" rel="stylesheet">
    
</head>
<body>
<!-- 用css設(shè)置樣式嫩实,看通過這種方式是否能加載本地assets目錄中的css文件 -->
<h4 class="text-left">H5調(diào)用安卓“拍照上傳“的功能:</h4>
<!-- 放在SDCARD中的圖片 -->
<img src="file:///storage/emulated/0/newCrop.jpg" alt="" class="img-responsive img-thumbnail">
<!-- 放在SDCARD中的圖片  packagename為包名-->
<img src="content://packagename/storage/emulated/0/newCrop.jpg" alt="本地圖片"/>
</body>
</html>

css文件內(nèi)容如下

.text-left{background-color:#f00}
IMG_20161214_163615.jpg

正常結(jié)果如上所示。

方式二:使用ContentProvider的方式

使用content://方式訪問本地資源的時(shí)候窥岩,需要重寫ContentProvider,簡(jiǎn)單代碼如下:

public class LoadPicProvider extends ContentProvider {

    @Override
    public boolean onCreate() {
        return false;
    }

    @Nullable
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        return null;
    }

    @Nullable
    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }

    @Nullable
    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
        URI filePath = URI.create( "file://" + uri.getPath() );
        File file = new File( filePath );
        ParcelFileDescriptor parcel = null;
        try {
            parcel = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return parcel;
    }

}

然后在mainfest中進(jìn)行注冊(cè)

<provider    android:authorities="packagename"    android:name=".LoadPicProvider">
</provider>

方式三:使用Base64的方式

參考鏈接 StackOverflow Embedding Base64 Images
示例代碼

ByteArrayOutputStream out = new ByteArrayOutputStream();
//TODO 文件讀取需要線程操作
FileInputStream fis = new FileInputStream(imageCropUri.toString());
byte buff[] = new byte[1024];
int length = -1;
while((length = fis.read(buff))!= -1){
    out.write(buff,0,length);
    out.flush();
}
String fileBase64 = Base64.encodeToString(out.toByteArray(),Base64.NO_WRAP);
//將當(dāng)前的fileBase64傳到h5頁面中甲献,并設(shè)置到img上

js代碼

<img alt="Embedded Image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA..." />

方式四:使用shouldInterceptRequest進(jìn)行文件資源的攔截

從API 11(Android 3.0)開始引入這個(gè)方法。shouldInterceptRequest這個(gè)回調(diào)可以通知主程序WebView處理的資源(css,js,image等)請(qǐng)求颂翼,并允許主程序進(jìn)行處理后返回?cái)?shù)據(jù)晃洒。如果主程序返回的數(shù)據(jù)為null,WebView會(huì)自行請(qǐng)求網(wǎng)絡(luò)加載資源朦乏,否則使用主程序提供的數(shù)據(jù)球及。注意這個(gè)回調(diào)發(fā)生在非UI線程中,所以進(jìn)行UI系統(tǒng)相關(guān)的操作是不可以的。
shouldInterceptRequest有兩種重載集歇。

  • public WebResourceResponse shouldInterceptRequest (WebView view, String url) 從API 11開始引入桶略,API 21棄用
  • public WebResourceResponse shouldInterceptRequest (WebView view, WebResourceRequest request) 從API 21開始引入
    所以在使用的時(shí)候语淘,最好兩者都要進(jìn)行重寫诲宇。
    測(cè)試代碼如下
mWebView.setWebViewClient(new WebViewClient() {
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        String key = "http://localhost/";
        WebResourceResponse response = null;
        if (url.contains(key)) {
            try {
                String imgPath = url.replace(key,"");
                imgPath = Uri.parse(imgPath).getPath();
                InputStream localCopy = new FileInputStream(imgPath);
                //當(dāng)前只針對(duì)圖片
                response = new WebResourceResponse("image/png", "UTF-8", localCopy);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return response;
    }
});

注意:當(dāng)從本地相冊(cè)拍照完成后,圖片的uri可能是這樣的file:///storage/emulated/0/newCrop.jpg惶翻,如果這個(gè)url回調(diào)給 js是顯示不出來的姑蓝。因?yàn)閣ebview根本不會(huì)自動(dòng)加載。所以這個(gè)時(shí)候可以考慮在當(dāng)前地址上面添加http://……這樣這個(gè)url設(shè)置完成之后吕粗,才能夠正常的發(fā)出纺荧。
例如我得拍照產(chǎn)生的image的uri如下

<img src="file:///storage/emulated/0/newCrop.jpg" alt="" class="img-responsive img-thumbnail">

用攔截的方式顯示不出來,然后后我改為

<img src="http://localhost/file:///storage/emulated/0/newCrop.jpg" alt="" class="img-responsive img-thumbnail">

這樣在http請(qǐng)求發(fā)生的時(shí)候颅筋,會(huì)被shouldInterceptRequest方法攔截
參看鏈接:
Webview加載本地圖片的方案對(duì)比

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末宙暇,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子议泵,更是在濱河造成了極大的恐慌占贫,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件先口,死亡現(xiàn)場(chǎng)離奇詭異型奥,居然都是意外死亡瞳收,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門厢汹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來螟深,“玉大人,你說我怎么就攤上這事烫葬〗缁。” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵搭综,是天一觀的道長(zhǎng)夹纫。 經(jīng)常有香客問我,道長(zhǎng)设凹,這世上最難降的妖魔是什么舰讹? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮闪朱,結(jié)果婚禮上月匣,老公的妹妹穿的比我還像新娘。我一直安慰自己奋姿,他們只是感情好锄开,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著称诗,像睡著了一般萍悴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上寓免,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天癣诱,我揣著相機(jī)與錄音,去河邊找鬼袜香。 笑死撕予,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蜈首。 我是一名探鬼主播实抡,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼欢策!你這毒婦竟也來了吆寨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤踩寇,失蹤者是張志新(化名)和其女友劉穎啄清,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姑荷,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盒延,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年缩擂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片添寺。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡胯盯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出计露,到底是詐尸還是另有隱情博脑,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布票罐,位于F島的核電站叉趣,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏该押。R本人自食惡果不足惜疗杉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蚕礼。 院中可真熱鬧烟具,春花似錦、人聲如沸奠蹬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽囤躁。三九已至冀痕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間狸演,已是汗流浹背言蛇。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留严沥,地道東北人猜极。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像消玄,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子丢胚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理翩瓜,服務(wù)發(fā)現(xiàn),斷路器携龟,智...
    卡卡羅2017閱讀 134,601評(píng)論 18 139
  • 0. 前言 前面有被用戶投訴 APP 流量消耗厲害: 于是乎考慮了流量方面的問題兔跌。暫時(shí) APP 中涉及流量的幾個(gè)方...
    zyl06閱讀 23,923評(píng)論 5 62
  • 轉(zhuǎn)載請(qǐng)注明出處: Webview秒開框架VasSonic源碼分析(一) Webview秒開框架VasSonic源碼...
    陳文超happylion閱讀 8,123評(píng)論 2 16
  • Tips 由于WebView的用法實(shí)在太多,如果您只是想查詢某個(gè)功能的使用——建議Ctrl+F(Commad+F)...
    BugDev閱讀 7,737評(píng)論 11 109
  • 時(shí)間:早晨6:10 大概在6個(gè)小時(shí)前峡蟋,我做了一件值得一提的事情:刪除玩了多年的游戲“英雄聯(lián)盟”坟桅。 起因是打一場(chǎng)排位...
    死宅程序員閱讀 222評(píng)論 0 1