WebView重定向的判斷

前言

不知道大家有沒(méi)有遇到過(guò)這種需求止吁,用WebView加載某個(gè)網(wǎng)頁(yè)佳窑,之后點(diǎn)擊網(wǎng)頁(yè)上面的鏈接淋硝,跳轉(zhuǎn)到另一個(gè)頁(yè)面或者打開(kāi)瀏覽器雹熬。特別是當(dāng)WebView只是某個(gè)頁(yè)面的一部分的時(shí)候,這種需求也是很合理的奖地。

遇到問(wèn)題

上面的需求很容易實(shí)現(xiàn):

  • 用WebView加載某個(gè)網(wǎng)頁(yè)
webView.loadUrl(url);
  • 點(diǎn)擊WebView的某個(gè)鏈接跳轉(zhuǎn)下一個(gè)頁(yè)面
webView.setWebViewClient(new WebViewClient(){
            @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
                Uri uri = Uri.parse(url);
                Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                try {
                    view.getContext().startActivity(intent);
                } catch (ActivityNotFoundException e) {
                    e.printStackTrace();
                }
                return true;
        }
});

但是這樣做了之后會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題橄唬,如果webView第一次加載的url重定向到了另一個(gè)地址,此時(shí)也會(huì)走shouldOverrideUrlLoading的回調(diào)参歹。這樣一來(lái)仰楚,出現(xiàn)的現(xiàn)象就是WebView是空的,直接打開(kāi)了瀏覽器犬庇。

解決問(wèn)題

要解決這個(gè)問(wèn)題僧界,很容易想到的解決方案是找找WebView有沒(méi)有對(duì)重定向的判斷方法,如果有的話臭挽,我們就可以對(duì)重定向的回調(diào)另外處理捂襟。
很不幸,WebView并沒(méi)有提供相應(yīng)的方法欢峰。是不是就沒(méi)辦法處理了呢葬荷?當(dāng)然不是。

解決方案一

這個(gè)方案是一個(gè)CSDN一個(gè)博主提供的:

WebView有一個(gè)getHitTestResult():返回的是一個(gè)HitTestResult纽帖,一般會(huì)根據(jù)打開(kāi)的鏈接的類(lèi)型宠漩,返回一個(gè)extra的信息,如果打開(kāi)鏈接不是一個(gè)url懊直,或者打開(kāi)的鏈接是JavaScript的url扒吁,他的類(lèi)型是UNKNOWN_TYPE,這個(gè)url就會(huì)通過(guò)requestFocusNodeHref(Message)異步重定向室囊。返回的extra為null雕崩,或者沒(méi)有返回extra。根據(jù)此方法的返回值融撞,判斷是否為null盼铁,可以用于解決網(wǎng)頁(yè)重定向。

詳見(jiàn)該博主原文懦铺,整理成代碼就是:

webView.setWebViewClient(new WebViewClient(){
            @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            //判斷重定向的方式一
            WebView.HitTestResult hitTestResult = view.getHitTestResult();
            if(hitTestResult == null) {
                return false;
            }
            if(hitTestResult.getType() == WebView.HitTestResult.UNKNOWN_TYPE) {
                return false;
            }

            Uri uri = Uri.parse(url);
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            try {
                view.getContext().startActivity(intent);
            } catch (ActivityNotFoundException e) {
                e.printStackTrace();
            }
            return true;
        }
});

該方案有個(gè)缺陷是捉貌,如果遇到的需求是前言描述的那樣,二正好點(diǎn)擊的鏈接發(fā)生了重定向,就不會(huì)在另一個(gè)頁(yè)面打開(kāi)趁窃,而是直接在當(dāng)前的WebView里了牧挣。
為了避免該缺陷,產(chǎn)生了方案二醒陆。

解決方案二

WebView在加載一個(gè)頁(yè)面開(kāi)始的時(shí)候會(huì)回調(diào)onPageStarted方法瀑构,在該頁(yè)面加載完成之后會(huì)回調(diào)onPageFinished方法。而如果該鏈接發(fā)生了重定向刨摩,回調(diào)shouldOverrideUrlLoading會(huì)在回調(diào)onPageFinished之前寺晌。
有了這個(gè)前提,我們就可以加一個(gè)mIsPageLoading的標(biāo)記澡刹,在onPageStarted回調(diào)的時(shí)候置為true呻征,在onPageFinished回調(diào)的時(shí)候置為false。在shouldOverrideUrlLoading里面就可以判斷該標(biāo)記罢浇,如果為true陆赋,則表示該回調(diào)是重定向,否則直接打開(kāi)瀏覽器嚷闭。代碼如下:

