getPublicStorage("Pictures") 未列出任何文件

ton*_*oni 1 javafx gluon-mobile

呼唤

File picturesDir = Services.get(StorageService.class)
            .flatMap(s -> s.getPublicStorage("Pictures"))
            .orElseThrow(() -> new RuntimeException("Error retrieving public storage")); 
for (File pic : picturesDir.listFiles()) {
        System.out.println("file " + pic.getName());
}
Run Code Online (Sandbox Code Playgroud)

没有列出任何文件。我认为它应该列出 iPhone 上我的图片库中的所有文件。

调用 s.getPublicStorage("") 它会列出两个文件夹:gluon、Pictures。

我怎样才能正确访问它?

Jos*_*eda 6

正如本问题前面所讨论的,在移动设备上没有 Swing 或 AWT,因此一旦您拥有 JavaFX 图像,就无法使用它来检索它SwingFXUtils

上述问题中提出的解决方案适用于 Android,因为您可以轻松获取该文件。相反,在 iOS 上,该文件位于图库中,并且当前的 Charm DownPicturesService无法访问图库。

从 JavaFX 获取可以发送到 Web 服务的 byteArray 的想法基于两个步骤,而不是修改该服务(使用像这样的本机代码) :Image

  • 获取图像像素作为字节数组
  • 将字节数组编码为字符串。

如果您检查 iOS 实现,就会发现来自 iOS 本机层的图像通过 Base64编码解码PicturesService::takePhoto发送到 JavaFX 层。

解决方案1

这个代码片段对我有用:

// Take a photo and add image to imageView
Button button = new Button("Take Photo");
button.setOnAction(e ->
    Services.get(PicturesService.class)
        .ifPresent(s -> s.takePhoto(false).ifPresent(imageView::setImage)));

// Encode image
imageView.imageProperty().addListener((obs, ov, image) -> {
    if (image != null) {
        // 1. image to byte array
        PixelReader pixelReader = image.getPixelReader();
        int width = (int) image.getWidth(); 
        int height = (int) image.getHeight(); 
        byte[] buffer = new byte[width * height * 4]; 
        pixelReader.getPixels(0, 0, width, height, PixelFormat.getByteBgraInstance(), buffer, 0, width * 4); 

        // 2. Encode to String
        String encoded = Base64.getEncoder().encodeToString(buffer);

        // 3. send string...
    }
} 
Run Code Online (Sandbox Code Playgroud)

您可以通过颠倒这些步骤并根据编码字符串创建图像来检查该过程是否有效:

byte[] imageBytes = Base64.getDecoder().decode(encoded.getBytes(StandardCharsets.UTF_8));

WritablePixelFormat<ByteBuffer> wf = PixelFormat.getByteBgraInstance();
WritableImage writableImage = new WritableImage(width, height);
PixelWriter pixelWriter = writableImage.getPixelWriter();
pixelWriter.setPixels(0, 0, width, height, wf, imageBytes, 0, width * 4);

imageView.setImage(writableImage);
Run Code Online (Sandbox Code Playgroud)

解决方案2

如果您想将字节数组从 转换PixelReader::getPixels为 a BufferedImage,这是行不通的:字节数组是不同的。

因此,您需要使用缓冲图像能够处理的东西。

看一下实现SwingFXUtils,它使用了一个 int 数组。

所以这是另一种可能性:

// Take a photo and add image to imageView
Button button = new Button("Take Photo");
button.setOnAction(e ->
    Services.get(PicturesService.class)
        .ifPresent(s -> s.takePhoto(false).ifPresent(imageView::setImage)));

// Encode image
imageView.imageProperty().addListener((obs, ov, image) -> {
    if (image != null) {
        // 1. image to int array
        PixelReader pixelReader = image.getPixelReader();
        int width = (int) image.getWidth(); 
        int height = (int) image.getHeight(); 
        int[] data = new int[width * height]; 
        pixelReader.getPixels(0, 0, width, height, PixelFormat.getIntArgbPreInstance(), data, 0, width); 

        // 2. int array to byte array
        ByteBuffer byteBuffer = ByteBuffer.allocate(data.length * 4);        
        IntBuffer intBuffer = byteBuffer.asIntBuffer();
        intBuffer.put(data);


        // 3. Encode to String
        String encoded = Base64.getEncoder().encodeToString(byteBuffer.array());

        // 4. send string...
    }
} 
Run Code Online (Sandbox Code Playgroud)

现在您必须解码字符串,获取 int 数组并创建缓冲图像:

// 1. Decode string
byte[] imageBytes = Base64.getDecoder().decode(encoded.getBytes(StandardCharsets.UTF_8));

// 2. get int array
ByteBuffer byteBuffer2 = ByteBuffer.wrap(imageBytes);
IntBuffer intBuffer2 = byteBuffer2.asIntBuffer();
int[] imageData = new int[intBuffer2.limit()];
intBuffer2.get(imageData);

// 3. create buffered image
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
bufferedImage.setRGB(0, 0, width, height, imageData, 0, width);
Run Code Online (Sandbox Code Playgroud)