Android与js交互

Android与js交互讲解

一、Android中调JS无参方法

实现Android调用JS脚本是非常简单的,直接Webview调用loadUrl方法,里面是JS的方法名,并可以传入参数,javascript:xxx()方法名需要和JS方法名相同
webview.loadUrl("javascript:javacalljs()");
"javascript:javacalljs()"中,"javascript:"是固定的前缀,表明调用html中的JavaScript脚本方法,如果以http或者https开头等就表示加载一个网页了。javacalljs是JavaScript中的方法名,这里调用的是无参方法,保证调用的方法名称和JavaScript中保持一致即可。

二、Android中调用JS方法并传递参数

与调用无参方法类似:
String par = "这是参数";
// 传递参数调用JS的方法
webview.loadUrl("javascript:javacalljswith('" + par + "')");
注意:这里的传递了一个字符串到html中,其中单引号中的表示字符串变量,不能省略单引号。无论传递变量还是常量都参数都需要用单引号包裹,否则会报错Uncaught ReferenceError: 这是参数 is not defined

三、JS中调用Android中的无/有参方法

webview.addJavascriptInterface(MainActivity.this,"android");
实现JS调用Android方法,需要在Java代码中用webview绑定javascriptInterface,js脚本通过这个接口来调用java代码, 第一个参数是自定义类对象,映射成JS对象,这里我直接传this,表示JS调用的java方法直接写在this下边,也可以自己定义一个类,将JS调用的java方法写在自定义的类中,第二个参数是别名,JS脚本通过这个别名来调用java的方法,这个别名跟HTML代码中也是对应的。
html中的代码:
<pre name="code" class="html"><html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=gb2312">
        <script type="text/javascript">
            function javacalljs(){
                 document.getElementById("content").innerHTML = "<br>JAVA调用了JS的无参函数";
            }
            function javacalljswith(arg){
                 document.getElementById("content").innerHTML = ("<br>"+arg);
            }
        </script>
    </head>
    <body>
      HTML 内容显示 <br/>
    <h1>
        <div id="content">内容显示</div>
    </h1>
    <br/>
        <input type="button" value="点击调用java代码" onclick="window.android.startFunction()"/><br/>
        <input type="button" value="点击调用java代码并传递参数" onclick="window.android.startFunction('js调用了java有参方法')"/>
        <input type="button" value="点击调用java代码方案二" onclick="window.demo.method()"/><br/>
        <input type="button" value="点击调用java代码并传递参数方案二" onclick="window.demo.method('js调用了java有参方法method')"/>
    </body>
</html>



Activity中的代码:
<pre name="code" class="java"><pre name="code" class="java">package cngfms.a10086.httpwx.webviewdemo;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private WebView webview;

    @SuppressLint("JavascriptInterface")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webview = (WebView) findViewById(R.id.webview);        // 启用javascript
        webview.getSettings().setJavaScriptEnabled(true);        // 从assets目录下面的加载html
        //方案一
        webview.addJavascriptInterface(MainActivity.this, "android");
        //方案二
        webview.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");
        webview.loadUrl("file:///android_asset/web.html");
        //Button按钮 无参调用HTML js方法
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {                // 无参数调用 JS的方法
                webview.loadUrl("javascript:javacalljs()");

            }
        });

        //Button按钮 有参调用HTML js方法
        findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String par = "这是参数";
                // 传递参数调用JS的方法
                webview.loadUrl("javascript:javacalljswith('" + par + "')");
            }
        });
    }

    //由于安全原因 targetSdkVersion>=17需要加 @JavascriptInterface
    //JS调用Android JAVA方法名和HTML中的按钮 onclick后的别名后面的名字对应
    @JavascriptInterface
    public void startFunction() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, "js调用了java无参方法", Toast.LENGTH_LONG).show();

            }
        });
    }

    @JavascriptInterface
    public void startFunction(final String text) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, text, Toast.LENGTH_LONG).show();
            }
        });
    }


    final class DemoJavaScriptInterface {
        DemoJavaScriptInterface(){}
        /**
         * 注意:targetSdkVersion>=17被调用的方法上必须加上@JavascriptInterface
         * 否则无法正常调用会提示找不到该方法
         */
        @JavascriptInterface
        public void method() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, "js调用了java无参方法method", Toast.LENGTH_LONG).show();
                }
            });
        }
        @JavascriptInterface
        public void method(final String text) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, text, Toast.LENGTH_LONG).show();
                }
            });
        }
    }
}


