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.mzph.cn/news/142552.shtml

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

相关文章

21、Flink 的table API与DataStream API 集成(1)- 介绍及入门示例、集成说明

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

arm2 day6

串口实现单个字符的收发 main.c uart4.c uart4.h

java轮播图接口实现

一. 内容简介 实现java后端用户管理接口&#xff0c;数据库使用msyql。 二. 软件环境 2.1 java 1.8 2.2 mysql Ver 8.0.13 for Win64 on x86_64 (MySQL Community Server - GPL) 2.3 IDEA ULTIMATE 2019.3 2.4d代码地址 https://gitee.com/JJW_1601897441/competitionAs…

【左程云算法全讲10】打表技巧和矩阵处理技巧

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了秋招面试的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;材料主要源于左程云算法课程进行的&#xff0c;每个知识点的修正和深入主要参考…

冲击900亿美元估值!邀约路演、秘密交表的Shein上市有望

双十一的狂欢刚刚结束&#xff0c;Shein即将赴美上市的消息又在电商圈里投下一枚重磅炸弹。 继被媒体曝光其寻求900亿美金估值后&#xff0c;最新的消息称其已邀请投资人参与路演&#xff0c;且已秘密完成交表。这个神秘的中国独角兽&#xff0c;离敲钟登陆美股的日子越来越近…

SoftwareTest6 - 用 Selenium 怎么点点点

用 Selenium 来点点点 一 . 什么是自动化 ?1.1 自动化测试的分类接口自动化测试UI 自动化测试 (界面测试) 1.2 实现自动化测试的工具 : selenium环境部署驱动 二 . selenium 的使用2.1 一个简单的示例 : 让谷歌浏览器在百度首页搜索蔡徐坤准备工作编写代码 2.2 打开谷歌浏览器…

【vue】AntDV组件库中a-upload实现文件上传:

文章目录 一、文档&#xff1a;二、使用(以Jeecg为例)&#xff1a;【1】template&#xff1a;【2】script&#xff1a; 三、效果图&#xff1a; 一、文档&#xff1a; Upload 上传–Ant Design Vue 二、使用(以Jeecg为例)&#xff1a; 【1】template&#xff1a; <a-uploa…

day08_子网划分与子网掩码

什么是子网划分? 1、概念&#xff1a;借主机位给网络位使用,以此来达到把一个大网段划分为n个儿子网段的目的&#xff0c;2. 为何要进行子网划分&#xff1f;3、子网掩码&#xff1a;就是对ip地址打记号4、 网络地址的计算机方式&#xff1a;ip地址与子网掩码都转换成二进制&a…

Kafka消息队列为什么会丢消息,要怎么解决?

Kafka消息队列为什么会丢消息&#xff0c;怎么解决Kafka消息队列丢消息问题 Kafka 是一个分布式的高可用、高性能消息队列&#xff0c;它可以用于大规模的数据处理和流式计算场景。在 Kafka 中丢失消息会导致数据的不连续性、计算结果的准确性下降等问题&#xff0c;从而影响到…

【C++ 学习 ㊲】- 五种特殊类的设计

目录 一、设计一个禁止拷贝的类 二、设计一个只能在堆区上创建对象的类 三、设计一个只能在栈区和静态区上创建对象的类 四、设计一个不能继承的类 五、设计一个只能创建一个对象的类&#xff08;单例模式&#xff09; 一、设计一个禁止拷贝的类 拷贝只会发生在两个场景中…

IronSource 聚合广告平台接入踩坑日记——游戏声音消失

1.IOS 播放完广告之后&#xff0c;关闭广告&#xff0c;发现整个游戏的声音消失 解决方案&#xff1a; 1.取消勾选 Mute Other audio sources&#xff0c; 对于这个选项&#xff0c;官方的说法是&#xff1a; 运行 Unity 应用程序时&#xff0c;停止或允许在后台播放来自其…

基于51单片机PCF8591数字电压表数码管显示设计( proteus仿真+程序+设计报告+讲解视频)

PCF8591数字电压表数码管显示 1.主要功能&#xff1a;讲解视频&#xff1a;2.仿真3. 程序代码4. 设计报告5. 设计资料内容清单&&下载链接资料下载链接&#xff08;可点击&#xff09;&#xff1a; 基于51单片机PCF8591数字电压表数码管设计( proteus仿真程序设计报告讲…

Vue3-TypeScript-Threejs:导入外部的glb格式3D模型

一、直接上代码&#xff0c;在vue3-typescript-threejs 项目 导入外部的glb格式3D模型 极简代码&#xff0c;快速理解 <template><div ref"container"></div></template><script lang"ts" setup>import { onMounted, ref …

IEEE--DSConv: Efficient Convolution Operator 论文翻译

论文地址:https://arxiv.org/pdf/1901.01928v1.pdf 目录 摘要 1 介绍 2 相关工作 3 DSConv层 4 量化过程 5 分布偏移 6 优化推断 7 训练 8 结果 8.1 ImageNet 8.2 内存和计算负载 8.3 转移性 9 结论 摘要 我们引入了一种卷积层的变体&#xff0c;称为DSConv&…

cmd打开idea

当我们用idea打开一个项目的时候&#xff0c;有时候这个项目目录是有的&#xff0c;但是用idea的open却找不到&#xff0c;有时候我要重新关闭窗口&#xff0c;再open好多次才有 于是我现在使用命令打开&#xff0c;先把idea安装路径的bin目录放在path里面 然后cd到项目路径&…

Linux操作系统使用及C高级编程-D3Linux shell命令(权限、输入输出)

Shell 是一种应用程序&#xff0c;用以完成用户与内核之间的交互 一个功能强大的编程语言&#xff08;C语言&#xff09; 一个解释执行的脚本语言&#xff0c;不需要编译&#xff0c;写完直接执行 目前Linux 乌班图的Shell默认是bash 查看当前提供的Shell&#xff1a;cat /…

Tomcat隐藏版本号和关闭默认管理页面

一. 隐藏Tomcat异常页面中的版本信息&#xff0c;Tomcat服务器版本号泄露 Tomcat/8.5.xx相关版本号等信息&#xff0c;是不安全的。这会被黑客获取到&#xff0c;利用该版本的其他漏洞对服务器进行异常操作&#xff0c;所以需要隐藏掉。 进入tomcat安装目录 apache-tomcat-8.…

怎么在uni-app中使用Vuex 深度解刨

本文深入研究Vuex,一个Vue.js状态管理库。我们将介绍创建它是为了解决的问题、其背后的核心概念、如何设置它,当然,还将在每一步中使用代码示例。 Vuex是一个由Vue团队构建的状态管理库,用于管理Vue.js应用程序中的数据。它提供了一种集中管理跨应用程序使用的数据的方式,…

设计模式-备忘录模式(Memento)

设计模式-备忘录模式&#xff08;Memento&#xff09; 一、备忘录模式概述1.1 什么是备忘录模式1.2 简单实现备忘录模式1.3 使用备忘录模式的注意事项 二、备忘录模式的用途三、备忘录模式实现方式3.1 基于数组的备忘录实现方式3.2 基于集合的备忘录实现方式3.3 基于HashMap的备…

如何修改文件的修改时间?

如何修改文件的修改时间&#xff1f;随着当代社会科技的不断进步&#xff0c;我们对信息和数据的依赖程度与日俱增。在这个信息化时代&#xff0c;文件处理已经成为数字化办公中不可或缺的一部分。文件处理的范围非常广&#xff0c;其中有一个比较冷门的操作技巧&#xff0c;那…