• Android学习笔记_32_通过WebView实现JS代码与Java代码互相通信


    webview两种实现方法,覆盖onKeyDown()方法

    缓存

    WebSettings应用注意的几个问题

    1、要实现JS代码与Java代码互相通信,需要通过Android的WebView控件,在视图布局界面引入该控件,代码如下:

    <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:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".MainActivity" >
    
        <WebView
            android:id="@+id/webView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
        />
    </RelativeLayout>

    2、准备html界面:

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    <script type="text/javascript">
        function show(jsondata){
            var jsonobjs = eval(jsondata);
            var table=document.getElementById("personTable");
            for(var y=0;y<jsonobjs.length;y++){
                var tr = table.insertRow(table.rows.length);
                var td1=tr.insertCell(0);
                td1.align="center";
                var td2=tr.insertCell(1);
                td2.align="center";
                
                td1.innerHTML=jsonobjs[y].name;
                td2.innerHTML="<a href='javascript:contact.call(""+jsonobjs[y].phone+"")'>"+jsonobjs[y].phone+"</a>";
            }
        }
    
    </script>
    </head>
    <body onload="javascript:contact.showContacts()">
        <table border="0" cellspacing="0" id="personTable" width="100%">
            <tr>
                <td width="35%" align="right">姓名</td><td align="center">电话</td>
            </tr>
        </table>
        <a href="javascript:window.location.reload()">刷新</a>
    </body>
    </html>

      在上述代码中类似"javascript:contact.showContacts()"这样的写法,它代表的意思是调用javascript对象contact的showContacts方法。而对象contact就要从后台java代码中获取。

    3、在java代码中创建javascript对象:

    package com.example.html;
    
    import java.util.List;
    
    import org.json.JSONArray;
    import org.json.JSONObject;
    
    import com.example.service.ContactService;
    
    import android.net.Uri;
    import android.os.Bundle;
    import android.annotation.SuppressLint;
    import android.app.Activity;
    import android.content.Intent;
    import android.view.Menu;
    import android.webkit.WebView;
    
    public class MainActivity extends Activity {
        private WebView webView;
        private ContactService contactService;
    
        @SuppressLint({ "JavascriptInterface", "SetJavaScriptEnabled" })
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            webView = (WebView) this.findViewById(R.id.webView);
            webView.loadUrl("file:///android_asset/contact.html");// 加载html文件
            webView.getSettings().setJavaScriptEnabled(true);// 启用javascript
    
            // 第一个参数在javascript中的一个对象,第二个参数在javascript中当前对象的变量
            webView.addJavascriptInterface(new JSObject(), "contact");
            contactService = new ContactService();
    
        }
    
        private final class JSObject {
            // 显示联系人列表,对于高版本的需要用@JavascriptInterface注释,否则调不到该方法
            @JavascriptInterfacepublic void showContacts() {
                try {
                    List<ContactService.Contact> contacts = contactService.getContacts();
                    JSONArray jsonArray = new JSONArray();
                    for (ContactService.Contact contact : contacts) {
                        JSONObject object = new JSONObject();
                        object.put("name", contact.getUsername());
                        object.put("phone", contact.getPhone());
                        jsonArray.put(object);
                    }
                    String json = jsonArray.toString();
                    // 后台调用前台html文件中javascript的方法show
                    webView.loadUrl("javascript:show('" + json + "')");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            // 打电话
            @SuppressWarnings("unused")
            public void call(String phone) {
                Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phone));
                startActivity(intent);
            }
        }
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
    }

      3.1 javascript调用java方法:

      上面的内部类JSObject 可以看成是javascript的对象,而contact可以看成是该对象的名称,内部的方法showContacts可以看成javascript对象的方法。因此对于在上述代码中"javascript:contact.showContacts()"的写法表示,执行内部类JSObject

    中的方法showContacts。

      3.2 java调用javascript方法:

      可以通过WebView控件调用,例如:webView.loadUrl("javascript:show('" + json + "')")则表示,调用javascript中的show方法。

    二、缓存

    WebView中存在着两种缓存:网页数据缓存(存储打开过的页面及资源)、H5缓存(即appcache)。
    
    一、网页缓存
    
    1、缓存构成
    /data/data/package_name/cache/
    /data/data/package_name/database/webview.db
    /data/data/package_name/database/webviewCache.db
    
    2、缓存模式
    较难理解的是以下两个模式:
    LOAD_DEFAULT,根据cache-control决定是否从网络上取数据。
    LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
    如:m.taobao.com的cache-control为no-cache,在模式LOAD_DEFAULT下,无论如何都会从网络上取数据,如果没有网络,就会出现错误页面;在LOAD_CACHE_ELSE_NETWORK模式下,无论是否有网络,只要本地有缓存,都使用缓存。本地没有缓存时才从网络上获取。
    m.sina.com.cn的cache-control为max-age=60,在两种模式下都使用本地缓存数据。
    
    总结:根据以上两种模式,建议缓存策略为,判断是否有网络,有的话,使用LOAD_DEFAULT,无网络时,使用LOAD_CACHE_ELSE_NETWORK。
    
    
    3、清除缓存
    clearCache(boolean)。
    CacheManager.clear。高版本中需要调用隐藏API。
    
    4、控制大小
    无系统API支持。
    可选方式:定时统计缓存大小、按时间顺序删除缓存。
    
    二、H5缓存
    
    1、缓存构成
    根据setAppCachePath(String appCachePath)提供的路径,在H5使用缓存过程中生成的缓存文件。
    
    2、缓存模式
    无模式选择,通过setAppCacheEnabled(boolean flag)设置是否打开。默认关闭,即,H5的缓存无法使用。
    
    3、清除缓存
    找到调用setAppCachePath(String appCachePath)设置缓存的路径,把它下面的文件全部删除就OK了。
    
    4、控制大小
    通过setAppCacheMaxSize(long appCacheMaxSize)设置缓存最大容量,默认为Max Integer。
    同时,可能通过覆盖WebChromeClient.onReachedMaxAppCacheSize(long requiredStorage, long quota, WebStorage.QuotaUpdater quotaUpdater)来设置缓存超过先前设置的最大容量时的策略。
    
    三、参考网址
    
    以下地址有关于H5缓存的一些内幕,如每个Application只调用一次WebSettings.setAppCachePath(),WebSettings.setAppCacheMaxSize()被忽略等一系列问题,需要仔细阅读和实验。
    http://code.google.com/p/android/issues/detail?id=24180

     三 webview一些参数和事件的设置:

    1) 设置WebView基本信息: 
        webview.getSettings().setJavaScriptEnabled(true);    //如果访问的页面中有Javascript,则webview必须设置支持Javascript。
        requestFocus();//触摸焦点起作用       
        this.setScrollBarStyle(SCROLLBARS_OUTSIDE_OVERLAY);// 取消滚动条
    2)  设置WevView要显示的网页:
        互联网用:webView.loadUrl("http://www.google.com"); 
        本地文件用:webView.loadUrl("file:///android_asset/XX.html");  本地文件存放在:assets文件中
    3)   如果希望点击链接由自己处理,而不是新开Android的系统browser中响应该链接。给WebView添加一个事件监听对象(WebViewClient)并重写其中的一些方法:
     shouldOverrideUrlLoading:对网页中超链接按钮的响应。当按下某个连接时WebViewClient会调用这个方法,并传递参数:按下的url。比如当webview内嵌网页的某个数字被点击时,它会自动认为这是一个电话请求,
     会传递url:tel:123,如果你不希望如此可通过重写shouldOverrideUrlLoading函数解决:
    4) 另外还有其他一些可重写的方法  
    4.1 接收到 Http 请求的事件 
    onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) 
    4.2 打开链接前的事件
    public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } 
    这个函数我们可以做很多操作,比如我们读取到某些特殊的URL,于是就可以不打开地址,取消这个操作,进行预先定义的其他操作,这对一个程序是非常必要的。
     
    4.3 载入页面完成的事件
    public void onPageFinished(WebView view, String url){ } 
    同样道理,我们知道一个页面载入完成,于是我们可以关闭loading条,切换程序动作。
     
    4.4 载入页面开始的事件
    public void onPageStarted(WebView view, String url, Bitmap favicon) { } 
    这个事件就是开始载入页面调用的,通常我们可以在这设定一个loading的页面,告诉用户程序在等待网络响应。
     
    通过这几个事件,我们可以很轻松的控制程序操作,一边用着浏览器显示内容,一边监控着用户操作实现我们需要的各种显示方式,同时可以防止用户产生误操作。
          
    5)       如果用webview点链接看了很多页以后,如果不做任何处理,点击系统“Back”键,整个浏览器会调用finish()而结束自身,如果希望浏览的网页回退而不是退出浏览器,需要在当前Activity中处理并消费掉该Back事件。
           覆盖Activity类的onKeyDown(int keyCoder,KeyEvent event)方法。
    public boolean onKeyDown(int keyCoder,KeyEvent event){  
         if(webView.canGoBack() && keyCoder == KeyEvent.KEYCODE_BACK){  
             webview.goBack();   //goBack()表示返回webView的上一页面  
             return true;  
         }  
        return false;                     
    }         
                               

     支付宝网页支付

    /**
     * 网页支付
     * @author libin
     *
     */
    public class AlipayWebActivity extends Activity {
        private WebView mWebView;
        private static final String TAG = "AlipayWebActivity";
        protected static final int PAY_SUCCESS = 20;
        protected static final int LOAD_FINISH_CODE = 40;
        private static final int DEFAULT_CODE = 50;

    public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.web); FactoryUtil.getInstance().addActivity(this); mWebView = (WebView) findViewById(R.id.webview); mWebView.setBackgroundColor(0); initial(); } @SuppressLint({"SetJavaScriptEnabled", "HandlerLeak"}) @TargetApi(Build.VERSION_CODES.HONEYCOMB) private void initial() { String url = getIntent().getStringExtra("url"); LogUtil.i(TAG, url); WebSettings webSettings = mWebView.getSettings(); mWebView.requestFocus(); webSettings.setJavaScriptEnabled(true); mWebView.setFocusable(true); webSettings.setBuiltInZoomControls(true); mWebView.setScrollBarStyle(0); if (MobileUtil.getMobileVersion() > 11) { mWebView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); } mWebView.setWebChromeClient(new WebChromeClient() { public void onProgressChanged(WebView view, int newProgress) { LogUtil.i(TAG, "newProgress: " + newProgress); if (newProgress == 100) { mUihandler.sendEmptyMessage(LOAD_FINISH_CODE); } super.onProgressChanged(view, newProgress); } }); mWebView.setWebViewClient(new WebViewClient() { public boolean shouldOverrideUrlLoading(WebView view, String url) { LogUtil.i(TAG, "URL : " + url); loadUrl(view, url); return true;//停止在当前界面 } public void onPageFinished(WebView view, String url) { LogUtil.i(TAG, "onPageFinished" + url); //trade_status : TRADE_FINISHED if (url.contains("&cmd=success&ptype=url")) { BaseDialogUtil.alertDialog(AlipayWebActivity.this, "提示信息", "支付成功", false, new BaseDialogUtil.DialogOnClickListener() { @Override public void positive(DialogInterface dialoginterface, int id) { FactoryUtil.getInstance().exit(); } @Override public void negative(DialogInterface dialog, int id) { } }); } super.onPageFinished(view, url); } public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); LogUtil.i(TAG, "onPageStarted" + url); } }); loadUrl(mWebView, url); } @SuppressLint("HandlerLeak") private Handler mUihandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case PAY_SUCCESS: clearCache(); FactoryUtil.getInstance().exit(); break; case LOAD_FINISH_CODE: dissDialogGamm(); break; case DEFAULT_CODE: showProgress(AlipayWebActivity.this); } super.handleMessage(msg); } }; private void loadUrl(final WebView webView, final String url) { mUihandler.sendEmptyMessage(DEFAULT_CODE); webView.loadUrl(url); } public boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) { mWebView.goBack(); return true; } else if (keyCode == KeyEvent.KEYCODE_BACK) { onBackPressed(); return true; } return super.onKeyDown(keyCode, event); } private void clearCache() { mWebView.clearCache(true); mWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null); finish(); } }
  • 相关阅读:
    Pyton 练习题2
    Python 知识点练习
    pycharm 汉化
    关于sublime编辑Python的安装与配置
    python练习题
    虚短和虚断
    OSI的7层协议
    5V电压的制作
    三角波,方波,正弦波的转换
    单片机不工作,晶振是否起振怎么检查
  • 原文地址:https://www.cnblogs.com/lbangel/p/3470705.html
Copyright © 2020-2023  润新知