/* * Copyright (c) 2019 Hemanth Savarala. * * Licensed under the GNU General Public License v3 * * This is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by * the Free Software Foundation either version 3 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. */ package code.name.monkey.retromusic.util; import android.content.Context; import android.database.Cursor; import android.os.Environment; import android.provider.MediaStore; import android.webkit.MimeTypeMap; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; import code.name.monkey.retromusic.loaders.SongLoader; import code.name.monkey.retromusic.loaders.SortedCursor; import code.name.monkey.retromusic.model.Song; public final class FileUtil { private FileUtil() { } public static byte[] readBytes(InputStream stream) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[4096]; int count; while ((count = stream.read(buffer)) != -1) { baos.write(buffer, 0, count); } stream.close(); return baos.toByteArray(); } @NonNull public static ArrayList matchFilesWithMediaStore(@NonNull Context context, @Nullable List files) { return SongLoader.INSTANCE.getSongs(makeSongCursor(context, files)); } public static String safeGetCanonicalPath(File file) { try { return file.getCanonicalPath(); } catch (IOException e) { e.printStackTrace(); return file.getAbsolutePath(); } } @Nullable public static SortedCursor makeSongCursor(@NonNull final Context context, @Nullable final List files) { String selection = null; String[] paths = null; if (files != null) { paths = toPathArray(files); if (files.size() > 0 && files.size() < 999) { // 999 is the max amount Androids SQL implementation can handle. selection = MediaStore.Audio.AudioColumns.DATA + " IN (" + makePlaceholders(files.size()) + ")"; } } Cursor songCursor = SongLoader.INSTANCE.makeSongCursor(context, selection, selection == null ? null : paths); return songCursor == null ? null : new SortedCursor(songCursor, paths, MediaStore.Audio.AudioColumns.DATA); } private static String makePlaceholders(int len) { StringBuilder sb = new StringBuilder(len * 2 - 1); sb.append("?"); for (int i = 1; i < len; i++) { sb.append(",?"); } return sb.toString(); } @Nullable private static String[] toPathArray(@Nullable List files) { if (files != null) { String[] paths = new String[files.size()]; for (int i = 0; i < files.size(); i++) { /*try { paths[i] = files.get(i).getCanonicalPath(); // canonical path is important here because we want to compare the path with the media store entry later } catch (IOException e) { e.printStackTrace(); paths[i] = files.get(i).getPath(); }*/ paths[i] = safeGetCanonicalPath(files.get(i)); } return paths; } return null; } @NonNull public static List listFiles(@NonNull File directory, @Nullable FileFilter fileFilter) { List fileList = new LinkedList<>(); File[] found = directory.listFiles(fileFilter); if (found != null) { Collections.addAll(fileList, found); } return fileList; } @NonNull public static List listFilesDeep(@NonNull File directory, @Nullable FileFilter fileFilter) { List files = new LinkedList<>(); internalListFilesDeep(files, directory, fileFilter); return files; } @NonNull public static List listFilesDeep(@NonNull Collection files, @Nullable FileFilter fileFilter) { List resFiles = new LinkedList<>(); for (File file : files) { if (file.isDirectory()) { internalListFilesDeep(resFiles, file, fileFilter); } else if (fileFilter == null || fileFilter.accept(file)) { resFiles.add(file); } } return resFiles; } private static void internalListFilesDeep(@NonNull Collection files, @NonNull File directory, @Nullable FileFilter fileFilter) { File[] found = directory.listFiles(fileFilter); if (found != null) { for (File file : found) { if (file.isDirectory()) { internalListFilesDeep(files, file, fileFilter); } else { files.add(file); } } } } public static boolean fileIsMimeType(File file, String mimeType, MimeTypeMap mimeTypeMap) { if (mimeType == null || mimeType.equals("*/*")) { return true; } else { // get the file mime type String filename = file.toURI().toString(); int dotPos = filename.lastIndexOf('.'); if (dotPos == -1) { return false; } String fileExtension = filename.substring(dotPos + 1).toLowerCase(); String fileType = mimeTypeMap.getMimeTypeFromExtension(fileExtension); if (fileType == null) { return false; } // check the 'type/subtype' pattern if (fileType.equals(mimeType)) { return true; } // check the 'type/*' pattern int mimeTypeDelimiter = mimeType.lastIndexOf('/'); if (mimeTypeDelimiter == -1) { return false; } String mimeTypeMainType = mimeType.substring(0, mimeTypeDelimiter); String mimeTypeSubtype = mimeType.substring(mimeTypeDelimiter + 1); if (!mimeTypeSubtype.equals("*")) { return false; } int fileTypeDelimiter = fileType.lastIndexOf('/'); if (fileTypeDelimiter == -1) { return false; } String fileTypeMainType = fileType.substring(0, fileTypeDelimiter); if (fileTypeMainType.equals(mimeTypeMainType)) { return true; } return fileTypeMainType.equals(mimeTypeMainType); } } public static String stripExtension(String str) { if (str == null) { return null; } int pos = str.lastIndexOf('.'); if (pos == -1) { return str; } return str.substring(0, pos); } public static String readFromStream(InputStream is) throws Exception { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { if (sb.length() > 0) { sb.append("\n"); } sb.append(line); } reader.close(); return sb.toString(); } public static String read(File file) throws Exception { FileInputStream fin = new FileInputStream(file); String ret = readFromStream(fin); fin.close(); return ret; } public static boolean isExternalMemoryAvailable() { Boolean isSDPresent = Environment.getExternalStorageState() .equals(android.os.Environment.MEDIA_MOUNTED); Boolean isSDSupportedDevice = Environment.isExternalStorageRemovable(); if (isSDSupportedDevice && isSDPresent) { // yes SD-card is present return true; } else { return false; // Sorry } } public static File safeGetCanonicalFile(File file) { try { return file.getCanonicalFile(); } catch (IOException e) { e.printStackTrace(); return file.getAbsoluteFile(); } } }