free.yhc.netmbuddy.utils.Utils.java Source code

Java tutorial

Introduction

Here is the source code for free.yhc.netmbuddy.utils.Utils.java

Source

/******************************************************************************
 * Copyright (C) 2012, 2013, 2014
 * Younghyung Cho. <yhcting77@gmail.com>
 * All rights reserved.
 *
 * This file is part of NetMBuddy
 *
 * This program is licensed under the FreeBSD license
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation
 * are those of the authors and should not be interpreted as representing
 * official policies, either expressed or implied, of the FreeBSD Project.
 *****************************************************************************/

package free.yhc.netmbuddy.utils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import org.apache.http.impl.cookie.DateParseException;
import org.apache.http.impl.cookie.DateUtils;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Rect;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Window;
import free.yhc.netmbuddy.R;
import free.yhc.netmbuddy.YTMPActivity;
import free.yhc.netmbuddy.model.Policy;
import free.yhc.netmbuddy.model.RTState;

public class Utils {
    private static final boolean DBG = false;
    private static final Utils.Logger P = new Logger(Utils.class);

    //private static final boolean DBG    = false;
    private static final boolean LOGF = false;
    private static final String TAG = "[YoutubeMusicPlayer]";

    // Value SHOULD match xml preference value for title tts.
    private static final int TITLE_TTS_HEAD = 0x02; // tts at the beginning
    private static final int TITLE_TTS_TAIL = 0x01; // tts at the end

    // This is only for debugging.
    private static boolean sInitialized = false;

