安卓Android与H5(JS)交互(双向)

安卓Android与H5(JS)交互(双向)

博主就今天周五又做了个需求(安卓Android与H5交互),原来上线的功能是服务器配置过来的学习报告(一个H5页面)并提供原始的微信分享功能,今天增加的是反向需求,由APP提供给服务器配置过来的H5页面的子级页面调用原生的微信分享,理了一下逻辑(写好给JS调用的方法),然后就是配合前端H5妹子,开启一下午的混合开发测试。(过程省略十万字,读者自行脑补)

  备注:本文默认相关知识点,1,webview开发 2,微信SDK接入 3,朋友以及好友圈分享 4,Android与H5交互

我们先上效果gif图,看图再分析

  • 图一:原生调用H5

    需求:数学题型,mathjax原生支持库目前有坑,技术选型实现以原生嵌套H5快速实现做题题型,技术涉及viewpager+h5混合开发


    • 原生调用H5
  • 图二:H5调用原生(周一补上图二)

    需求:H5页面课程,需要分享链接到微信,这就需要我们调用webview时,提供给JS来调用我们的接口,以实现H5调起原生的微信分享功能。

    原生调用微信分享gif

一 本文记录安卓原生与H5交互(双向)快速实现

1,Android与H5交互,首先要实现webview,以及相关配置
调用的本地webview.html文件,需要配置URL
private static final String URL = “file:///android_assetwebview.html”;

       //为了防止内存泄漏OOM,博主个人建议不在xml文件中创建Webview
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        mWebView = new WebView(getApplicationContext());
        mWebView.setLayoutParams(layoutParams);
        mFlWebviewContain.addView(mWebView);

        mWebSettings = mWebView.getSettings();
        //支持与JS交互
        mWebSettings.setJavaScriptEnabled(true);
        //支持插件
        //mWebSettings.s
        //设置自适应屏幕
        mWebSettings.setUseWideViewPort(true);
        mWebSettings.setLoadWithOverviewMode(true);
        //缩放操作
        mWebSettings.setSupportZoom(true);  //支持缩放,默认为true.是下面的那个的前提
        mWebSettings.setBuiltInZoomControls(true);  //设置内置的缩放控件
        mWebSettings.setDisplayZoomControls(false);  //隐藏原生的缩放控件

        //其他细节操作
        mWebSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);  //不缓存,每次都从网络获取
//        mWebSettings.setAppCacheEnabled(true);
        mWebSettings.setAllowFileAccess(true);   //设置可以访问文件
        mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true);  //支持通过JS打开新窗口
        mWebSettings.setLoadsImagesAutomatically(true);   //支持自动加载图片
        mWebSettings.setDefaultTextEncodingName("utf-8");  //设置编码格式

对应H5 Activity页面XML布局页面

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/web_container"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:fitsSystemWindows="true"
              android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/color_55ceac">

        <RelativeLayout
            android:id="@+id/rl_back"
            android:layout_width="80dp"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/iv_back"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_centerVertical="true"
                android:layout_marginLeft="5dp"
                android:paddingLeft="10dp"
                android:paddingRight="10dp"
                android:src="@mipmap/retreat"/>
        </RelativeLayout>


        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:textColor="@color/white"
            android:textSize="16sp"/>

        <!--分享图标-->
        <ImageView
            android:id="@+id/iv_share"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="15dp"
            android:padding="6dp"
            android:src="@mipmap/share"/>

        <TextView
            android:id="@+id/wte"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="15dp"
            android:textColor="@color/white"
            android:textSize="12sp"
            android:visibility="gone"/>

    </RelativeLayout>

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/login_btn_defalut"/>

    <ProgressBar
        android:id="@+id/web_progress"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="6dp"
        android:max="100"/>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <FrameLayout
            android:id="@+id/fl_webview_contain"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

        <RelativeLayout
            android:id="@+id/rl_load_error"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/white"
            android:clickable="true"
            android:visibility="gone">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:orientation="vertical">

                <ImageView
                    android:layout_width="170dp"
                    android:layout_height="200dp"
                    android:layout_gravity="center_horizontal"
                    android:src="@mipmap/no_load"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:layout_marginTop="15dp"
                    android:text="网络异常,点击重试"
                    android:textColor="@color/color_5c5c5c"
                    android:textSize="14sp"/>

            </LinearLayout>

        </RelativeLayout>
    </FrameLayout>

</LinearLayout>

二 实现安卓原生调用JS 方法

