当前位置: 首页 > news >正文

Android WebView上传文件/自定义弹窗技术,附件的解决方案

安卓内核开发

其实是Android的webview默认是不支持<input type="file"/>文件上传的。现在的前端页面需要处理的是:

权限

文件路径AndroidManifest.xml

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

宿主返回代码

   private ValueCallback<Uri> uploadMessage;private ValueCallback<Uri[]> uploadMessageAboveL;private final static int FILE_CHOOSER_RESULT_CODE = 10000;// 2.回调方法触发本地选择文件private void openImageChooserActivity() {Intent i = new Intent(Intent.ACTION_GET_CONTENT);i.addCategory(Intent.CATEGORY_OPENABLE);
//        i.setType("image/*");//图片上传
//        i.setType("file/*");//文件上传i.setType("*/*");//文件上传startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILE_CHOOSER_RESULT_CODE);}// 3.选择图片后处理@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == FILE_CHOOSER_RESULT_CODE) {if (null == uploadMessage && null == uploadMessageAboveL) return;Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();// Uri result = (((data == null) || (resultCode != RESULT_OK)) ? null : data.getData());if (uploadMessageAboveL != null) {onActivityResultAboveL(requestCode, resultCode, data);} else if (uploadMessage != null) {uploadMessage.onReceiveValue(result);uploadMessage = null;}} else {//这里uploadMessage跟uploadMessageAboveL在不同系统版本下分别持有了//WebView对象,在用户取消文件选择器的情况下,需给onReceiveValue传null返回值//否则WebView在未收到返回值的情况下,无法进行任何操作,文件选择器会失效if (uploadMessage != null) {uploadMessage.onReceiveValue(null);uploadMessage = null;} else if (uploadMessageAboveL != null) {uploadMessageAboveL.onReceiveValue(null);uploadMessageAboveL = null;}}}// 4. 选择内容回调到Html页面@TargetApi(Build.VERSION_CODES.LOLLIPOP)private void onActivityResultAboveL(int requestCode, int resultCode, Intent intent) {if (requestCode != FILE_CHOOSER_RESULT_CODE || uploadMessageAboveL == null)return;Uri[] results = null;if (resultCode == Activity.RESULT_OK) {if (intent != null) {String dataString = intent.getDataString();ClipData clipData = intent.getClipData();if (clipData != null) {results = new Uri[clipData.getItemCount()];for (int i = 0; i < clipData.getItemCount(); i++) {ClipData.Item item = clipData.getItemAt(i);results[i] = item.getUri();}}if (dataString != null)results = new Uri[]{Uri.parse(dataString)};}}uploadMessageAboveL.onReceiveValue(results);uploadMessageAboveL = null;}

webview完整扩展

