Android與H5交互探索之旅

本文已獨(dú)家授權(quán) 郭霖 ( guolin_blog ) 公眾號(hào)發(fā)布店雅!

周一清早咆霜,某技術(shù)(對(duì)接我司業(yè)務(wù)SDK的技術(shù))在有我司boss的微信群火急火燎地艾特我說(shuō)為什么H5的回調(diào) SDK 這邊收不到籍铁?看到消息的我內(nèi)心瞬間那是焦慮的一P狐树,飛奔公司打開(kāi)電腦雙擊IDE涮母,心想別人用的好好的挟冠,這不太科學(xué)呀鹏漆。

說(shuō)起H5與Android的交互巩梢,簡(jiǎn)單來(lái)說(shuō)就是android這邊提供對(duì)象,暴露方法讓H5的腳本文件進(jìn)行調(diào)用艺玲,但是如果出現(xiàn)交互失敗的情況括蝠,那就需要逐一分析挨個(gè)排除。本篇文章只針對(duì)原生Webview進(jìn)行討論板驳,市面上一些封裝好又跛、優(yōu)秀的第三方Webview這里就不涉及了。

定位一:Http 和 Https 混合資源加載

由于H5目前的大開(kāi)發(fā)環(huán)境若治,一個(gè)Js文件(最終會(huì)被 html引用)可能會(huì)出現(xiàn)兩種不同混合的資源(尤其是H5頁(yè)游慨蓝,頁(yè)游會(huì)使用大量的混合資源),比如 Http和https資源端幼。從Android5.0開(kāi)始礼烈,WebView默認(rèn)不支持同時(shí)加載Https和Http混合模式。如果Webview不允許混合加載婆跑,那么js文件可能就不會(huì)生效此熬,js文件異常,就可能會(huì)導(dǎo)致H5無(wú)法調(diào)用Android滑进;實(shí)際上犀忱,我們?cè)谧远xWebview時(shí)一般都允許它混合加載

WebSettings.setMixedContentMode.(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

WebSettings.setMixedContentMode()這個(gè)方法,也就是加載內(nèi)容的混合模式扶关,谷歌提供的混合模式一共有如下三種模式

  • MIXED_CONTENT_NEVER_ALLOW
    這種模式代表的意思是指:Webview不允許一個(gè)安全的站點(diǎn)(https)去加載非安全的站點(diǎn)內(nèi)容(http),比如阴汇,https網(wǎng)頁(yè)內(nèi)容的圖片是http鏈接。

  • MIXED_CONTENT_ALWAYS_ALLOW
    這種模式代表的意思是指:WebView是可以在一個(gè)安全的站點(diǎn)(Https)里加載非安全的站點(diǎn)內(nèi)容(Http), 這是WebView最不安全的操作模式节槐,但是畢竟通用搀庶,也就是一了百了的寫(xiě)法

  • MIXED_CONTENT_COMPATIBILITY_MODE
    這個(gè)模式比較有趣:當(dāng)涉及到混合式內(nèi)容時(shí)拐纱,WebView會(huì)嘗試去兼容最新Web瀏覽器的風(fēng)格。一些不安全的內(nèi)容(Http)能被加載到一個(gè)安全的站點(diǎn)上(Https)哥倔,而其他類(lèi)型的內(nèi)容將會(huì)被阻塞秸架。這些內(nèi)容的類(lèi)型是被允許加載還是被阻塞,可能會(huì)隨著版本的不同而改變咆蒿,官網(wǎng)并沒(méi)有給出明確的定義东抹。這種模式主要用于在A(yíng)pp里面不能控制內(nèi)容的渲染,但是又希望在一個(gè)安全的環(huán)境下運(yùn)行蜡秽。

綜上:如果想一了百了(簡(jiǎn)單快捷)設(shè)置府阀,直接WebSettings.MIXED_CONTENT_ALWAYS_ALLOW即可

定位二:WebSettings基本配置

WebSettings,這個(gè)抽象類(lèi)主要是用來(lái)管理WebView的狀態(tài)芽突,開(kāi)發(fā)者主動(dòng)對(duì)WebSettings進(jìn)行配置试浙,可以豐富WebView的功能以至于來(lái)滿(mǎn)足開(kāi)發(fā)需求。如果想通過(guò)Webview來(lái)實(shí)現(xiàn)Android與H5的交互寞蚌,需要對(duì)WebSettings進(jìn)行配置

首先:實(shí)例化WebSettings ( 通過(guò)Webview.getSettings( )來(lái)獲取 ):

WebSettings settings = webView.getSettings();

接著:設(shè)置WebView是否允許執(zhí)行JavaScript腳本田巴,默認(rèn)false,false為不允許挟秤,因此要將其手動(dòng)設(shè)置為true

settings.setJavaScriptEnabled(true);

然后:還有一個(gè)API也比較重要:

 settings.setDomStorageEnabled(true);

這個(gè)API的用法壹哺,是否開(kāi)啟本地DOM存儲(chǔ)。理論上對(duì)應(yīng)Html5中的localStorage(可以使用Android4.4手機(jī)和Chrome Inspcet Device聯(lián)調(diào)艘刚,關(guān)于這個(gè)聯(lián)調(diào)管宵,后文會(huì)講),用于持久化的本地存儲(chǔ)攀甚,除非主動(dòng)刪除數(shù)據(jù)箩朴,否則數(shù)據(jù)是永遠(yuǎn)不會(huì)過(guò)期的,因?yàn)槎鄶?shù)瀏覽器都支持 localStorage 的秋度,但是鑒于它的安全特性(任何人都能讀取到它炸庞,盡管有相應(yīng)的限制,將敏感數(shù)據(jù)存儲(chǔ)在這里依然不是明智之舉)荚斯,Android 默認(rèn)是關(guān)閉該功能的埠居,也就是false。但是事期,我們一般會(huì)將其設(shè)置true滥壕。

