/** * Copyright (C) 2013 - 2015 the enviroCar community * * This file is part of the enviroCar app. * * The enviroCar app 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. * * The enviroCar app 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 the enviroCar app. If not, see http://www.gnu.org/licenses/. */ package org.envirocar.core.util; import android.annotation.SuppressLint; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.location.Location; import android.os.AsyncTask; import android.os.Build; import android.os.Environment; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.archivers.ArchiveStreamFactory; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.commons.compress.utils.IOUtils; import org.envirocar.core.entity.Measurement; import org.envirocar.core.logging.Logger; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Scanner; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; public class Util { private static final Logger logger = Logger.getLogger(Util.class); public static final String NEW_LINE_CHAR = System .getProperty("line.separator"); public static final String EXTERNAL_SUB_FOLDER = "enviroCar"; private static ISO8601DateFormat jacksonFormat = new ISO8601DateFormat(); /** * Create a file in the .enviroCar folder of the external storage. * * @param fileName the name of the new file * @return the resulting file * @throws IOException */ public static File createFileOnExternalStorage(String fileName) throws IOException { File directory = resolveExternalStorageBaseFolder(); File f = new File(directory, fileName); f.createNewFile(); if (!f.isFile()) { throw new IOException(fileName + " is not a file!"); } return f; } public static File resolveCacheFolder(Context ctx) { return ctx.getCacheDir(); } public static File resolveExternalStorageBaseFolder() throws IOException { File directory = new File(Environment.getExternalStorageDirectory() + File.separator + EXTERNAL_SUB_FOLDER); if (!directory.exists()) { directory.mkdir(); } if (!directory.isDirectory()) { throw new IOException(directory.getAbsolutePath() + " is not a directory!"); } return directory; } /** * Zips a list of files into the target archive. * * @param files the list of files of the target archive * @param target the target filename * @throws IOException */ public static void zipNative(List<File> files, String target) throws IOException { ZipOutputStream zos = null; try { File targetFile = new File(target); FileOutputStream dest = new FileOutputStream(targetFile); zos = new ZipOutputStream(new BufferedOutputStream(dest)); for (File f : files) { byte[] bytes = readFileContents(f).toByteArray(); ZipEntry entry = new ZipEntry(f.getName()); zos.putNextEntry(entry); zos.write(bytes); zos.closeEntry(); } } catch (IOException e) { throw e; } finally { try { if (zos != null) zos.close(); } catch (IOException e) { logger.warn(e.getMessage(), e); } } } /** * Zips the set of files. It uses the Android native Zip mechanism * or Apache Common Compress for older Android versions (creating * malformed archives). * * @param files the list of files of the target archive * @param target the target filename * @throws IOException */ public static void zip(List<File> files, String target) throws IOException { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { zipInteroperable(files, target); } else { zipNative(files, target); } } /** * Android devices up to version 2.3.7 have a bug in the native * Zip archive creation, making the archive unreadable with some * programs. * * @param files the list of files of the target archive * @param target the target filename * @throws IOException */ public static void zipInteroperable(List<File> files, String target) throws IOException { ZipArchiveOutputStream aos = null; OutputStream out = null; try { File tarFile = new File(target); out = new FileOutputStream(tarFile); try { aos = (ZipArchiveOutputStream) new ArchiveStreamFactory() .createArchiveOutputStream(ArchiveStreamFactory.ZIP, out); } catch (ArchiveException e) { throw new IOException(e); } for (File file : files) { ZipArchiveEntry entry = new ZipArchiveEntry(file, file.getName()); entry.setSize(file.length()); aos.putArchiveEntry(entry); IOUtils.copy(new FileInputStream(file), aos); aos.closeArchiveEntry(); } } catch (IOException e) { throw e; } finally { aos.finish(); out.close(); } } /** * Read the byte contents of a file into a {@link ByteArrayOutputStream}. * * @param f the file to read * @return the contents as {@link ByteArrayOutputStream} * @throws IOException */ public static ByteArrayOutputStream readFileContents(File f) throws IOException { InputStream in = null; in = new FileInputStream(f); return readStreamContents(in); } public static ByteArrayOutputStream readStreamContents(InputStream in) throws IOException { try { byte[] buff = new byte[8000]; int bytesRead = 0; ByteArrayOutputStream bao = new ByteArrayOutputStream(); while ((bytesRead = in.read(buff)) != -1) { bao.write(buff, 0, bytesRead); } bao.flush(); return bao; } catch (IOException e) { throw e; } finally { if (in != null) in.close(); } } public static JsonObject readJsonContents(File f) throws IOException { BufferedReader bufferedReader = new BufferedReader(new FileReader(f)); CharSequence content = consumeBufferedReader(bufferedReader); JsonObject tou = new JsonParser().parse(content.toString()).getAsJsonObject(); return tou; } public static CharSequence consumeInputStream(InputStream in) throws IOException { Scanner sc = new Scanner(in, "UTF-8"); StringBuilder sb = new StringBuilder(); String sep = System.getProperty("line.separator"); while (sc.hasNext()) { sb.append(sc.nextLine()); sb.append(sep); } sc.close(); return sb; } private static CharSequence consumeBufferedReader( BufferedReader bufferedReader) throws IOException { StringBuilder content = new StringBuilder(); String line = ""; while ((line = bufferedReader.readLine()) != null) { content.append(line); } bufferedReader.close(); return content; } @SuppressLint("NewApi") public static <P, T extends AsyncTask<P, ?, ?>> void execute(T task, P... params) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); } else { task.execute(params); } } /** * Transform ISO 8601 string to Calendar. * * @param iso8601string * @return * @throws ParseException */ public static long isoDateToLong(final String iso8601string) throws ParseException { // Date date = isoDateFormat.parse(iso8601string.replace("Z", "+00:00")); // return date.getTime(); return jacksonFormat.parse(iso8601string).getTime(); } /** * Returns the distance of two points in kilometers. * * @param lat1 * @param lng1 * @param lat2 * @param lng2 * @return distance in km */ public static double getDistance(double lat1, double lng1, double lat2, double lng2) { float[] res = new float[1]; Location.distanceBetween(lat1, lng1, lat2, lng2, res); return res[0] / 1000.0d; } /** * Returns the distance of two measurements in kilometers. * * @param m1 first {@link Measurement} * @param m2 second {@link Measurement} * @return distance in km */ public static double getDistance(Measurement m1, Measurement m2) { return getDistance(m1.getLatitude(), m1.getLongitude(), m2.getLatitude(), m2.getLongitude ()); } public static String longToIsoDate(long time) { return jacksonFormat.format(new Date(time)); } public static void saveContentsToFile(String content, File f) throws IOException { if (!f.exists()) { f.createNewFile(); } BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter( f, false)); bufferedWriter.write(content); bufferedWriter.flush(); bufferedWriter.close(); } /** * method to get the current version */ public static String getVersionString(Context ctx) { StringBuilder out = new StringBuilder("Version "); try { out.append(getVersionStringShort(ctx)); out.append(" ("); out.append(ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0).versionCode); out.append("), "); } catch (NameNotFoundException e) { logger.warn(e.getMessage(), e); } try { ApplicationInfo ai = ctx.getPackageManager().getApplicationInfo( ctx.getPackageName(), 0); ZipFile zf = new ZipFile(ai.sourceDir); ZipEntry ze = zf.getEntry("classes.dex"); long time = ze.getTime(); out.append(SimpleDateFormat.getInstance().format(new Date(time))); zf.close(); } catch (Exception e) { logger.warn(e.getMessage(), e); } return out.toString(); } public static String getVersionStringShort(Context ctx) throws NameNotFoundException { return ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0).versionName; } }