android: Convert FileUtil to Kotlin
This commit is contained in:
		@@ -1,296 +0,0 @@
 | 
			
		||||
package org.yuzu.yuzu_emu.utils;
 | 
			
		||||
 | 
			
		||||
import android.content.ContentResolver;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.database.Cursor;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.os.ParcelFileDescriptor;
 | 
			
		||||
import android.provider.DocumentsContract;
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.Nullable;
 | 
			
		||||
import androidx.documentfile.provider.DocumentFile;
 | 
			
		||||
 | 
			
		||||
import org.yuzu.yuzu_emu.model.MinimalDocumentFile;
 | 
			
		||||
 | 
			
		||||
import java.io.FileOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.net.URLDecoder;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public class FileUtil {
 | 
			
		||||
    static final String PATH_TREE = "tree";
 | 
			
		||||
    static final String DECODE_METHOD = "UTF-8";
 | 
			
		||||
    static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
 | 
			
		||||
    static final String TEXT_PLAIN = "text/plain";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a file from directory with filename.
 | 
			
		||||
     * @param context Application context
 | 
			
		||||
     * @param directory parent path for file.
 | 
			
		||||
     * @param filename file display name.
 | 
			
		||||
     * @return boolean
 | 
			
		||||
     */
 | 
			
		||||
    @Nullable
 | 
			
		||||
    public static DocumentFile createFile(Context context, String directory, String filename) {
 | 
			
		||||
        try {
 | 
			
		||||
            Uri directoryUri = Uri.parse(directory);
 | 
			
		||||
            DocumentFile parent = DocumentFile.fromTreeUri(context, directoryUri);
 | 
			
		||||
            if (parent == null) return null;
 | 
			
		||||
            filename = URLDecoder.decode(filename, DECODE_METHOD);
 | 
			
		||||
            String mimeType = APPLICATION_OCTET_STREAM;
 | 
			
		||||
            if (filename.endsWith(".txt")) {
 | 
			
		||||
                mimeType = TEXT_PLAIN;
 | 
			
		||||
            }
 | 
			
		||||
            DocumentFile exists = parent.findFile(filename);
 | 
			
		||||
            if (exists != null) return exists;
 | 
			
		||||
            return parent.createFile(mimeType, filename);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot create file, error: " + e.getMessage());
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a directory from directory with filename.
 | 
			
		||||
     * @param context Application context
 | 
			
		||||
     * @param directory parent path for directory.
 | 
			
		||||
     * @param directoryName directory display name.
 | 
			
		||||
     * @return boolean
 | 
			
		||||
     */
 | 
			
		||||
    @Nullable
 | 
			
		||||
    public static DocumentFile createDir(Context context, String directory, String directoryName) {
 | 
			
		||||
        try {
 | 
			
		||||
            Uri directoryUri = Uri.parse(directory);
 | 
			
		||||
            DocumentFile parent = DocumentFile.fromTreeUri(context, directoryUri);
 | 
			
		||||
            if (parent == null) return null;
 | 
			
		||||
            directoryName = URLDecoder.decode(directoryName, DECODE_METHOD);
 | 
			
		||||
            DocumentFile isExist = parent.findFile(directoryName);
 | 
			
		||||
            if (isExist != null) return isExist;
 | 
			
		||||
            return parent.createDirectory(directoryName);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot create file, error: " + e.getMessage());
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Open content uri and return file descriptor to JNI.
 | 
			
		||||
     * @param context Application context
 | 
			
		||||
     * @param path Native content uri path
 | 
			
		||||
     * @param openmode will be one of "r", "r", "rw", "wa", "rwa"
 | 
			
		||||
     * @return file descriptor
 | 
			
		||||
     */
 | 
			
		||||
    public static int openContentUri(Context context, String path, String openmode) {
 | 
			
		||||
        try {
 | 
			
		||||
            Uri uri = Uri.parse(path);
 | 
			
		||||
            ParcelFileDescriptor parcelFileDescriptor = context.getContentResolver().openFileDescriptor(uri, openmode);
 | 
			
		||||
            if (parcelFileDescriptor == null) {
 | 
			
		||||
                Log.error("[FileUtil]: Cannot get the file descriptor from uri: " + path);
 | 
			
		||||
                return -1;
 | 
			
		||||
            }
 | 
			
		||||
            return parcelFileDescriptor.detachFd();
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception e) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot open content uri, error: " + e.getMessage());
 | 
			
		||||
        }
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reference:  https://stackoverflow.com/questions/42186820/documentfile-is-very-slow
 | 
			
		||||
     * This function will be faster than DoucmentFile.listFiles
 | 
			
		||||
     * @param context Application context
 | 
			
		||||
     * @param uri Directory uri.
 | 
			
		||||
     * @return CheapDocument lists.
 | 
			
		||||
     */
 | 
			
		||||
    public static MinimalDocumentFile[] listFiles(Context context, Uri uri) {
 | 
			
		||||
        final ContentResolver resolver = context.getContentResolver();
 | 
			
		||||
        final String[] columns = new String[]{
 | 
			
		||||
                DocumentsContract.Document.COLUMN_DOCUMENT_ID,
 | 
			
		||||
                DocumentsContract.Document.COLUMN_DISPLAY_NAME,
 | 
			
		||||
                DocumentsContract.Document.COLUMN_MIME_TYPE,
 | 
			
		||||
        };
 | 
			
		||||
        Cursor c = null;
 | 
			
		||||
        final List<MinimalDocumentFile> results = new ArrayList<>();
 | 
			
		||||
        try {
 | 
			
		||||
            String docId;
 | 
			
		||||
            if (isRootTreeUri(uri)) {
 | 
			
		||||
                docId = DocumentsContract.getTreeDocumentId(uri);
 | 
			
		||||
            } else {
 | 
			
		||||
                docId = DocumentsContract.getDocumentId(uri);
 | 
			
		||||
            }
 | 
			
		||||
            final Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri, docId);
 | 
			
		||||
            c = resolver.query(childrenUri, columns, null, null, null);
 | 
			
		||||
            while(c.moveToNext()) {
 | 
			
		||||
                final String documentId = c.getString(0);
 | 
			
		||||
                final String documentName = c.getString(1);
 | 
			
		||||
                final String documentMimeType = c.getString(2);
 | 
			
		||||
                final Uri documentUri = DocumentsContract.buildDocumentUriUsingTree(uri, documentId);
 | 
			
		||||
                MinimalDocumentFile document = new MinimalDocumentFile(documentName, documentMimeType, documentUri);
 | 
			
		||||
                results.add(document);
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot list file error: " + e.getMessage());
 | 
			
		||||
        } finally {
 | 
			
		||||
            closeQuietly(c);
 | 
			
		||||
        }
 | 
			
		||||
        return results.toArray(new MinimalDocumentFile[0]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check whether given path exists.
 | 
			
		||||
     * @param path Native content uri path
 | 
			
		||||
     * @return bool
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean Exists(Context context, String path) {
 | 
			
		||||
        Cursor c = null;
 | 
			
		||||
        try {
 | 
			
		||||
            Uri mUri = Uri.parse(path);
 | 
			
		||||
            final String[] columns = new String[] { DocumentsContract.Document.COLUMN_DOCUMENT_ID };
 | 
			
		||||
            c = context.getContentResolver().query(mUri, columns, null, null, null);
 | 
			
		||||
            return c.getCount() > 0;
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            Log.info("[FileUtil] Cannot find file from given path, error: " + e.getMessage());
 | 
			
		||||
        } finally {
 | 
			
		||||
            closeQuietly(c);
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check whether given path is a directory
 | 
			
		||||
     * @param path content uri path
 | 
			
		||||
     * @return bool
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean isDirectory(Context context, String path) {
 | 
			
		||||
        final ContentResolver resolver = context.getContentResolver();
 | 
			
		||||
        final String[] columns = new String[] {
 | 
			
		||||
                DocumentsContract.Document.COLUMN_MIME_TYPE
 | 
			
		||||
        };
 | 
			
		||||
        boolean isDirectory = false;
 | 
			
		||||
        Cursor c = null;
 | 
			
		||||
        try {
 | 
			
		||||
            Uri mUri = Uri.parse(path);
 | 
			
		||||
            c = resolver.query(mUri, columns, null, null, null);
 | 
			
		||||
            c.moveToNext();
 | 
			
		||||
            final String mimeType = c.getString(0);
 | 
			
		||||
            isDirectory = mimeType.equals(DocumentsContract.Document.MIME_TYPE_DIR);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot list files, error: " + e.getMessage());
 | 
			
		||||
        } finally {
 | 
			
		||||
            closeQuietly(c);
 | 
			
		||||
        }
 | 
			
		||||
        return isDirectory;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get file display name from given path
 | 
			
		||||
     * @param path content uri path
 | 
			
		||||
     * @return String display name
 | 
			
		||||
     */
 | 
			
		||||
    public static String getFilename(Context context, String path) {
 | 
			
		||||
        final ContentResolver resolver = context.getContentResolver();
 | 
			
		||||
        final String[] columns = new String[] {
 | 
			
		||||
                DocumentsContract.Document.COLUMN_DISPLAY_NAME
 | 
			
		||||
        };
 | 
			
		||||
        String filename = "";
 | 
			
		||||
        Cursor c = null;
 | 
			
		||||
        try {
 | 
			
		||||
            Uri mUri = Uri.parse(path);
 | 
			
		||||
            c = resolver.query(mUri, columns, null, null, null);
 | 
			
		||||
            c.moveToNext();
 | 
			
		||||
            filename = c.getString(0);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot get file size, error: " + e.getMessage());
 | 
			
		||||
        } finally {
 | 
			
		||||
            closeQuietly(c);
 | 
			
		||||
        }
 | 
			
		||||
        return filename;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String[] getFilesName(Context context, String path) {
 | 
			
		||||
        Uri uri = Uri.parse(path);
 | 
			
		||||
        List<String> files = new ArrayList<>();
 | 
			
		||||
        for (MinimalDocumentFile file: FileUtil.listFiles(context, uri)) {
 | 
			
		||||
            files.add(file.getFilename());
 | 
			
		||||
        }
 | 
			
		||||
        return files.toArray(new String[0]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get file size from given path.
 | 
			
		||||
     * @param path content uri path
 | 
			
		||||
     * @return long file size
 | 
			
		||||
     */
 | 
			
		||||
    public static long getFileSize(Context context, String path) {
 | 
			
		||||
        final ContentResolver resolver = context.getContentResolver();
 | 
			
		||||
        final String[] columns = new String[] {
 | 
			
		||||
                DocumentsContract.Document.COLUMN_SIZE
 | 
			
		||||
        };
 | 
			
		||||
        long size = 0;
 | 
			
		||||
        Cursor c =null;
 | 
			
		||||
        try {
 | 
			
		||||
            Uri mUri = Uri.parse(path);
 | 
			
		||||
            c = resolver.query(mUri, columns, null, null, null);
 | 
			
		||||
            c.moveToNext();
 | 
			
		||||
            size = c.getLong(0);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot get file size, error: " + e.getMessage());
 | 
			
		||||
        } finally {
 | 
			
		||||
            closeQuietly(c);
 | 
			
		||||
        }
 | 
			
		||||
        return size;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean copyUriToInternalStorage(Context context, Uri sourceUri, String destinationParentPath, String destinationFilename) {
 | 
			
		||||
        InputStream input = null;
 | 
			
		||||
        FileOutputStream output = null;
 | 
			
		||||
        try {
 | 
			
		||||
            input = context.getContentResolver().openInputStream(sourceUri);
 | 
			
		||||
            output = new FileOutputStream(destinationParentPath + "/" + destinationFilename);
 | 
			
		||||
            byte[] buffer = new byte[1024];
 | 
			
		||||
            int len;
 | 
			
		||||
            while ((len = input.read(buffer)) != -1) {
 | 
			
		||||
                output.write(buffer, 0, len);
 | 
			
		||||
            }
 | 
			
		||||
            output.flush();
 | 
			
		||||
            return true;
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot copy file, error: " + e.getMessage());
 | 
			
		||||
        } finally {
 | 
			
		||||
            if (input != null) {
 | 
			
		||||
                try {
 | 
			
		||||
                    input.close();
 | 
			
		||||
                } catch (IOException e) {
 | 
			
		||||
                    Log.error("[FileUtil]: Cannot close input file, error: " + e.getMessage());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (output != null) {
 | 
			
		||||
                try {
 | 
			
		||||
                    output.close();
 | 
			
		||||
                } catch (IOException e) {
 | 
			
		||||
                    Log.error("[FileUtil]: Cannot close output file, error: " + e.getMessage());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean isRootTreeUri(Uri uri) {
 | 
			
		||||
        final List<String> paths = uri.getPathSegments();
 | 
			
		||||
        return paths.size() == 2 && PATH_TREE.equals(paths.get(0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void closeQuietly(AutoCloseable closeable) {
 | 
			
		||||
        if (closeable != null) {
 | 
			
		||||
            try {
 | 
			
		||||
                closeable.close();
 | 
			
		||||
            } catch (RuntimeException rethrown) {
 | 
			
		||||
                throw rethrown;
 | 
			
		||||
            } catch (Exception ignored) {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,292 @@
 | 
			
		||||
package org.yuzu.yuzu_emu.utils
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.database.Cursor
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import android.provider.DocumentsContract
 | 
			
		||||
import androidx.documentfile.provider.DocumentFile
 | 
			
		||||
import org.yuzu.yuzu_emu.model.MinimalDocumentFile
 | 
			
		||||
import java.io.FileOutputStream
 | 
			
		||||
import java.io.IOException
 | 
			
		||||
import java.io.InputStream
 | 
			
		||||
import java.net.URLDecoder
 | 
			
		||||
 | 
			
		||||
object FileUtil {
 | 
			
		||||
    const val PATH_TREE = "tree"
 | 
			
		||||
    const val DECODE_METHOD = "UTF-8"
 | 
			
		||||
    const val APPLICATION_OCTET_STREAM = "application/octet-stream"
 | 
			
		||||
    const val TEXT_PLAIN = "text/plain"
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a file from directory with filename.
 | 
			
		||||
     * @param context Application context
 | 
			
		||||
     * @param directory parent path for file.
 | 
			
		||||
     * @param filename file display name.
 | 
			
		||||
     * @return boolean
 | 
			
		||||
     */
 | 
			
		||||
    fun createFile(context: Context?, directory: String?, filename: String): DocumentFile? {
 | 
			
		||||
        var decodedFilename = filename
 | 
			
		||||
        try {
 | 
			
		||||
            val directoryUri = Uri.parse(directory)
 | 
			
		||||
            val parent = DocumentFile.fromTreeUri(context!!, directoryUri) ?: return null
 | 
			
		||||
            decodedFilename = URLDecoder.decode(decodedFilename, DECODE_METHOD)
 | 
			
		||||
            var mimeType = APPLICATION_OCTET_STREAM
 | 
			
		||||
            if (decodedFilename.endsWith(".txt")) {
 | 
			
		||||
                mimeType = TEXT_PLAIN
 | 
			
		||||
            }
 | 
			
		||||
            val exists = parent.findFile(decodedFilename)
 | 
			
		||||
            return exists ?: parent.createFile(mimeType, decodedFilename)
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot create file, error: " + e.message)
 | 
			
		||||
        }
 | 
			
		||||
        return null
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a directory from directory with filename.
 | 
			
		||||
     * @param context Application context
 | 
			
		||||
     * @param directory parent path for directory.
 | 
			
		||||
     * @param directoryName directory display name.
 | 
			
		||||
     * @return boolean
 | 
			
		||||
     */
 | 
			
		||||
    fun createDir(context: Context?, directory: String?, directoryName: String?): DocumentFile? {
 | 
			
		||||
        var decodedDirectoryName = directoryName
 | 
			
		||||
        try {
 | 
			
		||||
            val directoryUri = Uri.parse(directory)
 | 
			
		||||
            val parent = DocumentFile.fromTreeUri(context!!, directoryUri) ?: return null
 | 
			
		||||
            decodedDirectoryName = URLDecoder.decode(decodedDirectoryName, DECODE_METHOD)
 | 
			
		||||
            val isExist = parent.findFile(decodedDirectoryName)
 | 
			
		||||
            return isExist ?: parent.createDirectory(decodedDirectoryName)
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot create file, error: " + e.message)
 | 
			
		||||
        }
 | 
			
		||||
        return null
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Open content uri and return file descriptor to JNI.
 | 
			
		||||
     * @param context Application context
 | 
			
		||||
     * @param path Native content uri path
 | 
			
		||||
     * @param openMode will be one of "r", "r", "rw", "wa", "rwa"
 | 
			
		||||
     * @return file descriptor
 | 
			
		||||
     */
 | 
			
		||||
    @JvmStatic
 | 
			
		||||
    fun openContentUri(context: Context, path: String, openMode: String?): Int {
 | 
			
		||||
        try {
 | 
			
		||||
            val uri = Uri.parse(path)
 | 
			
		||||
            val parcelFileDescriptor = context.contentResolver.openFileDescriptor(uri, openMode!!)
 | 
			
		||||
            if (parcelFileDescriptor == null) {
 | 
			
		||||
                Log.error("[FileUtil]: Cannot get the file descriptor from uri: $path")
 | 
			
		||||
                return -1
 | 
			
		||||
            }
 | 
			
		||||
            val fileDescriptor = parcelFileDescriptor.detachFd()
 | 
			
		||||
            parcelFileDescriptor.close()
 | 
			
		||||
            return fileDescriptor
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot open content uri, error: " + e.message)
 | 
			
		||||
        }
 | 
			
		||||
        return -1
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reference:  https://stackoverflow.com/questions/42186820/documentfile-is-very-slow
 | 
			
		||||
     * This function will be faster than DoucmentFile.listFiles
 | 
			
		||||
     * @param context Application context
 | 
			
		||||
     * @param uri Directory uri.
 | 
			
		||||
     * @return CheapDocument lists.
 | 
			
		||||
     */
 | 
			
		||||
    fun listFiles(context: Context, uri: Uri): Array<MinimalDocumentFile> {
 | 
			
		||||
        val resolver = context.contentResolver
 | 
			
		||||
        val columns = arrayOf(
 | 
			
		||||
            DocumentsContract.Document.COLUMN_DOCUMENT_ID,
 | 
			
		||||
            DocumentsContract.Document.COLUMN_DISPLAY_NAME,
 | 
			
		||||
            DocumentsContract.Document.COLUMN_MIME_TYPE
 | 
			
		||||
        )
 | 
			
		||||
        var c: Cursor? = null
 | 
			
		||||
        val results: MutableList<MinimalDocumentFile> = ArrayList()
 | 
			
		||||
        try {
 | 
			
		||||
            val docId: String = if (isRootTreeUri(uri)) {
 | 
			
		||||
                DocumentsContract.getTreeDocumentId(uri)
 | 
			
		||||
            } else {
 | 
			
		||||
                DocumentsContract.getDocumentId(uri)
 | 
			
		||||
            }
 | 
			
		||||
            val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri, docId)
 | 
			
		||||
            c = resolver.query(childrenUri, columns, null, null, null)
 | 
			
		||||
            while (c!!.moveToNext()) {
 | 
			
		||||
                val documentId = c.getString(0)
 | 
			
		||||
                val documentName = c.getString(1)
 | 
			
		||||
                val documentMimeType = c.getString(2)
 | 
			
		||||
                val documentUri = DocumentsContract.buildDocumentUriUsingTree(uri, documentId)
 | 
			
		||||
                val document = MinimalDocumentFile(documentName, documentMimeType, documentUri)
 | 
			
		||||
                results.add(document)
 | 
			
		||||
            }
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot list file error: " + e.message)
 | 
			
		||||
        } finally {
 | 
			
		||||
            closeQuietly(c)
 | 
			
		||||
        }
 | 
			
		||||
        return results.toTypedArray()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check whether given path exists.
 | 
			
		||||
     * @param path Native content uri path
 | 
			
		||||
     * @return bool
 | 
			
		||||
     */
 | 
			
		||||
    fun exists(context: Context, path: String?): Boolean {
 | 
			
		||||
        var c: Cursor? = null
 | 
			
		||||
        try {
 | 
			
		||||
            val mUri = Uri.parse(path)
 | 
			
		||||
            val columns = arrayOf(DocumentsContract.Document.COLUMN_DOCUMENT_ID)
 | 
			
		||||
            c = context.contentResolver.query(mUri, columns, null, null, null)
 | 
			
		||||
            return c!!.count > 0
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            Log.info("[FileUtil] Cannot find file from given path, error: " + e.message)
 | 
			
		||||
        } finally {
 | 
			
		||||
            closeQuietly(c)
 | 
			
		||||
        }
 | 
			
		||||
        return false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check whether given path is a directory
 | 
			
		||||
     * @param path content uri path
 | 
			
		||||
     * @return bool
 | 
			
		||||
     */
 | 
			
		||||
    fun isDirectory(context: Context, path: String): Boolean {
 | 
			
		||||
        val resolver = context.contentResolver
 | 
			
		||||
        val columns = arrayOf(
 | 
			
		||||
            DocumentsContract.Document.COLUMN_MIME_TYPE
 | 
			
		||||
        )
 | 
			
		||||
        var isDirectory = false
 | 
			
		||||
        var c: Cursor? = null
 | 
			
		||||
        try {
 | 
			
		||||
            val mUri = Uri.parse(path)
 | 
			
		||||
            c = resolver.query(mUri, columns, null, null, null)
 | 
			
		||||
            c!!.moveToNext()
 | 
			
		||||
            val mimeType = c.getString(0)
 | 
			
		||||
            isDirectory = mimeType == DocumentsContract.Document.MIME_TYPE_DIR
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot list files, error: " + e.message)
 | 
			
		||||
        } finally {
 | 
			
		||||
            closeQuietly(c)
 | 
			
		||||
        }
 | 
			
		||||
        return isDirectory
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get file display name from given path
 | 
			
		||||
     * @param path content uri path
 | 
			
		||||
     * @return String display name
 | 
			
		||||
     */
 | 
			
		||||
    fun getFilename(context: Context, path: String): String {
 | 
			
		||||
        val resolver = context.contentResolver
 | 
			
		||||
        val columns = arrayOf(
 | 
			
		||||
            DocumentsContract.Document.COLUMN_DISPLAY_NAME
 | 
			
		||||
        )
 | 
			
		||||
        var filename = ""
 | 
			
		||||
        var c: Cursor? = null
 | 
			
		||||
        try {
 | 
			
		||||
            val mUri = Uri.parse(path)
 | 
			
		||||
            c = resolver.query(mUri, columns, null, null, null)
 | 
			
		||||
            c!!.moveToNext()
 | 
			
		||||
            filename = c.getString(0)
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot get file size, error: " + e.message)
 | 
			
		||||
        } finally {
 | 
			
		||||
            closeQuietly(c)
 | 
			
		||||
        }
 | 
			
		||||
        return filename
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun getFilesName(context: Context, path: String): Array<String> {
 | 
			
		||||
        val uri = Uri.parse(path)
 | 
			
		||||
        val files: MutableList<String> = ArrayList()
 | 
			
		||||
        for (file in listFiles(context, uri)) {
 | 
			
		||||
            files.add(file.filename)
 | 
			
		||||
        }
 | 
			
		||||
        return files.toTypedArray()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get file size from given path.
 | 
			
		||||
     * @param path content uri path
 | 
			
		||||
     * @return long file size
 | 
			
		||||
     */
 | 
			
		||||
    @JvmStatic
 | 
			
		||||
    fun getFileSize(context: Context, path: String): Long {
 | 
			
		||||
        val resolver = context.contentResolver
 | 
			
		||||
        val columns = arrayOf(
 | 
			
		||||
            DocumentsContract.Document.COLUMN_SIZE
 | 
			
		||||
        )
 | 
			
		||||
        var size: Long = 0
 | 
			
		||||
        var c: Cursor? = null
 | 
			
		||||
        try {
 | 
			
		||||
            val mUri = Uri.parse(path)
 | 
			
		||||
            c = resolver.query(mUri, columns, null, null, null)
 | 
			
		||||
            c!!.moveToNext()
 | 
			
		||||
            size = c.getLong(0)
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot get file size, error: " + e.message)
 | 
			
		||||
        } finally {
 | 
			
		||||
            closeQuietly(c)
 | 
			
		||||
        }
 | 
			
		||||
        return size
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @JvmStatic
 | 
			
		||||
    fun copyUriToInternalStorage(
 | 
			
		||||
        context: Context,
 | 
			
		||||
        sourceUri: Uri?,
 | 
			
		||||
        destinationParentPath: String,
 | 
			
		||||
        destinationFilename: String
 | 
			
		||||
    ): Boolean {
 | 
			
		||||
        var input: InputStream? = null
 | 
			
		||||
        var output: FileOutputStream? = null
 | 
			
		||||
        try {
 | 
			
		||||
            input = context.contentResolver.openInputStream(sourceUri!!)
 | 
			
		||||
            output = FileOutputStream("$destinationParentPath/$destinationFilename")
 | 
			
		||||
            val buffer = ByteArray(1024)
 | 
			
		||||
            var len: Int
 | 
			
		||||
            while (input!!.read(buffer).also { len = it } != -1) {
 | 
			
		||||
                output.write(buffer, 0, len)
 | 
			
		||||
            }
 | 
			
		||||
            output.flush()
 | 
			
		||||
            return true
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            Log.error("[FileUtil]: Cannot copy file, error: " + e.message)
 | 
			
		||||
        } finally {
 | 
			
		||||
            if (input != null) {
 | 
			
		||||
                try {
 | 
			
		||||
                    input.close()
 | 
			
		||||
                } catch (e: IOException) {
 | 
			
		||||
                    Log.error("[FileUtil]: Cannot close input file, error: " + e.message)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (output != null) {
 | 
			
		||||
                try {
 | 
			
		||||
                    output.close()
 | 
			
		||||
                } catch (e: IOException) {
 | 
			
		||||
                    Log.error("[FileUtil]: Cannot close output file, error: " + e.message)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun isRootTreeUri(uri: Uri): Boolean {
 | 
			
		||||
        val paths = uri.pathSegments
 | 
			
		||||
        return paths.size == 2 && PATH_TREE == paths[0]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun closeQuietly(closeable: AutoCloseable?) {
 | 
			
		||||
        if (closeable != null) {
 | 
			
		||||
            try {
 | 
			
		||||
                closeable.close()
 | 
			
		||||
            } catch (rethrown: RuntimeException) {
 | 
			
		||||
                throw rethrown
 | 
			
		||||
            } catch (ignored: Exception) {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user