定位三:Android與H5交互之代碼細(xì)節(jié)

Android與H5的交互,實(shí)際是通過(guò)注解和對(duì)象兽泣、方法來(lái)完成的绎橘,
首先,Webview調(diào)用addJavascriptInterface方法撞叨,在立馬傳入具體的參數(shù)允許被H5調(diào)用金踪,系統(tǒng)源碼如下:

  webView.addJavascriptInterface( Object object, String name)

參數(shù)一:具體的對(duì)象,也就是H5與Android交互的實(shí)體類(lèi)
參數(shù)二:參數(shù)一對(duì)象的實(shí)例化對(duì)象牵敷,也就是給前端調(diào)用的類(lèi)名

具體使用胡岔,參考代碼如下:
A: 傳入類(lèi)和對(duì)象名(對(duì)象名與H5需要協(xié)商好),如果對(duì)象名不一致枷餐,H5無(wú)法調(diào)用Android的原生方法 靶瘸,而且要仔細(xì)區(qū)分大小寫(xiě)、l(小寫(xiě)的L)與I(大寫(xiě)的i)這些類(lèi)似的字符等等(稍微不注意就寫(xiě)錯(cuò)毛肋,一寫(xiě)錯(cuò)就無(wú)法調(diào)用....)

 webView.addJavascriptInterface(new H5CallBackAndroid(), "callBack");

B: Android 對(duì)象類(lèi)的編寫(xiě)(參考)

public class H5CallBackAndroid {

    @JavascriptInterface
    public void useHtmlData(String data) {
        if (data != null && data.length()>0){
            Log.i("info", "H5傳過(guò)來(lái)的數(shù)據(jù) :"+data);
            // Android 原生處理data
        }else {
            Log.i("info", "H5傳過(guò)來(lái)的數(shù)據(jù) 無(wú)效:");
        }
    }
}

注意:

  • H5調(diào)Android使用的方法怨咪,需要在方法上用 @JavascriptInterface注解來(lái)定義該方法;

  • 被該注解修飾的方法權(quán)限需要聲明為 public 這點(diǎn)尤其注意

定位四:SSL

