Merge pull request #3499 from ByteHamster/local-playable-improvements
Local playable improvements
This commit is contained in:
commit
935e2ceee0
|
@ -11,6 +11,7 @@ import android.graphics.Color;
|
|||
import android.graphics.PixelFormat;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.app.ActivityOptionsCompat;
|
||||
|
@ -76,7 +77,8 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
private static final String TAG = "MediaplayerActivity";
|
||||
private static final String PREFS = "MediaPlayerActivityPreferences";
|
||||
private static final String PREF_SHOW_TIME_LEFT = "showTimeLeft";
|
||||
private static final int REQUEST_CODE_STORAGE = 42;
|
||||
private static final int REQUEST_CODE_STORAGE_PLAY_VIDEO = 42;
|
||||
private static final int REQUEST_CODE_STORAGE_PLAY_AUDIO = 43;
|
||||
|
||||
PlaybackController controller;
|
||||
|
||||
|
@ -855,10 +857,13 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
|
||||
Toast.makeText(this, R.string.needs_storage_permission, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
|
||||
REQUEST_CODE_STORAGE);
|
||||
}
|
||||
|
||||
int code = REQUEST_CODE_STORAGE_PLAY_AUDIO;
|
||||
if (type == MediaType.VIDEO) {
|
||||
code = REQUEST_CODE_STORAGE_PLAY_VIDEO;
|
||||
}
|
||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, code);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -866,6 +871,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
ExternalMedia media = new ExternalMedia(intent.getData().getPath(), type);
|
||||
|
||||
new PlaybackServiceStarter(this, media)
|
||||
.callEvenIfRunning(true)
|
||||
.startWhenPrepared(true)
|
||||
.shouldStream(false)
|
||||
.prepareImmediately(true)
|
||||
|
@ -873,18 +879,22 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
if (requestCode == REQUEST_CODE_STORAGE) {
|
||||
if (grantResults.length <= 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
|
||||
Toast.makeText(this, R.string.needs_storage_permission, Toast.LENGTH_LONG).show();
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, int[] grantResults) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
if (requestCode == REQUEST_CODE_STORAGE_PLAY_AUDIO) {
|
||||
playExternalMedia(getIntent(), MediaType.AUDIO);
|
||||
} else if (requestCode == REQUEST_CODE_STORAGE_PLAY_VIDEO) {
|
||||
playExternalMedia(getIntent(), MediaType.VIDEO);
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(this, R.string.needs_storage_permission, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static FeedItem getFeedItem(@Nullable Playable playable) {
|
||||
if ((playable != null) && (playable instanceof FeedMedia)) {
|
||||
return ((FeedMedia)playable).getItem();
|
||||
if (playable instanceof FeedMedia) {
|
||||
return ((FeedMedia) playable).getItem();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -6,245 +6,252 @@ import android.content.SharedPreferences.Editor;
|
|||
import android.media.MediaMetadataRetriever;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Chapter;
|
||||
import de.danoeh.antennapod.core.feed.MediaType;
|
||||
import de.danoeh.antennapod.core.util.ChapterUtils;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
/** Represents a media file that is stored on the local storage device. */
|
||||
public class ExternalMedia implements Playable {
|
||||
public static final int PLAYABLE_TYPE_EXTERNAL_MEDIA = 2;
|
||||
public static final String PREF_SOURCE_URL = "ExternalMedia.PrefSourceUrl";
|
||||
public static final String PREF_POSITION = "ExternalMedia.PrefPosition";
|
||||
public static final String PREF_MEDIA_TYPE = "ExternalMedia.PrefMediaType";
|
||||
public static final String PREF_LAST_PLAYED_TIME = "ExternalMedia.PrefLastPlayedTime";
|
||||
|
||||
public static final int PLAYABLE_TYPE_EXTERNAL_MEDIA = 2;
|
||||
public static final String PREF_SOURCE_URL = "ExternalMedia.PrefSourceUrl";
|
||||
public static final String PREF_POSITION = "ExternalMedia.PrefPosition";
|
||||
public static final String PREF_MEDIA_TYPE = "ExternalMedia.PrefMediaType";
|
||||
public static final String PREF_LAST_PLAYED_TIME = "ExternalMedia.PrefLastPlayedTime";
|
||||
private final String source;
|
||||
private String episodeTitle;
|
||||
private String feedTitle;
|
||||
private MediaType mediaType;
|
||||
private List<Chapter> chapters;
|
||||
private int duration;
|
||||
private int position;
|
||||
private long lastPlayedTime;
|
||||
|
||||
private final String source;
|
||||
/**
|
||||
* Creates a new playable for files on the sd card.
|
||||
* @param source File path of the file
|
||||
* @param mediaType Type of the file
|
||||
*/
|
||||
public ExternalMedia(String source, MediaType mediaType) {
|
||||
super();
|
||||
this.source = source;
|
||||
this.mediaType = mediaType;
|
||||
}
|
||||
|
||||
private String episodeTitle;
|
||||
private String feedTitle;
|
||||
private MediaType mediaType = MediaType.AUDIO;
|
||||
private List<Chapter> chapters;
|
||||
private int duration;
|
||||
private int position;
|
||||
private long lastPlayedTime;
|
||||
/**
|
||||
* Creates a new playable for files on the sd card.
|
||||
* @param source File path of the file
|
||||
* @param mediaType Type of the file
|
||||
* @param position Position to start from
|
||||
* @param lastPlayedTime Timestamp when it was played last
|
||||
*/
|
||||
public ExternalMedia(String source, MediaType mediaType, int position, long lastPlayedTime) {
|
||||
this(source, mediaType);
|
||||
this.position = position;
|
||||
this.lastPlayedTime = lastPlayedTime;
|
||||
}
|
||||
|
||||
public ExternalMedia(String source, MediaType mediaType) {
|
||||
super();
|
||||
this.source = source;
|
||||
this.mediaType = mediaType;
|
||||
}
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public ExternalMedia(String source, MediaType mediaType, int position, long lastPlayedTime) {
|
||||
this(source, mediaType);
|
||||
this.position = position;
|
||||
this.lastPlayedTime = lastPlayedTime;
|
||||
}
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(source);
|
||||
dest.writeString(mediaType.toString());
|
||||
dest.writeInt(position);
|
||||
dest.writeLong(lastPlayedTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public void writeToPreferences(Editor prefEditor) {
|
||||
prefEditor.putString(PREF_SOURCE_URL, source);
|
||||
prefEditor.putString(PREF_MEDIA_TYPE, mediaType.toString());
|
||||
prefEditor.putInt(PREF_POSITION, position);
|
||||
prefEditor.putLong(PREF_LAST_PLAYED_TIME, lastPlayedTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(source);
|
||||
dest.writeString(mediaType.toString());
|
||||
dest.writeInt(position);
|
||||
dest.writeLong(lastPlayedTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToPreferences(Editor prefEditor) {
|
||||
prefEditor.putString(PREF_SOURCE_URL, source);
|
||||
prefEditor.putString(PREF_MEDIA_TYPE, mediaType.toString());
|
||||
prefEditor.putInt(PREF_POSITION, position);
|
||||
prefEditor.putLong(PREF_LAST_PLAYED_TIME, lastPlayedTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadMetadata() throws PlayableException {
|
||||
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
|
||||
try {
|
||||
mmr.setDataSource(source);
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
throw new PlayableException(
|
||||
"IllegalArgumentException when setting up MediaMetadataReceiver");
|
||||
} catch (RuntimeException e) {
|
||||
// http://code.google.com/p/android/issues/detail?id=39770
|
||||
e.printStackTrace();
|
||||
throw new PlayableException(
|
||||
"RuntimeException when setting up MediaMetadataRetriever");
|
||||
}
|
||||
episodeTitle = mmr
|
||||
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
|
||||
feedTitle = mmr
|
||||
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
|
||||
@Override
|
||||
public void loadMetadata() throws PlayableException {
|
||||
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
|
||||
try {
|
||||
duration = Integer.parseInt(mmr
|
||||
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
|
||||
mmr.setDataSource(source);
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
throw new PlayableException("IllegalArgumentException when setting up MediaMetadataReceiver");
|
||||
} catch (RuntimeException e) {
|
||||
// http://code.google.com/p/android/issues/detail?id=39770
|
||||
e.printStackTrace();
|
||||
throw new PlayableException("RuntimeException when setting up MediaMetadataRetriever");
|
||||
}
|
||||
episodeTitle = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
|
||||
if (episodeTitle == null) {
|
||||
episodeTitle = FilenameUtils.getName(source);
|
||||
}
|
||||
feedTitle = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
|
||||
try {
|
||||
duration = Integer.parseInt(mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
|
||||
} catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
throw new PlayableException("NumberFormatException when reading duration of media file");
|
||||
}
|
||||
ChapterUtils.loadChaptersFromFileUrl(this);
|
||||
}
|
||||
ChapterUtils.loadChaptersFromFileUrl(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadChapterMarks() {
|
||||
@Override
|
||||
public void loadChapterMarks() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEpisodeTitle() {
|
||||
return episodeTitle;
|
||||
}
|
||||
@Override
|
||||
public String getEpisodeTitle() {
|
||||
return episodeTitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Callable<String> loadShownotes() {
|
||||
return () -> "";
|
||||
}
|
||||
@Override
|
||||
public Callable<String> loadShownotes() {
|
||||
return () -> "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Chapter> getChapters() {
|
||||
return chapters;
|
||||
}
|
||||
@Override
|
||||
public List<Chapter> getChapters() {
|
||||
return chapters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWebsiteLink() {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public String getWebsiteLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPaymentLink() {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public String getPaymentLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFeedTitle() {
|
||||
return feedTitle;
|
||||
}
|
||||
@Override
|
||||
public String getFeedTitle() {
|
||||
return feedTitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdentifier() {
|
||||
return source;
|
||||
}
|
||||
@Override
|
||||
public Object getIdentifier() {
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDuration() {
|
||||
return duration;
|
||||
}
|
||||
@Override
|
||||
public int getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
@Override
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastPlayedTime() {
|
||||
return lastPlayedTime;
|
||||
}
|
||||
@Override
|
||||
public long getLastPlayedTime() {
|
||||
return lastPlayedTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaType getMediaType() {
|
||||
return mediaType;
|
||||
}
|
||||
@Override
|
||||
public MediaType getMediaType() {
|
||||
return mediaType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalMediaUrl() {
|
||||
return source;
|
||||
}
|
||||
@Override
|
||||
public String getLocalMediaUrl() {
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStreamUrl() {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public String getStreamUrl() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean localFileAvailable() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean localFileAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean streamAvailable() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean streamAvailable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveCurrentPosition(SharedPreferences pref, int newPosition, long timestamp) {
|
||||
SharedPreferences.Editor editor = pref.edit();
|
||||
editor.putInt(PREF_POSITION, newPosition);
|
||||
editor.putLong(PREF_LAST_PLAYED_TIME, timestamp);
|
||||
position = newPosition;
|
||||
lastPlayedTime = timestamp;
|
||||
editor.apply();
|
||||
}
|
||||
@Override
|
||||
public void saveCurrentPosition(SharedPreferences pref, int newPosition, long timestamp) {
|
||||
SharedPreferences.Editor editor = pref.edit();
|
||||
editor.putInt(PREF_POSITION, newPosition);
|
||||
editor.putLong(PREF_LAST_PLAYED_TIME, timestamp);
|
||||
position = newPosition;
|
||||
lastPlayedTime = timestamp;
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(int newPosition) {
|
||||
position = newPosition;
|
||||
}
|
||||
@Override
|
||||
public void setPosition(int newPosition) {
|
||||
position = newPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDuration(int newDuration) {
|
||||
duration = newDuration;
|
||||
}
|
||||
@Override
|
||||
public void setDuration(int newDuration) {
|
||||
duration = newDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastPlayedTime(long lastPlayedTime) {
|
||||
this.lastPlayedTime = lastPlayedTime;
|
||||
}
|
||||
@Override
|
||||
public void setLastPlayedTime(long lastPlayedTime) {
|
||||
this.lastPlayedTime = lastPlayedTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackStart() {
|
||||
@Override
|
||||
public void onPlaybackStart() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackPause(Context context) {
|
||||
@Override
|
||||
public void onPlaybackPause(Context context) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackCompleted(Context context) {
|
||||
@Override
|
||||
public void onPlaybackCompleted(Context context) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayableType() {
|
||||
return PLAYABLE_TYPE_EXTERNAL_MEDIA;
|
||||
}
|
||||
@Override
|
||||
public int getPlayableType() {
|
||||
return PLAYABLE_TYPE_EXTERNAL_MEDIA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChapters(List<Chapter> chapters) {
|
||||
this.chapters = chapters;
|
||||
}
|
||||
@Override
|
||||
public void setChapters(List<Chapter> chapters) {
|
||||
this.chapters = chapters;
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<ExternalMedia> CREATOR = new Parcelable.Creator<ExternalMedia>() {
|
||||
public ExternalMedia createFromParcel(Parcel in) {
|
||||
String source = in.readString();
|
||||
MediaType type = MediaType.valueOf(in.readString());
|
||||
int position = 0;
|
||||
if (in.dataAvail() > 0) {
|
||||
position = in.readInt();
|
||||
}
|
||||
long lastPlayedTime = 0;
|
||||
if (in.dataAvail() > 0) {
|
||||
lastPlayedTime = in.readLong();
|
||||
}
|
||||
public static final Parcelable.Creator<ExternalMedia> CREATOR = new Parcelable.Creator<ExternalMedia>() {
|
||||
public ExternalMedia createFromParcel(Parcel in) {
|
||||
String source = in.readString();
|
||||
MediaType type = MediaType.valueOf(in.readString());
|
||||
int position = 0;
|
||||
if (in.dataAvail() > 0) {
|
||||
position = in.readInt();
|
||||
}
|
||||
long lastPlayedTime = 0;
|
||||
if (in.dataAvail() > 0) {
|
||||
lastPlayedTime = in.readLong();
|
||||
}
|
||||
|
||||
return new ExternalMedia(source, type, position, lastPlayedTime);
|
||||
}
|
||||
return new ExternalMedia(source, type, position, lastPlayedTime);
|
||||
}
|
||||
|
||||
public ExternalMedia[] newArray(int size) {
|
||||
return new ExternalMedia[size];
|
||||
}
|
||||
};
|
||||
public ExternalMedia[] newArray(int size) {
|
||||
return new ExternalMedia[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public String getImageLocation() {
|
||||
|
|
Loading…
Reference in New Issue