kopia lustrzana https://github.com/ryukoposting/Signal-Android
175 wiersze
6.2 KiB
Java
175 wiersze
6.2 KiB
Java
package org.thoughtcrime.securesms.mms;
|
|
|
|
import android.content.Context;
|
|
import android.database.Cursor;
|
|
import android.net.Uri;
|
|
import android.provider.OpenableColumns;
|
|
import android.text.TextUtils;
|
|
import android.util.Pair;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.WorkerThread;
|
|
|
|
import org.signal.core.util.logging.Log;
|
|
import org.thoughtcrime.securesms.blurhash.BlurHash;
|
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
|
|
|
import java.io.IOException;
|
|
|
|
/**
|
|
* SlideFactory encapsulates logic related to constructing slides from a set of paramaeters as defined
|
|
* by {@link SlideFactory#getSlide}.
|
|
*/
|
|
public final class SlideFactory {
|
|
|
|
private static final String TAG = Log.tag(SlideFactory.class);
|
|
|
|
private SlideFactory() {
|
|
}
|
|
|
|
/**
|
|
* Generates a slide from the given parameters.
|
|
*
|
|
* @param context Application context
|
|
* @param contentType The contentType of the given Uri
|
|
* @param uri The Uri pointing to the resource to create a slide out of
|
|
* @param width (Optional) width, can be 0.
|
|
* @param height (Optional) height, can be 0.
|
|
*
|
|
* @return A Slide with all the information we can gather about it.
|
|
*/
|
|
@WorkerThread
|
|
public static @Nullable Slide getSlide(@NonNull Context context, @Nullable String contentType, @NonNull Uri uri, int width, int height) {
|
|
MediaType mediaType = MediaType.from(contentType);
|
|
|
|
try {
|
|
if (PartAuthority.isLocalUri(uri)) {
|
|
return getManuallyCalculatedSlideInfo(context, mediaType, uri, width, height);
|
|
} else {
|
|
Slide result = getContentResolverSlideInfo(context, mediaType, uri, width, height);
|
|
|
|
if (result == null) return getManuallyCalculatedSlideInfo(context, mediaType, uri, width, height);
|
|
else return result;
|
|
}
|
|
} catch (IOException e) {
|
|
Log.w(TAG, e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static @Nullable Slide getContentResolverSlideInfo(@NonNull Context context, @NonNull MediaType mediaType, @NonNull Uri uri, int width, int height) {
|
|
Cursor cursor = null;
|
|
long start = System.currentTimeMillis();
|
|
|
|
try {
|
|
cursor = context.getContentResolver().query(uri, null, null, null, null);
|
|
|
|
if (cursor != null && cursor.moveToFirst()) {
|
|
String fileName = cursor.getString(cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME));
|
|
long fileSize = cursor.getLong(cursor.getColumnIndexOrThrow(OpenableColumns.SIZE));
|
|
String mimeType = context.getContentResolver().getType(uri);
|
|
|
|
if (width == 0 || height == 0) {
|
|
Pair<Integer, Integer> dimens = MediaUtil.getDimensions(context, mimeType, uri);
|
|
width = dimens.first;
|
|
height = dimens.second;
|
|
}
|
|
|
|
Log.d(TAG, "remote slide with size " + fileSize + " took " + (System.currentTimeMillis() - start) + "ms");
|
|
return mediaType.createSlide(context, uri, fileName, mimeType, null, fileSize, width, height);
|
|
}
|
|
} finally {
|
|
if (cursor != null) cursor.close();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static @NonNull Slide getManuallyCalculatedSlideInfo(@NonNull Context context, @NonNull MediaType mediaType, @NonNull Uri uri, int width, int height) throws IOException {
|
|
long start = System.currentTimeMillis();
|
|
Long mediaSize = null;
|
|
String fileName = null;
|
|
String mimeType = null;
|
|
|
|
if (PartAuthority.isLocalUri(uri)) {
|
|
mediaSize = PartAuthority.getAttachmentSize(context, uri);
|
|
fileName = PartAuthority.getAttachmentFileName(context, uri);
|
|
mimeType = PartAuthority.getAttachmentContentType(context, uri);
|
|
}
|
|
|
|
if (mediaSize == null) {
|
|
mediaSize = MediaUtil.getMediaSize(context, uri);
|
|
}
|
|
|
|
if (mimeType == null) {
|
|
mimeType = MediaUtil.getMimeType(context, uri);
|
|
}
|
|
|
|
if (width == 0 || height == 0) {
|
|
Pair<Integer, Integer> dimens = MediaUtil.getDimensions(context, mimeType, uri);
|
|
width = dimens.first;
|
|
height = dimens.second;
|
|
}
|
|
|
|
Log.d(TAG, "local slide with size " + mediaSize + " took " + (System.currentTimeMillis() - start) + "ms");
|
|
return mediaType.createSlide(context, uri, fileName, mimeType, null, mediaSize, width, height);
|
|
}
|
|
|
|
public enum MediaType {
|
|
|
|
IMAGE(MediaUtil.IMAGE_JPEG),
|
|
GIF(MediaUtil.IMAGE_GIF),
|
|
AUDIO(MediaUtil.AUDIO_AAC),
|
|
VIDEO(MediaUtil.VIDEO_MP4),
|
|
DOCUMENT(MediaUtil.UNKNOWN),
|
|
VCARD(MediaUtil.VCARD);
|
|
|
|
private final String fallbackMimeType;
|
|
|
|
MediaType(String fallbackMimeType) {
|
|
this.fallbackMimeType = fallbackMimeType;
|
|
}
|
|
|
|
|
|
public @NonNull Slide createSlide(@NonNull Context context,
|
|
@NonNull Uri uri,
|
|
@Nullable String fileName,
|
|
@Nullable String mimeType,
|
|
@Nullable BlurHash blurHash,
|
|
long dataSize,
|
|
int width,
|
|
int height)
|
|
{
|
|
if (mimeType == null) {
|
|
mimeType = "application/octet-stream";
|
|
}
|
|
|
|
switch (this) {
|
|
case IMAGE: return new ImageSlide(context, uri, dataSize, width, height, blurHash);
|
|
case GIF: return new GifSlide(context, uri, dataSize, width, height);
|
|
case AUDIO: return new AudioSlide(context, uri, dataSize, false);
|
|
case VIDEO: return new VideoSlide(context, uri, dataSize);
|
|
case VCARD:
|
|
case DOCUMENT: return new DocumentSlide(context, uri, mimeType, dataSize, fileName);
|
|
default: throw new AssertionError("unrecognized enum");
|
|
}
|
|
}
|
|
|
|
public static @Nullable MediaType from(final @Nullable String mimeType) {
|
|
if (TextUtils.isEmpty(mimeType)) return null;
|
|
if (MediaUtil.isGif(mimeType)) return GIF;
|
|
if (MediaUtil.isImageType(mimeType)) return IMAGE;
|
|
if (MediaUtil.isAudioType(mimeType)) return AUDIO;
|
|
if (MediaUtil.isVideoType(mimeType)) return VIDEO;
|
|
if (MediaUtil.isVcard(mimeType)) return VCARD;
|
|
|
|
return DOCUMENT;
|
|
}
|
|
|
|
public String toFallbackMimeType() {
|
|
return fallbackMimeType;
|
|
}
|
|
}
|
|
}
|