org.zoumbox.mh_dla_notifier.MhDlaNotifierUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.zoumbox.mh_dla_notifier.MhDlaNotifierUtils.java

Source

/*
 * #%L
 * MountyHall DLA Notifier
 * $Id$
 * $HeadURL$
 * %%
 * Copyright (C) 2012 - 2014 Zoumbox.org
 * %%
 * This program 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/gpl-3.0.html>.
 * #L%
 */
package org.zoumbox.mh_dla_notifier;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.commons.codec.binary.Hex;

import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;

/**
 * @author Arno <arno@zoumbox.org>
 */
public class MhDlaNotifierUtils {

    private static final String TAG = MhDlaNotifierConstants.LOG_PREFIX + MhDlaNotifierUtils.class.getSimpleName();

    public static final int BLASON_MAX_SIZE = 1024;
    public static final int BLASON_WIDGET_MAX_SIZE = 300;

    public static final String INTPUT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String HOUR_DATE_FORMAT = "HH:mm:ss";
    public static final String HOUR_NO_SEC_DATE_FORMAT = "HH:mm";
    public static final String DAY_DATE_FORMAT = "dd MMM";
    public static final String DISPLAY_DATE_FORMAT = DAY_DATE_FORMAT + " - " + HOUR_DATE_FORMAT;

    public static final String BLASON_FILES_PREFIX = "v0.13.3_";

    protected static final String N_C = "n/c";

    public static final Predicate<Date> IS_IN_THE_FUTURE = new Predicate<Date>() {
        @Override
        public boolean apply(Date date) {
            if (date == null) {
                return false;
            }
            boolean result = date.after(new Date());
            return result;
        }
    };
    protected static final int CROP_PADDING = 10;

    /**
     * Encodes a raw byte[] to an hexadecimal String
     *
     * @param raw the byte[] to encode
     * @return the hexadecimal encoded text
     */
    public static String toHexadecimal(byte[] raw) {
        String result = null;
        if (raw != null) {
            result = new String(Hex.encodeHex(raw));
        }
        return result;
    }

    public static String md5(String text) {
        if (!Strings.isNullOrEmpty(text)) {
            try {
                // Create MD5 Hash
                MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
                digest.update(text.getBytes());
                byte messageDigest[] = digest.digest();

                String result = toHexadecimal(messageDigest);
                return result;

            } catch (NoSuchAlgorithmException nsae) {
                Log.e(TAG, "Algo MD5 non trouv", nsae);
            }
        }
        return "";
    }

    public static TimeZone getSpTimeZone() {
        TimeZone result = TimeZone.getTimeZone("Europe/Paris");
        return result;
    }

    public static TimeZone getDisplayTimeZone(Context context) {
        PreferencesHolder preferences = PreferencesHolder.load(context);
        TimeZone result = getDisplayTimeZone(preferences.timeZoneId);
        return result;
    }

    public static TimeZone getDisplayTimeZone(String timeZoneId) {
        TimeZone result;
        if (Strings.isNullOrEmpty(timeZoneId) || "default".equalsIgnoreCase(timeZoneId)) {
            // Heure du serveur MH
            result = getSpTimeZone();
        } else if ("system".equalsIgnoreCase(timeZoneId)) {
            // Heure du tlphone
            result = TimeZone.getDefault();
        } else {
            // Heure custom
            try {
                result = TimeZone.getTimeZone(timeZoneId);
            } catch (Exception eee) {
                result = getSpTimeZone();
            }
        }
        return result;
    }

    public static Date parseSpDate(String input) {
        Date result = null;
        if (input != null) {
            DateFormat inputDF = new SimpleDateFormat(INTPUT_DATE_FORMAT);
            inputDF.setTimeZone(getSpTimeZone());
            try {
                result = inputDF.parse(input);
            } catch (ParseException pe) {
                Log.e(TAG, "Date mal formate ", pe);
            }
        }
        return result;
    }

    //    public static String formatDate(String input) {
    //        Date date = parseSpDate(input);
    //        String result = formatDate(date);
    //        return result;
    //    }

    public static String formatDLAForDisplay(Context context, Date input) {
        String result = N_C;
        if (input != null) {
            CharSequence format = context.getText(R.string.dla_format);
            DateFormat outputDF = new SimpleDateFormat(format.toString(), Locale.FRENCH);
            outputDF.setTimeZone(getDisplayTimeZone(context));
            result = outputDF.format(input);
        }
        return result;
    }

    public static String formatDLAForDisplayShort(Context context, Date input) {
        String result = N_C;
        if (input != null) {
            CharSequence format = context.getText(R.string.dla_format_short);
            DateFormat outputDF = new SimpleDateFormat(format.toString(), Locale.FRENCH);
            outputDF.setTimeZone(getDisplayTimeZone(context));
            result = outputDF.format(input);
        }
        return result;
    }

