android 与js交互

年后请了几天假,今天第一天上班,这边博客本来应该年前写的,唉。。太懒了
先扯点没用的,总结下17年吧。
外包公司,项目倒是很多很杂,但总觉得论起细节、深度不够,但也学习到了很多的东西,而且庆幸的是和三个android同事一起进步、成长,成了很好的朋友。空闲时间写了一个安卓项目“AsYouLike”和一个小程序“我很随便的”,虽然不是特别难,但是自己一直以来的一个想法,总算实现了,还是有点骄傲的哈哈。自从我买了ipad之后,下班回去做好饭,就会打开虎牙看一起看栏目的士兵突击,一遍一遍,看不够似的,很多不经意的话,再重新听的时候,会有别样的感觉。想起几句,分享一下:我怕失落,怕丢失了始终怕不在乎。有容乃大,无欲则刚,容是别人,欲是自己。什么都要成功,搞不好就要失败。最初看的时候,里面会觉得里面的一句话“不抛弃,不放弃”,说的只是战友情,后来才明白,也是对自己追求理想的不抛弃不放弃。许三多跟成才说,人不能太舒服了,太舒服了会出问题,对于我们尤其适用。袁朗淘汰成才的时候,问成才,你的努力是为了什么,为了一个结果虚耗人生?虚耗人生?那怎样才算不虚耗人生呢?袁朗去部队看到独守营房的许三多时评价他不焦虑,这个时代应该很多人都会很焦虑吧,如此焦虑,如此功利。年底换到新的公司,是一家做自己产品的,今天刚刚知道,另一位同事要离职,我来这家公司其实是因为面试的时候觉得他比较牛才来的,但现在又不会太失落,总要承担一定的压力,总要靠自己啊,这不是什么坏事。
展望一下吧,18年希望自己能花更多的时间去学习,更有耐心,多跑步多锻炼身体,把两个项目优化一下,开发艺术探索看完,android提升的同时学习一下js和c。好了,先扯到这吧。

参考自:

说到Android与js交互,避免不了的就是WebView。
想要打开网页时不使用默认的浏览器打开,而是使用当前的WebView,做如下设置即可:

WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient(new WebViewClient());

如果当你点击链接的时候你想做更多的控制,则需要重写shouldOverrideUrlLoading方法。shouldOverrideUrlLoading返回true表示你已经处理此次请求。返回false表示有webview自行处理,一般都是把此url加载出来。post请求并不会回调这个函数。
比如有一个下面的需求:有一个web页面上一个链接,点击后我们不希望webview直接转到链接的页面,而是起一个我们自己写的activity,此时就需要让shouldOverrideUrlLoading返回true,如下:

private WebViewClient webViewClient = new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if (match(url)) {
                foo1();
                return  true;
            }
            return false;
        }
    };

常用的工具类:
**1.WebSettings类:**对WebView进行配置和管理
较常用的设置:

WebSettings webSettings = webView.getSettings();

//设置自适应屏幕,两者合用
webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小

//去掉缩放按钮
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
	webSettings.setBuiltInZoomControls(true);
	webSettings.setDisplayZoomControls(false);
} else {
	try {
            Class webview = Class.forName("android.webkit.WebView");
            Method method = webview.getMethod("getZoomButtonsController");
            ZoomButtonsController zoom_controll = (ZoomButtonsController) method.invoke(this, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
}

//设置缓存模式
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
//缓存模式如下:
//LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
//LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
//LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
//LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。

webSettings.setLoadsImagesAutomatically(true);//支持自动加载图片
webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式


**2.WebViewClient:**处理各种通知(开始加载/加载结束/加载失败等) & 请求事件
onPageStarted 开始加载 (显示加载进度条等)
onPageFinished 加载结束 (隐藏加载进度条等)
onReceivedError 加载失败(可在此处加载错误提示页面)
shouldOverrideUrlLoading (对要打开的链接做判断进而有不同的操作)
onReceivedSslError 任何HTTPS请求,遇到SSL错误时都会回调这个方法(在处理ssl错误时,遇到不信任的证书可以进行特殊处理,例如对域名进行判断,针对自己公司的域名“放行”,防止进入丑陋的错误证书页面。也可以与Chrome一样,弹出ssl证书疑问弹窗,给用户选择的余地。)
eg考拉做法:

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
    if (UrlUtils.isKaolaHost(getUrl())) {
        handler.proceed();
    } else {
        super.onReceivedSslError(view, handler, error);
    }
}

**3.WebChromeClient:**辅助 WebView 处理 Javascript 的对话框,加载进度,网站图标/标题等
onProgressChanged 加载进度
onReceivedTitle 网站标题
onJsAlert 当打开js弹窗时回调 返回true则消费掉此js弹窗,返回false则打开默认的提示框
onJsConfirm 当打开js确认框时回调
onJsPrompt 当打开js输入框时回调

android调用js代码

要调用的js代码如下:

<html>
<head>
    <meta charset="utf-8">
    <title>SilenceBurst</title>
    <script>
            function callJs(){
                alert("Android调用了js的callJs方法");
            }
    </script>
</head>
</html>
		final WebView webView = findViewById(R.id.web_view);
        WebSettings settings = webView.getSettings();
        //允许与js交互
        settings.setJavaScriptEnabled(true);
        //允许js弹窗
        settings.setJavaScriptCanOpenWindowsAutomatically(true);
        webView.loadUrl("file:///android_asset/call_js.html");

		//通过设置WebChromeClient来处理js的alert函数
        webView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
                AlertDialog alertDialog = new AlertDialog.Builder(CallJsActivity.this)
                        .setTitle("调用Js")
                        .setMessage(message)
                        .setPositiveButton("ok", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                result.confirm();
                            }
                        })
                        .create();
                alertDialog.setCanceledOnTouchOutside(false);
                alertDialog.show();
                return true;
            }
        });

