com.neuron.trafikanten.HelperFunctions.java Source code

Java tutorial

Introduction

Here is the source code for com.neuron.trafikanten.HelperFunctions.java

Source

/**
 *     Copyright (C) 2009 Anders Aagaard <aagaande@gmail.com>
 *
 *   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/>.
 */

package com.neuron.trafikanten;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.zip.GZIPInputStream;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Typeface;
import android.os.Build;
import android.util.Log;

/*
 * Small helper functions used by multiple classes.
 */
public class HelperFunctions {
    private final static String TAG = "Trafikanten-HelperFunctions";
    public final static SimpleDateFormat hourFormater = new SimpleDateFormat("HH:mm");
    public static final String KEY_DOWNLOADBYTE = "downloadkb";
    public static final int SECOND = 1000;
    public static final int MINUTE = 60 * SECOND;
    public static final int HOUR = 60 * MINUTE;

    /*
     * Render time in the way trafikanten.no wants
     *   From 1-9 minutes we use "X m", above that we use HH:MM
     */
    private static CharSequence nowText;

    public static void renderTime(final StringBuffer txt, Long currentTime, Context context, long time) {
        int diffMinutes = Math.round(((float) (time - currentTime)) / MINUTE);

        if (diffMinutes < -1) {
            // Negative time!
            diffMinutes = diffMinutes * -1;
            txt.append("-");
            txt.append(diffMinutes);
            txt.append(" min");
            return;
        } else if (diffMinutes < 1) {
            if (nowText == null) {
                nowText = context.getText(R.string.now);
            }
            txt.append(nowText);
            return;
        } else if (diffMinutes <= 9) {
            txt.append(diffMinutes);
            txt.append(" min");
            return;
        }

        //TODO Performance : hourFormater slow? can we construct HH:mm faster ourselfes and write directly to stringbuffer? aprox 110ms here
        txt.append(hourFormater.format(time));
    }

    private static String _applicationVersion = null;

    public static String GetApplicationVersion(Context context) {
        if (_applicationVersion == null) {
            try {
                _applicationVersion = context.getPackageManager().getPackageInfo(context.getPackageName(),
                        0).versionName;
            } catch (NameNotFoundException e) {
                e.printStackTrace();
                _applicationVersion = "0";
            }
        }
        return _applicationVersion;
    }

    private static String userAgentString = null;

    private static String getUserAgent(Context context) {
        if (userAgentString == null) {
            CharSequence appVersion = GetApplicationVersion(context);

            userAgentString = "TrafikantenAndroid/" + appVersion + " (aagaande) Device/" + Build.VERSION.RELEASE
                    + " (" + Locale.getDefault() + "; " + Build.MODEL + ")";

            // + Locale.getDefault() + ")";
        }
        return userAgentString;
    }

    /*
     * Do proper encoding that doesn't add + to the string (with JSON doesn't want)
     */
    public static String properEncode(String query) throws UnsupportedEncodingException {
        return URLEncoder.encode(query.trim(), "UTF-8").replace("+", "%20");
    }

    /*
     * Convert trafikanten's json date to an actual date
     */
    public static Long jsonToDate(String jsonString) {
        Calendar calendar = Calendar.getInstance();
        int indexOfPlus = jsonString.indexOf("+");
        int startOfDate = 5;
        if (jsonString.startsWith("/")) {
            // LEGACY : parse /Date( strings : Some date strings are /Date(253402297140000+0100)/, new ones are Date(253402297140000+0100)
            startOfDate = 6;
            calendar.setTimeInMillis(Long.parseLong(
                    jsonString.substring(startOfDate, indexOfPlus > 0 ? indexOfPlus : jsonString.length() - 2)));
        } else {
            calendar.setTimeInMillis(Long.parseLong(
                    jsonString.substring(startOfDate, indexOfPlus > 0 ? indexOfPlus : jsonString.length() - 1)));
        }
        if (indexOfPlus > -1) {
            calendar.setTimeZone(
                    TimeZone.getTimeZone("GMT-" + jsonString.substring(indexOfPlus, indexOfPlus + 3) + ":00"));
        }
        return calendar.getTimeInMillis();
    }

