WebView與Javascript交互及JS的注入

本篇目錄

前言

本篇講解Java代碼和Javascript代碼的相互調(diào)用以及JS代碼在Java中是如何動(dòng)態(tài)的注入WebView中。一些通用配置在第一部分中說明。


一缎谷、Java 調(diào)用 JS 中函數(shù)

1.添加權(quán)限(這里使用資源目錄下寫好的html文件)
<uses-permission android:name="android.permission.INTERNET"/>
2.webView配置
...
// 省略掉findView..webview
mWebView.getSettings().setJavaScriptEnabled(true);
3.利用webViewloadUrl()方法調(diào)用JS中函數(shù)

注意調(diào)用的函數(shù)前面添加javascript:

...
btn_invoke_js1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        // 調(diào)用JS中無參數(shù)的函數(shù)
        mWebView.loadUrl("javascript:javacalljs()");
        mWebView.loadUrl("javascript:javacalljswith(\"JAVA調(diào)用了JS的有參函數(shù)\")");
        }
    });
...

二、JS 調(diào)用 Java 中方法

1.添加js的回調(diào)接口

第一個(gè)參數(shù)是接收回調(diào)的類,這里寫成當(dāng)前的類杖小,接下來會(huì)在當(dāng)前類中添加被js調(diào)用的方法。obj為別名愚墓,和js中保持一致予权。

mWebView.addJavascriptInterface(this, "obj");
2.java中添加被js調(diào)用的方法。

<font color="red">注意一定不要忘記添加@JavascriptInterface</font>這里的方法和web.html中的window.obj.localMethods('Incoming parameters')保持一致浪册。

...
@JavascriptInterface
public void localMethods(String arg) {
    Log.i(TAG, "This method is called!");
    Toast.makeText(this, "This method is called!", Toast.LENGTH_SHORT).show();
}

三扫腺、(重點(diǎn))Java 中動(dòng)態(tài)注入 JS

1.注入JS方法

這里注入時(shí)機(jī)是onPageFinished()后;注入的JS是一個(gè)alert為例村象。

public class JsInjectionActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...  
        InsideWebViewClient mInsideWebViewClient = new InsideWebViewClient();  
        mWebView.setWebChromeClient(new WebChromeClient());
        mWebView.setWebViewClient(mInsideWebViewClient);
        WebSettings webSettings = mWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        mWebView.addJavascriptInterface(JsInjectionActivity.this, "obj");
        mWebView.loadUrl("file:///android_asset/web.html");
        ...
    }
    
    private class InsideWebViewClient extends WebViewClient {

        @Override
        public void onPageFinished(WebView view, String url) {
            mWebView.loadUrl("javascript:" + "window.alert('Js injection success')" );
            super.onPageFinished(view, url);
        }
    }
}
...

注意:以上注入的js包含一個(gè)alert笆环,寫完后可能會(huì)發(fā)現(xiàn)alert沒有彈出來。這時(shí)要去檢查myWebView.setWebChromeClient(new WebChromeClient());是否設(shè)置了厚者。

2.(重點(diǎn))注入的js導(dǎo)致的問題或可能出現(xiàn)的問題
  1. 注入js可能會(huì)導(dǎo)致加載的html5頁面總是一直在加載中躁劣,加載很慢或干脆加載不出來,這個(gè)問題不是針對(duì)所有的html5可能在某些網(wǎng)頁上會(huì)遇到這個(gè)問題库菲;
  2. 注入JS后回調(diào)函數(shù)沒有執(zhí)行到账忘;

解決方法:

@Override    
protected void onPause(){    
    super.onPause();    
  
    mWebView.pauseTimers();    
    if(isFinishing()){    
        mWebView.loadUrl("about:blank");    
        setContentView(new FrameLayout(this));    
    }    
}    
  
@Override    
protected void onResume(){    
    super.onResume();    
    mWebView.resumeTimers();    
}    

調(diào)用webView.loadUrl("about:blank");該方法使得webView只回執(zhí)一個(gè)白色背景,并且釋放之前加載頁面時(shí)使用的資源,并停止之前javascript的執(zhí)行闪萄。

pauseTimers, onPause 停止解析,javascript執(zhí)行等操作.區(qū)別是 onPause 只作用于調(diào)用它的WebView,而 pauseTimers 作用于當(dāng)前應(yīng)用中所有的WebView

resumeTimers, onResume 恢復(fù)解析,javascript執(zhí)行等操作.區(qū)別是 onResume 只作用于調(diào)用它的WebView,而 resumeTimers 作用于當(dāng)前應(yīng)用中所有的WebView梧却。

3.當(dāng)壓縮后的JS注入到webView中時(shí),注入沒有生效

