关于原生android与H5交互的方法
Posted z_xfan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于原生android与H5交互的方法相关的知识,希望对你有一定的参考价值。
文章目录
原生android与H5交互
前面讲解方法,结尾放代码
android调用H5方法
首先需要一个WebView
/*查找到WebView控件*/
mWebView = (WebView) findViewById(R.id.webView);
/*给WebView一个H5的链接,这里使用的是自己启动的Vue项目*/
mWebView.loadUrl("http://10.20.58.190:8081/");
/*对WebView进行设置*/
WebSettings webSettings = mWebView.getSettings();
/*既然要调用H5的方法,那么一定不能禁用JS方法*/
webSettings.setjavascriptEnabled(true);
- 方法一:使用WebView的loadUrl()方法,以loadUrl(script)的方式调用
android方法:
/*在某处写入这一行代码即可*/
mWebView.loadUrl("javascript:test1Fun('使用这种方法无法取得返回参数,且会刷新页面,如果js函数有返回值,则页面会仅展示返回值')");
需要H5支持:
/*
这里使用的是Vue,对data里的test1Content 进行了修改
*/
test1Fun(str)
this.test1Content = str;
// return "调用test1Fun成功";
/*
要注意的是,如果使用原生H5,直接在页面的JavaScript标签里写入一个方法即可
但是如果使用vue来写的话,需要将此方法暴露给window,如下
*/
mounted()
window.test1Fun = this.test1Fun;
这种方法比较简单,但是缺点在于android无法获取函数的返回值
注:如果调用的函数存在返回值的话,那么H5的页面会只显示返回值
- 方法二:使用WebView的evaluateJavascript()方法
android方法:
mWebView.evaluateJavascript("test2Fun('使用这种方法可以取得返回参数,且不会刷新页面')", new ValueCallback<String>()
@Override
public void onReceiveValue(String value)
text2.setText(value);
);
这种方法同样需要H5支持,同上:
test2Fun(str)
this.test2Content = str;
return "调用test2Fun成功";
/*同样需要暴露到window*/
mounted()
window.test2Fun = this.test2Fun;
这种方法比上一种方法更为灵活,且能够获取返回值
H5调用android
- 方法一:使用WebView的addJavascriptInterface()方法注入对象。
android注入:
/*将JsInteration注入到h5的window.android中*/
mWebView.addJavascriptInterface(new JsInteration(), "android");
/*这里实现JsInteration */
public class JsInteration
@JavascriptInterface
public String JsCallJava1(String value)
text3.setText(value);
return "调用JsCallJava1成功";
H5调用:
useJsCallJava1()
let a = window.android.JsCallJava1("我是JsCallJava1的返回值");
this.JsCallJava1Content = a;
这种方式运用最为广泛,一些企业级的项目都是以此为基础搭建H5调用android的桥方法,当然,为了防止注入过多的方法,参数一般是JSON字符串格式,在android获取到参数后,会将其转换为JSON,然后根据其状态,进行后续的操作反馈。
- 方法二:使用WebViewClient 的shouldOverrideUrlLoading()方法回调拦截请求。
android方法:
/*这里的url是H5将要进行跳转的链接,使用这个方法进行拦截*/
mWebView.setWebViewClient(new WebViewClient()
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
if (url.equals("http://10.20.58.190:8081/intercept"))
text4.setText("intercept");
// startActivity(new Intent(MainActivity.this,SecondFragment.class));
return true;
else
mWebView.loadUrl(url);
return false;
);
H5调用:
location.href = "http://10.20.58.190:8081/intercept";
注:这里一般是用于拦截链接,如果shouldOverrideUrlLoading
的返回值为true,则会进行拦截,H5不进行跳转,否则则进行跳转
- 方法三:重写 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息。
android方法:
mWebView.setWebChromeClient(new WebChromeClient()
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result)
if (message.equals("alert"))
alert.setText("成功");
return super.onJsAlert(view, url, message, result);
@Override
public boolean onJsConfirm(WebView view, String url, String message, JsResult result)
if (message.equals("confirm"))
confirm.setText("成功");
return super.onJsConfirm(view, url, message, result);
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)
if (message.equals("prompt"))
prompt.setText("成功");
return super.onJsPrompt(view, url, message, defaultValue, result);
);
H5触发:
useJsCallJava3(judge)
if(judge == 1)
alert('alert')
if(judge == 2)
confirm('confirm')
if(judge == 3)
prompt('prompt')
此方法将会监听三种弹窗,用户可以根据弹窗内容进行判断,但是请注意
如果在android拦截后,return了true,则会默认客户会对弹窗进行处理,所以我们要对弹窗进行额外处理,否则H5页面就会卡死。
因此这种方法为了避免麻烦,还是少用为好,并且不对弹窗进行拦截,仅监听即可。
最后,完整的demo如下
MainActivity.java:
package com.example.study_android_java_javascript;
import android.os.Bundle;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity
public static final String TAG = "MainActivity";
private WebView mWebView;
private TextView text1;
private TextView text2;
private TextView text3;
private TextView text4;
private Button btn1;
private Button btn2;
private Button btn_clear;
private TextView alert;
private TextView confirm;
private TextView prompt;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text1 =findViewById(R.id.text1);
text2 =findViewById(R.id.text2);
text3 = findViewById(R.id.text3);
text4 = findViewById(R.id.text4);
alert = findViewById(R.id.alert);
confirm = findViewById(R.id.confirm);
prompt = findViewById(R.id.prompt);
btn1 = (Button) findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
mWebView.loadUrl("javascript:test1Fun('使用这种方法无法取得返回参数,且会刷新页面,如果js函数有返回值,则页面会仅展示返回值')");
);
btn2 = (Button) findViewById(R.id.btn2);
btn2.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
mWebView.evaluateJavascript("test2Fun('使用这种方法可以取得返回参数,且不会刷新页面')", new ValueCallback<String>()
@Override
public void onReceiveValue(String value)
text2.setText(value);
);
);
btn_clear = findViewById(R.id.btn_clear);
btn_clear.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
mWebView.loadUrl("javascript:clearContent()");
text2.setText("暂无返回");
);
mWebView = (WebView) findViewById(R.id.webView);
mWebView.loadUrl("http://10.20.58.190:8081/");
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JsInteration(), "android");
mWebView.setWebViewClient(new WebViewClient()
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
if (url.equals("http://10.20.58.190:8081/intercept"))
text4.setText("intercept");
// startActivity(new Intent(MainActivity.this,SecondFragment.class));
return true;
else
mWebView.loadUrl(url);
return false;
);
mWebView.setWebChromeClient(new WebChromeClient()
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result)
if (message.equals("alert"))
alert.setText("成功");
return super.onJsAlert(view, url, message, result);
@Override
public boolean onJsConfirm(WebView view, String url, String message, JsResult result)
if (message.equals("confirm"))
confirm.setText("成功");
return super.onJsConfirm(view, url, message, result);
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)
if (message.equals("prompt"))
prompt.setText("成功");
return super.onJsPrompt(view, url, message, defaultValue, result);
);
//Android调用有返回值js方法
public class JsInteration
@JavascriptInterface
public String JsCallJava1(String value)
text3.setText(value);
return "调用JsCallJava1成功";
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal">
<WebView
android:layout_width="match_parent"
android:layout_height="200dp"
android:id="@+id/webView"
/>
<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="使用webview.loadUrl()调用JavaScript方法"/>
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="暂无返回"/>
<TextView
android:layout_width="match_parent"
android:layout_height="20dp"/>
<Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="使用webview.evaluateJavascript()调用JS方法"/>
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="暂无返回"/>
<Button
android:id="@+id/btn_clear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="清除H5的内容"
android:layout_marginTop="20dp"/>
<TextView
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="JavaScript调用Java方法:"/>
<TextView
android:id="@+id/text3"
android:<Android WebView实现原生与JS的交互
在现在的Android开发中,为了追求开发的效率以及移植的便利性,越来越多的开发者会在App中使用WebView作为部分业务内容展示与交互的主要载体。那么在这种Hybrid(混合式) App中,难免就会遇到页面JS需要与Java相互调用,调用Java方法去做那部分网页JS不能完成的功能或者是通过Java来注入JS使网页去执行相关的操作。
实现步骤:
1、 自定义WebView
public class MyWebView extends WebView
private WebViewInterface mWebViewInterface;
public MyWebView(Context context)
super(context);
init();
public void setWebViewInterface(WebViewInterface baseWebViewInterface)
mWebViewInterface = baseWebViewInterface;
//回调方法接口
public interface WebViewInterface
void showToast(String msg);
void getTitle(String title);
public void init()
WebSettings ws = getSettings();
setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
setHorizontalScrollBarEnabled(false);
setVerticalScrollBarEnabled(false);
ws.setJavaScriptEnabled(true);
ws.setDomStorageEnabled(true);
ws.setSupportZoom(true);
ws.setBuiltInZoomControls(true);
ws.setBuiltInZoomControls(false);
ws.setJavaScriptCanOpenWindowsAutomatically(true);
//注入带有Java方法的JS对象,名字可以自定义(js_obj)
addJavascriptInterface(new InJavaScriptObj(), "js_obj");
setWebViewClient(new MyWebViewClient());
setWebChromeClient(new MyWebChromeClient());
final class InJavaScriptObj
//android 4.2 之后版本提供给js调用的函数必须带有注释语句@JavascriptInterface
@JavascriptInterface
public void showToast(String msg)
mWebViewInterface.showToast(msg);
private class MyWebViewClient extends WebViewClient
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
//加载网页url,此处可以根据url进行相应的处理
return super.shouldOverrideUrlLoading(view, url);
@Override
public void onPageFinished(WebView view, String url)
//实现自己的逻辑
super.onPageFinished(view, url);
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon)
super.onPageStarted(view, url, favicon);
//实现自己的逻辑
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error)
//错误处理
super.onReceivedError(view, request, error);
@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse)
//http错误处理
super.onReceivedHttpError(view, request, errorResponse);
private class MyWebChromeClient extends WebChromeClient
@Override
public void onReceivedTitle(WebView view, String title)
super.onReceivedTitle(view, title);
//这个方法是收到网页的title的时候会调用的,这里我们可以拿到网页的title显示处理
mWebViewInterface.getTitle(title);
@Override
public boolean onJsAlert(WebView view, String url, String message, final JsResult result)
// 在这里你可以拦截网页的Alert来实现自己的逻辑,return true停止事件的继续传播,也可以使用默认实现
return super.onJsAlert(view, url, message, result);
@Override
public boolean onJsConfirm(WebView view, String url, String message, JsResult result)
// 在这里你可以实现拦截网页的Confirm来实现自己的逻辑,return true停止事件的继续传播,也可以使用默认实现
return super.onJsConfirm(view, url, message, result);
@Override
public void onProgressChanged(WebView view, int newProgress)
super.onProgressChanged(view, newProgress);
//在这里你可以进度的变化实现自己的逻辑
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)
return super.onJsPrompt(view, url, message, defaultValue, result);
2、使用自定义WebView来实现功能
布局文件:
[html]
view plain
copy
- <?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:orientation="vertical">
-
- <RelativeLayout
- android:id="@+id/rl_top"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:padding="10dp"
- android:background="#7DD13F"
- android:minHeight="?attr/actionBarSize">
-
- <ImageView
- android:id="@+id/iv_back"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:gravity="center"
- android:paddingBottom="12dp"
- android:paddingRight="12dp"
- android:paddingTop="12dp"
- android:src="@mipmap/icon_back" />
-
- <TextView
- android:id="@+id/tv_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:ellipsize="end"
- android:gravity="center"
- android:maxEms="8"
- android:textColor="#AF0000"
- android:singleLine="true"
- android:textSize="20sp" />
-
- <TextView
- android:id="@+id/tv_menu"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:gravity="center_vertical|right"
- android:text="网页弹窗"
- android:textSize="20sp"/>
- </RelativeLayout>
-
- <LinearLayout
- android:id="@+id/ll_webview"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_below="@+id/rl_top"
- android:orientation="vertical">
-
- </LinearLayout>
-
- </RelativeLayout>
activity:
public class WebViewActivity extends AppCompatActivity implements MyWebView.WebViewInterface, View.OnClickListener
private LinearLayout mWebViewLl;
private MyWebView mWebView;
private ImageView mBackIv;
private TextView mTitleTv;
private TextView mMenuTv;
private String url;
private static final int SET_TITLE = 0x101;
private Handler mHandler = new Handler()
@Override
public void handleMessage(Message msg)
if (msg.what == SET_TITLE)
setMyTitle((String) msg.obj);
;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_webview);
initView();
private void initView()
url = getIntent().getStringExtra("url");
mMenuTv = (TextView) findViewById(R.id.tv_menu);
mBackIv = (ImageView) findViewById(R.id.iv_back);
mWebViewLl = (LinearLayout) findViewById(R.id.ll_webview);
mTitleTv = (TextView) findViewById(R.id.tv_title);
mMenuTv.setOnClickListener(this);
mBackIv.setOnClickListener(this);
mWebView = new MyWebView(this);
mWebViewLl.addView(mWebView);
mWebView.setWebViewInterface(this);
mWebView.loadUrl(url);
//回调方法的实现
@Override
public void showToast(String msg)
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
//回调方法的实现
@Override
public void getTitle(String title)
Message message = new Message();
message.what = SET_TITLE;
message.obj = title;
mHandler.sendMessage(message);
private void setMyTitle(String title)
mTitleTv.setText(title);
@Override
public void onBackPressed()
back();
private void back()
if (mWebView.canGoBack())
mWebView.goBack();
else
this.finish();
@Override
public void onClick(View v)
switch (v.getId())
case R.id.iv_back:
back();
break;
case R.id.tv_menu:
//注入JS代码,Java调用JS
mWebView.loadUrl("javascript:alert('网页弹窗alert');");
break;
网页代码:
<head>
<title>测试</title>
<style>
a
color:green;
font-weight:900;
font-size:80px;
height:400;
width:500;
button
color:green;
font-size:50px;
height:300;
width:400;
</style>
<script>
//JS调用Java方法,js_obj为网页中带有Java方法的对象,可以自定义但是要和注入的名字一样
function myFunction()
js_obj.showToast("显示Toast");
</script>
</head>
<br>
<a href="file:///android_asset/test_1.html"> 链 接 </a> </br>
<button οnclick="myFunction()" >显示Toast</button>
</body>
</html>
效果:
源代码:https://github.com/cokernut/CustomWebView
以上是关于关于原生android与H5交互的方法的主要内容,如果未能解决你的问题,请参考以下文章