    /*
     * Converts inputstream to string
     */
    public static String InputStreamToString(InputStream stream) throws IOException {
        //long perfSTART = System.currentTimeMillis();

        final InputStreamReader input = new InputStreamReader(stream, "UTF-8");
        final char[] buffer = new char[8192];
        final StringBuilder output = new StringBuilder(8192);
        try {
            for (int read = input.read(buffer, 0, buffer.length); read != -1; read = input.read(buffer, 0,
                    buffer.length)) {
                output.append(buffer, 0, read);
            }
        } catch (IOException e) {
        }
        //Log.i(TAG,"PERF : Downloading web request took " + ((System.currentTimeMillis() - perfSTART)) + "ms");
        return output.toString();
    }

    /*
     * Updates statistics for byte downloaded.
     */
    private static void updateStatistics(Context context, long size) {
        if (size == 0)
            return;
        final SharedPreferences preferences = context.getSharedPreferences("trafikantenandroid",
                Context.MODE_PRIVATE);
        Long downloadByte = preferences.getLong(KEY_DOWNLOADBYTE, 0) + size;

        final SharedPreferences.Editor editor = preferences.edit();
        editor.putLong(KEY_DOWNLOADBYTE, downloadByte);
        editor.commit();
    }

    /*
     * Decides on whether or not we should use gzip compression or not.
     */
    public static class StreamWithTime {
        public InputStream stream;
        public long timeDifference;

        public StreamWithTime(InputStream stream, long timeDifference) {
            this.stream = stream;
            this.timeDifference = timeDifference;
        }
    }

    public static StreamWithTime executeHttpRequest(Context context, HttpUriRequest request, boolean parseTime)
            throws IOException {
        //long perfSTART = System.currentTimeMillis();

        /*
         * Add gzip header
         */
        request.setHeader("Accept-Encoding", "gzip");
        request.setHeader("User-Agent", getUserAgent(context));

        /*
         * Get the response, if we use gzip use the GZIPInputStream
         */
        long responseTime = System.currentTimeMillis();
        HttpResponse response = new DefaultHttpClient().execute(request);
        responseTime = (System.currentTimeMillis() - responseTime) / 2;
        InputStream content = response.getEntity().getContent();

        /*
         * Get trafikanten time to calculate time difference
         */
        long timeDifference = 0;
        if (parseTime) {
            try {
                final String header = response.getHeaders("Date")[0].getValue();
                final long trafikantenTime = new Date(header).getTime();
                //timeDifference = System.currentTimeMillis() - (System.currentTimeMillis() - timeDifference) - trafikantenTime;
                timeDifference = System.currentTimeMillis() - responseTime - trafikantenTime;
                Log.i(TAG, "Timedifference between local clock and trafikanten server : " + timeDifference + "ms ("
                        + (timeDifference / 1000) + "s)");
            } catch (Exception e) {
                e.printStackTrace(); // ignore this error, it's not critical.
            }
        }

        Header contentEncoding = response.getFirstHeader("Content-Encoding");
        Header contentLength = response.getFirstHeader("Content-Length");
        if (contentLength != null) {
            updateStatistics(context, Long.parseLong(contentLength.getValue()));
        } else {
            Log.e(TAG, "Contentlength is invalid!");
        }

        if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
            content = new GZIPInputStream(content);
            //Log.i(TAG,"Recieved compressed data - OK");
        } else {
            Log.i(TAG, "Recieved UNCOMPRESSED data - Problem server side");
        }

        //Log.i(TAG,"PERF : Sending web request took " + ((System.currentTimeMillis() - perfSTART)) + "ms");

        //return content;
        return new StreamWithTime(content, timeDifference);
    }

    /*
     * Create custom font for devi.
     */
    private static Typeface mTypeface = null;

    public static Typeface getTypeface(Activity activity) {
        if (mTypeface == null) {
            mTypeface = Typeface.createFromAsset(activity.getAssets(), "fonts/DejaVuSans.ttf");
        }
        return mTypeface;
    }
}