安卓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页面课程,需要分享链接到微信,这就需要我们调用webview时,提供给JS来调用我们的接口,以实现H5调起原生的微信分享功能。
一 本文记录安卓原生与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])