首页 文章

在Gluon Mobile中访问图像文件夹

提问于
浏览
1

我知道为了获得一个名字已知的单个图像我可以使用

getClass().getResource()..

但是,如果我在特定文件夹中有很多图像怎么办?我不想采用每个图像名称并调用getResource()方法 .

The following works on Desktop, but causes a crash on Android

public void initializeImages() {

        String platform = "android";

        if(Platform.isIOS())
        {
            platform = "ios";
        } else if(Platform.isDesktop())
        {
            platform = "main";
        }

        String path = "src/" + platform + "/resources/com/mobileapp/images/";


        File file = new File(path);
        File[] allFiles = file.listFiles();

        for (int i = 0; i < allFiles.length; i++) {
            Image img = null;
            try {
                img = ImageIO.read(allFiles[i]);
                files.add(createImage(img));
            } catch (IOException ex) {
                Logger.getLogger(ImageGroupRetriever.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

    }

 //Taken from a separate SO question. Not causing any issues
 public static javafx.scene.image.Image createImage(java.awt.Image image) throws IOException {
        if (!(image instanceof RenderedImage)) {
            BufferedImage bufferedImage = new BufferedImage(image.getWidth(null),
                    image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
            Graphics g = bufferedImage.createGraphics();
            g.drawImage(image, 0, 0, null);
            g.dispose();

            image = bufferedImage;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write((RenderedImage) image, "png", out);
        out.flush();
        ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
        return new javafx.scene.image.Image(in);
    }

我还需要在目录结构中考虑一些其他内容吗?

1 回答

  • 2

    如果您在Android上运行该代码,您将看到使用 adb logcat -v threadtime 的异常:

    Caused by: java.lang.NullPointerException: Attempt to get length of null array
    

    在for循环中调用 allFiles.length 的行 .

    在Android上,如果将图像复制到 src/android/resources ,则可能会有所不同 .

    如果你检查build / javafxports / android /文件夹,你会看到图像只是放在 com.mobileapp.images 下面 .

    这就是通常的 getClass().getResource("/com/mobileapp/images/<image.png>") 的原因 .

    您可以做的是将包含所有图像的zip文件添加到已知位置 . 然后使用Charm Down Storage插件将zip复制到Android上应用程序的私人文件夹,提取图像,最后您将能够在设备的专用路径上使用 File.listFiles .

    这适用于我,假设您在 com/mobileapp/images 下有一个名为 images.zip 的邮箱,其中包含所有文件:

    private List<Image> loadImages() {
        List<Image> list = new ArrayList<>();
    
        // 1 move zip to storage
        File dir;
        try {
            dir = Services.get(StorageService.class)
                    .map(s -> s.getPrivateStorage().get())
                    .orElseThrow(() -> new IOException("Error: PrivateStorage not available"));
    
            copyZip("/com/mobileapp/images/", dir.getAbsolutePath(), "images.zip");
        } catch (IOException ex) {
            System.out.println("IO error " + ex.getMessage());
            return list;
        }
    
        // 2 unzip
        try {
            unzip(new File(dir, "images.zip"), new File(dir, "images"));
        } catch (IOException ex) {
            System.out.println("IO error " + ex.getMessage());
        }
    
        // 3. load images
        File images = new File(dir, "images");
        for (int i = 0; i < images.listFiles().length; i++) {
            try {
                list.add(new Image(new FileInputStream(images.listFiles()[i])));
            } catch (FileNotFoundException ex) {
                System.out.println("Error " + ex.getMessage());
            }
    
        }
        return list;
    }
    
    public static void copyZip(String pathIni, String pathEnd, String name)  {
        try (InputStream myInput = BasicView.class.getResourceAsStream(pathIni + name)) {
            String outFileName =  pathEnd + "/" + name;
            try (OutputStream myOutput = new FileOutputStream(outFileName)) {
                byte[] buffer = new byte[1024];
                int length;
                while ((length = myInput.read(buffer)) > 0) {
                    myOutput.write(buffer, 0, length);
                }
                myOutput.flush();
    
            } catch (IOException ex) {
                System.out.println("Error " + ex);
            }
        } catch (IOException ex) {
            System.out.println("Error " + ex);
        }
    }
    
    public static void unzip(File zipFile, File targetDirectory) throws IOException {
        try (ZipInputStream zis = new ZipInputStream(
                new BufferedInputStream(new FileInputStream(zipFile)))) {
            ZipEntry ze;
            int count;
            byte[] buffer = new byte[8192];
            while ((ze = zis.getNextEntry()) != null) {
                File file = new File(targetDirectory, ze.getName());
                File dir = ze.isDirectory() ? file : file.getParentFile();
                if (!dir.isDirectory() && !dir.mkdirs())
                    throw new FileNotFoundException("Failed to ensure directory: " + dir.getAbsolutePath());
                if (ze.isDirectory())
                    continue;
                try (FileOutputStream fout = new FileOutputStream(file)) {
                    while ((count = zis.read(buffer)) != -1)
                        fout.write(buffer, 0, count);
                }
            }
        }
    }
    

    请注意,这在桌面和iOS上也可以正常工作 .

    unzip 方法基于此answer .

相关问题