Swati4star/Images-to-PDF

View on GitHub
app/src/main/java/swati4star/createpdf/util/FileUtils.java

Summary

Maintainability
A
2 hrs
Test Coverage
package swati4star.createpdf.util;

import static swati4star.createpdf.util.Constants.AUTHORITY_APP;
import static swati4star.createpdf.util.Constants.PATH_SEPERATOR;
import static swati4star.createpdf.util.Constants.STORAGE_LOCATION;
import static swati4star.createpdf.util.Constants.pdfExtension;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.print.PrintDocumentAdapter;
import android.print.PrintManager;
import android.provider.MediaStore;

import androidx.core.content.FileProvider;

import com.afollestad.materialdialogs.MaterialDialog;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import swati4star.createpdf.R;
import swati4star.createpdf.database.DatabaseHelper;
import swati4star.createpdf.util.lambda.Consumer;

public class FileUtils {

    private final Activity mContext;
    private final SharedPreferences mSharedPreferences;

    public FileUtils(Activity context) {
        this.mContext = context;
        mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
    }

    /**
     * Extracts file name from the path
     *
     * @param path - file path
     * @return - extracted filename
     */
    public static String getFileName(String path) {
        if (path == null)
            return null;

        int index = path.lastIndexOf(PATH_SEPERATOR);
        return index < path.length() ? path.substring(index + 1) : null;
    }

    /**
     * Extracts file name from the URI
     *
     * @param path - file path
     * @return - extracted filename without extension
     */
    public static String getFileNameWithoutExtension(String path) {
        if (path == null || path.lastIndexOf(PATH_SEPERATOR) == -1)
            return path;

        String filename = path.substring(path.lastIndexOf(PATH_SEPERATOR) + 1);
        filename = filename.replace(pdfExtension, "");

        return filename;
    }

    /**
     * Extracts directory path from full file path
     *
     * @param path absolute path of the file
     * @return absolute path of file directory
     */
    public static String getFileDirectoryPath(String path) {
        return path.substring(0, path.lastIndexOf(PATH_SEPERATOR) + 1);
    }

    /**
     * Prints a file
     *
     * @param file the file to be printed
     */
    public void printFile(final File file) {
        final PrintDocumentAdapter mPrintDocumentAdapter = new PrintDocumentAdapterHelper(file);

        PrintManager printManager = (PrintManager) mContext
                .getSystemService(Context.PRINT_SERVICE);
        String jobName = mContext.getString(R.string.app_name) + " Document";
        if (printManager != null) {
            printManager.print(jobName, mPrintDocumentAdapter, null);
            new DatabaseHelper(mContext).insertRecord(file.getAbsolutePath(), mContext.getString(R.string.printed));
        }
    }

    /**
     * Emails the desired PDF using application of choice by user
     *
     * @param file - the file to be shared
     */
    public void shareFile(File file) {
        Uri uri = FileProvider.getUriForFile(mContext, AUTHORITY_APP, file);
        ArrayList<Uri> uris = new ArrayList<>();
        uris.add(uri);
        shareFile(uris);
    }

    /**
     * Share the desired PDFs using application of choice by user
     *
     * @param files - the list of files to be shared
     */
    public void shareMultipleFiles(List<File> files) {
        ArrayList<Uri> uris = new ArrayList<>();
        for (File file : files) {
            Uri uri = FileProvider.getUriForFile(mContext, AUTHORITY_APP, file);
            uris.add(uri);
        }
        shareFile(uris);
    }