    //    public static String formatDate(Date input) {
    //        String result = N_C;
    //        if (input != null) {
    //            DateFormat outputDF = new SimpleDateFormat(DISPLAY_DATE_FORMAT, Locale.FRENCH);
    //            result = outputDF.format(input);
    //        }
    //        return result;
    //    }

    public static String formatDay(Date input) {
        String result = N_C;
        if (input != null) {
            DateFormat outputDF = new SimpleDateFormat(DAY_DATE_FORMAT, Locale.FRENCH);
            result = outputDF.format(input);
        }
        return result;
    }

    public static String formatHour(Date input) {
        String result = N_C;
        if (input != null) {
            DateFormat outputDF = new SimpleDateFormat(HOUR_DATE_FORMAT, Locale.FRENCH);
            result = outputDF.format(input);
        }
        return result;
    }

    public static String formatHourNoSecondsForDisplay(Context context, Date input) {
        String result = N_C;
        if (input != null) {
            DateFormat outputDF = new SimpleDateFormat(HOUR_NO_SEC_DATE_FORMAT, Locale.FRENCH);
            outputDF.setTimeZone(getDisplayTimeZone(context));
            result = outputDF.format(input);
        }
        return result;
    }

    //    public static final Function<Double, String> PRETTY_PRINT_DURATION_DOUBLE = new Function<Double, String>() {
    //        @Override
    //        public String apply(Double duration) {
    //            int durationInt = ((Double)Math.floor(duration)).intValue();
    //            int durationHours = durationInt / 60;
    //            int durationMinutes = durationInt % 60;
    //            Double durationSeconds = 60d * (duration - Math.floor(duration));
    //            String result;
    //            String hours = String.format("%d heures", durationHours);
    //            String minutes = String.format("%d minute", durationMinutes);
    //            if (durationMinutes > 1) {
    //                minutes += "s";
    //            }
    //            if (durationSeconds > 0) {
    //                String seconds = String.format("%.0f seconde", durationSeconds);
    //                if (durationSeconds > 1) {
    //                    seconds += "s";
    //                }
    //                result = String.format("%s, %s et %s", hours, minutes, seconds);
    //            } else {
    //                result = String.format("%s et %s", hours, minutes);
    //            }
    //
    //            return result;
    //        }
    //    };

    //    public static final Function<Integer, String> PRETTY_PRINT_DURATION = new Function<Integer, String>() {
    //        @Override
    //        public String apply(Integer duration) {
    //            int durationHours = duration / 60;
    //            int durationMinutes = duration % 60;
    //            String hours = String.format("%d heures", durationHours);
    //            String minutes = String.format("%d minute", durationMinutes);
    //            if (durationMinutes > 1) {
    //                minutes += "s";
    //            }
    //            String result = String.format("%s et %s", hours, minutes);
    //
    //            return result;
    //        }
    //    };

    public static String prettyPrintDuration(Context context, Integer duration) {
        int durationHours = duration / 60;
        int durationMinutes = duration % 60;
        CharSequence format = context.getText(R.string.dla_duration_format);
        String result = String.format(format.toString(), durationHours, durationMinutes);
        return result;
    }

