szkolny/app/src/main/java/pl/szczodrzynski/edziennik/utils/Utils.java

799 lines
28 KiB
Java
Raw Normal View History

package pl.szczodrzynski.edziennik.utils;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import androidx.annotation.AttrRes;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.Base64;
import android.util.Log;
import android.util.TypedValue;
import android.webkit.MimeTypeMap;
import android.widget.Toast;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.channels.FileChannel;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import androidx.core.content.FileProvider;
import pl.szczodrzynski.edziennik.App;
public class Utils {
private static final String TAG = "Utils";
public static String bs(@Nullable String s) {
return ns("", s);
}
public static String bs(String prefix, @Nullable String s) {
return ns("", prefix, s);
}
public static String bs(@Nullable String prefix, @Nullable String s, String suffix) {
return ns("", prefix, s, suffix);
}
public static String ns(String ifNull, @Nullable String s) {
return s == null || s.trim().isEmpty() ? ifNull : s;
}
public static String ns(String ifNull, String prefix, @Nullable String s) {
return s == null || s.trim().isEmpty() ? ifNull : prefix+s;
}
public static String ns(String ifNull, @Nullable String prefix, @Nullable String s, String suffix) {
return s == null || s.trim().isEmpty() ? ifNull : (prefix == null ? "" : prefix)+s+suffix;
}
public static boolean contains(@Nullable List<?> list, @NonNull Object o) {
if (list == null)
return false;
return list.contains(o);
/*for (Object o2: list) {
if (o.equals(o2))
return true;
}
return false;*/
}
public static List<String> debugLog = new ArrayList<>();
public static void d(String TAG, String message) {
if (App.devMode) {
Log.d(TAG, message);
//debugLog.add(TAG+": "+message);
}
}
public static void c(String TAG, String message) {
if (App.devMode) {
Log.d(TAG, "// " + message);
///debugLog.add(TAG+": // "+message);
}
}
/**
* Returns the first set (high) bit position, from right to left.
* @param n the number
* @return a 0-indexed position
*/
public static int rightmostSetBit(int n) {
return (int)((Math.log10(n & -n)) / Math.log10(2));
}
/**
* Returns the last set (high) bit position, from left to right.
* @param n the number
* @return a 0-indexed position
*/
public static int leftmostSetBit(int n) {
return (int)(Math.log(n) / Math.log(2));
}
/**
* Returns number of cells needed for given size of the widget.
*
* @param size Widget size in dp.
* @return Size in number of cells.
*/
public static int getCellsForSize(int size) {
int n = 2;
while (70 * n - 30 < size) {
++n;
}
return n - 1;
}
// EXCEPTION: thread does not change
/*public static void exception(String TAG, Response response, @NonNull Throwable throwable, String initialApiResponse, SyncCallback callback, Context activityContext) {
//d(TAG, "Thread/exception1/"+Thread.currentThread().getName());
if (Thread.currentThread().getName().equals("main")) {
AsyncTask.execute(() -> {
exceptionRun(TAG, response, throwable, initialApiResponse, callback, activityContext, true);
});
}
else {
exceptionRun(TAG, response, throwable, initialApiResponse, callback, activityContext, false);
}
}
private static void exceptionRun(String TAG, Response response, @NonNull Throwable throwable, String initialApiResponse, SyncCallback callback, Context activityContext, boolean finishOnMainThread) {
//d(TAG, "Thread/exception2/"+Thread.currentThread().getName());
String apiResponse = initialApiResponse;
throwable.printStackTrace();
if (response != null) {
//d(TAG, response.code() + " " + response.message());
if (apiResponse == null) {
apiResponse = response.code()+" "+response.message()+"\n";
if (response.raw().body() != null) {
try {
apiResponse += response.raw().body().string();
} catch (Exception e) {
e.printStackTrace();
apiResponse += "Exception while getting response body:\n"+Log.getStackTraceString(e);
}
}
else {
apiResponse += "Response body is null.";
}
}
String apiResponsePrefix = "Request:\n";
apiResponsePrefix += response.request().url().toString()+"\n";
apiResponsePrefix += response.request().headers().toString()+"\n";
apiResponsePrefix += response.request().bodyToString();
apiResponsePrefix += "\n\nResponse:\n";
apiResponse = apiResponsePrefix + apiResponse;
}
if (callback != null) {
String finalApiResponse = apiResponse;
if (!finishOnMainThread) {
exceptionFinish(TAG, response, throwable, finalApiResponse, callback, activityContext);
return;
}
new Handler(activityContext != null ? activityContext.getMainLooper() : Looper.getMainLooper()).post(() -> {
exceptionFinish(TAG, response, throwable, finalApiResponse, callback, activityContext);
});
}
}
private static void exceptionFinish(String TAG, Response response, @NonNull Throwable throwable, String finalApiResponse, SyncCallback callback, Context activityContext) {
//d(TAG, "Thread/exception3/"+Thread.currentThread().getName());
if (throwable instanceof UnknownHostException) {
callback.onError(activityContext, Error.CODE_NO_INTERNET, "", throwable, finalApiResponse);
}
else if (throwable instanceof SSLException) {
callback.onError(activityContext, Error.CODE_SSL_ERROR, "", throwable, finalApiResponse);
}
else if (throwable instanceof SocketTimeoutException) {
callback.onError(activityContext, Error.CODE_TIMEOUT, "", throwable, finalApiResponse);
}
else if (throwable instanceof InterruptedIOException) {
callback.onError(activityContext, Error.CODE_NO_INTERNET, "", throwable, finalApiResponse);
}
else {
if (response != null) {
if (response.code() == 424 || response.code() == 400 || response.code() == 401 || response.code() == 500 || response.code() == 503 || response.code() == 404) {
callback.onError(activityContext, CODE_MAINTENANCE, response.code() + " " + response.message() + " " + throwable.getMessage(), throwable, finalApiResponse);
}
else {
callback.onError(activityContext, CODE_OTHER, response.code() + " " + response.message() + " " + throwable.getMessage(), throwable, finalApiResponse);
}
}
else {
callback.onError(activityContext, CODE_OTHER, throwable.getMessage(), throwable, finalApiResponse);
}
}
}*/
public static String hexFromColorInt(@ColorInt int color) {
return String.format("%06X", (0xFFFFFF & color));
}
public static String getRealPathFromURI(Context context, Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
CursorLoader loader = new CursorLoader(context, contentUri, proj, null, null, null);
Cursor cursor = loader.loadInBackground();
int column_index;
String result = null;
try {
column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
result = cursor.getString(column_index);
cursor.close();
}
catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static int strToInt(String s, int defaultValue)
{
try {
return Integer.parseInt(s);
}
catch (Exception e) {
e.printStackTrace();
return defaultValue;
}
}
public static int strToInt(String s)
{
return Integer.parseInt(s);
}
public static String intToStr(Integer i)
{
return Integer.toString(i);
}
public static int crc16(final byte[] buffer) {
int crc = 0xFFFF;
for (byte aBuffer : buffer) {
crc = ((crc >>> 8) | (crc << 8)) & 0xffff;
crc ^= (aBuffer & 0xff); // byte to int, trunc sign
crc ^= ((crc & 0xff) >> 4);
crc ^= (crc << 12) & 0xffff;
crc ^= ((crc & 0xFF) << 5) & 0xffff;
}
crc &= 0xffff;
return crc+32768;
}
public static long crc32(byte[] buffer) {
CRC32 crc = new CRC32();
crc.update(buffer);
return crc.getValue();
}
public static String toPascalCase(String source) {
return source.toUpperCase().charAt(0)+source.toLowerCase().substring(1);
}
@ColorInt
public static int getAttr(Context context, @AttrRes int resourceId) {
TypedValue typedValue = new TypedValue();
Resources.Theme theme = context.getTheme();
theme.resolveAttribute(resourceId, typedValue, true);
return typedValue.data;
}
public static int dpToPx(int dp)
{
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
public static int pxToDp(int px)
{
return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
public static void openGooglePlay(Context context) {
openGooglePlay(context, context.getPackageName());
}
public static void openGooglePlay(Context context, String packageName) {
try {
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + packageName)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
} catch (android.content.ActivityNotFoundException e) {
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + packageName)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
}
public static void openUrl(Context context, String url) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
context.startActivity(i);
}
public static String checkAppExists(Context context, String packageName) {
try {
PackageInfo packageInfo;
packageInfo = context.getPackageManager().getPackageInfo(packageName, 0);
if (packageInfo != null) {
Log.d(TAG, packageInfo.toString());
Log.d(TAG, packageInfo.packageName+" "+packageInfo.versionName+" "+packageInfo.versionCode);
return packageInfo.versionName;
}
else {
return null;
}
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void copy(File src, File dst) throws IOException {
FileInputStream inStream = new FileInputStream(src);
FileOutputStream outStream = new FileOutputStream(dst);
FileChannel inChannel = inStream.getChannel();
FileChannel outChannel = outStream.getChannel();
inChannel.transferTo(0, inChannel.size(), outChannel);
inStream.close();
outStream.close();
}
public static Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// "RECREATE" THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(
bm, 0, 0, width, height, matrix, false);
bm.recycle();
return resizedBitmap;
}
public static class VulcanRequestEncryptionUtils {
private static final String ALGORITHM_NAME = "SHA1withRSA";
private static final String CERT_TYPE = "pkcs12";
private static final String CONTAINER_NAME = "LoginCert";
private static final String PASSWORD = "CE75EA598C7743AD9B0B7328DED85B06";
public static String signContent(byte[] contents, final InputStream cert) throws IOException, GeneralSecurityException, NullPointerException {
final KeyStore instance = KeyStore.getInstance(CERT_TYPE);
instance.load(cert, PASSWORD.toCharArray());
final PrivateKey privateKey = (PrivateKey) instance.getKey(CONTAINER_NAME, PASSWORD.toCharArray());
final Signature instance2 = Signature.getInstance(ALGORITHM_NAME);
instance2.initSign(privateKey);
instance2.update(contents);
return Base64.encodeToString(instance2.sign(), Base64.DEFAULT).replace("\n", "");
}
}
public static class VulcanQrEncryptionUtils {
private static final String PASSWORD = "tDVS4ykCBBAeN33h";
public static String decode(String content) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, ShortBufferException, BadPaddingException, IllegalBlockSizeException {
@SuppressLint("GetInstance") Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
byte[] input = Base64.decode(content, Base64.DEFAULT);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(PASSWORD.getBytes(), "AES"));
byte[] plainText = new byte[cipher.getOutputSize(input.length)];
int ptLength = cipher.update(input, 0, input.length, plainText, 0);
ptLength += cipher.doFinal(plainText, ptLength);
return new String(plainText);
}
}
public static class AESCrypt
{
private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
public static String encrypt(String value, String key) throws Exception
{
Key keyObj = generateKey(key);
Cipher cipher = Cipher.getInstance(AESCrypt.ALGORITHM);
byte[] iv = new byte[16];
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, keyObj, ivSpec);
byte [] encryptedByteValue = cipher.doFinal(value.getBytes("utf-8"));
String encryptedValue64 = Base64.encodeToString(encryptedByteValue, Base64.DEFAULT);
return encryptedValue64;
}
public static String decrypt(String value, String key) throws Exception
{
Key keyObj = generateKey(key);
Cipher cipher = Cipher.getInstance(AESCrypt.ALGORITHM);
byte[] iv = new byte[16];
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, keyObj, ivSpec);
byte[] decryptedValue64 = Base64.decode(value, Base64.DEFAULT);
byte [] decryptedByteValue = cipher.doFinal(decryptedValue64);
String decryptedValue = new String(decryptedByteValue,"utf-8");
return decryptedValue;
}
private static Key generateKey(String key) throws Exception
{
Key keyObj = new SecretKeySpec(key.getBytes(),AESCrypt.ALGORITHM);
return keyObj;
}
}
private static String Base64UrlSafe(byte[] data)
{
String enc = Base64.encodeToString(data, Base64.URL_SAFE | Base64.NO_WRAP);
return enc.replace("=", "");
}
private final static char[] hexArray = "0123456789abcdef".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
public static String HmacSHA512(String message, String secret)
{
try {
Mac sha_HMAC = Mac.getInstance("HmacSHA512");
SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA512");
sha_HMAC.init(secret_key);
return Base64UrlSafe(sha_HMAC.doFinal(message.getBytes()));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
public static String HmacMD5(String message, String secret)
{
try {
Mac sha_HMAC = Mac.getInstance("HmacMD5");
SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacMD5");
sha_HMAC.init(secret_key);
return bytesToHex(sha_HMAC.doFinal(message.getBytes()));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
public static String MD5(String message)
{
try {
// Create MD5 Hash
MessageDigest md = java.security.MessageDigest.getInstance("MD5");
return Base64UrlSafe(md.digest(message.getBytes()));
}catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
public static float getGradeValue(String grade) {
switch (grade) {
case "1-":
return 0.75f;
case "1":
return 1.00f;
case "1+":
return 1.50f;
case "2-":
return 1.75f;
case "2":
return 2.00f;
case "2+":
return 2.50f;
case "3-":
return 2.75f;
case "3":
return 3.00f;
case "3+":
return 3.50f;
case "4-":
return 3.75f;
case "4":
return 4.00f;
case "4+":
return 4.50f;
case "5-":
return 4.75f;
case "5":
return 5.00f;
case "5+":
return 5.50f;
case "6-":
return 5.75f;
case "6":
return 6.00f;
case "6+":
return 6.50f;
}
return 0.00f;
}
public static int getVulcanGradeColor(String name) {
switch (name) {
case "1-":
case "1":
case "1+":
return 0xffd65757;
case "2-":
case "2":
case "2+":
return 0xff9071b3;
case "3-":
case "3":
case "3+":
return 0xffd2ab24;
case "4-":
case "4":
case "4+":
return 0xff50b6d6;
case "5-":
case "5":
case "5+":
return 0xff2cbd92;
case "6-":
case "6":
case "6+":
return 0xff91b43c;
default:
return 0xff3D5F9C;
}
}
public static int getWordGradeValue(String grade) {
switch (grade) {
case "niedostateczny":
return 1;
case "dopuszczający":
return 2;
case "dostateczny":
return 3;
case "dobry":
return 4;
case "bardzo dobry":
return 5;
case "celujący":
return 6;
default:
return 0;
}
}
public static boolean zipFileAtPath(String sourcePath, String toLocation) {
final int BUFFER = 2048;
File sourceFile = new File(sourcePath);
try {
BufferedInputStream origin = null;
FileOutputStream dest = new FileOutputStream(toLocation);
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
dest));
if (sourceFile.isDirectory()) {
zipSubFolder(out, sourceFile, sourceFile.getParent().length());
} else {
byte data[] = new byte[BUFFER];
FileInputStream fi = new FileInputStream(sourcePath);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(getLastPathComponent(sourcePath));
entry.setTime(sourceFile.lastModified()); // to keep modification time after unzipping
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
}
out.close();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/*
*
* Zips a subfolder
*
*/
private static void zipSubFolder(ZipOutputStream out, File folder,
int basePathLength) throws IOException {
final int BUFFER = 2048;
File[] fileList = folder.listFiles();
BufferedInputStream origin = null;
for (File file : fileList) {
if (file.isDirectory()) {
zipSubFolder(out, file, basePathLength);
} else {
byte data[] = new byte[BUFFER];
String unmodifiedFilePath = file.getPath();
String relativePath = unmodifiedFilePath
.substring(basePathLength);
FileInputStream fi = new FileInputStream(unmodifiedFilePath);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(relativePath);
entry.setTime(file.lastModified()); // to keep modification time after unzipping
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
}
}
}
/*
* gets the last path component
*
* Example: getLastPathComponent("downloads/example/fileToZip");
* Result: "fileToZip"
*/
public static String getLastPathComponent(String filePath) {
String[] segments = filePath.split("/");
if (segments.length == 0)
return "";
String lastPathComponent = segments[segments.length - 1];
return lastPathComponent;
}
public static String readableFileSize(long size) {
if(size <= 0) return "0B";
final String[] units = new String[] { "B", "kB", "MB", "GB", "TB", "PB" };
int digitGroups = (int) (Math.log10(size)/Math.log10(1024));
return new DecimalFormat("#,##0.#").format(size/Math.pow(1024, digitGroups)) + units[digitGroups];
}
public static int monthFromName(String name) {
int month = 1;
switch (name) {
case "stycznia":
month = 1;
break;
case "lutego":
month = 2;
break;
case "marca":
month = 3;
break;
case "kwietnia":
month = 4;
break;
case "maja":
month = 5;
break;
case "czerwca":
month = 6;
break;
case "lipca":
month = 7;
break;
case "sierpnia":
month = 8;
break;
case "września":
month = 9;
break;
case "października":
month = 10;
break;
case "listopada":
month = 11;
break;
case "grudnia":
month = 12;
break;
}
return month;
}
private static String convertStreamToString(InputStream is) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line;
boolean first = true;
while ((line = reader.readLine()) != null) {
if (!(first && !(first = !first)))
sb.append("\n");
sb.append(line);
}
reader.close();
return sb.toString();
}
public static String getStringFromFile (File fl) throws Exception {
FileInputStream fin = new FileInputStream(fl);
String ret = convertStreamToString(fin);
//Make sure you close all streams.
fin.close();
return ret;
}
public static void openFile(Context context, File file) {
try {
Uri uri = Uri.fromFile(file);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file);
}
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(getExtensionFromFileName(file.toString()));
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, mimeType == null ? "*/*" : mimeType);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(context, "Nie ma aplikacji która otwiera ten typ pliku", Toast.LENGTH_LONG).show();
}
}
private static File storageDir = null;
public static File getStorageDir() {
if (storageDir != null)
return storageDir;
storageDir = Environment.getExternalStoragePublicDirectory("Szkolny.eu");
storageDir.mkdirs();
return storageDir;
}
public static void writeStringToFile(File file, String data) throws IOException {
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(file));
outputStreamWriter.write(data);
outputStreamWriter.close();
}
public static String getExtensionFromFileName(String fileName) {
return fileName.substring(fileName.lastIndexOf(".")+1).toLowerCase();
}
public static String getCurrentTimeUsingCalendar() {
Calendar cal = Calendar.getInstance();
Date date=cal.getTime();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
return dateFormat.format(date);
}
}