WebView-Android与H5交互、设置cookie、post请求、滑动监听、点击监听、关闭音频视频

mWbRealize.loadUrl("http://652857502.scene.eqxiu.com/s/vknb0n8W?eqrcode=1&from=singlemessage&isappinstalled=0");
//支持javascript
web.getSettings().setJavaScriptEnabled(true); 
// 设置可以支持缩放 
web.getSettings().setSupportZoom(true); 
// 设置出现缩放工具 
web.getSettings().setBuiltInZoomControls(true);
//扩大比例的缩放
web.getSettings().setUseWideViewPort(true);//让webview读取网页设置的viewport,pc版网页 
//自适应屏幕
web.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);//适应屏幕,内容将自动缩放  
webView.getSettings().setLayoutAlgorithm(LayoutAlgorithm.NARROW_COLUMNS);//适应内容大小  
web.getSettings().setLoadWithOverviewMode(true);
settings.setDomStorageEnabled(true);//打开DOM储存API
settings.setBlockNetworkImage(true);//拦截图片的加载
web.setInitialScale(25);//为25%,最小缩放等级 

// 设置缓存模式:不使用缓存
 mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
// 设置启动缓存  
 webView.getSettings().setDefaultTextEncodingName("utf-8");  
 webView.getSettings().setAppCacheEnabled(true);
 webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);  

postUrl

//需要访问的网址  
String url = "http://www.cqjg.gov.cn/netcar/FindThree.aspx";  
//post访问需要提交的参数  
String postDate = "txtName=zzz&QueryTypeLst=1&CertificateTxt=dsds";  
//由于webView.postUrl(url, postData)中 postData类型为byte[] ,  
//通过EncodingUtils.getBytes(data, charset)方法进行转换  
webView.postUrl(url, EncodingUtils.getBytes(postDate, "UTF-8"));  

EncodingUtils是 HttpCore里面的,要加依赖
compile 'org.apache.httpcomponents:httpcore:4.4.4'
网页只加载出一部分,下面就不加载了?
  ● I/chromium(27693): [INFO:CONSOLE(8)] “Uncaught TypeError: Cannot call method ‘getItem’ of null”, source: url
网页加载不完成并报出如上错误时,有可能是你的DOM储存API没有打开,在代码中加上一行:
mWebView.getSettings().setDomStorageEnabled(true);

如果希望点击链接由自己处理,而不是新开Android的系统browser中响应该链接。给WebView加一个事件监听对象(WebViewClient)并重写其中的一些方法:shouldOverrideUrlLoading:对网页中超链接按钮的响应。当按下某个连接时WebViewClient会调用这个方法,并传递参数:按下的url。

webView.setWebViewClient(new WebViewClient(){
         @Override
         public boolean shouldOverrideUrlLoading(WebView view, String url) {
 
          view.loadUrl(url);   //在当前的webview中跳转到新的url
 //如果不需要其他对点击链接事件的处理返回true,否则返回false
          return true;
         }
   @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, String url) {

            if (url.startsWith("http") || url.startsWith("https")) { //http和https协议开头的执行正常的流程
                return super.shouldInterceptRequest(view, url);
            } else {  //其他的URL则会开启一个Acitity然后去调用原生APP

                if (url.contains("mqqwpa")){


                    if (OthersUtil.isQQClientAvailable(mContext)){

                        Intent in = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                        startActivity(in);
                        return null;
                    }else {

//                        Toast.makeText(mContext, "您的手机未安装手机QQ", Toast.LENGTH_SHORT).show();
//                        return super.shouldInterceptRequest(view, url);
                        return null;
                    }
                }

                Intent in = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                startActivity(in);
                return null;
            }
        }
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
//            showErrorPage();//显示错误页面
            hideErrorPage();
        };
        public void onPageFinished(WebView view, String url) {//处理网页加载成功时
//            loading_over.setVisibility(View.GONE);
//            hideErrorPage();
        }
//监听webview界面切换
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
    super.onPageStarted(view, url, favicon);
    if (url.contains("https://www.hzjr.com/Mobile/Index/customer?token=")){
        mCloseService.setVisibility(View.GONE);
    }
}
        });

加载html标签

mWebView.loadDataWithBaseURL(null, stringHtml, "text/html", "utf-8", null);

onReceivedError 不能捕捉失败的回调???

onReceivedError 有两个重载的方法,要重写第二个

