Android 与 WebView 数据交互

简介:

1. 创建Android 项目

    1. 打开Android Studio

-w450

    1. 创建一个空的Android项目

-w450

    1. 打开Android虚拟机,这里使用的是Genymotion

15268784107324.jpg

2. 添加webview

    1. 清空layout内容,添加WebView控件
<WebView
        android:id="@+id/web"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    1. MainActivity中创建引入webview
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    WebView mweb = findViewById(R.id.web);
    mweb.loadUrl("http://www.baidu.com");
}
    1. 此时运行项目,发现android安装成功,webview也可以打开,但是页面请求失败,需要给APP添加联网权限。
      AndroidManifest.xmlmanifest标签内添加
<uses-permission android:name="android.permission.INTERNET"/>
    1. 此时运行项目,发现webview可以打开并且百度页面可以访问了,但是仔细发现webview并不是在自己的APP上打开的,而是弹出系统浏览器。因为webview只是载体,内容的渲染需要使用webviewChromClient类去实现此时需要setWebViewClient
...
WebView mweb = findViewById(R.id.web);
mweb.setWebViewClient(new WebViewClient());
mweb.loadUrl("http://www.baidu.com");
...
    1. 运行APP后可以看到webview已经差不多是我们想要的了

15268792310451.jpg

3. 设置JavaScript可执行

仔细看会发现,通过上面步骤打开的百度首页跟我们平时看到的广告页面不一样,原因是WebView默认禁止了JS的执行。这也是我觉得百度首页做的比较好的地方,在无JS环境下仍可提供服务。

  • 添加setJavaScriptEnabled
...
mweb.setWebViewClient(new WebViewClient());
mweb.getSettings().setJavaScriptEnabled(true);
mweb.loadUrl("http://www.baidu.com");
...

此时再打开页面,就会发现广告出来了,并且页面很卡。

15268796309520.jpg

4. WebView 调用 Android 方法

1. 使用addJavascriptInterface

    1. 添加JS接口
      创建JavaScriptInterFace.java类,用来写JS调用方法
package com.test.myapplication;

import android.util.Log;
import android.webkit.JavascriptInterface;

public class JavaScriptInterFace {

    @JavascriptInterface
    public String getValue(String name) {
        Log.d("tagee", "getValue:" + name);
        return "call back";
    }
}

因为安全问题,在Android4.2中JS只能访问带有 @JavascriptInterface注解的Java函数。

    1. addJavascriptInterface注入
...
mweb.setWebViewClient(new WebViewClient());
mweb.getSettings().setJavaScriptEnabled(true);
mweb.addJavascriptInterface(new JavaScriptInterFace(), "JSBridge"); 
// JSBridge 为 webview 中调用的对象名称
mweb.loadUrl("http://www.baidu.com");
...
    1. 加载本地 html 文件

app/src/main目录下面创建目录assets并新建a.html文件,写入如下代码

<!doctype html>
<html lang="en">
    <head></head>
    <body>
        <h1 id="h1">123</h1>
        <script>
            if(window.JSBridge){
                alert(JSBridge.getValue('from JS'));
            }
        </script>
    </body>
</html>

修改webview的loadUrl参数

mweb.addJavascriptInterface(new JavaScriptInterFace(), "JSBridge"); 
mweb.loadUrl("file:///android_asset/a.html");

此时重新build,可以看到Logcat打印出from JS,并且页面弹窗。

2.通过loadUrl()

loadUrl可以执行JavaScript代码,他有如下特征:

1. 调用`loadUrl`会刷新页面
2. 当参数为要执行的JS代码时,要有document对象,至少得load一个空白页,否则会失效
3. 若返回值为非空字符串,则会将返回值替换页面原本的内容
4. 可以调用html中的js代码,但需要在`onPageFinished`回调之后才能调用,并且注意第三点的影响,防止返回字符串替换文档

如:

...
mweb.addJavascriptInterface(new JavaScriptInterFace(), "JSBridge"); 
mweb.loadUrl("javascript:aler(123)"); //因当前webview没用加载任何页面,脚本无效
...
mweb.addJavascriptInterface(new JavaScriptInterFace(), "JSBridge"); 
mweb.loadUrl("file:///android_asset/a.html");
mweb.loadUrl("javascript:'123'"); //此时页面被替换成123
protected void onCreate(Bundle savedInstanceState) {
    ...
    mweb.addJavascriptInterface(new JavaScriptInterFace(), "JSBridge"); 
    mweb.setWebViewClient(new mWebViewClient());
    mweb.loadUrl("file:///android_asset/a.html");
}
...
private class mWebViewClient extends WebViewClient{
    @Override
    public void onPageFinished(WebView view, String url) {
        view.loadUrl("javascript:callJS()");//callJS为a.html中定义的方法
        super.onPageFinished(view, url);
    }
} 

实际使用时,Android更多的是调用远程JS代码,即将加载的JS代码路径改成url即可。或则直接拼接JS代码时也会放在闭包中执行,防止替换页面内容。

3. 通过evaluateJavascript()

如果是Android4.4后,推荐使用evaluateJavascript,比loadUrl效率更高,并且不会刷新页面。
evaluateJavascript有两个参数,第一个为脚本内容,第二个则是脚本的执行结果。在onPageFinished调用:

view.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String value) {
        Log.d("tagee", value);
    }
});

4. 通过shouldOverrideUrlLoading()

shouldOverrideUrlLoadingWebViewClient对象的一个"生命周期",用拦截URL的请求,监听网页地址的变化,返回turefalse来决定webview是否加载URL。

