Android中JS与Native原生交互

前言


之前面试也遇到到这个,现在做邮箱系统也有类似需求,决定好好研究一番!


效果图




什么是JS?


 JS:JavaScript的缩写,是个脚本语言,跟Java也没有太大的关系,相对来说,从事前端工作的用的比较多,比如学习过PHP,ASP.NET(我大学的专业)的都要牢牢的掌握,因此我略懂一点,大学看过杨中科老师的.NET视频,视频讲的很好,学习了Dom,JQurey,Ajax等,JQuery其实就是封装了一个JS的函数等可以理解为一个JS的快捷库,对于前端来说,JS是很重要的,我觉得安卓和前端类似,咱们也要学点,毕竟安卓本身也是“混搭”模型,跟网页比较类似,跳来跳去的.


什么是Native?



近几年很火的一个词语啊,ReactNative,H5等都跟Native挂钩。安卓和IOS开发的App就是Native App(原生App),而用RN或者H5开发的app叫做“网页”app,严格意义上来说,不能叫做app,其实就是用网页技术html,js等来开发的,界面效果等各方面比较像原生app而已,网页技术发展比较快,但是替代原生,我觉得还是要走很长一段路的,感觉原生也替代不了,以后也许会有个革新吧,我们拭目以待就是啦!


怎么理解JS和Native交互


前两节简单说了下JS和Native的意思,JS和Native交互严格意思说的不太准确,因为是这个网页html里面可能嵌套了一些JS代码,而正是通过这些JS代码来与原生App进行交互,传递数据,这个层面上JS和Native交互还是比较准确的。
两者相互调用过程如下:

1.Native原生调用网页里JS代码块


   原生这里指Android或者IOS,比如一个按钮的点击事件来调用这个网页里的一个JS函数,如下所示:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <script>
        function showInfo(content)
        {
            document.getElementById("info").innerHTML=content;
        }
        //这个函数来更新id为hrefId的html块,传入参数随意,可以是字符串,数字等
        function updateHref(defaultContent){
        //这里面我定义了一个对象,对象随意定义了name和age,还可以继续的添加比如性别
            var person = new Object();
            person.name = defaultContent;
            person.age = 11;
           document.getElementById("hrefId").innerHTML=person.name + "年龄= " + person.age;
        }


    </script>

</head>
<body>
Android调用Js的showInfo方法,传的数据为:<span id="info"> </span>
<br>
<a href="#" id="hrefId" οnclick="window.GJNativeAPI.callAndroid('')">
    这个就是JS调用Android Native的方法了,传什么值可以由 调用者本身控制
</a>
</body>
</html>

上面是我在assets目录放的一个html文件,符合W3C规范的html文件,上面有些地方是有注释的,JS代码块的风格是以<Script>开头,以</Script>结束,中间是编写JS函数的地方,初始化变量的地方.上面有两个函数,一个是showInfo(content),你一定会问,content是什么鬼,这个我为了“见名知意”,这个参数其实可以是任意类型,可以是字符串或者数字,如果不太懂语法的话,博客最后会有一个链接,大家可以简单学习下JS的函数,语法等,略知一二就行.

2.JS调用原生Native定义好的方法


另一个函数叫updateHref(defaultContent),这个我是为了更新

<a href="#" id="hrefId" οnclick="window.GJNativeAPI.callAndroid('')">
    这个就是JS调用Android Native的方法了,传什么值可以由 调用者本身控制
</a>

这块的内容而写的函数,就是效果图中第二个按钮点击后,会弹出SnackBar提示并更新这个链接Href的innerHtml(内容).

具体说下:第一个按钮就是android原生调用了JS的函数showInfo,而这个showInfo就是为id为info的innerHtml 赋值,即内容.

第二个函数,是JS调用Android原生代码里定义的函数callAndroid(String str),看下我代码里的

 /**
     * 供 js 调用的本地对象
     */
    public class GJNativeAPI {
        @JavascriptInterface
        public void callAndroid(final String str) {
            Snackbar.make(getCurrentFocus(), str, Snackbar.LENGTH_SHORT).show();
        }
    }
然后回过头来看网页中的定义
<a href="#" id="hrefId" οnclick="window.GJNativeAPI.callAndroid('')">
    这个就是JS调用Android Native的方法了,传什么值可以由 调用者本身控制
</a>

ID为hrefId的click事件为"window.GJNativeAPI.callAndroid('可以传一个默认内容'),这个事件就是响应了咱们自己定义的事件了,这个就是JS调用原生Native的方法啦.

这个跟网页交互,肯定要有展示网页的控件啦,首先想到的是WebView,IOS是UIWebView,首先Webview需要loadUrl,否则无法进行JS和Native的互相访问.

WebView配置,具体代码如下:

   webView.loadUrl(TEST_HTML);
        webView.addJavascriptInterface(new GJNativeAPI(), "GJNativeAPI");
        webView.setWebViewClient(webViewClient);

完整代码如下:

package com.androidjsnativedemo;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;


public class WebViewActivity extends AppCompatActivity {
    private static final String TEST_HTML = "file:///android_asset/h5.html";

    WebView webView;

    Button androidHandleJs, jsHandleAndroid;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview);
        initView();
        initWebViewConfig();
        initData();
        initListener();
    }

    private void initView() {
        webView = (WebView) findViewById(R.id.webview);
        androidHandleJs = (Button) findViewById(R.id.androidHandleJs);
        jsHandleAndroid = (Button) findViewById(R.id.jsHandleAndroid);
    }

    private void initData() {
        webView.loadUrl(TEST_HTML);
        webView.addJavascriptInterface(new GJNativeAPI(), "GJNativeAPI");
        webView.setWebViewClient(webViewClient);
    }

    private void initWebViewConfig() {
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
    }

    private void initListener() {
        androidHandleJs.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                webView.loadUrl("javascript:showInfo('Android 调用 JS里的方法,我是来自Android端调用并传数据给你更新Html界面')");
            }
        });
        jsHandleAndroid.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                webView.loadUrl("javascript:window.GJNativeAPI.callAndroid('JS调用Android自定义的Native方法并在Native原生Activity提示')");
                webView.loadUrl("javascript:updateHref('更改href的默认内容')");
            }
        });
        webView.setWebViewClient(new WebViewClient());
    }

    /**
     * 供 js 调用的本地对象
     */
    public class GJNativeAPI {
        @JavascriptInterface
        public void callAndroid(final String str) {
            Snackbar.make(getCurrentFocus(), str, Snackbar.LENGTH_SHORT).show();
        }
    }

    private WebViewClient webViewClient = new WebViewClient() {

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            webView.loadUrl("javascript:window.GJNativeAPI.callAndroid('JS调用Android自定义的Native方法并在Native原生Activity提示')");
            webView.loadUrl("javascript:updateHref('更改href的默认内容')");
        }
    };
}

大家所看到的webview.loadUrl(javascipt:updateHref)",这些语法等可以到网上学习

点击打开链接 3W学校,很方便,资源很丰富!

每天都努力一点点吧,加油!




发布了60 篇原创文章 · 获赞 109 · 访问量 36万+

猜你喜欢

转载自blog.csdn.net/shenshibaoma/article/details/75389800