com.github.feribg.audiogetter.helpers.Utils.java Source code

Java tutorial

Introduction

Here is the source code for com.github.feribg.audiogetter.helpers.Utils.java

Source

package com.github.feribg.audiogetter.helpers;

import android.os.Build;
import android.util.Log;

import com.github.feribg.audiogetter.config.App;
import com.github.feribg.audiogetter.config.Constants;

import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.message.BasicNameValuePair;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Utils {

    /*
     * calculateMD5(File file)
    * -----------------------
    *
    * Copyright (C) 2012 The CyanogenMod Project
    *
    * * Licensed under the GNU GPLv2 license
    *
    * The text of the license can be found in the LICENSE_GPL file
    * or at https://www.gnu.org/licenses/gpl-2.0.txt
    */
    public static String calculateMD5(File file) {
        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            Log.e(App.TAG, "Exception while getting Digest", e);
            return null;
        }

        InputStream is;
        try {
            is = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            Log.e(App.TAG, "Exception while getting FileInputStream", e);
            return null;
        }

        byte[] buffer = new byte[8192];
        int read;
        try {
            while ((read = is.read(buffer)) > 0) {
                digest.update(buffer, 0, read);
            }
            byte[] md5sum = digest.digest();
            BigInteger bigInt = new BigInteger(1, md5sum);
            String output = bigInt.toString(16);
            // Fill to 32 chars
            output = String.format("%32s", output).replace(' ', '0');
            return output;
        } catch (IOException e) {
            //throw new RuntimeException("Unable to process file for MD5", e);
            Log.e(App.TAG, "Unable to process file for MD5", e); //TODO check if actually avoid FC
            return "00000000000000000000000000000000"; // fictional bad MD5: needed without "throw new RuntimeException"
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                Log.e(App.TAG, "Exception on closing MD5 input stream", e);
            }
        }
    }

    /**
     * Copy a file with the option to overwrite existing files
     *
     * @param src
     * @param dst
     * @param overwrite
     * @throws IOException
     */
    public static void copyFile(File src, File dst, Boolean overwrite) throws IOException {
        FileChannel inChannel = new FileInputStream(src).getChannel();
        FileChannel outChannel = new FileOutputStream(dst).getChannel();
        if (!dst.exists() || (dst.exists() && overwrite)) {
            try {
                if (dst.exists()) {
                    Log.d(App.TAG, "copyFile: destination exists but overwriting");
                }
                inChannel.transferTo(0, inChannel.size(), outChannel);
            } finally {
                if (inChannel != null)
                    inChannel.close();
                if (outChannel != null)
                    outChannel.close();
            }
        } else {
            Log.e(App.TAG, "copyFile: destination already exists:" + dst.getAbsolutePath());
            throw new IOException("copyFile: destination already exists:" + dst.getAbsolutePath());
        }
    }

    /**
     * Return a string containing specific CPU information for the device
     *
     * @return
     */
    public static String getCpuInfo() {
        StringBuffer sb = new StringBuffer();
        sb.append("abi: ").append(Build.CPU_ABI).append("\n");
        if (new File("/proc/cpuinfo").exists()) {
            try {
                BufferedReader br = new BufferedReader(new FileReader(new File("/proc/cpuinfo")));
                String aLine;
                while ((aLine = br.readLine()) != null) {
                    sb.append(aLine + "\n");
                }
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }

    /**
     * Returns the correct arm version for use with ffmpeg
     *
     * @return
     */
    public static int armCpuVersion() {
        String cpuAbi = Build.CPU_ABI;
        Log.d(App.TAG, "CPU_ABI: " + cpuAbi);
        if (cpuAbi.equals("armeabi-v7a")) {
            return 7;
        } else if (cpuAbi.equals("armeabi")) {
            return 5;
        } else {
            return 0;
        }
    }

    /**
     * Make byte size in a readable format
     *
     * @param bytes
     * @param decimal
     * @return
     */
    public static String makeSizeHumanReadable(long bytes, boolean decimal) {
        String hr = "-";
        int unit = decimal ? 1000 : 1024;
        if (bytes < unit) {
            hr = bytes + " B";
        } else {
            int exp = (int) (Math.log(bytes) / Math.log(unit));
            String pre = (decimal ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (decimal ? "" : "i");
            hr = String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
        }
        hr = hr.replace("-1 B", "-").replace("0 B", "-");
        return hr;
    }

    /**
     * Return integer percentage amount
     *
     * @param complete
     * @param total
     * @return
     */
    public static int normalizePercent(long complete, long total) {
        if (total == 0) {
            return 0;
        }
        return Math.round(complete * 100 / total);
    }

    /**
     * Clean the filename, stripping illegal chars
     *
     * @param filename any string to be used for filename
     * @return clean filesystem safe filename
     */
    public static String cleanFilename(String filename) {
        filename = filename.replaceAll("[^a-z\\(\\)A-Z0-9\\.\\-]", "_");
        return filename;
    }

    /**
     * Merge two byte arrays
     *
     * @param arr1 first array
     * @param arr2 second array
     * @return combined byte array
     */
    public static byte[] mergeArrays(byte[] arr1, byte[] arr2) {
        byte[] combined = new byte[arr1.length + arr2.length];

        System.arraycopy(arr1, 0, combined, 0, arr1.length);
        System.arraycopy(arr2, 0, combined, arr1.length, arr2.length);
        return combined;
    }

    /**
     * Given a packet length generate a valid ADTS header to wrap it into
     *
     * @param packetLen number of bytes for that packet
     * @return correct byte array for ADTS header
     */
    private static byte[] generateAdtsHeader(int packetLen) {
        byte[] packet = new byte[7];
        packetLen += 7; //packet length must count the ADTS header itself
        int profile = 2; //AAC LC
        //39=MediaCodecInfo.CodecProfileLevel.AACObjectELD;
        int freqIdx = 4; //44.1KHz
        int chanCfg = 2; //CPE

        // fill in ADTS data
        packet[0] = (byte) 0xFFF;
        packet[1] = (byte) 0xF9;
        packet[2] = (byte) (((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2));
        packet[3] = (byte) (((chanCfg & 3) << 6) + (packetLen >> 11));
        packet[4] = (byte) ((packetLen & 0x7FF) >> 3);
        packet[5] = (byte) (((packetLen & 7) << 5) + 0x1F);
        packet[6] = (byte) 0xFC;

        return packet;
    }

    /**
     * @param path    relative path for the resource including / prefix
     * @param qparams NameValuePair list of parameters
     * @return a correctly formatted and urlencoded string
     * @throws URISyntaxException
     */
    public static URI getUri(String scheme, String path, List<NameValuePair> qparams) throws URISyntaxException {
        return URIUtils.createURI(scheme, Constants.Backend.API_HOST, -1, path,
                URLEncodedUtils.format(qparams, "UTF-8"), null);
    }

    /**
     * Prepare soundcloud search URL
     * @param query
     * @param offset
     * @return
     * @throws URISyntaxException
     */
    public static URI getSoundCloudSearchURI(String query, Integer offset) throws URISyntaxException {
        List<NameValuePair> qparams = new ArrayList<NameValuePair>();
        qparams.add(new BasicNameValuePair("client_id", Constants.Soundcloud.CLIENT_ID));
        qparams.add(new BasicNameValuePair("offset", String.valueOf(offset)));
        qparams.add(new BasicNameValuePair("limit", String.valueOf(Constants.Soundcloud.PER_PAGE)));
        qparams.add(new BasicNameValuePair("q", query));
        return URIUtils.createURI(Constants.Soundcloud.API_SCHEME, Constants.Soundcloud.API_HOST, -1,
                Constants.Soundcloud.API_SEARCH, URLEncodedUtils.format(qparams, "UTF-8"), null);
    }

    /**
     * Used to build an mp3 skull search query. An initial request might be needed to fetch the
     * CSRF token from the page source before searching
     * @param query
     * @param csrf
     * @return
     * @throws URISyntaxException
     */
    public static URI getMp3SkullSearchURI(String query, String csrf) throws URISyntaxException {
        List<NameValuePair> qparams = new ArrayList<NameValuePair>();
        qparams.add(new BasicNameValuePair("q", query));
        qparams.add(new BasicNameValuePair("fckh", csrf));
        return URIUtils.createURI(Constants.Mp3skull.API_SCHEME, Constants.Mp3skull.API_HOST, -1,
                Constants.Mp3skull.API_SEARCH, URLEncodedUtils.format(qparams, "UTF-8"), null);
    }

    /**
     * Get the base Mp3Skull url to determine CSRF token for the session
     * @return
     * @throws URISyntaxException
     */
    public static URI getMp3SkullBaseURI() throws URISyntaxException {
        return URIUtils.createURI(Constants.Mp3skull.API_SCHEME, Constants.Mp3skull.API_HOST, -1, null, null, null);
    }

    /**
     * Prepare Vimeo search URL
     * @param query
     * @param page
     * @return
     * @throws URISyntaxException
     */
    public static URI getVimeoSearchURI(String query, Integer page) throws URISyntaxException {
        List<NameValuePair> qparams = new ArrayList<NameValuePair>();
        qparams.add(new BasicNameValuePair("query", query));
        qparams.add(new BasicNameValuePair("page", String.valueOf(page)));
        qparams.add(new BasicNameValuePair("per_page", String.valueOf(Constants.Vimeo.PER_PAGE)));
        return URIUtils.createURI(Constants.Vimeo.API_SCHEME, Constants.Vimeo.API_HOST, -1,
                Constants.Vimeo.API_SEARCH, URLEncodedUtils.format(qparams, "UTF-8"), null);
    }

    /**
     * Prepare a valid Youtube API request URI
     * @param query
     * @param pageToken
     * @return
     * @throws URISyntaxException
     */
    public static URI getYoutubeSearchURI(String query, String pageToken) throws URISyntaxException {
        List<NameValuePair> qparams = new ArrayList<NameValuePair>();
        qparams.add(new BasicNameValuePair("q", query));
        //if there is a specific page to load
        if (pageToken != null && pageToken.length() > 0) {
            qparams.add(new BasicNameValuePair("pageToken", pageToken));
        }
        qparams.add(new BasicNameValuePair("part", "snippet,id"));
        qparams.add(new BasicNameValuePair("maxResults", String.valueOf(Constants.Youtube.PER_PAGE)));
        qparams.add(new BasicNameValuePair("safeSearch", Constants.Youtube.SAFE_SEARCH));
        qparams.add(new BasicNameValuePair("type", Constants.Youtube.TYPE));
        qparams.add(new BasicNameValuePair("key", Constants.Youtube.API_TOKEN));
        return URIUtils.createURI(Constants.Youtube.API_SCHEME, Constants.Youtube.API_HOST, -1,
                Constants.Youtube.API_SEARCH, URLEncodedUtils.format(qparams, "UTF-8"), null);
    }

    /**
     * Break a list of strings into multiple lists of given max size partitionSize
     *
     * @param originalList  the original list
     * @param partitionSize max number of elements per list
     * @return a list of paritioned lists
     */
    public static List<List> partition(List originalList, int partitionSize) {
        List<List> partitions = new LinkedList<List>();
        for (int i = 0; i < originalList.size(); i += partitionSize) {
            partitions.add(originalList.subList(i, i + Math.min(partitionSize, originalList.size() - i)));
        }
        return partitions;
    }

    /**
     * Extract a list of urls from a string
     * Retrieved from: http://www.java-tutorial.ch/core-java-tutorial/extract-urls-using-java-regular-expressions
     *
     * @param value
     * @return
     */
    public static List<String> extractUrls(String value) {
        List<String> result = new ArrayList<String>();
        String urlPattern = "((https?):((//)|(\\\\))+[\\w\\d:#@%/;$()~_?\\+-=\\\\\\.&]*)";
        Pattern p = Pattern.compile(urlPattern, Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(value);
        while (m.find()) {
            result.add(value.substring(m.start(0), m.end(0)));
        }
        return result;
    }

}