您现在的位置是:亿华云 > IT科技
基于鸿蒙分布式跨设备文件服务-信件管理
亿华云2025-10-09 06:58:13【IT科技】6人已围观
简介想了解更多内容,请访问:和华为官方合作共建的鸿蒙技术社区https://harmonyos.51cto.com一. 前言先说说写这个跨设备文件服务信件管理应用前, 都想过做什么, 首先看了梁迪迪的基于
想了解更多内容,基于请访问:
和华为官方合作共建的鸿蒙鸿蒙技术社区
https://harmonyos.51cto.com
一. 前言
先说说写这个跨设备文件服务信件管理应用前, 都想过做什么, 首先看了梁迪迪的基于分布式文件服务的文本编辑器,也想做一个文档的,比如创建word,excel,pdf文件,然后点击可以打开WPS软件来编辑,可惜搜索了网上找不到打开WPS方法,最后放弃了;然后想到弄一个画板,在画板上画上自己想表达的内容,保存为图片,跨设备可以打开图片查看,开始时保存图片,想用截屏的方法,查看文档没有找到Java调用系统的截屏方式,看到了JS的,但是要API7才支持,最后也放弃了,然而脑子里一闪,想起以前读书时,自习课不用大声说话,很多同学都是通过传纸条,那时也流行写信件,就往这个想法开始撸码,这里有几个知识点,之前没有写过,比如怎么把文本框输入的内容写到信纸上,然后保存为图片,在另一台设备上点击图片,可以查看里面的亿华云计算内容,通过网上搜索,还是找到相似的知识点, 才能在今天里做出了这个跨设备查看文件应用.
先简单说一下这个跨设备信件管理应用,A手机创建一封信件,生成图片,在A手机显示本地端, 在B手机显示远程端, 同时A,B手机都可以打开查看信件内容,这里使用到了分布式数据库管理,使用列表存储图片名,方便列表显示出来,然后点击相应的图片,获取到图片名,再到分布式文件路径获取到图片,显示出来.
二. 实现效果
开发工具环境下视频:https://www.bilibili.com/video/BV16L4y1i7b1/
手机+手机环境下视频:https://www.bilibili.com/video/BV1mL411g72B/
三. 创建工程
在这当作你已经安装好最新版本DevEco-Studio开发工具, 点击File -> New -> New Project… 弹出Create HarmonyOS Project窗口, 这里我选择空白Java模板创建, 上一个视频播放实例是用JS写的界面,这个跨设备信件管理界面就用Java来写,分布服务还是式跨设备JS写界面快,调试也快些.

Java模块布局模块
四. 主界面开发
先介绍公共类Java代码,文件有了这些公共类,信件以后做类似功能的源码下载管理应用,可以直接复制公共类文件可以使用:
DistributedFileUtil 分布式文件工具类:
package com.army.study.util; import com.army.study.ResourceTable; import ohos.agp.render.Canvas; import ohos.agp.render.Paint; import ohos.agp.render.Texture; import ohos.agp.utils.Color; import ohos.app.Context; import ohos.global.resource.NotExistException; import ohos.media.image.ImagePacker; import ohos.media.image.ImageSource; import ohos.media.image.PixelMap; import ohos.media.image.common.Size; import java.io.*; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * 分布式文件工具类 */ public class DistributedFileUtil { // 上下文 private final Context mContext; /** * 构造方法 * @param context */ public DistributedFileUtil(Context context) { this.mContext = context; } /** * 写信件 * @param fileName * @param letterContent * @return */ public PixelMap writeLetter(String fileName,基于 String letterContent) { // 获取分布式文件路径 String filePath = mContext.getDistributedDir() + File.separator + fileName + ".jpg"; Texture texture=null; try { // 从资源文件获取信纸背景图片 InputStream inputStream = mContext.getResourceManager().getResource(ResourceTable.Media_bg); ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions(); srcOpts.formatHint = "image/jpeg"; ImageSource imageSource = ImageSource.create(inputStream, srcOpts); // 设置图片参数 ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions(); decodingOptions.desiredSize=new Size(720,1080); PixelMap pixelMap = imageSource.createPixelmap(decodingOptions); //用于保存画图结果 texture=new Texture(pixelMap); Canvas canvas=new Canvas(texture); Paint paint=new Paint(); paint.setTextSize(50); paint.setStrokeWidth(8); paint.setColor(Color.BLACK); // 把内容写到信纸上 canvas.drawChars(paint,letterContent.toCharArray(),50,140); // 文件输出流 FileOutputStream fos=new FileOutputStream(filePath); ImagePacker imagePacker = ImagePacker.create(); ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions(); packingOptions.format = "image/jpeg";//只支持image/jpeg packingOptions.quality = 90; boolean result = imagePacker.initializePacking(fos, packingOptions); if(result) { //这里获取绘画后的pixelMap用来保存 result = imagePacker.addImage(texture.getPixelMap()); if (result) { long dataSize = imagePacker.finalizePacking(); System.out.println("文件大小:"+dataSize); ToastUtil.getInstance().showToast(mContext, "创建成功!"); } } fos.flush(); fos.close(); } catch (IOException | NotExistException e) { System.out.println("文件保存出错:"+e.getMessage()); e.printStackTrace(); } return texture.getPixelMap(); } /** * 读取信件 * @param fileName * @param letterContent * @return */ public PixelMap readImage(String fileName,鸿蒙 String letterContent) { // 获取分布式文件路径 String filePath = mContext.getDistributedDir() + File.separator + fileName; // 根据分布式文件路径,生成文件 File file = new File(filePath); if (!file.exists()) { // 如果文件不存在, 调用写信件 writeLetter(fileName, letterContent); } // 图片参数 ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions(); srcOpts.formatHint = "image/jpeg"; // 创建图片源 ImageSource imageSource = ImageSource.create(file, srcOpts); // 生成图片 PixelMap pixelMap = imageSource.createPixelmap(null); return pixelMap; } /** * 获取文件列表 * @return */ public List<String> getFileList() { // 获取分布式文件列表 File[] files = mContext.getDistributedDir().listFiles(); List<File> listFile = new ArrayList<>(Arrays.asList(files)); // 排序文件顺序 listFile.sort((file, newFile) -> { if (file.lastModified() > newFile.lastModified()) { return -1; } else if (file.lastModified() == newFile.lastModified()) { return 0; } else { return 1; } }); List<String> listFileName = new ArrayList<>(); // 获取文件列表文件名 for (File f : listFile) { if (f.isFile()) { String name = f.getName(); listFileName.add(name); } } return listFileName; } }ToastUtil 提示信息框:
package com.army.study.util; import com.army.study.ResourceTable; import ohos.agp.components.Component; import ohos.agp.components.LayoutScatter; import ohos.agp.components.Text; import ohos.agp.window.dialog.ToastDialog; import ohos.app.Context; /** * Toast工具类 * */ public class ToastUtil { private ToastDialog toastDialog; private ToastUtil() { } public static ToastUtil getInstance() { return ToastUtilInstance.INSTANCE; } private static class ToastUtilInstance { private static final ToastUtil INSTANCE = new ToastUtil(); } /** * 显示Toast * * @param context * @param content */ public void showToast(Context context, String content) { if (toastDialog != null && toastDialog.isShowing()) { toastDialog.cancel(); } Component toastLayout = LayoutScatter.getInstance(context) .parse(ResourceTable.Layout_layout_toast, null, false); Text toastText = (Text) toastLayout.findComponentById(ResourceTable.Id_text_msg_toast); toastText.setText(content); toastDialog = new ToastDialog(context); toastDialog.setComponent(toastLayout); toastDialog.setTransparent(true); toastDialog.show(); } }预览信件内容:
/** * 预览信件内容 */ public class PreviewLetterDialog extends CommonDialog { public PreviewLetterDialog(Context context, PixelMap imgId) { super(context); Component container = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_dialog_previce_letter, null, false); setContentCustomComponent(container); setSize(MATCH_PARENT, MATCH_CONTENT); setCornerRadius(AttrHelper.vp2px(20, context)); Image image = (Image) container.findComponentById(ResourceTable.Id_preview); image.setPixelMap(imgId); Button btnCancel = (Button) container.findComponentById(ResourceTable.Id_button_dialog_create_file_cancel); Button btnConfirm = (Button) container.findComponentById(ResourceTable.Id_button_dialog_create_file_confirm); btnCancel.setClickedListener(component -> { destroy();}); btnConfirm.setClickedListener(component -> { destroy();}); } }写信件对话框:
/** * 写信件对话框 */ public class CreateLetterDialog extends CommonDialog { private OnCallBack onCallBack; public CreateLetterDialog(Context context) { super(context); Component container = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_dialog_write_letter, null, false); setContentCustomComponent(container); Optional<Display> display = DisplayManager.getInstance().getDefaultDisplay(context); int width = (int) (display.get().getAttributes().width * 0.9); int height = AttrHelper.vp2px(270, context); setSize(width, height); setCornerRadius(AttrHelper.vp2px(20, context)); TextField letterContent = (TextField) container.findComponentById(ResourceTable.Id_tf_dialog_create_file_name); Button btnCancel = (Button) container.findComponentById(ResourceTable.Id_button_dialog_create_file_cancel); Button btnConfirm = (Button) container.findComponentById(ResourceTable.Id_button_dialog_create_file_confirm); btnConfirm.setEnabled(false); btnConfirm.setAlpha(0.5f); letterContent.addTextObserver((text, i, i1, i2) -> { if(text.isEmpty()){ btnConfirm.setEnabled(false); btnConfirm.setAlpha(0.5f); }else{ btnConfirm.setEnabled(true); btnConfirm.setAlpha(1f); } }); btnCancel.setClickedListener(component -> { destroy();}); btnConfirm.setClickedListener(component -> { if(onCallBack!=null){ // 设备ID String deviceID = KvManagerFactory.getInstance().createKvManager(new KvManagerConfig(context)) .getLocalDeviceInfo().getId(); // 组合文件名,方便区分是分布服务否为当前设备创造的文件 String name = deviceID + "-" + letterContent.getText(); onCallBack.onConfirm(name); } destroy(); }); } public void setOnCallBack(OnCallBack onCallBack) { this.onCallBack = onCallBack; } public interface OnCallBack { void onConfirm(String name); } }主界面代码图:

讲解到此了,不要忘记了config.json文件的式跨设备权限配置哦,在module下添加
"reqPermissions": [ { "name": "ohos.permission.DISTRIBUTED_DATASYNC" },文件 { "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO" }, { "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE" }, { "name": "ohos.permission.WRITE_MEDIA" }, { "name": "ohos.permission.READ_MEDIA" } ],想了解更多内容,请访问:
和华为官方合作共建的信件鸿蒙技术社区
https://harmonyos.51cto.com
很赞哦!(3)
相关文章
- 互联网中的地址是数字的IP地址,域名解析的作用主要就是为了便于记忆。
- 使用Python自动化Microsoft Excel和Word
- JDK新特性-Lambda表达式的神操作
- Python实例方法、类方法和类方法静态方法浅析
- 主流搜索引擎显示的相关搜索项越多,越能积极反映该域名的市场价值。同时,被评估域名的搜索引擎显示结果不佳可能是由于以下两个原因:
- 一图看懂 ASP.NET Core 中的服务生命周期
- 如何使用Spinnaker克服Kubernetes持续交付的挑战
- Python批量加水印只需一行命令!
- 并非一个好米任何人都会给你一个好的价格。那你该如何用以有的好米卖出最理想的价格呢?
- 编写简洁的React代码建议