Android HTML与原生交互
来源:互联网 发布:usb数据延长线 编辑:程序博客网 时间:2024/05/20 20:20
前言
HTML+原生交互是最近比较流行的方式,很多人都在使用,用了这么久的这种模式,小编#整合了下,方便技术更替之后再次查看,也希望这篇文章能够对你有用。
下面就简单整合下,HTML与原生如何交互
1.布局
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/comm_bg" android:orientation="vertical"> <include android:id="@+id/layout_top_bar" layout="@layout/top_bar" /> //PtrClassicFrameLayout [下拉刷新框架view] <com.reach.doooly.pullresh.PtrClassicFrameLayout xmlns:cube_ptr="http://schemas.android.com/apk/res-auto" android:id="@+id/view_frame" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/layout_top_bar"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <WebView android:id="@+id/view_webview" android:layout_width="match_parent" android:layout_height="match_parent" /> <ProgressBar android:id="@+id/view_progressbar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="1dp" android:progressDrawable="@drawable/pull_progressbar_pg" android:visibility="gone" /> </RelativeLayout> <include layout="@layout/webview_err_view" android:visibility="gone"/> </RelativeLayout> </com.reach.doooly.pullresh.PtrClassicFrameLayout></RelativeLayout>
2.activity
package com.reach.doooly.server;import android.app.Activity;import android.os.Bundle;import com.reach.doooly.R;/** * Created by Albert on 2017/10/16. */public class WebViewActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.webview_layout); }}
下面我们需要做的是
[1]初始化webview
private WebView webView; private void initView(){ webView=(WebView)findViewById(R.id.view_webview); }
[2]webview提供javascript支持
WebSettings webSettings = webView.getSettings(); webSettings.setTextZoom(100);//设置web端界面不随html改变 webSettings.setDomStorageEnabled(true); // 使用localStorage webSettings.setLoadWithOverviewMode(true); // 设置页面自适应屏幕 webSettings.setJavaScriptEnabled(true); // 支持javascript webSettings.setNeedInitialFocus(false); // 阻止内部节点获取焦点 webSettings.setPluginState(PluginState.ON); webSettings.setAllowFileAccess(true); webSettings.setAllowContentAccess(true); webSettings.setAllowFileAccessFromFileURLs(true); webSettings.setAllowUniversalAccessFromFileURLs(true); // 修复加载资源失败BUG end webSettings.setSavePassword(false); // SDK3.0以上开启硬件加速,部分机器 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); } webView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY); webView.requestFocusFromTouch(); webView.setFocusable(true); webView.setLongClickable(true); webView.setHorizontalScrollBarEnabled(false);//水平不显示 webView.setVerticalScrollBarEnabled(false); //垂直不显示 webView.setOnLongClickListener(new WebView.OnLongClickListener() { @Override public boolean onLongClick(View v) { return true; } }); if (Build.VERSION.SDK_INT >= 21) {//添加这一句https和http都兼容,但其实中并没有什么用,只是为了防止有问题填写的 webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); } webSettings.setDomStorageEnabled(true); webSettings.setAppCacheMaxSize(1024*1024*8);//设置缓冲大小,我设的是8M String appCacheDir = context.getDir("cache", Context.MODE_PRIVATE).getPath(); webSettings.setAppCachePath(appCacheDir); webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH); webSettings.setAllowFileAccess(true); webSettings.setAppCacheEnabled(true); webSettings.setDomStorageEnabled(true); webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); // 移除有安全隐患的接口 removeUnSafeJavascriptInterface(); webView.setWebViewClient(webViewClient); webView.setWebChromeClient(webChromeClient);
移除有js安全隐患的接口
/** * 移除有安全隐患的JS接口 */ private void removeUnSafeJavascriptInterface() { try { webView.removeJavascriptInterface("searchBoxJavaBridge_"); webView.removeJavascriptInterface("accessibility"); webView.removeJavascriptInterface("accessibilityTraversal"); } catch (Exception e) { } }
下面为一些事件处理等支持
/** * 添加javascript插件 * * @param plugin * @param name */ @SuppressLint("JavascriptInterface") public void addJavascriptInterface(Object plugin, String name) { webView.addJavascriptInterface(plugin, name); } /** * 是否支持JS alert 显示 * * @param isSupport */ public void setSupportJsAlert(boolean isSupport) { try { if (!isSupport) { webView.setWebChromeClient(null); } else { webView.setWebChromeClient(new WebChromeClient() { @Override public boolean onJsAlert(WebView view, String url, String message, final JsResult result) { CommAlertDialog CommAlertDialog1 = new CommAlertDialog(context); CommAlertDialog1.setConfim(); CommAlertDialog1.setMessage("提示:"); final TextView comm_submit = (TextView) comm_dialog.findViewById(R.id.comm_submit); comm_submit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { result.confirm(); } }); CommAlertDialog1.setCancelable(false); CommAlertDialog1.show(); return true; } }); } } catch (Exception e) { } } private WebChromeClient webChromeClient=new WebChromeClient(){ @Override public void onProgressChanged(WebView view, int newProgress) { // TODO 自动生成的方法存根 if (newProgress == 100) { if(context instanceof LoginFragmentActvity || context instanceof WebViewActivity) { progressBar.setVisibility(View.INVISIBLE);// 加载完网页进度条消失 }else{ progressBar.setVisibility(View.GONE);// 加载完网页进度条消失 } if(plugin!=null){ plugin.hideWaitPanel(); } } else { progressBar.setVisibility(View.VISIBLE); progressBar.setProgress(newProgress);// 设置进度值 if(plugin!=null){ plugin.showWaitPanel(); } } } }; private WebViewClient webViewClient = new WebViewClient() { @Override public void onReceivedSslError(WebView view, android.webkit.SslErrorHandler handler, android.net.http.SslError error) { handler.proceed(); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { try { view.requestFocus(); view.loadUrl(url); webView.setVisibility(View.VISIBLE); error_rela_layout.setVisibility(View.GONE); } catch (Exception e) { } return true; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { Logs.d(TAG, "onPageStarted----"); plugin.showWaitPanel("加载中..."); } @Override public void onPageFinished(WebView view, String url) { plugin.hideWaitPanel(); if (context instanceof RHFragmentActivty) {//处理标题事件 RHFragmentActivty ac = (RHFragmentActivty) context; } if (comm_dialog != null && comm_dialog.isShowing()) { error_rela_layout.setVisibility(View.VISIBLE); } else { error_rela_layout.setVisibility(View.GONE); } } @Override public void onReceivedError(WebView view, final int errorCode, String description, String failingUrl) { try { plugin.hideWaitPanel(); error_rela_layout.setVisibility(View.VISIBLE); plugin.errPageBack(); String errorFlagString = ""; switch (errorCode) { case ERROR_AUTHENTICATION:// errorFlagString = "用户认证失败"; errorFlagString = "网络异常,请检查网络"; break; case ERROR_CONNECT: errorFlagString = "连接服务器失败"; break; case ERROR_TIMEOUT: errorFlagString = "网络连接超时"; break; case ERROR_PROXY_AUTHENTICATION:// errorFlagString = "用户代理验证失败"; errorFlagString = "网络异常,请检查网络"; break; case ERROR_HOST_LOOKUP: //errorFlagString = "服务器绑定或代理失败"; errorFlagString = "网络异常,请检查网络"; break; case ERROR_BAD_URL: errorFlagString = "URL 格式错误"; break; default: errorFlagString = "未知错误"; break; } final int err = errorCode; final String msg = description; if (comm_dialog == null) { comm_dialog = new CommAlertDialog(context); comm_dialog.setConfim(); comm_dialog.setTitle("系统提示"); comm_dialog.setMessage(errorFlagString + ""); final TextView comm_submit = (TextView) comm_dialog.findViewById(R.id.comm_submit); comm_submit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (webViewManageListener != null) { webViewManageListener.onClickErrorConfirm(err, msg); } comm_dialog.dismiss(); } }); } if (comm_dialog != null && comm_dialog.isShowing() != true) { comm_dialog.show(); }// if (view.canGoBack()) {// view.goBack();// } } catch (Exception e) { plugin.hideWaitPanel(); plugin.errPageBack();// if (view.canGoBack()) {// view.goBack();// } } } }; /** * WebViewManage 监听器 */ public interface WebViewManageListener { // 联网错误弹出确认框,点击确认框监听 public void onClickErrorConfirm(int errorCode, String description); }
在页面错误中,每个项目的实际需求不一样,请按照当前项目的实际需求开发选取。
3.NATIVE提供该HTML的js方法
1)js方法类的父类
package com.reach.doooly.base.plugin;/** * 插件基类,项目中插件需要继承此类,防止js注入 * @author qinming.fu@reach-core.com * Copyright (c) 2014 Shanghai P&C Information Technology Co., Ltd. */public class RHBasePlugin { /** * 防止js注入 */ public Object getClass(Object o) { return null; } /** * 处理js回调函数,如果函数不带括号,就加上括号 */ public String handleJsFunc(String func) { String handledFunc = func; if (!func.endsWith(")")) { handledFunc += "()"; } return handledFunc; }}
2)具体提供给html的js func实现
下面以弹出加载框为例子
package com.reach.doooly.pullresh.webview;import android.Manifest;import android.app.Activity;import android.app.AlertDialog;import android.content.Intent;import android.content.pm.PackageManager;import android.hardware.Camera;import android.net.Uri;import android.os.Bundle;import android.support.v4.app.ActivityCompat;import android.view.LayoutInflater;import android.view.View;import android.webkit.JavascriptInterface;import android.webkit.WebView;import android.widget.ImageView;import android.widget.TextView;import com.google.gson.Gson;import com.reach.doooly.R;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;import java.io.File;import java.net.URISyntaxException;import java.util.ArrayList;import java.util.List;/** * @Description native与webjs交互插件插件名称"SysClientJs" * @Author Lewis(lgs@yitong.com.cn) 2014年7月3日 上午9:23:33 * @Class JsPlugin Copyright (c) 2014 Shanghai P&C Information Technology * Co.,Ltd. All rights reserved. 修改人:fuqinming */public class NativePlugin extends RHBasePlugin { public static final String TAG = "NativePlugin"; public static final String NAME = "RHNativeJS"; private Activity activity; private CommAlertDialog builder;// 公用的弹出框 private WebView webView; private TopBarSetListener topBarSetListener; private LoadingDialog loadProgress;// 加载框 private static char ER_SPLIT_CHAR = 29; private static String ER_CODE_MESSAGE = "MOBILE" + ER_SPLIT_CHAR + "type" + ER_SPLIT_CHAR + "cardId"; public NativePlugin(Activity activity, WebView webView) { this.activity = activity; this.webView = webView; } public void setTopBarSetListener(TopBarSetListener topBarSetListener) { this.topBarSetListener = topBarSetListener; } /** * 2.show 加载框 */ @JavascriptInterface public void showWaitPanel() { Logs.d(TAG, "showWaitPanel开启等待层msg"); activity.runOnUiThread(new Runnable() { @Override public void run() { if (loadProgress == null && activity instanceof MainActivity) { loadProgress = new LoadingDialog(activity); } if (loadProgress != null && !activity.isFinishing() && !loadProgress.isShowing()) { // 满足1.当前加载框存在2.activity没有关闭3.加载框没有关闭 loadProgress.show(); } } }); } }
在activity中给js类添加别名
webViewManage.addJavascriptInterface(nativePlugin, NativePlugin.NAME);
4.HTML调用
<html><head> <title>测试</title> <script type="text/javascript"> function btnAction() { alert("测试initTopTitle() native") RHNativeJS.showWaitPanel(); }; function jumpOne(){ alert("执行弹出"); //window.location.href='http://baidu.com'; }; function jumpTwo(){ alert("执行弹出2"); //window.location.href='http://blog.csdn.net/changemyself/article/details/40212057'; }; //btnAction(); </script></head><body><button type="submit" onclick="btnAction()"> 加载</button><p/><button type="submit" onclick="jumpOne()"> 加载1</button><p/><button type="submit" onclick="jumpTwo()"> 加载2</button></body></html>
让webview加载这个url
url = "file:///android_asset/index.html"; Logs.d(TAG, "url:" + url); webView.loadUrl(url);
这样简单就完成了,运行代码之后会出现效果,先弹出框,然后弹出loadding框
下面是开发中需要特别注意的:
1)需要兼容HTTp和HTTPS,除了需要android原生代码证书认证之后,还需要web端jquery在2.3以上
2)html报错不会马上有小x提示,可以亲们注意日志,会提示某个方法不存在
3)键盘弹出隐藏,这里如果为adjustSize,会整体出现webview往上走,顾最好html自己实现键盘控制,当然也可以原生写,但是比较麻烦。为了更好的体验,web端实现最好不过了欧。
阅读全文
0 0
- Android HTML与原生交互
- IOS 原生与HTML交互
- android 原生与h5交互
- JS与Android原生交互
- android与html交互
- android与html交互
- android原生与js的交互。
- H5与android原生的JS交互
- Android原生代码与html5交互
- Android原生开发与HTML5交互
- Android原生代码与HTML5的交互
- h5页面与Android原生页面交互
- Android原生与H5交互的实现
- Android WebView 与 原生的交互
- H5页面与Android原生页面交互
- Android中JS与Native原生交互
- Android原生与H5交互的实现
- Android原生与H5交互的实现
- 面试时,如何回答你还有什么想要了解的?
- nodejs基础教程--http 与express比较
- 二路归并排序Python实现
- 直流电机PID控制例程程序注释
- SparkSQL已编程模式指定Schema
- Android HTML与原生交互
- 【区块链】DOCKER部署量子链私有网络环境以及部署智能合约实践
- Spring Cloud生态系统
- 字符函数库include<ctype.h>和字符串函数库include<string>
- gogland使用File Watchers 配置gofmt
- 数据分析
- 机器学习-kNN 算法(1)
- 自定义view-drawText
- 警告: A docBase has been specified, and will be ignored