Android WebView专题

WebView 专题

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

  1. Layout添加WebView组件;

    <WebView
            android: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;
    
        @Override
        protected 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/");
        }
    
        @Override
        protected 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中引用

    <application
            android: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
         */
        @JavascriptInterface
        public 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 {
        @Override
        public 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 page
                return false;
            }
            // Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs
            Intent 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);
        }
    
        @Override
        public 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')");
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            // 数据库版本更新时调用
    
        }
    }
    

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

    public class MyApplication extends Application {
        @Override
        public 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
         */
        @JavascriptInterface
        public 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
         */
        @JavascriptInterface
        public 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(){
    @Override
    public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
        AlertDialog dialog = new AlertDialog.Builder(view.getContext())
            .setTitle("提示")
            .setMessage(message)
            .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // do nothing
                }
            }).create();
        dialog.show();
        result.confirm();
        return true;
    }
});

修改后:

在这里插入图片描述

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

webView_first.setWebChromeClient(new WebChromeClient(){
    @Override
    public 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;
    }

    @Override
    public 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;
    }

    @Override
    public 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;
    }
});

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv8-Seg改进:卷积变体系列篇 | SCConv(空间和通道重建卷积) | CVPR2023

🚀🚀🚀本文改进:SCConv(空间和通道重建卷积),引入到YOLOv8,与C2f结合实现二次创新; 🚀🚀🚀SCConv亲测在多个数据集能够实现涨点 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1)手把…

项目管理:如何利用有限的时间完成无限的任务

时间管理&#xff0c;实质上就是利用有限的时间完成无限的任务。它要求我们通过对任务的安排&#xff0c;实现在有限的时间内&#xff0c;使任务变得更有条理。 时间管理就像整理房间。如果你长期不进行整理&#xff0c;房间的杂物就会越积越多。如果将各类物品进行分类&…

Java智慧工地大数据中心源码

智慧工地形成安全、质量、进度、人员、机械、绿色施工六大针对性解决方案。 智慧工地技术架构&#xff1a;微服务JavaSpring Cloud VueUniApp MySql 安全管理 围绕重大危险源提供管控&#xff0c;可视化跟踪消防、安防、基坑、高支模、临边防护、卸料平台等设施设备的安全状态…

mysql数据库时间

记录MySQL今天又一个新的问题&#xff1a; 场景&#xff1a;nodejs后台容器部署 问题原因&#xff1a;纯属好心办坏事&#xff0c;由于考虑了时区&#xff08;现在看来纯属多余&#xff09;&#xff0c;在写入时间时使用了time_str.toLocaleString("chinese", { ti…

绩效管理系统有哪些?

绩效管理系统有哪些&#xff1f; 把绩效管理系统按照两大指标分类—— 按地域划分&#xff08;主要看兼容性和稳定性&#xff09;按照功能性质划分&#xff08;主要看实用性和拓展性&#xff09; 按照以上两个维度&#xff0c;我们可以简单把绩效管理系统分为4大不同类型——…

arcgis--浮点型栅格数据转整型

利用【Spatial Analyst工具】-【数学】-【转为整型】工具&#xff0c;将浮点型数据转为整型。如下&#xff1a; 【转为整型】对话框参数设计如下&#xff1a; 转换结果如下&#xff1a;

基于ssm的学生档案管理系统(有报告)。Javaee项目,ssm项目。

演示视频&#xff1a; 基于ssm的学生档案管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm项目。 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 项目介绍&#xff…

UBC SDK日志级别重复率优化实践

作者 | wunan 导读 日志中中台每日传输的日志PV量级可达千亿级&#xff0c;在上报过程中减少冗余日志数据&#xff0c;能够降低下游数据处理的难度和成本&#xff0c;提高数据的准确性和质量&#xff0c;更好地支持业务系统的运行和优化。本文介绍了UBC SDK对日志重复打包的优化…

锅鸡unity和unityHub泼姐

