文章目录[隐藏]
感觉这个和通过复写shouldOverrideUrlLoading来调用andriod代码有相似之处,但发现了有趣的一点是它在触发后可以把Android的一个数据给返回到JS代码之处;
代码
布局
HTML
在src/main/下创建一个文件夹assets,里面添加一个index.html文件,内容如下;
<html>
<head>
<meta charset="utf-8">
<title>emperinter</title>
<script>
function clickprompt(){
var name,password;
name = document.getElementById("n").value;
document.getElementById("gn").innerHTML = name;
password = document.getElementById("p").value;
document.getElementById("gp").innerHTML = password;
var data = "js://demo?arg1=" + name + "&arg=" + password + "&arg3=test&fuck=fuck";
document.getElementById("toandroid").innerHTML = data;
// 调用prompt(),result为Android传来的值
var result=prompt(data);
alert("demo " + result);
document.getElementById("info").innerHTML = result;
}
</script>
</head>
<body>
<div align="center">
name:<input id="n">
<br/>
password:<input id="p">
<p id="info">Android 传进来的值</p>
get_name:<p style="color:red;" id="gn">get_name</p>
get_password:<p style="color:red" id="gp">get_password</p>
<p id="toandroid">传给Android的一套js数据</p>
<!-- 点击按钮则调用clickprompt() -->
<button style="font-size:32px;" type="button" onclick="clickprompt()">点击调用Android代码</button>
<p></p>
</div>
</body>
</html>
MainActivity
注意这里的Uri参数是message!
public class MainActivity extends AppCompatActivity {
WebView mwebview;
TextView mtxt0;
TextView mtxt1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mwebview = (WebView) findViewById(R.id.MainWeb);
mtxt0 = (TextView) findViewById(R.id.MainTxt0);
mtxt1 = (TextView) findViewById(R.id.MainTxt1);
WebSettings websettings = mwebview.getSettings();
// 允许 WebView 加载 JS 代码
websettings.setJavaScriptEnabled(true);
// 允许 JS 弹窗
websettings.setJavaScriptCanOpenWindowsAutomatically(true);
try {
mwebview.loadUrl("file:///android_asset/index.html");
Log.e("LoadUrl:", "Successful !");
}catch (Exception ex) {
Log.e("LoadUrl:", "wrong !");
}
mwebview.setWebChromeClient(new WebChromeClient(){
//拦截输入框(原理同复写shouldOverrideUrlLoading)
//参数message:代表prompt()的内容(不是url)
//参数result:代表输入框的返回值
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result){
//根据协议的参数,判段是否所需要的url
//一般根据schema(协议格式) & authority(协议名)判断(前两个参数)
//假定传入进来的 rul = "js://demo?arg1=111&arg2=222" (同时也是约定好需要拦截的)
Uri uri = Uri.parse(message);
// 如果url的协议 = 预先约定的js协议
// 就往下解析参数
if(uri.getScheme().equals("js")){
//如果 authority = 预先约定协议里的webview,即代表都符合约定的协议
//所以拦截rul,下面JS开始调用Android需要的方法
if(uri.getAuthority().equals("demo")){
//参数result:代表消息框的返回值(输入值),这里的参数会传递给JS里面去;
result.confirm("从Android向JS返回的数据");
Set<String> collection = uri.getQueryParameterNames();
Iterator<String> it = collection.iterator();
String txt0 = uri.getQueryParameter(it.next());
String txt1 = uri.getQueryParameter(it.next());
mtxt0.setText(txt0);
Log.e("arg1",txt0);
mtxt1.setText(txt1);
Log.e("arg2",txt1);
//// 测试传参
Log.e("test:",uri.getQueryParameter(it.next()));
Log.e("fuck:",uri.getQueryParameter(it.next()));
}
return true;
}
return super.onJsPrompt(view,url,message,defaultValue,result);
}
// 通过alert()和confirm()拦截的原理相同
// 拦截JS的警告框
// @Override
// public boolean onJsAlert(WebView view,String url,String message, JsResult result){
// return super.onJsAlert(view,url,message,result);
// }
//
// // 拦截JS的确认框
// public boolean onJsConfirm(WebView view,String url,String message,JsResult result){
// return super.onJsConfirm(view,url,message,result);
// }
});
}
}