mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Merge pull request #1090 from deltachat/fix_playback_64bit
update audio playing capabilitys to signals current state
This commit is contained in:
+2
-1
@@ -39,7 +39,8 @@ dependencies {
|
||||
implementation 'android.arch.lifecycle:extensions:1.1.1' // Used in situations where data changes should be displayed directly (e.G. Search)
|
||||
implementation 'android.arch.lifecycle:common-java8:1.1.1' // Used in situations where data changes should be displayed directly (e.G. Search)
|
||||
|
||||
implementation 'com.google.android.exoplayer:exoplayer:r2.3.1' // plays video.
|
||||
implementation 'com.google.android.exoplayer:exoplayer-core:2.9.1' // plays video and audio
|
||||
implementation 'com.google.android.exoplayer:exoplayer-ui:2.9.1'
|
||||
|
||||
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.5' // used as JSON library TODO: check if java builtin would work as well
|
||||
|
||||
|
||||
@@ -355,7 +355,7 @@ public class ConversationItem extends LinearLayout
|
||||
public void onStop() {}
|
||||
|
||||
@Override
|
||||
public void onProgress(double progress, int millis) {}
|
||||
public void onProgress(double progress, long millis) {}
|
||||
|
||||
@Override
|
||||
public void onReceivedDuration(int millis) {
|
||||
|
||||
@@ -1,34 +1,41 @@
|
||||
package org.thoughtcrime.securesms.audio;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Build;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.PowerManager;
|
||||
import android.os.PowerManager.WakeLock;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.DefaultLoadControl;
|
||||
import com.google.android.exoplayer2.DefaultRenderersFactory;
|
||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||
import com.google.android.exoplayer2.ExoPlayerFactory;
|
||||
import com.google.android.exoplayer2.LoadControl;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
|
||||
import com.google.android.exoplayer2.source.ExtractorMediaSource;
|
||||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.attachments.AttachmentServer;
|
||||
import org.thoughtcrime.securesms.mms.AudioSlide;
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.guava.Optional;
|
||||
import org.thoughtcrime.securesms.video.exo.AttachmentDataSourceFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class AudioSlidePlayer implements SensorEventListener {
|
||||
public class AudioSlidePlayer {
|
||||
|
||||
private static final String TAG = AudioSlidePlayer.class.getSimpleName();
|
||||
|
||||
@@ -37,14 +44,10 @@ public class AudioSlidePlayer implements SensorEventListener {
|
||||
private final @NonNull Context context;
|
||||
private final @NonNull AudioSlide slide;
|
||||
private final @NonNull Handler progressEventHandler;
|
||||
private final @NonNull AudioManager audioManager;
|
||||
private final @NonNull SensorManager sensorManager;
|
||||
private final @NonNull Sensor proximitySensor;
|
||||
private final @Nullable WakeLock wakeLock;
|
||||
|
||||
private @NonNull WeakReference<Listener> listener;
|
||||
private @Nullable MediaPlayerWrapper mediaPlayer;
|
||||
private @Nullable AttachmentServer audioAttachmentServer;
|
||||
private @Nullable SimpleExoPlayer mediaPlayer;
|
||||
private @Nullable SimpleExoPlayer durationCalculator;
|
||||
private long startTime;
|
||||
|
||||
public synchronized static AudioSlidePlayer createFor(@NonNull Context context,
|
||||
@@ -67,56 +70,31 @@ public class AudioSlidePlayer implements SensorEventListener {
|
||||
this.slide = slide;
|
||||
this.listener = new WeakReference<>(listener);
|
||||
this.progressEventHandler = new ProgressEventHandler(this);
|
||||
this.audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
|
||||
this.sensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
|
||||
this.proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
this.wakeLock = ServiceUtil.getPowerManager(context).newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
|
||||
} else {
|
||||
this.wakeLock = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void requestDuration() {
|
||||
if(this.mediaPlayer == null) {
|
||||
this.mediaPlayer = new MediaPlayerWrapper();
|
||||
try {
|
||||
this.audioAttachmentServer = new AttachmentServer(context, slide.asAttachment());
|
||||
this.startTime = System.currentTimeMillis();
|
||||
|
||||
audioAttachmentServer.start();
|
||||
this.mediaPlayer.setDataSource(context, audioAttachmentServer.getUri());
|
||||
|
||||
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
|
||||
@Override
|
||||
public void onPrepared(MediaPlayer mp) {
|
||||
Log.w(TAG, "onPrepared");
|
||||
synchronized (AudioSlidePlayer.this) {
|
||||
if (mediaPlayer == null) return;
|
||||
}
|
||||
getListener().onReceivedDuration(mediaPlayer.getDuration());
|
||||
if (mediaPlayer != null) {
|
||||
mediaPlayer.stop();
|
||||
mediaPlayer.release();
|
||||
}
|
||||
|
||||
if (audioAttachmentServer != null) {
|
||||
audioAttachmentServer.stop();
|
||||
}
|
||||
|
||||
mediaPlayer = null;
|
||||
audioAttachmentServer = null;
|
||||
try {
|
||||
LoadControl loadControl = new DefaultLoadControl.Builder().setBufferDurationsMs(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE).createDefaultLoadControl();
|
||||
durationCalculator = ExoPlayerFactory.newSimpleInstance(context, new DefaultRenderersFactory(context), new DefaultTrackSelector(), loadControl);
|
||||
durationCalculator.setPlayWhenReady(false);
|
||||
durationCalculator.addListener(new Player.EventListener() {
|
||||
@Override
|
||||
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
|
||||
if (playbackState == Player.STATE_READY) {
|
||||
Util.runOnMain(() -> {
|
||||
Log.d(TAG, "request duration " + durationCalculator.getDuration());
|
||||
getListener().onReceivedDuration(Long.valueOf(durationCalculator.getDuration()).intValue());
|
||||
durationCalculator.release();
|
||||
durationCalculator.removeListener(this);
|
||||
durationCalculator = null;
|
||||
});
|
||||
}
|
||||
});
|
||||
mediaPlayer.prepareAsync();
|
||||
|
||||
} catch (IOException e) {
|
||||
}
|
||||
});
|
||||
durationCalculator.prepare(createMediaSource(slide.getUri()));
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, e);
|
||||
getListener().onReceivedDuration(0);
|
||||
}
|
||||
} else {
|
||||
getListener().onReceivedDuration(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,95 +103,97 @@ public class AudioSlidePlayer implements SensorEventListener {
|
||||
}
|
||||
|
||||
private void play(final double progress, boolean earpiece) throws IOException {
|
||||
if (this.mediaPlayer != null) return;
|
||||
if (this.mediaPlayer != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.mediaPlayer = new MediaPlayerWrapper();
|
||||
this.audioAttachmentServer = new AttachmentServer(context, slide.asAttachment());
|
||||
if (slide.getUri() == null) {
|
||||
throw new IOException("Slide has no URI!");
|
||||
}
|
||||
|
||||
LoadControl loadControl = new DefaultLoadControl.Builder().setBufferDurationsMs(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE).createDefaultLoadControl();
|
||||
this.mediaPlayer = ExoPlayerFactory.newSimpleInstance(context, new DefaultRenderersFactory(context), new DefaultTrackSelector(), loadControl);
|
||||
this.startTime = System.currentTimeMillis();
|
||||
|
||||
audioAttachmentServer.start();
|
||||
mediaPlayer.prepare(createMediaSource(slide.getUri()));
|
||||
mediaPlayer.setPlayWhenReady(true);
|
||||
mediaPlayer.setAudioAttributes(new AudioAttributes.Builder()
|
||||
.setContentType(earpiece ? C.CONTENT_TYPE_SPEECH : C.CONTENT_TYPE_MUSIC)
|
||||
.setUsage(earpiece ? C.USAGE_VOICE_COMMUNICATION : C.USAGE_MEDIA)
|
||||
.build());
|
||||
mediaPlayer.addListener(new Player.EventListener() {
|
||||
|
||||
boolean started = false;
|
||||
|
||||
mediaPlayer.setDataSource(context, audioAttachmentServer.getUri());
|
||||
mediaPlayer.setAudioStreamType(earpiece ? AudioManager.STREAM_VOICE_CALL : AudioManager.STREAM_MUSIC);
|
||||
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
|
||||
@Override
|
||||
public void onPrepared(MediaPlayer mp) {
|
||||
Log.w(TAG, "onPrepared");
|
||||
synchronized (AudioSlidePlayer.this) {
|
||||
if (mediaPlayer == null) return;
|
||||
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
|
||||
Log.d(TAG, "onPlayerStateChanged(" + playWhenReady + ", " + playbackState + ")");
|
||||
switch (playbackState) {
|
||||
case Player.STATE_READY:
|
||||
|
||||
if (progress > 0) {
|
||||
mediaPlayer.seekTo((int) (mediaPlayer.getDuration() * progress));
|
||||
}
|
||||
Log.i(TAG, "onPrepared() " + mediaPlayer.getBufferedPercentage() + "% buffered");
|
||||
synchronized (AudioSlidePlayer.this) {
|
||||
if (mediaPlayer == null) return;
|
||||
Log.d(TAG, "DURATION: " + mediaPlayer.getDuration());
|
||||
|
||||
sensorManager.registerListener(AudioSlidePlayer.this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
|
||||
mediaPlayer.start();
|
||||
if (started) {
|
||||
Log.d(TAG, "Already started. Ignoring.");
|
||||
return;
|
||||
}
|
||||
|
||||
setPlaying(AudioSlidePlayer.this);
|
||||
started = true;
|
||||
|
||||
if (progress > 0) {
|
||||
mediaPlayer.seekTo((long) (mediaPlayer.getDuration() * progress));
|
||||
}
|
||||
|
||||
setPlaying(AudioSlidePlayer.this);
|
||||
}
|
||||
|
||||
notifyOnStart();
|
||||
progressEventHandler.sendEmptyMessage(0);
|
||||
break;
|
||||
|
||||
case Player.STATE_ENDED:
|
||||
Log.i(TAG, "onComplete");
|
||||
synchronized (AudioSlidePlayer.this) {
|
||||
getListener().onReceivedDuration(Long.valueOf(mediaPlayer.getDuration()).intValue());
|
||||
mediaPlayer = null;
|
||||
}
|
||||
|
||||
notifyOnStop();
|
||||
progressEventHandler.removeMessages(0);
|
||||
}
|
||||
|
||||
notifyOnStart();
|
||||
progressEventHandler.sendEmptyMessage(0);
|
||||
}
|
||||
});
|
||||
|
||||
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
|
||||
@Override
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
Log.w(TAG, "onComplete");
|
||||
synchronized (AudioSlidePlayer.this) {
|
||||
mediaPlayer = null;
|
||||
|
||||
if (audioAttachmentServer != null) {
|
||||
audioAttachmentServer.stop();
|
||||
audioAttachmentServer = null;
|
||||
}
|
||||
|
||||
sensorManager.unregisterListener(AudioSlidePlayer.this);
|
||||
|
||||
if (wakeLock != null && wakeLock.isHeld()) {
|
||||
wakeLock.release(PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY);
|
||||
}
|
||||
}
|
||||
|
||||
notifyOnStop();
|
||||
progressEventHandler.removeMessages(0);
|
||||
}
|
||||
});
|
||||
|
||||
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
|
||||
@Override
|
||||
public boolean onError(MediaPlayer mp, int what, int extra) {
|
||||
Log.w(TAG, "MediaPlayer Error: " + what + " , " + extra);
|
||||
public void onPlayerError(ExoPlaybackException error) {
|
||||
Log.w(TAG, "MediaPlayer Error: " + error);
|
||||
|
||||
Toast.makeText(context, R.string.error, Toast.LENGTH_SHORT).show();
|
||||
|
||||
synchronized (AudioSlidePlayer.this) {
|
||||
mediaPlayer = null;
|
||||
|
||||
if (audioAttachmentServer != null) {
|
||||
audioAttachmentServer.stop();
|
||||
audioAttachmentServer = null;
|
||||
}
|
||||
|
||||
sensorManager.unregisterListener(AudioSlidePlayer.this);
|
||||
|
||||
if (wakeLock != null && wakeLock.isHeld()) {
|
||||
wakeLock.release(PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY);
|
||||
}
|
||||
}
|
||||
|
||||
notifyOnStop();
|
||||
progressEventHandler.removeMessages(0);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
mediaPlayer.prepareAsync();
|
||||
private MediaSource createMediaSource(@NonNull Uri uri) {
|
||||
DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(context, "GenericUserAgent", null);
|
||||
AttachmentDataSourceFactory attachmentDataSourceFactory = new AttachmentDataSourceFactory(context, defaultDataSourceFactory, null);
|
||||
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true);
|
||||
|
||||
return new ExtractorMediaSource.Factory(attachmentDataSourceFactory)
|
||||
.setExtractorsFactory(extractorsFactory)
|
||||
.createMediaSource(uri);
|
||||
}
|
||||
|
||||
public synchronized void stop() {
|
||||
Log.w(TAG, "Stop called!");
|
||||
Log.i(TAG, "Stop called!");
|
||||
|
||||
removePlaying(this);
|
||||
|
||||
@@ -222,14 +202,7 @@ public class AudioSlidePlayer implements SensorEventListener {
|
||||
this.mediaPlayer.release();
|
||||
}
|
||||
|
||||
if (this.audioAttachmentServer != null) {
|
||||
this.audioAttachmentServer.stop();
|
||||
}
|
||||
|
||||
sensorManager.unregisterListener(AudioSlidePlayer.this);
|
||||
|
||||
this.mediaPlayer = null;
|
||||
this.audioAttachmentServer = null;
|
||||
this.mediaPlayer = null;
|
||||
}
|
||||
|
||||
public synchronized static void stopAll() {
|
||||
@@ -241,7 +214,7 @@ public class AudioSlidePlayer implements SensorEventListener {
|
||||
public void setListener(@NonNull Listener listener) {
|
||||
this.listener = new WeakReference<>(listener);
|
||||
|
||||
if (this.mediaPlayer != null && this.mediaPlayer.isPlaying()) {
|
||||
if (this.mediaPlayer != null && this.mediaPlayer.getPlaybackState() == Player.STATE_READY) {
|
||||
notifyOnStart();
|
||||
}
|
||||
}
|
||||
@@ -256,7 +229,7 @@ public class AudioSlidePlayer implements SensorEventListener {
|
||||
return new Pair<>(0D, 0);
|
||||
} else {
|
||||
return new Pair<>((double) mediaPlayer.getCurrentPosition() / (double) mediaPlayer.getDuration(),
|
||||
mediaPlayer.getCurrentPosition());
|
||||
(int) mediaPlayer.getCurrentPosition());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +255,7 @@ public class AudioSlidePlayer implements SensorEventListener {
|
||||
Util.runOnMain(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
getListener().onProgress(progress, (int) millis);
|
||||
getListener().onProgress(progress, millis);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -297,7 +270,7 @@ public class AudioSlidePlayer implements SensorEventListener {
|
||||
@Override
|
||||
public void onStop() {}
|
||||
@Override
|
||||
public void onProgress(double progress, int millis) {}
|
||||
public void onProgress(double progress, long millis) {}
|
||||
@Override
|
||||
public void onReceivedDuration(int millis) {}
|
||||
};
|
||||
@@ -318,54 +291,11 @@ public class AudioSlidePlayer implements SensorEventListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
if (event.sensor.getType() != Sensor.TYPE_PROXIMITY) return;
|
||||
if (mediaPlayer == null || !mediaPlayer.isPlaying()) return;
|
||||
|
||||
int streamType;
|
||||
|
||||
if (event.values[0] < 5f && event.values[0] != proximitySensor.getMaximumRange()) {
|
||||
streamType = AudioManager.STREAM_VOICE_CALL;
|
||||
} else {
|
||||
streamType = AudioManager.STREAM_MUSIC;
|
||||
}
|
||||
|
||||
if (streamType == AudioManager.STREAM_VOICE_CALL &&
|
||||
mediaPlayer.getAudioStreamType() != streamType &&
|
||||
!audioManager.isWiredHeadsetOn())
|
||||
{
|
||||
double position = mediaPlayer.getCurrentPosition();
|
||||
double duration = mediaPlayer.getDuration();
|
||||
double progress = position / duration;
|
||||
|
||||
if (wakeLock != null) wakeLock.acquire();
|
||||
stop();
|
||||
try {
|
||||
play(progress, true);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
} else if (streamType == AudioManager.STREAM_MUSIC &&
|
||||
mediaPlayer.getAudioStreamType() != streamType &&
|
||||
System.currentTimeMillis() - startTime > 500)
|
||||
{
|
||||
if (wakeLock != null) wakeLock.release();
|
||||
stop();
|
||||
notifyOnStop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
public void onStart();
|
||||
public void onStop();
|
||||
public void onProgress(double progress, int millis);
|
||||
public void onReceivedDuration(int millis);
|
||||
void onStart();
|
||||
void onStop();
|
||||
void onProgress(double progress, long millis);
|
||||
void onReceivedDuration(int millis);
|
||||
}
|
||||
|
||||
private static class ProgressEventHandler extends Handler {
|
||||
@@ -380,7 +310,7 @@ public class AudioSlidePlayer implements SensorEventListener {
|
||||
public void handleMessage(Message msg) {
|
||||
AudioSlidePlayer player = playerReference.get();
|
||||
|
||||
if (player == null || player.mediaPlayer == null || !player.mediaPlayer.isPlaying()) {
|
||||
if (player == null || player.mediaPlayer == null || !isPlayerActive(player.mediaPlayer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -388,20 +318,9 @@ public class AudioSlidePlayer implements SensorEventListener {
|
||||
player.notifyOnProgress(progress.first, progress.second);
|
||||
sendEmptyMessageDelayed(0, 50);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MediaPlayerWrapper extends MediaPlayer {
|
||||
|
||||
private int streamType;
|
||||
|
||||
@Override
|
||||
public void setAudioStreamType(int streamType) {
|
||||
this.streamType = streamType;
|
||||
super.setAudioStreamType(streamType);
|
||||
}
|
||||
|
||||
public int getAudioStreamType() {
|
||||
return streamType;
|
||||
private boolean isPlayerActive(@NonNull SimpleExoPlayer player) {
|
||||
return player.getPlaybackState() == Player.STATE_READY || player.getPlaybackState() == Player.STATE_BUFFERING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
|
||||
|
||||
if (seekBar.getProgress() + 5 >= seekBar.getMax()) {
|
||||
backwardsCounter = 4;
|
||||
onProgress(0.0, 0);
|
||||
onProgress(0.0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,13 +153,15 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgress(double progress, int millis) {
|
||||
public void onProgress(double progress, long millis) {
|
||||
int seekProgress = (int)Math.floor(progress * this.seekBar.getMax());
|
||||
|
||||
if (seekProgress > seekBar.getProgress() || backwardsCounter > 3) {
|
||||
backwardsCounter = 0;
|
||||
this.seekBar.setProgress(seekProgress);
|
||||
this.timestamp.setText(DateUtils.getFormatedDuration(millis));
|
||||
if (millis != -1) {
|
||||
this.timestamp.setText(DateUtils.getFormatedDuration(millis));
|
||||
}
|
||||
} else {
|
||||
backwardsCounter++;
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ public class AttachmentManager {
|
||||
public void onStop() {}
|
||||
|
||||
@Override
|
||||
public void onProgress(double progress, int millis) {}
|
||||
public void onProgress(double progress, long millis) {}
|
||||
|
||||
@Override
|
||||
public void onReceivedDuration(int millis) {
|
||||
|
||||
@@ -170,7 +170,7 @@ public class DateUtils extends android.text.format.DateUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getFormatedDuration(int millis) {
|
||||
public static String getFormatedDuration(long millis) {
|
||||
return String.format("%02d:%02d",
|
||||
TimeUnit.MILLISECONDS.toMinutes(millis),
|
||||
TimeUnit.MILLISECONDS.toSeconds(millis-(TimeUnit.MILLISECONDS.toMinutes(millis)*60000)));
|
||||
|
||||
@@ -30,21 +30,17 @@ import android.widget.Toast;
|
||||
import android.widget.VideoView;
|
||||
|
||||
import com.google.android.exoplayer2.DefaultLoadControl;
|
||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||
import com.google.android.exoplayer2.ExoPlayer;
|
||||
import com.google.android.exoplayer2.ExoPlayerFactory;
|
||||
import com.google.android.exoplayer2.LoadControl;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
import com.google.android.exoplayer2.Timeline;
|
||||
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
|
||||
import com.google.android.exoplayer2.source.ExtractorMediaSource;
|
||||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
|
||||
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelector;
|
||||
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
|
||||
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||
@@ -180,7 +176,7 @@ public class VideoPlayer extends FrameLayout {
|
||||
videoView.setMediaController(mediaController);
|
||||
}
|
||||
|
||||
private static class ExoPlayerListener implements ExoPlayer.EventListener {
|
||||
private static class ExoPlayerListener implements Player.EventListener {
|
||||
private final Window window;
|
||||
|
||||
ExoPlayerListener(Window window) {
|
||||
@@ -190,12 +186,12 @@ public class VideoPlayer extends FrameLayout {
|
||||
@Override
|
||||
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
|
||||
switch(playbackState) {
|
||||
case ExoPlayer.STATE_IDLE:
|
||||
case ExoPlayer.STATE_BUFFERING:
|
||||
case ExoPlayer.STATE_ENDED:
|
||||
case Player.STATE_IDLE:
|
||||
case Player.STATE_BUFFERING:
|
||||
case Player.STATE_ENDED:
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
break;
|
||||
case ExoPlayer.STATE_READY:
|
||||
case Player.STATE_READY:
|
||||
if (playWhenReady) {
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
} else {
|
||||
@@ -206,20 +202,7 @@ public class VideoPlayer extends FrameLayout {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimelineChanged(Timeline timeline, Object manifest) { }
|
||||
|
||||
@Override
|
||||
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { }
|
||||
|
||||
@Override
|
||||
public void onLoadingChanged(boolean isLoading) { }
|
||||
|
||||
@Override
|
||||
public void onPlayerError(ExoPlaybackException error) { }
|
||||
|
||||
@Override
|
||||
public void onPositionDiscontinuity() { }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -6,10 +6,12 @@ import android.net.Uri;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSource;
|
||||
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
import com.google.android.exoplayer2.upstream.TransferListener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class AttachmentDataSource implements DataSource {
|
||||
|
||||
@@ -21,6 +23,10 @@ public class AttachmentDataSource implements DataSource {
|
||||
this.defaultDataSource = defaultDataSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTransferListener(TransferListener transferListener) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long open(DataSpec dataSpec) throws IOException {
|
||||
dataSource = defaultDataSource;
|
||||
@@ -37,6 +43,11 @@ public class AttachmentDataSource implements DataSource {
|
||||
return dataSource.getUri();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getResponseHeaders() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
dataSource.close();
|
||||
|
||||
@@ -11,11 +11,11 @@ import com.google.android.exoplayer2.upstream.TransferListener;
|
||||
|
||||
public class AttachmentDataSourceFactory implements DataSource.Factory {
|
||||
|
||||
private final DefaultDataSourceFactory defaultDataSourceFactory;
|
||||
private final DefaultDataSourceFactory defaultDataSourceFactory;
|
||||
|
||||
public AttachmentDataSourceFactory(@NonNull Context context,
|
||||
@NonNull DefaultDataSourceFactory defaultDataSourceFactory,
|
||||
@Nullable TransferListener<? super DataSource> listener)
|
||||
@Nullable TransferListener listener)
|
||||
{
|
||||
this.defaultDataSourceFactory = defaultDataSourceFactory;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user