使用 Gluon ShareService 共享多个文件(图片和 txt)

Sharing multiple files with Gluon ShareService (image and txt)

我们想知道如何使用 Gluon ShareService 共享多个文件(图像和 txt 文件)。特别是如何使用 PictureService 共享以前拍摄和存储(在图库中)的图像。

但是我们需要先用路径和图像名称创建一个文件。遗憾的是,PictureService 保存的图像的图像标题包含拍摄照片时的日期和时间。

我们尝试使用 loadImageFromGallery 方法获取图像名称,但此 returns 无效并打开 recent-screen.

这是我们尝试分享的图片:

public void sharePicture() {
    Services.get(PicturesService.class).ifPresent(picturesService -> {
          Image image = picturesService.loadImageFromGallery().get();
      File file= new File("Pictures", image.toString());
      Services.get(ShareService.class).ifPresent(service -> {
        service.share("image/jpg", file);
      });
    });
  }

您走在正确的轨道上,结合来自 Charm Down 的不同服务,以便 select 来自画廊的图像并分享它。

不过,这种方法存在一个主要问题:您无法轻松地将 JavaFX Image 转换为 File

到目前为止 PicturesService return 只是一个 JavaFX 图像,而不是一个文件,因此我们需要一种方法将该图像保存到一个我们可以读取和共享的文件中。

这个过程并不容易,因为在移动设备上我们没有 SwingUtilities

最初使用 PixelReader 读取图像并获取字节数组的方法实际上并不奏效,因为它会给您一个无法读取或共享的大原始文件。

我使用了这个 solution,它利用 PNG 编码器从 JavaFX 图像中获取 png 的字节数组:

PngEncoderFX encoder = new PngEncoderFX(image, true);
byte[] bytes = encoder.pngEncode();

然后我将该字节数组保存到 public 存储文件夹中的一个文件中(以便共享),我可以使用 `StorageService:

检索该文件
private File getImageFile(Image image) {
    if (image == null) {
        return null;
    }

    // 1. Encode image to png
    PngEncoderFX encoder = new PngEncoderFX(image, true);
    byte[] bytes = encoder.pngEncode();

    // 2.Write byte array to a file in public storage 
    File root = Services.get(StorageService.class)
            .flatMap(storage -> storage.getPublicStorage("Pictures"))
            .orElse(null);
    if (root != null) {
        File file = new File(root, "Image-" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("uuuuMMdd-HHmmss")) + ".png");
        try (FileOutputStream fos = new FileOutputStream(file)) {
            fos.write(bytes);
            return file;
        } catch (IOException ex) {
            System.out.println("Error: " + ex);
        }
    }
    return null;
}

现在,您可以调用 PicturesService,检索图像,将其保存到文件中,最后 share 它:

Services.get(PicturesService.class).ifPresent(pictures -> {
    // 1. Retrieve picture from gallery
    pictures.loadImageFromGallery().ifPresent(image -> {
        // 2. Convert image to file
        File imageFile = getImageFile(image);

        // 3. Share file
        if (imageFile != null) {
            Services.get(ShareService.class).ifPresent(share -> {
                share.share("image/png", imageFile);
            });
        }
    });
});

请注意,如果您尝试对大图像进行编码,可能 运行 会出现内存问题。

无论如何,如果 PicturesService 首先 return 一个文件,所有过程都可以简化。如果您想提出问题,可以 here.

编辑

避免内存问题并减小共享文件大小的可能解决方案,基于此 ,正在缩小原始图像,如果它超过一定大小,就像它已经是在 PicturesService 的 iOS 实现中完成:

private Image scaleImage(Image source) {
    // Possible limit based on memory limitations
    double maxResolution = 1280; 

    double width = source.getWidth();
    double height = source.getHeight();
    double targetWidth = width;
    double targetHeight = height;
    if (width > maxResolution || height > maxResolution) {
        double  ratio = width/height;
        if (ratio > 1) {
            targetWidth = maxResolution;
            targetHeight = targetWidth/ ratio;
        }
        else {
            targetHeight = maxResolution;
            targetWidth = targetHeight * ratio;
        }
    }

    ImageView imageView = new ImageView(source);
    imageView.setPreserveRatio(true);
    imageView.setFitWidth(targetWidth);
    imageView.setFitHeight(targetHeight);
    return imageView.snapshot(null, null);
}

此方法现在可以在getImageFile()中使用:

    // 1 Scale image to avoid memory issues
    Image scaledImage = scaleImage(image);

    // 2. Encode image to png
    PngEncoderFX encoder = new PngEncoderFX(scaledImage, true);
    byte[] bytes = encoder.pngEncode();

    // 3. Write byte array to a file in public storage 
    ...