/* * This file is part of GPSLogger for Android. * * GPSLogger for Android 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 2 of the License, or * (at your option) any later version. * * GPSLogger for Android 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 GPSLogger for Android. If not, see <http://www.gnu.org/licenses/>. */ package com.mendhak.gpslogger.common; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.util.Log; import android.widget.Toast; import arida.ufc.br.moapgpstracker.R; import org.w3c.dom.Document; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.*; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; public class Utilities { private static final int LOGLEVEL = 5; private static ProgressDialog pd; private static void LogToDebugFile(String message) { if (AppSettings.isDebugToFile()) { DebugLogger.Write(message); } } public static void LogInfo(String message) { if (LOGLEVEL >= 3) { Log.i("GPSLogger", message); } LogToDebugFile(message); } public static int convertCoordinates(double coord){ return (int)(coord * 1e6); } public static void LogError(String methodName, Exception ex) { try { LogError(methodName + ":" + ex.getMessage()); } catch (Exception e) { /**/ } } private static void LogError(String message) { Log.e("GPSLogger", message); LogToDebugFile(message); } @SuppressWarnings("unused") public static void LogDebug(String message) { if (LOGLEVEL >= 4) { Log.d("GPSLogger", message); } LogToDebugFile(message); } public static void LogWarning(String message) { if (LOGLEVEL >= 2) { Log.w("GPSLogger", message); } LogToDebugFile(message); } @SuppressWarnings("unused") public static void LogVerbose(String message) { if (LOGLEVEL >= 5) { Log.v("GPSLogger", message); } LogToDebugFile(message); } /** * Gets user preferences, populates the AppSettings class. */ public static void PopulateAppSettings(Context context) { Utilities.LogInfo("Getting preferences"); SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(context); AppSettings.setUseImperial(prefs.getBoolean("useImperial", false)); AppSettings.setUseSatelliteTime(prefs.getBoolean("satellite_time", false)); AppSettings.setLogToKml(prefs.getBoolean("log_kml", false)); AppSettings.setLogToGpx(prefs.getBoolean("log_gpx", false)); AppSettings.setLogToPlainText(prefs.getBoolean("log_plain_text", false)); AppSettings.setLogToOpenGTS(prefs.getBoolean("log_opengts", false)); AppSettings.setShowInNotificationBar(prefs.getBoolean( "show_notification", true)); AppSettings.setPreferCellTower(prefs.getBoolean("prefer_celltower", false)); String minimumDistanceString = prefs.getString( "distance_before_logging", "0"); if (minimumDistanceString != null && minimumDistanceString.length() > 0) { AppSettings.setMinimumDistanceInMeters(Integer .valueOf(minimumDistanceString)); } else { AppSettings.setMinimumDistanceInMeters(0); } if (AppSettings.shouldUseImperial()) { AppSettings.setMinimumDistanceInMeters(Utilities.FeetToMeters(AppSettings .getMinimumDistanceInMeters())); } String minimumSecondsString = prefs.getString("time_before_logging", "60"); if (minimumSecondsString != null && minimumSecondsString.length() > 0) { AppSettings .setMinimumSeconds(Integer.valueOf(minimumSecondsString)); } else { AppSettings.setMinimumSeconds(60); } AppSettings.setNewFileCreation(prefs.getString("new_file_creation", "onceaday")); if (AppSettings.getNewFileCreation().equals("onceaday")) { AppSettings.setNewFileOnceADay(true); } else { AppSettings.setNewFileOnceADay(false); } AppSettings.setAutoSendEnabled(prefs.getBoolean("autosend_enabled", false)); AppSettings.setAutoEmailEnabled(prefs.getBoolean("autoemail_enabled", false)); if (Float.valueOf(prefs.getString("autosend_frequency", "0")) >= 8f) { SharedPreferences.Editor editor = prefs.edit(); editor.putString("autosend_frequency", "8"); editor.commit(); } AppSettings.setAutoSendDelay(Float.valueOf(prefs.getString( "autosend_frequency", "0"))); AppSettings.setSmtpServer(prefs.getString("smtp_server", "")); AppSettings.setSmtpPort(prefs.getString("smtp_port", "25")); AppSettings.setSmtpSsl(prefs.getBoolean("smtp_ssl", true)); AppSettings.setSmtpUsername(prefs.getString("smtp_username", "")); AppSettings.setSmtpPassword(prefs.getString("smtp_password", "")); AppSettings.setAutoEmailTargets(prefs.getString("autoemail_target", "")); AppSettings.setDebugToFile(prefs.getBoolean("debugtofile", false)); AppSettings.setShouldSendZipFile(prefs.getBoolean("autosend_sendzip", true)); AppSettings.setSmtpFrom(prefs.getString("smtp_from", "")); AppSettings.setOpenGTSEnabled(prefs.getBoolean("opengts_enabled", false)); AppSettings.setAutoOpenGTSEnabled(prefs.getBoolean("autoopengts_enabled", false)); AppSettings.setOpenGTSServer(prefs.getString("opengts_server", "")); AppSettings.setOpenGTSServerPort(prefs.getString("opengts_server_port", "")); AppSettings.setOpenGTSServerCommunicationMethod(prefs.getString("opengts_server_communication_method", "")); AppSettings.setOpenGTSServerPath(prefs.getString("autoopengts_server_path", "")); AppSettings.setOpenGTSDeviceId(prefs.getString("opengts_device_id", "")); } public static void ShowProgress(Context ctx, String title, String message) { if (ctx != null) { pd = new ProgressDialog(ctx, ProgressDialog.STYLE_HORIZONTAL); pd.setMax(100); pd.setIndeterminate(true); pd = ProgressDialog.show(ctx, title, message, true, true); } } public static void HideProgress() { if (pd != null) { pd.dismiss(); } } /** * Displays a message box to the user with an OK button. * * @param title * @param message * @param className The calling class, such as GpsMainActivity.this or * mainActivity. */ public static void MsgBox(String title, String message, Context className) { MsgBox(title, message, className, null); } /** * Displays a message box to the user with an OK button. * * @param title * @param message * @param className The calling class, such as GpsMainActivity.this or * mainActivity. * @param msgCallback An object which implements IHasACallBack so that the click * event can call the callback method. */ private static void MsgBox(String title, String message, Context className, final IMessageBoxCallback msgCallback) { AlertDialog alertDialog = new AlertDialog.Builder(className).create(); alertDialog.setTitle(title); alertDialog.setMessage(message); alertDialog.setButton(className.getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { if (msgCallback != null) { msgCallback.MessageBoxResult(which); } } }); alertDialog.show(); } /** * Converts seconds into friendly, understandable description of time. * * @param numberOfSeconds * @return */ public static String GetDescriptiveTimeString(int numberOfSeconds, Context context) { String descriptive; int hours; int minutes; int seconds; int remainingSeconds; // Special cases if (numberOfSeconds == 1) { return context.getString(R.string.time_onesecond); } if (numberOfSeconds == 30) { return context.getString(R.string.time_halfminute); } if (numberOfSeconds == 60) { return context.getString(R.string.time_oneminute); } if (numberOfSeconds == 900) { return context.getString(R.string.time_quarterhour); } if (numberOfSeconds == 1800) { return context.getString(R.string.time_halfhour); } if (numberOfSeconds == 3600) { return context.getString(R.string.time_onehour); } if (numberOfSeconds == 4800) { return context.getString(R.string.time_oneandhalfhours); } if (numberOfSeconds == 9000) { return context.getString(R.string.time_twoandhalfhours); } // For all other cases, calculate hours = numberOfSeconds / 3600; remainingSeconds = numberOfSeconds % 3600; minutes = remainingSeconds / 60; seconds = remainingSeconds % 60; // Every 5 hours and 2 minutes // XYZ-5*2*20* descriptive = context.getString(R.string.time_hms_format, String.valueOf(hours), String.valueOf(minutes), String.valueOf(seconds)); return descriptive; } /** * Converts given bearing degrees into a rough cardinal direction that's * more understandable to humans. * * @param bearingDegrees * @return */ public static String GetBearingDescription(float bearingDegrees, Context context) { String direction; String cardinal; if (bearingDegrees > 348.75 || bearingDegrees <= 11.25) { cardinal = context.getString(R.string.direction_north); } else if (bearingDegrees > 11.25 && bearingDegrees <= 33.75) { cardinal = context.getString(R.string.direction_northnortheast); } else if (bearingDegrees > 33.75 && bearingDegrees <= 56.25) { cardinal = context.getString(R.string.direction_northeast); } else if (bearingDegrees > 56.25 && bearingDegrees <= 78.75) { cardinal = context.getString(R.string.direction_eastnortheast); } else if (bearingDegrees > 78.75 && bearingDegrees <= 101.25) { cardinal = context.getString(R.string.direction_east); } else if (bearingDegrees > 101.25 && bearingDegrees <= 123.75) { cardinal = context.getString(R.string.direction_eastsoutheast); } else if (bearingDegrees > 123.75 && bearingDegrees <= 146.26) { cardinal = context.getString(R.string.direction_southeast); } else if (bearingDegrees > 146.25 && bearingDegrees <= 168.75) { cardinal = context.getString(R.string.direction_southsoutheast); } else if (bearingDegrees > 168.75 && bearingDegrees <= 191.25) { cardinal = context.getString(R.string.direction_south); } else if (bearingDegrees > 191.25 && bearingDegrees <= 213.75) { cardinal = context.getString(R.string.direction_southsouthwest); } else if (bearingDegrees > 213.75 && bearingDegrees <= 236.25) { cardinal = context.getString(R.string.direction_southwest); } else if (bearingDegrees > 236.25 && bearingDegrees <= 258.75) { cardinal = context.getString(R.string.direction_westsouthwest); } else if (bearingDegrees > 258.75 && bearingDegrees <= 281.25) { cardinal = context.getString(R.string.direction_west); } else if (bearingDegrees > 281.25 && bearingDegrees <= 303.75) { cardinal = context.getString(R.string.direction_westnorthwest); } else if (bearingDegrees > 303.75 && bearingDegrees <= 326.25) { cardinal = context.getString(R.string.direction_northwest); } else if (bearingDegrees > 326.25 && bearingDegrees <= 348.75) { cardinal = context.getString(R.string.direction_northnorthwest); } else { direction = context.getString(R.string.unknown_direction); return direction; } direction = context.getString(R.string.direction_roughly, cardinal); return direction; } /** * Makes string safe for writing to XML file. Removes lt and gt. Best used * when writing to file. * * @param desc * @return */ public static String CleanDescription(String desc) { desc = desc.replace("<", ""); desc = desc.replace(">", ""); desc = desc.replace("&", "&"); desc = desc.replace("\"", """); return desc; } /** * Given a Date object, returns an ISO 8601 date time string in UTC. * Example: 2010-03-23T05:17:22Z but not 2010-03-23T05:17:22+04:00 * * @param dateToFormat The Date object to format. * @return The ISO 8601 formatted string. */ public static String GetIsoDateTime(Date dateToFormat) { // GPX specs say that time given should be in UTC, no local time. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); return sdf.format(dateToFormat); } public static String GetReadableDateTime(Date dateToFormat) { SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy HH:mm"); return sdf.format(dateToFormat); } /** * Converts given meters to feet. * * @param m * @return */ public static int MetersToFeet(int m) { return (int) Math.round(m * 3.2808399); } /** * Converts given feet to meters * * @param f * @return */ public static int FeetToMeters(int f) { return (int) Math.round(f / 3.2808399); } /** * Converts given meters to feet and rounds up. * * @param m * @return */ public static int MetersToFeet(double m) { return MetersToFeet((int) m); } public static boolean IsEmailSetup() { return AppSettings.isAutoEmailEnabled() && AppSettings.getAutoEmailTargets().length() > 0 && AppSettings.getSmtpServer().length() > 0 && AppSettings.getSmtpPort().length() > 0 && AppSettings.getSmtpUsername().length() > 0; } public static boolean IsOpenGTSSetup() { return AppSettings.isOpenGTSEnabled() && AppSettings.getOpenGTSServer().length() > 0 && AppSettings.getOpenGTSServerPort().length() > 0 && AppSettings.getOpenGTSServerCommunicationMethod().length() > 0 && AppSettings.getOpenGTSDeviceId().length() > 0; } /** * Uses the Haversine formula to calculate the distnace between to lat-long coordinates * * @param latitude1 The first point's latitude * @param longitude1 The first point's longitude * @param latitude2 The second point's latitude * @param longitude2 The second point's longitude * @return The distance between the two points in meters */ public static double CalculateDistance(double latitude1, double longitude1, double latitude2, double longitude2) { /* Haversine formula: A = sin��(��lat/2) + cos(lat1).cos(lat2).sin��(��long/2) C = 2.atan2(���a, ���(1���a)) D = R.c R = radius of earth, 6371 km. All angles are in radians */ double deltaLatitude = Math.toRadians(Math.abs(latitude1 - latitude2)); double deltaLongitude = Math.toRadians(Math.abs(longitude1 - longitude2)); double latitude1Rad = Math.toRadians(latitude1); double latitude2Rad = Math.toRadians(latitude2); double a = Math.pow(Math.sin(deltaLatitude / 2), 2) + (Math.cos(latitude1Rad) * Math.cos(latitude2Rad) * Math.pow(Math.sin(deltaLongitude / 2), 2)); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); return 6371 * c * 1000; //Distance in meters } /** * Checks if a string is null or empty * * @param text * @return */ public static boolean IsNullOrEmpty(String text) { return text == null || text.length() == 0; } public static byte[] GetByteArrayFromInputStream(InputStream is) { try { int length; int size = 1024; byte[] buffer; if (is instanceof ByteArrayInputStream) { size = is.available(); buffer = new byte[size]; is.read(buffer, 0, size); } else { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); buffer = new byte[size]; while ((length = is.read(buffer, 0, size)) != -1) { outputStream.write(buffer, 0, length); } buffer = outputStream.toByteArray(); } return buffer; } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (Exception e) { Utilities.LogWarning("GetStringFromInputStream - could not close stream"); } } return null; } /** * Loops through an input stream and converts it into a string, then closes the input stream * * @param is * @return */ public static String GetStringFromInputStream(InputStream is) { String line; StringBuilder total = new StringBuilder(); // Wrap a BufferedReader around the InputStream BufferedReader rd = new BufferedReader(new InputStreamReader(is)); // Read response until the end try { while ((line = rd.readLine()) != null) { total.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (Exception e) { Utilities.LogWarning("GetStringFromInputStream - could not close stream"); } } // Return full string return total.toString(); } /** * Converts an input stream containing an XML response into an XML Document object * * @param stream * @return */ public static Document GetDocumentFromInputStream(InputStream stream) { Document doc; try { DocumentBuilderFactory xmlFactory = DocumentBuilderFactory.newInstance(); xmlFactory.setNamespaceAware(true); DocumentBuilder builder = xmlFactory.newDocumentBuilder(); doc = builder.parse(stream); } catch (Exception e) { doc = null; } return doc; } /** * Gets the GPSLogger-specific MIME type to use for a given filename/extension * * @param fileName * @return */ public static String GetMimeTypeFromFileName(String fileName) { if (fileName == null || fileName.length() == 0) { return ""; } int pos = fileName.lastIndexOf("."); if (pos == -1) { return "application/octet-stream"; } else { String extension = fileName.substring(pos + 1, fileName.length()); if (extension.equalsIgnoreCase("gpx")) { return "application/gpx+xml"; } else if (extension.equalsIgnoreCase("kml")) { return "application/vnd.google-earth.kml+xml"; } else if (extension.equalsIgnoreCase("zip")) { return "application/zip"; } } //Unknown mime type return "application/octet-stream"; } }