一、前言:
在 Android 中我们要给 js 传递参数;js 也会给我们传递参数;有时候也要拿到 js 的点击事件,来完成 app 本地操作。
WebView 常见的坑: 点击查看:
1. Activity中的使用:
public class MyAgreementDetailsActivity extends BaseDaggerActivity<MyAgreementDetailsPresenter> 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<ResponseEmptyDataBean> 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"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical"
android:background="@color/color_FFFFFF"
>
<include layout="@layout/layout_title_bar"/>
<ProgressBar
android:id="@+id/progressBar1"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_2"
android:progressDrawable="@color/color_FFF96857"
android:visibility="gone"
/>
<com.sumansoul.teacher.widget.custom.CustWebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.sumansoul.teacher.widget.custom.CustWebView>
</LinearLayout>
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