1. 若没有设置 WebViewClient 则由系统(Activity Manager)处理该 url,通常是使用浏览器打开或弹出浏览器选择对话框,即出现上文2.4的情况。
2. 若设置 WebViewClient 且该方法返回 true ,则说明由应用的代码处理该 url,WebView不跳转。 
3. 若设置 WebViewClient 且该方法返回 false,则说明由 WebView 处理该 url,即用 WebView 加载该 url。 
private class mWebViewClient extends WebViewClient{
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
     
        //此处可以解析url进行处理,
        //也可以直接调用view.loadUrl(url); 在当前的webview中跳转到新的url
        //若前端直接location.href="js://web?param1=123&param2=asd"
        Uri uri = Uri.parse(url);
        if ( uri.getScheme().equals("js")) {
            //可以在此处获取页面请求数据并处理
            //或则直接跳转activity等
            return true;
        }
        return false;
    }
} 

值得一提的是以前一直有一个误区,以为使用一个不可见的iframe标签,再动态改变其src也可以捕捉url变化达到传值的目的。测试过不可行,包括默认写入和动态创建iframe

4. 通过onJsAlert()、onJsConfirm()、onJsPrompt()

原理和上面一条一样,通过监听页面的弹窗事件,达到传值的目的,不细说了。

目录
相关文章
|
7月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
732 4
|
17天前
|
缓存 JavaScript 前端开发
Android WebView常见问题
本文主要介绍了在Android开发中WebView的使用方法,包括加载网址、设置相关属性(如JavaScript支持、缓存模式、屏幕适配等)、监听网页加载过程以及返回上一页面的功能实现。同时针对Android P版本限制明文流量的问题(ERR_CLEARTEXT_NOT_PERMITTED),提供了在`AndroidManifest.xml`中添加`android:usesCleartextTraffic=&quot;true&quot;`的解决办法。文章还附有完整代码示例,帮助开发者快速上手并解决常见问题。希望对您的开发工作有所帮助!
|
18天前
|
存储 XML Java
Android 文件数据储存之内部储存 + 外部储存
简介:本文详细介绍了Android内部存储与外部存储的使用方法及核心原理。内部存储位于手机内存中,默认私有,适合存储SharedPreferences、SQLite数据库等重要数据,应用卸载后数据会被清除。外部存储包括公共文件和私有文件,支持SD卡或内部不可移除存储,需申请权限访问。文章通过代码示例展示了如何保存、读取、追加、删除文件以及将图片保存到系统相册的操作,帮助开发者理解存储机制并实现相关功能。
254 2
|
3月前
|
XML JavaScript Android开发
【Android】网络技术知识总结之WebView,HttpURLConnection,OKHttp,XML的pull解析方式
本文总结了Android中几种常用的网络技术,包括WebView、HttpURLConnection、OKHttp和XML的Pull解析方式。每种技术都有其独特的特点和适用场景。理解并熟练运用这些技术,可以帮助开发者构建高效、可靠的网络应用程序。通过示例代码和详细解释,本文为开发者提供了实用的参考和指导。
104 15
|
4月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
284 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
8月前
|
Java Linux Android开发
移动应用开发与操作系统的交互:深入理解Android和iOS
在数字时代,移动应用成为我们日常生活的一部分。本文将深入探讨移动应用开发的核心概念、移动操作系统的工作原理以及它们如何相互作用。我们将通过实际代码示例,展示如何在Android和iOS平台上创建一个简单的“Hello World”应用,并解释其背后的技术原理。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和知识。
|
10月前
|
开发工具 Android开发 开发者
Android平台如何不推RTMP|不发布RTSP流|不实时录像|不回传GB28181数据时实时快照?
本文介绍了一种在Android平台上实现实时截图快照的方法,尤其适用于无需依赖系统接口的情况,如在RTMP推送、RTSP服务或GB28181设备接入等场景下进行截图。通过底层模块(libSmartPublisher.so)实现了截图功能,封装了`SnapShotImpl.java`类来管理截图流程。此外,提供了关键代码片段展示初始化SDK实例、执行截图、以及在Activity销毁时释放资源的过程。此方案还考虑到了快照数据的灵活处理需求,符合GB/T28181-2022的技术规范。对于寻求更灵活快照机制的开发者来说,这是一个值得参考的设计思路。
180 1
|
8月前
|
程序员 开发工具 Android开发
Android|WebView 禁止长按,限制非白名单域名的跳转层级
如何限制 WebView 仅域名白名单网址能随意跳转,并禁用长按选择文字。
119 2
|
8月前
|
存储 大数据 数据库
Android经典面试题之Intent传递数据大小为什么限制是1M?
在 Android 中,使用 Intent 传递数据时存在约 1MB 的大小限制,这是由于 Binder 机制的事务缓冲区限制、Intent 的设计初衷以及内存消耗和性能问题所致。推荐使用文件存储、SharedPreferences、数据库存储或 ContentProvider 等方式传递大数据。
323 0
|
10月前
|
JSON Java Android开发
Android 开发者必备秘籍:轻松攻克 JSON 格式数据解析难题,让你的应用更出色!
【8月更文挑战第18天】在Android开发中,解析JSON数据至关重要。JSON以其简洁和易读成为首选的数据交换格式。开发者可通过多种途径解析JSON,如使用内置的`JSONObject`和`JSONArray`类直接操作数据,或借助Google提供的Gson库将JSON自动映射为Java对象。无论哪种方法,正确解析JSON都是实现高效应用的关键,能帮助开发者处理网络请求返回的数据,并将其展示给用户,从而提升应用的功能性和用户体验。
204 1