mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 17:29:32 +01:00
committed by
Greyson Parrelli
parent
d507df2e7e
commit
a6690e1bde
@@ -26,21 +26,11 @@ import android.widget.FrameLayout;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.exoplayer2.DefaultLoadControl;
|
||||
import com.google.android.exoplayer2.DefaultRenderersFactory;
|
||||
import com.google.android.exoplayer2.ExoPlayerFactory;
|
||||
import com.google.android.exoplayer2.LoadControl;
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
|
||||
import com.google.android.exoplayer2.source.ClippingMediaSource;
|
||||
import com.google.android.exoplayer2.source.ExtractorMediaSource;
|
||||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
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.TrackSelector;
|
||||
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
|
||||
import com.google.android.exoplayer2.source.MediaSourceFactory;
|
||||
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
|
||||
import com.google.android.exoplayer2.ui.PlayerControlView;
|
||||
import com.google.android.exoplayer2.ui.PlayerView;
|
||||
@@ -51,6 +41,7 @@ import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.mms.VideoSlide;
|
||||
import org.thoughtcrime.securesms.video.exo.AttachmentDataSourceFactory;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class VideoPlayer extends FrameLayout {
|
||||
@@ -87,21 +78,30 @@ public class VideoPlayer extends FrameLayout {
|
||||
this.exoControls.setShowTimeoutMs(-1);
|
||||
}
|
||||
|
||||
private CreateMediaSource createMediaSource;
|
||||
private MediaItem mediaItem;
|
||||
|
||||
public void setVideoSource(@NonNull VideoSlide videoSource, boolean autoplay) {
|
||||
Context context = getContext();
|
||||
DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(context);
|
||||
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory();
|
||||
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
|
||||
LoadControl loadControl = new DefaultLoadControl();
|
||||
Context context = getContext();
|
||||
|
||||
if (exoPlayer == null) {
|
||||
exoPlayer = ExoPlayerFactory.newSimpleInstance(context, renderersFactory, trackSelector, loadControl);
|
||||
DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(context, "GenericUserAgent", null);
|
||||
AttachmentDataSourceFactory attachmentDataSourceFactory = new AttachmentDataSourceFactory(context, defaultDataSourceFactory, null);
|
||||
MediaSourceFactory mediaSourceFactory = new DefaultMediaSourceFactory(attachmentDataSourceFactory);
|
||||
|
||||
exoPlayer = new SimpleExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build();
|
||||
exoPlayer.addListener(new ExoPlayerListener(this, window, playerStateCallback, playerPositionDiscontinuityCallback));
|
||||
exoPlayer.addListener(new Player.EventListener() {
|
||||
exoPlayer.addListener(new Player.Listener() {
|
||||
@Override
|
||||
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
|
||||
public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) {
|
||||
onPlaybackStateChanged(playWhenReady, exoPlayer.getPlaybackState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackStateChanged(int playbackState) {
|
||||
onPlaybackStateChanged(exoPlayer.getPlayWhenReady(), playbackState);
|
||||
}
|
||||
|
||||
private void onPlaybackStateChanged(boolean playWhenReady, int playbackState) {
|
||||
if (playerCallback != null) {
|
||||
switch (playbackState) {
|
||||
case Player.STATE_READY:
|
||||
@@ -118,15 +118,9 @@ public class VideoPlayer extends FrameLayout {
|
||||
exoControls.setPlayer(exoPlayer);
|
||||
}
|
||||
|
||||
DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(context, "GenericUserAgent", null);
|
||||
AttachmentDataSourceFactory attachmentDataSourceFactory = new AttachmentDataSourceFactory(context, defaultDataSourceFactory, null);
|
||||
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
|
||||
|
||||
createMediaSource = () -> new ExtractorMediaSource.Factory(attachmentDataSourceFactory)
|
||||
.setExtractorsFactory(extractorsFactory)
|
||||
.createMediaSource(videoSource.getUri());
|
||||
|
||||
exoPlayer.prepare(createMediaSource.create());
|
||||
mediaItem = MediaItem.fromUri(Objects.requireNonNull(videoSource.getUri()));
|
||||
exoPlayer.setMediaItem(mediaItem);
|
||||
exoPlayer.prepare();
|
||||
exoPlayer.setPlayWhenReady(autoplay);
|
||||
}
|
||||
|
||||
@@ -151,10 +145,7 @@ public class VideoPlayer extends FrameLayout {
|
||||
}
|
||||
|
||||
public @Nullable View getControlView() {
|
||||
if (this.exoControls != null) {
|
||||
return this.exoControls;
|
||||
}
|
||||
return null;
|
||||
return this.exoControls;
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
@@ -198,9 +189,13 @@ public class VideoPlayer extends FrameLayout {
|
||||
}
|
||||
|
||||
public void clip(long fromUs, long toUs, boolean playWhenReady) {
|
||||
if (this.exoPlayer != null && createMediaSource != null) {
|
||||
MediaSource clippedMediaSource = new ClippingMediaSource(createMediaSource.create(), fromUs, toUs);
|
||||
exoPlayer.prepare(clippedMediaSource);
|
||||
if (this.exoPlayer != null && mediaItem != null) {
|
||||
MediaItem clippedMediaItem = mediaItem.buildUpon()
|
||||
.setClipStartPositionMs(TimeUnit.MICROSECONDS.toMillis(fromUs))
|
||||
.setClipEndPositionMs(TimeUnit.MICROSECONDS.toMillis(toUs))
|
||||
.build();
|
||||
exoPlayer.setMediaItem(clippedMediaItem);
|
||||
exoPlayer.prepare();
|
||||
exoPlayer.setPlayWhenReady(playWhenReady);
|
||||
clipped = true;
|
||||
clippedStartUs = fromUs;
|
||||
@@ -208,9 +203,10 @@ public class VideoPlayer extends FrameLayout {
|
||||
}
|
||||
|
||||
public void removeClip(boolean playWhenReady) {
|
||||
if (exoPlayer != null && createMediaSource != null) {
|
||||
if (exoPlayer != null && mediaItem != null) {
|
||||
if (clipped) {
|
||||
exoPlayer.prepare(createMediaSource.create());
|
||||
exoPlayer.setMediaItem(mediaItem);
|
||||
exoPlayer.prepare();
|
||||
clipped = false;
|
||||
clippedStartUs = 0;
|
||||
}
|
||||
@@ -246,7 +242,7 @@ public class VideoPlayer extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
private static class ExoPlayerListener implements Player.EventListener {
|
||||
private static class ExoPlayerListener implements Player.Listener {
|
||||
private final VideoPlayer videoPlayer;
|
||||
private final Window window;
|
||||
private final PlayerStateCallback playerStateCallback;
|
||||
@@ -264,7 +260,16 @@ public class VideoPlayer extends FrameLayout {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
|
||||
public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) {
|
||||
onPlaybackStateChanged(playWhenReady, videoPlayer.exoPlayer.getPlaybackState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackStateChanged(int playbackState) {
|
||||
onPlaybackStateChanged(videoPlayer.exoPlayer.getPlayWhenReady(), playbackState);
|
||||
}
|
||||
|
||||
private void onPlaybackStateChanged(boolean playWhenReady, int playbackState) {
|
||||
switch (playbackState) {
|
||||
case Player.STATE_IDLE:
|
||||
case Player.STATE_BUFFERING:
|
||||
@@ -289,7 +294,10 @@ public class VideoPlayer extends FrameLayout {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPositionDiscontinuity(int reason) {
|
||||
public void onPositionDiscontinuity(@NonNull Player.PositionInfo oldPosition,
|
||||
@NonNull Player.PositionInfo newPosition,
|
||||
int reason)
|
||||
{
|
||||
if (playerPositionDiscontinuityCallback != null) {
|
||||
playerPositionDiscontinuityCallback.onPositionDiscontinuity(videoPlayer, reason);
|
||||
}
|
||||
@@ -314,8 +322,4 @@ public class VideoPlayer extends FrameLayout {
|
||||
|
||||
void onStopped();
|
||||
}
|
||||
|
||||
private interface CreateMediaSource {
|
||||
MediaSource create();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package org.thoughtcrime.securesms.video.exo;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSource;
|
||||
@@ -34,7 +36,7 @@ public class AttachmentDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTransferListener(TransferListener transferListener) {
|
||||
public void addTransferListener(@NonNull TransferListener transferListener) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -47,7 +49,7 @@ public class AttachmentDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] buffer, int offset, int readLength) throws IOException {
|
||||
public int read(@NonNull byte[] buffer, int offset, int readLength) throws IOException {
|
||||
return dataSource.read(buffer, offset, readLength);
|
||||
}
|
||||
|
||||
@@ -57,7 +59,7 @@ public class AttachmentDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getResponseHeaders() {
|
||||
public @NonNull Map<String, List<String>> getResponseHeaders() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ public class AttachmentDataSourceFactory implements DataSource.Factory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttachmentDataSource createDataSource() {
|
||||
public @NonNull AttachmentDataSource createDataSource() {
|
||||
return new AttachmentDataSource(defaultDataSourceFactory.createDataSource(),
|
||||
new PartDataSource(context, listener),
|
||||
new BlobDataSource(context, listener));
|
||||
|
||||
@@ -5,27 +5,38 @@ import android.net.Uri;
|
||||
import android.support.v4.media.MediaDescriptionCompat;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||
import com.google.android.exoplayer2.drm.DrmSessionManagerProvider;
|
||||
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.offline.StreamKey;
|
||||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
import com.google.android.exoplayer2.source.MediaSourceFactory;
|
||||
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class is responsible for creating a MediaSource object for a given Uri, using AttachmentDataSourceFactory
|
||||
*/
|
||||
public final class AttachmentMediaSourceFactory {
|
||||
@SuppressWarnings("deprecation")
|
||||
public final class AttachmentMediaSourceFactory implements MediaSourceFactory {
|
||||
|
||||
private final ExtractorMediaSource.Factory extractorMediaSourceFactory;
|
||||
private final ProgressiveMediaSource.Factory progressiveMediaSourceFactory;
|
||||
|
||||
public AttachmentMediaSourceFactory(@NonNull Context context) {
|
||||
DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(context, "GenericUserAgent", null);
|
||||
AttachmentDataSourceFactory attachmentDataSourceFactory = new AttachmentDataSourceFactory(context, defaultDataSourceFactory, null);
|
||||
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true);
|
||||
|
||||
extractorMediaSourceFactory = new ExtractorMediaSource.Factory(attachmentDataSourceFactory)
|
||||
.setExtractorsFactory(extractorsFactory);
|
||||
progressiveMediaSourceFactory = new ProgressiveMediaSource.Factory(attachmentDataSourceFactory, extractorsFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,13 +47,53 @@ public final class AttachmentMediaSourceFactory {
|
||||
* @return A preparable MediaSource
|
||||
*/
|
||||
public @NonNull MediaSource createMediaSource(MediaDescriptionCompat description) {
|
||||
return createMediaSource(description.getMediaUri());
|
||||
return progressiveMediaSourceFactory.createMediaSource(
|
||||
new MediaItem.Builder().setUri(description.getMediaUri()).setTag(description).build()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MediaSource for a given Uri
|
||||
*/
|
||||
public @NonNull MediaSource createMediaSource(Uri uri) {
|
||||
return extractorMediaSourceFactory.createMediaSource(uri);
|
||||
@Override
|
||||
public MediaSourceFactory setStreamKeys(@Nullable List<StreamKey> streamKeys) {
|
||||
return progressiveMediaSourceFactory.setStreamKeys(streamKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaSourceFactory setDrmSessionManagerProvider(@Nullable DrmSessionManagerProvider drmSessionManagerProvider) {
|
||||
return progressiveMediaSourceFactory.setDrmSessionManagerProvider(drmSessionManagerProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaSourceFactory setDrmSessionManager(@Nullable DrmSessionManager drmSessionManager) {
|
||||
return progressiveMediaSourceFactory.setDrmSessionManager(drmSessionManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaSourceFactory setDrmHttpDataSourceFactory(@Nullable HttpDataSource.Factory drmHttpDataSourceFactory) {
|
||||
return progressiveMediaSourceFactory.setDrmHttpDataSourceFactory(drmHttpDataSourceFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaSourceFactory setDrmUserAgent(@Nullable String userAgent) {
|
||||
return progressiveMediaSourceFactory.setDrmUserAgent(userAgent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaSourceFactory setLoadErrorHandlingPolicy(@Nullable LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
|
||||
return progressiveMediaSourceFactory.setLoadErrorHandlingPolicy(loadErrorHandlingPolicy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getSupportedTypes() {
|
||||
return new int[] { C.TYPE_OTHER };
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaSource createMediaSource(MediaItem mediaItem) {
|
||||
return progressiveMediaSourceFactory.createMediaSource(mediaItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaSource createMediaSource(Uri uri) {
|
||||
return progressiveMediaSourceFactory.createMediaSource(uri);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ public class BlobDataSource implements DataSource {
|
||||
private final @NonNull Context context;
|
||||
private final @Nullable TransferListener listener;
|
||||
|
||||
private Uri uri;
|
||||
private DataSpec dataSpec;
|
||||
private InputStream inputStream;
|
||||
|
||||
BlobDataSource(@NonNull Context context, @Nullable TransferListener listener) {
|
||||
@@ -34,21 +34,21 @@ public class BlobDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTransferListener(TransferListener transferListener) {
|
||||
public void addTransferListener(@NonNull TransferListener transferListener) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long open(DataSpec dataSpec) throws IOException {
|
||||
this.uri = dataSpec.uri;
|
||||
this.inputStream = BlobProvider.getInstance().getStream(context, uri, dataSpec.position);
|
||||
this.dataSpec = dataSpec;
|
||||
this.inputStream = BlobProvider.getInstance().getStream(context, dataSpec.uri, dataSpec.position);
|
||||
|
||||
if (listener != null) {
|
||||
listener.onTransferStart(this, dataSpec, false);
|
||||
}
|
||||
|
||||
long size = unwrapLong(BlobProvider.getFileSize(uri));
|
||||
long size = unwrapLong(BlobProvider.getFileSize(dataSpec.uri));
|
||||
if (size == 0) {
|
||||
size = BlobProvider.getInstance().calculateFileSize(context, uri);
|
||||
size = BlobProvider.getInstance().calculateFileSize(context, dataSpec.uri);
|
||||
}
|
||||
|
||||
if (size - dataSpec.position <= 0) throw new EOFException("No more data");
|
||||
@@ -61,11 +61,11 @@ public class BlobDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] buffer, int offset, int readLength) throws IOException {
|
||||
public int read(@NonNull byte[] buffer, int offset, int readLength) throws IOException {
|
||||
int read = inputStream.read(buffer, offset, readLength);
|
||||
|
||||
if (read > 0 && listener != null) {
|
||||
listener.onBytesTransferred(this, null, false, read);
|
||||
listener.onBytesTransferred(this, dataSpec, false, read);
|
||||
}
|
||||
|
||||
return read;
|
||||
@@ -73,11 +73,11 @@ public class BlobDataSource implements DataSource {
|
||||
|
||||
@Override
|
||||
public Uri getUri() {
|
||||
return uri;
|
||||
return dataSpec.uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getResponseHeaders() {
|
||||
public @NonNull Map<String, List<String>> getResponseHeaders() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ public class ChunkedDataSource implements DataSource {
|
||||
private final OkHttpClient okHttpClient;
|
||||
private final TransferListener transferListener;
|
||||
|
||||
private Uri uri;
|
||||
private DataSpec dataSpec;
|
||||
private volatile InputStream inputStream;
|
||||
private volatile Exception exception;
|
||||
|
||||
@@ -38,12 +38,12 @@ public class ChunkedDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTransferListener(TransferListener transferListener) {
|
||||
public void addTransferListener(@NonNull TransferListener transferListener) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long open(DataSpec dataSpec) throws IOException {
|
||||
this.uri = dataSpec.uri;
|
||||
public long open(@NonNull DataSpec dataSpec) throws IOException {
|
||||
this.dataSpec = dataSpec;
|
||||
this.exception = null;
|
||||
|
||||
if (inputStream != null) {
|
||||
@@ -55,7 +55,7 @@ public class ChunkedDataSource implements DataSource {
|
||||
CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
ChunkedDataFetcher fetcher = new ChunkedDataFetcher(okHttpClient);
|
||||
|
||||
fetcher.fetch(this.uri.toString(), dataSpec.length, new ChunkedDataFetcher.Callback() {
|
||||
fetcher.fetch(this.dataSpec.uri.toString(), dataSpec.length, new ChunkedDataFetcher.Callback() {
|
||||
@Override
|
||||
public void onSuccess(InputStream stream) {
|
||||
inputStream = stream;
|
||||
@@ -87,7 +87,7 @@ public class ChunkedDataSource implements DataSource {
|
||||
transferListener.onTransferStart(this, dataSpec, false);
|
||||
}
|
||||
|
||||
if ( dataSpec.length != C.LENGTH_UNSET && dataSpec.length - dataSpec.position <= 0) {
|
||||
if (dataSpec.length != C.LENGTH_UNSET && dataSpec.length - dataSpec.position <= 0) {
|
||||
throw new EOFException("No more data");
|
||||
}
|
||||
|
||||
@@ -95,11 +95,11 @@ public class ChunkedDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] buffer, int offset, int readLength) throws IOException {
|
||||
public int read(@NonNull byte[] buffer, int offset, int readLength) throws IOException {
|
||||
int read = inputStream.read(buffer, offset, readLength);
|
||||
|
||||
if (read > 0 && transferListener != null) {
|
||||
transferListener.onBytesTransferred(this, null, false, read);
|
||||
transferListener.onBytesTransferred(this, dataSpec, false, read);
|
||||
}
|
||||
|
||||
return read;
|
||||
@@ -107,7 +107,7 @@ public class ChunkedDataSource implements DataSource {
|
||||
|
||||
@Override
|
||||
public @Nullable Uri getUri() {
|
||||
return uri;
|
||||
return dataSpec.uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,7 +20,7 @@ public class ChunkedDataSourceFactory implements DataSource.Factory {
|
||||
|
||||
|
||||
@Override
|
||||
public DataSource createDataSource() {
|
||||
public @NonNull DataSource createDataSource() {
|
||||
return new ChunkedDataSource(okHttpClient, listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class PartDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTransferListener(TransferListener transferListener) {
|
||||
public void addTransferListener(@NonNull TransferListener transferListener) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,7 +62,7 @@ public class PartDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] buffer, int offset, int readLength) throws IOException {
|
||||
public int read(@NonNull byte[] buffer, int offset, int readLength) throws IOException {
|
||||
int read = inputSteam.read(buffer, offset, readLength);
|
||||
|
||||
if (read > 0 && listener != null) {
|
||||
@@ -78,7 +78,7 @@ public class PartDataSource implements DataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getResponseHeaders() {
|
||||
public @NonNull Map<String, List<String>> getResponseHeaders() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user