Android WebView专题

WebView 专题

第一个WebView程序:加载远程网址

  1. Layout添加WebView组件;

    <WebViewandroid:id="@+id/webView_first"android:layout_width="match_parent"android:layout_height="match_parent"/>
    
  2. 初始化组件,加载Url;

    public class FirstWebViewActivity extends AppCompatActivity{private WebView webView_first;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_first_web_view);webView_first=findViewById(R.id.webView_first);webView_first.loadUrl("https://www.baidu.com/");}@Overrideprotected void onDestroy() {super.onDestroy();webView_first.removeAllViews();webView_first.destroy();}
    }
    
  3. Manifest文件添加网络访问权限

    <uses-permission android:name="android.permission.INTERNET" />
    
  4. 出现错误:

    NetworkSecurityConfig   com.hymy.webviewstarter              D  No Network Security Config specified, using platform default
    Denied starting an intent without a user gesture, URI
    

    解决方法:

    res/xml下添加 network_security_config.xml 文件:

    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config> //默认配置:允许明文通信<base-config cleartextTrafficPermitted="true" />
    </network-security-config>
    

    在AndroidManifest.xml中引用

    <applicationandroid:networkSecurityConfig="@xml/network_security_config"...
    
  5. 出现错误:

    访问bing.com无法加载封面图片:

    The resource xxx was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally.
    

    解决方法:

    webView_first=findViewById(R.id.webView_first);
    //启用JavaScript
    WebSettings webSettings = webView_first.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webView_first.loadUrl("https://cn.bing.com/?mkt=zh-CN");
    
  6. 下载:在bing搜索网站首页,好看的壁纸,点击可以下载图片,将图片下载到 SD 卡下的Downloader目录下

    参考:https://cloud.tencent.com/developer/article/1742327

  7. 将 JavaScript代码绑定到Android代码

    js调用Android代码中的方法

    新建 WebAppInterface 类

    /*** @Author : alex* @Date : on 2023/11/14 09:21.* @Description :描述*/
    public class WebAppInterface {Context mContext;/*** 初始化接口,并设置context* @param c*/WebAppInterface(Context c){mContext=c;}/*** 在Web页面显示消息提示* @param toast*/@JavascriptInterfacepublic void showToast(String toast){Toast.makeText(mContext,toast,Toast.LENGTH_SHORT).show();}
    }
    

    webview 绑定接口:

     webView_first.addJavascriptInterface(new WebAppInterface(this),"Android");
    

    html代码示例:

    <!doctype html>
    <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Bootstrap demo</title><link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.1/css/bootstrap.min.css" rel="stylesheet"></head><body><h1>Hello, world!</h1><input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /><script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.1/js/bootstrap.bundle.min.js"></script><script type="text/javascript">function showAndroidToast(toast) {Android.showToast(toast);}</script></body>
    </html>
    
  8. webview中的跳转连接

    参考:https://www.digitalocean.com/community/tutorials/android-webview-example-tutorial

    当 html 中有跳转链接的时候,可以直接阻止、选择性阻止在我们的App跳转、或者可以打开系统浏览器,加载外部链接。

    webView_first.setWebViewClient(new MyWebViewClient());private class MyWebViewClient extends WebViewClient {@Overridepublic boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {Log.i("FirstWebViewActivity",request.getUrl().getHost());if ("192.168.96.108".equals(request.getUrl().getHost())) {// This is my website, so do not override; let my WebView load the pagereturn false;}// Otherwise, the link is not for a page on my site, so launch another Activity that handles URLsIntent intent = new Intent(Intent.ACTION_VIEW, request.getUrl());startActivity(intent);return true;}
    }
    
  9. webview加载本地网页,实现 sqlite 数据库增删改查

    使用的库 gson:

    implementation 'com.google.code.gson:gson:2.8.5'
    

    首先新建assets文件夹,android默认工程没有创建。

    在这里插入图片描述

    编写 DBHelper ,定义数据库名,在 onCreate 中初始化数据库:

    public class MyDatabaseHelper extends SQLiteOpenHelper {public static final String DATABASE_NAME = "student.db";public static final int DATABASE_VERSION =1;public MyDatabaseHelper(Context context){super(context,DATABASE_NAME,null,DATABASE_VERSION);}@Overridepublic void onCreate(SQLiteDatabase db) {// 数据库首次创建时调用,执行创建表等语句// 创建student表db.execSQL("CREATE TABLE student (" +"id INTEGER PRIMARY KEY AUTOINCREMENT," +"name TEXT," +"age INTEGER," +"birth TEXT)");// 如果需要初始化数据可以在这里插入:db.execSQL("INSERT INTO student (name, age, birth) " +"VALUES ('张三', 18, '1980-01-01')");}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {// 数据库版本更新时调用}
    }
    

    然后定义 MyApplication,在程序启动的时候初始化数据库:

    public class MyApplication extends Application {@Overridepublic void onCreate() {super.onCreate();//检测数据库是否存在,不存在则创建数据库Context context = getApplicationContext();MyDatabaseHelper dbHelper = new MyDatabaseHelper(context);SQLiteDatabase db = dbHelper.getWritableDatabase();}
    }
    

    定义数据增、查接口类,供H5中调用:

    public class JsDBInterface {private SQLiteDatabase db;public JsDBInterface(Context context){// 在构造函数中打开数据库MyDatabaseHelper helper = new MyDatabaseHelper(context);db = helper.getWritableDatabase();}/*** 插入数据* @param name* @param age* @param birth*/@JavascriptInterfacepublic void insertData(String name,int age,String birth){//检查参数if(name==null||name.isEmpty()){return;}//插入数据ContentValues values = new ContentValues();values.put("name",name);values.put("age",age);values.put("birth",birth);db.insert("student",null,values);Log.i("插入数据",name);}/*** 查询数据* @return*/@JavascriptInterfacepublic String getAllStudents(){List<Student> students = new ArrayList<>();//查询数据库中的所有学生Cursor cursor = db.query("student",null,null,null,null,null,null);//获取所有列
    //        String[] cols = cursor.getColumnNames();
    //        int nameIndex=-1;while (cursor.moveToNext()){int columnIndex1=cursor.getColumnIndex("id");int columnIndex2=cursor.getColumnIndex("name");int columnIndex3=cursor.getColumnIndex("age");int columnIndex4=cursor.getColumnIndex("birth");int id=0;String name="null";int age=0;String birth="0000-00-00";if(columnIndex1>=0){id = cursor.getInt(columnIndex1);}if(columnIndex2>=0){name=cursor.getString(columnIndex2);}if(columnIndex3>=0){age = cursor.getInt(columnIndex3);}if(columnIndex4>=0){birth=cursor.getString(columnIndex4);}Student stu = new Student(id,name,age,birth);students.add(stu);}cursor.close();Gson gson = new Gson();String json = gson.toJson(students);return json;}
    }
    

    数据实体类:

    public class Student {private int id;private String name;private int age;private String birth;public int getId() {return id;}public Student(int id,String name, int age, String birth) {this.id=id;this.name = name;this.age = age;this.birth = birth;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getBirth() {return birth;}public void setBirth(String birth) {this.birth = birth;}
    }
    

    在 Activity 中注册接口:

    webView.addJavascriptInterface(new JsDBInterface(MainActivity.this),"JsDBInterface");加载本地网页:
    private String localUrl="file:///android_asset/index.html";
    webView_first.loadUrl(localUrl);
    

    HTML 使用了vue,调用代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./vue.min.js"></script>
    </head>
    <body><div id="app"><h2>{{message}}</h2><ul><li v-for="user in users" :key="user.id">{{user.name}}</li></ul><button id="btnInsertStudent" onclick="addStudent()">新增学生</button><button id="btnGetAllStudents" onclick="getAllStudent()">查询所有学生</button><ul id='studentList'></ul></div><script>var app = new Vue({el:'#app',data(){return {message:'Hello Vue!'}},mounted(){}})function addStudent(){JsDBInterface.insertData("小明",18,"2010-01-01");alert('添加成功')}function getAllStudent(){var data = JsDBInterface.getAllStudents();var students = JSON.parse(data);var studentTxt='';for(var i = 0; i < students.length; i++) {var stu = students[i];studentTxt += '<li>' + stu.name + ',' + stu.age + ',' + stu.birth + '</li>';}var ul = document.getElementById('studentList');ul.innerHTML = studentTxt;}</script>
    </body>
    </html>
    

    结果:
    在这里插入图片描述

  10. webview h5 alert 不运行

    参考:https://copyprogramming.com/howto/modify-alert-title-javascript-in-android-webview

    最简单的处理方法是:添加下面的代码

    webView_first.setWebChromeClient(new WebChromeClient());
    

    在这里插入图片描述

但是上面的标题会显示网址,可以用下面的方法进行修改:

webView_first.setWebChromeClient(new WebChromeClient(){@Overridepublic boolean onJsAlert(WebView view, String url, String message, JsResult result) {AlertDialog dialog = new AlertDialog.Builder(view.getContext()).setTitle("提示").setMessage(message).setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// do nothing}}).create();dialog.show();result.confirm();return true;}
});

修改后:

在这里插入图片描述

此外如果对 alert, prompt, confirm统一进行修改,可以使用下面代码:

webView_first.setWebChromeClient(new WebChromeClient(){@Overridepublic boolean onJsAlert(WebView view, String url, String message, JsResult result) {new AlertDialog.Builder(view.getContext()).setTitle("alert").setMessage(message).setPositiveButton("确定", (DialogInterface dialog, int which) -> result.confirm()).setOnDismissListener((DialogInterface dialog) -> result.confirm()).create().show();return true;}@Overridepublic boolean onJsConfirm(WebView view, String url, String message, JsResult result) {new AlertDialog.Builder(view.getContext()).setTitle("confirm").setMessage(message).setPositiveButton("确定", (DialogInterface dialog, int which) -> result.confirm()).setNegativeButton("取消", (DialogInterface dialog, int which) -> result.cancel()).setOnDismissListener((DialogInterface dialog) -> result.cancel()).create().show();return true;}@Overridepublic boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {final EditText input = new EditText(view.getContext());input.setInputType(InputType.TYPE_CLASS_TEXT);input.setText(defaultValue);new AlertDialog.Builder(view.getContext()).setTitle("prompt").setMessage(message).setView(input).setPositiveButton("确定", (DialogInterface dialog, int which) -> result.confirm(input.getText().toString())).setNegativeButton("取消", (DialogInterface dialog, int which) -> result.cancel()).setOnDismissListener((DialogInterface dialog) -> result.cancel()).create().show();return true;}
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/191278.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Socket网络编程(服务端和客户端代码示例)

本文主要讲解Socket网络编程。 首先介绍socket&#xff0c;包括TCP和UDP通信过程&#xff1b;然后介绍常用的函数&#xff1b;最后编写client-server例子&#xff0c;并进行测试。 文章目录 Socket介绍TCP通信过程服务器端通信过程&#xff1a;客户端通信过程&#xff1a; UDP通…

SA实战 ·《SpringCloud Alibaba实战》第13章-服务网关:项目整合SpringCloud Gateway网关

大家好,我是冰河~~ 一不小心[SpringCloud Alibaba实战》专栏都更新到第13章了,再不上车就跟不上了,小伙伴们快跟上啊! 在《SpringCloud Alibaba实战》专栏前面的文章中,我们实现了用户微服务、商品微服务和订单微服务之间的远程调用,并且实现了服务调用的负载均衡。也基于…

FusionDiff:第一个基于扩散模型实现的多聚焦图像融合的论文

文章目录 1. 论文介绍2. 研究动机3. 模型结构3.1 网络架构3.2 前向扩散过程3.3 逆向扩散过程3.4 训练和推理过程 4. 小样本学习4. 实验结果 1. 论文介绍 题目&#xff1a;FusionDiff: Multi-focus image fusion using denoising diffusion probabilistic models 作者&#xf…

【Mysql系列】Mysql基础篇

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Smart Link 和 Monitor Link应用

定义 Smart Link常用于双上行链路组网&#xff0c;提高接入的可靠性。 Monitor Link通过监视上行接口&#xff0c;使下行接口同步上行接口状态&#xff0c;起到传递故障信息的作用。 Smart Link&#xff0c;又叫做备份链路。一个Smart Link由两个接口组成&#xff0c;其中一个…

医用污水处理一体化设备怎么选

选择医用污水处理一体化设备时&#xff0c;可以从以下几个方面进行考虑&#xff1a; 设备材质&#xff1a;选择耐腐蚀、耐磨损、抗老化的材质&#xff0c;例如不锈钢、玻璃钢等。同时要确保设备罐体的抗压性能。工艺流程&#xff1a;选择高效、稳定、安全的工艺流程&#xff0…

智慧渔业捕捞计数项目设计书

&#xff08;一&#xff09;项目背景 根据捕捞水域的不同&#xff0c;我国水产捕捞可划分为海洋捕捞、远洋捕捞以及淡水捕捞三大类型。其中&#xff0c;淡水渔业主要是指在淡水水域进行捕捞、养殖以获得淡水水产品并对这些水产品进行加工的社会生产领域。 近年来&#xff0c;随…

vim相关命令讲解!

本文旨在讲解vim 以及其相关的操作&#xff01; 希望读完本文&#xff0c;读者会有一定的收获&#xff01;好的&#xff0c;干货马上就来&#xff01; 初识vim 在讲解vim之前&#xff0c;我们首先要了解vim是什么&#xff0c;有什么作用&#xff1f;只有了解了vim才能更好的理…

【Amazon】云上探索实验室—了解 AI 编程助手 Amazon Codewhisperer

文章目录 一、前言&#x1f4e2;二、关于云上探索实验室&#x1f579;️三、领学员需要做什么&#xff1f;✴️四、领学员能获得什么&#xff1f;&#x1f523;五、学课通道入口&#x1f447;1️⃣CSDN平台2️⃣网易云课堂3️⃣Skill Builder 平台 六、活动详情链接 一、前言&a…

详解IP安全:IPSec协议簇 | AH协议 | ESP协议 | IKE协议

目录 IP安全概述 IPSec协议簇 IPSec的实现方式 AH&#xff08;Authentication Header&#xff0c;认证头&#xff09; ESP&#xff08;Encapsulating Security Payload&#xff0c;封装安全载荷&#xff09; IKE&#xff08;Internet Key Exchange&#xff0c;因特网密钥…

Shell脚本 CPU,内存,磁盘占用率检测

CPU&#xff1a;运算资源占用 内存&#xff1a;RAM类介质 磁盘&#xff1a;ROM类介质 一、CPU #!/bin/bash# 设置阈值&#xff0c;当CPU占用超过该阈值时进行输出提示 threshold80while true do# 使用top命令获取CPU占用信息&#xff0c;并使用grep和awk筛选和解析输出结果…

开源会议通知H5页面邀请函制作源码系统+自动翻页 带完整的搭建教程

现如今&#xff0c;线上活动越来越频繁&#xff0c;而会议邀请函也成为了活动组织者不可或缺的工具。然而&#xff0c;传统的邮件、短信等方式发送邀请函已经无法满足现代人的需求。因此&#xff0c;开发一款现代化的、功能丰富的会议邀请函系统势在必行。下面源码小编将来给大…

Wireshark学习 与 TCP/IP协议分析

Wireshark简介和工具应用 如何开始抓包&#xff1f; 打开wireshark&#xff0c;显示如下网络连接。选择你正在使用的&#xff0c;&#xff08;比如我正在使用无线网上网&#xff09;&#xff0c;双击 可以先看下自己的ip地址和网关ip地址&#xff08;看抓包数据时候会用到&…

【React】Antd 组件基本使用

Antd 组件基本使用 第一步 安装并引入 antd 包 使用命令下载这个组件库 yarn add antd在我们需要使用的文件下引入&#xff0c;我这里是在 App.jsx 内引入 import { Button } from antd现在我们可以在 App 中使用 Button 组件 <div>App..<Button type"prima…

基于Mahony互补滤波的IMU数据优化_学习笔记整理

这周自己被安排进行优化软件 IMU 姿态解算项目&#xff0c;之前自己只简单了解四元数&#xff0c;对IMU数据处理从未接触&#xff0c;通过这一周的学习感觉收获颇丰&#xff0c;在今天光棍节之际&#xff0c;&#xff0c;&#xff0c;用大半天的时间对这一周的收获进行整理&…

程序员刚毕业找工作,选大厂和小厂有什么区别

前言 **关于应届生毕业之后应该去大厂好还是小厂好&#xff0c;一直都是被热议的话题之一。**对于刚毕业的应届生来说是一个特别难的问题&#xff0c;怕选择错会后悔。同时周围的亲戚朋友也各抒己见&#xff1a;‘’一定要去大公司&#xff01;大公司名气响&#xff0c;在那里…

Amazon Bedrock | 大语言模型CLAUDE 2体验

这场生成式AI与大语言模型的饥饿游戏&#xff0c;亚马逊云科技也参与了进来。2023年&#xff0c;亚马逊云科技正式发布了 Amazon Bedrock&#xff0c;是客户使用基础模型构建和扩展生成式AI应用程序的最简单方法&#xff0c;为所有开发者降低使用门槛。在 Bedrock 上&#xff0…

医学统计学必备知识点分享,常笑医学为医学生答疑解惑

医学统计学作为医学生必修的一门课程&#xff0c;贯穿了医学生的整个职业生涯&#xff0c;在论文撰写、科研课题设计、医学研究职业发展等方面有着不可替代的重要性。 但是医学统计的学习门槛很高&#xff0c;大学开设的课程往往只侧重于理论&#xff0c;而没有结合实际工作&a…

什么叫做云安全?云安全有哪些要求?

云安全(Cloud Security)是一种基于云计算的安全防护策略&#xff0c;旨在保护企业数据和应用程序的安全性和完整性。云安全利用云计算的分布式处理和存储能力&#xff0c;以更高效、更灵活的方式提供安全服务。 云安全的要求主要包括以下几个方面&#xff1a; 数据安全和隐私保…

reticulate | R-python调用 | 安装及配置 | conda文件配置

reticulate | R-python安装及配置 | conda文件配置 1. 基础知识2. 安装reticulate from CRAN3. 包含了用于Python和R之间协同操作的全套工具&#xff0c;在R和Rstudio中均可使用4. 配置python环境4.1 4种环境配置方式4.2 miniconda 环境install_miniconda()报错一install_minic…