private boolean mIsPageLoading;
//代碼省略
webView.setWebViewClient(new WebViewClient(){
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            //判斷重定向的方式二
            if(mIsPageLoading) {
                return false;
            }

            if(url != null && url.startsWith("http")) {
                webView.loadUrl(url);
                return true;
            } else {
                Uri uri = Uri.parse(url);
                Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                try {
                    view.getContext().startActivity(intent);
                } catch (ActivityNotFoundException e) {
                    e.printStackTrace();
                }
                return true;
            }
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            mIsPageLoading= true;
            Log.d(TAG, "onPageStarted");
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            mIsPageLoading= false;
            Log.d(TAG, "onPageFinished");
        }
});

沒(méi)有十全十美的方案攒岛,該方案也會(huì)產(chǎn)生另一個(gè)問(wèn)題:當(dāng)頁(yè)面沒(méi)有全部加載完之前,加載出來(lái)的部分頁(yè)面的鏈接也是可以點(diǎn)擊的胞锰。這樣一來(lái)在shouldOverrideUrlLoading里面本來(lái)是對(duì)鏈接的點(diǎn)擊也會(huì)被當(dāng)成重定向鏈接在當(dāng)前的WebView里面打開(kāi)灾锯。
要避免這種情況,只能在頁(yè)面完全加載出來(lái)之前禁止WebView的點(diǎn)擊嗅榕。

webView.setOnTouchListener(new WebViewTouchListener());
//代碼省略
private class WebViewTouchListener implements View.OnTouchListener {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return !mIsLoading;
        }
}

結(jié)語(yǔ)

上面的兩種方案都能解決部分問(wèn)題顺饮,但是都有缺陷。只能說(shuō)沒(méi)有完美的方案凌那,只有符合需求的方案拒秘。

江湖規(guī)矩您市,源碼見(jiàn) github

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末弄喘,一起剝皮案震驚了整個(gè)濱河市江场,隨后出現(xiàn)的幾起案子澎办,更是在濱河造成了極大的恐慌嘲碱,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件局蚀,死亡現(xiàn)場(chǎng)離奇詭異麦锯,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)琅绅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)扶欣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事料祠÷媾酰” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵髓绽,是天一觀的道長(zhǎng)敛苇。 經(jīng)常有香客問(wèn)我,道長(zhǎng)枫攀,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任株茶,我火速辦了婚禮,結(jié)果婚禮上启盛,老公的妹妹穿的比我還像新娘蹦掐。我一直安慰自己驰徊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布棍厂。 她就那樣靜靜地躺著,像睡著了一般牺弹。 火紅的嫁衣襯著肌膚如雪浦马。 梳的紋絲不亂的頭發(fā)上张漂,一...
    開(kāi)封第一講書(shū)人閱讀 49,829評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音航攒,去河邊找鬼磺陡。 笑死漠畜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的憔狞。 我是一名探鬼主播蝴悉,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼瘾敢,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼尿这!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起庆杜,我...
    開(kāi)封第一講書(shū)人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎欣福,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體拓劝,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雏逾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了郑临。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片栖博。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖厢洞,靈堂內(nèi)的尸體忽然破棺而出仇让,到底是詐尸還是另有隱情,我是刑警寧澤躺翻,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布丧叽,位于F島的核電站,受9級(jí)特大地震影響公你,放射性物質(zhì)發(fā)生泄漏踊淳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一陕靠、第九天 我趴在偏房一處隱蔽的房頂上張望迂尝。 院中可真熱鬧,春花似錦剪芥、人聲如沸垄开。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)溉躲。三九已至,卻和暖如春益兄,著一層夾襖步出監(jiān)牢的瞬間签财,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工偏塞, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人邦鲫。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓灸叼,卻偏偏與公主長(zhǎng)得像神汹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子古今,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

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