0

I have to decrypt image and load it to ImageView by means of Glide with a constraint to do not save decrypted images on the disk. As I know Glide has an opportunity to do that with DataFetcher. As an example of a DataFetcher usage I would like do load an image from a zip file first.

A have read Writing a custom ModelLoader and on the base of author's repository I have created my own repository with an attempt to rewrite the code for the case of unzipping a single picture zip file inside of DataFetcher.loadData method and load it to ImageView.

public class FileDataFetcher implements DataFetcher<InputStream> {
    private final FileEnveloper fileEnveloper;

    FileDataFetcher(FileEnveloper fileEnveloper) {
        this.fileEnveloper = fileEnveloper;
    }

    @Override
    public void loadData(@NonNull Priority priority, DataCallback<? super InputStream> callback) {
        try {
            unzip(); //Works fine!

            FileInputStream fin = new FileInputStream(fileEnveloper.getFile());
            ZipInputStream zin = new ZipInputStream(fin);
            callback.onDataReady(zin);
        } catch (IOException e) {
            e.printStackTrace();
            callback.onLoadFailed(e);
        }
    }

    @Override
    public void cleanup() {
        // Intentionally empty only because we're not opening an InputStream or another I/O resource!
    }

    @Override
    public void cancel() {
        // Intentionally empty.
    }

    @NonNull
    @Override
    public Class<InputStream> getDataClass() {
        return InputStream.class;
    }

    @NonNull
    @Override
    public DataSource getDataSource() {
        return DataSource.LOCAL;
    }

    private void unzip() throws IOException {
        String location = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator ;
        FileInputStream fin = new FileInputStream(fileEnveloper.getFile());
        ZipInputStream zin = new ZipInputStream(fin);
        ZipEntry ze;
        while ((ze = zin.getNextEntry()) != null) {
            if (ze.isDirectory()) {
                File dir = new File(location + ze.getName());
                if (!dir.exists() || !dir.isDirectory())
                    dir.mkdirs();
            } else {
                FileOutputStream fout = new FileOutputStream(location + ze.getName());
                byte[] buffer = new byte[1024];
                int read = 0;
                while ((read = zin.read(buffer)) != -1) {
                    fout.write(buffer, 0, read);
                }
                zin.closeEntry();
                fout.close();
            }
        }
        zin.close();
    }
}

Method unzip() works fine and desired unzipped picture appears on the disk, but callback.onDataReady(zin) leads to the stack trace:

2019-12-22 13:57:22.605 28803-28803/judds.github.com.base64modelloaderexample W/Glide: Load failed for judds.github.com.base64modelloaderexample.FileEnveloper@2d3a6e1c with size [720x1257]
class com.bumptech.glide.load.engine.GlideException: Failed to load resource
  Cause (1 of 1): class com.bumptech.glide.load.engine.GlideException: Failed LoadPath{ZipInputStream->Object->Drawable}, LOCAL
    Cause (1 of 3): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{ZipInputStream->GifDrawable->Drawable}
    Cause (2 of 3): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{ZipInputStream->Bitmap->Drawable}
    Cause (3 of 3): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{ZipInputStream->BitmapDrawable->Drawable}

I suppose the reason is not in Glide but in the wrong usage of ZipInputStream with Glide. Does anybody know how it should be done?

Zoe
  • 27,060
  • 21
  • 118
  • 148
isabsent
  • 3,683
  • 3
  • 25
  • 46

1 Answers1

0

To get it work (for single file in zip-archive) we have to set ZipInputStream in the initial position with zin.getNextEntry() as follows:

@Override
public void loadData(@NonNull Priority priority, DataCallback<? super InputStream> callback) {
    try {
        unzip(); //Works fine!

        FileInputStream fin = new FileInputStream(fileEnveloper.getFile());
        ZipInputStream zin = new ZipInputStream(fin);
        zin.getNextEntry();//Essential!!!
        callback.onDataReady(zin);
    } catch (IOException e) {
        e.printStackTrace();
        callback.onLoadFailed(e);
    }
}
isabsent
  • 3,683
  • 3
  • 25
  • 46