migration to Kotlin (WIP)
This commit is contained in:
parent
bdd18d9e71
commit
b315ebe724
6 changed files with 106 additions and 152 deletions
|
@ -1,79 +0,0 @@
|
||||||
package deckers.thibault.aves.utils;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.exifinterface.media.ExifInterface;
|
|
||||||
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class MetadataHelper {
|
|
||||||
|
|
||||||
// interpret EXIF code to angle (0, 90, 180 or 270 degrees)
|
|
||||||
public static int getOrientationDegreesForExifCode(int exifOrientation) {
|
|
||||||
switch (exifOrientation) {
|
|
||||||
case ExifInterface.ORIENTATION_ROTATE_180: // bottom, right side
|
|
||||||
return 180;
|
|
||||||
case ExifInterface.ORIENTATION_ROTATE_90: // right side, top
|
|
||||||
return 90;
|
|
||||||
case ExifInterface.ORIENTATION_ROTATE_270: // left side, bottom
|
|
||||||
return 270;
|
|
||||||
}
|
|
||||||
// all other orientations (regular, flipped...) default to an angle of 0 degree
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// yyyyMMddTHHmmss(.sss)?(Z|+/-hhmm)?
|
|
||||||
public static long parseVideoMetadataDate(@Nullable String dateString) {
|
|
||||||
if (dateString == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// optional sub-second
|
|
||||||
String subSecond = null;
|
|
||||||
Matcher subSecondMatcher = Pattern.compile("(\\d{6})(\\.\\d+)").matcher(dateString);
|
|
||||||
if (subSecondMatcher.find()) {
|
|
||||||
subSecond = subSecondMatcher.group(2).substring(1);
|
|
||||||
dateString = subSecondMatcher.replaceAll("$1");
|
|
||||||
}
|
|
||||||
|
|
||||||
// optional time zone
|
|
||||||
TimeZone timeZone = null;
|
|
||||||
Matcher timeZoneMatcher = Pattern.compile("(Z|[+-]\\d{4})$").matcher(dateString);
|
|
||||||
if (timeZoneMatcher.find()) {
|
|
||||||
timeZone = TimeZone.getTimeZone("GMT" + timeZoneMatcher.group().replaceAll("Z", ""));
|
|
||||||
dateString = timeZoneMatcher.replaceAll("");
|
|
||||||
}
|
|
||||||
|
|
||||||
Date date = null;
|
|
||||||
try {
|
|
||||||
DateFormat parser = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.US);
|
|
||||||
parser.setTimeZone((timeZone != null) ? timeZone : TimeZone.getTimeZone("GMT"));
|
|
||||||
date = parser.parse(dateString);
|
|
||||||
} catch (ParseException e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
if (date == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
long dateMillis = date.getTime();
|
|
||||||
if (subSecond != null) {
|
|
||||||
try {
|
|
||||||
int millis = (int) (Double.parseDouble("." + subSecond) * 1000);
|
|
||||||
if (millis >= 0 && millis < 1000) {
|
|
||||||
dateMillis += millis;
|
|
||||||
}
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dateMillis;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
package deckers.thibault.aves.utils;
|
|
||||||
|
|
||||||
public class MimeTypes {
|
|
||||||
public static final String IMAGE = "image";
|
|
||||||
public static final String DNG = "image/x-adobe-dng"; // .dng
|
|
||||||
public static final String GIF = "image/gif";
|
|
||||||
public static final String HEIC = "image/heic";
|
|
||||||
public static final String HEIF = "image/heif";
|
|
||||||
public static final String JPEG = "image/jpeg";
|
|
||||||
public static final String PNG = "image/png";
|
|
||||||
public static final String PSD = "image/x-photoshop"; // .psd
|
|
||||||
public static final String SVG = "image/svg+xml"; // .svg
|
|
||||||
public static final String WEBP = "image/webp";
|
|
||||||
|
|
||||||
public static final String VIDEO = "video";
|
|
||||||
public static final String AVI = "video/avi";
|
|
||||||
public static final String MP2T = "video/mp2t"; // .m2ts
|
|
||||||
public static final String MP4 = "video/mp4";
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
package deckers.thibault.aves.utils;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileDescriptor;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.channels.FileChannel;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class Utils {
|
|
||||||
private static final int logTagMaxLength = 23;
|
|
||||||
private static final Pattern logTagPackagePattern = Pattern.compile("(\\w)(\\w*)\\.");
|
|
||||||
|
|
||||||
public static String createLogTag(Class<?> clazz) {
|
|
||||||
// shorten class name to "a.b.CccDdd"
|
|
||||||
String logTag = logTagPackagePattern.matcher(clazz.getName()).replaceAll("$1.");
|
|
||||||
if (logTag.length() > logTagMaxLength) {
|
|
||||||
// shorten class name to "a.b.CD"
|
|
||||||
String simpleName = clazz.getSimpleName();
|
|
||||||
String shortSimpleName = simpleName.replaceAll("[a-z]", "");
|
|
||||||
logTag = logTag.replace(simpleName, shortSimpleName);
|
|
||||||
if (logTag.length() > logTagMaxLength) {
|
|
||||||
// shorten class name to "CD"
|
|
||||||
logTag = shortSimpleName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return logTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void copyFile(final File source, final FileDescriptor descriptor) throws IOException {
|
|
||||||
try (FileInputStream inStream = new FileInputStream(source); FileOutputStream outStream = new FileOutputStream(descriptor)) {
|
|
||||||
final FileChannel inChannel = inStream.getChannel();
|
|
||||||
final FileChannel outChannel = outStream.getChannel();
|
|
||||||
final long size = inChannel.size();
|
|
||||||
long position = 0;
|
|
||||||
while (position < size) {
|
|
||||||
position += inChannel.transferTo(position, 1024L * 1024L, outChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void copyFile(final File source, final File destination) throws IOException {
|
|
||||||
try (FileInputStream inStream = new FileInputStream(source); FileOutputStream outStream = new FileOutputStream(destination)) {
|
|
||||||
final FileChannel inChannel = inStream.getChannel();
|
|
||||||
final FileChannel outChannel = outStream.getChannel();
|
|
||||||
final long size = inChannel.size();
|
|
||||||
long position = 0;
|
|
||||||
while (position < size) {
|
|
||||||
position += inChannel.transferTo(position, 1024L * 1024L, outChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
package deckers.thibault.aves.utils
|
||||||
|
|
||||||
|
import androidx.exifinterface.media.ExifInterface
|
||||||
|
import java.text.DateFormat
|
||||||
|
import java.text.ParseException
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
object MetadataHelper {
|
||||||
|
// interpret EXIF code to angle (0, 90, 180 or 270 degrees)
|
||||||
|
@JvmStatic
|
||||||
|
fun getOrientationDegreesForExifCode(exifOrientation: Int): Int = when (exifOrientation) {
|
||||||
|
ExifInterface.ORIENTATION_ROTATE_180 -> 180
|
||||||
|
ExifInterface.ORIENTATION_ROTATE_90 -> 90
|
||||||
|
ExifInterface.ORIENTATION_ROTATE_270 -> 270
|
||||||
|
else -> 0 // all other orientations (regular, flipped...) default to an angle of 0 degree
|
||||||
|
}
|
||||||
|
|
||||||
|
// yyyyMMddTHHmmss(.sss)?(Z|+/-hhmm)?
|
||||||
|
@JvmStatic
|
||||||
|
fun parseVideoMetadataDate(metadataDate: String?): Long {
|
||||||
|
var dateString = metadataDate ?: return 0
|
||||||
|
|
||||||
|
// optional sub-second
|
||||||
|
var subSecond: String? = null
|
||||||
|
val subSecondMatcher = Pattern.compile("(\\d{6})(\\.\\d+)").matcher(dateString)
|
||||||
|
if (subSecondMatcher.find()) {
|
||||||
|
subSecond = subSecondMatcher.group(2)?.substring(1)
|
||||||
|
dateString = subSecondMatcher.replaceAll("$1")
|
||||||
|
}
|
||||||
|
|
||||||
|
// optional time zone
|
||||||
|
var timeZone: TimeZone? = null
|
||||||
|
val timeZoneMatcher = Pattern.compile("(Z|[+-]\\d{4})$").matcher(dateString)
|
||||||
|
if (timeZoneMatcher.find()) {
|
||||||
|
timeZone = TimeZone.getTimeZone("GMT" + timeZoneMatcher.group().replace("Z".toRegex(), ""))
|
||||||
|
dateString = timeZoneMatcher.replaceAll("")
|
||||||
|
}
|
||||||
|
|
||||||
|
val date: Date = try {
|
||||||
|
val parser = SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.US)
|
||||||
|
parser.timeZone = timeZone ?: TimeZone.getTimeZone("GMT")
|
||||||
|
parser.parse(dateString)
|
||||||
|
} catch (e: ParseException) {
|
||||||
|
// ignore
|
||||||
|
null
|
||||||
|
} ?: return 0
|
||||||
|
|
||||||
|
var dateMillis = date.time
|
||||||
|
if (subSecond != null) {
|
||||||
|
try {
|
||||||
|
val millis = (".$subSecond".toDouble() * 1000).toInt()
|
||||||
|
if (millis in 0..999) {
|
||||||
|
dateMillis += millis.toLong()
|
||||||
|
}
|
||||||
|
} catch (e: NumberFormatException) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dateMillis
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package deckers.thibault.aves.utils
|
||||||
|
|
||||||
|
object MimeTypes {
|
||||||
|
const val IMAGE = "image"
|
||||||
|
const val DNG = "image/x-adobe-dng" // .dng
|
||||||
|
const val GIF = "image/gif"
|
||||||
|
const val HEIC = "image/heic"
|
||||||
|
const val HEIF = "image/heif"
|
||||||
|
const val JPEG = "image/jpeg"
|
||||||
|
const val PNG = "image/png"
|
||||||
|
const val PSD = "image/x-photoshop" // .psd
|
||||||
|
const val SVG = "image/svg+xml" // .svg
|
||||||
|
const val WEBP = "image/webp"
|
||||||
|
const val VIDEO = "video"
|
||||||
|
const val AVI = "video/avi"
|
||||||
|
const val MP2T = "video/mp2t" // .m2ts
|
||||||
|
const val MP4 = "video/mp4"
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package deckers.thibault.aves.utils
|
||||||
|
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
object Utils {
|
||||||
|
private const val LOG_TAG_MAX_LENGTH = 23
|
||||||
|
private val LOG_TAG_PACKAGE_PATTERN = Pattern.compile("(\\w)(\\w*)\\.")
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun createLogTag(clazz: Class<*>): String {
|
||||||
|
// shorten class name to "a.b.CccDdd"
|
||||||
|
var logTag = LOG_TAG_PACKAGE_PATTERN.matcher(clazz.name).replaceAll("$1.")
|
||||||
|
if (logTag.length > LOG_TAG_MAX_LENGTH) {
|
||||||
|
// shorten class name to "a.b.CD"
|
||||||
|
val simpleName = clazz.simpleName
|
||||||
|
val shortSimpleName = simpleName.replace("[a-z]".toRegex(), "")
|
||||||
|
logTag = logTag.replace(simpleName, shortSimpleName)
|
||||||
|
if (logTag.length > LOG_TAG_MAX_LENGTH) {
|
||||||
|
// shorten class name to "CD"
|
||||||
|
logTag = shortSimpleName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return logTag
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue