android中在webview注入执行javascript方法

nandy007
   2015-05-23 17:41:34发布  2016-12-17 15:38:35更新 0收藏, 11693浏览
ExMobi原生扩展
已关闭
0

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)webViewDidFinishLoadUIWebView *)webView 中使用[webView stringByEvaluatingJavaScriptFromString"xxx"];即可 。

3个回答

0

首先谢谢你的解答,但是我的代码和你写的第一种是一样的,你的注意点我都注意到了,但是还是不行,所以想请你看一下我的那个贴的附件源码。我也是在onpagefinished里面注入的,但是就是不执行,目前菜鸟,还没找到原因,网上的方法都尝试了。求解答

1

2

IMG20150523140057.jpg  (0.40M  下载次数:390次)

IMG20150523141938.jpg  (0.42M  下载次数:253次)

xbding
    2015-05-25 09:12:35回答  2016-12-17 15:39:08更新
0

不清楚你错在哪里,这是我一个项目中的代码,提出来给你做比较

package com.appplugin.ImageShow360Component;


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import com.appplugin.ImageShow360Component.stub.ResManager;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

public class ImageShow360ComponentRelayout extends RelativeLayout {
        
        public Context context_;
        private ImageShow360Component mCom;
        
        
        private WebView mWebView;
        private Handler mHandler;
    private WebSettings mWebSettings;
    private String zipfilepath;

        public ImageShow360ComponentRelayout(Context context) {
                super(context);
                context_ = context;
                // TODO Auto-generated constructor stub
        }
        public void initRelayout(ImageShow360Component imageShow360Com) {
                // TODO Auto-generated method stub
                mCom = imageShow360Com;                
        //  String  getAbsolutePath =  mCom.helper_getAbsolutePath("res:image/bg_login.jpg");                
          //Log.e("2222222222222222getAbsolutePath",getAbsolutePath);                
                LayoutInflater inflater = LayoutInflater.from(context_);
                LinearLayout viewp = (LinearLayout) inflater.inflate(ResManager.getInstance().getResourcesIdentifier("R.layout.spritespin_main"), null);
                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
                                android.view.ViewGroup.LayoutParams.MATCH_PARENT,
                                android.view.ViewGroup.LayoutParams.MATCH_PARENT);
                this.addView(viewp, params);

                 mWebView = (WebView) this.findViewById(ResManager.getInstance().getResourcesIdentifier("R.id.spritespin_webview"));
        
                /* Button mbutton = (Button) this.findViewById(R.id.spritespin_button);
                 
                
                 mbutton.setOnClickListener(new OnClickListener() {
                        
                        @Override
                        public void onClick(View v) {
                                // TODO Auto-generated method stub
                                
                                changeimage("res:image/car.zip");
                                Log.e("点击了按钮","点击了按钮");
                                
                        }
                });*/
                 
                 mHandler = new Handler();
 
        // 设置支持JavaScript等
                       
         
        mWebSettings = mWebView.getSettings();
        mWebSettings.setJavaScriptEnabled(true);
        mWebSettings.setBuiltInZoomControls(false);
        mWebSettings.setLightTouchEnabled(true);
        mWebSettings.setSupportZoom(false);
        mWebView.setHapticFeedbackEnabled(false);
       // mWebView.setBackgroundColor(0x00000000);
          // mWebView.setInitialScale(0); // 改变这个值可以设定初始大小
  
          //重要,用于与页面交互!
        mWebView.addJavascriptInterface(new Object() {
              @SuppressWarnings("unused")
            public void oneClick(final String locX, final String locY) {//此处的参数可传入作为js参数
                 mHandler.post(new Runnable() {
                      public void run() {
                        
                      }
                });
              }
        }, "demo");//此名称在页面中被调用,方法如下:
         //<body onClick="window.demo.clickOnAndroid(event.pageX,event.pageY)">
 
      
        
