de.petermoesenthin.alarming.util.FileUtil.java Source code

Java tutorial

Introduction

Here is the source code for de.petermoesenthin.alarming.util.FileUtil.java

Source

/*
 * Alarming, an alarm app for the Android platform
 *
 * Copyright (C) 2014-2015 Peter Msenthin <peter.moesenthin@gmail.com>
 *
 * Alarming 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 program 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.petermoesenthin.alarming.util;

import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import android.webkit.MimeTypeMap;
import com.google.gson.Gson;
import de.petermoesenthin.alarming.pref.AlarmSoundPref;
import de.petermoesenthin.alarming.pref.PrefKey;
import de.petermoesenthin.alarming.pref.PrefUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;

import java.io.*;

public class FileUtil {

    public static final String DEBUG_TAG = FileUtil.class.getSimpleName();

    public static final String APP_EXT_STORAGE_FOLDER = "alarming";
    public static final String AUDIO_METADATA_FILE_EXTENSION = "alarmingmeta";

    public static void updateAlarmSoundUris(Context context) {
        File[] files = getAlarmDirectoryAudioFileList(context);
        String[] fileUris;
        if (files == null || files.length == 0) {
            Log.d(DEBUG_TAG, "No audio files found");
            fileUris = new String[0];
        } else {
            fileUris = new String[files.length];
            for (int i = 0; i < files.length; i++) {
                Log.d(DEBUG_TAG, "Found file " + i + ":" + files[i].getAbsolutePath());
                fileUris[i] = files[i].getPath();
            }
        }
        Gson gson = new Gson();
        String urisJson = gson.toJson(fileUris);
        PrefUtil.putString(context, PrefKey.ALARM_SOUND_URIS_GSON, urisJson);
    }

    public interface OnCopyFinishedListener {

        void onOperationFinished();
    }

    /**
     * Copies a file to the Alarming directory in the external storage
     *
     * @param context Application context
     * @param uri     Uri of file to copy
     */
    public static void saveFileToExtAppStorage(final Context context, final Uri uri,
            final OnCopyFinishedListener op) {
        final File applicationDirectory = getApplicationDirectory();
        if (!applicationDirectory.exists()) {
            applicationDirectory.mkdirs();
        }
        File noMedia = new File(applicationDirectory.getPath() + File.separatorChar + ".nomedia");
        if (!noMedia.exists()) {
            try {
                noMedia.createNewFile();
                Log.e(DEBUG_TAG, "Created .nomedia file in: " + noMedia.getAbsolutePath());
            } catch (IOException e) {
                Log.e(DEBUG_TAG, "Unable to create .nomedia file", e);
            }
        }

        String fileName = getFilenameFromUriNoSpace(uri);
        final File destinationFile = new File(applicationDirectory.getPath() + File.separatorChar + fileName);

        Log.d(DEBUG_TAG, "Source file name: " + fileName);
        Log.d(DEBUG_TAG, "Source file uri: " + uri.toString());
        Log.d(DEBUG_TAG, "Destination file: " + destinationFile.getPath());

        Thread copyThread = new Thread(new Runnable() {
            @Override
            public void run() {
                BufferedInputStream bis = null;
                BufferedOutputStream bos = null;
                if (isExternalStorageWritable()) {
                    try {
                        InputStream uriStream = context.getContentResolver().openInputStream(uri);
                        bis = new BufferedInputStream(uriStream);
                        bos = new BufferedOutputStream(new FileOutputStream(destinationFile.getPath(), false));
                        byte[] buf = new byte[1024];
                        while (bis.read(buf) != -1) {
                            bos.write(buf);
                        }
                    } catch (IOException e) {
                        Log.e(DEBUG_TAG, "Unable to copy file from URI", e);

                    } finally {
                        try {
                            if (bis != null)
                                bis.close();
                            if (bos != null)
                                bos.close();
                        } catch (IOException e) {
                            Log.e(DEBUG_TAG, "Unable to close buffers", e);
                        }
                    }
                }
                if (op != null) {
                    op.onOperationFinished();
                }
            }
        });
        copyThread.start();
    }

    /**
     * Checks if the external storage is writeable
     *
     * @return
     */
    public static boolean isExternalStorageWritable() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            return true;
        }
        return false;
    }

    /**
     * Checks if the external storage is readable
     *
     * @return
     */
    public static boolean isExternalStorageReadable() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            return true;
        }
        return false;
    }

    /**
     * Returns the filename from a given path and replaces all spaces with underscores
     *
     * @param uri
     * @return
     */
    public static String getFilenameFromUriNoSpace(Uri uri) {
        String result = null;
        String path = uri.getPath();
        File f = getFile(path);
        result = f.getName().replaceAll("\\s", "_");
        return result;
    }

    /**
     * Deletes a file on external storage
     *
     * @param path
     */
    public static void deleteFile(String path) {
        File file = new File(path);
        if (file.delete()) {
            Log.d(DEBUG_TAG, file.getName() + " is deleted!");
        } else {
            Log.d(DEBUG_TAG, "Delete operation is failed.");
        }
    }

    /**
     * @param path Path of file to get
     * @return File with given path
     */
    public static File getFile(String path) {
        return new File(path);
    }

    /**
     * @return Application directory in external storage
     */
    public static File getApplicationDirectory() {
        return new File(Environment.getExternalStorageDirectory().getPath() + File.separatorChar
                + APP_EXT_STORAGE_FOLDER + File.separatorChar);
    }

    /**
     * Returns a file list of all non-hidden files in the application directory.
     *
     * @return
     */
    public static File[] getAlarmDirectoryFileList() {
        return FileUtil.getApplicationDirectory().listFiles(new FileFilter() {
            @Override
            public boolean accept(File f) {
                return !f.isHidden();
            }
        });
    }

    /**
     * Returns a file list of all non-hidden audio files in the application directory.
     *
     * @return
     */
    public static File[] getAlarmDirectoryAudioFileList(final Context context) {
        return FileUtil.getApplicationDirectory().listFiles(new FileFilter() {
            @Override
            public boolean accept(File f) {
                // Early out if hidden
                if (f.isHidden()) {
                    return false;
                }
                String extension = FilenameUtils.getExtension(f.getPath());
                if (extension.equals(AUDIO_METADATA_FILE_EXTENSION)) {
                    return false;
                }
                return fileIsOK(context, f.getPath());
            }
        });
    }

    public static AlarmSoundPref buildBasicMetaFile(String path) {
        AlarmSoundPref alsg = new AlarmSoundPref();
        String[] meta = MediaUtil.getBasicMetaData(path);
        alsg.setMetaArtist(meta[0]);
        alsg.setMetaTitle(meta[1]);
        alsg.setLength(Integer.valueOf(meta[2]));
        //TODO get hash for file (not path!)
        return alsg;
    }

    /**
     * Writes the sound configuration file based on
     *
     * @param soundFilePath the path of the used sound file and
     * @param alsg          the configuration in form of a AlarmSoundGson object
     */
    public static void writeSoundConfigurationFile(String soundFilePath, AlarmSoundPref alsg) {
        Log.d(DEBUG_TAG, "Writing sound configuration file");
        String configFilePath = getMetaFilePath(soundFilePath);
        File configFile = getFile(configFilePath);
        Gson gs = new Gson();
        String js = gs.toJson(alsg);
        try {
            FileUtils.write(configFile, js, "UTF-8");
        } catch (IOException e) {
            Log.e(DEBUG_TAG, "Could not write audio configuration file", e);
        }
    }

    /**
     * Reads the configuration file for an alarm sound
     *
     * @param soundFilePath Path to the sound file since the configuration is next to it
     * @return
     */
    public static AlarmSoundPref readSoundConfigurationFile(String soundFilePath) {
        Log.d(DEBUG_TAG, "Reading sound configuration file");
        Gson gs = new Gson();
        String metaFilePath = getMetaFilePath(soundFilePath);
        File f = getFile(metaFilePath);
        String js = "";
        try {
            js = FileUtils.readFileToString(f, "UTF-8");
        } catch (FileNotFoundException e) {
            Log.e(DEBUG_TAG, "Could not find configuration file");
            return null;
        } catch (IOException e) {
            Log.e(DEBUG_TAG, "Unable to read file");
            return null;
        }
        return gs.fromJson(js, AlarmSoundPref.class);
    }

    public static String getMetaFilePath(String soundFilePath) {
        return FilenameUtils.removeExtension(soundFilePath) + "." + AUDIO_METADATA_FILE_EXTENSION;
    }

    /**
     * Checks if a file is ok for the application to use
     *
     * @param context
     * @param path
     * @return
     */
    public static boolean fileIsOK(Context context, String path) {
        String mimeType;
        mimeType = FileUtil.getMimeType(context, path);
        if (mimeType == null) {
            Log.d(DEBUG_TAG, "No MIME type found. Returning.");
            return false;
        }
        if (!mimeType.startsWith("audio")) {
            Log.d(DEBUG_TAG, "FileCheck: MIME type does not match requirements");
            return false;
        }
        try {
            MediaUtil.getBasicMetaData(path);
        } catch (RuntimeException e) {
            Log.e(DEBUG_TAG, "Cannot read file");
            return false;
        }
        return true;
    }

    /**
     * Returns a mime type for a file in given path.
     *
     * @param path Path to the file.
     * @return Null if no MIME type is found.
     */
    public static String getMimeType(Context context, String path) {
        Log.d(DEBUG_TAG, "Checking mime type for " + path);
        String mimeType = null;
        String extension = FilenameUtils.getExtension(path);
        if (extension != null) {
            MimeTypeMap mime = MimeTypeMap.getSingleton();
            mimeType = mime.getMimeTypeFromExtension(extension);
            Log.d(DEBUG_TAG, "MimeTypeMap found " + mimeType + " for extension " + extension);
        }
        if (mimeType == null) {
            ContentResolver contentResolver = context.getContentResolver();
            mimeType = contentResolver.getType(Uri.parse(path));
            Log.d(DEBUG_TAG, "ContentResolver found " + mimeType + ".");
        }
        return mimeType;
    }

}