1、public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {

2、 public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {

setWebChromeClient

setWebChromeClient主要处理解析,渲染网页等浏览器做的事情

WebChromeClient是辅助WebView处理Javascript的对话框,网站图标,网站title,加载进度等 

onCloseWindow(关闭WebView) 

onCreateWindow() 

onJsAlert (WebView上alert不能弹出来的,要WebChromeClient处理) 

onJsPrompt 

onJsConfirm 

onProgressChanged 

onReceivedIcon 

onReceivedTitle

setWebViewClient

WebViewClient是帮助WebView处理各种通知、请求事件的

onLoadResource 

onPageStart 

onPageFinish 

onReceiveError 

onReceivedHttpAuthRequest 

点击超链接启动QQ

mWebView = (ProgressWebView) findViewById(R.id.baseweb_webview); mWebView.getSettings().setJavaScriptEnabled(true); String url ="http://wpa.qq.com/msgrd?v=3&uin=748895431&site=qq&menu=yes"; mWebView.loadUrl(url); mWebView.setWebViewClient(new WebViewClient() { 
public boolean shouldOverrideUrlLoading(WebView view, String url) {
 view.loadUrl(url); return true;
 } 
@Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
 if (url.startsWith("http") || url.startsWith("https")) {
 //http和https协议开头的执行正常的流程 return super.shouldInterceptRequest(view, url); 
} else { 
//其他的URL则会开启一个Acitity然后去调用原生APP Intent in = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(in); return null;
 }
 }
 });

滑动监听

自定义webview重写onScrollChanged方法,利用接口回调

public class HzjrWebView extends WebView {
    private OnScrollChangedCallback mOnScrollChangedCallback;
    public HzjrWebView(Context context) {
        super(context);
    }

    public HzjrWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public HzjrWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onScrollChanged(final int l, final int t, final int oldl,
                                   final int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);

        if (mOnScrollChangedCallback != null) {
            mOnScrollChangedCallback.onScroll(l , oldl, t , oldt);

        }
    }

//    public OnScrollChangedCallback getOnScrollChangedCallback() {
//        return mOnScrollChangedCallback;
//    }

    public void setOnScrollChangedCallback(
            final OnScrollChangedCallback onScrollChangedCallback) {
        mOnScrollChangedCallback = onScrollChangedCallback;
    }

    /**
     * Impliment in the activity/fragment/view that you want to listen to the webview
     */
    public interface OnScrollChangedCallback {
         void onScroll(int l,int oldl,int t, int oldt);
    }
}

页面关闭之后,视频或者音频还在播放的问题

方法1:
调用
 webView.loadUrl("about:blank");
这个方法会 销毁所有的video和audio 包括js的所有正在运行的function
方法2:
@Override
public void onPause() {
    super.onPause();
    myWebView.onPause();
    myWebView.pauseTimers();
}

@Override
public void onResume() {
    super.onResume();
    myWebView.resumeTimers();
    myWebView.onResume();
}


@Override
protected void onDestroy() {
    myWebView.destroy();
    myWebView = null;
    super.onDestroy();
}

复写生命周期的方法;最好的方法;(有时会挂 java.lang.IllegalArgumentException: Receiver not registered: android.widget.ZoomButtonsController$1@3ed4bcc7)

要在销毁之前把根布局的所有子布局remove

mLlH5.removeAllViews();

回退时回到上一个页面,而不是退出WebView

mWebView.goBack(); //后退 
mWebView.goForward();//前进 
mWebView.reload(); //刷新
public class MainActivity extends Activity {
    private WebView webview;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //2、在Activity中实例化WebView
        setContentView(R.layout.activity_main);
        webview = (WebView) findViewById(R.id.webview);

        //第2步也可以替换为下面这两句,就不要R.layout.activity_main布局文件了
        //mwebview = new WebView(this);                       //实例化WebView对象  
        //setContentView(mwebview); 

        // 设置WebView属性,能够执行Javascript脚本
        webview.getSettings().setJavaScriptEnabled(true);
        //3、 加载需要显示的网页
        webview.loadUrl("http://www.baidu.com/");
        ///4、设置响应超链接,在安卓5.0系统,不使用下面语句超链接也是正常的,但在MIUI中安卓4.4.4中需要使用下面这条语句,才能响应超链接
        webview.setWebViewClient(new HelloWebViewClient());
    }

    @Override
    // 设置回退
    // 5、覆盖Activity类的onKeyDown(int keyCoder,KeyEvent event)方法
    public boolean onKeyDown(int keyCode, KeyEvent event) {
           //按下返回键并且webview界面可以返回
        if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) {

            webview.goBack(); // goBack()表示返回WebView的上一页面
            return true;
        }
        return super.onKeyDown(keyCode,event);
    }

    // Web视图
    private class HelloWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    }
}

设置cookie

ATTENTION:
    要在webView设置setting之后,loadUrl之前调用此方法,否则无效
    
    关于设置cookie失效的问题,在5.0以下可能会有失效的情况,sync是异步操作。
    失效的原因是在removeSessionCookie之后立马setCookie可能会是设置之后又被清除了,可以加个延迟。
    在5.0以上官方回调了同步方法。
    具体介绍参考博客:https://blog.csdn.net/b275518834/article/details/51004237
    /**
     * 给WebView同步Cookie
     *
     * @param context 上下文
     * @param url     可以使用[domain][host]
     */
    private void syncCookie(Context context, String url) {
        CookieSyncManager.createInstance(context);
        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.setAcceptCookie(true);
//        cookieManager.removeSessionCookie();// 移除旧的[可以省略]
        cookieManager.setCookie(url,cookie);
        CookieSyncManager.getInstance().sync();// To get instant sync instead of waiting for the timer to trigger, the host can call this.
    }

还有权限:

<uses-permission android:name="android.permission.INTERNET" />
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

