WebView中Js与Android本地函数的相互调用

介绍

随着Html5的普及,html在表现力上不一定比原生应用差,并且有很强的扩展兼容性,所以越来越多的应用是采用Html与Android原生混合开发模式实现。

既然要实现混合开发,那么Js与Android原生函数的相互调用就必不可少了。这里写了一个demo,实现点击html中的图片进行本地展示。

原理

1、Android调用js很简单,直接webView.loadUrl("javascript:JS中的方法名称()");即可。

2、js调用Android方法,需要使用WebView.addJavascriptInterface(Object obj, String interfaceName)这个方法告诉WebView我要添加一个Js接口调用本地函数。

3、demo中用到了universalimageloader与PhotoView实现图片加载与浏览

http://www.cnblogs.com/leestar54/p/4220068.htmlhttp://www.cnblogs.com/leestar54/p/4105726.html

4、demo中涉及到了一个JS闭包的问题,闭包中所记录的自由变量,只是对这个变量的一个引用,而非变量的值,当这个变量被改变了,闭包里获取到的变量值,也会被改变.

http://www.cnblogs.com/mzwr1982/archive/2012/05/20/2509295.html

实现

MainActivity

package com.example.javascriptinterface;

import java.util.ArrayList;

import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;

import android.support.v7.app.ActionBarActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.graphics.Bitmap;

public class MainActivity extends ActionBarActivity {
    private WebView webView1;
    private ProgressDialog pbar;
    private Handler mHandler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化通用图片加载器
        DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
                .cacheInMemory(true).cacheOnDisk(true).build();
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
                this).defaultDisplayImageOptions(defaultOptions).build();
        ImageLoader.getInstance().init(config);

        pbar = new ProgressDialog(MainActivity.this);
        pbar.setTitle("提示");
        pbar.setMessage("加载中…");
        pbar.setIndeterminate(true);
        webView1 = (WebView) findViewById(R.id.webView1);
        webView1.setWebViewClient(new WebViewClient() {

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
                pbar.show();
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                pbar.dismiss();
                //网页加载完成,Weiview中注入Js
                addImageClickListner();
            }

        });

        //允许webview执行JS
        webView1.getSettings().setJavaScriptEnabled(true);
        webView1.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
        webView1.loadUrl("http://news.163.com/jnews/mobile/#detail/99/AI8ESHB000964J4O");
        //添加JS接口,这样就可以在js中调用本地函数了。
        webView1.addJavascriptInterface(new JavascriptInterface(this),
                "imagelistner");
    }

    public class JavascriptInterface {

        private Context context;

        public JavascriptInterface(Context context) {
            this.context = context;
        }

        //一定要声明该函数是JavascriptInterface
        @android.webkit.JavascriptInterface
        public void openImage(String img, final int index) {

            final String simg = img;
            final int findex = index;

            mHandler.post(new Runnable() {

                @Override
                public void run() {
                    String[] imgs = simg.split(",");
                    ArrayList<String> imgsUrl = new ArrayList<String>();
                    for (String s : imgs) {
                        imgsUrl.add(s);
                    }
                    Intent intent = new Intent();
                    intent.putExtra("index", findex);//当前点击图片index
                    intent.putStringArrayListExtra("infos", imgsUrl);//图片链接数组
                    intent.setClass(context, PhotosActivity.class);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    context.startActivity(intent);
                }
            });

        }
    }

    private void addImageClickListner() {

        //click函数解决了闭包,用来实现显示当前点击图片
        webView1.loadUrl("javascript:(function(){"
                + "var objs = document.getElementsByTagName(\"img\");"
                + "var imgurl='';"
                + "for(var i=0;i<objs.length;i++)  "
                + "{"
                + "imgurl+=objs[i].src+',';"
                + " objs[i].onclick=(function(j){return function(){window.imagelistner.openImage(imgurl,j);}; })(i);  "
                + "}" + "} " + ")()");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

完成之后看起来是这样的

demo地址

链接:http://pan.baidu.com/s/1dDEPPkP 密码:7y6g

 

posted @ 2015-02-15 15:05  leestar54  阅读(5060)  评论(0编辑  收藏  举报