核心代码: mWebView.loadUrl(“javascript:htmlCall(” + listarray+ “)”);

        //复写shouldOverrideUrlLoading()方法.使得打开网页时不调用系统浏览器,而是在本Webview中显示
        mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                return false;
            }

            //开始载入页面调用的,我们可以设定一个loading的页面,告诉用户程序在等待网络响应
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {

            }

            //在页面加载结束时调用.我们可以关闭loading条,切换程序动作
            @Override
            public void onPageFinished(final WebView view, String url) {

                    //访问JS方法
                    mWebView.post(new Runnable() {
                        @Override
                        public void run() {
                            mWebView.loadUrl("javascript:htmlCall(" + contain + ")");

                        }
                    });

                }
            }

            //加载页面出现错误时
            @Override
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
               //显示加载错误
                mRlWebviewLoading.setVisibility(View.GONE);
                mTvWebviewError.setVisibility(View.VISIBLE);

            }

            //webView默认是不处理https请求的,页面显示空白,需要进行如下设置
            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                handler.proceed();   //等待证书响应
                //handler.cancel();  //表示挂起连接,为默认方式
                //handler.handleMessage(null);   //可做其他处理
            }
        });

调用的本地webview.html

<!DOCTYPE html>
<html>
<head>
    <title>MathJax TeX Test Page</title>
    <!-- Copyright (c) 2010-2011 Design Science, Inc. -->
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7"/>
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    <script type="text/x-mathjax-config">
        MathJax.Hub.Config({
            tex2jax: {
            inlineMath: [["$","$"],["\\(","\\)"],["\[","\]"] ]},
            messageStyle: 'none',
            tex2jax: {preview: 'none'},
            displayAlign: "left",
            displayIndent: "2em"
        });

      MathJax.Hub.Queue(function () {
            var height = document.body.offsetHeight;
            MathJax.Hub.Queue(["Typeset", MathJax.Hub]);

             window.AndroidWebView.showInfoFromJs(height);
   });



    </script>
    <script type="text/javascript" src="../MathJax.js?config=TeX-AMS_HTML-full"></script>
    <style>
        *{
            margin:0;
            padding:0;
        }
        .contain{
            width: 100%;
            margin: 0 auto;
            padding-top:10px
        }
        .devide{
            padding-bottom: 20px;
        }
        img{
           max-width:100%;
           display:block;
           margin: 0 auto;
        }
        p{
           font-size:.14rem
        }

        body{
                    word-wrap:break-word;
                    font-family:Arial;
                }

        @media screen and (min-width:360px) and (max-width:414px) {
            html { font-size: 625%;}
        }

        @media screen and (min-width:415px) {
            html {
                font-size: 843.75%;
            }
        }

        @media screen and (min-width:320px) and (max-width:360px) {
            html {
                font-size: 550%;
            }
        }
    </style>

</head>
<!--<body style="opacity:0">-->
<body>
<div class="contain" id="sua">
    <div id="subjects_par" class="devide">
        <p style = "font-size:.16rem;font-weight:bold">【题目】</p>
        <p id="subjects"></p>
    </div>
    <div id="answers_par" style="display: none"  class="devide">
        <p style = "font-size:.16rem;font-weight:bold">【答案】</p>
        <p id="answers"></p>
    </div>
    <div id="analysis_par" style="display: none"  class="devide">
        <p style = "font-size:.16rem;font-weight:bold">【解析】</p>
        <p id="analysis"></p>
    </div>
</div>
</body>

<script>
<!-- 调用JS方法,输入数组参数-->
    var htmlCall = function(array){
        document.getElementById('subjects').innerHTML=array.subjects;
        document.getElementById('answers').innerHTML=array.answers;
        document.getElementById('analysis').innerHTML=array.analysis;


        if(array.question_finish == 1){
            document.getElementById('answers_par').style.display = 'block';
            document.getElementById('analysis_par').style.display = 'block';
        }

    }
</script>

</html>

三 实现JS调用原生方法

核心代码: //在js中调用本地java方法

        mWebView.addJavascriptInterface(new JsInterface(mContext), "AndroidWebView");

提供给JS调用类与方法

    /**
     * @ 创建:   kx
     * @ 时间:    2018/8/31
     * @ 描述:    接口提供给JS 调用原生分享        LoadH5UrlNoRefreshActivity
     */
    public class JsInterface {

        private Context mContext;

        public JsInterface(Context context) {
            this.mContext = context;
        }

        /**
         * 在js中调用window.AndroidWebView.js2ShareWechat(title,text,mWebURl),便会触发此方法。
         *
         * @param title 分享标题      例子:xx的学习报告
         * @param text  分享文本内容   例子:xx的学习报告新鲜出炉啦!赶快来围观~~
         */
        @JavascriptInterface
        public void js2ShareWechat(final String title, final String text, final String webURlL) {

            //TODO 原生回调微信分享

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    showBroadView(title, text, AppConfig.H5HOST + webURlL);
                }
            });
        }

    /**提供给JS判断前段,Android or ios */
        @JavascriptInterface
        public String jsString() {
            return "Android";
        }
    }

Demo下载

原生与H5双向调用完整例子 Demo

四 结尾

 一周的充实又紧凑的开发过后,在恬谧地周末得以放松并总结,写下此文,实乃高兴
 如有问题bug或者写的不当之处,请联系博主,请读者不吝赐教,博主感激不尽(博主
 邮箱[email protected]

猜你喜欢

转载自blog.csdn.net/qXing123456789/article/details/82291472