Android开发Android技术知识

Android WebView和JavaScript交互

2017-05-28  本文已影响0人  贼厉害

现在移动应用几乎都是 Hybrid App(混合模式移动应用)是指介于web-app、native-app这两者之间的app,兼具“Native App良好用户交互体验的优势”和“Web App跨平台开发的优势”。
而hybrid的实现关键在于打通Java和JavaScript之间的交互。
在Android开发中我们是使用WebView控件来加载HTML页面的,WebView默认为我们提供了让Java和HTML页面中JavaScript脚本交互的能力。

1 Java调用JavaScript

java调用JavaScript非常简单,只需要执行下面代码即可。

mWebView.loadUrl("javascript:methodName(parameterValues)");

不过其中还需要注意几个细节,我们先来看个例子,然后再介绍需要注意的地方。

IDE:Android Studio

先写一个H5的页面test.html,把它放在了assets资源文件下

<!DOCTYPE HTML>

<head>
    <title>java调用JavaScript</title>
</head>
<!--提供给java调用的方法-->
<script type="text/javascript"/>
    function alertMessage(message) {
        alert(message)
    }
</script>

</HTML>

xml布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/id_linearlayout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/id_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="alertMessage"/>

    <WebView
        android:id="@+id/id_webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></WebView>
</LinearLayout>

Activity代码:

public class MyWebView extends AppCompatActivity {
    private WebView mWebView;
    private Button mButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_web_view);
        mWebView = (WebView) findViewById(R.id.id_webview);
        mButton = (Button) findViewById(R.id.id_button);
        loadURL();
    }

    private void loadURL() {
        mWebView.setWebViewClient(new WebViewClient());//此方法可以在webview中打开链接而不会跳转到外部浏览器
        mWebView.setWebChromeClient(new WebChromeClient());//各种内容的渲染需要使用webviewChromClient去实现,比如alert()方法
        mWebView.loadUrl("file:///android_asset/test.html");
    }

    private void initEvents() {
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mWebView.loadUrl("javascript:alertMessage(\""+"Message"+"\")");//注意转义字符
            }
        });
    }

    //重写onKeyDown,当浏览网页,WebView可以后退时执行后退操作。
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
            mWebView.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}

需要注意的是setWebViewClient(new WebViewClient())和setWebChromeClient(new WebChromeClient())方法。

01.jpg

点击按钮之后效果

02.jpg

2 JavaScript调用Java

WebView提供了一个名为WebSettings的工具类实现让Webview中的JavaScript脚本调用android应用的Java方法,实现方式很简单。

增加H5页面代码

<!DOCTYPE HTML>

<head>
    <title>h5</title>
</head>
<!--调用java方法-->
<body>
    <input type="button" value=" 打印Log" onclick=" javaObject.printLog('printLog');">
    <input type="button" value=" 显示Toast" onclick=" javaObject.showToast();">
</body>

<!--提供给java调用的方法-->
<script type="text/javascript"/>
    function alertMessage(message) {
        alert(message)
    }
</script>

</HTML>

我们新建提供给JavaScript调用的Java类javaObject

public class javaObject {
    private Context context;
    private final String TAG = "javaObjectLog";

    public javaObject(Context context) {
        this.context = context;
    }
    
    public void printLog(String mes){
        Log.i(TAG, mes);
    }

    
    public void showToast(){
        Toast.makeText(context, "Toast", Toast.LENGTH_SHORT).show();
    }
}

增加Activity代码

public class MyWebView extends AppCompatActivity {
    private WebView mWebView;
    private Button mButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_web_view);
        mWebView = (WebView) findViewById(R.id.id_webview);
        mButton = (Button) findViewById(R.id.id_button);
        loadURL();
        initEvents();
    }

    private void initEvents() {
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mWebView.loadUrl("javascript:alertMessage(\""+"Message"+"\")");
            }
        });
    }

    private void loadURL() {
        mWebView.setWebViewClient(new WebViewClient());//此方法可以在webview中打开链接而不会跳转到外部浏览器
        mWebView.setWebChromeClient(new WebChromeClient());//各种内容的渲染需要使用webviewChromClient去实现,比如alert()方法
        WebSettings webSettings = mWebView.getSettings();//
        webSettings.setJavaScriptEnabled(true);//
        mWebView.loadUrl("file:///android_asset/test.html");

        mWebView.addJavascriptInterface(new javaObject(this), "javaObject");//把javaObject类对象暴露给JavaScript
    }


    //重写onKeyDown,当浏览网页,WebView可以后退时执行后退操作。
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
            mWebView.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}

03.jpg

这种方法是官方提供的,但是却存在极大地安全隐患,所以从Android 4.2开始,Google就修复了这个漏洞,所以如果你测试机是4.2以上你会发现并没有成功调用暴露的方法。我们想要安全的使用上面的方法,唯一需要改动的就是对暴露给JavaScript调用的方法添加@JavascriptInterface注解。修改如下:

public class javaObject {
    private Context context;
    private final String TAG = "javaObjectLog";

    public javaObject(Context context) {
        this.context = context;
    }
    @JavascriptInterface
    public void printLog(String mes){
        Log.i(TAG, mes);
    }

    @JavascriptInterface
    public void showToast(){
        Toast.makeText(context, "Toast", Toast.LENGTH_SHORT).show();
    }
}

输出结果

04.jpg 05.png
上一篇下一篇

猜你喜欢

热点阅读