React Native WebView踩坑記

React Native WebView踩坑記

在使用React Native開發(fā)應用時,有些第三方的頁面需要在WebView中展示硕舆,最初使用WebView展示幾個簡單的廣告推廣頁時,沒有遇到什么問題骤公。隨著使用深入,遇到React Native WebView組件的幾個問題阶捆,一番探索,終于明白了問題點刊咳。

React Native Android WebView body height 100%

遇到這個問題是在使用0.30版本時儡司,在該版本下有一個外部業(yè)務的頁面在我們的WebView展示時渲染不出來,表現為頁面是一個空白頁捕犬。

通過觀察日志、斷點調試也沒有看到什么錯誤信息提示碉碉。

遇到這種問題,思路是首先搜索官方issues,經過搜索贴届,果然發(fā)現已有issue
https://github.com/facebook/react-native/issues/5211

下面的討論中,有人提到了Android端WebView對height 100%的樣式不能識別毫蚓,當頁面body設置height 100%時昔善,在WebView中會為頁面body設置height 0,因此頁面渲染為空白頁君仆。

有了這個提示牲距,打開chrome://inspect開始調試當前WebView钥庇,經過審查工具查看樣式,發(fā)現確實這一頁面為body設置了height 100%皮服。幸好WebView允許我們向頁面注入js代碼参咙,于是可以通過向頁面注入下列代碼解決

const jsForInjection = `
  var el = document.getElementsByTagName('body')[0];
  el.style.height = '${Dimensions.get('window').height}px';
`

跟進React Native release notes發(fā)現,在0.32版本蕴侧,修復了這一缺陷,鏈接https://github.com/facebook/react-native/commit/1bb1385c7d199a473f76cdec357de2ab4d1d61b6

React Native Android&iOS WebView view height 100%

看到前文提到的官方說明敲才,提到已修復這一缺陷還沒高興多久。又遇到了另一個問題紧武。在另一個業(yè)務的頁面中,使用了比較復雜的布局方式敏储,在頁面內容的某一個子區(qū)域阻星,又使用了height 100%這種布局已添。

這一次不只是Android了,iOS的WebView也不能正確解析這一樣式畦幢,使用height 100%布局的這一個子區(qū)域渲染為空白區(qū)域缆蝉。

這里沒有通用的解決方式了,其他業(yè)務如果可以去修改自身的樣式布局當然是最好刊头。更實際的解決方案,是發(fā)現一例,解決一例弦讽。

以這里遇到的一個頁面為例膀哲,通過chrome://inspect定位到具體是哪一個區(qū)域的問題后被碗,通過注入js,定向的修改這一樣式兴喂。

這是一個沒有辦法的辦法了焚志。

 var licaiapp = document.getElementsByClassName('hero-product')[0];
  if(licaiapp){
  licaiapp.style.height = '542px';
  }

React Native Android 私有協議 crash

在網頁中使用js通過私有協議調起外部App,這種方式對大家來說應該不會陌生酱酬。

在Android 0.30版本的使用中,這里沒遇到問題汗菜,但是升級到0.35版本后挑社,發(fā)現在用戶沒有安裝App A時,在WebView加載的頁面中痛阻,通過私有協議調起App A時,會導致App crash麻车。

通過查看Android Studio日志斗这,發(fā)現下面異常信息

No Activity found to handle Intent { act=android.intent.action.VIEW dat=investapp://webend-promotion flg=0x10000000 }

根據這一異常信息,查看安裝端ReactWebViewManager源碼表箭,發(fā)現問題的根源在于下面方法

@Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.startsWith("http://") || url.startsWith("https://")) {
          return false;
        } else {
          Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); 
          intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
          view.getContext().startActivity(intent);   
          return true;   
        }              
    }

React Native 0.31版本開始免钻,在ReactWebViewManager中增加了上述方法极舔,加載私有協議時,通過else中的邏輯調起App拆魏。問題是這里代碼慈俯,在用戶未安裝這一App拥峦,startActivity不能被正確響應時會拋出Exception,而代碼的調用處又沒有try/catch刑峡,因此導致了crash

