mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 12:05:22 +00:00
parent
4f7ac59c6f
commit
551274f167
@ -126,6 +126,7 @@
|
|||||||
<string name="ConversationActivity_unblock_question">Unblock?</string>
|
<string name="ConversationActivity_unblock_question">Unblock?</string>
|
||||||
<string name="ConversationActivity_are_you_sure_you_want_to_unblock_this_contact">Are you sure you want to unblock this contact?</string>
|
<string name="ConversationActivity_are_you_sure_you_want_to_unblock_this_contact">Are you sure you want to unblock this contact?</string>
|
||||||
<string name="ConversationActivity_unblock">Unblock</string>
|
<string name="ConversationActivity_unblock">Unblock</string>
|
||||||
|
<string name="ConversationActivity_attachment_exceeds_size_limits">Attachment exceeds size limits for the type of message you\'re sending.</string>
|
||||||
|
|
||||||
<!-- ConversationFragment -->
|
<!-- ConversationFragment -->
|
||||||
<string name="ConversationFragment_message_details">Message details</string>
|
<string name="ConversationFragment_message_details">Message details</string>
|
||||||
|
@ -35,6 +35,7 @@ import android.os.Build;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.view.WindowCompat;
|
import android.support.v4.view.WindowCompat;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
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.MmsSmsColumns.Types;
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.mms.AttachmentManager;
|
import org.thoughtcrime.securesms.mms.AttachmentManager;
|
||||||
|
import org.thoughtcrime.securesms.mms.AttachmentManager.MediaType;
|
||||||
import org.thoughtcrime.securesms.mms.AttachmentTypeSelectorAdapter;
|
import org.thoughtcrime.securesms.mms.AttachmentTypeSelectorAdapter;
|
||||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
||||||
import org.thoughtcrime.securesms.mms.MediaTooLargeException;
|
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.DynamicLanguage;
|
||||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||||
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
|
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
|
||||||
@ -288,13 +291,16 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
switch (reqCode) {
|
switch (reqCode) {
|
||||||
case PICK_IMAGE:
|
case PICK_IMAGE:
|
||||||
addAttachmentImage(masterSecret, data.getData());
|
setMedia(data.getData(),
|
||||||
|
MediaUtil.isGif(MediaUtil.getMimeType(this, data.getData())) ? MediaType.GIF
|
||||||
|
: MediaType.IMAGE,
|
||||||
|
false);
|
||||||
break;
|
break;
|
||||||
case PICK_VIDEO:
|
case PICK_VIDEO:
|
||||||
addAttachmentVideo(data.getData());
|
setMedia(data.getData(), MediaType.VIDEO, false);
|
||||||
break;
|
break;
|
||||||
case PICK_AUDIO:
|
case PICK_AUDIO:
|
||||||
addAttachmentAudio(data.getData());
|
setMedia(data.getData(), MediaType.AUDIO, false);
|
||||||
break;
|
break;
|
||||||
case PICK_CONTACT_INFO:
|
case PICK_CONTACT_INFO:
|
||||||
addAttachmentContactInfo(data.getData());
|
addAttachmentContactInfo(data.getData());
|
||||||
@ -308,7 +314,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
break;
|
break;
|
||||||
case TAKE_PHOTO:
|
case TAKE_PHOTO:
|
||||||
if (attachmentManager.getCaptureUri() != null) {
|
if (attachmentManager.getCaptureUri() != null) {
|
||||||
addAttachmentImage(masterSecret, attachmentManager.getCaptureUri());
|
setMedia(attachmentManager.getCaptureUri(), MediaType.IMAGE, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -671,9 +677,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
Uri draftVideo = getIntent().getParcelableExtra(DRAFT_VIDEO_EXTRA);
|
Uri draftVideo = getIntent().getParcelableExtra(DRAFT_VIDEO_EXTRA);
|
||||||
|
|
||||||
if (draftText != null) composeText.setText(draftText);
|
if (draftText != null) composeText.setText(draftText);
|
||||||
if (draftImage != null) addAttachmentImage(masterSecret, draftImage);
|
|
||||||
if (draftAudio != null) addAttachmentAudio(draftAudio);
|
if (draftImage != null) setMedia(draftImage, MediaType.IMAGE, false);
|
||||||
if (draftVideo != null) addAttachmentVideo(draftVideo);
|
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) {
|
if (draftText == null && draftImage == null && draftAudio == null && draftVideo == null) {
|
||||||
initializeDraftFromDatabase();
|
initializeDraftFromDatabase();
|
||||||
@ -707,11 +714,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
if (draft.getType().equals(Draft.TEXT)) {
|
if (draft.getType().equals(Draft.TEXT)) {
|
||||||
composeText.setText(draft.getValue());
|
composeText.setText(draft.getValue());
|
||||||
} else if (draft.getType().equals(Draft.IMAGE)) {
|
} 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)) {
|
} 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)) {
|
} 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) {
|
private void setMedia(Uri uri, MediaType mediaType, boolean isCapture) {
|
||||||
try {
|
attachmentManager.setMedia(masterSecret, uri, mediaType, getCurrentMediaConstraints(), isCapture);
|
||||||
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 addAttachmentContactInfo(Uri contactUri) {
|
private void addAttachmentContactInfo(Uri contactUri) {
|
||||||
@ -1132,6 +1092,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
return rawText;
|
return rawText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MediaConstraints getCurrentMediaConstraints() {
|
||||||
|
return sendButton.getSelectedTransport().getType() == Type.TEXTSECURE
|
||||||
|
? MediaConstraints.PUSH_CONSTRAINTS
|
||||||
|
: MediaConstraints.MMS_CONSTRAINTS;
|
||||||
|
}
|
||||||
|
|
||||||
private void markThreadAsRead() {
|
private void markThreadAsRead() {
|
||||||
new AsyncTask<Long, Void, Void>() {
|
new AsyncTask<Long, Void, Void>() {
|
||||||
@Override
|
@Override
|
||||||
@ -1198,8 +1164,24 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
final Context context = getApplicationContext();
|
final Context context = getApplicationContext();
|
||||||
SlideDeck slideDeck;
|
SlideDeck slideDeck;
|
||||||
|
|
||||||
if (attachmentManager.isAttachmentPresent()) slideDeck = new SlideDeck(attachmentManager.getSlideDeck());
|
if (attachmentManager.isAttachmentPresent()) {
|
||||||
else slideDeck = new SlideDeck();
|
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,
|
OutgoingMediaMessage outgoingMessage = new OutgoingMediaMessage(this, recipients, slideDeck,
|
||||||
getMessage(), distributionType);
|
getMessage(), distributionType);
|
||||||
@ -1272,8 +1254,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onImageCapture(@NonNull final byte[] imageBytes) {
|
public void onImageCapture(@NonNull final byte[] imageBytes) {
|
||||||
attachmentManager.setCaptureUri(CaptureProvider.getInstance(this).create(masterSecret, recipients, imageBytes));
|
setMedia(CaptureProvider.getInstance(this).create(masterSecret, recipients, imageBytes), MediaType.IMAGE, true);
|
||||||
addAttachmentImage(masterSecret, attachmentManager.getCaptureUri());
|
|
||||||
quickAttachmentDrawer.hide(false);
|
quickAttachmentDrawer.hide(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1397,4 +1378,5 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
initializeSecurity();
|
initializeSecurity();
|
||||||
updateToggleButtonState();
|
updateToggleButtonState();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ public class ImageMediaAdapter extends CursorRecyclerViewAdapter<ViewHolder> {
|
|||||||
part.setContentType(imageRecord.getContentType().getBytes());
|
part.setContentType(imageRecord.getContentType().getBytes());
|
||||||
part.setPartId(imageRecord.getPartId());
|
part.setPartId(imageRecord.getPartId());
|
||||||
|
|
||||||
Slide slide = MediaUtil.getSlideForPart(getContext(), masterSecret, part, imageRecord.getContentType());
|
Slide slide = MediaUtil.getSlideForPart(getContext(), part, imageRecord.getContentType());
|
||||||
if (slide != null) {
|
if (slide != null) {
|
||||||
imageView.setImageResource(slide, masterSecret);
|
imageView.setImageResource(slide, masterSecret);
|
||||||
}
|
}
|
||||||
|
@ -201,7 +201,12 @@ public class ThumbnailView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
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) {
|
public void hideControls(boolean hideControls) {
|
||||||
@ -209,6 +214,11 @@ public class ThumbnailView extends FrameLayout {
|
|||||||
if (hideControls) hideProgressWheel();
|
if (hideControls) hideProgressWheel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showProgressSpinner() {
|
||||||
|
getProgressWheel().spin();
|
||||||
|
getProgressWheel().setVisibility(VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
@TargetApi(VERSION_CODES.JELLY_BEAN_MR1)
|
@TargetApi(VERSION_CODES.JELLY_BEAN_MR1)
|
||||||
private boolean isContextValid() {
|
private boolean isContextValid() {
|
||||||
return !(getContext() instanceof Activity) ||
|
return !(getContext() instanceof Activity) ||
|
||||||
|
@ -1094,7 +1094,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
List<IdentityKeyMismatch> mismatches = getMismatchedIdentities(mismatchDocument);
|
List<IdentityKeyMismatch> mismatches = getMismatchedIdentities(mismatchDocument);
|
||||||
List<NetworkFailure> networkFailures = getFailures(networkDocument);
|
List<NetworkFailure> networkFailures = getFailures(networkDocument);
|
||||||
|
|
||||||
ListenableFutureTask<SlideDeck> slideDeck = getSlideDeck(masterSecret, dateReceived, id);
|
ListenableFutureTask<SlideDeck> slideDeck = getSlideDeck(dateReceived, id);
|
||||||
|
|
||||||
return new MediaMmsMessageRecord(context, id, recipients, recipients.getPrimaryRecipient(),
|
return new MediaMmsMessageRecord(context, id, recipients, recipients.getPrimaryRecipient(),
|
||||||
addressDeviceId, dateSent, dateReceived, receiptCount,
|
addressDeviceId, dateSent, dateReceived, receiptCount,
|
||||||
@ -1159,8 +1159,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ListenableFutureTask<SlideDeck> getSlideDeck(final MasterSecret masterSecret,
|
private ListenableFutureTask<SlideDeck> getSlideDeck(final long timestamp,
|
||||||
final long timestamp,
|
|
||||||
final long id)
|
final long id)
|
||||||
{
|
{
|
||||||
ListenableFutureTask<SlideDeck> future = getCachedSlideDeck(timestamp, id);
|
ListenableFutureTask<SlideDeck> future = getCachedSlideDeck(timestamp, id);
|
||||||
@ -1172,12 +1171,9 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
Callable<SlideDeck> task = new Callable<SlideDeck>() {
|
Callable<SlideDeck> task = new Callable<SlideDeck>() {
|
||||||
@Override
|
@Override
|
||||||
public SlideDeck call() throws Exception {
|
public SlideDeck call() throws Exception {
|
||||||
if (masterSecret == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
PartDatabase partDatabase = DatabaseFactory.getPartDatabase(context);
|
PartDatabase partDatabase = DatabaseFactory.getPartDatabase(context);
|
||||||
PduBody body = getPartsAsBody(partDatabase.getParts(id));
|
PduBody body = getPartsAsBody(partDatabase.getParts(id));
|
||||||
SlideDeck slideDeck = new SlideDeck(context, masterSecret, body);
|
SlideDeck slideDeck = new SlideDeck(context, body);
|
||||||
|
|
||||||
if (!body.containsPushInProgress()) {
|
if (!body.containsPushInProgress()) {
|
||||||
slideCache.put(timestamp + "::" + id, new SoftReference<>(slideDeck));
|
slideCache.put(timestamp + "::" + id, new SoftReference<>(slideDeck));
|
||||||
|
@ -21,9 +21,11 @@ import android.content.ActivityNotFoundException;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -36,7 +38,6 @@ import org.thoughtcrime.securesms.components.ThumbnailView;
|
|||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.providers.CaptureProvider;
|
import org.thoughtcrime.securesms.providers.CaptureProvider;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -54,7 +55,7 @@ public class AttachmentManager {
|
|||||||
|
|
||||||
public AttachmentManager(Activity view, AttachmentListener listener) {
|
public AttachmentManager(Activity view, AttachmentListener listener) {
|
||||||
this.attachmentView = view.findViewById(R.id.attachment_editor);
|
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.slideDeck = new SlideDeck();
|
||||||
this.context = view;
|
this.context = view;
|
||||||
this.attachmentListener = listener;
|
this.attachmentListener = listener;
|
||||||
@ -70,6 +71,7 @@ public class AttachmentManager {
|
|||||||
@Override public void onAnimationRepeat(Animation animation) {}
|
@Override public void onAnimationRepeat(Animation animation) {}
|
||||||
@Override public void onAnimationEnd(Animation animation) {
|
@Override public void onAnimationEnd(Animation animation) {
|
||||||
slideDeck.clear();
|
slideDeck.clear();
|
||||||
|
thumbnail.clear();
|
||||||
attachmentView.setVisibility(View.GONE);
|
attachmentView.setVisibility(View.GONE);
|
||||||
attachmentListener.onAttachmentChanged();
|
attachmentListener.onAttachmentChanged();
|
||||||
}
|
}
|
||||||
@ -83,34 +85,55 @@ public class AttachmentManager {
|
|||||||
captureUri = null;
|
captureUri = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setImage(MasterSecret masterSecret, Uri image)
|
public void setMedia(@NonNull final MasterSecret masterSecret,
|
||||||
throws IOException, BitmapDecodingException, MediaTooLargeException
|
@NonNull final Uri uri,
|
||||||
|
@NonNull final MediaType mediaType,
|
||||||
|
@NonNull final MediaConstraints constraints,
|
||||||
|
final boolean isCapture)
|
||||||
{
|
{
|
||||||
if (MediaUtil.isGif(MediaUtil.getMimeType(context, image))) {
|
new AsyncTask<Void, Void, Slide>() {
|
||||||
setMedia(new GifSlide(context, masterSecret, image), masterSecret);
|
@Override protected void onPreExecute() {
|
||||||
} else {
|
slideDeck.clear();
|
||||||
setMedia(new ImageSlide(context, masterSecret, image), masterSecret);
|
thumbnail.clear();
|
||||||
}
|
thumbnail.showProgressSpinner();
|
||||||
}
|
attachmentView.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
public void setVideo(Uri video) throws IOException, MediaTooLargeException {
|
if (isCapture) captureUri = uri;
|
||||||
setMedia(new VideoSlide(context, video));
|
if (!uri.equals(captureUri)) cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAudio(Uri audio) throws IOException, MediaTooLargeException {
|
@Override protected @Nullable Slide doInBackground(Void... params) {
|
||||||
setMedia(new AudioSlide(context, audio));
|
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) {
|
@Override protected void onPostExecute(@Nullable final Slide slide) {
|
||||||
setMedia(slide, null);
|
if (slide == null) {
|
||||||
}
|
attachmentView.setVisibility(View.GONE);
|
||||||
|
Toast.makeText(context,
|
||||||
public void setMedia(final Slide slide, @Nullable MasterSecret masterSecret) {
|
R.string.ConversationActivity_sorry_there_was_an_error_setting_your_attachment,
|
||||||
slideDeck.clear();
|
Toast.LENGTH_SHORT).show();
|
||||||
slideDeck.addSlide(slide);
|
} else if (!areConstraintsSatisfied(context, masterSecret, slide, constraints)) {
|
||||||
attachmentView.setVisibility(View.VISIBLE);
|
attachmentView.setVisibility(View.GONE);
|
||||||
thumbnail.setImageResource(slide, masterSecret);
|
Toast.makeText(context,
|
||||||
attachmentListener.onAttachmentChanged();
|
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() {
|
public boolean isAttachmentPresent() {
|
||||||
@ -118,7 +141,7 @@ public class AttachmentManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public SlideDeck getSlideDeck() {
|
public @NonNull SlideDeck getSlideDeck() {
|
||||||
return slideDeck;
|
return slideDeck;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,10 +166,6 @@ public class AttachmentManager {
|
|||||||
return captureUri;
|
return captureUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCaptureUri(Uri captureUri) {
|
|
||||||
this.captureUri = captureUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void capturePhoto(Activity activity, Recipients recipients, int requestCode) {
|
public void capturePhoto(Activity activity, Recipients recipients, int requestCode) {
|
||||||
try {
|
try {
|
||||||
Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
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 {
|
private class RemoveButtonListener implements View.OnClickListener {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
@ -194,4 +223,22 @@ public class AttachmentManager {
|
|||||||
public interface AttachmentListener {
|
public interface AttachmentListener {
|
||||||
void onAttachmentChanged();
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,27 +18,25 @@ package org.thoughtcrime.securesms.mms;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources.Theme;
|
import android.content.res.Resources.Theme;
|
||||||
import android.database.Cursor;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.provider.MediaStore.Audio;
|
|
||||||
import android.support.annotation.DrawableRes;
|
import android.support.annotation.DrawableRes;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
|
||||||
import org.thoughtcrime.securesms.util.ResUtil;
|
import org.thoughtcrime.securesms.util.ResUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import ws.com.google.android.mms.ContentType;
|
||||||
import ws.com.google.android.mms.pdu.PduPart;
|
import ws.com.google.android.mms.pdu.PduPart;
|
||||||
|
|
||||||
public class AudioSlide extends Slide {
|
public class AudioSlide extends Slide {
|
||||||
|
|
||||||
public AudioSlide(Context context, Uri uri) throws IOException, MediaTooLargeException {
|
public AudioSlide(Context context, Uri uri, long dataSize) throws IOException {
|
||||||
super(context, constructPartFromUri(context, uri));
|
super(context, constructPartFromUri(context, uri, ContentType.AUDIO_UNSPECIFIED, dataSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
public AudioSlide(Context context, MasterSecret masterSecret, PduPart part) {
|
public AudioSlide(Context context, PduPart part) {
|
||||||
super(context, masterSecret, part);
|
super(context, part);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -55,30 +53,4 @@ public class AudioSlide extends Slide {
|
|||||||
public @DrawableRes int getPlaceholderRes(Theme theme) {
|
public @DrawableRes int getPlaceholderRes(Theme theme) {
|
||||||
return ResUtil.getDrawableRes(theme, R.attr.conversation_icon_attach_audio);
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,33 +2,18 @@ package org.thoughtcrime.securesms.mms;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
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 java.io.IOException;
|
||||||
|
|
||||||
import ws.com.google.android.mms.pdu.PduPart;
|
import ws.com.google.android.mms.pdu.PduPart;
|
||||||
|
|
||||||
public class GifSlide extends ImageSlide {
|
public class GifSlide extends ImageSlide {
|
||||||
public GifSlide(Context context, MasterSecret masterSecret, PduPart part) {
|
public GifSlide(Context context, PduPart part) {
|
||||||
super(context, masterSecret, part);
|
super(context, part);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GifSlide(Context context, MasterSecret masterSecret, Uri uri)
|
public GifSlide(Context context, Uri uri, long dataSize) throws IOException {
|
||||||
throws IOException, BitmapDecodingException, MediaTooLargeException
|
super(context, uri, dataSize);
|
||||||
{
|
|
||||||
super(context, masterSecret, uri);
|
|
||||||
assertMediaSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
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.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public Uri getThumbnailUri() {
|
@Override public Uri getThumbnailUri() {
|
||||||
|
@ -22,9 +22,6 @@ import android.net.Uri;
|
|||||||
import android.support.annotation.DrawableRes;
|
import android.support.annotation.DrawableRes;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
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;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -34,12 +31,12 @@ import ws.com.google.android.mms.pdu.PduPart;
|
|||||||
public class ImageSlide extends Slide {
|
public class ImageSlide extends Slide {
|
||||||
private static final String TAG = ImageSlide.class.getSimpleName();
|
private static final String TAG = ImageSlide.class.getSimpleName();
|
||||||
|
|
||||||
public ImageSlide(Context context, MasterSecret masterSecret, PduPart part) {
|
public ImageSlide(Context context, PduPart part) {
|
||||||
super(context, masterSecret, part);
|
super(context, part);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImageSlide(Context context, MasterSecret masterSecret, Uri uri) throws IOException, BitmapDecodingException {
|
public ImageSlide(Context context, Uri uri, long size) throws IOException {
|
||||||
super(context, masterSecret, constructPartFromUri(context, uri));
|
super(context, constructPartFromUri(context, uri, ContentType.IMAGE_JPEG, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -62,20 +59,4 @@ public class ImageSlide extends Slide {
|
|||||||
public boolean hasImage() {
|
public boolean hasImage() {
|
||||||
return true;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,16 +27,16 @@ public class PushMediaConstraints extends MediaConstraints {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getGifMaxSize() {
|
public int getGifMaxSize() {
|
||||||
return 1 * MB;
|
return 5 * MB;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getVideoMaxSize() {
|
public int getVideoMaxSize() {
|
||||||
return MmsMediaConstraints.MAX_MESSAGE_SIZE;
|
return 100 * MB;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAudioMaxSize() {
|
public int getAudioMaxSize() {
|
||||||
return MmsMediaConstraints.MAX_MESSAGE_SIZE;
|
return 100 * MB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,10 @@ import android.content.res.Resources.Theme;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.annotation.DrawableRes;
|
import android.support.annotation.DrawableRes;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -32,20 +34,14 @@ import ws.com.google.android.mms.pdu.PduPart;
|
|||||||
|
|
||||||
public abstract class Slide {
|
public abstract class Slide {
|
||||||
|
|
||||||
protected final PduPart part;
|
protected final PduPart part;
|
||||||
protected final Context context;
|
protected final Context context;
|
||||||
protected MasterSecret masterSecret;
|
|
||||||
|
|
||||||
public Slide(Context context, @NonNull PduPart part) {
|
public Slide(Context context, @NonNull PduPart part) {
|
||||||
this.part = part;
|
this.part = part;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Slide(Context context, @NonNull MasterSecret masterSecret, @NonNull PduPart part) {
|
|
||||||
this(context, part);
|
|
||||||
this.masterSecret = masterSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getContentType() {
|
public String getContentType() {
|
||||||
return new String(part.getContentType());
|
return new String(part.getContentType());
|
||||||
}
|
}
|
||||||
@ -90,18 +86,24 @@ public abstract class Slide {
|
|||||||
return !getPart().getPartId().isValid();
|
return !getPart().getPartId().isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void assertMediaSize(Context context, Uri uri, long max)
|
|
||||||
throws MediaTooLargeException, IOException
|
|
||||||
{
|
|
||||||
InputStream in = context.getContentResolver().openInputStream(uri);
|
|
||||||
long size = 0;
|
|
||||||
byte[] buffer = new byte[512];
|
|
||||||
int read;
|
|
||||||
|
|
||||||
while ((read = in.read(buffer)) != -1) {
|
protected static PduPart constructPartFromUri(@NonNull Context context,
|
||||||
size += read;
|
@NonNull Uri uri,
|
||||||
if (size > max) throw new MediaTooLargeException("Media exceeds maximum message size.");
|
@NonNull String defaultMime,
|
||||||
}
|
long dataSize)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
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
|
@Override
|
||||||
@ -125,7 +127,4 @@ public abstract class Slide {
|
|||||||
return Util.hashCode(getContentType(), hasAudio(), hasImage(),
|
return Util.hashCode(getContentType(), hasAudio(), hasImage(),
|
||||||
hasVideo(), isDraft(), getUri(), getThumbnailUri(), getTransferProgress());
|
hasVideo(), isDraft(), getUri(), getThumbnailUri(), getTransferProgress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -47,10 +47,10 @@ public class SlideDeck {
|
|||||||
this.slides.addAll(copy.getSlides());
|
this.slides.addAll(copy.getSlides());
|
||||||
}
|
}
|
||||||
|
|
||||||
public SlideDeck(Context context, MasterSecret masterSecret, PduBody body) {
|
public SlideDeck(Context context, PduBody body) {
|
||||||
for (int i=0;i<body.getPartsNum();i++) {
|
for (int i=0;i<body.getPartsNum();i++) {
|
||||||
String contentType = Util.toIsoString(body.getPart(i).getContentType());
|
String contentType = Util.toIsoString(body.getPart(i).getContentType());
|
||||||
Slide slide = MediaUtil.getSlideForPart(context, masterSecret, body.getPart(i), contentType);
|
Slide slide = MediaUtil.getSlideForPart(context, body.getPart(i), contentType);
|
||||||
if (slide != null) slides.add(slide);
|
if (slide != null) slides.add(slide);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,31 +16,27 @@
|
|||||||
*/
|
*/
|
||||||
package org.thoughtcrime.securesms.mms;
|
package org.thoughtcrime.securesms.mms;
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources.Theme;
|
import android.content.res.Resources.Theme;
|
||||||
import android.database.Cursor;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.provider.MediaStore;
|
|
||||||
import android.support.annotation.DrawableRes;
|
import android.support.annotation.DrawableRes;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
|
||||||
import org.thoughtcrime.securesms.util.ResUtil;
|
import org.thoughtcrime.securesms.util.ResUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import ws.com.google.android.mms.ContentType;
|
||||||
import ws.com.google.android.mms.pdu.PduPart;
|
import ws.com.google.android.mms.pdu.PduPart;
|
||||||
|
|
||||||
public class VideoSlide extends Slide {
|
public class VideoSlide extends Slide {
|
||||||
|
|
||||||
public VideoSlide(Context context, Uri uri) throws IOException, MediaTooLargeException {
|
public VideoSlide(Context context, Uri uri, long dataSize) throws IOException {
|
||||||
super(context, constructPartFromUri(context, uri));
|
super(context, constructPartFromUri(context, uri, ContentType.VIDEO_UNSPECIFIED, dataSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
public VideoSlide(Context context, MasterSecret masterSecret, PduPart part) {
|
public VideoSlide(Context context, PduPart part) {
|
||||||
super(context, masterSecret, part);
|
super(context, part);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -57,30 +53,4 @@ public class VideoSlide extends Slide {
|
|||||||
public boolean hasVideo() {
|
public boolean hasVideo() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PduPart constructPartFromUri(Context context, Uri uri)
|
|
||||||
throws IOException, MediaTooLargeException
|
|
||||||
{
|
|
||||||
PduPart part = new PduPart();
|
|
||||||
ContentResolver resolver = context.getContentResolver();
|
|
||||||
Cursor cursor = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
cursor = resolver.query(uri, new String[] {MediaStore.Video.Media.MIME_TYPE}, null, null, null);
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
Log.w("VideoSlide", "Setting mime type: " + cursor.getString(0));
|
|
||||||
part.setContentType(cursor.getString(0).getBytes());
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (cursor != null)
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
assertMediaSize(context, uri, MmsMediaConstraints.MAX_MESSAGE_SIZE);
|
|
||||||
part.setDataUri(uri);
|
|
||||||
part.setContentId((System.currentTimeMillis()+"").getBytes());
|
|
||||||
part.setName(("Video" + System.currentTimeMillis()).getBytes());
|
|
||||||
|
|
||||||
return part;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -66,16 +66,16 @@ public class MediaUtil {
|
|||||||
return BitmapUtil.createScaledBitmap(context, new DecryptableUri(masterSecret, uri), maxSize, maxSize);
|
return BitmapUtil.createScaledBitmap(context, new DecryptableUri(masterSecret, uri), maxSize, maxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Slide getSlideForPart(Context context, MasterSecret masterSecret, PduPart part, String contentType) {
|
public static Slide getSlideForPart(Context context, PduPart part, String contentType) {
|
||||||
Slide slide = null;
|
Slide slide = null;
|
||||||
if (isGif(contentType)) {
|
if (isGif(contentType)) {
|
||||||
slide = new GifSlide(context, masterSecret, part);
|
slide = new GifSlide(context, part);
|
||||||
} else if (ContentType.isImageType(contentType)) {
|
} else if (ContentType.isImageType(contentType)) {
|
||||||
slide = new ImageSlide(context, masterSecret, part);
|
slide = new ImageSlide(context, part);
|
||||||
} else if (ContentType.isVideoType(contentType)) {
|
} else if (ContentType.isVideoType(contentType)) {
|
||||||
slide = new VideoSlide(context, masterSecret, part);
|
slide = new VideoSlide(context, part);
|
||||||
} else if (ContentType.isAudioType(contentType)) {
|
} else if (ContentType.isAudioType(contentType)) {
|
||||||
slide = new AudioSlide(context, masterSecret, part);
|
slide = new AudioSlide(context, part);
|
||||||
}
|
}
|
||||||
|
|
||||||
return slide;
|
return slide;
|
||||||
@ -90,6 +90,22 @@ public class MediaUtil {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long getMediaSize(Context context, MasterSecret masterSecret, Uri uri) throws IOException {
|
||||||
|
InputStream in = PartAuthority.getPartStream(context, masterSecret, uri);
|
||||||
|
if (in == null) throw new IOException("Couldn't obtain input stream.");
|
||||||
|
|
||||||
|
long size = 0;
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int read;
|
||||||
|
|
||||||
|
while ((read = in.read(buffer)) != -1) {
|
||||||
|
size += read;
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isGif(String contentType) {
|
public static boolean isGif(String contentType) {
|
||||||
return !TextUtils.isEmpty(contentType) && contentType.trim().equals("image/gif");
|
return !TextUtils.isEmpty(contentType) && contentType.trim().equals("image/gif");
|
||||||
}
|
}
|
||||||
@ -111,7 +127,11 @@ public class MediaUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static @Nullable String getDiscreteMimeType(@NonNull PduPart part) {
|
public static @Nullable String getDiscreteMimeType(@NonNull PduPart part) {
|
||||||
final String[] sections = (Util.toIsoString(part.getContentType()).split("/", 2));
|
return getDiscreteMimeType(Util.toIsoString(part.getContentType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @Nullable String getDiscreteMimeType(@NonNull String mimeType) {
|
||||||
|
final String[] sections = mimeType.split("/", 2);
|
||||||
return sections.length > 1 ? sections[0] : null;
|
return sections.length > 1 ? sections[0] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user