H5与Android交互

首先最重要最容易忽略的网络权限
public class MainActivity extends AppCompatActivity {

/***************************************************************
 * H5和Android通信三种方式
 * 1.android主动调用js:javascript:方法名(参数)
 * 2.js主动调用Android
 * 3.js callback式调用Android,来源(解耦H5只关心H5,客户端只关心android)
 * ***************************************************************
 */

private WebView mWebview;

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

    //设置webview
    WebSettings settings = mWebview.getSettings();
    settings.setJavaScriptEnabled(true);

    //页面加载完成调用js方法
    //重新浏览器内核对象
    initWebClient();

    //js和Android两种不同开发语言,不认识
    //核心方法:设置js和Android通信桥梁接口(简而言之,就是设置通信桥梁类)
    JavascriptMethos jsMethos = new JavascriptMethos(this, mWebview);
    //参数1:提供给js调用的方法的对象, 参数2:参数1的映射字符串(第一个参数的别名),因为字符串再所有开发一样通用
    mWebview.addJavascriptInterface(jsMethos, JavascriptMethos.JSINTERFACE);

    //显示
    mWebview.loadUrl("http:/10.0.3.2:8080/html35/index.html");
}

private void initWebClient() {
    mWebview.setWebChromeClient(new WebChromeClient());


    mWebview.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
        }

        //页面加载完成调用该方法
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            //调用js 方法
            //WebView.loadUrl("javascript:方法名(参数)")
            JSONObject json = new JSONObject();
            try {
                json.put("name", "android");
                json.put("msg", "你好,我是Android,加个蚝友");
                mWebview.loadUrl("javascript:receiveMessage("+json.toString()+")");
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    });
}

    private void initView() {
        mWebview = (WebView) findViewById(R.id.webview);
    }
}



/**
 * 统一管理所有js和Android通信
 * 
 */

public class JavascriptMethos {

    public static String JSINTERFACE = "jsInterface";
    private Context mContext;
    private WebView mWebView;

    public JavascriptMethos(Context mContext, WebView mWebView) {
        this.mContext = mContext;
        this.mWebView = mWebView;
}

/**
 * 给js调用的弹出toast方法
 * 为什么要添加注解:android4.2以上(包含),如果不加注解,
 * js无法调用Android方法,因为4.2之前js和android通信有安全问题,如果不加上该注解,4.2以上js无法调用Android方法
 *
 * @param json
 */
@JavascriptInterface
public void showToast(String json) {
    Toast.makeText(mContext, json, Toast.LENGTH_SHORT).show();
}

@JavascriptInterface
public void getHotelData(String json) throws JSONException {

    //解析callbak方法名
    JSONObject jsJson = new JSONObject(json);
    final String callback = jsJson.optString("callback");

    System.out.println("接收到js传递callback参数=" + json);
    //模拟访问网络
    //返回json
    final JSONObject callbackJson = new JSONObject();
    try {
        callbackJson.put("name", "8天连锁酒店");
        callbackJson.put("hotel", "99");
        callbackJson.put("phone", "075588888888");

        //调用js方法
        //mWebView.loadUrl("javascript:方法名(参数)");默认Android调用js独立运行在一个进程WebViewCoreThread
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                //mWebView.loadUrl("javascript:receiveHotelData(" + callbackJson.toString() + ")");
                mWebView.loadUrl("javascript:"+callback+"(" + callbackJson.toString() + ")");
            }
        });
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

    private Handler mHandler = new Handler();
}
demo

https://github.com/jiaweizeng/H5AndAndroid

control是java对象名称,toastMessage是方法名称,双方约定俗成,写死。

<body>
    <button type="button" id="button" onclick="toastMessage('js调用了android方法')">js访问android中方法</button>
    <script>
        function toastMessage(message) {
            window.control.toastMessage(message)
        }  
    </script>
</body>


public class MainActivity extends AppCompatActivity {

    @SuppressLint({"JavascriptInterface", "AddJavascriptInterface", "SetJavaScriptEnabled"})
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        WebView webView = findViewById(R.id.wv);

        WebSettings webSettings = webView.getSettings();

        webSettings.setJavaScriptEnabled(true);
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        webView.loadUrl("http://192.168.1.38/hzjrH5/jiaohu.html");
        //js访问android,定义接口
        webView.addJavascriptInterface(this, "control");
    }

    @JavascriptInterface
    public void toastMessage(String s){
        Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show();
        finish();
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • WebView·开车指南 目录 WebView简介 WebView基本使用 WebView常用方法 WebSett...
    小庄bb阅读 3,433评论 3 25
  • WebView·开车指南 目录 WebView简介 WebView基本使用 WebView常用方法 WebSett...
    南城的人阅读 4,710评论 0 19
  • Tips 由于WebView的用法实在太多,如果您只是想查询某个功能的使用——建议Ctrl+F(Commad+F)...
    BugDev阅读 7,690评论 11 109
  • “十汨,十原。” “在。” 十原和我比肩跪在泓湛堂中央,静静地接受着众师兄殷切的目光——不,准确地说,...
    12宋不才阅读 559评论 0 3