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. myeclipse/eclipse安装反编译插件jadclipse

    jad是一个使用比较广泛的Java反编译软件,jadClipse是jad在eclipse下的插件,下面像大家介绍下如何将jadclipse加入到myeclipse/eclipse中. 文件下载 (1) ...

  2. Spring Boot学习——单元测试

    本随笔记录使用Spring Boot进行单元测试,主要是Service和API(Controller)进行单元测试. 一.Service单元测试 选择要测试的service类的方法,使用idea自动创 ...

  3. Maven整合Spring与Solr

    首先,在maven的pom.xml文件中配置对spring和solrj客户端的依赖: <project xmlns="http://maven.apache.org/POM/4.0.0 ...

  4. hashCode()与equals()区别

    这两个方法均是超类Object自带的成员方法.Object类是所有Java类的祖先.每个类都使用 Object 作为超类.所有对象(包括数组)都实现这个类的方法.在不明确给出超类的情况下,Java会自 ...

  5. StringBuilder基本用法

    //StringBuilder用法 public class StringBuilderTest { public static void main(String[] args) { StringBu ...

  6. CSU 1356 Catch

    原题链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1356 题目需要我们判断给定图在某一步是否会有可能出现在所有节点.首先,我们不妨假设给定图 ...

  7. 秀尔算法:破解RSA加密的“不灭神话” --zz

    http://netsecurity.51cto.com/art/201508/488766.htm RSA加密曾被视为最可靠的加密算法,直到秀尔算法出现,打破了RSA的不灭神话. RSA加密 VS ...

  8. 面试题32:从1到n整数中1出现的次数

    这是一道广为流传的google面试题.用最直观的方法求解并不是很难,但遗憾的是效率不是很高:而要得出一个效率较高的算法,需要比较强的分析能力,并不是件很容易的事情.当然,google的面试题中简单的也 ...

  9. Wannafly挑战赛18 C - 异或和

    思路:我刚开始是想旋转四次坐标,每次用bit计算每个点左上角的点到这个点的距离,TLE了.... 这种算曼哈顿距离的可以将x 轴和 y 轴独立开来,分别计算. #include<bits/std ...

  10. vars 变量预解析

    JavaScript中,你可以在函数的任何位置声明多个var语句,并且它们就好像是在函数顶部声明一样发挥作用,这种行为称为 hoisting(悬置/置顶解析/预解析).当你使用了一个变量,然后不久在函 ...