private class Cyber_ChromeClient extends WebChromeClient {
{@Overridepublic void onProgressChanged(WebView view, int newProgress) {super.onProgressChanged(view, newProgress);//  mProgress.setProgress(newProgress);}@Overridepublic void onReceivedTitle(WebView view, String title) {super.onReceivedTitle(view, title);// mTitle.setText(title);}@Overridepublic void onReceivedIcon(WebView view, Bitmap icon) {super.onReceivedIcon(view, icon);}@Overridepublic boolean onJsAlert(WebView view, String url, String message, final android.webkit.JsResult result) {new AlertDialog.Builder(cyber_instance).setTitle("悠然智慧管理4.0").setMessage(message).setPositiveButton(android.R.string.ok,new AlertDialog.OnClickListener() {public void onClick(DialogInterface arg0, int arg1) {// TODO Auto-generated method stubresult.confirm();}}).setCancelable(false).create().show();return true;}//2020-5-15/*** 对网络连接状态进行判断* @return  true, 可用; false, 不可用*/private boolean isOpenNetwork() {ConnectivityManager connManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);NetworkInfo networkInfo = connManager.getActiveNetworkInfo();     if(networkInfo!= null) {//2.获取当前网络连接的类型信息//int networkType = networkInfo.getType();if(ConnectivityManager.TYPE_WIFI == networkType){//当前为wifi网络}else if(ConnectivityManager.TYPE_MOBILE == networkType){//当前为mobile网络}return connManager.getActiveNetworkInfo().isAvailable(); }return false;}/*** 覆盖默认的window.confirm展示界面,避免title里显示为“:来自file:”*/public boolean onJsConfirm(WebView view, String url, String message,final JsResult result) {final AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());builder.setTitle("优然智慧管理系统").setMessage(message).setPositiveButton("确定", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {result.confirm();}}).setNeutralButton("取消", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {result.cancel();}});builder.setOnCancelListener(new DialogInterface.OnCancelListener() {@Overridepublic void onCancel(DialogInterface dialog) {result.cancel();}});// 屏蔽keycode等于84之类的按键,避免按键后导致对话框消息而页面无法再弹出对话框的问题builder.setOnKeyListener(new DialogInterface.OnKeyListener() {@Overridepublic boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {//Log.v("onJsConfirm", "keyCode==" + keyCode + "event="+ event);return true;}});// 禁止响应按back键的事件// builder.setCancelable(false);AlertDialog dialog = builder.create();dialog.show();return true;// return super.onJsConfirm(view, url, message, result);}/*** 覆盖默认的window.prompt展示界面,避免title里显示为“:来自file:”* window.prompt('请输入您的域名地址', '618119.com');*/public boolean onJsPrompt(WebView view, String url, String message,String defaultValue, final JsPromptResult result) {final AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());builder.setTitle("优然智慧管理系统").setMessage(message);final EditText et = new EditText(view.getContext());et.setSingleLine();et.setText(defaultValue);builder.setView(et).setPositiveButton("确定", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {result.confirm(et.getText().toString());}}).setNeutralButton("取消", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {result.cancel();}});// 屏蔽keycode等于84之类的按键,避免按键后导致对话框消息而页面无法再弹出对话框的问题builder.setOnKeyListener(new DialogInterface.OnKeyListener() {public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {//Log.v("onJsPrompt", "keyCode==" + keyCode + "event="+ event);if (keyCode == KeyEvent.KEYCODE_ENTER) {result.confirm(et.getText().toString());dialog.dismiss();return true;}else{return false;}//}});// 禁止响应按back键的事件// builder.setCancelable(false);final  AlertDialog    dialog = builder.create();//2021-3-18 回车检测et.setOnKeyListener(new View.OnKeyListener() {@Overridepublic boolean onKey(View v, int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_ENTER) {// 监听到回车键,会执行2次该方法。按下与松开result.confirm(et.getText().toString());dialog.dismiss();}return false;}});dialog.show();return true;// return super.onJsPrompt(view, url, message, defaultValue,// result);}/2020-5-15//20240604 文件// For Android < 3.0public void openFileChooser(ValueCallback<Uri> valueCallback) {uploadMessage = valueCallback;openImageChooserActivity();}// For Android  >= 3.0public void openFileChooser(ValueCallback valueCallback, String acceptType) {uploadMessage = valueCallback;openImageChooserActivity();}//For Android  >= 4.1public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {uploadMessage = valueCallback;openImageChooserActivity();}// For Android >= 5.0@Overridepublic boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {uploadMessageAboveL = filePathCallback;openImageChooserActivity();return true;}}
}

调用浏览

