• webview与js交互


    对于android初学者应该都了解webView这个组件。之前我也是对其进行了一些简单的了解,但是在一个项目中不得不用webview的时候,发现了webview的强大之处,今天就分享一下使用webview的一些经验。

    1、首先了解一下webview。

    webview介绍的原文如下:A View that displays web pages. This class is the basis upon which you can roll your own web browser or simply display some online content within your Activity. It uses the WebKit rendering engine to display web pages and includes methods to navigate forward and backward through a history, zoom in and out, perform text searches and more.

    从上面你应该了解到了基本功能,也就是显示网页。之所以我说webview功能强大是因为它和js的交互非常方便,很简单就可以实现。

    2、webview能做什么?

    ①webView可以利用html做界面布局,虽然目前还比较少人这么使用,不过我相信当一些客户端需要复杂的图文(图文都是动态生成)混排的时候它肯定是个不错的选择。

    ②直接显示网页,这功能当然也是它最基本的功能。

    ③和js交互。(如果你的js基础比java基础好的话那么采用这种方式做一些复杂的处理是个不错的选择)。

    3、如何使用webview?

    这里直接用一个svn上取下的demo,先上demo后讲解。demo的结构图如下:

    WebViewDemo.java

    复制代码
    package com.google.android.webviewdemo;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.util.Log;
    import android.webkit.JsResult;
    import android.webkit.WebChromeClient;
    import android.webkit.WebSettings;
    import android.webkit.WebView;
    
    /**
     * Demonstrates how to embed a WebView in your activity. Also demonstrates how
     * to have javascript in the WebView call into the activity, and how the activity 
     * can invoke javascript.
     * <p>
     * In this example, clicking on the android in the WebView will result in a call into
     * the activities code in {@link DemoJavaScriptInterface#clickOnAndroid()}. This code
     * will turn around and invoke javascript using the {@link WebView#loadUrl(String)}
     * method.
     * <p>
     * Obviously all of this could have been accomplished without calling into the activity
     * and then back into javascript, but this code is intended to show how to set up the 
     * code paths for this sort of communication.
     *
     */
    public class WebViewDemo extends Activity {
    
        private static final String LOG_TAG = "WebViewDemo";
    
        private WebView mWebView;
    
        private Handler mHandler = new Handler();
    
        @Override
        public void onCreate(Bundle icicle) {
            super.onCreate(icicle);
            setContentView(R.layout.main);
            mWebView = (WebView) findViewById(R.id.webview);
    
            WebSettings webSettings = mWebView.getSettings();
            webSettings.setSavePassword(false);
            webSettings.setSaveFormData(false);
            webSettings.setJavaScriptEnabled(true);
            webSettings.setSupportZoom(false);
    
            mWebView.setWebChromeClient(new MyWebChromeClient());
    
            mWebView.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");
    
            mWebView.loadUrl("file:///android_asset/demo.html");
        }
    
        final class DemoJavaScriptInterface {
    
            DemoJavaScriptInterface() {
            }
    
            /**
             * This is not called on the UI thread. Post a runnable to invoke
             * loadUrl on the UI thread.
             */
            public void clickOnAndroid() {
                mHandler.post(new Runnable() {
                    public void run() {
                        mWebView.loadUrl("javascript:wave()");
                    }
                });
    
            }
        }
    
        /**
         * Provides a hook for calling "alert" from javascript. Useful for
         * debugging your javascript.
         */
        final class MyWebChromeClient extends WebChromeClient {
            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                Log.d(LOG_TAG, message);
                result.confirm();
                return true;
            }
        }
    }
    复制代码

    demo.html

    复制代码
    <html>
        <script language="javascript">
            /* This function is invoked by the activity */
            function wave() {
                alert("1");
                document.getElementById("droid").src="android_waving.png";
                alert("2");
            }
        </script>
        <body>
            <!-- Calls into the javascript interface for the activity -->
            <a onClick="window.demo.clickOnAndroid()"><div style="80px;
                margin:0px auto;
                padding:10px;
                text-align:center;
                border:2px solid #202020;" >
                    <img id="droid" src="android_normal.png"/><br>
                    Click me!
            </div></a>
        </body>
    </html>
    复制代码

    main.xml

    复制代码
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
        
        <TextView  
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content" 
            android:text="@string/intro"
            android:padding="4dip"
            android:textSize="16sp"
            />
        
        <WebView
            android:id="@+id/webview"
            android:layout_width="fill_parent" 
            android:layout_height="0dip"
            android:layout_weight="1"
            />
            
    </LinearLayout>
    复制代码

    4、如何交互?

    ①android如何调用js。

    调用 形式:

    mWebView.loadUrl("javascript:wave()");

    其中wave()是js中的一个方法,当然你可以把这个方法改成其他的方法,也就是android调用其他的方法。

    ②js如何调用android。

    调用形式:

    <a onClick="window.demo.clickOnAndroid()">

    代码中的“demo”是在android中指定的调用名称,即

     mWebView.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");

    代码中的clickOnAndroid()是“demo”对应的对象:new DemoJavaScriptInterface() 中的一个方法。

    ③双向交互。

    当然是把前面的两种方式组合一下就可以了。

    5、讲解demo。

    现在你一定了解了android和js的交互了。是时候分析一些demo了,根据上面讲的你也应该比较清楚了。具体交互流程如下:

    ①点击图片,则在js端直接调用android上的方法clickOnAndroid();

    ②clickOnAndroid()方法(利用线程)调用js的方法。

    ③被②调用的js直接控制html。

    个人总结:利用webView的这种方式在有些时候UI布局就可以转成相应的html代码编写了,而html布局样式之类有DW这样强大的工具,而且网上很多源码,很多代码片。在UI和视觉效果上就会节省很多时间,重复发明轮子没有任何意义。

    欢迎各位朋友留言交流。

    WebView.loadUrl方法弹出外部浏览器的解决办法
    跳转到同一个页面,之前传进来的地址就可以直接加载在页面上,这次就自动弹出来了浏览器,页面上没有任何内容,而两次使用的都是 
    webView.loadUrl(url)语句,网址格式也大体相同。这时候我们要统一成在界面显示,也就是说不弹出浏览器。 
    只要覆盖一个方法: 
    mywebView.setWebViewClient(new WebViewClient() {
    public boolean shouldOverrideUrlLoading(WebView view, String url)
      { //  重写此方法表明点击网页里面的链接还是在当前的webview里跳转,不跳到浏览器那边
      view.loadUrl(url);
      return true;
      }
    });
    就可以解决这个问题 
        @Override
        public void onClick(View arg0) {
            // TODO Auto-generated method stub
    
            web_view.loadUrl("http://www.baidu.com");
    
            // WebChromeClienty用来处理WebView的Javascript的对话框、
            // 网站图标、网站title、加载进度等,重写里面的方法即可
            web_view.setWebChromeClient(new WebChromeClient());// 此方法此处可不写
    
            // WebViewClient用来处理WebView各种通知、请求事件等,重写里面的方法即可
            web_view.setWebViewClient(new WebViewClient() {
    
                // 点击页面中的链接会调用这个方法
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    // TODO Auto-generated method stub
    
                    // 跳转到另外的activity
                    Intent intent = new Intent(getApplication(),
                            SecondActivity.class);
                    startActivity(intent);
    
                    Log.i("qing", "shouldOverrideUrlLoading..." + url);
                    return super.shouldOverrideUrlLoading(view, url);
                }
    
            });
    
        }
    
    }
    1. shouldOverrideUrlLoading(WebView view, String url)
        官方注释:Give the host application a chance to take over the control when a new url is about to be loaded in the current WebView. If WebViewClient is not provided,by default WebView will ask Activity Manager to choose the proper handler for the url. If WebViewClient is provided, return true means the host application handles the url, while return false means the current WebView handles the url. This method is not called for requests using the POST "method". 
    翻译:当一个新的url要在当前WebView进行加载的时候,这个方法给应用一个机会来控制url的处理。如果WebView没有setWebViewClient,则默认操作是WebView将询问Activity Manager获取合适的handler处理url。如果WebView设置了setWebViewClient,返回true代表当前应用来处理url,返回false则代表当前webview来处理url。如果http请求是POST方法,该方法将不会被调用。
    代码示例:/** 
     * 所有以www.example.com开头的url调用系统浏览器打开 其他的url在当前webview打开 
     */
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) { 
      if (url.indexOf("http://www.example.com") != -1) { 
        // 调用系统默认浏览器处理url 
        view.stopLoading(); 
        view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); 
        return true; 
      } 
      return false; 
    } 
    
    2. shouleOverrideKeyEvent(WebView view, KeyEvent event)
        官方注释:Give the host application a chance to handle the key event synchronously. e.g. menu shortcut key events need to be filtered this way. If return true, WebView will not handle the key event. If return false, WebView will always handle the key event, so none of the super in the view chain will see the key event. The default behavior returns false. 
    翻译:给当前应用一个机会来异步处理按键事件。返回true,WebView将不会处理该按键事件,返回false,WebView将处理该按键事件。默认返回是false。
    3. onPageStarted(WebView view, String url, Bitmap favicon)和onPageFinished(WebView view, String url)
        官方注释:Notify the host application that a page has started loading. This method is called once for each main frame load so a page with iframes or framesets will call onPageStarted one time for the main frame. This also means that onPageStarted will not be called when the contents of an embedded frame changes, i.e. clicking a link whose target is an iframe. 
    翻译:当页面开始加载时被调用。但是,当页面被嵌套时(例如iframe里有一个链接跳转),该方法将不会被调用。(今天就遇到了这种情况,可以通过重载onLoadResource来控制url跳转)
        官方注释:Notify the host application that a page has finished loading. This method is called only for main frame. When onPageFinished() is called, the rendering picture may not be updated yet. To get the notification for the new Picture, use onNewPicture(WebView, Picture). 
    翻译:在页面加载结束时被调用。代码示例:
        // 获取页面加载时间  
    private long startTime; 
     private long endTime; 
     private long spendTime; 
       
     @Override
     public void onPageFinished(WebView view, String url) { 
       endTime = System.currentTimeMillis(); 
       spendTime = endTime - startTime; 
       Toast.makeText(view.getContext(), "spend time is:" + spendTime, Toast.LENGTH_SHORT).show(); 
     } 
       
     @Override
     public void onPageStarted(WebView view, String url, Bitmap favicon) { 
       startTime = System.currentTimeMillis(); 
     } 4. onLoadResource(WebView view, String url)
        官方注释:Notify the host application that the WebView will load the resource specified by the given url. 
    翻译:通知应用程序WebView将要加载指定url的资源,每一个资源(例如图片,嵌套url,js,css文件)。(可以通过该方法处理iframe嵌套的url)
    代码示例:
    
    @Override
    public void onLoadResource(WebView view, String url) { 
      if (url.indexOf("http://www.example.com") != -1 && view != null) { 
        view.stopLoading(); 
        view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); 
      }       
    } 
  • 相关阅读:
    Intent
    BroadcastReceiver
    AsyncTask两种线程池
    多线程、Service与IntentService的比较
    AsyncTask
    转:Android开发:使用DDMS Heap进行内存泄露调试
    (原创)Android Binder设计与实现
    (原)一句mpAudioPolicy->get_input引发的血案
    LOCAL_WHOLE_STATIC_LIBRARIES与LOCAL_STATIC_LIBRARIES的区别
    非static成员函数通过类名::来调用,空指针调用成员方法不出错!
  • 原文地址:https://www.cnblogs.com/yaowen/p/5407010.html
Copyright © 2020-2023  润新知