    /**
     * Emails the desired PDF using application of choice by user
     *
     * @param uris - list of uris to be shared
     */
    private void shareFile(ArrayList<Uri> uris) {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_SEND_MULTIPLE);
        intent.putExtra(Intent.EXTRA_TEXT, mContext.getString(R.string.i_have_attached_pdfs_to_this_message));
        intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setType(mContext.getString(R.string.pdf_type));
        mContext.startActivity(Intent.createChooser(intent,
                mContext.getResources().getString(R.string.share_chooser)));
    }

    /**
     * opens a file in appropriate application
     *
     * @param path - path of the file to be opened
     */
    public void openFile(String path, FileType fileType) {
        if (path == null) {
            StringUtils.getInstance().showSnackbar(mContext, R.string.error_path_not_found);
            return;
        }
        openFileInternal(path, fileType == FileType.e_PDF ?
                mContext.getString(R.string.pdf_type) : mContext.getString(R.string.txt_type));
    }

    /**
     * This function is used to open the created file
     * applications on the device.
     *
     * @param path - file path
     */
    private void openFileInternal(String path, String dataType) {
        File file = new File(path);
        Intent target = new Intent(Intent.ACTION_VIEW);
        target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
        try {
            Uri uri = FileProvider.getUriForFile(mContext, AUTHORITY_APP, file);

            target.setDataAndType(uri, dataType);
            target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            openIntent(Intent.createChooser(target, mContext.getString(R.string.open_file)));
        } catch (Exception e) {
            StringUtils.getInstance().showSnackbar(mContext, R.string.error_open_file);
        }
    }

    /**
     * Checks if the new file already exists.
     *
     * @param finalOutputFile Path of pdf file to check
     * @param mFile           File List of all PDFs
     * @return Number to be added finally in the name to avoid overwrite
     */
    private int checkRepeat(String finalOutputFile, final List<File> mFile) {
        boolean flag = true;
        int append = 0;
        while (flag) {
            append++;
            String name = finalOutputFile.replace(mContext.getString(R.string.pdf_ext),
                    append + mContext.getString(R.string.pdf_ext));
            flag = mFile.contains(new File(name));
        }

        return append;
    }

    /**
     * Get real image path from uri.
     *
     * @param uri - uri of the image
     * @return - real path of the image file on device
     */
    public String getUriRealPath(Uri uri) {
        if (uri == null || FileUriUtils.getInstance().isWhatsappImage(uri.getAuthority()))
            return null;

        return FileUriUtils.getInstance().getUriRealPathAboveKitkat(mContext, uri);
    }

    /***
     * Check if file already exists in pdf_dir
     * @param mFileName - Name of the file
     * @return true if file exists else false
     */

    public boolean isFileExist(String mFileName) {
        String path = mSharedPreferences.getString(STORAGE_LOCATION,
                StringUtils.getInstance().getDefaultStorageLocation()) + mFileName;
        File file = new File(path);

        return file.exists();
    }

    /**
     * Extracts file name from the URI
     *
     * @param uri - file uri
     * @return - extracted filename
     */
    public String getFileName(Uri uri) {
        String fileName = null;
        String scheme = uri.getScheme();

        if (scheme == null)
            return null;

        if (scheme.equals("file")) {
            return uri.getLastPathSegment();
        } else if (scheme.equals("content")) {
            Cursor cursor = mContext.getContentResolver().query(uri, null, null, null, null);

            if (cursor != null) {
                if (cursor.getCount() != 0) {
                    int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DISPLAY_NAME);
                    cursor.moveToFirst();
                    fileName = cursor.getString(columnIndex);
                }
                cursor.close();
            }
        }

        return fileName;
    }

    /**
     * Returns name of the last file with "_pdf" suffix.
     *
     * @param filesPath - ArrayList of image paths
     * @return fileName with _pdf suffix
     */
    public String getLastFileName(ArrayList<String> filesPath) {
        if (filesPath.size() == 0)
            return "";

        String lastSelectedFilePath = filesPath.get(filesPath.size() - 1);
        String nameWithoutExt = stripExtension(getFileNameWithoutExtension(lastSelectedFilePath));

        return nameWithoutExt + mContext.getString(R.string.pdf_suffix);
    }

    /**
     * Returns the filename without its extension
     *
     * @param fileNameWithExt fileName with extension. Ex: androidDev.jpg
     * @return fileName without extension. Ex: androidDev
     */
    public String stripExtension(String fileNameWithExt) {
        // Handle null case specially.
        if (fileNameWithExt == null) return null;

        // Get position of last '.'.
        int pos = fileNameWithExt.lastIndexOf(".");

        // If there wasn't any '.' just return the string as is.
        if (pos == -1) return fileNameWithExt;

        // Otherwise return the string, up to the dot.
        return fileNameWithExt.substring(0, pos);
    }

    /**
     * Opens image in a gallery application
     *
     * @param path - image path
     */
    public void openImage(String path) {
        File file = new File(path);
        Intent target = new Intent(Intent.ACTION_VIEW);
        target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
        Uri uri = FileProvider.getUriForFile(mContext, AUTHORITY_APP, file);
        target.setDataAndType(uri, "image/*");
        target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        openIntent(Intent.createChooser(target, mContext.getString(R.string.open_file)));
    }

    /**
     * Opens the targeted intent (if possible), otherwise show a snackbar
     *
     * @param intent - input intent
     */
    private void openIntent(Intent intent) {
        try {
            mContext.startActivity(intent);
        } catch (ActivityNotFoundException e) {
            StringUtils.getInstance().showSnackbar(mContext, R.string.snackbar_no_pdf_app);
        }
    }

    /**
     * Returns file chooser intent
     *
     * @return - intent
     */
    public Intent getFileChooser() {
        String folderPath = Environment.getExternalStorageDirectory() + "/";
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_GET_CONTENT);
        Uri myUri = Uri.parse(folderPath);
        intent.setDataAndType(myUri, mContext.getString(R.string.pdf_type));

        return Intent.createChooser(intent, mContext.getString(R.string.merge_file_select));
    }

    /**
     * Returns file chooser intent that can select multiple files
     *
     * @return - intent
     */
    public Intent getMultipleFileChooser() {
        String folderPath = Environment.getExternalStorageDirectory() + "/";
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_GET_CONTENT);
        Uri myUri = Uri.parse(folderPath);
        intent.setDataAndType(myUri, mContext.getString(R.string.pdf_type));
        intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
        return Intent.createChooser(intent, mContext.getString(R.string.merge_file_select));
    }

    String getUniqueFileName(String fileName) {
        String outputFileName = fileName;
        File file = new File(outputFileName);

        if (!isFileExist(file.getName()))
            return outputFileName;

        File parentFile = file.getParentFile();
        if (parentFile != null) {
            File[] listFiles = parentFile.listFiles();

            if (listFiles != null) {
                int append = checkRepeat(outputFileName, Arrays.asList(listFiles));
                outputFileName = outputFileName.replace(mContext.getString(R.string.pdf_ext),
                        append + mContext.getResources().getString(R.string.pdf_ext));
            }
        }

        return outputFileName;
    }

    /**
     * Opens a Dialog to select a filename.
     * If the file under that name already exists, an overwrite dialog gets opened.
     * If the overwrite is cancelled, this first dialog gets opened again.
     *
     * @param preFillName a prefill Name for the file
     * @param ext         the file extension
     * @param saveMethod  the method that should be called when a filename is chosen
     */
    public void openSaveDialog(String preFillName, String ext, Consumer<String> saveMethod) {

        MaterialDialog.Builder builder = DialogUtils.getInstance().createCustomDialog(mContext,
                R.string.creating_pdf, R.string.enter_file_name);
        builder.input(mContext.getString(R.string.example), preFillName, (dialog, input) -> {
            if (StringUtils.getInstance().isEmpty(input)) {
                StringUtils.getInstance().showSnackbar(mContext, R.string.snackbar_name_not_blank);
            } else {
                final String filename = input.toString();
                if (!isFileExist(filename + ext)) {
                    saveMethod.accept(filename);
                } else {
                    MaterialDialog.Builder builder2 = DialogUtils.getInstance().createOverwriteDialog(mContext);
                    builder2.onPositive((dialog2, which) -> saveMethod.accept(filename))
                            .onNegative((dialog1, which) ->
                                    openSaveDialog(preFillName, ext, saveMethod)).show();
                }
            }
        }).show();
    }

    public enum FileType {
        e_PDF,
        e_TXT
    }
}