当前位置

网站首页> 程序设计 > 开源项目 > 程序开发 > 浏览文章

Android中WebView页面交互 - share

作者:小梦 来源: 网络 时间: 2024-03-20 阅读:

代码

在android内打开一个网页的时候,有时我们会要求与网页有一些交互。而这些交互是在基于javaScript的基础上。那么我们来学习一下android如何与网页进行JS交互。完整代码如下:

import android.annotation.SuppressLint;import android.os.Bundle;import android.text.TextUtils;import android.view.KeyEvent;import android.view.View;import android.view.View.OnClickListener;import android.webkit.CookieManager;import android.webkit.CookieSyncManager;import android.webkit.JavascriptInterface;import android.webkit.URLUtil;import android.webkit.WebChromeClient;import android.webkit.WebView;import android.webkit.WebViewClient;import android.widget.TextView;import org.json.JSONObject;/** * 软件内通用打开网页的容器页面 * * @author ZRP */public class CommonWebActivity extends BaseActivity {    protected CustomFrameLayout customFrameLayout;    protected TextView errorTxt;    protected View refresh;// 刷新按钮    protected WebView webView;    protected String url = "";// 网址url    protected String param = "";// 交互参数,如json字符串    protected WebChromeClient chromeClient = new WebChromeClient() {        public void onProgressChanged(WebView view, int newProgress) {if (newProgress == 100) {    // 判断有无网络    if (!NetUtil.isAvaliable()) {        customFrameLayout.show(R.id.common_net_error);        refresh.setVisibility(View.VISIBLE);        refresh.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {webView.loadUrl(url);}        });    } else {        // 判断网络请求网址是否有效        if (!URLUtil.isValidUrl(url)) {customFrameLayout.show(R.id.common_net_error);errorTxt.setText("无效网址");        } else {customFrameLayout.show(R.id.common_web);        }    }}        }        // 获取到url打开页面的标题        public void onReceivedTitle(WebView view, String title) {setBackView(R.id.back_view, title);        }        // js交互提示        public boolean onJsAlert(WebView view, String url, String message, android.webkit.JsResult result){return super.onJsAlert(view, url, message, result);        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        url = getIntent().getStringExtra("url");        param = getIntent().getStringExtra("param");        setContentView(R.layout.common_web_activity);        initView();    }    @SuppressLint("SetJavaScriptEnabled")    private void initView() {        setBackView(R.id.back);        customFrameLayout = (CustomFrameLayout) findViewById(R.id.web_fram);        customFrameLayout.setList(new int[]{R.id.common_web, R.id.common_net_error, R.id.common_loading});        customFrameLayout.show(R.id.common_loading);        refresh = findViewById(R.id.error_btn);        errorTxt = (TextView) findViewById(R.id.error_txt);        webView = (WebView) findViewById(R.id.common_web);        webView.getSettings().setDefaultTextEncodingName("utf-8");        webView.getSettings().setJavaScriptEnabled(true);        synCookies();//格式化写入cookie,需写在setJavaScriptEnabled之后        webView.setWebChromeClient(chromeClient);        webView.setWebViewClient(new WebViewClient() {// 让webView内的链接在当前页打开,不调用系统浏览器@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {    view.loadUrl(url);    return true;}        });        webView.addJavascriptInterface(new JavaScriptInterface(), "zrp");        webView.loadUrl(url);    }    /**     * CookieManager会将这个Cookie存入该应用程序/data/data/databases/目录下的webviewCookiesChromium.db数据库的cookies表中     * 需要在当前用户退出登录的时候进行清除     */    private void synCookies() {    String[] split = App.cookie.split(";");    for (int i = 0; i < split.length; i++) {        CookieManager.getInstance().setCookie(url, split[i]);    }   }    /**     * 回调网页中的脚本接口。     *     * @param notify 传给网页的通知内容。     */    public void onNotifyListener(String notify) {        if (webView != null) {webView.loadUrl("javascript:onCommandListener('" + notify + "')");        }    }    /**     * android js交互实现     * String ret = zrp.command("");     * <p/>     * webView.loadUrl("javascript:onCommandListener('param')");     */    public class JavaScriptInterface {        @JavascriptInterface        public void command(String jsonString) {if (TextUtils.isEmpty(jsonString)) {    return ;}//根据网页交互回传的json串进行操作        }    }}

其中CustomFrameLayout为界面切换控件,分别在无网络,网址错误等情况下进行提示:

import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.widget.FrameLayout;/** * 用于状态切换的布局,只显示1个状态 */public class CustomFrameLayout extends FrameLayout {    private int[] list;    public CustomFrameLayout(Context context) {        super(context);        initView();    }    public CustomFrameLayout(Context context, AttributeSet attrs) {        super(context, attrs);        initView();    }    public CustomFrameLayout(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        initView();    }    /**     * 设置子面板id数组     *     * @param list     */    public void setList(int[] list) {        this.list = list;        show(0);    }    /**     * 显示某个面板     *     * @param id     */    public void show(int id) {        if (list == null) {for (int i = 0; i < getChildCount(); ++i) {    View view = getChildAt(i);    if (id == view.getId()) {        view.setVisibility(View.VISIBLE);    } else {        view.setVisibility(View.GONE);    }}return;        }        for (int aList : list) {View item = findViewById(aList);if (item == null) {    continue;}if (aList == id) {    item.setVisibility(View.VISIBLE);} else {    item.setVisibility(View.GONE);}        }    }    /**     * 隐藏所有面板     */    public void GoneAll() {        if (list == null) {for (int i = 0; i < getChildCount(); ++i) {    View view = getChildAt(i);    view.setVisibility(View.GONE);}return;        }        for (int aList : list) {View item = findViewById(aList);if (item == null) {    continue;}item.setVisibility(View.GONE);        }    }    /**     * 切换。     * @param index     */    public void showOfIndex(int index) {        for (int i = 0; i < getChildCount(); ++i) {View view = getChildAt(i);if (index == i) {    view.setVisibility(View.VISIBLE);} else {    view.setVisibility(View.GONE);}        }    }    public void initView() {    }}

界面布局为:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <include layout="@layout/common_back" />    <com.zrp.test.CustomFrameLayout        android:id="@+id/web_fram"        android:layout_width="match_parent"        android:layout_height="match_parent" >        <WebViewandroid:id="@+id/common_web"android:layout_width="match_parent"android:layout_height="match_parent" />        <include layout="@layout/common_net_error" />        <include layout="@layout/common_loading" />    </com.zrp.test.CustomFrameLayout></LinearLayout>

测试分析

好了,这时候我们来添加一些数据进行测试:

用上面的方法为web页面中的param赋值,在asset文件夹中放入要进行测试的html文件,url赋值为:url = "file:///android_asset/html.html";
如上html.html文件源码为:

<!DOCTYPE html><html><head>    <title>测试容器调用</title></head><body><div class="main"><button onclick="test2()">调用容器方法</button></div><script type="text/javascript">   function test(){       alert("容器调用web方法");   }    function test2(){        alert("test2() begin");        zrp.command("{'type':1,'text':'hello boy'}");        alert("test2() end");    }</script></body></html>

java调用js:可通过在java代码中异步执行webView.loadUrl("javascript:test()");来调用网页代码中的test()方法。

js调用java:在网页代码中可以看到button的点击事件添加了zrp.command("{'type':1,'text':'hello boy'}");来回传一个json串给java页面,即js通过以上的方法调用了java的方法。

如果webView展示页面的时候需要给网页传递cookie,即各种登录信息,则需要在调用webView.loadUrl(url)之前一句调用如下方法:注意!多个cookie值必须多次进行setCookie!

设置cookie方法一:

/** * CookieManager会将这个Cookie存入该应用程序/data/data/databases/目录下的webviewCookiesChromium.db数据库的cookies表中 * 需要在当前用户退出登录的时候进行清除 */private void synCookies() {    CookieSyncManager.createInstance(this);    CookieManager cookieManager = CookieManager.getInstance();    cookieManager.setAcceptCookie(true);    cookieManager.removeSessionCookie();    String[] split = App.cookie.split(";");    for (int i = 0; i < split.length; i++) {        cookieManager.setCookie(url, split[i]);    }    CookieSyncManager.getInstance().sync();}

在当前用户退出登录的时候清除掉保存的cookie信息。

/** * 清除当前用户存储到cookies表中的所有数据 */private void removeCookie() {    CookieSyncManager.createInstance(this);    CookieManager cookieManager = CookieManager.getInstance();    cookieManager.removeAllCookie();    CookieSyncManager.getInstance().sync();}

注意:在调用设置Cookie之后不能再设置如下的这类属性,否则设置cookie无效。

webView.getSettings().setBuiltInZoomControls(true);  webView.getSettings().setJavaScriptEnabled(true);  

但是!在如上设置cookie之后,每次设置cookie的时候都有延时,要是点击频率较快的时候,会出现cookie没有被设置进去的问题!

设置方法二:
经过一番查找,找到如下两个解决办法:

  1. http://blog.csdn.net/swust_chenpeng/article/details/37699841,这个是开了一个异步任务来进行等待,然后再次设置cookie,感觉没有从根源上解决这个问题啊。。。但是思路值得参考

  2. http://stackoverflow.com/questions/22637409/android-how-to-pass-cookie-to-load-url-with-webview,有用!设置之后立竿见影。

/** * CookieManager会将这个Cookie存入该应用程序/data/data/databases/目录下的webviewCookiesChromium.db数据库的cookies表中 * 需要在当前用户退出登录的时候进行清除 */private void synCookies() {    String[] split = App.cookie.split(";");    for (int i = 0; i < split.length; i++) {        CookieManager.getInstance().setCookie(url, split[i]);    }}

同时,在退出登录的时候清除cookie,CookieManager.getInstance().removeAllCookie();,清除当前用户存储到cookies表中的所有数据

热点阅读

网友最爱