我的解決方式:
JS格式化后或是非壓縮狀態(tài)注入成功败去,不知道別人有沒有遇到過類似問題放航,或者是其它原因,這里有疑問圆裕,如果有遇到相同問題的广鳍,歡迎一起交流。

在線js格式化吓妆,縮進(jìn)方式選擇:4個(gè)空格縮進(jìn)
http://tool.oschina.net/codeformat/js


四赊时、完整代碼

完整代碼,不包含js注入遇到的問題部分行拢,自行加入祖秒。

1. web.html文件

文件路徑:..src/main/assets/web.html

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=gb2312">
    <script type="text/javascript">

    function javacalljs(){
        document.getElementById("content").innerHTML = "<br>JAVA調(diào)用了JS的無參函數(shù)";
    }

    function javacalljswith(arg){
        document.getElementById("content").innerHTML = ("<br>"+arg);
    }

    </script>
</head>
<body>
HTML 內(nèi)容顯示 <br/>
<h1>
    <div id="content">內(nèi)容顯示</div>
</h1>
<br/>
<input type="button" value="點(diǎn)擊調(diào)用java代碼" onclick="window.obj.localMethods('Incoming parameters')"/><br/>
</body>
</html>

2. JsInjectionActivity.java文件
public class JsInjectionActivity extends Activity {
    private static final String TAG = JsInjectionActivity.class.getSimpleName();

    private WebView mWebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button btn_invoke_js1 = (Button) findViewById(R.id.btn_invoke_js1);
        Button btn_invoke_js2 = (Button) findViewById(R.id.btn_invoke_js2);

        mWebView = (WebView) findViewById(R.id.webview);

        InsideWebViewClient mInsideWebViewClient = new InsideWebViewClient();
        mWebView.setWebChromeClient(new WebChromeClient());
        mWebView.setWebViewClient(mInsideWebViewClient);
        WebSettings webSettings = mWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        mWebView.addJavascriptInterface(JsInjectionActivity.this, "obj");
        mWebView.loadUrl("file:///android_asset/web.html");

        btn_invoke_js1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mWebView.loadUrl("javascript:javacalljs()");
            }
        });

        btn_invoke_js2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mWebView.loadUrl("javascript:javacalljswith(\"JAVA調(diào)用了JS的有參函數(shù)\")");
            }
        });
    }

    @JavascriptInterface
    public void localMethods(String arg) {
        Log.i(TAG, "This method is called!");
        Toast.makeText(this, "This method is called!", Toast.LENGTH_SHORT).show();
    }

    private class InsideWebViewClient extends WebViewClient {

        @Override
        public void onPageFinished(WebView view, String url) {
            mWebView.loadUrl("javascript:" + "window.alert('Js injection success')" );
            super.onPageFinished(view, url);
        }
    }

}

最后

不懂得地方歡迎私信我,我會(huì)在第一時(shí)間給予回復(fù)舟奠,如閱讀中發(fā)現(xiàn)寫錯(cuò)的地方竭缝,歡迎糾正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末沼瘫,一起剝皮案震驚了整個(gè)濱河市抬纸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌耿戚,老刑警劉巖湿故,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異膜蛔,居然都是意外死亡坛猪,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門皂股,熙熙樓的掌柜王于貴愁眉苦臉地迎上來砚哆,“玉大人,你說我怎么就攤上這事屑墨。” “怎么了纷铣?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵卵史,是天一觀的道長。 經(jīng)常有香客問我搜立,道長以躯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮忧设,結(jié)果婚禮上刁标,老公的妹妹穿的比我還像新娘。我一直安慰自己址晕,他們只是感情好膀懈,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谨垃,像睡著了一般启搂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上刘陶,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天胳赌,我揣著相機(jī)與錄音,去河邊找鬼匙隔。 笑死疑苫,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的纷责。 我是一名探鬼主播捍掺,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼碰逸!你這毒婦竟也來了乡小?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤饵史,失蹤者是張志新(化名)和其女友劉穎满钟,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胳喷,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡湃番,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吭露。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吠撮。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖讲竿,靈堂內(nèi)的尸體忽然破棺而出泥兰,到底是詐尸還是另有隱情,我是刑警寧澤题禀,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布鞋诗,位于F島的核電站,受9級(jí)特大地震影響迈嘹,放射性物質(zhì)發(fā)生泄漏削彬。R本人自食惡果不足惜全庸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望融痛。 院中可真熱鬧壶笼,春花似錦、人聲如沸雁刷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽安券。三九已至墩崩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間侯勉,已是汗流浹背鹦筹。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留址貌,地道東北人铐拐。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像练对,于是被迫代替她去往敵國和親遍蟋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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