1.loadUrl

//调用javascript的callJs方法
webView.loadUrl("javascript:callJs()");

2.evaluateJavascript

webView.evaluateJavascript("javascript:callJs()", new ValueCallback<String>() {
                    @Override
                    public void onReceiveValue(String value) {
                        //value为js返回的结果
                        Toast.makeText(CallJsActivity.this, value, Toast.LENGTH_LONG).show();
                    }
                });

总结: 使用WebView的evaluateJavascript方法调用js代码比loadUrl效率更高,易于获取返回值,更简洁(该方法执行不会使页面刷新,而loadUrl会),但evaluateJavascript方法Android4.4之后才可以使用
建议:

		// Android版本变量
        final int version = Build.VERSION.SDK_INT;
		// 因为该方法在 Android 4.4 版本才可使用,所以使用时需进行版本判断
        if (version < 18) {
            mWebView.loadUrl("javascript:callJS()");
        } else {
            mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
                @Override
                public void onReceiveValue(String value) {
                    //此处为 js 返回的结果
                }
            });
        }

js调用android代码

1.addJavascriptInterface
定义一个与JS对象映射关系的Android类:AndroidtoJs
多次调用addJavascriptInterface之后的会把之前的覆盖

//继承自Object
public class AndroidToJs extends Object {
    //被js调用的方法必须加入@JavascriptInterface注解
    @JavascriptInterface
    public void hello(String msg) {
        System.out.println(msg);
    }
}

调用

	//设置与js交互的权限
	settings.setJavaScriptEnabled(true);
	//将java对象映射到js对象
	webView.addJavascriptInterface(new AndroidToJs(), "test");
	webView.loadUrl("file:///android_asset/add_javascript_interface.html");

add_javascript_interface

<html>
<head>
    <meta charset="utf-8">
    <title>SilenceBurst</title>
    <script>
            function callAndroid(){
                test.hello("js调用了Android的hello方法");
            }
    </script>
</head>
<body>
<button type="button" onclick="callAndroid()">点我调android方法</button>
</body>
</html>

需要注意的是,此方法存在严重的安全漏洞 你不知道的 Android WebView 使用漏洞

2.通过shouldOverrideUrlLoading回调拦截url

//设置与js交互的权限
settings.setJavaScriptEnabled(true);
//允许js弹窗
settings.setJavaScriptCanOpenWindowsAutomatically(true);
webView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        Uri uri = Uri.parse(url);
        /*
         *根据协议的参数判断是否是需要的url
         * 一般通过scheme(协议格式)和authority(协议名)判断
         */
        if ("js".equals(uri.getScheme()) && "webview".equals(uri.getAuthority())) {
        //到此处根据即可做相关的操作,即js调用android完成,下面代码传返回值给js
            Set<String> parameters = uri.getQueryParameterNames();
            Iterator<String> iterator = parameters.iterator();
            HashMap<String, String> map = new HashMap<>();
            while (iterator.hasNext()) {
                String next = iterator.next();
                map.put(next, uri.getQueryParameter(next));
            }
            //hello方法做一个吐司提示js调用android成功
            String result = hello(map);
            //传递返回值给js 单引号要注意啊!!!
            webView.loadUrl("javascript:getResult('" + result + "')");
            return true;
        }
        return super.shouldOverrideUrlLoading(view, url);
    }
});
//通过设置WebChromeClient来处理js的alert函数
webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
        AlertDialog alertDialog = new AlertDialog.Builder(mContext)
                .setTitle("调用Js")
                .setMessage(message)
                .setPositiveButton("ok", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        result.confirm();
                    }
                })
                .create();
        alertDialog.setCanceledOnTouchOutside(false);
        alertDialog.show();
        return true;
    }
});
webView.loadUrl("file:///android_asset/should_override_url_loading.html");

should_override_url_loading

<html>
<head>
    <meta charset="utf-8">
    <title>SilenceBurst</title>
    <script>
            function callAndroid(){
                 /*约定的url协议为:js://webview?arg1=111&arg2=222*/
                 document.location = "js://webview?arg1=111&arg2=222";
            }

            function getResult(result){
                alert("result is"+result);
            }
    </script>
</head>
<body>
<button type="button" onclick="callAndroid()">点我调android方法</button>
</body>
</html>

3.通过 WebChromeClient 的onJsAlert、onJsConfirm、onJsPrompt方法回调拦截JS对话框alert、confirm、prompt 消息
(类似shouldOverrideUrlLoading拦截)

//设置与js交互的权限
settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
        Uri uri = Uri.parse(message);
        if ("js".equals(uri.getScheme()) && "webview".equals(uri.getAuthority())) {
            //此处即为js调用android时,android代码里判断拦截掉js弹出的输入框,并传入值到js提示框
            //参数:代表消息框的返回值(输入值)
            result.confirm("js 调用android的方法成功了");
            return true;
        }
        return super.onJsPrompt(view, url, message, defaultValue, result);
    }
});
webView.loadUrl("file:///android_asset/on_js_prompt.html");

on_js_prompt

<html>
<head>
    <meta charset="utf-8">
    <title>SilenceBurst</title>
    <script>
            function clickPrompt(){
                var result = prompt("js://webview?arg1=111&arg2=222");
                alert("webview"+result);
            }
    </script>
</head>
<body>
<button type="button" onclick="clickPrompt()">点我调android方法</button>
</body>
</html>

最后,请接受我双手奉上的demo地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值