由于HTTPS協(xié)議通過(guò)SSL進(jìn)行通信润匙,當(dāng)使用HTTPS通信的url在Webview出現(xiàn)錯(cuò)誤時(shí)诗眨,一般會(huì)通過(guò)onReceivedSslError回調(diào)通知,常見(jiàn)的做法是直接忽略孕讳,讓W(xué)ebview繼續(xù)加載

        webView.setWebViewClient(new WebViewClient(){

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                Log.i("log", "shouldOverrideUrlLoading: url"+url);
                return super.shouldOverrideUrlLoading(view, url);
            }

            @Override
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {          
                super.onReceivedError(view, request, error);
            }

            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                //繼續(xù)加載
                handler.proceed();
            }
        });

這里的 SslErrorHandler:也就是當(dāng)前處理錯(cuò)誤的Handler匠楚,它只有兩個(gè)函數(shù):

  • SslErrorHandler.proceed()
  • SslErrorHandler.cancel()

其中,SslErrorHandler.proceed()表示忽略錯(cuò)誤繼續(xù)加載厂财;SslErrorHandler.cancel()表示取消加載芋簿。在onReceivedSslError的默認(rèn)實(shí)現(xiàn)中是使用的SslErrorHandler.cancel()來(lái)取消加載,所以一旦出來(lái)SSL錯(cuò)誤璃饱,HTTPS網(wǎng)站就會(huì)被取消加載与斤、,如果想忽略錯(cuò)誤繼續(xù)加載就只有重寫(xiě)onReceivedSslError荚恶,并調(diào)用SslErrorHandler.proceed()繼續(xù)加載

定位五:混淆

如果項(xiàng)目開(kāi)啟了混淆撩穿,也就是minifyEnabled設(shè)置為了true

  buildTypes {
      //。裆甩。冗锁。省略
        release {
            //開(kāi)啟混淆
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }


    }

但是,如果沒(méi)有配置Webview的混淆規(guī)則嗤栓,也是無(wú)法與H5正常交互的冻河,這點(diǎn)非常重要!\运А叨叙!

關(guān)于Webview常見(jiàn)的混淆規(guī)則如下:

#保留annotation, 例如 @JavascriptInterface 等 annotation
-keepattributes *Annotation*

#保留跟 javascript相關(guān)的屬性 
-keepattributes JavascriptInterface

#保留JavascriptInterface中的方法
-keepclassmembers class * {
    @android.webkit.JavascriptInterface <methods>;
}
#這個(gè)類(lèi)是用來(lái)與js交互堪澎,所以這個(gè)類(lèi)中的 字段 擂错,方法, 不能被混淆樱蛤、全路徑名稱(chēng).類(lèi)名
-keepclassmembers public class com.youpackgename.xxx.H5CallBackAndroid{
   <fields>;
   <methods>;
   public *;
   private *;
}

更多的混淆細(xì)則钮呀,可自行通過(guò)瀏覽器了解查閱詳細(xì)的混淆配置信息

定位六:前端兄弟的問(wèn)題

如果前端兄弟寫(xiě)錯(cuò)了或者弄錯(cuò)了(小寫(xiě)的c寫(xiě)成大寫(xiě)的C剑鞍、l(小寫(xiě)的L)與I(大寫(xiě)的i)等等),出現(xiàn)這種情況當(dāng)然是無(wú)法調(diào)用到android原生的方法呀爽醋,所以必要的時(shí)候也可以找他幫忙一起看看

定位七:Android9.0新特性

由于從Android 9.0(API級(jí)別28)開(kāi)始蚁署,系統(tǒng)內(nèi)部默認(rèn)禁用明文支持(也就是明面上不支持http),因此http的url均無(wú)法在webview中加載蚂四。(這種情況是針對(duì)9.0系統(tǒng) webview打不開(kāi)的情況光戈,特此做補(bǔ)充說(shuō)明)


9.0-Webview報(bào)錯(cuò)

解決辦法

  • 在A(yíng)ndroidManifest.xml文件中的Application標(biāo)簽添加android:usesCleartextTraffic="true",參考代碼如下:
<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:name=".tools.App"
        android:roundIcon="@mipmap/ic_launcher_round"

        <!--讓9.0 webview 支持htp-->
        android:usesCleartextTraffic="true"

        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>


    </application>

補(bǔ)充:H5與Android的調(diào)試

關(guān)于H5與Android的聯(lián)合調(diào)試遂赠,下面做個(gè)簡(jiǎn)單說(shuō)明:

準(zhǔn)備工作:

  • PC下載并安裝chrome(谷歌)瀏覽器
  • 一臺(tái)安卓手機(jī)(4.4系統(tǒng)以上)久妆,用usb線(xiàn)鏈接電腦,打開(kāi)開(kāi)發(fā)者模式跷睦,且允許WebView進(jìn)行調(diào)試筷弦,需新增如下代碼
  WebView.setWebContentsDebuggingEnabled(true);

編譯并運(yùn)行代碼

  • chrome瀏覽器地址欄輸入 chrome://inspect,進(jìn)入后點(diǎn)擊 inspect 即進(jìn)入調(diào)試模式(需要翻(越)墻(壁))
進(jìn)入調(diào)試界面

在A(yíng)PP上顯示具體的H5界面后抑诸,該調(diào)試界面才會(huì)顯示需要調(diào)試的包名等具體信息奸笤。點(diǎn)擊inspect后,就會(huì)進(jìn)入調(diào)試界面哼鬓。一番操作后你會(huì)發(fā)現(xiàn)在網(wǎng)頁(yè)上操作监右、和手機(jī)操作是同步進(jìn)行的


調(diào)試界面

查看請(qǐng)求體、響應(yīng)體該如何操作异希?
一番操作后(如:用戶(hù)登錄)健盒,如下圖,點(diǎn)擊all 紅色箭頭称簿,然后看一下藍(lán)色方框內(nèi)的是不是很熟悉扣癣,當(dāng)然這里只是簡(jiǎn)單介紹如何快速使用以供參考。

調(diào)試小技巧

如果這篇文章對(duì)您有開(kāi)發(fā)or學(xué)習(xí)上的些許幫助憨降,希望各位看官留下寶貴的star父虑,謝謝。

Ps:著作權(quán)歸作者所有,轉(zhuǎn)載請(qǐng)注明作者, 商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)授药,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處(開(kāi)頭或結(jié)尾請(qǐng)?zhí)砑愚D(zhuǎn)載出處士嚎,添加原文url地址),文章請(qǐng)勿濫用,也希望大家尊重筆者的勞動(dòng)成果

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市悔叽,隨后出現(xiàn)的幾起案子莱衩,更是在濱河造成了極大的恐慌,老刑警劉巖娇澎,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笨蚁,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)括细,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)伪很,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人奋单,你說(shuō)我怎么就攤上這事是掰。” “怎么了辱匿?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)炫彩。 經(jīng)常有香客問(wèn)我匾七,道長(zhǎng),這世上最難降的妖魔是什么江兢? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任昨忆,我火速辦了婚禮,結(jié)果婚禮上杉允,老公的妹妹穿的比我還像新娘邑贴。我一直安慰自己,他們只是感情好叔磷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布拢驾。 她就那樣靜靜地躺著,像睡著了一般改基。 火紅的嫁衣襯著肌膚如雪繁疤。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天秕狰,我揣著相機(jī)與錄音稠腊,去河邊找鬼。 笑死鸣哀,一個(gè)胖子當(dāng)著我的面吹牛架忌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播我衬,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼叹放,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了挠羔?” 一聲冷哼從身側(cè)響起许昨,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎褥赊,沒(méi)想到半個(gè)月后糕档,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年速那,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了俐银。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡端仰,死狀恐怖捶惜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情荔烧,我是刑警寧澤吱七,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站鹤竭,受9級(jí)特大地震影響踊餐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜臀稚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一吝岭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吧寺,春花似錦窜管、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至赖条,卻和暖如春蜓肆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谋币。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工仗扬, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蕾额。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓早芭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親诅蝶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子退个,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355