給官方提了issue玄柠,不過很快被close說覺得不是RN的問題。随闪。。
https://github.com/facebook/react-native/issues/10499

看其他issue也有提到這個bug撮奏,不再去修改問題了当宴。

解決辦法,基于官方的ReactWebViewManager做下修改吧户矢,然后封裝一個自定義WebView出來給JS端調用。

React Native iOS 私有協議問題

在iOS模擬器加載一個外部業(yè)務的頁面時捌年,遇到一個奇怪的問題挂洛。業(yè)務的頁面,首先在WebView里渲染出來虏劲,然后又跳去了默認失敗界面,如下圖所示

起初一直沒理解到底是什么問題励堡,實際上已有issue說的還算明白了
https://github.com/facebook/react-native/issues/9037

最初在沒理解問題是什么時候堡掏,嘗試了其他方案,引入了社區(qū)的react-native-wkwebview來替代官方的WebView摊趾,引入后發(fā)現確實解決了問題,頁面可以正常渲染砾层,在已安裝目標App的手機上贱案,也可以調起App了。

后來隨著對Android端WebView問題的跟進侨糟,在加上又看了下上面反饋的issue瘩燥,意識到這里也是因為WebView加載私有協議失敗引起的,不同的是厉膀,在iOS端,加載私有協議失敗后凳兵,進入了失敗處理邏輯企软,跳到了失敗提示界面。

解決方案仗哨,iOS端為解決這一問題提供了一個便利的方法,

onShouldStartLoadWithRequest

可以在這個方法中萨醒,根據url的協議頭桩卵,決定是否真的發(fā)起請求,還是調起外部App雏节,代碼如下


onShouldStartLoadWithRequest(event){
        if(event.url.startsWith('http://') || event.url.startsWith('https://')) {
            return true;
        }else{
            Linking.canOpenURL(event.url)
                .then(supported => {
                    if(supported){
                       return Linking.openURL(url);
                    }else{
                        return false;
                    }
                }).catch(err => {
                    return false;
            })
        }
    }

ReactNative與WebView雙向通信

這個問題當前業(yè)務中還沒用到,不過目前官方API辞州,僅支持向WebView中注入JS寥粹,還不支持從WebView中的頁面調用React Native中的方法埃元。

解決辦法媚狰,社區(qū)已有一個解決方案react-native-webview-bridge

如果覺得有幫助,可以掃描二維碼對我打賞崭孤,謝謝

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末辨宠,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子精偿,更是在濱河造成了極大的恐慌赋兵,老刑警劉巖笔咽,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拓轻,死亡現場離奇詭異经伙,居然都是意外死亡,警方通過查閱死者的電腦和手機帕膜,發(fā)現死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門垮刹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人荒典,你說我怎么就攤上這事∷露” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵滩字,是天一觀的道長。 經常有香客問我漓藕,道長挟裂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任嫩与,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘饵筑。我一直安慰自己,他們只是感情好架专,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著玄帕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪委刘。 梳的紋絲不亂的頭發(fā)上鹰椒,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機與錄音漆际,去河邊找鬼。 笑死施符,一個胖子當著我的面吹牛擂找,可吹牛的內容都是我干的。 我是一名探鬼主播婴洼,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼欢唾!你這毒婦竟也來了?” 一聲冷哼從身側響起礁遣,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤祟霍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后沸呐,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡寓娩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年呼渣,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片焊夸。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡蓝角,死狀恐怖,靈堂內的尸體忽然破棺而出帅容,到底是詐尸還是另有隱情,我是刑警寧澤遣钳,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布麦乞,位于F島的核電站,受9級特大地震影響姐直,放射性物質發(fā)生泄漏。R本人自食惡果不足惜声畏,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望愿棋。 院中可真熱鬧,春花似錦才睹、人聲如沸甘邀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至逗抑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背护盈。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工腐宋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留紊服,地道東北人胸竞。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓卫枝,卻偏偏與公主長得像煎饼,于是被迫代替她去往敵國和親校赤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內容