链接在下面 支持pj所有国际版本的Unity和UnityHub。 自从 Unity2022.2.0 及以上版本重构了License逻辑&#xff0c;目前无法pj。问题跳转&#xff1a;#78 下载地址 Unity国际版 官方下载地址&#xff08;需要配置代理&#xff0c;代理没配置好可能会下载的国内版&#xff09…

记忆科技携手中国电信,一站式存储打造坚实数字底座

11月10日&#xff0c;以“数字科技 焕新启航”为主题的2023数字科技生态大会在广州盛大开幕&#xff0c;本次大会由中国电信、广东省人民政府联合举办&#xff0c;是一场数字科技领域的年度盛会。忆联母公司记忆科技作为中国电信的合作伙伴之一受邀参会&#xff0c;深度参与了大…

ARPG----C++学习记录05 Section10 碰撞,重叠事件

collision碰撞 Query only 仅查询。包括请求&#xff0c;扫描和重叠&#xff0c;扫描两个物体知否存在重叠Physics Only 仅物理。重力&#xff0c;反弹等物理计算都开启 按下“~”输入show collision可以查看碰撞 给石块添加碰撞&#xff0c;Query可以阻挡人物过去&#xff0c;…

域名怎么注册?一步步教你如何注册自己的域名

在互联网时代&#xff0c;网站是个人或企业展示品牌形象和推广品牌的重要工具&#xff0c;而无论是个人还是企业&#xff0c;在建设网站时&#xff0c;都需要提前注册域名。那么域名应该怎么注册呢&#xff1f;从域名选择&#xff0c;到选择域名注册商&#xff0c;再到域名注册…

段的概念_重定位的引入

段的概念 代码段、只读数据段、可读可写数据段、BSS段。 char g_Char A; //可读可写&#xff0c;不能放在ROM上&#xff0c;应该放在RAM里 const char g_Char2 B; //只读变量&#xff0c;可以放在ROM上 int g_A 0; //初始值为0&#xff0c;没有必要浪费空间 int g_B; //没…

MATLAB Simulink和SMART PLC水箱液位高度PID控制(联合仿真)

SMART PLC 向导PID的详细介绍请查看下面文章链接: S7-200 SMART PLC PID向导详细介绍(如何实现P、PD、PID控制器)-CSDN博客文章浏览阅读1k次。这篇博客主要介绍SMART PLC PID向导的使用,PID控制相关的其它内容请查看专栏系列文章,常用链接如下:SMART PLC PID负压控制(过程…

【uniapp】确认弹出框,选择确定和取消

代码如下&#xff1a; <view style"display: flex; justify-content: space-around;"><button class"button" click"submit">t提交</button> </view>submit(){let thatthisuni.showModal({title: 提示&#xff1a;,con…

AERMOD模型配置方法

数值模式模拟是分析大气污染物时空分布和成分贡献的重要工具&#xff0c;利用模拟结果可以分析大气污染的来源、成因、污染程度、持续时间、主要成分、相对贡献等问题&#xff0c;有助于分析并合理控制污染源排放&#xff0c;为产业调整提供参考。当前&#xff0c;针对不同理论…

【Linux】软硬链接和动静态库

软硬链接 软硬链接的区别&#xff1a; **软链接&#xff1a;**是一个独立文件&#xff0c;有自己独立的 inode 和 inode 编号。**硬链接&#xff1a;**不是一个独立的文件&#xff0c;它和目标文件使用的是同一个 inode。硬链接就是单纯的在 Linux 指定的目录下&#xff0c;给…

怎样能实现不同服务器之间的文件实时同步?

数字化时代&#xff0c;数据已经成为企业的重要资产&#xff0c;其中文件共享是企业运行中的重要业务场景。由于办公文件可能存在不同服务器甚至不同的城市之间&#xff0c;企业文件的实时同步是很多中大型企业急需解决的问题&#xff0c;为了不耽误业务的运行&#xff0c;甚至…

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

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