注意:方法名和别名在Android和html中必须保持一致。同时targetSdkVersion>=17被调用的方法上必须加上@JavascriptInterface否则无法正常调用会提示找不到该方法

四、webview使用的注意

1.多线程

如果你在子线程中调用WebView的相关方法,而不在UI线程,则可能会出现无法预料的错误。 所以,当你的程序中需要用到多线程时候,也请使用 runOnUiThread()方法来保证你关于WebView的操作是在UI线程中进行的:
runOnUiThread(newRunnable(){
    @Override
    publicvoid run(){
       // Code for WebView goes here
    }
});

2.线程阻塞

永远不要阻塞UI线程,这是开发Android程序的一个真理。虽然是真理,我们却往往不自觉的犯一些错误违背它,一个开发中常犯的错误就是:在UI线程中去等待JavaScript 的回调。
例如:
// This code is BAD and will block the UI thread
webView.loadUrl("javascript:fn()"); while(result ==null){ 
Thread.sleep(100); }
千万不要这样做,Android 4.4中,提供了新的Api来做这件事情。evaluateJavascript() 就是专门来异步执行JavaScript代码的。

3.evaluateJavascript() 方法

专门用于异步调用JavaScript方法,并且能够得到一个回调结果。 示例: mWebView.evaluateJavascript(script, new ValueCallback<String>() {      @Override      public void onReceiveValue(String value) {           //TODO      } });

4.处理 WebView 中 url 跳转

新版WebView对于自定义scheme的url跳转,新增了更为严格的限制条件。当你实现了 shouldOverrideUrlLoading() 或 shouldInterceptRequest() 回调,WebView 也只会在跳转url是合法Url时才会跳转。 例如,如果你使用这样一个url : <ahref="showProfile"]]>Show Profile</a> 正确的使用方式是: <ahref="example-app:showProfile"]]>Show Profile</a> 对应的检测Url跳转的方式: // The URL scheme should be non-hierarchical (no trailing slashes) privatestaticfinalString APP_SCHEME ="example-app:"; @Override publicboolean shouldOverrideUrlLoading(WebView view,String url){     if(url.startsWith(APP_SCHEME)){         urlData =URLDecoder.decode(url.substring(APP_SCHEME.length()),"UTF-8");         respondToData(urlData);         returntrue;     }     returnfalse; } 当然,也可以这样使用: webView.loadDataWithBaseURL("example-app://example.co.uk/", HTML_DATA,  null,"UTF-8",null);

5.UserAgent 变化

如果你的App对应的服务端程序,会根据客户端传来的UserAgent来做不同的事情,那么你需要注意的是,新版本的WebView中,UserAgent有了些微妙的改变: Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16H) AppleWebKit/537.36(KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36 使用 getDefaultUserAgent()方法可以获取默认的UserAgent,也可以通过: mWebView.getSettings().setUserAgentString(ua); mWebView.getSettings().getUserAgentString(); 来设置和获取自定义的UserAgent。

6.使用addJavascriptInterface()的注意事项

从Android4.2开始。只有添加  @JavascriptInterface 声明的Java方法才可以被JavaScript调用,例如: class JsObject {     @JavascriptInterface     public String toString() { return "injectedObject"; }  }  webView.addJavascriptInterface(new JsObject(), "injectedObject");  webView.loadData("", "text/html", null);  webView.loadUrl("javascript:alert(injectedObject.toString())");

7.Remote Debugging

新版的WebView还提供了一个很厉害的功能:使用Chrome来调试你运行在WebView中的程序。

            
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/OONullPointerAlex/article/details/52373416
上一篇Activity动画
下一篇Unable to start the virtual device.VirtualBox cannot start the virtual device
想对作者说点什么? 我来说一句

AndroidJS交互 DEMO

2016年03月15日 6.13MB 下载

android webview开发与js交互

2015年07月30日 2.06MB 下载

android webview与js交互简单demo

2016年08月10日 1.24MB 下载

android不使用webview与js交互

2016年10月27日 17.51MB 下载

Js交互文件

2016年12月02日 8KB 下载

没有更多推荐了,返回首页

关闭
关闭