首页 > 技术文章 > WebView Js注入

yaowen 2016-08-16 10:32 原文

注入前:

注入后:

 

主界面:

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. package com.example.webviewjsdemo;  
  2.   
  3. import android.os.Bundle;  
  4. import android.app.Activity;  
  5. import android.view.Menu;  
  6. import android.webkit.WebChromeClient;  
  7. import android.webkit.WebSettings;  
  8. import android.webkit.WebView;  
  9. import android.webkit.WebViewClient;  
  10. import android.widget.Toast;  
  11.   
  12. public class MainActivity extends Activity {  
  13.   
  14.     private WebView wv;  
  15.   
  16.     @Override  
  17.     protected void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.activity_main);  
  20.   
  21.         wv = (WebView) findViewById(R.id.wv_main);  
  22.   
  23.         wv.setWebChromeClient(new WebChromeClient() {  
  24.         });  
  25.   
  26.         wv.setWebViewClient(new WebViewClient() {  
  27.             @Override  
  28.             public void onPageFinished(final WebView view, String url) {  
  29.                 Toast.makeText(getApplicationContext(), "3秒后改变内容", 1).show();  
  30.                 new Thread(){  
  31.                     public void run() {  
  32.                         try {  
  33.                             Thread.sleep(3000);  
  34.                         } catch (InterruptedException e) {  
  35.                             e.printStackTrace();  
  36.                         }  
  37.                         view.loadUrl("javascript:function myFunction(){x=document.getElementById(\"demo\");  x.innerHTML=\"改变了html内容!\";}");  
  38.                         view.loadUrl("javascript:myFunction()");  
  39.                     };  
  40.                 }.start();  
  41.                 super.onPageFinished(view, url);  
  42.             }  
  43.         });  
  44.   
  45.         WebSettings wvSettings = wv.getSettings();  
  46.         wvSettings.setJavaScriptEnabled(true);  
  47.   
  48.         wv.loadUrl("file:///android_asset/demo.html");  
  49.     }  
  50.   
  51. }  

 

 

主界面layout:

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     tools:context=".MainActivity" >  
  6.   
  7.     <WebView  
  8.         android:id="@+id/wv_main"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="match_parent"  
  11.         android:layout_centerHorizontal="true"  
  12.         android:layout_centerVertical="true" />  
  13.   
  14. </RelativeLayout>  


assets目录下的demo.html文件

 

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
    1. <!DOCTYPE html>  
    2. <html>  
    3.     <body>  
    4.         <h1>Js注入</h1>  
    5.         <p id="demo" style="color:red;font-size:16px;">  
    6.             这里将会改变。  
    7.         </p>  
    8.     </body>  
    9. </html>  
      1. Android中向webview注入js代码可以通过webview.loadUrl("javascript:xxx")来实现,然后就会执行javascript后面的代码。

        但是当需要注入一整个js文件的时候,貌似就有点麻烦了。
        不过理清以下思路,方法其实也很简单,如下:
        我们通过在webview的onPageFinished方法中执行js代码注入:

        第一种:
        当webview加载完之后,读取整个js文件中的内容,然后将整个文件内容以字符串的形式,通过webview.loadUrl("javascript:fileContentString")注入

        复制代码
        URL url = new URL("http://www.rayray.ray/ray.js");
        in = url.openStream();
        byte buff[] = new byte[1024];
        ByteArrayOutputStream fromFile = new ByteArrayOutputStream();
        FileOutputStream out = null;
        do {
               int numread = in.read(buff);
               if (numread <= 0) {
                 break;
                 }
                fromFile.write(buff, 0, numread);
             } while (true);
        String wholeJS = fromFile.toString();
        复制代码

         

        @Override
        public void onPageFinished(WebView view, String url) 
         {
                super.onPageFinished(view, url);
                 webview.loadUrl("javascript:" + wholeJS);
         }

         

        第二种:
        页面加载完之后,直接向webview对应的html中加入<script>便签,并包含要注入的js的Url地址,如下:

        String js = "var newscript = document.createElement(\"script\");";
        js += "newscript.src=\"http://www.123.456/789.js\";";
        js += "document.body.appendChild(newscript);";

         

        @Override
         public void onPageFinished(WebView view, String url) 
          {
               super.onPageFinished(view, url);
                webview.loadUrl("javascript:" + js);
          }

         

        后记:上面两种方式中,第二种方法更加简单方便一点。不过第二种方法也有问题,当你注入完JS之后你想要立即调用其中的方法,第一种方法没问题可以调用到。但是第二种方法中,你要确保注入的<script>便签对应的js文件加载完才可调用成功。

        解决:在第二种方法中为加入script标签添加onload事件,确保该script已加载完成。代码可更改如下:

        String js = "var newscript = document.createElement(\"script\");";
           js += "newscript.src=\"http://www.123.456/789.js\";";
           js += "newscript.onload=function(){xxx();};";  //xxx()代表js中某方法
           js += "document.body.appendChild(newscript);";

         


        IOS中也一样,按照同样的思路然后在-(void)webViewDidFinishLoad:(UIWebView *)webView 中使用[webView stringByEvaluatingJavaScriptFromString:@"xxx"];即可 。

推荐阅读