    // For debugging
    private static PrintWriter sLogWriter = null;
    private static DateFormat sLogTimeDateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
            DateFormat.MEDIUM, Locale.ENGLISH);

    // Even if these two variables are not 'final', those should be handled like 'final'
    //   because those are set only at init() function, and SHOULD NOT be changed.
    private static Context sAppContext = null;
    private static Handler sUiHandler = null;

    private static SharedPreferences sPrefs = null;
    private static TimeElemComparator sTimeElemComparator = new TimeElemComparator();

    private static final String[] sDateFormats = new String[] {
            // To support W3CDTF
            "yyyy-MM-d'T'HH:mm:ss.SSSZ", "yyyy-MM-d'T'HH:mm:ss.SSS'Z'", "yyyy-MM-d'T'HH:mm:ssZ",
            "yyyy-MM-d'T'HH:mm:ss'Z'", };

    public static enum PrefLevel {
        LOW, NORMAL, HIGH
    }

    public static enum PrefQuality {
        LOW(R.string.low), MIDLOW(R.string.midlow), NORMAL(R.string.normal), HIGH(R.string.high), VERYHIGH(
                R.string.veryhigh);

        private int text;

        private PrefQuality(int aText) {
            text = aText;
        }

        public int getText() {
            return text;
        }

        public static PrefQuality getMatchingQuality(int text) {
            for (PrefQuality q : PrefQuality.values()) {
                if (q.getText() == text)
                    return q;
            }
            return null;
        }
    }

    public static enum PrefTitleSimilarityThreshold {
        VERYLOW(Policy.SIMILARITY_THRESHOLD_VERYLOW), LOW(Policy.SIMILARITY_THRESHOLD_LOW), NORMAL(
                Policy.SIMILARITY_THRESHOLD_NORMAL), HIGH(
                        Policy.SIMILARITY_THRESHOLD_HIGH), VERYHIGH(Policy.SIMILARITY_THRESHOLD_VERYHIGH);

        private float v;

        private PrefTitleSimilarityThreshold(float aV) {
            v = aV;
        }

        public float getValue() {
            return v;
        }
    }

    private static class TimeElem {
        public Object v;
        public long time;

        public TimeElem(Object aV, long aTime) {
            v = aV;
            time = aTime;
        }
    }

    private static class TimeElemComparator implements Comparator<TimeElem> {
        @Override
        public int compare(TimeElem a0, TimeElem a1) {
            if (a0.time < a1.time)
                return -1;
            else if (a0.time > a1.time)
                return 1;
            else
                return 0;
        }
    }

    // ========================================================================
    //
    // Initialization
    //
    // ========================================================================

    public static void init(Context aAppContext) {
        // This is called first for module initialization.
        // So, ANY DEPENDENCY to other module is NOT allowed
        eAssert(!sInitialized);
        if (!sInitialized)
            sInitialized = true;

        new File(Policy.APPDATA_DIR).mkdirs();
        new File(Policy.APPDATA_VIDDIR).mkdirs();
        new File(Policy.APPDATA_LOGDIR).mkdirs();

        // Clear/Create cache directory!
        File cacheF = new File(Policy.APPDATA_CACHEDIR);
        FileUtils.removeFileRecursive(cacheF, cacheF);
        cacheF.mkdirs();

        // Clear/Make temp directory!
        File tempF = new File(Policy.APPDATA_TMPDIR);
        FileUtils.removeFileRecursive(tempF, tempF);
        tempF.mkdirs();

        if (LOGF) {
            new File(Policy.APPDATA_LOGDIR).mkdirs();
            String dateText = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.ENGLISH)
                    .format(new Date(System.currentTimeMillis()));
            dateText = dateText.replace(' ', '_');
            File logF = new File(Policy.APPDATA_LOGDIR + dateText + ".log");
            try {
                sLogWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(logF)));
            } catch (FileNotFoundException e) {
                eAssert(false);
            }
        }

        sAppContext = aAppContext;
        sUiHandler = new Handler();
        sPrefs = PreferenceManager.getDefaultSharedPreferences(getAppContext());

    }

    // ========================================================================
    //
    // Fundamentals
    //
    // ========================================================================
    private static enum LogLV {
        V("[V]", 6), D("[D]", 5), I("[I]", 4), W("[W]", 3), E("[E]", 2), F("[F]", 1);

        private String pref; // prefix string
        private int pri; // priority

        LogLV(String aPref, int aPri) {
            pref = aPref;
            pri = aPri;
        }

        String pref() {
            return pref;
        }

        int pri() {
            return pri;
        }
    }

    public static class Logger {
        private final Class<?> _mCls;

        public Logger(Class<?> cls) {
            _mCls = cls;
        }

        // For logging
        public void v(String msg) {
            log(_mCls, LogLV.V, msg);
        }

        public void d(String msg) {
            log(_mCls, LogLV.D, msg);
        }

        public void i(String msg) {
            log(_mCls, LogLV.I, msg);
        }

        public void w(String msg) {
            log(_mCls, LogLV.W, msg);
        }

        public void e(String msg) {
            log(_mCls, LogLV.E, msg);
        }

        public void f(String msg) {
            log(_mCls, LogLV.F, msg);
        }
    }

    private static void log(Class<?> cls, LogLV lv, String msg) {
        if (null == msg)
            return;

        StackTraceElement ste = Thread.currentThread().getStackTrace()[5];
        msg = ste.getClassName() + "/" + ste.getMethodName() + "(" + ste.getLineNumber() + ") : " + msg;

        if (!LOGF) {
            switch (lv) {
            case V:
                Log.v(cls.getSimpleName(), msg);
                break;
            case D:
                Log.d(cls.getSimpleName(), msg);
                break;
            case I:
                Log.i(cls.getSimpleName(), msg);
                break;
            case W:
                Log.w(cls.getSimpleName(), msg);
                break;
            case E:
                Log.e(cls.getSimpleName(), msg);
                break;
            case F:
                Log.wtf(cls.getSimpleName(), msg);
                break;
            }
        } else {
            long timems = System.currentTimeMillis();
            sLogWriter.printf("<%s:%03d> [%s] %s\n", sLogTimeDateFormat.format(new Date(timems)), timems % 1000,
                    lv.name(), msg);
            sLogWriter.flush();
        }
    }

    // Assert
    public static void eAssert(boolean cond) {
        if (!cond)
            throw new AssertionError();
    }

    public static Context getAppContext() {
        return sAppContext;
    }

    public static Resources getResources() {
        return getAppContext().getResources();
    }

    public static String getResString(int id) {
        return getResources().getString(id);
    }

    public static Handler getUiHandler() {
        return sUiHandler;
    }

    public static boolean isUiThread(Thread thread) {
        return thread == sUiHandler.getLooper().getThread();
    }

    public static boolean isUiThread() {
        return isUiThread(Thread.currentThread());
    }
    // ========================================================================
    //
    //
    //
    // ========================================================================

    /**
     * Is is valid string?
     * Valid means "Not NULL and Not empty".
     * @param v
     * @return
     */
    public static boolean isValidValue(CharSequence v) {
        return !(null == v || v.length() <= 0);
    }

    /**
     * Is any available active network at this device?
     * @return
     */
    public static boolean isNetworkAvailable() {

        ConnectivityManager cm = (ConnectivityManager) getAppContext()
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo ni;

        if (isPrefUseWifiOnly())
            ni = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        else
            ni = cm.getActiveNetworkInfo();

        if (null != ni)
            return ni.isConnectedOrConnecting();
        else
            return false;
    }

    public static String getCurrentTopActivity() {
        ActivityManager am = (ActivityManager) getAppContext().getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
        ActivityManager.RunningTaskInfo ar = tasks.get(0);
        return ar.topActivity.getClassName().toString();
    }

    public static boolean isAppForeground() {
        return getCurrentTopActivity().startsWith(getAppContext().getPackageName() + ".");
    }

    public static void resumeApp() {
        Intent intent = new Intent(Utils.getAppContext(), YTMPActivity.class);
        intent.setAction(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        Utils.getAppContext().startActivity(intent);
    }

    // ------------------------------------------------------------------------
    //
    //
    //
    // ------------------------------------------------------------------------
    public static long[] convertArrayLongTolong(Long[] L) {
        long[] l = new long[L.length];
        for (int i = 0; i < L.length; i++)
            l[i] = L[i];
        return l;
    }

    public static int[] convertArrayIntegerToint(Integer[] I) {
        int[] i = new int[I.length];
        for (int j = 0; j < I.length; j++)
            i[j] = I[j];
        return i;
    }

    // ------------------------------------------------------------------------
    //
    // Date
    //
    // ------------------------------------------------------------------------
    public static String removeLeadingTrailingWhiteSpace(String s) {
        s = s.replaceFirst("^\\s+", "");
        return s.replaceFirst("\\s+$", "");
    }

    public static Date parseDateString(String dateString) {
        dateString = removeLeadingTrailingWhiteSpace(dateString);
        Date date = null;
        try {
            date = DateUtils.parseDate(dateString, sDateFormats);
        } catch (DateParseException e) {
        }
        return date;
    }

    // ------------------------------------------------------
    // To handle generic array
    // ------------------------------------------------------
    public static <T> T[] toArray(List<T> list, T[] a) {
        if (a.length < list.size())
            a = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), list.size());
        return list.toArray(a);
    }

    public static <T> T[] toArray(List<T> list, Class<T> k) {
        return list.toArray((T[]) java.lang.reflect.Array.newInstance(k, list.size()));
    }

    public static <T> T[] newArray(Class<T> k, int size) {
        return (T[]) java.lang.reflect.Array.newInstance(k, size);
    }

    // ------------------------------------------------------------------------
    //
    // Accessing preference
    //
    // ------------------------------------------------------------------------
    private static String getStringPreference(String key, String defvalue) {
        String value = (String) RTState.get().getOverridingPreference(key);
        if (null == value)
            value = sPrefs.getString(key, defvalue);
        return value;
    }

    private static int getIntPreference(String key, int defvalue) {
        Integer value = (Integer) RTState.get().getOverridingPreference(key);
        if (null == value)
            value = sPrefs.getInt(key, defvalue);
        return value;
    }

    private static boolean getBooleanPreference(String key, boolean defvalue) {
        Boolean value = (Boolean) RTState.get().getOverridingPreference(key);
        if (null == value)
            value = sPrefs.getBoolean(key, defvalue);
        return value;
    }

    public static SharedPreferences getSharedPreference() {
        return sPrefs;
    }

    public static boolean isPrefSuffle() {
        return getBooleanPreference(getResString(R.string.csshuffle), false);
    }

    public static boolean isPrefRepeat() {
        return getBooleanPreference(getResString(R.string.csrepeat), false);
    }

    public static PrefQuality getPrefQuality() {
        String v = getStringPreference(getResString(R.string.csquality), getResString(R.string.csNORMAL));
        for (PrefQuality q : PrefQuality.values()) {
            if (q.name().equals(v))
                return q;
        }
        eAssert(false);
        return null;
    }

    public static float getPrefTitleSimilarityThreshold() {
        String v = getStringPreference(getResString(R.string.cstitle_similarity_threshold),
                getResString(R.string.csNORMAL));
        for (PrefTitleSimilarityThreshold q : PrefTitleSimilarityThreshold.values()) {
            if (q.name().equals(v))
                return q.getValue();
        }
        eAssert(false);
        return Policy.SIMILARITY_THRESHOLD_NORMAL;
    }

    public static PrefLevel getPrefMemConsumption() {
        // See preference.xml for meaning of each number value.
        String lv = sPrefs.getString(getResString(R.string.csmem_consumption), getResString(R.string.csNORMAL));
        if (getResString(R.string.csLOW).equals(lv))
            return PrefLevel.LOW;
        else if (getResString(R.string.csNORMAL).equals(lv))
            return PrefLevel.NORMAL;
        else if (getResString(R.string.csHIGH).equals(lv))
            return PrefLevel.HIGH;
        else {
            eAssert(false);
            return PrefLevel.NORMAL;
        }
    }

    public static boolean isPrefLockScreen() {
        return getBooleanPreference(getResString(R.string.cslockscreen), false);
    }

    public static boolean isPrefStopOnBack() {
        return getBooleanPreference(getResString(R.string.csstop_on_back), true);
    }

    public static boolean isPrefErrReport() {
        return getBooleanPreference(getResString(R.string.cserr_report), true);
    }

    private static boolean isPrefUseWifiOnly() {
        return getBooleanPreference(getResString(R.string.csuse_wifi_only), true);
    }

    public static int getPrefTtsValue() {
        int value = 0;
        try {
            value = Integer.parseInt(sPrefs.getString(getResString(R.string.cstitle_tts), "0"));
        } catch (NumberFormatException ignored) {
        }
        return value;
    }

    public static boolean isPrefTtsEnabled() {
        return 0 != getPrefTtsValue();
    }

    public static boolean isPrefHeadTts() {
        return (0 != (TITLE_TTS_HEAD & getPrefTtsValue()));
    }

    public static boolean isPrefTailTts() {
        return (0 != (TITLE_TTS_TAIL & getPrefTtsValue()));
    }

    // ------------------------------------------------------------------------
    //
    // Min Max
    //
    // ------------------------------------------------------------------------
    public static float max(float f0, float f1) {
        return (f0 < f1) ? f1 : f0;
    }

    // ------------------------------------------------------------------------
    //
    // Bit mask handling
    //
    // ------------------------------------------------------------------------
    public static long bitClear(long flag, long mask) {
        return flag & ~mask;
    }

    public static long bitSet(long flag, long value, long mask) {
        flag = bitClear(flag, mask);
        return flag | (value & mask);
    }

    public static boolean bitCompare(long flag, long value, long mask) {
        return value == (flag & mask);
    }

    public static boolean bitIsSet(long flag, long mask) {
        return bitCompare(flag, mask, mask);
    }

    public static boolean bitIsClear(long flag, long mask) {
        return bitCompare(flag, 0, mask);
    }

    public static int bitClear(int flag, int mask) {
        return flag & ~mask;
    }

    public static int bitSet(int flag, int value, int mask) {
        flag = bitClear(flag, mask);
        return flag | (value & mask);
    }

    public static boolean bitCompare(int flag, int value, int mask) {
        return value == (flag & mask);
    }

    public static boolean bitIsSet(int flag, int mask) {
        return bitCompare(flag, mask, mask);
    }

    public static boolean bitIsClear(int flag, int mask) {
        return bitCompare(flag, 0, mask);
    }

    // ------------------------------------------------------------------------
    //
    // Misc
    //
    // ------------------------------------------------------------------------
    public static String secsToTimeText(int secs) {
        int h = secs / 60 / 60;
        secs -= h * 60 * 60;
        int m = secs / 60;
        secs -= m * 60;
        return String.format("%02d:%02d:%02d", h, m, secs);
    }

    public static String secsToMinSecText(int secs) {
        int m = secs / 60;
        secs -= m * 60;
        return String.format("%02d:%02d", m, secs);
    }

    public static String millisToHourMinText(long millies) {
        int s = (int) (millies / 1000);
        int m = s / 60;
        int h = m / 60;
        m -= h * 60;
        return String.format("%02d:%02d", h, m);
    }

    public static void copy(OutputStream os, InputStream is) throws IOException, InterruptedException {
        byte buf[] = new byte[1024 * 16];
        int len;
        while ((len = is.read(buf)) > 0) {
            if (Thread.currentThread().isInterrupted())
                throw new InterruptedException();
            os.write(buf, 0, len);
        }
    }

    public static <K, V> K findKey(HashMap<K, V> map, V value) {
        Iterator<K> iter = map.keySet().iterator();
        while (iter.hasNext()) {
            K key = iter.next();
            if (map.get(key).equals(value))
                return key;
        }
        return null;
    }

    public static Object[] getSortedKeyOfTimeMap(HashMap<? extends Object, Long> timeMap) {
        TimeElem[] te = new TimeElem[timeMap.size()];
        Object[] vs = timeMap.keySet().toArray(new Object[0]);
        for (int i = 0; i < vs.length; i++)
            te[i] = new TimeElem(vs[i], timeMap.get(vs[i]));
        Arrays.sort(te, sTimeElemComparator);
        Object[] sorted = new Object[vs.length];
        for (int i = 0; i < sorted.length; i++)
            sorted[i] = te[i].v;

        return sorted;
    }

    // ------------------------------------------------------------------------
    //
    // Other android specifics.
    //
    // ------------------------------------------------------------------------
    public static boolean copyAssetFile(String dest, String assetFile) {
        try {
            InputStream is = Utils.getAppContext().getAssets().open(assetFile);
            FileOutputStream os = new FileOutputStream(new File(dest));
            copy(os, is);
            is.close();
            os.close();
            return true;
        } catch (InterruptedException e) {
            return false;
        } catch (IOException e) {
            return false;
        }
    }

    public static void sendMail(Context context, String receiver, String subject, String text, File attachment) {
        if (!Utils.isNetworkAvailable())
            return;

        Intent intent = new Intent(Intent.ACTION_SEND);
        if (null != receiver)
            intent.putExtra(Intent.EXTRA_EMAIL, new String[] { receiver });
        intent.putExtra(Intent.EXTRA_TEXT, text);
        intent.putExtra(Intent.EXTRA_SUBJECT, subject);
        if (null != attachment)
            intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(attachment));
        intent.setType("message/rfc822");
        try {
            context.startActivity(intent);
        } catch (ActivityNotFoundException e) {
            UiUtils.showTextToast(context, R.string.msg_fail_find_app);
        }
    }

    /**
     * Only available when status bar is showing.
     * @param activity
     * @return
     */
    public static int getStatusBarHeight(Activity activity) {
        Rect rect = new Rect();
        Window window = activity.getWindow();
        window.getDecorView().getWindowVisibleDisplayFrame(rect);
        // Below is for future reference.
        // int StatusBarHeight = rect.top;
        // int contentViewTop = window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
        // int TitleBarHeight= contentViewTop - StatusBarHeight;
        return rect.top;
    }

    public static Rect getVisibleFrame(Activity activity) {
        Rect rect = new Rect();
        Window window = activity.getWindow();
        window.getDecorView().getWindowVisibleDisplayFrame(rect);
        return rect;
    }
}