从零开始开发纯血鸿蒙应用之处理外部文件
从零开始开发纯血鸿蒙应用
- 一、外部文件
- 二、外部文件的访问形式
- 1、主动访问
- 2、被动访问
- 三、代码实现
- 1、DocumentViewPicker
- 2、Ability Skills
- 3、onNewWant 函数
- 4、冷启动时处理外部文件
一、外部文件
对于移动端app来说,什么是外部文件呢?是那些存储在手机之外的存储介质中的文件吗?还是另有说法呢?
不同于桌面端的应用,手机操作系统对文件的访问控制非常严格,但app读写文件又是非常基础的需要,所以,像华为的鸿蒙系统以及苹果手机的iOS系统,都专门为app开辟了一个名为沙箱目录的目录区域,每个app都有自己专属的一个沙箱目录。
app在自己的沙箱目录里,可以很自由的进行文件的创建和读写、以及删除。对于存放在自己的沙箱目录中的文件,我称之为app的内部文件,而那些存储在自己的沙箱目录外的文件,或是存储在用户目录的文件,也或是存储在其他app的沙箱目录中的文件,我就称之为外部文件。
需要提醒的是,app的沙箱目录,在手机上用文件管理是看不到的,必须借助电脑上的专门工具,例如 DevEco Studio 才能看到。app 的沙箱目录一般路径为 /data/app/el2/100/base/[package name]/hap/entry。

对于 DevEco Studio 提供的 Device File Browser,我想多说两句,一是该工具提供了两种查看视图,普通文件视图和沙箱文件视图,第二种视图依赖于应用需要在 module.josn5 中开启 ohos.permission.INTERNET 权限;二是该工具并不是所有app的沙箱目录都可以查看:

二、外部文件的访问形式
外部文件的访问,主要有两种形式:主动访问和被动访问。
1、主动访问
所谓主动访问,就是app自己通过主动调用鸿蒙 API——picker,拉起文件选择面板,让用户去选择文件,然后再对目标文件进行内容读取和处理。

picker 会将选中的目标文件的File URI暴露出来,通过该File URI,就可以按图索骥进行文件操作,比如读取文件属性信息。
2、被动访问

如上图的这种操作,我相信大家平日的手机使用过程中,都会遇到。当一个文件不是当前app能够进行处理的时候,往往系统就会让你选中用其他应用去处理,实际上,这种方式就是让你选择的那个目标应用被动地进行外部文件的访问和处理。
在鸿蒙系统中,一个app默认是不具有被动处理外部文件的能力的,想要具备这种能力,需要app自己向系统声明,一般就是在 module.json5 文件中进行相关配置。
三、代码实现
1、DocumentViewPicker
鸿蒙系统针对不同的文件类型,提供了多种具体的 picker,其中,针对文件的就是这里即将进行介绍的DocumentViewPicker。
DocumentViewPicker 的使用非常简单,只需传入一个 option 即可:
const option: picker.DocumentSelectOptions = new picker.DocumentSelectOptions();
option.maxSelectNumber = 1;
option.fileSuffixFilters = ['.txt', '.log', '.csv', '.ini', '.conf', '.md', '.markdown', '.rtf', '.json','.xml', '.ets', '.java', '.py','.c', '.cpp', '.h', '.html']
const filePicker = new picker.DocumentViewPicker(this.ctx);
filePicker.select(option).then((uri) => {Logger.info(`选中的文件:${uri}`, TAG);const param: StrRouterParam = new StrRouterParam(uri[0]);router.pushUrl({url: "pages/ImportFilePage",params: param})
})
过程步骤可以描述为如下的几步:
1)创建一个 picker.DocumentSelectOptions 对象
2)使用 picker.DocumentSelectOptions 对象的属性,设置最大选中数、目标文件后缀等必要的文件过滤条件。picker.DocumentSelectOptions 对象一共有如下属性:
- maxSelectNumber:最大可选中数,值域范围1~500,如果是选择目录,那么该值只能为1;默认值为 1.
- defaultFilePathUri:指定选择文件或目录路径,即默认的文件或目录路径;没有默认值。
- fileSuffixFilters:目标文件的后缀;默认全部文件。
- selectMode:选择模式,用于设置支持选择的资源类型:文件、文件夹或二者混合;默认是文件。
- authMode:授权模式,默认为 false;当值为 true,则 defaultFilePathUri 必填,表示待授权的 uri。
3)利用 UI 上下文,创建一个 picker.DocumentViewPicker 对象,并使用该对象的 select 方法拉起文件选择面板,而select 方法的回调处理中,可以获得用户选中的文件的 uri,我这里是将该 uri 通过 router 路由携带跳转到专门用展示外部文件的页面里,然后展示文件内容:

2、Ability Skills
前面说了,应用默认是不具有被动处理外部文件的能力的,除非向系统声明了,而这个声明就是在 module.json5 中进行能力声明:

skills 标签里的 actions 标签,用于声明具体的能力动作,上面的ohos.want.action.viewData,就表示查看数据的操作;同样位于 skills 标签里面的 uris 标签,可以为 viewData 动作进行进一步的细化,声明支持何种类型的数据的查看,如上的配置,则表示支持通用纯文本文件类型的数据的查看。
通过类似如上的配置,当用户需要进入“使用其他应用打开文件”的场景时,系统就会判断待打开的文件,是否与应用在 module.json5 文件中声明的数据查看能力相符合,如果符合就会展示在应用候选中,否则就不展示。
3、onNewWant 函数
光在 module.json5 文件中声明 Ability Skills,尚不足以形成真正的处理外部文件的能力,因为传记录的文件uri 没有任何代码进行读取等文件操作,而想要实现这一步骤,就需要用到一个应用生命周期函数 onNewWant 函数。

当应用已经完成冷启动并进入后台运行状态时,用户的“选择某某app打开文件”的操作,就会触发该生命周期函数,而函数的 Want 参数里面,就包含了用户想要打开的文件的 File Uri,因此,就可以用类似如下的代码进行处理:

4、冷启动时处理外部文件
用户在其他app页面,选择用当前应用去打开文件时,当前应用可能并未完成冷启动,这时候,就不会触发 OnNewWant 函数,而是触发 onCreate 函数:

然而,由于 onCreate 函数早于 onWindowStageCreate 的执行,意味着 UI 进程还没开始,也就是页面跳转动作还不能进行,所以,在 onCreate 函数里面处理其他app传进来的文件,是不合适的,不妨移步到 onWindowStageCreate 函数中。

onWindowStageCreate 函数的参数,虽然没有 Want 对象,但是 this 上下文里面就有有一个 launchWant 实例,借助它依旧能够获取到其他app传入的文件 uri,由于 windowStage.loadContent 不像 router.push 那样携带参数,而 windowStage.loadContent 在被执行完成之前,应用主页未被渲染出来,router.push 依旧用不了,所以,我利用 AppStorage 去完成外部文件 uri 的透传:

在应用主页的 aboutToAppear 生命周期函数中,判断 AppStorage 中记录的 SignalConstants.SIGNAL_OUTFILE_URI 是否为非空字符串,如果是,则将对应的外部文件的 File Uri 通过 router.push 携带跳转到 ViewOutsideFile 页面,从而完成冷启动状态下对外部文件的处理。
相关文章:
从零开始开发纯血鸿蒙应用之处理外部文件
从零开始开发纯血鸿蒙应用 一、外部文件二、外部文件的访问形式1、主动访问2、被动访问 三、代码实现1、DocumentViewPicker2、Ability Skills3、onNewWant 函数4、冷启动时处理外部文件 一、外部文件 对于移动端app来说,什么是外部文件呢?是那些存储在…...
Spring中三级缓存详细讲解
1、Spring三级缓存是什么,过程是怎么样的? Spring 中的三级缓存主要用于单例 Bean 的生命周期管理,特别是在循环依赖时,它通过不同阶段暴露 Bean 实例来确保依赖注入的顺利完成。缓存的内容如下: 一级缓存 (singleton…...
论文阅读:《Whole-animal connectomes of both Caenorhabditis elegans sexes》
一 论文整体概述 论文下载链接:《Whole-animal connectomes of both Caenorhabditis elegans sexes》 补充信息和额外数据:https://www.nature.com/articles/s41586-019-1352-7 1. 作者期刊背景 该论文由Scott W. Emmons,David H. Hall等…...
嵌入式开发之STM32学习笔记day03
STM32之ADC(模拟数字转换器) 1 ADC简述2 ADC转换时间3 ADC转化结果存放机制4 ADC转化结果存放机制5 ADC电压转换 1 ADC简述 ADC(Analog-Digital Converter)模拟—数字转换器;ADC可以将引脚上连续变化的模拟电压转换为…...
windows10 安装 Golang 版本控制工具g与使用
下载包:https://github.com/voidint/g/releases 解压, 并添加到环境变量 g 常用命令 查询当前可供安装的stable状态及所有的 go 版本 # stable 版本 g ls-remote stable# 所有版本 g ls-remote安装目标 go 版本1.23.4g install 1.23.4切换到已安装的…...
SpringBoot 使用 Cache 集成 Redis做缓存保姆教程
1. 项目背景 Spring Cache是Spring框架提供的一个缓存抽象层,它简化了缓存的使用和管理。Spring Cache默认使用服务器内存,并无法控制缓存时长,查找缓存中的数据比较麻烦。 因此Spring Cache支持将缓存数据集成到各种缓存中间件中。本文已常…...
R数据分析:多分类问题预测模型的ROC做法及解释
有同学做了个多分类的预测模型,结局有三个类别,做的模型包括多分类逻辑回归、随机森林和决策树,多分类逻辑回归是用ROC曲线并报告AUC作为模型评估的,后面两种模型报告了混淆矩阵,审稿人就提出要统一模型评估指标。那么肯定是统一成ROC了,刚好借这个机会给大家讲讲ROC在多…...
数据结构与算法之二叉树: LeetCode 654. 最大二叉树 (Ts版)
最大二叉树 https://leetcode.cn/problems/maximum-binary-tree/ 描述 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点,其值为 nums 中的最大值递归地在最大值 左边 的 子数组前缀上 构建左子树递归地在最大值…...
Linux 容器漏洞
定义:Linux 容器漏洞是指在容器技术(如 Docker、LXC 等)运行环境中存在的安全弱点。这些漏洞可能存在于容器镜像本身、容器运行时(如 runc)、容器编排工具(如 Kubernetes)或者容器与主机之间的交…...
file与io流(1)
-1- java.io.File类的使用 (1) 概述 File类及本章下的各种流,都定义在java.io包下。一个File对象代表硬盘或网络中可能存在的一个文件或者文件目录(俗称文件夹),与平台无关。(体会万事万物皆…...
忘记了PDF文件的密码,怎么办?
PDF文件可以加密,大家都不陌生,并且大家应该也都知道PDF文件有两种密码,一个打开密码、一个限制编辑密码,因为PDF文件设置了密码,那么打开、编辑PDF文件就会受到限制。忘记了PDF密码该如何解密? PDF和offi…...
Linux权限管理(用户和权限之间的关系)
Linux系列 文章目录 Linux系列一、Linux下用户类型二、普通权限的基本概念2.1、Linux中权限的类别2.2、Linux中权限对应的三种身份2.3、文件权限的标识 三、文件权限设置四、修改文件属主和属组4.1、chown修改文件的属主4.2、修改所属组 五、文件掩码六、目录权限 一、Linux下用…...
Python Selenium库入门使用,图文详细。附网页爬虫、web自动化操作等实战操作。
文章目录 前言1 创建conda环境安装Selenium库2 浏览器驱动下载(以Chrome和Edge为例)3 基础使用(以Chrome为例演示)3.1 与浏览器相关的操作3.1.1 打开/关闭浏览器3.1.2 访问指定域名的网页3.1.3 控制浏览器的窗口大小3.1.4 前进/后…...
【Uniapp-Vue3】使用defineExpose暴露子组件的属性及方法
如果我们想要让父组件访问到子组件中的变量和方法,就需要使用defineExpose暴露: defineExpose({ 变量 }) 子组件配置 父组件配置 父组件要通过onMounted获取到子组件的DOM 传递多个属性和方法 子组件 父组件...
【多模态LLM】英伟达NVLM多模态大模型训练细节和数据集
前期笔者介绍了OCR-free的多模态大模型,可以参考:【多模态&文档智能】OCR-free感知多模态大模型技术链路及训练数据细节,其更偏向于训练模型对于密集文本的感知能力。本文看一看英伟达出品的多模态大模型NVLM-1.0系列,虽然暂未…...
HTTP详解——HTTP基础
HTTP 基本概念 HTTP 是超文本传输协议 (HyperText Transfer Protocol) 超文本传输协议(HyperText Transfer Protocol) HTTP 是一个在计算机世界里专门在 两点 之间 传输 文字、图片、音视频等 超文本 数据的 约定和规范 1. 协议 约定和规范 2. 传输 两点之间传输…...
MySQL教程之:输入查询
如上一节所述,确保您已连接到服务器。这样做本身不会选择任何要使用的数据库,但没关系。在这一点上,了解一下如何发出查询比直接创建表、加载数据和从中检索数据更重要。本节介绍输入查询的基本原则,使用几个查询,您可…...
docker+ffmpeg+nginx+rtmp 拉取摄像机视频
1、构造程序容器镜像 app.py import subprocess import json import time import multiprocessing import socketdef check_rtmp_server(host, port, timeout5):try:with socket.create_connection((host, port), timeout):print(f"RTMP server at {host}:{port} is avai…...
不同音频振幅dBFS计算方法
1. 振幅的基本概念 振幅是描述音频信号强度的一个重要参数。它通常表示为信号的幅度值,幅度越大,声音听起来就越响。为了更好地理解和处理音频信号,通常会将振幅转换为分贝(dB)单位。分贝是一个对数单位,能…...
【17. 电话号码的字母组合 中等】
题目: 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 示例 1: 输入:digits “23”…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
