Added support for playing local external media files
This commit is contained in:
parent
cc741d6643
commit
dcbf334bad
|
@ -74,7 +74,17 @@
|
||||||
android:name=".activity.AudioplayerActivity"
|
android:name=".activity.AudioplayerActivity"
|
||||||
android:configChanges="keyboardHidden|orientation"
|
android:configChanges="keyboardHidden|orientation"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:screenOrientation="portrait" android:label=" "/>
|
android:screenOrientation="portrait" >
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data android:scheme="file" />
|
||||||
|
<data android:mimeType="audio/*" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".service.download.DownloadService"
|
android:name=".service.download.DownloadService"
|
||||||
|
@ -323,7 +333,11 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.DirectoryChooserActivity"
|
android:name=".activity.DirectoryChooserActivity"
|
||||||
android:label="@string/choose_data_directory" />
|
android:label="@string/choose_data_directory" />
|
||||||
<activity android:label="@string/organize_queue_label" android:name=".activity.OrganizeQueueActivity" android:configChanges="orientation"></activity>
|
<activity
|
||||||
|
android:name=".activity.OrganizeQueueActivity"
|
||||||
|
android:configChanges="orientation"
|
||||||
|
android:label="@string/organize_queue_label" >
|
||||||
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
|
@ -1,5 +1,7 @@
|
||||||
package de.danoeh.antennapod.activity;
|
package de.danoeh.antennapod.activity;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -22,10 +24,12 @@ import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.adapter.ChapterListAdapter;
|
import de.danoeh.antennapod.adapter.ChapterListAdapter;
|
||||||
import de.danoeh.antennapod.asynctask.ImageLoader;
|
import de.danoeh.antennapod.asynctask.ImageLoader;
|
||||||
import de.danoeh.antennapod.feed.Chapter;
|
import de.danoeh.antennapod.feed.Chapter;
|
||||||
|
import de.danoeh.antennapod.feed.MediaType;
|
||||||
import de.danoeh.antennapod.feed.SimpleChapter;
|
import de.danoeh.antennapod.feed.SimpleChapter;
|
||||||
import de.danoeh.antennapod.fragment.CoverFragment;
|
import de.danoeh.antennapod.fragment.CoverFragment;
|
||||||
import de.danoeh.antennapod.fragment.ItemDescriptionFragment;
|
import de.danoeh.antennapod.fragment.ItemDescriptionFragment;
|
||||||
import de.danoeh.antennapod.service.PlaybackService;
|
import de.danoeh.antennapod.service.PlaybackService;
|
||||||
|
import de.danoeh.antennapod.util.playback.ExternalMedia;
|
||||||
import de.danoeh.antennapod.util.playback.Playable;
|
import de.danoeh.antennapod.util.playback.Playable;
|
||||||
|
|
||||||
/** Activity for playing audio files. */
|
/** Activity for playing audio files. */
|
||||||
|
@ -71,9 +75,31 @@ public class AudioplayerActivity extends MediaplayerActivity {
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
getSupportActionBar().setDisplayShowTitleEnabled(false);
|
||||||
detachedFragments = new Fragment[NUM_CONTENT_FRAGMENTS];
|
detachedFragments = new Fragment[NUM_CONTENT_FRAGMENTS];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (getIntent().getAction() != null
|
||||||
|
&& getIntent().getAction().equals(Intent.ACTION_VIEW)) {
|
||||||
|
Intent intent = getIntent();
|
||||||
|
if (AppConfig.DEBUG)
|
||||||
|
Log.d(TAG, "Received VIEW intent: "
|
||||||
|
+ intent.getData().getPath());
|
||||||
|
ExternalMedia media = new ExternalMedia(intent.getData().getPath(), MediaType.AUDIO);
|
||||||
|
Intent launchIntent = new Intent(this, PlaybackService.class);
|
||||||
|
launchIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media);
|
||||||
|
launchIntent.putExtra(PlaybackService.EXTRA_START_WHEN_PREPARED,
|
||||||
|
true);
|
||||||
|
launchIntent.putExtra(PlaybackService.EXTRA_SHOULD_STREAM, false);
|
||||||
|
launchIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY,
|
||||||
|
true);
|
||||||
|
startService(launchIntent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onAwaitingVideoSurface() {
|
protected void onAwaitingVideoSurface() {
|
||||||
startActivity(new Intent(this, VideoplayerActivity.class));
|
startActivity(new Intent(this, VideoplayerActivity.class));
|
||||||
|
@ -193,8 +219,7 @@ public class AudioplayerActivity extends MediaplayerActivity {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
ImageLoader.getInstance().loadThumbnailBitmap(
|
ImageLoader.getInstance().loadThumbnailBitmap(
|
||||||
media.getImageFileUrl(),
|
media.getImageFileUrl(), butNavLeft);
|
||||||
butNavLeft);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
butNavRight.setImageDrawable(drawables.getDrawable(0));
|
butNavRight.setImageDrawable(drawables.getDrawable(0));
|
||||||
|
|
|
@ -238,78 +238,79 @@ public abstract class MediaplayerActivity extends SherlockFragmentActivity
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
Playable media = controller.getMedia();
|
Playable media = controller.getMedia();
|
||||||
if (media == null) {
|
if (item.getItemId() == android.R.id.home) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case android.R.id.home:
|
|
||||||
Intent intent = new Intent(MediaplayerActivity.this,
|
Intent intent = new Intent(MediaplayerActivity.this,
|
||||||
MainActivity.class);
|
MainActivity.class);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||||
| Intent.FLAG_ACTIVITY_NEW_TASK);
|
| Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
break;
|
return true;
|
||||||
case R.id.disable_sleeptimer_item:
|
} else if (media != null) {
|
||||||
if (controller.serviceAvailable()) {
|
switch (item.getItemId()) {
|
||||||
AlertDialog.Builder stDialog = new AlertDialog.Builder(this);
|
case R.id.disable_sleeptimer_item:
|
||||||
stDialog.setTitle(R.string.sleep_timer_label);
|
if (controller.serviceAvailable()) {
|
||||||
stDialog.setMessage(getString(R.string.time_left_label)
|
AlertDialog.Builder stDialog = new AlertDialog.Builder(this);
|
||||||
+ Converter.getDurationStringLong((int) controller
|
stDialog.setTitle(R.string.sleep_timer_label);
|
||||||
.getSleepTimerTimeLeft()));
|
stDialog.setMessage(getString(R.string.time_left_label)
|
||||||
stDialog.setPositiveButton(R.string.disable_sleeptimer_label,
|
+ Converter.getDurationStringLong((int) controller
|
||||||
new DialogInterface.OnClickListener() {
|
.getSleepTimerTimeLeft()));
|
||||||
|
stDialog.setPositiveButton(
|
||||||
|
R.string.disable_sleeptimer_label,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog,
|
public void onClick(DialogInterface dialog,
|
||||||
int which) {
|
int which) {
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
controller.disableSleepTimer();
|
controller.disableSleepTimer();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
stDialog.setNegativeButton(R.string.cancel_label,
|
stDialog.setNegativeButton(R.string.cancel_label,
|
||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog,
|
public void onClick(DialogInterface dialog,
|
||||||
int which) {
|
int which) {
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
stDialog.create().show();
|
stDialog.create().show();
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case R.id.set_sleeptimer_item:
|
|
||||||
if (controller.serviceAvailable()) {
|
|
||||||
TimeDialog td = new TimeDialog(this,
|
|
||||||
R.string.set_sleeptimer_label,
|
|
||||||
R.string.set_sleeptimer_label) {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTimeEntered(long millis) {
|
|
||||||
controller.setSleepTimer(millis);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
td.show();
|
|
||||||
break;
|
break;
|
||||||
|
case R.id.set_sleeptimer_item:
|
||||||
|
if (controller.serviceAvailable()) {
|
||||||
|
TimeDialog td = new TimeDialog(this,
|
||||||
|
R.string.set_sleeptimer_label,
|
||||||
|
R.string.set_sleeptimer_label) {
|
||||||
|
|
||||||
}
|
@Override
|
||||||
case R.id.visit_website_item:
|
public void onTimeEntered(long millis) {
|
||||||
Uri uri = Uri.parse(media.getWebsiteLink());
|
controller.setSleepTimer(millis);
|
||||||
startActivity(new Intent(Intent.ACTION_VIEW, uri));
|
}
|
||||||
break;
|
};
|
||||||
case R.id.support_item:
|
td.show();
|
||||||
new FlattrClickWorker(this, media.getPaymentLink())
|
break;
|
||||||
.executeAsync();
|
|
||||||
break;
|
}
|
||||||
case R.id.share_link_item:
|
case R.id.visit_website_item:
|
||||||
ShareUtils.shareLink(this, media.getWebsiteLink());
|
Uri uri = Uri.parse(media.getWebsiteLink());
|
||||||
break;
|
startActivity(new Intent(Intent.ACTION_VIEW, uri));
|
||||||
|
break;
|
||||||
|
case R.id.support_item:
|
||||||
|
new FlattrClickWorker(this, media.getPaymentLink())
|
||||||
|
.executeAsync();
|
||||||
|
break;
|
||||||
|
case R.id.share_link_item:
|
||||||
|
ShareUtils.shareLink(this, media.getWebsiteLink());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -187,7 +187,7 @@ public class FeedMedia extends FeedFile implements Playable {
|
||||||
@Override
|
@Override
|
||||||
public void loadMetadata() throws PlayableException {
|
public void loadMetadata() throws PlayableException {
|
||||||
if (getChapters() == null) {
|
if (getChapters() == null) {
|
||||||
ChapterUtils.loadChapters(this);
|
ChapterUtils.loadChaptersFromStreamUrl(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,8 +185,7 @@ public class PlaybackService extends Service {
|
||||||
* Same as getPlayerActivityIntent(context), but here the type of activity
|
* Same as getPlayerActivityIntent(context), but here the type of activity
|
||||||
* depends on the FeedMedia that is provided as an argument.
|
* depends on the FeedMedia that is provided as an argument.
|
||||||
*/
|
*/
|
||||||
public static Intent getPlayerActivityIntent(Context context,
|
public static Intent getPlayerActivityIntent(Context context, Playable media) {
|
||||||
Playable media) {
|
|
||||||
MediaType mt = media.getMediaType();
|
MediaType mt = media.getMediaType();
|
||||||
if (mt == MediaType.VIDEO) {
|
if (mt == MediaType.VIDEO) {
|
||||||
return new Intent(context, VideoplayerActivity.class);
|
return new Intent(context, VideoplayerActivity.class);
|
||||||
|
@ -539,17 +538,23 @@ public class PlaybackService extends Service {
|
||||||
} else if (media.localFileAvailable()) {
|
} else if (media.localFileAvailable()) {
|
||||||
player.setDataSource(media.getFileUrl());
|
player.setDataSource(media.getFileUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prepareImmediately) {
|
||||||
|
setStatus(PlayerStatus.PREPARING);
|
||||||
|
player.prepareAsync();
|
||||||
|
} else {
|
||||||
|
setStatus(PlayerStatus.INITIALIZED);
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
media = null;
|
||||||
if (prepareImmediately) {
|
setStatus(PlayerStatus.ERROR);
|
||||||
setStatus(PlayerStatus.PREPARING);
|
sendBroadcast(new Intent(
|
||||||
player.prepareAsync();
|
ACTION_SHUTDOWN_PLAYBACK_SERVICE));
|
||||||
} else {
|
|
||||||
setStatus(PlayerStatus.INITIALIZED);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "InitTask could not load metadata");
|
Log.e(TAG, "InitTask could not load metadata");
|
||||||
|
media = null;
|
||||||
setStatus(PlayerStatus.ERROR);
|
setStatus(PlayerStatus.ERROR);
|
||||||
sendBroadcast(new Intent(
|
sendBroadcast(new Intent(
|
||||||
ACTION_SHUTDOWN_PLAYBACK_SERVICE));
|
ACTION_SHUTDOWN_PLAYBACK_SERVICE));
|
||||||
|
@ -801,7 +806,11 @@ public class PlaybackService extends Service {
|
||||||
public void stop() {
|
public void stop() {
|
||||||
if (AppConfig.DEBUG)
|
if (AppConfig.DEBUG)
|
||||||
Log.d(TAG, "Stopping playback");
|
Log.d(TAG, "Stopping playback");
|
||||||
player.stop();
|
if (status == PlayerStatus.PREPARED || status == PlayerStatus.PAUSED
|
||||||
|
|| status == PlayerStatus.STOPPED
|
||||||
|
|| status == PlayerStatus.PLAYING) {
|
||||||
|
player.stop();
|
||||||
|
}
|
||||||
setCurrentlyPlayingMedia(PlaybackPreferences.NO_MEDIA_PLAYING);
|
setCurrentlyPlayingMedia(PlaybackPreferences.NO_MEDIA_PLAYING);
|
||||||
stopSelf();
|
stopSelf();
|
||||||
}
|
}
|
||||||
|
@ -1346,7 +1355,7 @@ public class PlaybackService extends Service {
|
||||||
throw new IllegalArgumentException("Playable must not be null");
|
throw new IllegalArgumentException("Playable must not be null");
|
||||||
}
|
}
|
||||||
playable = params[0];
|
playable = params[0];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
playable.loadMetadata();
|
playable.loadMetadata();
|
||||||
} catch (PlayableException e) {
|
} catch (PlayableException e) {
|
||||||
|
|
|
@ -83,7 +83,7 @@ public class PlayerWidgetService extends Service {
|
||||||
PlaybackService.getPlayerActivityIntent(this), 0);
|
PlaybackService.getPlayerActivityIntent(this), 0);
|
||||||
|
|
||||||
views.setOnClickPendingIntent(R.id.layout_left, startMediaplayer);
|
views.setOnClickPendingIntent(R.id.layout_left, startMediaplayer);
|
||||||
if (playbackService != null) {
|
if (playbackService != null && playbackService.getMedia() != null) {
|
||||||
Playable media = playbackService.getMedia();
|
Playable media = playbackService.getMedia();
|
||||||
PlayerStatus status = playbackService.getStatus();
|
PlayerStatus status = playbackService.getStatus();
|
||||||
|
|
||||||
|
|
|
@ -831,12 +831,9 @@ public class DownloadService extends Service {
|
||||||
} finally {
|
} finally {
|
||||||
mediaplayer.release();
|
mediaplayer.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (media.getItem().getChapters() == null) {
|
if (media.getItem().getChapters() == null) {
|
||||||
ChapterUtils.readID3ChaptersFromPlayableFileUrl(media);
|
ChapterUtils.loadChaptersFromFileUrl(media);
|
||||||
if (media.getItem().getChapters() == null) {
|
|
||||||
ChapterUtils.readOggChaptersFromPlayableFileUrl(media);
|
|
||||||
}
|
|
||||||
if (media.getItem().getChapters() != null) {
|
if (media.getItem().getChapters() != null) {
|
||||||
chaptersRead = true;
|
chaptersRead = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,7 +242,7 @@ public class ChapterUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadChapters(Playable media) {
|
public static void loadChaptersFromStreamUrl(Playable media) {
|
||||||
if (AppConfig.DEBUG)
|
if (AppConfig.DEBUG)
|
||||||
Log.d(TAG, "Starting chapterLoader thread");
|
Log.d(TAG, "Starting chapterLoader thread");
|
||||||
ChapterUtils.readID3ChaptersFromPlayableStreamUrl(media);
|
ChapterUtils.readID3ChaptersFromPlayableStreamUrl(media);
|
||||||
|
@ -253,4 +253,15 @@ public class ChapterUtils {
|
||||||
if (AppConfig.DEBUG)
|
if (AppConfig.DEBUG)
|
||||||
Log.d(TAG, "ChapterLoaderThread has finished");
|
Log.d(TAG, "ChapterLoaderThread has finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void loadChaptersFromFileUrl(Playable media) {
|
||||||
|
if (media.localFileAvailable()) {
|
||||||
|
ChapterUtils.readID3ChaptersFromPlayableFileUrl(media);
|
||||||
|
if (media.getChapters() == null) {
|
||||||
|
ChapterUtils.readOggChaptersFromPlayableFileUrl(media);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Could not load chapters from file url: local file not available");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,238 @@
|
||||||
|
package de.danoeh.antennapod.util.playback;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.SharedPreferences.Editor;
|
||||||
|
import android.media.MediaMetadataRetriever;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import de.danoeh.antennapod.PodcastApp;
|
||||||
|
import de.danoeh.antennapod.feed.Chapter;
|
||||||
|
import de.danoeh.antennapod.feed.MediaType;
|
||||||
|
import de.danoeh.antennapod.util.ChapterUtils;
|
||||||
|
import de.danoeh.antennapod.util.FileNameGenerator;
|
||||||
|
|
||||||
|
/** 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";
|
||||||
|
|
||||||
|
private String source;
|
||||||
|
|
||||||
|
private String episodeTitle;
|
||||||
|
private String feedTitle;
|
||||||
|
private String shownotes;
|
||||||
|
private MediaType mediaType = MediaType.AUDIO;
|
||||||
|
private List<Chapter> chapters;
|
||||||
|
private String imageUrl;
|
||||||
|
private int duration;
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
public ExternalMedia(String source, MediaType mediaType) {
|
||||||
|
super();
|
||||||
|
this.source = source;
|
||||||
|
this.mediaType = mediaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExternalMedia(String source, MediaType mediaType, int position) {
|
||||||
|
this(source, mediaType);
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeString(source);
|
||||||
|
dest.writeString(mediaType.toString());
|
||||||
|
dest.writeInt(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToPreferences(Editor prefEditor) {
|
||||||
|
prefEditor.putString(PREF_SOURCE_URL, source);
|
||||||
|
prefEditor.putString(PREF_MEDIA_TYPE, mediaType.toString());
|
||||||
|
prefEditor.putInt(PREF_POSITION, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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");
|
||||||
|
}
|
||||||
|
episodeTitle = mmr
|
||||||
|
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
|
||||||
|
feedTitle = mmr
|
||||||
|
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
|
||||||
|
duration = Integer.parseInt(mmr
|
||||||
|
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
|
||||||
|
ChapterUtils.loadChaptersFromFileUrl(this);
|
||||||
|
byte[] imgData = mmr.getEmbeddedPicture();
|
||||||
|
File cacheDir = PodcastApp.getInstance().getExternalCacheDir();
|
||||||
|
if (cacheDir != null) {
|
||||||
|
OutputStream out = null;
|
||||||
|
try {
|
||||||
|
File tmpFile = File.createTempFile(
|
||||||
|
FileNameGenerator.generateFileName(source) + "-img",
|
||||||
|
null, cacheDir);
|
||||||
|
out = new BufferedOutputStream(new FileOutputStream(tmpFile));
|
||||||
|
IOUtils.write(imgData, out);
|
||||||
|
imageUrl = tmpFile.getAbsolutePath();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new PlayableException("IOException during loadMetadata()");
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEpisodeTitle() {
|
||||||
|
return episodeTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadShownotes(ShownoteLoaderCallback callback) {
|
||||||
|
callback.onShownotesLoaded(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Chapter> getChapters() {
|
||||||
|
return chapters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getWebsiteLink() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPaymentLink() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFeedTitle() {
|
||||||
|
return feedTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getImageFileUrl() {
|
||||||
|
return imageUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getIdentifier() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDuration() {
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MediaType getMediaType() {
|
||||||
|
return mediaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFileUrl() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStreamUrl() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean localFileAvailable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean streamAvailable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveCurrentPosition(SharedPreferences pref, int newPosition) {
|
||||||
|
SharedPreferences.Editor editor = pref.edit();
|
||||||
|
editor.putInt(PREF_POSITION, newPosition);
|
||||||
|
position = newPosition;
|
||||||
|
editor.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPosition(int newPosition) {
|
||||||
|
position = newPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDuration(int newDuration) {
|
||||||
|
duration = newDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackStart() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackCompleted() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPlayableType() {
|
||||||
|
return PLAYABLE_TYPE_EXTERNAL_MEDIA;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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();
|
||||||
|
}
|
||||||
|
ExternalMedia extMedia = new ExternalMedia(source, type, position);
|
||||||
|
return extMedia;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExternalMedia[] newArray(int size) {
|
||||||
|
return new ExternalMedia[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -150,6 +150,14 @@ public interface Playable extends Parcelable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ExternalMedia.PLAYABLE_TYPE_EXTERNAL_MEDIA:
|
||||||
|
String source = pref.getString(ExternalMedia.PREF_SOURCE_URL, null);
|
||||||
|
String mediaType = pref.getString(ExternalMedia.PREF_MEDIA_TYPE, null);
|
||||||
|
if (source != null && mediaType != null) {
|
||||||
|
int position = pref.getInt(ExternalMedia.PREF_POSITION, 0);
|
||||||
|
return new ExternalMedia(source,MediaType.valueOf(mediaType), position);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
Log.e(TAG, "Could not restore Playable object from preferences");
|
Log.e(TAG, "Could not restore Playable object from preferences");
|
||||||
return null;
|
return null;
|
||||||
|
|
Loading…
Reference in New Issue