1. 交互方式总结

1Android与JS通过WebView互相调用方法,实际上是:

  • Android去调用JS的代码
  • JS去调用Android的代码
    二者沟通的桥梁是WebView

    对于Android调用JS代码的方法有2种: 
    1. 通过WebViewloadUrl() 
    2. 通过WebViewevaluateJavascript()

    对于JS调用Android代码的方法有3种: 
    1. 通过WebViewaddJavascriptInterface()进行对象映射 
    2. 通过 WebViewClient 的shouldOverrideUrlLoading ()方法回调拦截 url 
    3. 通过 WebChromeClient 的onJsAlert()onJsConfirm()onJsPrompt()方法回调拦截JS对话框alert()confirm()prompt() 消息

  • 2.1 Android通过WebView调用 JS 代码

  • mWebView =(WebView) findViewById(R.id.webview);
    mWebView.loadUrl("file:///android_asset/javascript.html");
    LocationActivity.this.webView.post(() -> LocationActivity.this.webView.evaluateJavascript(
    "javascript:locationDidChange('" + LocationActivity.this.locationString + "')", value -> {
    // 此处为 js 返回的结果
    }));

    2.2 JS通过WebView调用 Android 代码

  • 方式2:通过 WebViewClient 的方法shouldOverrideUrlLoading ()回调拦截 url

  • <!DOCTYPE html>
    <html> <head>
    <meta charset="utf-8">
    <title>Carson_Ho</title> <script>
    function callAndroid(){
    /*约定的url协议为:js://webview?arg1=111&arg2=222*/
    document.location = "js://webview?arg1=111&arg2=222";
    }
    </script>
    </head> <!-- 点击按钮则调用callAndroid()方法 -->
    <body>
    <button type="button" id="button1" onclick="callAndroid()">点击调用Android代码</button>
    </body>
    </html>
    private class MyWebViewClient extends WebViewClient {
    
            @TargetApi()
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    return this.shouldOverrideUrlLoading(view, request.getUrl().toString());
    } @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
    // 步骤2:根据协议的参数,判断是否是所需要的url
    // 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)
    // 假定传入进来的 url = "js://webview?arg1=111&arg2=222"(同时也是约定好的需要拦截的)
    Uri uri = Uri.parse(url);
    // 如果url的协议 = 预先约定的 js 协议
    // 就解析往下解析参数
    if (uri.getScheme().equals("js")) {
    // 如果 authority = 预先约定协议里的 webview,即代表都符合约定的协议
    // 所以拦截url,下面JS开始调用Android需要的方法
    if (uri.getAuthority().equals("webview")) {
    Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + uri.getQueryParameter("tel")));
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    LocationActivity.this.startActivity(intent);
    } else if (uri.getAuthority().equals("location")) { LocationActivity.this.webView.post(() -> LocationActivity.this.webView.evaluateJavascript(
    "javascript:locationDidChange('" + LocationActivity.this.locationString + "')", value -> {
    // 此处为 js 返回的结果
    })); } else if (uri.getAuthority().equals("toast")) { Toast.makeText(LocationActivity.this, uri.getQueryParameter("info"), Toast.LENGTH_SHORT).show();
    } else if (uri.getAuthority().equals("takePhoto")) { photoIdent = uri.getQueryParameter("ident");
    openPopupWindow();
    } else if (uri.getAuthority().equals("takeVideo")) {
    /***************************** 录制视频 ***********************************/
    EventBus.getDefault().post(new VideoIdentEvent(uri.getQueryParameter("ident")));
    Intent intent = new Intent(LocationActivity.this, VideoActivity.class);
    intent.putExtra(VideoActivity.VIDEO_IDENT, uri.getQueryParameter("ident"));
    startActivity(intent);
    } else if (uri.getAuthority().equals("playVideo")) {
    /***************************** 播放视频 ***********************************/
    startActivity(new Intent(LocationActivity.this, VideoPlayerActivity.class).putExtra("path",
    uri.getQueryParameter("path")));
    } else if (uri.getAuthority().equals("takeAudio")) {
    /******************************** 录制音频 ********************************/
    dialogShow(uri.getQueryParameter("ident"));
    } else if (org.apache.commons.lang3.StringUtils.equals(uri.getAuthority(), "userLogin")) {
    /******************************** 登录 ********************************/
    String username = uri.getQueryParameter("username");
    if (TextUtils.isEmpty(username)) {
    return true;
    } JPushInterface.setAlias(LocationActivity.this, username.hashCode(), username); String account = uri.getQueryParameter("yx_username");
    String password = uri.getQueryParameter("yx_password"); chatFragment.startImLogin(username, account, password);
    } else if (org.apache.commons.lang3.StringUtils.equals(uri.getAuthority(), "userLogout")) {
    /******************************** 退出 ********************************/
    chatFragment.logout(); finish();
    } else if (org.apache.commons.lang3.StringUtils.equals(uri.getAuthority(), "playAudio")) {
    /***************************** 播放视频 ***********************************/
    MediaActivity.start(LocationActivity.this, uri.getQueryParameter("path"));
    } return true;
    } return false;
    }

    这种方式的优点就是不存在漏洞,并且稳定

