基于鸿蒙分布式跨设备文件服务-信件管理

开发 前端 分布式
这个跨设备信件管理应用,A手机创建一封信件,生成图片,在A手机显示本地端, 在B手机显示远程端, 同时A,B手机都可以打开查看信件内容,这里使用到了分布式数据库管理,使用列表存储图片名.

[[431770]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

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写界面快,调试也快些.

基于鸿蒙分布式跨设备文件服务-信件管理-鸿蒙HarmonyOS技术社区

Java模块布局模块

四. 主界面开发

先介绍公共类Java代码,有了这些公共类,以后做类似功能的应用,可以直接复制公共类文件可以使用:

DistributedFileUtil 分布式文件工具类:

  1. package com.army.study.util; 
  2.  
  3. import com.army.study.ResourceTable; 
  4. import ohos.agp.render.Canvas; 
  5. import ohos.agp.render.Paint; 
  6. import ohos.agp.render.Texture; 
  7. import ohos.agp.utils.Color; 
  8. import ohos.app.Context; 
  9. import ohos.global.resource.NotExistException; 
  10. import ohos.media.image.ImagePacker; 
  11. import ohos.media.image.ImageSource; 
  12. import ohos.media.image.PixelMap; 
  13. import ohos.media.image.common.Size
  14.  
  15. import java.io.*; 
  16. import java.util.ArrayList; 
  17. import java.util.Arrays; 
  18. import java.util.List; 
  19.  
  20. /** 
  21.  * 分布式文件工具类 
  22.  */ 
  23. public class DistributedFileUtil { 
  24.     // 上下文 
  25.     private final Context mContext; 
  26.  
  27.     /** 
  28.      * 构造方法 
  29.      * @param context 
  30.      */ 
  31.     public DistributedFileUtil(Context context) { 
  32.         this.mContext = context; 
  33.     } 
  34.  
  35.     /** 
  36.      * 写信件 
  37.      * @param fileName 
  38.      * @param letterContent 
  39.      * @return 
  40.      */ 
  41.     public PixelMap writeLetter(String fileName, String letterContent) { 
  42.         // 获取分布式文件路径 
  43.         String filePath = mContext.getDistributedDir() + File.separator + fileName + ".jpg"
  44.         Texture texture=null
  45.         try { 
  46.             // 从资源文件获取信纸背景图片 
  47.             InputStream inputStream = mContext.getResourceManager().getResource(ResourceTable.Media_bg); 
  48.             ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions(); 
  49.             srcOpts.formatHint = "image/jpeg"
  50.             ImageSource imageSource = ImageSource.create(inputStream, srcOpts); 
  51.             // 设置图片参数 
  52.             ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions(); 
  53.             decodingOptions.desiredSize=new Size(720,1080); 
  54.             PixelMap pixelMap = imageSource.createPixelmap(decodingOptions); 
  55.             //用于保存画图结果 
  56.             texture=new Texture(pixelMap); 
  57.             Canvas canvas=new Canvas(texture); 
  58.             Paint paint=new Paint(); 
  59.             paint.setTextSize(50); 
  60.             paint.setStrokeWidth(8); 
  61.             paint.setColor(Color.BLACK); 
  62.             // 把内容写到信纸上 
  63.             canvas.drawChars(paint,letterContent.toCharArray(),50,140); 
  64.             // 文件输出流 
  65.             FileOutputStream fos=new FileOutputStream(filePath); 
  66.  
  67.             ImagePacker imagePacker = ImagePacker.create(); 
  68.             ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions(); 
  69.             packingOptions.format = "image/jpeg";//只支持image/jpeg 
  70.             packingOptions.quality = 90; 
  71.             boolean result = imagePacker.initializePacking(fos, packingOptions); 
  72.             if(result) 
  73.             { 
  74.                 //这里获取绘画后的pixelMap用来保存 
  75.                 result = imagePacker.addImage(texture.getPixelMap()); 
  76.                 if (result) { 
  77.                     long dataSize = imagePacker.finalizePacking(); 
  78.                     System.out.println("文件大小:"+dataSize); 
  79.                     ToastUtil.getInstance().showToast(mContext, "创建成功!"); 
  80.                 } 
  81.             } 
  82.  
  83.             fos.flush(); 
  84.             fos.close(); 
  85.         } catch (IOException | NotExistException e) { 
  86.             System.out.println("文件保存出错:"+e.getMessage()); 
  87.             e.printStackTrace(); 
  88.         } 
  89.          
  90.         return texture.getPixelMap(); 
  91.     } 
  92.  
  93.     /** 
  94.      * 读取信件 
  95.      * @param fileName 
  96.      * @param letterContent 
  97.      * @return 
  98.      */ 
  99.     public PixelMap readImage(String fileName, String letterContent) { 
  100.         // 获取分布式文件路径 
  101.         String filePath = mContext.getDistributedDir() + File.separator + fileName; 
  102.         // 根据分布式文件路径,生成文件 
  103.         File file = new File(filePath); 
  104.         if (!file.exists()) { 
  105.             // 如果文件不存在, 调用写信件 
  106.             writeLetter(fileName, letterContent); 
  107.         } 
  108.         // 图片参数 
  109.         ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions(); 
  110.         srcOpts.formatHint = "image/jpeg"
  111.         // 创建图片源 
  112.         ImageSource imageSource = ImageSource.create(file, srcOpts); 
  113.         // 生成图片 
  114.         PixelMap pixelMap = imageSource.createPixelmap(null); 
  115.  
  116.         return pixelMap; 
  117.     } 
  118.  
  119.     /** 
  120.      * 获取文件列表 
  121.      * @return 
  122.      */ 
  123.     public List<String> getFileList() { 
  124.         // 获取分布式文件列表 
  125.         File[] files = mContext.getDistributedDir().listFiles(); 
  126.         List<File> listFile = new ArrayList<>(Arrays.asList(files)); 
  127.         // 排序文件顺序 
  128.         listFile.sort((file, newFile) -> { 
  129.             if (file.lastModified() > newFile.lastModified()) { 
  130.                 return -1; 
  131.             } else if (file.lastModified() == newFile.lastModified()) { 
  132.                 return 0; 
  133.             } else { 
  134.                 return 1; 
  135.             } 
  136.         }); 
  137.         List<String> listFileName = new ArrayList<>(); 
  138.         // 获取文件列表文件名 
  139.         for (File f : listFile) { 
  140.             if (f.isFile()) { 
  141.                 String name = f.getName(); 
  142.                 listFileName.add(name); 
  143.             } 
  144.         } 
  145.         return listFileName; 
  146.     } 

ToastUtil 提示信息框:

  1. package com.army.study.util; 
  2.  
  3.  
  4. import com.army.study.ResourceTable; 
  5. import ohos.agp.components.Component; 
  6. import ohos.agp.components.LayoutScatter; 
  7. import ohos.agp.components.Text; 
  8. import ohos.agp.window.dialog.ToastDialog; 
  9. import ohos.app.Context; 
  10.  
  11. /** 
  12.  * Toast工具类 
  13.  * 
  14.  */ 
  15. public class ToastUtil { 
  16.     private ToastDialog toastDialog; 
  17.  
  18.     private ToastUtil() { 
  19.     } 
  20.  
  21.     public static ToastUtil getInstance() { 
  22.         return ToastUtilInstance.INSTANCE; 
  23.     } 
  24.  
  25.     private static class ToastUtilInstance { 
  26.         private static final ToastUtil INSTANCE = new ToastUtil(); 
  27.     } 
  28.  
  29.     /** 
  30.      * 显示Toast 
  31.      * 
  32.      * @param context 
  33.      * @param content 
  34.      */ 
  35.     public void showToast(Context context, String content) { 
  36.         if (toastDialog != null && toastDialog.isShowing()) { 
  37.             toastDialog.cancel(); 
  38.         } 
  39.  
  40.         Component toastLayout = LayoutScatter.getInstance(context) 
  41.                 .parse(ResourceTable.Layout_layout_toast, nullfalse); 
  42.         Text toastText = (Text) toastLayout.findComponentById(ResourceTable.Id_text_msg_toast); 
  43.         toastText.setText(content); 
  44.         toastDialog = new ToastDialog(context); 
  45.         toastDialog.setComponent(toastLayout); 
  46.         toastDialog.setTransparent(true); 
  47.         toastDialog.show(); 
  48.     } 

预览信件内容:

  1. /** 
  2.  * 预览信件内容 
  3.  */ 
  4. public class PreviewLetterDialog extends CommonDialog { 
  5.  
  6.     public PreviewLetterDialog(Context context, PixelMap imgId) { 
  7.         super(context); 
  8.         Component container = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_dialog_previce_letter, nullfalse); 
  9.         setContentCustomComponent(container); 
  10.         setSize(MATCH_PARENT, MATCH_CONTENT); 
  11.  
  12.         setCornerRadius(AttrHelper.vp2px(20, context)); 
  13.  
  14.         Image image = (Image) container.findComponentById(ResourceTable.Id_preview); 
  15.         image.setPixelMap(imgId); 
  16.  
  17.  
  18.         Button btnCancel = (Button) container.findComponentById(ResourceTable.Id_button_dialog_create_file_cancel); 
  19.         Button btnConfirm = (Button) container.findComponentById(ResourceTable.Id_button_dialog_create_file_confirm); 
  20.  
  21.         btnCancel.setClickedListener(component -> { destroy();}); 
  22.         btnConfirm.setClickedListener(component -> { destroy();}); 
  23.     } 
  24.  

写信件对话框:

  1. /** 
  2.  * 写信件对话框 
  3.  */ 
  4. public class CreateLetterDialog extends CommonDialog { 
  5.     private OnCallBack onCallBack; 
  6.  
  7.     public CreateLetterDialog(Context context) { 
  8.         super(context); 
  9.         Component container = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_dialog_write_letter, nullfalse); 
  10.         setContentCustomComponent(container); 
  11.  
  12.         Optional<Display> display = DisplayManager.getInstance().getDefaultDisplay(context); 
  13.         int width = (int) (display.get().getAttributes().width * 0.9); 
  14.         int height = AttrHelper.vp2px(270, context); 
  15.         setSize(width, height); 
  16.         setCornerRadius(AttrHelper.vp2px(20, context)); 
  17.  
  18.         TextField letterContent = (TextField) container.findComponentById(ResourceTable.Id_tf_dialog_create_file_name); 
  19.         Button btnCancel = (Button) container.findComponentById(ResourceTable.Id_button_dialog_create_file_cancel); 
  20.         Button btnConfirm = (Button) container.findComponentById(ResourceTable.Id_button_dialog_create_file_confirm); 
  21.         btnConfirm.setEnabled(false); 
  22.         btnConfirm.setAlpha(0.5f); 
  23.         letterContent.addTextObserver((text, i, i1, i2) -> { 
  24.             if(text.isEmpty()){ 
  25.                 btnConfirm.setEnabled(false); 
  26.                 btnConfirm.setAlpha(0.5f); 
  27.             }else
  28.                 btnConfirm.setEnabled(true); 
  29.                 btnConfirm.setAlpha(1f); 
  30.             } 
  31.         }); 
  32.  
  33.         btnCancel.setClickedListener(component -> { destroy();}); 
  34.  
  35.         btnConfirm.setClickedListener(component -> { 
  36.             if(onCallBack!=null){ 
  37.                 // 设备ID 
  38.                 String deviceID = KvManagerFactory.getInstance().createKvManager(new KvManagerConfig(context)) 
  39.                         .getLocalDeviceInfo().getId(); 
  40.                 // 组合文件名,方便区分是否为当前设备创造的文件 
  41.                 String name = deviceID + "-" + letterContent.getText(); 
  42.                 onCallBack.onConfirm(name); 
  43.             } 
  44.             destroy(); 
  45.         }); 
  46.     } 
  47.  
  48.     public void setOnCallBack(OnCallBack onCallBack) { 
  49.         this.onCallBack = onCallBack; 
  50.     } 
  51.  
  52.     public interface OnCallBack { 
  53.         void onConfirm(String name); 
  54.     } 

 主界面代码图:

基于鸿蒙分布式跨设备文件服务-信件管理-鸿蒙HarmonyOS技术社区

讲解到此了,不要忘记了config.json文件的权限配置哦,在module下添加

  1. "reqPermissions": [ 
  2.     { 
  3.       "name""ohos.permission.DISTRIBUTED_DATASYNC" 
  4.     }, 
  5.     { 
  6.       "name""ohos.permission.GET_DISTRIBUTED_DEVICE_INFO" 
  7.     }, 
  8.     { 
  9.       "name""ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE" 
  10.     }, 
  11.     { 
  12.       "name""ohos.permission.WRITE_MEDIA" 
  13.     }, 
  14.     { 
  15.       "name""ohos.permission.READ_MEDIA" 
  16.     } 
  17.   ], 

 想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2021-08-13 13:53:23

鸿蒙HarmonyOS应用

2020-11-13 12:09:46

HarmonyOS

2023-05-29 14:07:00

Zuul网关系统

2022-02-17 18:08:04

OpenHarmon应用开发鸿蒙

2014-12-08 10:02:46

Docker开源跨容器服务

2017-10-24 11:28:23

Zookeeper分布式锁架构

2015-04-21 09:39:03

javajava分布式爬虫

2023-12-29 08:18:31

Session分布式系统微服务

2023-11-20 15:32:29

2010-11-01 05:50:46

分布式文件系统

2011-07-26 09:57:02

分布式网络管理带外网络

2017-10-17 08:33:31

存储系统分布式

2017-03-14 11:52:52

微服务架构数据管理

2022-03-08 15:24:23

BitMapRedis数据

2020-07-15 09:20:48

MyCatMySQL分布式

2017-04-13 10:51:09

Consul分布式

2021-08-16 09:55:41

鸿蒙HarmonyOS应用

2022-04-24 16:00:03

Ability鸿蒙

2019-01-28 11:03:03

NginxFastDFS服务器

2019-10-10 09:16:34

Zookeeper架构分布式
点赞
收藏

51CTO技术栈公众号