  //非常重要cwpd_Web.setWebViewClient(new Cyber_WebviewClient());cwpd_Web.setWebChromeClient(new Cyber_ChromeClient());

相关文章:

Android WebView上传文件/自定义弹窗技术,附件的解决方案

安卓内核开发 其实是Android的webview默认是不支持<input type"file"/>文件上传的。现在的前端页面需要处理的是&#xff1a; 权限 文件路径AndroidManifest.xml <uses-permission android:name"android.permission.WRITE_EXTERNAL_STORAGE"/&g…...

selenium 输入框、按钮,输入点击,获取元素属性等简单例子

元素操作 nput框 输入send_keys&#xff0c; input框 清除clear()&#xff0c; 按钮 点击click() 按钮 提交submit() 获取元素 tag_name、 class属性值、 坐标尺寸 """ input框 输入1次&#xff0c;再追加输入一次&#xff0c; 清除&#xff0c; 再重新输入&…...

结构体构造函数

【知识点&#xff1a;结构体构造函数】下面两段代码等价。 &#xff08;1&#xff09;结构体构造函数写法 struct LinkNode {int data;LinkNode* next;LinkNode(int x):data(x),next(NULL) {} }; LinkNode* Lnew LinkNode(123); &#xff08;2&#xff09;非结构体构造函数写…...

基于单片机的电子万年历设计

摘要: 本设计以 AT89C51 单片机为主控器,使用 DS1302 时钟芯片、DS18B20 温度芯片、LCD1602 显示模块,利用Proteus 仿真软件和 Keil 编译软件进行了基于单片机的电子万年历仿真,设计的万年历可以在液晶上显示时间,同时还具有时间校准、温度显示等功能。 关键词 :单片机…...

大厂真实面试题(一)

滴滴大数据sql 取出累计值与1000差值最小的记录 1.题目 已知有表t_cost_detail包含id和money两列,id为自增,请累加计算money值,并求出累加值与1000差值最小的记录。 2.分析 本题主要是想找到累加值域1000差距最小的记录,也就是我们要对上述按照id进行排序并且累加,并…...

Docker搭建ELKF日志分析系统

Docker搭建ELKF日志分析系统 文章目录 Docker搭建ELKF日志分析系统资源列表基础环境一、系统环境准备1.1、创建所需的映射目录1.2、修改系统参数1.3、单击创建elk-kgc网络桥接 二、基于Dockerfile构建Elasticsearch镜像2.1、创建Elasticsearch工作目录2.2、上传资源到指定工作路…...

把系统引导做到U盘,实现插上U盘才能开机

前言 有个小伙伴提出了这样一个问题&#xff1a;能不能把U盘制作成电脑开机的钥匙&#xff1f; 小白稍微思考了一下&#xff0c;便做了这样一个回复&#xff1a;可以。 至于为什么要思考一下&#xff0c;这样会显得我有认真思考他提出的问题。 Windows7或以上系统均支持UEF…...

【计算机网络基础知识】

首先举一个生活化的例子&#xff0c;当你和朋友打电话时&#xff0c;你可能会使用三次握手和四次挥手的过程进行类比&#xff1a; 三次握手&#xff08;Three-Way Handshake&#xff09;&#xff1a; 你打电话给朋友&#xff1a;你首先拨打你朋友的电话号码并等待他接听。这就…...

个股场外期权个人如何参与买卖?

个股场外期权作为一种金融衍生品&#xff0c;为个人投资者提供了多样化的投资选择和风险管理工具。想要参与个股场外期权的买卖&#xff0c;以下是一些关键步骤和考虑因素。 文章来源/&#xff1a;财智财经 第一步&#xff1a;选择合适的金融机构 首先&#xff0c;个人投资者需…...

程序猿大战Python——pycharm软件的使用

基础配置 目标&#xff1a;了解PyCharm软件的基础配置处理。 修改背景颜色&#xff1a; Appearance -> Theme 修改字体大小&#xff1a; 搜索font -> Font 例如&#xff0c;一起完成背景、字体大小的修改。 总结&#xff1a; &#xff08;1&#xff09;如果要对PyChar…...

Unity Standard shader 修改(增加本地坐标裁剪)

本想随便找一个裁剪的shader&#xff0c;可无奈的是没找到一个shader符合要求&#xff0c;美术制作的场景都是用的都标准的着色器他们不在乎你的功能逻辑需求&#xff0c;他们只关心场景的表现&#xff0c;那又找不到和unity标准着色器表现一样的shader 1.通过贴图的透明通道做…...

【数据结构】排序——插入排序,选择排序

前言 本篇博客我们正式开启数据结构中的排序&#xff0c;说到排序&#xff0c;我们能联想到我之前在C语言博客中的冒泡排序&#xff0c;它是排序中的一种&#xff0c;但实现效率太慢&#xff0c;这篇博客我们介绍两种新排序&#xff0c;并好好深入理解排序 &#x1f493; 个人主…...

2024.6.9刷题记录

目录 一、1103. 分糖果 II 1.模拟 2.数学 二、312. 戳气球 1.递归-记忆化搜索 2.区间dp 三、2. 两数相加 1.迭代 2.递归-新建节点 3.递归-原节点 四、4. 寻找两个正序数组的中位数 1.堆 2.双指针二分 五、5. 最长回文子串 1.动态规划 2.中心扩展算法 六、6. Z…...

Matlab|遗传粒子群-混沌粒子群-基本粒子群

目录 1 主要内容 2 部分代码 3 效果图 4 下载链接 1 主要内容 很多同学在发文章时候最犯愁的就是创新点创新点创新点&#xff08;重要的事情说三遍&#xff09;&#xff0c;对于采用智能算法的模型&#xff0c;可以采用算法改进的方式来达到提高整个文章创新水平的目的&…...

31|HTTP3:甩掉TCP、TLS 的包袱,构建高效网络

前面两篇文章我们分析了HTTP/1和HTTP/2&#xff0c;在HTTP/2出现之前&#xff0c;开发者需要采取很多变通的方式来解决HTTP/1所存在的问题&#xff0c;不过HTTP/2在2018年就开始得到了大规模的应用&#xff0c;HTTP/1中存在的一大堆缺陷都得到了解决。 HTTP/2的一个核心特性是…...

2 程序的灵魂—算法-2.2 简单算法举例-【例 2.3】

【例 2.3】判定 2000 — 2500 年中的每一年是否闰年&#xff0c;将结果输出。 润年的条件: 1. 能被 4 整除&#xff0c;但不能被 100 整除的年份&#xff1b; 2. 能被 100 整除&#xff0c;又能被 400 整除的年份&#xff1b; 设 y 为被检测的年份&#xff0c;则算法可表示如下…...

Python中的上下文管理器(contextlib)模块

Python中的contextlib模块提供了一些用于创建和管理上下文管理器&#xff08;context managers&#xff09;的工具。上下文管理器是实现了__enter__()和__exit__()方法的对象&#xff0c;它们通常用于确保在代码块执行前后执行某些操作&#xff0c;比如资源获取与释放、设置和重…...

C语言:定义和使用结构体变量

定义和使用结构体变量 介绍基础用法1.定义结构体2. 声明结构体变量3. 初始化和访问结构体成员4. 使用指针访问结构体成员5. 使用结构体数组 高级用法6. 嵌套结构体7. 匿名结构体8. 结构体和动态内存分配9. 结构体作为函数参数按值传递按引用传递 介绍 在C语言中&#xff0c;结…...

Vue3学习第二天记录

Vue3学习第二天记录 背景说明截图记录一个简单的JS文件Vue3的watch()函数Vue3的toRef()/toRefs()函数前端数据类型的分类前端写一个对外暴露的函数前端的...语法Vue3中watch()函数的总结Vue3中watchEffect()函数Vue3中watch()函数的坑Vue3中computed()函数 背景 最近在学习尚硅…...

C语言:双链表

一、什么是双链表&#xff1f; 双链表&#xff0c;顾名思义&#xff0c;是一种每个节点都包含两个链接的链表&#xff1a;一个指向下一个节点&#xff0c;另一个指向前一个节点。这种结构使得双链表在遍历、插入和删除操作上都表现出色。与单链表相比&#xff0c;双链表不仅可以…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7

在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤&#xff1a; 第一步&#xff1a; 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为&#xff1a; // 改为 v…...