zoukankan      html  css  js  c++  java
  • Android WebView与JavaScript交互操作(Demo)

    版权声明:本文为博主原创文章,未经博主同意不得转载。 https://blog.csdn.net/ma_hoking/article/details/32707013

    应用场景:

           为了使Android移动项目能够在较短的时间内完毕开发。同一时候减少技术人员开发的成本投入。往往会採用Hybrid APP的开发模式。相关Hybrid APP(混合型应用)參看:http://blog.csdn.net/mahoking/article/details/30235243 採用这种模式,为了解决更好的用户体验。可訪问本地资源的能力。势必须要了解与掌握Android(java)与JavaScript之间的交互、相互调用操作的方法与技术。

    【转载使用。请注明出处:http://blog.csdn.net/mahoking/article/details/32707013

    知识点介绍:

            本文重要的知识点补充是WebView对象(android.webkit.WebView)。
    在Android手机中内置了一款高性能webkit内核浏览器。在Android SDK中封装为一个叫做WebView组件。

     
            WebKit是Mac OS X v10.3及以上版本号所包括的软件框架(对v10.2.7及以上版本号也可通过软件更新获取)。 同一时候。WebKit也是Mac OS X的Safari网页浏览器的基础。WebKit是一个开源项目。主要由KDE的KHTML改动而来而且包括了一些来自苹果公司的一些组件。 
             传统上,WebKit包括一个网页引擎WebCore和一个脚本引擎JavaScriptCore。它们分别相应的是KDE的KHTML和KJS。只是, 随着JavaScript引擎的独立性越来越强,如今WebKit和WebCore已经基本上混用不分(比如Google Chrome和Maxthon 3採用V8引擎,却仍然宣称自己是WebKit内核)。
    【注意事项】
    1.AndroidManifest.xml中必须使用许可"android.permission.INTERNET",否则会出Web page not available错误。
    2.假设訪问的页面中有Javascript。则webview必须设置支持Javascript。webview.getSettings().setJavaScriptEnabled(true);  
    3.假设页面中链接,假设希望点击链接继续在当前browser中响应,而不是新开Android的系统browser中响应该链接,必须覆盖 webview的WebViewClient对象。
    4.对于第一点, 假设使用Android SDK提供了一个schema,前缀为"file:///android_asset/"。WebView遇到这种schema。会去载入assets文件夹下的资源。

    如"file:///android_asset/demo.html"。可不必使用许可"android.permission.INTERNET"。
            在使用WebView组件的过程中可能会接触到WebViewClient与WebChromeClient,那么这两个类究竟有什么不同呢?
             WebViewClient主要帮助WebView处理各种通知、请求事件的。比方:

    • onLoadResource
    • onPageStart
    • onPageFinish
    • onReceiveError 等
                  WebChromeClient主要辅助WebView处理Javascript的对话框、站点图标、站点title、载入进度等比方:
    • onCloseWindow(关闭WebView)
    • onCreateWindow()
    • onJsAlert (WebView上alert无效,须要定制WebChromeClient处理弹出)
    • onJsPrompt
    • onJsConfirm
    • onReceivedTitle等
                 两者存在非常多的区别。在实际使用过程中,假设你仅仅准备让WebView处理一些html的页面内容,仅仅用WebViewClient就能够了。假设须要产生更丰富的处理效果,比方JS对话框、进度条等,就要使用到WebChromeClient。更进一步的介绍将在以下进行。

    【转载使用,请注明出处:http://blog.csdn.net/mahoking/article/details/32707013


    使用方式:

    第一步:
    本文的演示程序的主界面为activity_web.xml,相应的Activtiy为WebActivtiy.java。
    【activity_web.xml】
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"
        tools:context=".WebActivity" >
        <LinearLayout android:layout_height="wrap_content" 
            android:background="@drawable/bgcolorblue"
            android:id="@+id/top_layout"
            android:layout_width="match_parent"
            android:layout_alignParentTop="true"
            android:orientation="horizontal">
            <Button android:layout_height="wrap_content"
                android:background="@drawable/titlebackground"
                android:layout_weight="1"
                android:layout_marginLeft="5dp"
                android:layout_marginRight="5dp"
                android:layout_width="match_parent"
                android:id="@+id/javaCallJs_web_button"
                android:text="Java调用无參数JS"/>
            <Button android:layout_height="wrap_content"
                android:background="@drawable/titlebackground"
                android:layout_weight="1"
                android:layout_marginLeft="5dp"
                android:layout_marginRight="5dp"
                android:layout_width="match_parent"
                android:id="@+id/javaCallJsParam_web_button"
                android:text="Java调用含參数JS"/>
        </LinearLayout>
        <WebView 
            android:layout_below="@id/top_layout"
            android:id="@+id/webView_web"
            android:layout_width="match_parent"
        	android:layout_height="match_parent"/>
    </RelativeLayout>

    【WebActivtiy.java】
    package cn.mahaochen.webviewtest;
    
    import cn.mahaochen.webviewtest.assist.ButtonListener;
    import cn.mahaochen.webviewtest.assist.MJavascriptInterface;
    import cn.mahaochen.webviewtest.assist.MWebChromeClient;
    import cn.mahaochen.webviewtest.assist.MWebViewClient;
    import android.os.Bundle;
    import android.app.Activity;
    import android.graphics.Color;
    import android.view.KeyEvent;
    import android.view.Menu;
    import android.webkit.WebView;
    import android.widget.Button;
    
    /**
     * @date 2014-6-20
     * @author MaHaochen
     */
    public class WebActivity extends Activity {
    	private WebView webView;
    	private Button paramButton;
    	private Button noParamButton;
    	
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_web);
    		initViews();
    	}
    
    	private void initViews() {
    		webView = (WebView) findViewById(R.id.webView_web);
    		// 设置WebView对JavaScript的支持
    		webView.getSettings().setJavaScriptEnabled(true);
    		// 从assets文件夹以下的载入html
    		webView.loadUrl("file:///android_asset/web.html");
    		//自己定义WebView的背景颜色
    		webView.setBackgroundColor(Color.TRANSPARENT);//先设置背景色为transparent
    //		webView.setBackgroundResource(R.drawable.webbg);//然后设置背景图片
    		webView.setBackgroundResource(R.drawable.bgcolorblue);
    //		webView.loadUrl("http://www.baidu.com");
    		MWebViewClient mWebViewClient = new MWebViewClient(webView,getApplicationContext());
    		webView.setWebViewClient(mWebViewClient);
    		MWebChromeClient mWebChromeClient = new MWebChromeClient(getApplicationContext());
    		webView.setWebChromeClient(mWebChromeClient);
    		//加入JS调用Android(Java)的方法接口
    		MJavascriptInterface mJavascriptInterface = new MJavascriptInterface(getApplicationContext());
    		webView.addJavascriptInterface(mJavascriptInterface, "WebViewFunc");
    		
    		//初始化按钮,并绑定监听事件。事件的作用是调用JS的功能方法
    		noParamButton = (Button) findViewById(R.id.javaCallJs_web_button);
    		paramButton = (Button) findViewById(R.id.javaCallJsParam_web_button);
    		ButtonListener buttonListener = new ButtonListener(webView);
    		noParamButton.setOnClickListener(buttonListener);
    		paramButton.setOnClickListener(buttonListener);
    	}
    	
    	/**
    	 * 退出监听
    	 */
    	@Override
    	public boolean dispatchKeyEvent(KeyEvent event) {
    			if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
    					&& event.getAction() == KeyEvent.ACTION_DOWN
    					&& event.getRepeatCount() == 0
    					) {
    				if(webView.canGoBack()){
    					webView.goBack();
    					return false;
    				}else {
    					WebActivity.this.finish();
    					return true;
    				}
    			}
    			return false;
    //		return super.dispatchKeyEvent(event);
    	}
    
    	//*******************华丽的切割线***********************
    	@Override
    	public boolean onCreateOptionsMenu(Menu menu) {
    //		getMenuInflater().inflate(R.menu.web, menu);
    		return true;
    	}
    }

    第二步:
            从第一步能够看到,以上补充了分别继承自WebViewClient、WebChromeClient的MWebViewClient、MWebChromeClient对象和MJavascriptInterface、ButtonListener对象。相应的对象的相关方法与操作的介绍将会在代码中较具体的叙述。
    【MWebViewClient.java】
    package cn.mahaochen.webviewtest.assist;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.net.http.SslError;
    import android.util.Log;
    import android.webkit.SslErrorHandler;
    import android.webkit.WebView;
    import android.webkit.WebViewClient;
    import android.widget.Toast;
    
    /**
     * @date 2014-6-20
     * @author MaHaochen
     */
    public class MWebViewClient  extends WebViewClient {
    
    	private WebView webView;
    	private Context context;
    	
    	public MWebViewClient(WebView webView) {
    		super();
    		this.webView = webView;
    	}
    
    	public MWebViewClient(WebView webView, Context context) {
    		super();
    		this.webView = webView;
    		this.context = context;
    	}
    
    	/**
    	 * 在点击请求的是链接是才会调用,
    	 * 重写此方法返回true表明点击网页里面的链接还是在当前的webview里跳转,不跳到浏览器那边。
    	 */
    	@Override
    	public boolean shouldOverrideUrlLoading(WebView view, String url) {
    		// 使用自己的WebView组件来响应Url载入事件。而不是使用默认浏览器器载入页面
    		webView.loadUrl(url);
    		// 记得消耗掉这个事件。

    给不知道的朋友再解释一下。Android中返回True的意思就是到此为止, // 事件就会不会冒泡传递了,我们称之为消耗掉 return true; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { // Toast.makeText(context, "WebViewClient.onPageStarted页面開始载入", Toast.LENGTH_SHORT).show(); Log.e("WebActivity", "页面载入開始"); super.onPageStarted(view, url, favicon); } @Override public void onPageFinished(WebView view, String url) { // Toast.makeText(context, "WebViewClient.onPageFinished页面载入完毕", Toast.LENGTH_SHORT).show(); Log.e("WebActivity", "页面载入完毕"); super.onPageFinished(view, url); } /** * 在载入页面资源时会调用,每个资源(比方图片)的载入都会调用一次。 */ @Override public void onLoadResource(WebView view, String url) { // Toast.makeText(context, "WebViewClient.onLoadResource", Toast.LENGTH_SHORT).show(); Log.e("WebActivity", "onLoadResource"); super.onLoadResource(view, url); } /** * 重写此方法能够让webview处理https请求 [拓展] */ @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { super.onReceivedSslError(view, handler, error); } }


    【MWebChromeClient.java】
    package cn.mahaochen.webviewtest.assist;
    
    import android.app.Activity;
    import android.content.Context;
    import android.webkit.JsPromptResult;
    import android.webkit.JsResult;
    import android.webkit.WebChromeClient;
    import android.webkit.WebView;
    
    /**
     * @date 2014-6-20
     * @author MaHaochen
     */
    public class MWebChromeClient extends WebChromeClient {
    
    	private Context context;
    	
    	public MWebChromeClient(Context context) {
    		super();
    		this.context = context;
    	}
    
    	// 处理Alert事件
    	@Override
    	public boolean onJsAlert(WebView view, String url, String message,
    			JsResult result) {
    		return super.onJsAlert(view, url, message, result);
    	}
    
    	// onReceivedTitle()方法改动网页标题
    	@Override
    	public void onReceivedTitle(WebView view, String title) {
    		((Activity)context).setTitle("能够用onReceivedTitle()方法改动网页标题");
    		super.onReceivedTitle(view, title);
    	}
    
    	// 处理Confirm事件
    	@Override
    	public boolean onJsConfirm(WebView view, String url, String message,
    			JsResult result) {
    		return super.onJsConfirm(view, url, message, result);
    	}
    
    	// 处理提示事件
    	@Override
    	public boolean onJsPrompt(WebView view, String url, String message,
    			String defaultValue, JsPromptResult result) {
    		return super.onJsPrompt(view, url, message, defaultValue, result);
    	}
    }

    【MJavascriptInterface.java】
    package cn.mahaochen.webviewtest.assist;
    
    import android.content.Context;
    import android.widget.Toast;
    
    /**
     * @date 2014-6-20
     * @author MaHaochen
     */
    public class MJavascriptInterface {
    
    	private Context context;
    
    	public MJavascriptInterface(Context context) {
    		super();
    		this.context = context;
    	}
    	
    	/**
    	 * JS调用Android(Java)无參数的方法
    	 */
    	public void jsCallWebView() {
    		Toast.makeText(context, "JS Call Java!",
    				Toast.LENGTH_SHORT).show();
    	}
    
    	/**
    	 * JS调用Android(Java)含參数的方法
    	 * @param param
    	 */
    	public void jsCallWebView(String param) {
    		Toast.makeText(context, "JS Call Java!" + param,
    				Toast.LENGTH_SHORT).show();
    	}
    }

    【ButtonListener.java】
    package cn.mahaochen.webviewtest.assist;
    
    import cn.mahaochen.webviewtest.R;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.webkit.WebView;
    
    /**
     * @date 2014-6-20
     * @author MaHaochen
     */
    public class ButtonListener implements OnClickListener{
    	private WebView webView;
    	public ButtonListener(WebView webView) {
    		super();
    		this.webView = webView;
    	}
    
    	@Override
    	public void onClick(View v) {
    		switch (v.getId()) {
    		case R.id.javaCallJs_web_button:
    			webView.loadUrl("javascript:javacalljs()"); // 无參数调用
    			break;
    		case R.id.javaCallJsParam_web_button:
    		webView.loadUrl("javascript:javacalljsparam(" + "'含參数'"+ ")"); // 无參数调用
    			break;
    		default:
    			break;
    		}
    	}
    }

    第三步:
            以上是所有的Java代码部分的信息。本例旨为演示WebView(Java)与JS(JavaScript)的互操作。

    所以须要补充另两个资源文件web.html与jump.html页面。该页面位于项目的assets文件夹下。


    【web.html】
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=GBK"/>
    <script type="text/javascript">
    
    //Java调用JS代码无參数
    function javacalljs(){
    	 document.getElementById("content").innerHTML +=     
             "<br>java调用了js函数";  
    }
    
    //Java调用JS代码有參数
    function javacalljsparam(param){
    	 document.getElementById("content").innerHTML +=     
             "<br>java调用了js函数含參数param"+param;  
    }
    
    function testFunc(){
    
    	window.WebViewFunc.jsCallWebView();
    }
    
    </script>
    
    <title>測试页面</title>
    </head>
    <body>
    <a onClick="testFunc()">无參数JS调用java代码</a><br/> 
    <a onClick="window.WebViewFunc.jsCallWebView('含有參数')">含參数调用java代码</a><br/> 
    <br />
    <div id="content">内容显示 <a href="jump.html" target="_self">跳转新页面jump.html</a></div>  
    </body>
    </html>

    【jump.html】
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=GBK"/>
    <script type="text/javascript">
    
    //Java调用JS代码无參数
    function javacalljs(){
    	 document.getElementById("content").innerHTML +=     
             "<br>java调用了js函数";  
    }
    
    //Java调用JS代码有參数
    function javacalljsparam(param){
    	 document.getElementById("content").innerHTML +=     
             "<br>java调用了js函数含參数param"+param;  
    }
    
    function testFunc(){
    
    	window.WebViewFunc.jsCallWebView();
    }
    
    </script>
    
    <title>測试页面</title>
    </head>
    <body>
    <a onClick="testFunc()">无參数JS调用java代码</a><br/> 
    <a onClick="window.WebViewFunc.jsCallWebView('含有參数')">含參数调用java代码</a><br/> 
    <br />
    <div id="content">内容显示</div>  
    </body>
    </html>

    ■注:因为本演示案例加入必要的图片文件与样式文件。才干够出现以下效果截图,所以假设获取完整的效果,请在【下载地址】栏。自行下载完整项目。


    【转载使用,请注明出处:http://blog.csdn.net/mahoking/article/details/32707013

    效果截图:


    下载地址:


    參考文献:

    1、 http://www.cnblogs.com/oakpip/archive/2011/04/08/2009800.html
    2、 http://blog.csdn.net/jackyhuangch/article/details/8310033

查看全文
  • 相关阅读:
    java中的 equals 与 ==
    String类的内存分配
    SVN用命令行更换本地副本IP地址
    npoi 设置单元格格式
    net core 微服务框架 Viper 调用链路追踪
    打不死的小强 .net core 微服务 快速开发框架 Viper 限流
    net core 微服务 快速开发框架 Viper 初体验20201017
    Anno 框架 增加缓存、限流策略、事件总线、支持 thrift grpc 作为底层传输
    net core 微服务 快速开发框架
    Viper 微服务框架 编写一个hello world 插件02
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10700309.html
  • Copyright © 2011-2022 走看看