package de.tum.in.tumcampusapp.auxiliary;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.preference.PreferenceManager;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import de.tum.in.tumcampusapp.BuildConfig;
/**
* Class for common helper functions used by a lot of classes
*/
public final class Utils {
private static final String LOGGING_REGEX = "[a-zA-Z0-9.]+\\.";
private Utils() {
// Utils is a utility class
}
/**
* Builds a HTML document out of a css file and the body content.
*
* @param css The CSS specification
* @param body The body content
* @return The HTML document.
*/
public static String buildHTMLDocument(String css, String body) {
String header = "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"de\" lang=\"de\">" +
"<head><meta name=\"viewport\" content=\"width=device-width\" />" +
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></head>";
String resultCss = "<style type=\"text/css\">" + css + "</style>";
String resultBody = "<body>" + body + "</body>";
String footer = "</html>";
return header + resultCss + resultBody + footer;
}
/**
* Cut substring from a text.
*
* @param text The text.
* @param startString Start string where the cutting begins.
* @param endString End string where the cutting ends.
* @return The cut text.
*/
public static String cutText(String text, String startString, String endString) {
int startPos = text.indexOf(startString);
int endPos = text.indexOf(endString, startPos);
if (startPos == -1) {
startPos = 0;
}
if (endPos == -1 || endPos < startPos) {
endPos = text.length();
}
return text.substring(startPos + startString.length(), endPos);
}
/**
* Converts a date-string to Date
*
* @param str String with ISO-Date (yyyy-mm-dd)
* @return Date
*/
public static Date getDate(String str) {
try {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
return dateFormat.parse(str);
} catch (ParseException e) {
log(e, str);
}
return new Date();
}
/**
* Converts Date to an ISO date-string
*
* @param d Date
* @return String (yyyy-mm-dd)
*/
public static String getDateString(Date d) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
return dateFormat.format(d);
}
/**
* Converts Date to an ISO datetime-string
*
* @param d Date
* @return String (yyyy-mm-dd hh:mm:ss)
*/
public static String getDateTimeString(Date d) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
return dateFormat.format(d);
}
/**
* Converts a datetime-string to Date
*
* @param str String with ISO-DateTime (yyyy-mm-dd hh:mm:ss)
* @return Date
*/
public static Date getISODateTime(String str) {
try {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
return dateFormat.parse(str);
} catch (ParseException e) {
log(e, str);
}
return new Date();
}
/**
* Get a value from the default shared preferences
*
* @param c Context
* @param key setting name
* @param defaultVal default value
* @return setting value, "" if undefined
*/
public static String getSetting(Context c, String key, String defaultVal) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(c);
return sp.getString(key, defaultVal);
}
/**
* Get a value from the default shared preferences
*
* @param c Context
* @param key setting name
* @param classInst e.g. ChatMember.class
* @return setting value, "" if undefined
*/
public static <T> T getSetting(Context c, String key, Class<T> classInst) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(c);
String val = sp.getString(key, null);
if (val != null) {
return new Gson().fromJson(val, classInst);
}
return null;
}
/**
* Return the boolean value of a setting
*
* @param c Context
* @param name setting name
* @param defaultVal default value
* @return true if setting was checked, else value
*/
public static boolean getSettingBool(Context c, String name, boolean defaultVal) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(c);
return sp.getBoolean(name, defaultVal);
}
/**
* Logs an exception and additional information
* Use this anywhere in the app when a fatal error occurred.
* If you can give a better description of what went wrong
* use {@link #log(Exception, String)} instead.
*
* @param e Exception (source for message and stack trace)
*/
public static void log(Throwable e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String s = Thread.currentThread().getStackTrace()[3].getClassName().replaceAll(LOGGING_REGEX, "");
Log.e(s, e + "\n" + sw);
}
/**
* Logs an exception and additional information
* Use this anywhere in the app when a fatal error occurred.
* If you can't give an exact error description simply use
* {@link #log(Exception)} instead.
*
* @param e Exception (source for message and stack trace)
* @param message Additional information for exception message
*/
public static void log(Throwable e, String message) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String s = Thread.currentThread().getStackTrace()[3].getClassName().replaceAll(LOGGING_REGEX, "");
Log.e(s, e + " " + message + '\n' + sw);
}
/**
* Logs a message
* Use this to log the current app state.
*
* @param message Information or Debug message
*/
public static void log(String message) {
if (!BuildConfig.DEBUG) {
return;
}
String s = Thread.currentThread().getStackTrace()[3].getClassName().replaceAll(LOGGING_REGEX, "");
Log.d(s, message);
}
/**
* Logs a message
* Use this to log additional information that is not important in most cases.
*
* @param message Information or Debug message
*/
public static void logv(String message) {
if (!BuildConfig.DEBUG) {
return;
}
String s = Thread.currentThread().getStackTrace()[3].getClassName().replaceAll(LOGGING_REGEX, "");
Log.v(s, message);
}
/**
* Logs a message with specified tag
* Use this to log a particular work
*
* @param message Information or Debug message
*/
public static void logwithTag(String tag, String message) {
if (!BuildConfig.DEBUG) {
return;
}
Log.v(tag, message);
}
/**
* Get md5 hash from string
*
* @param str String to hash
* @return md5 hash as string
*/
public static String md5(String str) {
return Hashing.md5().hashBytes(str.getBytes(Charsets.UTF_8)).toString();
}
/**
* Returns a String[]-List from a CSV input stream
*
* @param fin CSV input stream
* @return String[]-List with Columns matched to array values
*/
public static List<String[]> readCsv(InputStream fin) {
List<String[]> list = new ArrayList<>(64);
try {
BufferedReader in = new BufferedReader(new InputStreamReader(fin, Charsets.UTF_8));
try {
String reader;
while ((reader = in.readLine()) != null) {
list.add(splitCsvLine(reader));
}
} finally {
in.close();
}
} catch (IOException e) {
log(e);
}
return list;
}
/**
* Sets the value of a setting
*
* @param c Context
* @param key setting key
*/
public static void setSetting(Context c, String key, boolean value) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(c);
sp.edit().putBoolean(key, value).apply();
}
/**
* Sets the value of a setting
*
* @param c Context
* @param key setting key
* @param value String value
*/
public static void setSetting(Context c, String key, String value) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(c);
sp.edit().putString(key, value).apply();
}
/**
* Sets the value of a setting
*
* @param c Context
* @param key setting key
*/
public static void setSetting(Context c, String key, Object value) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(c);
sp.edit().putString(key, new Gson().toJson(value)).apply();
}
/**
* Shows a long {@link Toast} message.
*
* @param context The activity where the toast is shown
* @param msg The toast message id
*/
public static void showToast(Context context, int msg) {
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
}
/**
* Shows a long {@link Toast} message.
*
* @param context The activity where the toast is shown
* @param msg The toast message
*/
public static void showToast(Context context, CharSequence msg) {
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
}
/**
* Splits a line from a CSV file into column values
* <p/>
* e.g. "aaa;aaa";"bbb";1 gets aaa,aaa;bbb;1;
*
* @param str CSV line
* @return String[] with CSV column values
*/
private static String[] splitCsvLine(CharSequence str) {
StringBuilder result = new StringBuilder();
boolean open = false;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c == '"') {
open = !open;
continue;
}
if (open && c == ';') {
result.append(',');
} else {
result.append(c);
}
}
// fix trailing ";", e.g. ";;;".split().length = 0
result.append("; ");
return result.toString().split(";");
}
/**
* Converts a meter based value to a formatted string
*
* @param meters Meters to represent
* @return Formatted meters. e.g. 10m, 12.5km
*/
public static String formatDist(float meters) {
if (meters < 1000) {
return ((int) meters) + "m";
} else if (meters < 10000) {
int front = (int) (meters / 1000f);
int back = (int) Math.abs(meters / 100f) % 10;
return front + "." + back + "km";
} else {
return ((int) (meters / 1000f)) + "km";
}
}
/**
* Sets an internal preference's boolean value
*
* @param context Context
* @param key Key
* @param value Value
*/
public static void setInternalSetting(Context context, String key, boolean value) {
SharedPreferences prefs = context.getSharedPreferences(Const.INTERNAL_PREFS, Context.MODE_PRIVATE);
prefs.edit().putBoolean(key, value).apply();
}
/**
* Sets an internal preference's integer value
*
* @param context Context
* @param key Key
* @param value Value
*/
public static void setInternalSetting(Context context, String key, int value) {
SharedPreferences prefs = context.getSharedPreferences(Const.INTERNAL_PREFS, Context.MODE_PRIVATE);
prefs.edit().putInt(key, value).apply();
}
/**
* Sets an internal preference's long value
*
* @param context Context
* @param key Key
* @param value Value
*/
public static void setInternalSetting(Context context, String key, long value) {
SharedPreferences prefs = context.getSharedPreferences(Const.INTERNAL_PREFS, Context.MODE_PRIVATE);
prefs.edit().putLong(key, value).apply();
}
/**
* Sets an internal preference's string value
*
* @param context Context
* @param key Key
* @param value Value
*/
public static void setInternalSetting(Context context, String key, String value) {
SharedPreferences prefs = context.getSharedPreferences(Const.INTERNAL_PREFS, Context.MODE_PRIVATE);
prefs.edit().putString(key, value).apply();
}
/**
* Gets an internal preference's boolean value
*
* @param context Context
* @param key Key
* @param value Default value
* @return The value of the setting or the default value,
* if no setting with the specified key exists
*/
public static boolean getInternalSettingBool(Context context, String key, boolean value) {
SharedPreferences prefs = context.getSharedPreferences(Const.INTERNAL_PREFS, Context.MODE_PRIVATE);
return prefs.getBoolean(key, value);
}
/**
* Gets an internal preference's integer value
*
* @param context Context
* @param key Key
* @param value Default value
* @return The value of the setting or the default value,
* if no setting with the specified key exists
*/
public static int getInternalSettingInt(Context context, String key, int value) {
SharedPreferences prefs = context.getSharedPreferences(Const.INTERNAL_PREFS, Context.MODE_PRIVATE);
return prefs.getInt(key, value);
}
/**
* Gets an internal preference's long value
*
* @param context Context
* @param key Key
* @param value Default value
* @return The value of the setting or the default value,
* if no setting with the specified key exists
*/
public static long getInternalSettingLong(Context context, String key, long value) {
SharedPreferences prefs = context.getSharedPreferences(Const.INTERNAL_PREFS, Context.MODE_PRIVATE);
return prefs.getLong(key, value);
}
/**
* Gets an internal preference's string value
*
* @param context Context
* @param key Key
* @param value Default value
* @return The value of the setting or the default value,
* if no setting with the specified key exists
*/
public static String getInternalSettingString(Context context, String key, String value) {
SharedPreferences prefs = context.getSharedPreferences(Const.INTERNAL_PREFS, Context.MODE_PRIVATE);
return prefs.getString(key, value);
}
/**
* @return Application's version code from the {@code PackageManager}.
*/
public static int getAppVersion(Context context) {
try {
PackageInfo packageInfo = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionCode;
} catch (PackageManager.NameNotFoundException e) {
// should never happen
throw new AssertionError("Could not get package name: " + e);
}
}
public static void showToastOnUIThread(final Activity activity, final int s) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Utils.showToast(activity, s);
}
});
}
public static void showToastOnUIThread(final Activity activity, final String s) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Utils.showToast(activity, s);
}
});
}
/**
* Removes all html tags from a string
*
* @param html text which contains html tags
* @return cleaned text without any tags
*/
public static String stripHtml(String html) {
return fromHtml(html).toString();
}
public static boolean isBackgroundServicePermitted(Context context) {
return isBackgroundServiceEnabled(context) && (isBackgroundServiceAlwaysEnabled(context) || NetUtils.isConnectedWifi(context));
}
private static boolean isBackgroundServiceEnabled(Context context) {
return Utils.getSettingBool(context, Const.BACKGROUND_MODE, false);
}
private static boolean isBackgroundServiceAlwaysEnabled(Context context) {
return "0".equals(Utils.getSetting(context, "background_mode_set_to", "0"));
}
public static String arrayListToString(Iterable<String> array) {
return TextUtils.join(",", array);
}
@TargetApi(Build.VERSION_CODES.N)
@SuppressWarnings("deprecation")
public static Spanned fromHtml(String source) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ?
Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY) :
Html.fromHtml(source);
}
}