原生+H5开发之:js交互【location方式】的更多相关文章

  1. 原生+H5开发之:Android webview配置

    在上一篇文章Android 原生开发.H5.React-Native开发特点,我们可以了解到三种Android开发方式的区别和优缺点.[Android开发:原生+H5]系列的文章,将主要讲解Andro ...

  2. Android 与H5之间的js交互

    之前项目做过一些Android和Html5之间js交互方面的东西,今天有时间就总结一下: 一.为什么要进行js交互: 为了方便原生开发和Html之间数据传递,在静态页面的情况下可以改变原生开发的页面: ...

  3. 鸿蒙系统应用开发之JS实现一个简单的List

    在之前的文章鸿蒙应用开发之怎么更好的远程连接手表模拟器做调试里我运行了一个穿戴设备的应用,利用JS UI实现了一个最简单的HelloWorld. 今天我打算在智慧屏设备上利用豆瓣音乐的接口数据实现一个 ...

  4. android webView开发之js调用java代码示例

    1.webView设置 webView.getSettings().setJavaScriptEnabled(true);//设置支持js webView.addJavascriptInterface ...

  5. H5开发之Eclipes 编码乱码问题

    1.编码不对 a.对某文件或某工程更改编码: 鼠标移到工程名或文件名,右键->Properties->Resource->Text file enCoding ->更改编码(G ...

  6. Android开发之UI的编程方式创建

    我们知道,android中一个activity对应一个xml的UI配置文件,除了用xml文件配置的方式创建用户界面外,还可以使用代码编程的方式来创建一个用户界面.如果用户界面需要在运行过程中动态生成的 ...

  7. (一〇七)iPad开发之modal的切换方式与展示方式

    在iPad上modal有四种切换方式,分别是竖直进入(由下到上,默认方式).水平翻转.淡入淡出. 属性要设置在将要modal出来的控制器上: /* typedef NS_ENUM(NSInteger, ...

  8. 微信小游戏开发之JS面向对象

    //游戏开发之面向对象 //在js的开发模式中有两种模式:函数式+面向对象 //1.es5 // 拓展一:函数的申明和表达式之间的区别 // 函数的申明: // function funA(){ // ...

  9. Android开发之5大布局方式详解

    Android中常用的5大布局方式有以下几种: 线性布局(LinearLayout):按照垂直或者水平方向布局的组件. 帧布局(FrameLayout):组件从屏幕左上方布局组件. 表格布局(Tabl ...

随机推荐

  1. 62.Unique Paths---dp

    题目链接 题目大意:给一个m*n的方格,从左上角走到右下角,中间无任何障碍,问有多少种走法. 法一:DFS,超时,简单模板深搜,无任何剪枝,结果一半的数据超时.代码如下: public int uni ...

  2. weblogic12.1.3 静默安装 建域

    --安装依赖包 yum -y install compat-libcap1 compat-libstdc++ gcc gcc-c++ glibc-devel libaio-devel libstdc+ ...

  3. puppet practice

    目标 试验环境有两台主机(VM)构成,一台是master,一台是agent,完成以下工作: 新建用户newuser; 安装 ubuntu-cloud-keyring package,更改文件/etc/ ...

  4. 禁用quartz自动检查更新

    禁用quartz自动检查更新的3种方法 1, <bean id="startQuertz" lazy-init="false" autowire=&quo ...

  5. Qt跨线程调用错误解析及解决办法

    错误提示:Error: Cannot create children for a parent that is in a different thread. 错误案例分析 新建SerialLink子线 ...

  6. scikit-learn模块学习笔记(数据预处理模块preprocessing)

    本篇文章主要简单介绍sklearn中的数据预处理preprocessing模块,它可以对数据进行标准化.preprocessing 模块提供了数据预处理函数和预处理类,预处理类主要是为了方便添加到pi ...

  7. 让R与Python共舞

    转载:http://ices01.sinaapp.com/?p=129      R(又称R语言)是一款开源的跨平台的数值统计和数值图形化展现 工具.通俗点说,R是用来做统计和画图的.R拥有自己的脚本 ...

  8. mac 安装mongodb与常用操作

    1.安装 brew update brew install mongodb 2.启动mongo mongod --config /usr/local/etc/mongod.conf 3.启动 mong ...

  9. Effective STL 阅读笔记: Item 3: Make copying cheap and correct for objects in containers

    容器 (Containers) 用来存储对象 (Objects), 但是被存储的对象却并非原原本本是你给他的那一个, 而是你指定对象的一个拷贝.而后续对该容器内存储对象的操作,大多也是基于拷贝的. 拷 ...

  10. 【前端笔记】浅谈js继承

    我们先想想我们用js最后要怎样实现面向对象的编程.事实上我们必须用上原型链这种东西. 我们的父类superType有属性和方法,并且一些能被子类subType继承,一些能被覆盖,但是丝毫不会影响到父类 ...