From 551274f167db2905714b0b76abc97394a2e221f6 Mon Sep 17 00:00:00 2001 From: Jake McGinty Date: Fri, 4 Sep 2015 17:33:22 -0700 Subject: [PATCH] Large attachment support Closes #4019 // FREEBIE --- res/values/strings.xml | 1 + .../securesms/ConversationActivity.java | 108 ++++++++--------- .../securesms/ImageMediaAdapter.java | 2 +- .../securesms/components/ThumbnailView.java | 12 +- .../securesms/database/MmsDatabase.java | 10 +- .../securesms/mms/AttachmentManager.java | 109 +++++++++++++----- .../securesms/mms/AudioSlide.java | 38 +----- .../thoughtcrime/securesms/mms/GifSlide.java | 23 +--- .../securesms/mms/ImageSlide.java | 27 +---- .../securesms/mms/PushMediaConstraints.java | 6 +- src/org/thoughtcrime/securesms/mms/Slide.java | 43 ++++--- .../thoughtcrime/securesms/mms/SlideDeck.java | 4 +- .../securesms/mms/VideoSlide.java | 40 +------ .../securesms/util/MediaUtil.java | 32 ++++- 14 files changed, 209 insertions(+), 246 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 8da04333f6..28220cceae 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -126,6 +126,7 @@ Unblock? Are you sure you want to unblock this contact? Unblock + Attachment exceeds size limits for the type of message you\'re sending. Message details diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java index 3b945074ff..b9026de61e 100644 --- a/src/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationActivity.java @@ -35,6 +35,7 @@ import android.os.Build; import android.os.Bundle; import android.provider.ContactsContract; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.view.WindowCompat; import android.text.Editable; import android.text.TextWatcher; @@ -85,6 +86,7 @@ import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.MmsSmsColumns.Types; import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.mms.AttachmentManager; +import org.thoughtcrime.securesms.mms.AttachmentManager.MediaType; import org.thoughtcrime.securesms.mms.AttachmentTypeSelectorAdapter; import org.thoughtcrime.securesms.mms.MediaConstraints; import org.thoughtcrime.securesms.mms.MediaTooLargeException; @@ -113,6 +115,7 @@ import org.thoughtcrime.securesms.util.DirectoryHelper; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.GroupUtil; +import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; @@ -288,13 +291,16 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity switch (reqCode) { case PICK_IMAGE: - addAttachmentImage(masterSecret, data.getData()); + setMedia(data.getData(), + MediaUtil.isGif(MediaUtil.getMimeType(this, data.getData())) ? MediaType.GIF + : MediaType.IMAGE, + false); break; case PICK_VIDEO: - addAttachmentVideo(data.getData()); + setMedia(data.getData(), MediaType.VIDEO, false); break; case PICK_AUDIO: - addAttachmentAudio(data.getData()); + setMedia(data.getData(), MediaType.AUDIO, false); break; case PICK_CONTACT_INFO: addAttachmentContactInfo(data.getData()); @@ -308,7 +314,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity break; case TAKE_PHOTO: if (attachmentManager.getCaptureUri() != null) { - addAttachmentImage(masterSecret, attachmentManager.getCaptureUri()); + setMedia(attachmentManager.getCaptureUri(), MediaType.IMAGE, true); } break; } @@ -671,9 +677,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity Uri draftVideo = getIntent().getParcelableExtra(DRAFT_VIDEO_EXTRA); if (draftText != null) composeText.setText(draftText); - if (draftImage != null) addAttachmentImage(masterSecret, draftImage); - if (draftAudio != null) addAttachmentAudio(draftAudio); - if (draftVideo != null) addAttachmentVideo(draftVideo); + + if (draftImage != null) setMedia(draftImage, MediaType.IMAGE, false); + else if (draftAudio != null) setMedia(draftAudio, MediaType.AUDIO, false); + else if (draftVideo != null) setMedia(draftVideo, MediaType.VIDEO, false); if (draftText == null && draftImage == null && draftAudio == null && draftVideo == null) { initializeDraftFromDatabase(); @@ -707,11 +714,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity if (draft.getType().equals(Draft.TEXT)) { composeText.setText(draft.getValue()); } else if (draft.getType().equals(Draft.IMAGE)) { - addAttachmentImage(masterSecret, Uri.parse(draft.getValue())); + setMedia(Uri.parse(draft.getValue()), MediaType.IMAGE, false); } else if (draft.getType().equals(Draft.AUDIO)) { - addAttachmentAudio(Uri.parse(draft.getValue())); + setMedia(Uri.parse(draft.getValue()), MediaType.AUDIO, false); } else if (draft.getType().equals(Draft.VIDEO)) { - addAttachmentVideo(Uri.parse(draft.getValue())); + setMedia(Uri.parse(draft.getValue()), MediaType.VIDEO, false); } } @@ -917,55 +924,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } } - private void addAttachmentImage(MasterSecret masterSecret, Uri imageUri) { - try { - attachmentManager.setImage(masterSecret, imageUri); - } catch (IOException | BitmapDecodingException e) { - Log.w(TAG, e); - attachmentManager.clear(); - Toast.makeText(this, R.string.ConversationActivity_sorry_there_was_an_error_setting_your_attachment, - Toast.LENGTH_LONG).show(); - } catch (MediaTooLargeException e) { - attachmentManager.clear(); - Toast.makeText(this, getString(R.string.ConversationActivity_the_gif_you_selected_was_too_big), - Toast.LENGTH_LONG).show(); - Log.w(TAG, e); - } - } - - private void addAttachmentVideo(Uri videoUri) { - try { - attachmentManager.setVideo(videoUri); - } catch (IOException e) { - attachmentManager.clear(); - Toast.makeText(this, R.string.ConversationActivity_sorry_there_was_an_error_setting_your_attachment, - Toast.LENGTH_LONG).show(); - Log.w("ComposeMessageActivity", e); - } catch (MediaTooLargeException e) { - attachmentManager.clear(); - - Toast.makeText(this, getString(R.string.ConversationActivity_sorry_the_selected_video_exceeds_message_size_restrictions, - (MmsMediaConstraints.MAX_MESSAGE_SIZE/1024)), - Toast.LENGTH_LONG).show(); - Log.w("ComposeMessageActivity", e); - } - } - - private void addAttachmentAudio(Uri audioUri) { - try { - attachmentManager.setAudio(audioUri); - } catch (IOException e) { - attachmentManager.clear(); - Toast.makeText(this, R.string.ConversationActivity_sorry_there_was_an_error_setting_your_attachment, - Toast.LENGTH_LONG).show(); - Log.w("ComposeMessageActivity", e); - } catch (MediaTooLargeException e) { - attachmentManager.clear(); - Toast.makeText(this, getString(R.string.ConversationActivity_sorry_the_selected_audio_exceeds_message_size_restrictions, - (MmsMediaConstraints.MAX_MESSAGE_SIZE/1024)), - Toast.LENGTH_LONG).show(); - Log.w("ComposeMessageActivity", e); - } + private void setMedia(Uri uri, MediaType mediaType, boolean isCapture) { + attachmentManager.setMedia(masterSecret, uri, mediaType, getCurrentMediaConstraints(), isCapture); } private void addAttachmentContactInfo(Uri contactUri) { @@ -1132,6 +1092,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity return rawText; } + private MediaConstraints getCurrentMediaConstraints() { + return sendButton.getSelectedTransport().getType() == Type.TEXTSECURE + ? MediaConstraints.PUSH_CONSTRAINTS + : MediaConstraints.MMS_CONSTRAINTS; + } + private void markThreadAsRead() { new AsyncTask() { @Override @@ -1198,8 +1164,24 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity final Context context = getApplicationContext(); SlideDeck slideDeck; - if (attachmentManager.isAttachmentPresent()) slideDeck = new SlideDeck(attachmentManager.getSlideDeck()); - else slideDeck = new SlideDeck(); + if (attachmentManager.isAttachmentPresent()) { + Slide mediaSlide = attachmentManager.getSlideDeck().getThumbnailSlide(); + MediaConstraints constraints = getCurrentMediaConstraints(); + + if (mediaSlide != null && + !constraints.isSatisfied(this, masterSecret, mediaSlide.getPart()) && + !constraints.canResize(mediaSlide.getPart())) + { + Toast.makeText(context, + R.string.ConversationActivity_attachment_exceeds_size_limits, + Toast.LENGTH_SHORT).show(); + return; + } + + slideDeck = new SlideDeck(attachmentManager.getSlideDeck()); + } else { + slideDeck = new SlideDeck(); + } OutgoingMediaMessage outgoingMessage = new OutgoingMediaMessage(this, recipients, slideDeck, getMessage(), distributionType); @@ -1272,8 +1254,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity @Override public void onImageCapture(@NonNull final byte[] imageBytes) { - attachmentManager.setCaptureUri(CaptureProvider.getInstance(this).create(masterSecret, recipients, imageBytes)); - addAttachmentImage(masterSecret, attachmentManager.getCaptureUri()); + setMedia(CaptureProvider.getInstance(this).create(masterSecret, recipients, imageBytes), MediaType.IMAGE, true); quickAttachmentDrawer.hide(false); } @@ -1397,4 +1378,5 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity initializeSecurity(); updateToggleButtonState(); } + } diff --git a/src/org/thoughtcrime/securesms/ImageMediaAdapter.java b/src/org/thoughtcrime/securesms/ImageMediaAdapter.java index 200fe28a86..6691399db0 100644 --- a/src/org/thoughtcrime/securesms/ImageMediaAdapter.java +++ b/src/org/thoughtcrime/securesms/ImageMediaAdapter.java @@ -74,7 +74,7 @@ public class ImageMediaAdapter extends CursorRecyclerViewAdapter { part.setContentType(imageRecord.getContentType().getBytes()); part.setPartId(imageRecord.getPartId()); - Slide slide = MediaUtil.getSlideForPart(getContext(), masterSecret, part, imageRecord.getContentType()); + Slide slide = MediaUtil.getSlideForPart(getContext(), part, imageRecord.getContentType()); if (slide != null) { imageView.setImageResource(slide, masterSecret); } diff --git a/src/org/thoughtcrime/securesms/components/ThumbnailView.java b/src/org/thoughtcrime/securesms/components/ThumbnailView.java index 8d37cff54d..2ad29342ce 100644 --- a/src/org/thoughtcrime/securesms/components/ThumbnailView.java +++ b/src/org/thoughtcrime/securesms/components/ThumbnailView.java @@ -201,7 +201,12 @@ public class ThumbnailView extends FrameLayout { } public void clear() { - if (isContextValid()) Glide.clear(this); + if (isContextValid()) Glide.clear(image); + if (slideDeckFuture != null) slideDeckFuture.removeListener(slideDeckListener); + slide = null; + slideId = null; + slideDeckFuture = null; + slideDeckListener = null; } public void hideControls(boolean hideControls) { @@ -209,6 +214,11 @@ public class ThumbnailView extends FrameLayout { if (hideControls) hideProgressWheel(); } + public void showProgressSpinner() { + getProgressWheel().spin(); + getProgressWheel().setVisibility(VISIBLE); + } + @TargetApi(VERSION_CODES.JELLY_BEAN_MR1) private boolean isContextValid() { return !(getContext() instanceof Activity) || diff --git a/src/org/thoughtcrime/securesms/database/MmsDatabase.java b/src/org/thoughtcrime/securesms/database/MmsDatabase.java index c479b3e52a..a85c2aa703 100644 --- a/src/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/src/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -1094,7 +1094,7 @@ public class MmsDatabase extends MessagingDatabase { List mismatches = getMismatchedIdentities(mismatchDocument); List networkFailures = getFailures(networkDocument); - ListenableFutureTask slideDeck = getSlideDeck(masterSecret, dateReceived, id); + ListenableFutureTask slideDeck = getSlideDeck(dateReceived, id); return new MediaMmsMessageRecord(context, id, recipients, recipients.getPrimaryRecipient(), addressDeviceId, dateSent, dateReceived, receiptCount, @@ -1159,8 +1159,7 @@ public class MmsDatabase extends MessagingDatabase { } } - private ListenableFutureTask getSlideDeck(final MasterSecret masterSecret, - final long timestamp, + private ListenableFutureTask getSlideDeck(final long timestamp, final long id) { ListenableFutureTask future = getCachedSlideDeck(timestamp, id); @@ -1172,12 +1171,9 @@ public class MmsDatabase extends MessagingDatabase { Callable task = new Callable() { @Override public SlideDeck call() throws Exception { - if (masterSecret == null) - return null; - PartDatabase partDatabase = DatabaseFactory.getPartDatabase(context); PduBody body = getPartsAsBody(partDatabase.getParts(id)); - SlideDeck slideDeck = new SlideDeck(context, masterSecret, body); + SlideDeck slideDeck = new SlideDeck(context, body); if (!body.containsPushInProgress()) { slideCache.put(timestamp + "::" + id, new SoftReference<>(slideDeck)); diff --git a/src/org/thoughtcrime/securesms/mms/AttachmentManager.java b/src/org/thoughtcrime/securesms/mms/AttachmentManager.java index bb0168b911..e401918a55 100644 --- a/src/org/thoughtcrime/securesms/mms/AttachmentManager.java +++ b/src/org/thoughtcrime/securesms/mms/AttachmentManager.java @@ -21,9 +21,11 @@ import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.AsyncTask; import android.os.Build; import android.provider.ContactsContract; import android.provider.MediaStore; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.Log; import android.view.View; @@ -36,7 +38,6 @@ import org.thoughtcrime.securesms.components.ThumbnailView; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.providers.CaptureProvider; import org.thoughtcrime.securesms.recipients.Recipients; -import org.thoughtcrime.securesms.util.BitmapDecodingException; import org.thoughtcrime.securesms.util.MediaUtil; import java.io.IOException; @@ -54,7 +55,7 @@ public class AttachmentManager { public AttachmentManager(Activity view, AttachmentListener listener) { this.attachmentView = view.findViewById(R.id.attachment_editor); - this.thumbnail = (ThumbnailView)view.findViewById(R.id.attachment_thumbnail); + this.thumbnail = (ThumbnailView) view.findViewById(R.id.attachment_thumbnail); this.slideDeck = new SlideDeck(); this.context = view; this.attachmentListener = listener; @@ -70,6 +71,7 @@ public class AttachmentManager { @Override public void onAnimationRepeat(Animation animation) {} @Override public void onAnimationEnd(Animation animation) { slideDeck.clear(); + thumbnail.clear(); attachmentView.setVisibility(View.GONE); attachmentListener.onAttachmentChanged(); } @@ -83,34 +85,55 @@ public class AttachmentManager { captureUri = null; } - public void setImage(MasterSecret masterSecret, Uri image) - throws IOException, BitmapDecodingException, MediaTooLargeException + public void setMedia(@NonNull final MasterSecret masterSecret, + @NonNull final Uri uri, + @NonNull final MediaType mediaType, + @NonNull final MediaConstraints constraints, + final boolean isCapture) { - if (MediaUtil.isGif(MediaUtil.getMimeType(context, image))) { - setMedia(new GifSlide(context, masterSecret, image), masterSecret); - } else { - setMedia(new ImageSlide(context, masterSecret, image), masterSecret); - } - } - - public void setVideo(Uri video) throws IOException, MediaTooLargeException { - setMedia(new VideoSlide(context, video)); - } + new AsyncTask() { + @Override protected void onPreExecute() { + slideDeck.clear(); + thumbnail.clear(); + thumbnail.showProgressSpinner(); + attachmentView.setVisibility(View.VISIBLE); - public void setAudio(Uri audio) throws IOException, MediaTooLargeException { - setMedia(new AudioSlide(context, audio)); - } + if (isCapture) captureUri = uri; + if (!uri.equals(captureUri)) cleanup(); + } - public void setMedia(final Slide slide) { - setMedia(slide, null); - } + @Override protected @Nullable Slide doInBackground(Void... params) { + long start = System.currentTimeMillis(); + try { + final long mediaSize = MediaUtil.getMediaSize(context, masterSecret, uri); + final Slide slide = mediaType.createSlide(context, uri, mediaSize); + Log.w(TAG, "slide with size " + mediaSize + " took " + (System.currentTimeMillis() - start) + "ms"); + return slide; + } catch (IOException ioe) { + Log.w(TAG, ioe); + return null; + } + } - public void setMedia(final Slide slide, @Nullable MasterSecret masterSecret) { - slideDeck.clear(); - slideDeck.addSlide(slide); - attachmentView.setVisibility(View.VISIBLE); - thumbnail.setImageResource(slide, masterSecret); - attachmentListener.onAttachmentChanged(); + @Override protected void onPostExecute(@Nullable final Slide slide) { + if (slide == null) { + attachmentView.setVisibility(View.GONE); + Toast.makeText(context, + R.string.ConversationActivity_sorry_there_was_an_error_setting_your_attachment, + Toast.LENGTH_SHORT).show(); + } else if (!areConstraintsSatisfied(context, masterSecret, slide, constraints)) { + attachmentView.setVisibility(View.GONE); + Toast.makeText(context, + R.string.ConversationActivity_attachment_exceeds_size_limits, + Toast.LENGTH_SHORT).show(); + } else { + slideDeck.addSlide(slide); + attachmentView.setVisibility(View.VISIBLE); + thumbnail.setImageResource(slide, masterSecret); + attachmentListener.onAttachmentChanged(); + } + } + }.execute(); } public boolean isAttachmentPresent() { @@ -118,7 +141,7 @@ public class AttachmentManager { } - public SlideDeck getSlideDeck() { + public @NonNull SlideDeck getSlideDeck() { return slideDeck; } @@ -143,10 +166,6 @@ public class AttachmentManager { return captureUri; } - public void setCaptureUri(Uri captureUri) { - this.captureUri = captureUri; - } - public void capturePhoto(Activity activity, Recipients recipients, int requestCode) { try { Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); @@ -183,6 +202,16 @@ public class AttachmentManager { } } + private boolean areConstraintsSatisfied(final @NonNull Context context, + final @NonNull MasterSecret masterSecret, + final @Nullable Slide slide, + final @NonNull MediaConstraints constraints) + { + return slide == null || + constraints.isSatisfied(context, masterSecret, slide.getPart()) || + constraints.canResize(slide.getPart()); + } + private class RemoveButtonListener implements View.OnClickListener { @Override public void onClick(View v) { @@ -194,4 +223,22 @@ public class AttachmentManager { public interface AttachmentListener { void onAttachmentChanged(); } + + public enum MediaType { + IMAGE, GIF, AUDIO, VIDEO; + + public @NonNull Slide createSlide(@NonNull Context context, + @NonNull Uri uri, + long dataSize) + throws IOException + { + switch (this) { + case IMAGE: return new ImageSlide(context, uri, dataSize); + case GIF: return new GifSlide(context, uri, dataSize); + case AUDIO: return new AudioSlide(context, uri, dataSize); + case VIDEO: return new VideoSlide(context, uri, dataSize); + default: throw new AssertionError("unrecognized enum"); + } + } + } } diff --git a/src/org/thoughtcrime/securesms/mms/AudioSlide.java b/src/org/thoughtcrime/securesms/mms/AudioSlide.java index 68bc123bc2..78948e65c2 100644 --- a/src/org/thoughtcrime/securesms/mms/AudioSlide.java +++ b/src/org/thoughtcrime/securesms/mms/AudioSlide.java @@ -18,27 +18,25 @@ package org.thoughtcrime.securesms.mms; import android.content.Context; import android.content.res.Resources.Theme; -import android.database.Cursor; import android.net.Uri; -import android.provider.MediaStore.Audio; import android.support.annotation.DrawableRes; import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.util.ResUtil; import java.io.IOException; +import ws.com.google.android.mms.ContentType; import ws.com.google.android.mms.pdu.PduPart; public class AudioSlide extends Slide { - public AudioSlide(Context context, Uri uri) throws IOException, MediaTooLargeException { - super(context, constructPartFromUri(context, uri)); + public AudioSlide(Context context, Uri uri, long dataSize) throws IOException { + super(context, constructPartFromUri(context, uri, ContentType.AUDIO_UNSPECIFIED, dataSize)); } - public AudioSlide(Context context, MasterSecret masterSecret, PduPart part) { - super(context, masterSecret, part); + public AudioSlide(Context context, PduPart part) { + super(context, part); } @Override @@ -55,30 +53,4 @@ public class AudioSlide extends Slide { public @DrawableRes int getPlaceholderRes(Theme theme) { return ResUtil.getDrawableRes(theme, R.attr.conversation_icon_attach_audio); } - - public static PduPart constructPartFromUri(Context context, Uri uri) throws IOException, MediaTooLargeException { - PduPart part = new PduPart(); - - assertMediaSize(context, uri, MmsMediaConstraints.MAX_MESSAGE_SIZE); - - Cursor cursor = null; - - try { - cursor = context.getContentResolver().query(uri, new String[]{Audio.Media.MIME_TYPE}, null, null, null); - - if (cursor != null && cursor.moveToFirst()) - part.setContentType(cursor.getString(0).getBytes()); - else - throw new IOException("Unable to query content type."); - } finally { - if (cursor != null) - cursor.close(); - } - - part.setDataUri(uri); - part.setContentId((System.currentTimeMillis()+"").getBytes()); - part.setName(("Audio" + System.currentTimeMillis()).getBytes()); - - return part; - } } diff --git a/src/org/thoughtcrime/securesms/mms/GifSlide.java b/src/org/thoughtcrime/securesms/mms/GifSlide.java index 4c87c25742..9fcbb65e86 100644 --- a/src/org/thoughtcrime/securesms/mms/GifSlide.java +++ b/src/org/thoughtcrime/securesms/mms/GifSlide.java @@ -2,33 +2,18 @@ package org.thoughtcrime.securesms.mms; import android.content.Context; import android.net.Uri; -import android.provider.MediaStore.Audio.Media; - -import org.thoughtcrime.securesms.crypto.MasterSecret; -import org.thoughtcrime.securesms.util.BitmapDecodingException; import java.io.IOException; import ws.com.google.android.mms.pdu.PduPart; public class GifSlide extends ImageSlide { - public GifSlide(Context context, MasterSecret masterSecret, PduPart part) { - super(context, masterSecret, part); - } - - public GifSlide(Context context, MasterSecret masterSecret, Uri uri) - throws IOException, BitmapDecodingException, MediaTooLargeException - { - super(context, masterSecret, uri); - assertMediaSize(); + public GifSlide(Context context, PduPart part) { + super(context, part); } - private void assertMediaSize() throws MediaTooLargeException, IOException { - // TODO move assertion outside of slides and take available transport options into account - assertMediaSize(context, getPart().getDataUri(), MediaConstraints.PUSH_CONSTRAINTS.getGifMaxSize()); - if (!MediaConstraints.PUSH_CONSTRAINTS.isSatisfied(context, masterSecret, part)) { - throw new MediaTooLargeException("Media exceeds maximum message size."); - } + public GifSlide(Context context, Uri uri, long dataSize) throws IOException { + super(context, uri, dataSize); } @Override public Uri getThumbnailUri() { diff --git a/src/org/thoughtcrime/securesms/mms/ImageSlide.java b/src/org/thoughtcrime/securesms/mms/ImageSlide.java index 95fea0352d..5720a53074 100644 --- a/src/org/thoughtcrime/securesms/mms/ImageSlide.java +++ b/src/org/thoughtcrime/securesms/mms/ImageSlide.java @@ -22,9 +22,6 @@ import android.net.Uri; import android.support.annotation.DrawableRes; import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.crypto.MasterSecret; -import org.thoughtcrime.securesms.util.BitmapDecodingException; -import org.thoughtcrime.securesms.util.MediaUtil; import java.io.IOException; @@ -34,12 +31,12 @@ import ws.com.google.android.mms.pdu.PduPart; public class ImageSlide extends Slide { private static final String TAG = ImageSlide.class.getSimpleName(); - public ImageSlide(Context context, MasterSecret masterSecret, PduPart part) { - super(context, masterSecret, part); + public ImageSlide(Context context, PduPart part) { + super(context, part); } - public ImageSlide(Context context, MasterSecret masterSecret, Uri uri) throws IOException, BitmapDecodingException { - super(context, masterSecret, constructPartFromUri(context, uri)); + public ImageSlide(Context context, Uri uri, long size) throws IOException { + super(context, constructPartFromUri(context, uri, ContentType.IMAGE_JPEG, size)); } @Override @@ -62,20 +59,4 @@ public class ImageSlide extends Slide { public boolean hasImage() { return true; } - - private static PduPart constructPartFromUri(Context context, Uri uri) - throws IOException, BitmapDecodingException - { - PduPart part = new PduPart(); - - final String mimeType = MediaUtil.getMimeType(context, uri); - - part.setDataUri(uri); - part.setContentType((mimeType != null ? mimeType : ContentType.IMAGE_JPEG).getBytes()); - part.setContentId((System.currentTimeMillis()+"").getBytes()); - part.setName(("Image" + System.currentTimeMillis()).getBytes()); - - return part; - } - } diff --git a/src/org/thoughtcrime/securesms/mms/PushMediaConstraints.java b/src/org/thoughtcrime/securesms/mms/PushMediaConstraints.java index f59ece7865..d505ebe6e8 100644 --- a/src/org/thoughtcrime/securesms/mms/PushMediaConstraints.java +++ b/src/org/thoughtcrime/securesms/mms/PushMediaConstraints.java @@ -27,16 +27,16 @@ public class PushMediaConstraints extends MediaConstraints { @Override public int getGifMaxSize() { - return 1 * MB; + return 5 * MB; } @Override public int getVideoMaxSize() { - return MmsMediaConstraints.MAX_MESSAGE_SIZE; + return 100 * MB; } @Override public int getAudioMaxSize() { - return MmsMediaConstraints.MAX_MESSAGE_SIZE; + return 100 * MB; } } diff --git a/src/org/thoughtcrime/securesms/mms/Slide.java b/src/org/thoughtcrime/securesms/mms/Slide.java index 7f52885292..60e925576d 100644 --- a/src/org/thoughtcrime/securesms/mms/Slide.java +++ b/src/org/thoughtcrime/securesms/mms/Slide.java @@ -21,8 +21,10 @@ import android.content.res.Resources.Theme; import android.net.Uri; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import org.thoughtcrime.securesms.crypto.MasterSecret; +import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.Util; import java.io.IOException; @@ -32,20 +34,14 @@ import ws.com.google.android.mms.pdu.PduPart; public abstract class Slide { - protected final PduPart part; - protected final Context context; - protected MasterSecret masterSecret; + protected final PduPart part; + protected final Context context; public Slide(Context context, @NonNull PduPart part) { this.part = part; this.context = context; } - public Slide(Context context, @NonNull MasterSecret masterSecret, @NonNull PduPart part) { - this(context, part); - this.masterSecret = masterSecret; - } - public String getContentType() { return new String(part.getContentType()); } @@ -90,18 +86,24 @@ public abstract class Slide { return !getPart().getPartId().isValid(); } - protected static void assertMediaSize(Context context, Uri uri, long max) - throws MediaTooLargeException, IOException + + protected static PduPart constructPartFromUri(@NonNull Context context, + @NonNull Uri uri, + @NonNull String defaultMime, + long dataSize) + throws IOException { - InputStream in = context.getContentResolver().openInputStream(uri); - long size = 0; - byte[] buffer = new byte[512]; - int read; - - while ((read = in.read(buffer)) != -1) { - size += read; - if (size > max) throw new MediaTooLargeException("Media exceeds maximum message size."); - } + final PduPart part = new PduPart(); + final String mimeType = MediaUtil.getMimeType(context, uri); + final String derivedMimeType = mimeType != null ? mimeType : defaultMime; + + part.setDataSize(dataSize); + part.setDataUri(uri); + part.setContentType(derivedMimeType.getBytes()); + part.setContentId((System.currentTimeMillis()+"").getBytes()); + part.setName((MediaUtil.getDiscreteMimeType(derivedMimeType) + System.currentTimeMillis()).getBytes()); + + return part; } @Override @@ -125,7 +127,4 @@ public abstract class Slide { return Util.hashCode(getContentType(), hasAudio(), hasImage(), hasVideo(), isDraft(), getUri(), getThumbnailUri(), getTransferProgress()); } - - - } diff --git a/src/org/thoughtcrime/securesms/mms/SlideDeck.java b/src/org/thoughtcrime/securesms/mms/SlideDeck.java index 794b63b895..66afee40be 100644 --- a/src/org/thoughtcrime/securesms/mms/SlideDeck.java +++ b/src/org/thoughtcrime/securesms/mms/SlideDeck.java @@ -47,10 +47,10 @@ public class SlideDeck { this.slides.addAll(copy.getSlides()); } - public SlideDeck(Context context, MasterSecret masterSecret, PduBody body) { + public SlideDeck(Context context, PduBody body) { for (int i=0;i 1 ? sections[0] : null; }