parent
8b342ee18b
commit
69b102bfe3
7 changed files with 121 additions and 13 deletions
|
@ -11,4 +11,10 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:contentDescription="@string/media_preview_activity__image_content_description" />
|
android:contentDescription="@string/media_preview_activity__image_content_description" />
|
||||||
|
|
||||||
|
<org.thoughtcrime.securesms.video.VideoPlayer
|
||||||
|
android:id="@+id/video_player"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
13
res/layout/video_player.xml
Normal file
13
res/layout/video_player.xml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<VideoView android:id="@+id/video_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
|
@ -535,14 +535,13 @@ public class ConversationItem extends LinearLayout
|
||||||
public void onClick(final View v, final Slide slide) {
|
public void onClick(final View v, final Slide slide) {
|
||||||
if (shouldInterceptClicks(messageRecord) || !batchSelected.isEmpty()) {
|
if (shouldInterceptClicks(messageRecord) || !batchSelected.isEmpty()) {
|
||||||
performClick();
|
performClick();
|
||||||
} else if (MediaPreviewActivity.isContentTypeSupported(slide.getContentType()) &&
|
} else if (MediaPreviewActivity.isContentTypeSupported(slide.getContentType()) && slide.getUri() != null) {
|
||||||
slide.getThumbnailUri() != null)
|
|
||||||
{
|
|
||||||
Intent intent = new Intent(context, MediaPreviewActivity.class);
|
Intent intent = new Intent(context, MediaPreviewActivity.class);
|
||||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
intent.setDataAndType(slide.getUri(), slide.getContentType());
|
intent.setDataAndType(slide.getUri(), slide.getContentType());
|
||||||
if (!messageRecord.isOutgoing()) intent.putExtra(MediaPreviewActivity.RECIPIENT_EXTRA, recipient.getRecipientId());
|
if (!messageRecord.isOutgoing()) intent.putExtra(MediaPreviewActivity.RECIPIENT_EXTRA, recipient.getRecipientId());
|
||||||
intent.putExtra(MediaPreviewActivity.DATE_EXTRA, messageRecord.getTimestamp());
|
intent.putExtra(MediaPreviewActivity.DATE_EXTRA, messageRecord.getTimestamp());
|
||||||
|
intent.putExtra(MediaPreviewActivity.SIZE_EXTRA, slide.asAttachment().getSize());
|
||||||
|
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -34,6 +34,7 @@ import android.widget.Toast;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.components.ZoomingImageView;
|
import org.thoughtcrime.securesms.components.ZoomingImageView;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
|
import org.thoughtcrime.securesms.mms.VideoSlide;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient.RecipientModifiedListener;
|
import org.thoughtcrime.securesms.recipients.Recipient.RecipientModifiedListener;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||||
|
@ -41,6 +42,9 @@ import org.thoughtcrime.securesms.util.DateUtils;
|
||||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||||
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
|
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
|
||||||
import org.thoughtcrime.securesms.util.SaveAttachmentTask.Attachment;
|
import org.thoughtcrime.securesms.util.SaveAttachmentTask.Attachment;
|
||||||
|
import org.thoughtcrime.securesms.video.VideoPlayer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activity for displaying media attachments in-app
|
* Activity for displaying media attachments in-app
|
||||||
|
@ -50,16 +54,19 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
||||||
|
|
||||||
public static final String RECIPIENT_EXTRA = "recipient";
|
public static final String RECIPIENT_EXTRA = "recipient";
|
||||||
public static final String DATE_EXTRA = "date";
|
public static final String DATE_EXTRA = "date";
|
||||||
|
public static final String SIZE_EXTRA = "size";
|
||||||
|
|
||||||
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
||||||
|
|
||||||
private MasterSecret masterSecret;
|
private MasterSecret masterSecret;
|
||||||
|
|
||||||
private ZoomingImageView image;
|
private ZoomingImageView image;
|
||||||
|
private VideoPlayer video;
|
||||||
private Uri mediaUri;
|
private Uri mediaUri;
|
||||||
private String mediaType;
|
private String mediaType;
|
||||||
private Recipient recipient;
|
private Recipient recipient;
|
||||||
private long date;
|
private long date;
|
||||||
|
private long size;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) {
|
protected void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) {
|
||||||
|
@ -131,6 +138,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
||||||
|
|
||||||
private void initializeViews() {
|
private void initializeViews() {
|
||||||
image = (ZoomingImageView)findViewById(R.id.image);
|
image = (ZoomingImageView)findViewById(R.id.image);
|
||||||
|
video = (VideoPlayer)findViewById(R.id.video_player);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeResources() {
|
private void initializeResources() {
|
||||||
|
@ -139,6 +147,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
||||||
mediaUri = getIntent().getData();
|
mediaUri = getIntent().getData();
|
||||||
mediaType = getIntent().getType();
|
mediaType = getIntent().getType();
|
||||||
date = getIntent().getLongExtra(DATE_EXTRA, System.currentTimeMillis());
|
date = getIntent().getLongExtra(DATE_EXTRA, System.currentTimeMillis());
|
||||||
|
size = getIntent().getLongExtra(SIZE_EXTRA, 0);
|
||||||
|
|
||||||
if (recipientId > -1) {
|
if (recipientId > -1) {
|
||||||
recipient = RecipientFactory.getRecipientForId(this, recipientId, true);
|
recipient = RecipientFactory.getRecipientForId(this, recipientId, true);
|
||||||
|
@ -157,13 +166,26 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
||||||
|
|
||||||
Log.w(TAG, "Loading Part URI: " + mediaUri);
|
Log.w(TAG, "Loading Part URI: " + mediaUri);
|
||||||
|
|
||||||
if (mediaType != null && mediaType.startsWith("image/")) {
|
try {
|
||||||
image.setImageUri(masterSecret, mediaUri);
|
if (mediaType != null && mediaType.startsWith("image/")) {
|
||||||
|
image.setVisibility(View.VISIBLE);
|
||||||
|
video.setVisibility(View.GONE);
|
||||||
|
image.setImageUri(masterSecret, mediaUri);
|
||||||
|
} else if (mediaType != null && mediaType.startsWith("video/")) {
|
||||||
|
image.setVisibility(View.GONE);
|
||||||
|
video.setVisibility(View.VISIBLE);
|
||||||
|
video.setVideoSource(masterSecret, new VideoSlide(this, mediaUri, size));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w(TAG, e);
|
||||||
|
Toast.makeText(getApplicationContext(), R.string.MediaPreviewActivity_unssuported_media_type, Toast.LENGTH_LONG).show();
|
||||||
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cleanupMedia() {
|
private void cleanupMedia() {
|
||||||
image.setImageDrawable(null);
|
image.setImageDrawable(null);
|
||||||
|
video.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void forward() {
|
private void forward() {
|
||||||
|
@ -208,6 +230,6 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isContentTypeSupported(final String contentType) {
|
public static boolean isContentTypeSupported(final String contentType) {
|
||||||
return contentType != null && contentType.startsWith("image/");
|
return contentType != null && (contentType.startsWith("image/") || contentType.startsWith("video/"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package org.thoughtcrime.securesms.audio;
|
package org.thoughtcrime.securesms.attachments;
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -7,7 +7,6 @@ import android.support.annotation.NonNull;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
|
@ -33,9 +32,9 @@ import java.util.StringTokenizer;
|
||||||
/**
|
/**
|
||||||
* @author Stefan "frostymarvelous" Froelich <stefan d0t froelich At whisppa DoT com>
|
* @author Stefan "frostymarvelous" Froelich <stefan d0t froelich At whisppa DoT com>
|
||||||
*/
|
*/
|
||||||
public class AudioAttachmentServer implements Runnable {
|
public class AttachmentServer implements Runnable {
|
||||||
|
|
||||||
private static final String TAG = AudioAttachmentServer.class.getSimpleName();
|
private static final String TAG = AttachmentServer.class.getSimpleName();
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final MasterSecret masterSecret;
|
private final MasterSecret masterSecret;
|
||||||
|
@ -46,7 +45,7 @@ public class AudioAttachmentServer implements Runnable {
|
||||||
|
|
||||||
private volatile boolean isRunning;
|
private volatile boolean isRunning;
|
||||||
|
|
||||||
public AudioAttachmentServer(Context context, MasterSecret masterSecret, Attachment attachment)
|
public AttachmentServer(Context context, MasterSecret masterSecret, Attachment attachment)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
try {
|
try {
|
|
@ -12,6 +12,7 @@ import android.util.Pair;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
|
import org.thoughtcrime.securesms.attachments.AttachmentServer;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.mms.AudioSlide;
|
import org.thoughtcrime.securesms.mms.AudioSlide;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
|
@ -33,7 +34,7 @@ public class AudioSlidePlayer {
|
||||||
|
|
||||||
private @NonNull WeakReference<Listener> listener;
|
private @NonNull WeakReference<Listener> listener;
|
||||||
private @Nullable MediaPlayer mediaPlayer;
|
private @Nullable MediaPlayer mediaPlayer;
|
||||||
private @Nullable AudioAttachmentServer audioAttachmentServer;
|
private @Nullable AttachmentServer audioAttachmentServer;
|
||||||
|
|
||||||
public synchronized static AudioSlidePlayer createFor(@NonNull Context context,
|
public synchronized static AudioSlidePlayer createFor(@NonNull Context context,
|
||||||
@NonNull MasterSecret masterSecret,
|
@NonNull MasterSecret masterSecret,
|
||||||
|
@ -64,7 +65,7 @@ public class AudioSlidePlayer {
|
||||||
if (this.mediaPlayer != null) return;
|
if (this.mediaPlayer != null) return;
|
||||||
|
|
||||||
this.mediaPlayer = new MediaPlayer();
|
this.mediaPlayer = new MediaPlayer();
|
||||||
this.audioAttachmentServer = new AudioAttachmentServer(context, masterSecret, slide.asAttachment());
|
this.audioAttachmentServer = new AttachmentServer(context, masterSecret, slide.asAttachment());
|
||||||
|
|
||||||
audioAttachmentServer.start();
|
audioAttachmentServer.start();
|
||||||
|
|
||||||
|
|
68
src/org/thoughtcrime/securesms/video/VideoPlayer.java
Normal file
68
src/org/thoughtcrime/securesms/video/VideoPlayer.java
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
package org.thoughtcrime.securesms.video;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.MediaController;
|
||||||
|
import android.widget.VideoView;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.R;
|
||||||
|
import org.thoughtcrime.securesms.attachments.AttachmentServer;
|
||||||
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
|
import org.thoughtcrime.securesms.mms.VideoSlide;
|
||||||
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class VideoPlayer extends FrameLayout {
|
||||||
|
|
||||||
|
@NonNull private final VideoView videoView;
|
||||||
|
@Nullable private AttachmentServer attachmentServer;
|
||||||
|
|
||||||
|
public VideoPlayer(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VideoPlayer(Context context, AttributeSet attrs) {
|
||||||
|
this(context, attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VideoPlayer(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
|
||||||
|
inflate(context, R.layout.video_player, this);
|
||||||
|
|
||||||
|
this.videoView = ViewUtil.findById(this, R.id.video_view);
|
||||||
|
|
||||||
|
initializeVideoViewControls(videoView);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVideoSource(@NonNull MasterSecret masterSecret, @NonNull VideoSlide videoSource) throws IOException {
|
||||||
|
if (this.attachmentServer != null) {
|
||||||
|
this.attachmentServer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.attachmentServer = new AttachmentServer(getContext(), masterSecret, videoSource.asAttachment());
|
||||||
|
this.attachmentServer.start();
|
||||||
|
|
||||||
|
this.videoView.setVideoURI(this.attachmentServer.getUri());
|
||||||
|
this.videoView.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanup() {
|
||||||
|
if (this.attachmentServer != null) {
|
||||||
|
this.attachmentServer.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeVideoViewControls(@NonNull VideoView videoView) {
|
||||||
|
MediaController mediaController = new MediaController(getContext());
|
||||||
|
mediaController.setAnchorView(videoView);
|
||||||
|
mediaController.setMediaPlayer(videoView);
|
||||||
|
|
||||||
|
videoView.setMediaController(mediaController);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue