Need help to build app Compress multiple images and auto zipping them - Kotlin Android

92 Views Asked by At

I am a beginner in Android app development with the Kotlin language. I have written some simple apps, and now I am planning to write an app that allows users to compress multiple images which are stored in the internal memory (in JPG format), at a custom compression rate (entered in EditText), and then automatically compress all of these images into a zip file for easy attachment to email or sharing. The compressed and zipped image files are saved to a custom folder. Due to my lack of experience, I would appreciate your guidance on where to start. Thank you very much.

I have tried following some instructions on the internet, but when I run them, I get an error message, or the program only allows me to compress one image at a time.

2

There are 2 best solutions below

0
Ankit Dubey On

You can try below code snippet for compressing multiple files.

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipHelper {

    public static void compressFiles(String zipFilePath, String[] sourceFiles) throws IOException {
        try (ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFilePath)))) {
            byte[] buffer = new byte[1024];
            for (String filePath : sourceFiles) {
                try (BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(filePath))) {
                    ZipEntry zipEntry = new ZipEntry(getFileNameFromPath(filePath));
                    zipOutputStream.putNextEntry(zipEntry);
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        zipOutputStream.write(buffer, 0, bytesRead);
                    }
                    zipOutputStream.closeEntry();
                }
            }
        }
    }

    private static String getFileNameFromPath(String filePath) {
        // Extract the file name from the full path
        int lastSeparator = filePath.lastIndexOf("/");
        return (lastSeparator == -1) ? filePath : filePath.substring(lastSeparator + 1);
    }
}

Below is the sample code use above method.

String[] filesToCompress = new String[]{"/path/to/file1.txt", "/path/to/file2.txt", "/path/to/file3.png"};
String zipFilePath = "/path/to/archive.zip";

try {
    ZipHelper.compressFiles(zipFilePath, filesToCompress);
    // Compression completed successfully
} catch (IOException e) {
    e.printStackTrace();
    // Handle compression error
}

Hope it helps. Ankit

0
Flamingo On

Thank @Ankit Dubey, this my code for function createZipFile, but it not works. The error message is "open failed:EPERM(operation not permissted)", even though I have given the app full memory read/write permissions.

private val zipLock = Object()
    private suspend fun createZipFile(imageFiles: List<File>) {
        withContext(Dispatchers.IO) {
            try {
                synchronized(zipLock) {
                    val currentTime = System.currentTimeMillis()
                    zipFileName = "Images_${currentTime}.zip"
                    val zipFilePath = File(getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), zipFileName)
                    ZipOutputStream(BufferedOutputStream(FileOutputStream(zipFilePath))).use { zipOut ->
                        for (imageFile in imageFiles) {
                            val zipEntry = ZipEntry(imageFile.name)
                            zipOut.putNextEntry(zipEntry)

                            val input = BufferedInputStream(FileInputStream(imageFile))
                            val data = ByteArray(2048)
                            var count: Int
                            while (input.read(data, 0, 2048).also { count = it } != -1) {
                                zipOut.write(data, 0, count)
                            }

                            input.close()
                            zipOut.closeEntry()
                        }
                    }
                }

                withContext(Dispatchers.Main) {
                    Toast.makeText(
                        this@MainActivity,
                        "Files have been successfully packed: ${zipFileName}",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            } catch (e: Exception) {
                e.printStackTrace()
                withContext(Dispatchers.Main) {
                    Toast.makeText(this@MainActivity, "Files have been unsuccessfully packed: ${e.message}", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }