Added support for video playback

This commit is contained in:
daniel oeh 2012-06-27 14:10:38 +02:00
parent 18e8212981
commit 853556b0cf
4 changed files with 135 additions and 35 deletions

View File

@ -4,12 +4,23 @@
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="@+id/imgvCover"
<ViewSwitcher
android:id="@+id/viewswitcher"
android:layout_width="match_parent"
android:layout_height="283dp"
android:layout_weight="0.02"
android:src="@drawable/navigation_cancel" />
android:layout_weight="0.02" >
<ImageView
android:id="@+id/imgvCover"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/navigation_cancel" />
<VideoView
android:id="@+id/videoview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</ViewSwitcher>
<RelativeLayout
android:id="@+id/playtime_layout"

View File

@ -7,11 +7,14 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.graphics.PixelFormat;
import android.media.MediaPlayer;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
@ -19,6 +22,8 @@ import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.VideoView;
import android.widget.ViewSwitcher;
import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.Menu;
@ -31,7 +36,8 @@ import de.podfetcher.service.PlaybackService;
import de.podfetcher.service.PlayerStatus;
import de.podfetcher.util.Converter;
public class MediaplayerActivity extends SherlockActivity {
public class MediaplayerActivity extends SherlockActivity implements
SurfaceHolder.Callback {
private final String TAG = "MediaplayerActivity";
private static final int DEFAULT_SEEK_DELTA = 30000; // Seek-Delta to use
@ -46,7 +52,9 @@ public class MediaplayerActivity extends SherlockActivity {
private FeedManager manager;
// Widgets
private ViewSwitcher viewswitcher;
private ImageView imgvCover;
private VideoView videoview;
private TextView txtvStatus;
private TextView txtvPosition;
private TextView txtvLength;
@ -68,7 +76,7 @@ public class MediaplayerActivity extends SherlockActivity {
unbindService(mConnection);
} catch (IllegalArgumentException e) {
// ignore
}
}
if (positionObserver != null) {
positionObserver.cancel(true);
}
@ -88,10 +96,20 @@ public class MediaplayerActivity extends SherlockActivity {
}
@Override
protected void onPause() {
super.onPause();
if (playbackService.isRunning && playbackService != null
&& playbackService.isPlayingVideo()) {
playbackService.pause();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "Creating Activity");
getWindow().setFormat(PixelFormat.TRANSPARENT);
this.setContentView(R.layout.mediaplayer_activity);
manager = FeedManager.getInstance();
setupGUI();
@ -167,6 +185,12 @@ public class MediaplayerActivity extends SherlockActivity {
break;
case SEEKING:
setStatusMsg(R.string.player_seeking_msg, View.VISIBLE);
break;
case AWAITING_VIDEO_SURFACE:
Log.d(TAG, "Preparing video playback");
SurfaceHolder holder = videoview.getHolder();
holder.addCallback(this);
viewswitcher.showNext();
}
}
@ -227,7 +251,9 @@ public class MediaplayerActivity extends SherlockActivity {
}
private void setupGUI() {
viewswitcher = (ViewSwitcher) findViewById(R.id.viewswitcher);
imgvCover = (ImageView) findViewById(R.id.imgvCover);
videoview = (VideoView) findViewById(R.id.videoview);
txtvPosition = (TextView) findViewById(R.id.txtvPosition);
txtvLength = (TextView) findViewById(R.id.txtvLength);
txtvStatus = (TextView) findViewById(R.id.txtvStatus);
@ -363,4 +389,24 @@ public class MediaplayerActivity extends SherlockActivity {
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "Videoview holder created");
if (status == PlayerStatus.AWAITING_VIDEO_SURFACE) {
playbackService.setVideoSurface(holder);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}

View File

@ -17,6 +17,7 @@ import android.media.AudioManager.OnAudioFocusChangeListener;
import android.media.MediaPlayer;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.view.SurfaceHolder;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Binder;
@ -30,7 +31,6 @@ import de.podfetcher.feed.FeedManager;
/** Controls the MediaPlayer that plays a FeedMedia-file */
public class PlaybackService extends Service {
/** Logging tag */
private static final String TAG = "PlaybackService";
@ -40,8 +40,7 @@ public class PlaybackService extends Service {
public static final String PREF_LAST_PLAYED_FEED_ID = "de.podfetcher.preferences.lastPlayedFeedId";
/** True if last played media was streamed. */
public static final String PREF_LAST_IS_STREAM = "de.podfetcher.preferences.lastIsStream";
/** Contains the id of the FeedMedia object. */
public static final String EXTRA_MEDIA_ID = "extra.de.podfetcher.service.mediaId";
/** Contains the id of the Feed object of the FeedMedia. */
@ -70,12 +69,13 @@ public class PlaybackService extends Service {
/** True if media should be streamed (Extracted from Intent Extra) . */
private boolean shouldStream;
private boolean startWhenPrepared;
private boolean playingVideo;
private FeedManager manager;
private PlayerStatus status;
private PositionSaver positionSaver;
private PlayerStatus statusBeforeSeek;
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
@ -164,26 +164,7 @@ public class PlaybackService extends Service {
shouldStream = playbackType;
startWhenPrepared = intent.getBooleanExtra(
EXTRA_START_WHEN_PREPARED, false);
try {
if (shouldStream) {
player.setDataSource(media.getDownload_url());
setStatus(PlayerStatus.PREPARING);
player.prepareAsync();
} else {
player.setDataSource(media.getFile_url());
setStatus(PlayerStatus.PREPARING);
player.prepare();
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
setupMediaplayer();
} else {
Log.e(TAG, "Media is null");
@ -199,6 +180,64 @@ public class PlaybackService extends Service {
return Service.START_STICKY;
}
/**
* Called by a mediaplayer Activity as soon as it has prepared its
* mediaplayer.
*/
public void setVideoSurface(SurfaceHolder sh) {
player.setDisplay(sh);
try {
if (shouldStream) {
player.setDataSource(media.getDownload_url());
setStatus(PlayerStatus.PREPARING);
player.prepareAsync();
} else {
player.setDataSource(media.getFile_url());
setStatus(PlayerStatus.PREPARING);
player.prepare();
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/** Called after service has extracted the media it is supposed to play. */
private void setupMediaplayer() {
try {
if (media.getMime_type().startsWith("audio")) {
playingVideo = false;
if (shouldStream) {
player.setDataSource(media.getDownload_url());
setStatus(PlayerStatus.PREPARING);
player.prepareAsync();
} else {
player.setDataSource(media.getFile_url());
setStatus(PlayerStatus.PREPARING);
player.prepare();
}
} else if (media.getMime_type().startsWith("video")) {
playingVideo = true;
setStatus(PlayerStatus.AWAITING_VIDEO_SURFACE);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void setupPositionSaver() {
if (positionSaver == null) {
positionSaver = new PositionSaver() {
@ -229,18 +268,18 @@ public class PlaybackService extends Service {
}
}
};
private MediaPlayer.OnSeekCompleteListener onSeekCompleteListener = new MediaPlayer.OnSeekCompleteListener() {
@Override
public void onSeekComplete(MediaPlayer mp) {
if (status == PlayerStatus.SEEKING) {
setStatus(statusBeforeSeek);
}
}
};
private MediaPlayer.OnCompletionListener completionListener = new MediaPlayer.OnCompletionListener() {
@Override
@ -382,6 +421,10 @@ public class PlaybackService extends Service {
}
public boolean isPlayingVideo() {
return playingVideo;
}
public boolean isShouldStream() {
return shouldStream;
}

View File

@ -1,5 +1,5 @@
package de.podfetcher.service;
public enum PlayerStatus {
ERROR, PREPARING, PAUSED, PLAYING, STOPPED, PREPARED, SEEKING
ERROR, PREPARING, PAUSED, PLAYING, STOPPED, PREPARED, SEEKING, AWAITING_VIDEO_SURFACE
}