关于原生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的交互

个人主页 Documents

在现在的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
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical">  
  6.   
  7.     <RelativeLayout  
  8.         android:id="@+id/rl_top"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="wrap_content"  
  11.         android:padding="10dp"  
  12.         android:background="#7DD13F"  
  13.         android:minHeight="?attr/actionBarSize">  
  14.   
  15.         <ImageView  
  16.             android:id="@+id/iv_back"  
  17.             android:layout_width="wrap_content"  
  18.             android:layout_height="wrap_content"  
  19.             android:layout_centerVertical="true"  
  20.             android:gravity="center"  
  21.             android:paddingBottom="12dp"  
  22.             android:paddingRight="12dp"  
  23.             android:paddingTop="12dp"  
  24.             android:src="@mipmap/icon_back" />  
  25.   
  26.         <TextView  
  27.             android:id="@+id/tv_title"  
  28.             android:layout_width="wrap_content"  
  29.             android:layout_height="wrap_content"  
  30.             android:layout_centerInParent="true"  
  31.             android:ellipsize="end"  
  32.             android:gravity="center"  
  33.             android:maxEms="8"  
  34.             android:textColor="#AF0000"  
  35.             android:singleLine="true"  
  36.             android:textSize="20sp" />  
  37.   
  38.         <TextView  
  39.             android:id="@+id/tv_menu"  
  40.             android:layout_width="wrap_content"  
  41.             android:layout_height="wrap_content"  
  42.             android:layout_alignParentRight="true"  
  43.             android:layout_centerVertical="true"  
  44.             android:gravity="center_vertical|right"  
  45.             android:text="网页弹窗"  
  46.             android:textSize="20sp"/>  
  47.     </RelativeLayout>  
  48.   
  49.     <LinearLayout  
  50.         android:id="@+id/ll_webview"  
  51.         android:layout_width="match_parent"  
  52.         android:layout_height="match_parent"  
  53.         android:layout_below="@+id/rl_top"  
  54.         android:orientation="vertical">  
  55.   
  56.     </LinearLayout>  
  57.   
  58. </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交互的方法的主要内容,如果未能解决你的问题,请参考以下文章

RN系列:Android原生与RN如何交互通信

android与H5数据交互(kotlin)

android与h5交互原理,h5与原生 app 交互的原理

H5&&Android交互

Android WebView与H5交互汇总

Android WebView与H5交互汇总