Android(安卓)中 WebView 交互
16lz
2021-01-24
一、前言:
在 Android 中我们要给 js 传递参数;js 也会给我们传递参数;有时候也要拿到 js 的点击事件,来完成 app 本地操作。
WebView 常见的坑: 点击查看:
1. Activity中的使用:
public class MyAgreementDetailsActivity extends BaseDaggerActivity implements MyAgreementDetailsContract.View { @Inject MyAgreementDetailsPresenter myAgreementPresenter; @BindView(R.id.iv_main_back) ImageView ivMainBack; @BindView(R.id.tv_main_title) TextView tvMainTitle; @BindView(R.id.iv_main_clock) ImageView ivMainClock; @BindView(R.id.rl_title) RelativeLayout rlTitle; @BindView(R.id.progressBar1) ProgressBar progressBar1; @BindView(R.id.webview) CustWebView webview; private String agreementName; private String agreementId; private String url; private int nper; private int agrType; private int isChange; private String token; private boolean isFirst = false; public static void launch(Context context, String agreement_id, String agreement_name, int nper, String url, int agr_type, int is_change) { Intent intent = new Intent(context, MyAgreementDetailsActivity.class); intent.putExtra("agreementName", agreement_name); intent.putExtra("agreementId", agreement_id); intent.putExtra("url", url); intent.putExtra("nper", nper); intent.putExtra("agrType", agr_type); intent.putExtra("isChange", is_change); context.startActivity(intent); } @Override public MyAgreementDetailsPresenter createPresent() { return myAgreementPresenter; } @RequiresApi(api = Build.VERSION_CODES.KITKAT) @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_agreement_view); ButterKnife.bind(this); initEvent(); initData(); } @RequiresApi(api = Build.VERSION_CODES.KITKAT) @SuppressLint("JavascriptInterface") private void initData() { token = SPUtils.getInstance(SPConstant.TOKEN).getString(SPConstant.TOKEN); agreementName = getIntent().getStringExtra("agreementName"); //协议id agreementId = getIntent().getStringExtra("agreementId"); //期数 nper = getIntent().getIntExtra("nper", 0); //跳转链接 url = getIntent().getStringExtra("url"); agrType = getIntent().getIntExtra("agrType", 0); isChange = getIntent().getIntExtra("isChange", 0); tvMainTitle.setText(agreementName); final WebSettings webSettings = webview.getSettings(); //启用JS webSettings.setJavaScriptEnabled(true); //设置是否支持变焦 webSettings.setSupportZoom(true); //缩放 webSettings.setBuiltInZoomControls(true); webSettings.setDisplayZoomControls(false); //多窗口 webSettings.setJavaScriptCanOpenWindowsAutomatically(true); webSettings.setSupportMultipleWindows(true); webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); webSettings.setDefaultFontSize(18); webSettings.setAllowFileAccess(true); webSettings.setAllowFileAccessFromFileURLs(true); //启用缓存 webSettings.setAppCacheEnabled(true); webSettings.setAllowFileAccess(true); // webSettings.setDomStorageEnabled(true); //设置缓存模式 webSettings.setBlockNetworkImage(false); //解决图片不显示 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); } webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); webSettings.setUseWideViewPort(true); webSettings.setLoadWithOverviewMode(true); try { if (Build.VERSION.SDK_INT >= 16) { Class<?> clazz = webview.getSettings().getClass(); Method method = clazz.getMethod( "setAllowUniversalAccessFromFileURLs", boolean.class);//利用反射机制去修改设置对象 if (method != null) { method.invoke(webview.getSettings(), true);//修改设置 } } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } webview.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { // TODO 自动生成的方法存根 if (newProgress == 100) { progressBar1.setVisibility(View.GONE);//加载完网页进度条消失 } else { progressBar1.setVisibility(View.VISIBLE);//开始加载网页时显示进度条 progressBar1.setProgress(newProgress);//设置进度值 } } }); webview.loadUrl(url); //在js中调用本地java方法 callAndroid webview.addJavascriptInterface(new JsInterface(this), "click"); //允许调试 if (BuildConfig.DEBUG){ WebView.setWebContentsDebuggingEnabled(true); }else { WebView.setWebContentsDebuggingEnabled(false); } /** * webView 加载的时候 会跳到手机自带的浏览器 * 给自己定义个webview添加客户端 */ webview.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return super.shouldOverrideUrlLoading(view, url); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); // webview.loadUrl("javascript:loadingDate(' " + mLoginSMSBean.getToken() + " ' ,'" + mAgreementBean.getAgreement_id() + "' ,'" + "2" + "','" + mAgreementBean.getAgr_type() + "','" + mAgreementBean.getNper() + "' ,'" + mAgreementBean.getIs_change() + "' )"); if (!isFirst) { isFirst = true; webview.loadUrl("javascript:loadingDate('" + token + "','" + agreementId + "','" + "2" + "','" + agrType + "','" + nper + "','" + isChange + "' )"); // LogUtils.d("LUO", "===" + token); } } }); webview.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN) { //按返回键操作并且能回退网页 if (keyCode == KeyEvent.KEYCODE_BACK && webview.canGoBack()) { //后退 webview.goBack(); return true; } } return false; } }); } private void initEvent() { //返回 ivMainBack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); } @Override public void onError(String error) { ToastUtils.showShort(error); } @Override public void AgreementDetailsSuccess(BaseHttpResponse data) { ToastUtils.showShort("协议签署成功"); finish(); } /** * 2.编写一个提供给Web的Js接口类 */ public class JsInterface { private Context mContext; public JsInterface(Context context) { this.mContext = context; } //在js中调用window.AndroidWebView.showInfoFromJs(name),便会触发此方法。 @JavascriptInterface public void clickAction(String json, String flag) { if(!TextUtils.isEmpty(json)){ JsBean jsBean = JSON.parseObject(json, JsBean.class); submitData(jsBean); }// LogUtils.d("LUO", json + "==========" + flag);// ToastUtils.showShort("点击了按钮"); } } private void submitData(JsBean jsBean) { HashMap map = new HashMap(); map.put("agreement_id",agreementId);// 协议id map.put("nickname",jsBean.getNickname());//用户姓名 map.put("id_card_no",jsBean.getId_card_no());//身份证号 map.put("mobile",jsBean.getMobile());// 联系方式 map.put("province",jsBean.getProvince());// 省 map.put("city",jsBean.getCity());// 市 map.put("country",jsBean.getCountry());// 县 map.put("address",jsBean.getAddress());//详细地址 map.put("email",jsBean.getEmail());//邮箱地址 map.put("title",jsBean.getTitle());// 协议标题 map.put("signed",jsBean.getSigned()); map.put("signed_time",jsBean.getSigned_time());//签署时间// map.put("front_id_card",);//身份证正面照链接// map.put("back_id_card",);//身份证反面照链接 map.put("agr_type",String.valueOf(agrType));//协议类型 1:普通协议 2:隐私协议 map.put("nper",String.valueOf(nper));//期数 map.put("nper_upper",jsBean.getNper_upper());//大写期数 //本地网络请求 myAgreementPresenter.getAgreementDetails(map); }}
2. activity_agreement_view.xml 布局:
<?xml version="1.0" encoding="utf-8"?>
3. 自定义CustWebView:
public class CustWebView extends WebView { private OnTouchScreenListener onTouchScreenListener; public CustWebView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public CustWebView(Context context, AttributeSet attrs) { super(context, attrs); } public CustWebView(Context context) { super(context); } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (onTouchScreenListener != null) onTouchScreenListener.onTouchScreen(); } if (event.getAction() == MotionEvent.ACTION_UP) { if (onTouchScreenListener != null) { onTouchScreenListener.onReleaseScreen(); } } return super.onTouchEvent(event); } public interface OnTouchScreenListener { void onTouchScreen(); void onReleaseScreen(); } public void setOnTouchScreenListener(OnTouchScreenListener onTouchScreenListener) { this.onTouchScreenListener = onTouchScreenListener; }}
二、总结:
1. 设置WebView属性,能够执行Javascript脚本
mWebView.getSettings().setJavaScriptEnabled(true);//设置js可用
2. 设置加载进度条
webview.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { // TODO 自动生成的方法存根 if (newProgress == 100) { progressBar1.setVisibility(View.GONE);//加载完网页进度条消失 } else { progressBar1.setVisibility(View.VISIBLE);//开始加载网页时显示进度条 progressBar1.setProgress(newProgress);//设置进度值 } } });
3. 浏览器内部跳转:
/** * webView 加载的时候 会跳到手机自带的浏览器 * 给自己定义个webview添加客户端 */ webview.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return super.shouldOverrideUrlLoading(view, url); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); } });
4. webview 显示点击返回键:
webview.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN) { //按返回键操作并且能回退网页 if (keyCode == KeyEvent.KEYCODE_BACK && webview.canGoBack()) { //后退 webview.goBack(); return true; } } return false; } });
5. webview 是否允许调试:
//允许调试 if (BuildConfig.DEBUG){ WebView.setWebContentsDebuggingEnabled(true); }else { WebView.setWebContentsDebuggingEnabled(false); }
6. 接受 JS 给 Android 传递参数:
在js中调用本地java方法
webview.addJavascriptInterface(new JsInterface(this), "click");
/** * 2.编写一个提供给Web的Js接口类 */ public class JsInterface { private Context mContext; public JsInterface(Context context) { this.mContext = context; } // @JavascriptInterface一定要写 @JavascriptInterface public void clickAction(String json, String flag) { LogUtils.d("LUO", json + "==========" + flag); ToastUtils.showShort("点击了按钮"); } }
7. Android 给 JS 传递参数
mWebView.loadUrl("javascript:javaCall('fasff')");
页面加载完成后,给 JS 传递参数:
/** * webView 加载的时候 会跳到手机自带的浏览器 * 给自己定义个webview添加客户端 */ webview.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return super.shouldOverrideUrlLoading(view, url); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); // webview.loadUrl("javascript:loadingDate(' " + mLoginSMSBean.getToken() + " ' ,'" + mAgreementBean.getAgreement_id() + "' ,'" + "2" + "','" + mAgreementBean.getAgr_type() + "','" + mAgreementBean.getNper() + "' ,'" + mAgreementBean.getIs_change() + "' )"); if (!isFirst) { isFirst = true; webview.loadUrl("javascript:loadingDate('" + token + "','" + agreementId + "','" + "2" + "','" + agrType + "','" + nper + "','" + isChange + "' )"); // LogUtils.d("LUO", "===" + token); } } });
8. 无法下载文件?
在自己写的 WebView 下是无法直接下载文件,需要自己监听下载事件并对下载的动作进行处理。
/*** 当下载文件时打开系统自带的浏览器进行下载,当然也可以对捕获到的 url 进行处理在应用内下载。**/webView.setDownloadListener(new FileDownLoadListener());private class FileDownLoadListener implements DownloadListener { @Override public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) { Uri uri = Uri.parse(url); Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent); }}
作者:cpacm
链接:https://www.jianshu.com/p/fea5e829b30a
参考链接:https://blog.csdn.net/qq_21267961/article/details/79494829
更多相关文章
- Android(安卓)Apk加固(安全专项)
- android activy加载
- Android(安卓), and
- Android中webview拨打加载网页中的电话超链接
- android打开网站
- Android(安卓)listview下拉刷新 上拉加载
- 自定义view-制作一个加载中的圆形
- Android有效解决加载大图片内存溢出问题及优化虚拟机内存
- android RecycleView实现下拉刷新和上拉加载