/*
* Copyright 2008-2013, ETH Zürich, Samuel Welten, Michael Kuhn, Tobias Langner,
* Sandro Affentranger, Lukas Bossard, Michael Grob, Rahul Jain,
* Dominic Langenegger, Sonia Mayor Alonso, Roger Odermatt, Tobias Schlueter,
* Yannick Stucki, Sebastian Wendland, Samuel Zehnder, Samuel Zihlmann,
* Samuel Zweifel
*
* This file is part of Jukefox.
*
* Jukefox 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 any later version. Jukefox 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
* Jukefox. If not, see <http://www.gnu.org/licenses/>.
*/
package ch.ethz.dcg.jukefox.commons.utils;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Environment;
import android.os.StatFs;
import android.provider.MediaStore;
import ch.ethz.dcg.jukefox.commons.Constants;
import ch.ethz.dcg.jukefox.model.collection.BaseAlbum;
import ch.ethz.dcg.jukefox.model.collection.BaseArtist;
import ch.ethz.dcg.jukefox.model.collection.BaseSong;
import ch.ethz.dcg.pancho3.model.JukefoxApplication;
public class AndroidUtils {
private final static String TAG = AndroidUtils.class.getSimpleName();
private static Boolean isSensorProblemDevice = null;
public static String getVersionName() {
try {
Context context = JukefoxApplication.getAppContext();
ComponentName comp = new ComponentName(context, JukefoxApplication.class);
PackageInfo pinfo = context.getPackageManager().getPackageInfo(comp.getPackageName(), 0);
return pinfo.versionName;
} catch (android.content.pm.PackageManager.NameNotFoundException e) {
return "";
}
}
public static int getVersionCode() {
try {
Context context = JukefoxApplication.getAppContext();
ComponentName comp = new ComponentName(context, JukefoxApplication.class);
PackageInfo pinfo = context.getPackageManager().getPackageInfo(comp.getPackageName(), 0);
return pinfo.versionCode;
} catch (android.content.pm.PackageManager.NameNotFoundException e) {
return -1;
}
}
public static String getModel() {
return android.os.Build.MODEL;
}
public static String getAndroidVersionName() {
return android.os.Build.VERSION.RELEASE;
}
public static long getAvailableInternalMemorySize() {
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return availableBlocks * blockSize;
}
public static long getAvailableExternalMemorySize() {
File path = Environment.getExternalStorageDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return availableBlocks * blockSize;
}
// public static boolean isSdCardOk() {
// try {
// Log.d(TAG, "1");
// File f = new File(Constants.SDCARD_PATH);
// boolean b = f.exists() && f.isDirectory() && f.canWrite()
// && f.canRead();
// if (!b) {
// return false;
// }
// Log.d(TAG, "2");
// String[] files = f.list();
// Log.d(TAG, "3");
// if (files.length > 0) {
// return true;
// } else {
// return false;
// }
// } catch (Exception e) {
// Log.w(TAG, e);
// return false;
// }
// }
public static boolean isSdCardOk() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
Log.w(TAG, "Access to sd-card is read only");
return false;
} else {
return false;
}
}
public static boolean fileExists(String filename) throws IOException {
File f = new File(filename);
return f.exists();
}
public static boolean deleteFile(String filename) throws IOException {
Log.v(TAG, "Delete file: " + filename);
File f = new File(filename);
return f.delete();
}
public static float distance(float x1, float y1, float x2, float y2) {
float d1 = x1 - x2;
float d2 = y1 - y2;
return (float) Math.sqrt((float) Math.pow(d1, 2) + Math.pow(d2, 2));
}
public static float squareDistance(float[] p1, float[] p2) throws ArrayIndexOutOfBoundsException {
if (p1.length != p2.length) {
throw new ArrayIndexOutOfBoundsException(Math.max(p1.length, p2.length));
}
float sum = 0;
for (int i = 0; i < p1.length; i++) {
float d = p1[i] - p2[i];
sum += d * d;
}
return sum;
}
public static float distance(float[] p1, float[] p2) {
return (float) Math.sqrt(squareDistance(p1, p2));
}
public static boolean isMultiTouchOs() {
Log.v("Version String", android.os.Build.VERSION.RELEASE);
// double osVersion =
// Double.parseDouble(android.os.Build.VERSION.RELEASE);
// return osVersion >= version;
try {
if (android.os.Build.VERSION.RELEASE.length() < 1) {
return false;
}
String firstLetter = android.os.Build.VERSION.RELEASE.substring(0, 1);
Integer v = Integer.parseInt(firstLetter);
return v >= 2;
} catch (Exception e) {
Log.w("PersHelper", e);
return android.os.Build.VERSION.RELEASE.startsWith("2");
}
}
/**
* return true if the current os version has a problem with reading the
* duration of certain media files.
*
* @param version
* @return
*/
public static boolean isDurationProblemOs() {
Log.v(TAG, "Version String: " + android.os.Build.VERSION.RELEASE);
try {
if (android.os.Build.VERSION.RELEASE.length() < 1) {
return false;
}
return android.os.Build.VERSION.RELEASE.startsWith("2.3");
} catch (Exception e) {
Log.w(TAG, e);
return false;
}
}
public static boolean isMediaScannerScanning(Context context) {
boolean result = false;
Cursor cursor = query(context, MediaStore.getMediaScannerUri(),
new String[] { MediaStore.MEDIA_SCANNER_VOLUME }, null, null, null);
if (cursor != null) {
if (cursor.getCount() == 1) {
cursor.moveToFirst();
result = "external".equals(cursor.getString(0));
}
cursor.close();
}
return result;
}
public static Cursor query(Context context, Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
return query(context, uri, projection, selection, selectionArgs, sortOrder, 0);
}
public static Cursor query(Context context, Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder, int limit) {
try {
ContentResolver resolver = context.getContentResolver();
if (resolver == null) {
return null;
}
if (limit > 0) {
uri = uri.buildUpon().appendQueryParameter("limit", "" + limit).build();
}
return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
} catch (UnsupportedOperationException ex) {
return null;
}
}
public static boolean isNullOrEmpty(String string, boolean trim) {
if (string == null || string.length() == 0) {
return true;
}
if (trim && string.trim().length() == 0) {
return true;
}
return false;
}
public static String replaceXmlEntities(String str) {
if (str == null) {
return null;
}
// $evilChars=array ( '&', '"', "'", '<', '>' );
// $niceChards=array ( '&' , '"', ''' , '<' , '>' );
str = str.replace("&", "&");
str = str.replace(""", "\"");
str = str.replace("'", "'");
str = str.replace("<", "<");
str = str.replace(">", ">");
return str;
}
public static String readBufferToString(BufferedReader br) throws IOException {
if (br == null) {
return null;
}
StringBuffer buf = new StringBuffer();
String line = br.readLine();
while (line != null) {
buf.append(line);
buf.append("\n");
line = br.readLine();
}
String content = buf.toString();
return content;
}
public static boolean isNetworkException(Exception e) {
if (e == null) {
return false;
}
if (e instanceof SocketException) {
return true;
}
if (e instanceof SocketTimeoutException) {
return true;
}
if (e instanceof UnknownHostException) {
return true;
}
return false;
}
public static float scalarProduct(float[] v1, float[] v2) {
float s = 0;
for (int i = 0; i < Constants.DIM; i++) {
s += v1[i] * v2[i];
}
return s;
}
private static byte[] getByteArrayFromInputStream(InputStream is) throws IOException {
// byte[] byteArray = null;
//
// byteArray = new byte[is.available()];
// is.read(byteArray);
// return byteArray;
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
return buffer.toByteArray();
}
public static Bitmap getBitmapFromResource(Resources res, int resourceId, int maxSize) {
Bitmap bitmap = null;
int dummySize = maxSize * maxSize / 4; // KB
while (bitmap == null && dummySize <= maxSize * maxSize * 4) {
try {
int sampleFactor = getSampleFactor(res, resourceId, maxSize);
BitmapFactory.Options resample = new BitmapFactory.Options();
resample.inSampleSize = sampleFactor;
bitmap = BitmapFactory.decodeResource(res, resourceId, resample);
} catch (Throwable e) {
System.gc();
// Avoid that heap has to be grown for the BitmapFactory,
// as this would lead to an out of memory error
int[] dummyArray = new int[dummySize * 1024];
// Avoid being eliminated by optimization of compiler
if (dummyArray != null) {
dummyArray = null;
System.gc();
}
Log.w(TAG, e);
dummySize *= 2;
}
}
return bitmap;
}
public static Bitmap getBitmapFromInputStream(InputStream is, int maxSize) {
byte[] inputBytes;
try {
// TODO: Check if PatchInputStream is still necessary. see
// http://code.google.com/p/android/issues/detail?id=6066
inputBytes = getByteArrayFromInputStream(new PatchInputStream(is));
} catch (IOException e3) {
Log.w(TAG, e3);
return null;
}
return getBitmapFromByteArray(inputBytes, maxSize);
}
public static Bitmap getBitmapFromByteArray(byte[] byteArray, int maxSize) {
Bitmap bitmap = null;
try {
try {
int sampleFactor = getSampleFactor(byteArray, maxSize);
BitmapFactory.Options resample = new BitmapFactory.Options();
resample.inSampleSize = sampleFactor;
bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, resample);
} catch (Error e) {
// Avoid that heap has to be grown for the BitmapFactory,
// as this would lead to an out of memory error
int[] dummyArray = new int[byteArray.length];
// Avoid being eliminated by optimization of compiler
if (dummyArray != null) {
dummyArray = null;
System.gc();
}
Log.w("BitmapFactory", e);
}
if (bitmap == null) {
try {
int sampleFactor = getSampleFactor(byteArray, maxSize);
BitmapFactory.Options resample = new BitmapFactory.Options();
resample.inSampleSize = sampleFactor;
bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, resample);
} catch (Error e) {
System.gc();
Log.w("BitmapFactory", e);
}
}
} catch (Throwable e) {
Log.w("Bitmap", e);
}
return bitmap;
}
public static Bitmap getBitmapFromFile(String path, int maxSize) {
Bitmap bitmap = null;
int dummySize = maxSize * maxSize / 4; // KB
while (bitmap == null && dummySize <= maxSize * maxSize * 4) {
try {
int sampleFactor = getSampleFactor(path, maxSize);
BitmapFactory.Options resample = new BitmapFactory.Options();
resample.inSampleSize = sampleFactor;
bitmap = BitmapFactory.decodeFile(path, resample);
} catch (Throwable e) {
// Avoid that heap has to be grown for the BitmapFactory,
// as this would lead to an out of memory error
int[] dummyArray = new int[dummySize * 1024];
// Avoid being eliminated by optimization of compiler
if (dummyArray != null) {
dummyArray = null;
System.gc();
}
Log.w(TAG, e);
dummySize *= 2;
}
}
return bitmap;
}
private static int getSampleFactor(String path, int maxSize) {
BitmapFactory.Options bounds = getBounds(path);
return getSampleFactor(maxSize, bounds);
}
private static int getSampleFactor(byte[] byteArray, int maxSize) {
BitmapFactory.Options bounds = getBounds(byteArray);
return getSampleFactor(maxSize, bounds);
}
private static int getSampleFactor(Resources res, int resrouceId, int maxSize) {
BitmapFactory.Options bounds = getBounds(res, resrouceId);
return getSampleFactor(maxSize, bounds);
}
private static int getSampleFactor(int maxSize, BitmapFactory.Options bounds) {
int width = bounds.outWidth;
int height = bounds.outHeight;
if (width > height) {
if (width > maxSize) {
return width / maxSize + 1;
} else {
return 1;
}
} else {
if (height > maxSize) {
return height / maxSize + 1;
} else {
return 1;
}
}
}
public static BitmapFactory.Options getBounds(byte[] byteArray) {
BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, bounds);
return bounds;
}
public static BitmapFactory.Options getBounds(Resources res, int resourceId) {
BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resourceId, bounds);
return bounds;
}
public static BitmapFactory.Options getBounds(String path) {
BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, bounds);
return bounds;
}
public static float[] normalizeCoordsSum(float[] vector, float newSum) {
float sum = 0;
for (int i = 0; i < vector.length; i++) {
sum += vector[i];
}
for (int i = 0; i < vector.length; i++) {
vector[i] /= sum * newSum;
}
return vector;
}
public static float[] getMean(float[] coords1, float[] coords2) {
if (coords1.length != coords2.length) {
Log.wtf(TAG, new NullPointerException());
return null;
}
float[] mean = new float[coords1.length];
for (int i = 0; i < coords1.length; i++) {
mean[i] = (coords1[i] + coords2[i]) / 2;
}
return mean;
}
public static ArrayList<Integer> getRandomNumbers(int range, int count, Random rnd) {
if (count > range) {
return null;
}
if (count < 0 || range < 0) {
return null;
}
HashMap<Integer, Integer> used = new HashMap<Integer, Integer>();
ArrayList<Integer> indices = new ArrayList<Integer>();
int n = range;
while (indices.size() < count) {
Integer r = Integer.valueOf(rnd.nextInt(n));
if (used.containsKey(r)) {
indices.add(used.get(r));
} else {
indices.add(r);
}
addToUsed(used, r, n - 1);
n--;
}
return indices;
}
private static void addToUsed(HashMap<Integer, Integer> used, Integer key, Integer value) {
if (used.containsKey(value)) {
value = used.get(value);
addToUsed(used, key, value);
}
used.put(key, value);
}
public static float dotProduct(float[] vector1, float[] vector2) {
if (vector1 == null || vector2 == null) {
}
float sum = 0;
for (int i = 0; i < vector1.length; i++) {
float float1 = vector1[i];
float float2 = vector2[i];
// sum += vector1[i] * vector2[i];
sum += float1 * float2;
}
return sum;
}
public static boolean hasInternetConnection(Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity == null) {
Log.w(TAG, "couldn't get connectivity manager");
} else {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
return true;
}
}
}
}
return false;
}
public static float norm2(float[] vec) {
float sum = 0;
for (float f : vec) {
sum += Math.pow(f, 2);
}
return (float) Math.sqrt(sum);
}
public static String getString(int resId) {
return JukefoxApplication.getAppContext().getString(resId);
}
public static DefaultHttpClient createHttpClientWithDefaultSettings() {
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, Constants.CONNECTION_TIMEOUT);
HttpConnectionParams.setSoTimeout(params, Constants.CONNECTION_TIMEOUT);
DefaultHttpClient httpClient = new DefaultHttpClient(params);
HttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(2, true);
httpClient.setHttpRequestRetryHandler(retryHandler);
return httpClient;
}
/**
* Add a weighted vector to another resultVec = resultVec + (summand*weight)
*
* @param resultVec
* @param summand
*/
public static void addWeightedVector(float[] resultVec, float[] summand, float weight) {
for (int i = 0; i < resultVec.length; i++) {
resultVec[i] += summand[i] * weight;
}
}
/**
* Divide all element of a vector by a scalar
*
* @param resultVec
* @param divisor
*/
public static void divideVector(float[] resultVec, float divisor) {
for (int i = 0; i < resultVec.length; i++) {
resultVec[i] /= divisor;
}
}
/**
* On the Motorola Atrix, activating the sensors results in a buzzing sound.
* On Android 2.3.x devices activating the sensors leads to a huge battery
* consumption
*
* @return
*/
public static boolean isSensorProblemDevice() {
if (isSensorProblemDevice == null) {
// Compare it to the model name of the motorola atrix
if (android.os.Build.MODEL.equals("MB860")) {
Log.v(TAG, "SensorProblemDevice - MB860");
isSensorProblemDevice = true;
} else if (android.os.Build.VERSION.RELEASE.startsWith("2.3")) {
Log.v(TAG, "SensorProblemDevice - 2.3.x");
isSensorProblemDevice = true;
} else {
isSensorProblemDevice = false;
}
}
Log.v(TAG, "isSensorProblemDevice: " + isSensorProblemDevice);
return isSensorProblemDevice;
}
public static void printSongCollection(String label,
Collection<? extends BaseSong<? extends BaseArtist, ? extends BaseAlbum>> songs) {
Log.v(TAG, label);
for (BaseSong<? extends BaseArtist, ? extends BaseAlbum> s : songs) {
Log.v(TAG, "id: " + s.getId() + ", " + s.getArtist() + " - " + s.getTitle());
}
}
public static void printCollection(String label, Collection<? extends Object> collection) {
Log.v(TAG, label);
for (Object o : collection) {
Log.v(TAG, o.toString());
}
}
public static boolean equals(float[] p1, float[] p2) {
if (p1 == null) {
return p2 == null;
}
if (p2 == null) {
return false;
}
if (p1.length != p2.length) {
return false;
}
for (int i = 0; i < p1.length; i++) {
if (p1[i] != p2[i]) {
return false;
}
}
return true;
}
public static int getHashCode(float[] p) {
if (p == null) {
return 0;
}
int hash = 0;
for (Float f : p) {
hash ^= f.hashCode();
}
return hash;
}
public static List<String> listFilesRecursive(String startPath, FilenameFilter filter) {
List<String> files = new ArrayList<String>();
File start = new File(startPath);
addFilesRecursive(files, start, filter);
return files;
}
public static void addFilesRecursive(List<String> files, File location, FilenameFilter filter) {
if (!location.exists()) {
return;
}
if (!location.isDirectory()) {
if (filter.accept(location.getParentFile(), location.getName())) {
files.add(location.getAbsolutePath());
}
}
// we are in a directory => add all files matching filter and then
// recursively add all files in subdirectories
File[] tmp = location.listFiles(filter);
if (tmp != null) {
for (File file : tmp) {
files.add(file.getAbsolutePath());
}
}
File[] dirs = location.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isDirectory();
}
});
if (dirs == null) {
return;
}
for (File dir : dirs) {
addFilesRecursive(files, dir, filter);
}
}
}