        if(mCom.get("imagezip").length() != 0)
        {
                
                changeimage(mCom.get("imagezip"));
        }
                 
                
        }
        
        public void getimages() {
                // TODO Auto-generated method stub
                new Thread(new Runnable() {
                        @Override
                        public void run() {
                                
                                handler.sendEmptyMessage(1);
                        }
                }).start();
                
        }
    
        Handler handler = new Handler() {
                public void handleMessage(android.os.Message msg) {
                        Log.e("执行初始方法","执行初始方法"); 
                                                                                                
                        File zipfile=new File(zipfilepath);
                        try {
                                String frames = upZipFile(zipfile,"/mnt/sdcard/imageshow360");
                                                        
                                //["/mnt/sdcard/imageshow360/car/01.png"
                                String path = frames.split(",")[0].replaceAll("\\[|\"", "");
                                Log.e("1111111111111111111111",path);
                                
                                Bitmap imageBitmap = BitmapFactory.decodeFile(path);
                                
                                int w = imageBitmap.getWidth();
                                int h = imageBitmap.getHeight();
                                
                                mWebView.loadUrl("javascript:init('"+frames+"','"+w+"','"+h+"')");
                        } catch (ZipException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                        } catch (IOException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                        }
                                                
                };
        };
    
        
        
        /**
            * 解压缩功能.
            * 将zipFile文件解压到folderPath目录下.
            * @throws Exception
        */
            public String upZipFile(File zipFile, String folderPath)throws ZipException,IOException {
            //public static void upZipFile() throws Exception{
                    String imagesArrayStr="[";
                ZipFile zfile=new ZipFile(zipFile);
                Enumeration zList=zfile.entries();
                ZipEntry ze=null;
                byte[] buf=new byte[1024];
                while(zList.hasMoreElements()){
                    ze=(ZipEntry)zList.nextElement();    
                    if(ze.isDirectory()){
                        Log.d("upZipFile", "ze.getName() = "+ze.getName());
                        String dirstr = folderPath + ze.getName();
                        //dirstr.trim();
                        dirstr = new String(dirstr.getBytes("8859_1"), "GB2312");
                        Log.d("upZipFile", "str = "+dirstr);
                        File f=new File(dirstr);
                        f.mkdir();
                        continue;
                    }
                    Log.d("upZipFile", "ze.getName() = "+ze.getName());
                    
                    imagesArrayStr = imagesArrayStr + "\"/mnt/sdcard/imageshow360/"+ze.getName()+"\",";
                    
                    OutputStream os=new BufferedOutputStream(new FileOutputStream(getRealFileName(folderPath, ze.getName())));
                    InputStream is=new BufferedInputStream(zfile.getInputStream(ze));
                    int readLen=0;
                    while ((readLen=is.read(buf, 0, 1024))!=-1) {
                        os.write(buf, 0, readLen);
                    }
                    is.close();
                    os.close();    
                }
                
                imagesArrayStr = imagesArrayStr + "]";
                zfile.close();
               // Log.d("upZipFile",imagesArrayStr);
                return imagesArrayStr;
            }

            /**
            * 给定根目录,返回一个相对路径所对应的实际文件名.
            * @param baseDir 指定根目录
            * @param absFileName 相对路径名,来自于ZipEntry中的name
            * @return java.io.File 实际的文件
        */
            public static File getRealFileName(String baseDir, String absFileName){
                String[] dirs=absFileName.split("/");
                File ret=new File(baseDir);
                String substr = null;
                if(dirs.length>1){
                    for (int i = 0; i < dirs.length-1;i++) {
                        substr = dirs[i];
                        try {
                            //substr.trim();
                            substr = new String(substr.getBytes("8859_1"), "GB2312");
                            
                        } catch (UnsupportedEncodingException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        ret=new File(ret, substr);
                        
                    }
                    Log.d("upZipFile", "1ret = "+ret);
                    if(!ret.exists())
                        ret.mkdirs();
                    substr = dirs[dirs.length-1];
                    try {
                        //substr.trim();
                        substr = new String(substr.getBytes("8859_1"), "GB2312");
                        Log.d("upZipFile", "substr = "+substr);
                    } catch (UnsupportedEncodingException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    
                    ret=new File(ret, substr);
                    Log.d("upZipFile", "2ret = "+ret);
                    return ret;
                }
                return ret;
            }

                public void changeimage(String filepath) {
                        // TODO Auto-generated method stub
                        
                          mWebView.loadUrl("file:///android_asset/examples/demos.html");
                         zipfilepath =  mCom.helper_getAbsolutePath(filepath);
                        
                         mWebView.setWebViewClient(new WebViewClient(){
                                @Override
                                        public void onPageFinished(WebView view, String url) {
                                                super.onPageFinished(view, url);
                                                getimages();  
                                        }                
                        });  
                        
                }
                
                
        
}

对应demos.html

<!DOCTYPE html>
<html >
  <head>
    <meta content='text/html;charset=UTF-8' http-equiv='content-type'>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0"/>
    <title></title>
    <script src="javascripts/jquery-1.7.2.min.js" type="text/javascript"></script>
    <script src="javascripts/src/spritespin.js" type="text/javascript"></script>
    <script type="text/javascript">
    function init(framestr,w,h){
            
    
        var frames = eval(framestr);
        
      $("#360frames").spritespin({
        width     : w,
        height    : h,
        frames    : frames.length,
        behavior  : "drag", // "hold" drag
        module    : "360",
        sense     : 1,
        source    : frames,
        animate   : true,
        loop      : true,
        frameWrap : true,
        frameStep : 1,
        frameTime : 60,
        enableCanvas : true
      });
         
    }
    </script>

    <style type="text/css">
      .spritespin-preload {
        background : url('images/ajax-loader.gif') no-repeat 50% 50%;
      }
      .spritespin-instance {
        border: 0px dashed;
        margin: 0px;
        width:100%;
           
      }
      .spritespin-stage
      {
         text-align:center;
      }
      body {
          text-align:center;
          margin: 0 auto;
           width:100%;
    }
   
   
    </style>
   
  </head>
  <body>
     
    <div id="360frames"></div>  
  <!--   <input type="text" id="ddd"/> -->
    
  </body>
</html>

yuanhongqian
    2015-05-25 10:41:47回答  2016-12-17 15:39:45更新
0

为什么没人跟我说 alert要重写onjsalert方法呢~~写的一直都是对的~~

xbding
    2015-05-27 08:57:41回答

我要回答

下载APP
扫码下载栗子社区APP