    public static Date substractMinutes(Date date, int minutes) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, -minutes);
        Date result = calendar.getTime();
        return result;
    }

    public static void toast(Context context, CharSequence message, Object... args) {
        if (message != null) {
            String messageString = message.toString();
            if (args != null) {
                messageString = String.format(messageString, args);
            }
            Toast.makeText(context, messageString, Toast.LENGTH_LONG).show();
        }
    }

    public static Bitmap loadBlason(String blasonUrl, File filesDir) {
        Bitmap result = loadBlason0(blasonUrl, filesDir, BLASON_MAX_SIZE);
        return result;
    }

    public static Bitmap loadBlasonForWidget(String blasonUrl, File filesDir) {
        Bitmap result = loadBlason0(blasonUrl, filesDir, BLASON_WIDGET_MAX_SIZE);
        return result;
    }

    protected static Bitmap loadBlason0(String blasonUrl, File filesDir, int blasonMaxSize) {
        Bitmap result = null;
        if (!Strings.isNullOrEmpty(blasonUrl)) {
            String fileName = BLASON_FILES_PREFIX + MhDlaNotifierUtils.md5(blasonUrl) + "_" + blasonMaxSize;
            File localFile = new File(filesDir, fileName);
            Log.i(TAG, "localFile: " + localFile);
            if (!localFile.exists()) {

                result = loadAndCropBlason(blasonUrl, filesDir);

                if (result != null && (result.getWidth() > blasonMaxSize || result.getHeight() > blasonMaxSize)) {

                    double blasonMaxSizeDouble = blasonMaxSize;

                    double factor = Math.min(blasonMaxSizeDouble / result.getWidth(),
                            blasonMaxSizeDouble / result.getHeight());
                    int newWidth = (int) (result.getWidth() * factor);
                    int newHeight = (int) (result.getHeight() * factor);
                    Log.i(TAG, String.format("Will resize from %dx%d to %dx%d", result.getWidth(),
                            result.getHeight(), newWidth, newHeight));

                    result = Bitmap.createScaledBitmap(result, newWidth, newHeight, true);

                    Log.i(TAG, "Save resized result to " + localFile);
                    FileOutputStream fos = null;
                    try {
                        fos = new FileOutputStream(localFile);

                        result.compress(Bitmap.CompressFormat.PNG, 90, fos);

                    } catch (Exception eee) {
                        Log.e(TAG, "Exception", eee);
                    } finally {
                        closeQuitely(fos);
                    }
                }

            } else {

                Log.i(TAG, "Existing, loading from cache");
                BufferedInputStream bis = null;
                try {
                    bis = new BufferedInputStream(new FileInputStream(localFile));

                    result = BitmapFactory.decodeStream(bis);

                    bis.close();
                } catch (Exception eee) {
                    Log.e(TAG, "Exception", eee);
                } finally {
                    closeQuitely(bis);
                }
            }
        }
        return result;
    }

    protected static void closeQuitely(Closeable closeable) {
        try {
            if (closeable != null) {
                closeable.close();
            }
        } catch (IOException e) {
            Log.e(TAG, "Un exception occurred", e);
        }
    }

    protected static Bitmap loadAndCropBlason(String blasonUrl, File filesDir) {

        Bitmap result = null;
        if (!Strings.isNullOrEmpty(blasonUrl)) {
            String fileName = BLASON_FILES_PREFIX + MhDlaNotifierUtils.md5(blasonUrl) + "_cropped";
            File localFile = new File(filesDir, fileName);
            Log.i(TAG, "localFile: " + localFile);
            if (!localFile.exists()) {

                Bitmap rawBlason = loadRawBlason(blasonUrl, filesDir);

                if (rawBlason != null) {
                    int minX = Integer.MAX_VALUE;
                    int minY = Integer.MAX_VALUE;
                    int maxX = Integer.MIN_VALUE;
                    int maxY = Integer.MIN_VALUE;
                    for (int x = 0; x < rawBlason.getWidth(); x++) {
                        for (int y = 0; y < rawBlason.getHeight(); y++) {
                            int pixel = rawBlason.getPixel(x, y);
                            int alpha = (pixel >> 24) & 0xff;
                            boolean transparent = alpha == 0;
                            if (!transparent) {
                                minX = Math.min(minX, x);
                                minY = Math.min(minY, y);
                                maxX = Math.max(maxX, x);
                                maxY = Math.max(maxY, y);
                            }
                        }
                    }

                    int cropMinX = Math.max(0, minX - CROP_PADDING);
                    int cropMinY = Math.max(0, minY - CROP_PADDING);
                    int cropMaxX = Math.min(rawBlason.getWidth() - 1, maxX + CROP_PADDING);
                    int cropMaxY = Math.min(rawBlason.getHeight() - 1, maxY + CROP_PADDING);

                    Log.i(TAG,
                            "Size info: " + rawBlason.getWidth() + "x" + rawBlason.getHeight() + " ; "
                                    + "Alpha info: min=" + minX + "x" + minY + " ; max=" + maxX + "x" + maxY + " ; "
                                    + "Crop info: min=" + cropMinX + "x" + cropMinY + " ; max=" + cropMaxX + "x"
                                    + cropMaxY);

                    if (cropMinX > 0 || cropMinY > 0 || cropMaxX < rawBlason.getWidth()
                            || cropMaxY < rawBlason.getHeight()) {

                        result = Bitmap.createBitmap(rawBlason, cropMinX, cropMinY, cropMaxX - cropMinX,
                                cropMaxY - cropMinY);

                        Log.i(TAG, "Save cropped result to " + localFile);
                        FileOutputStream fos = null;
                        try {
                            fos = new FileOutputStream(localFile);

                            result.compress(Bitmap.CompressFormat.PNG, 90, fos);

                        } catch (Exception eee) {
                            Log.e(TAG, "Exception", eee);
                        } finally {
                            closeQuitely(fos);
                        }
                    }
                }
            } else {

                Log.i(TAG, "Existing, loading from cache");
                BufferedInputStream bis = null;
                try {
                    bis = new BufferedInputStream(new FileInputStream(localFile));

                    result = BitmapFactory.decodeStream(bis);

                    bis.close();
                } catch (Exception eee) {
                    Log.e(TAG, "Exception", eee);
                } finally {
                    closeQuitely(bis);
                }
            }
        }
        return result;
    }

    protected static Bitmap loadRawBlason(String blasonUrl, File filesDir) {
        Bitmap result = null;
        if (!Strings.isNullOrEmpty(blasonUrl)) {
            String fileName = BLASON_FILES_PREFIX + MhDlaNotifierUtils.md5(blasonUrl);
            File localFile = new File(filesDir, fileName);
            Log.i(TAG, "localFile: " + localFile);
            if (!localFile.exists()) {

                Log.i(TAG, "Not existing, fetching from " + blasonUrl);
                BufferedInputStream bis = null;
                try {
                    URL url = new URL(blasonUrl);
                    URLConnection conn = url.openConnection();
                    conn.connect();
                    bis = new BufferedInputStream(conn.getInputStream());
                    result = BitmapFactory.decodeStream(bis);

                } catch (Exception eee) {
                    Log.e(TAG, "Exception", eee);
                } finally {
                    closeQuitely(bis);
                }

                if (result != null) {
                    Log.i(TAG, "Save fetched result to " + localFile);
                    FileOutputStream fos = null;
                    try {
                        fos = new FileOutputStream(localFile);

                        result.compress(Bitmap.CompressFormat.PNG, 90, fos);

                    } catch (Exception eee) {
                        Log.e(TAG, "Exception", eee);
                        return null;
                    } finally {
                        closeQuitely(fos);
                    }
                }
            } else {

                Log.i(TAG, "Existing, loading from cache");
                BufferedInputStream bis = null;
                try {
                    bis = new BufferedInputStream(new FileInputStream(localFile));

                    result = BitmapFactory.decodeStream(bis);

                    bis.close();
                } catch (Exception eee) {
                    Log.e(TAG, "Exception", eee);
                } finally {
                    closeQuitely(bis);
                }
            }
        }
        return result;
    }

    protected static void inputStreamToFile(InputStream is, File to) throws IOException {
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(to);
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
        } finally {
            if (out != null) {
                out.close();
            }
            is.close();
        }
    }

    public static String loadGuilde(int guildeNumber, File filesDir) {
        String result = "";
        if (guildeNumber > 0) {
            File localFile = new File(filesDir, "guildes.txt");

            if (!localFile.exists()) {
                Log.i(TAG, "Not existing, fetching from " + "http://www.mountyhall.com/ftp/Public_Guildes.txt");
                BufferedInputStream bis = null;
                try {
                    URL url = new URL("http://www.mountyhall.com/ftp/Public_Guildes.txt");
                    URLConnection conn = url.openConnection();
                    conn.connect();
                    final BufferedInputStream fbis = new BufferedInputStream(conn.getInputStream());
                    bis = fbis;

                    inputStreamToFile(fbis, localFile);
                } catch (Exception eee) {
                    Log.e(TAG, "Exception", eee);
                } finally {
                    closeQuitely(bis);
                }
            }

            BufferedReader reader = null;
            try {
                reader = new BufferedReader(
                        new InputStreamReader(new FileInputStream(localFile), Charsets.ISO_8859_1));
                String str;
                String beginsWith = guildeNumber + ";";
                while ((str = reader.readLine()) != null) {
                    if (str.startsWith(beginsWith)) {
                        List<String> split = Lists
                                .newArrayList(Splitter.on(";").omitEmptyStrings().trimResults().split(str));
                        result = split.get(1);
                        break;
                    }
                }
            } catch (FileNotFoundException e) {
                // Forget...
            } catch (IOException e) {
                // Forget
            } finally {
                closeQuitely(reader);
            }

        }
        return result;
    }

    public static final Function<Context, Intent> GET_PLAY_INTENT = new Function<Context, Intent>() {
        @Override
        public Intent apply(Context input) {
            Uri uri = MhDlaNotifierConstants.MH_PLAY_URI;
            PreferencesHolder preferences = PreferencesHolder.load(input);
            if (preferences.useSmartphoneInterface) {
                uri = MhDlaNotifierConstants.MH_PLAY_SMARTPHONE_URI;
            }
            Intent webIntent = new Intent(Intent.ACTION_VIEW, uri);
            return webIntent;
        }
    };

    protected static String readVersion(Context context) {
        try {
            PackageManager manager = context.getPackageManager();
            PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
            return info.versionName;
        } catch (PackageManager.NameNotFoundException e) {
            Log.w(TAG, "Unable to read version", e);
            return N_C;
        }
    }

    protected static String readVersionAndCode(Context context) {
        try {
            PackageManager manager = context.getPackageManager();
            PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
            return String.format("%s (%d)", info.versionName, info.versionCode);
        } catch (PackageManager.NameNotFoundException e) {
            Log.w(TAG, "Unable to read full version", e);
            return N_C;
        }
    }

}