HarmonyOS 文件管理服务:让你的应用支持"删除到回收站"
什么是文件管理服务
你有没有遇到过这种情况:不小心删了一个重要文件,然后就找不回来了?电脑上一般有回收站,删了文件还能从回收站里恢复。但手机上呢?很多手机 App 删除文件就是直接删了,没有后悔的机会。
文件管理服务(File Manager Service Kit)就是来解决这个问题的。它是鸿蒙生态下的文件管理服务,提供了"删除到回收站"的能力。简单说,就是让你的 App 删除文件时,不是直接删掉,而是放到回收站里,用户可以随时恢复。
你可能会问:回收站在哪?在鸿蒙系统里,回收站是系统级的功能,用户可以在文件管理器里找到。你只需要调用文件管理服务的接口,把文件"移到回收站"就行,剩下的事情系统会帮你处理。
核心功能
文件管理服务目前提供的核心功能就一个:
- 删除到回收站:把文件移到回收站,而不是直接删除
虽然功能看起来简单,但这个能力非常重要。想想看,你的 App 如果有文件管理功能,用户肯定会期望有回收站,就像电脑上的回收站一样。没有回收站的文件管理器,用户用起来总是提心吊胆的,生怕一不小心删错了东西。
环境搭建
硬件要求
- 设备类型:华为手机、平板、PC/2in1
- HarmonyOS 系统:HarmonyOS 5.0.5 Release 及以上
软件要求
- DevEco Studio 版本:DevEco Studio 5.0.5 Release 及以上
- HarmonyOS SDK 版本:HarmonyOS 5.0.5 Release SDK 及以上
搭建步骤
- 安装 DevEco Studio:去华为开发者官网下载安装,跟着提示走就行
- 配置开发环境:确保网络环境正常,DevEco Studio 需要联网才能用
- 设备调试:使用真机进行调试,模拟器也可以
项目结构
└── entry/src/main ├── ets │ ├── entryability │ │ └── EntryAbility.ets // 程序入口类 │ └── pages │ └── Index.ets // 主界面 └── resources // 资源文件目录项目结构非常简单,核心逻辑都在Index.ets里。这个 Codelab 的重点就是教你调用文件管理服务的接口,所以代码量不大。
第一步:导入模块
import{fileManagerService}from'@kit.FileManagerServiceKit';import{BusinessError}from'@kit.BasicServicesKit';import{common}from'@kit.AbilityKit';import{hilog}from'@kit.PerformanceAnalysisKit';import{picker}from'@kit.CoreFileKit';import{PromptAction}from'@kit.ArkUI';导入的模块有点多,一个个来说:
fileManagerService:文件管理服务的核心接口,我们用它来调用"删除到回收站"功能。这是整个文章最重要的模块BusinessError:错误处理用的。华为的 Kit 接口基本都用这个来返回错误信息,包括错误码和错误描述common:获取上下文用的。调用文件管理服务接口时需要传入应用的上下文hilog:日志工具,开发调试的时候看输出用的。出了问题也能查日志,建议别删picker:文件选择器,让用户选择要删除的文件。你想啊,用户得先选中一个文件,才能删除它对吧PromptAction:弹出提示用的,比如"删除成功"、"删除失败"这种提示框
第二步:定义日志标签
constdomain=0x0000;consttag='deleteTag';定义日志的标签,方便在控制台里找到我们的日志输出。domain是日志的域,tag是标签名,你可以随便取,只要方便识别就行。
为什么要定义这个?因为鸿蒙系统里会有很多日志输出,如果你不加标签,根本找不到自己写的日志。就像在一堆信件里找自己的信,有个名字标记就好找多了。
第三步:创建文件选择器
letcontext:common.UIAbilityContext=this.getUIContext().getHostContext()ascommon.UIAbilityContext;letpromptAction:PromptAction=this.getUIContext().getPromptAction();letselectOptions:picker.DocumentSelectOptions=newpicker.DocumentSelectOptions();selectOptions.defaultFilePathUri='file://docs/storage/Users/currentUser';letdocumentPicker=newpicker.DocumentViewPicker(context);创建文件选择器的过程,我一行一行解释:
- 获取上下文(context):这是应用的运行环境,很多接口都需要传入这个参数。你可以理解为"当前页面的环境信息"
- 获取提示操作(promptAction):用来弹出提示信息,比如 Toast 提示。不获取这个的话,你就没办法弹提示了
- 创建选择选项(selectOptions):可以设置默认打开的路径。这里设置为用户文件目录,这样用户打开选择器时直接看到的就是自己的文件
- 创建文件选择器(documentPicker):用来让用户选择文件。这个选择器是系统提供的,长得和系统文件管理器一样
defaultFilePathUri设置了文件选择器打开时默认显示的路径。如果你不设置这个,选择器可能会打开一个默认目录,用户还得自己导航到想要的目录,体验不好。
第四步:选择文件并删除到回收站
documentPicker.select(selectOptions,async(err:BusinessError,documentSelectResult:Array<string>)=>{if(err){hilog.error(domain,tag,'DocumentViewPicker.select failed with err: '+JSON.stringify(err));return;}// 选择成功,处理文件});调用documentPicker.select打开文件选择器。用户会看到一个系统文件选择界面,可以选择一个或多个文件。
选择完成后,回调函数会被调用:
- 如果
err有值,说明出了问题(比如用户取消了选择),打印错误信息然后 return - 如果
err没有值,说明选择成功,documentSelectResult里就是用户选中的文件 URI 列表
try{for(leturiofdocumentSelectResult){hilog.info(domain,tag,'deleteToTrash start');constret:string=awaitfileManagerService.deleteToTrash(uri);hilog.info(domain,tag,'deleteToTrash end, ret:%{public}',ret);}promptAction.showToast({message:`delete success`,duration:5});}catch(error){hilog.error(domain,tag,`error.code:${error.code}, error.message:${error.message}`);promptAction.showToast({message:`delete failed, error.code:${error.code}, error.message:${error.message}`,duration:5});}这是核心逻辑,我拆开来说:
- 遍历用户选择的所有文件:用户可能选了多个文件,所以用
for...of循环处理 - 调用
fileManagerService.deleteToTrash(uri):这是整个文章最重要的 API。它不会直接删除文件,而是把文件移到回收站里。用户可以在文件管理器的回收站里找到这些文件,随时恢复 - 全部成功后,弹出"删除成功"的提示:让用户知道操作完成了
- 如果出错了,弹出错误信息:可能是因为文件不存在、权限不足等原因
deleteToTrash的返回值是一个字符串,表示操作结果。你可以根据这个返回值判断是否成功。
为什么要用try...catch?因为删除文件可能会失败。比如文件已经被删了、文件路径不对、没有权限等等。如果不捕获异常,程序可能会崩溃。
完整代码
把上面的步骤合在一起,完整的代码是这样的:
import{fileManagerService}from'@kit.FileManagerServiceKit';import{BusinessError}from'@kit.BasicServicesKit';import{common}from'@kit.AbilityKit';import{hilog}from'@kit.PerformanceAnalysisKit';import{picker}from'@kit.CoreFileKit';import{PromptAction}from'@kit.ArkUI';constdomain=0x0000;consttag='deleteTag';@Entry@Componentstruct Index{build(){Column(){Button($r('app.string.select_files_to_delete')).onClick(async()=>{try{letcontext:common.UIAbilityContext=this.getUIContext().getHostContext()ascommon.UIAbilityContext;letpromptAction:PromptAction=this.getUIContext().getPromptAction();letselectOptions:picker.DocumentSelectOptions=newpicker.DocumentSelectOptions();selectOptions.defaultFilePathUri='file://docs/storage/Users/currentUser';letdocumentPicker=newpicker.DocumentViewPicker(context);documentPicker.select(selectOptions,async(err:BusinessError,documentSelectResult:Array<string>)=>{if(err){hilog.error(domain,tag,'DocumentViewPicker.select failed with err: '+JSON.stringify(err));return;}try{for(leturiofdocumentSelectResult){hilog.info(domain,tag,'deleteToTrash start');constret:string=awaitfileManagerService.deleteToTrash(uri);hilog.info(domain,tag,'deleteToTrash end, ret:%{public}',ret);}promptAction.showToast({message:`delete success`,duration:5});}catch(error){hilog.error(domain,tag,`error.code:${error.code}, error.message:${error.message}`);promptAction.showToast({message:`delete failed, error.code:${error.code}, error.message:${error.message}`,duration:5});}});}catch(error){leterr:BusinessError=errorasBusinessError;hilog.error(domain,tag,'DocumentViewPicker failed with err: '+JSON.stringify(err));}})}.height('100%').width('100%').justifyContent(FlexAlign.Center)}}整个流程就是:点击按钮 → 打开文件选择器 → 用户选择文件 → 调用deleteToTrash删除到回收站 → 显示结果提示。
看起来代码挺长的,但其实逻辑很简单。大部分代码都是在做准备工作(创建选择器、获取上下文),真正干活的就一行:fileManagerService.deleteToTrash(uri)。
实际应用场景
文件管理服务在实际开发中有很多用途:
文件管理器
// 文件管理器中的删除功能asyncfunctiondeleteFileToTrash(uri:string){try{constret:string=awaitfileManagerService.deleteToTrash(uri);console.info('文件已移到回收站');// 可以在这里更新 UI,把文件从列表里移除}catch(error){console.error(`删除失败:${error.code},${error.message}`);// 提示用户删除失败}}在文件管理器里,用户删除文件时,调用deleteToTrash把文件移到回收站,而不是直接删除。这样用户可以随时从回收站恢复文件。
你可能会问:那回收站满了怎么办?鸿蒙系统的回收站有自动清理机制,会按照先进先出的原则清理旧文件。你不需要自己管理回收站的空间。
笔记应用
// 笔记应用中删除附件asyncfunctiondeleteNoteAttachment(attachmentUri:string){try{awaitfileManagerService.deleteToTrash(attachmentUri);// 更新笔记,移除附件引用console.info('附件已移到回收站');}catch(error){console.error(`删除附件失败:${error.code}`);}}在笔记应用里,用户删除笔记附件时,也可以用这个功能。附件被移到回收站,用户如果发现误删了,可以去回收站恢复。
图片编辑应用
// 图片编辑应用中删除原图asyncfunctiondeleteOriginalImage(imageUri:string){try{awaitfileManagerService.deleteToTrash(imageUri);console.info('原图已移到回收站');}catch(error){console.error(`删除原图失败:${error.code}`);}}在图片编辑应用里,编辑完图片后,如果用户想删除原图,可以用这个功能把原图移到回收站。这样即使用户后悔了,也能从回收站找回来。
适用场景
文件管理服务适合以下场景:
- 文件管理器:文件删除和回收站管理
- 笔记应用:笔记附件的删除
- 图片应用:图片文件的删除
- 文档应用:文档文件的删除
- 下载管理器:下载文件的删除
注意事项
- 文件权限:删除文件前,需要确保对文件有读写权限。可以通过文件选择器让用户授权,这是最简单的方式
- 文件 URI:要确保传入的文件 URI 是有效的,否则会删除失败。URI 格式一般是
file://docs/... - 回收站管理:删除到回收站的文件会占用存储空间,提醒用户定期清理回收站
- 错误处理:要做好错误处理,比如文件不存在、权限不足等情况。不要让程序因为删除失败就崩溃
- 用户体验:删除前最好给用户一个确认提示,避免误删。毕竟移到回收站虽然可以恢复,但多一步确认总是好的
核心流程图
删除文件到回收站的完整流程:
文件管理服务的应用场景:
总结
文件管理服务让你的应用支持"删除到回收站",核心流程:
- 导入文件管理服务模块
- 创建文件选择器,让用户选择要删除的文件
- 调用
deleteToTrash把文件移到回收站 - 处理成功和失败的情况
虽然功能看起来简单,但"删除到回收站"是一个非常实用的功能。它让用户不再担心误删文件,提升了应用的用户体验。如果你的 App 有文件管理功能,一定要加上这个能力。