Skip to content

Instantly share code, notes, and snippets.

@moagrius
Created May 10, 2016 21:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moagrius/f2ca1d2d5c451d8b862304e46caf69f1 to your computer and use it in GitHub Desktop.
Save moagrius/f2ca1d2d5c451d8b862304e46caf69f1 to your computer and use it in GitHub Desktop.
import android.app.Service;
import android.content.Intent;
import android.media.MediaCodec;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.view.Surface;
import android.widget.MediaController;
import com.google.android.exoplayer.ExoPlaybackException;
import com.google.android.exoplayer.ExoPlayer;
import com.google.android.exoplayer.MediaCodecAudioTrackRenderer;
import com.google.android.exoplayer.MediaCodecSelector;
import com.google.android.exoplayer.MediaCodecVideoTrackRenderer;
import com.google.android.exoplayer.extractor.ExtractorSampleSource;
import com.google.android.exoplayer.upstream.Allocator;
import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.upstream.DefaultAllocator;
import com.google.android.exoplayer.upstream.DefaultUriDataSource;
import com.google.android.exoplayer.util.Util;
public class BackgroundAudioService extends Service implements ExoPlayer.Listener, MediaController.MediaPlayerControl {
private static final int BUFFER_SEGMENT_SIZE = 64 * 1024;
private static final int BUFFER_SEGMENT_COUNT = 256;
private static final int BUFFER_SIZE = BUFFER_SEGMENT_SIZE * BUFFER_SEGMENT_COUNT;
private MediaCodecVideoTrackRenderer mVideoRenderer;
private MediaCodecAudioTrackRenderer mAudioRenderer;
private ExoPlayer mExoPlayer;
private Surface mSurface;
private final IBinder mBackgroundAudioServiceBinder = new BackgroundAudioServiceBinder();
public class BackgroundAudioServiceBinder extends Binder {
BackgroundAudioService getService() {
return BackgroundAudioService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBackgroundAudioServiceBinder;
}
public void playUri(Uri uri){
mExoPlayer = ExoPlayer.Factory.newInstance(2);
mExoPlayer.addListener(this);
Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE);
String userAgent = Util.getUserAgent(this, BackgroundAudioService.class.getSimpleName());
DataSource dataSource = new DefaultUriDataSource(this, null, userAgent);
ExtractorSampleSource sampleSource = new ExtractorSampleSource(uri, dataSource, allocator, BUFFER_SIZE);
mAudioRenderer = new MediaCodecAudioTrackRenderer(sampleSource, MediaCodecSelector.DEFAULT);
mVideoRenderer = new MediaCodecVideoTrackRenderer(getApplicationContext(), sampleSource, MediaCodecSelector.DEFAULT, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT);
mExoPlayer.sendMessage(mVideoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, mSurface);
mExoPlayer.prepare(mVideoRenderer, mAudioRenderer);
mExoPlayer.setPlayWhenReady(true);
}
public ExoPlayer getExoPlayer(){
return mExoPlayer;
}
public void setSurface(Surface surface, boolean shouldBlock) {
mSurface = surface;
if(mExoPlayer != null) {
if(shouldBlock) {
mExoPlayer.blockingSendMessage(mVideoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, surface);
} else {
mExoPlayer.sendMessage(mVideoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, surface);
}
}
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
Log.d(BackgroundAudioService.class.getSimpleName(), String.format(">>>>> Player state changed"));
Log.d(BackgroundAudioService.class.getSimpleName(), String.format(">>>>> %s", playbackState));
}
@Override
public void onPlayWhenReadyCommitted() {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
}
/**
* MediaController
*/
@Override
public int getAudioSessionId() {
throw new UnsupportedOperationException();
}
@Override
public int getBufferPercentage() {
if(mExoPlayer == null){
return 0;
}
return mExoPlayer.getBufferedPercentage();
}
@Override
public int getCurrentPosition() {
if(mExoPlayer == null){
return 0;
}
return (int) mExoPlayer.getCurrentPosition();
}
@Override
public int getDuration() {
if(mExoPlayer == null){
return 0;
}
int duration = (int) mExoPlayer.getDuration();
return duration == ExoPlayer.UNKNOWN_TIME ? 0 : duration;
}
@Override
public boolean isPlaying() {
return mExoPlayer != null && mExoPlayer.getPlayWhenReady();
}
@Override
public void start() {
if(mExoPlayer != null) {
mExoPlayer.setPlayWhenReady(true);
}
}
@Override
public void pause() {
if(mExoPlayer != null) {
mExoPlayer.setPlayWhenReady(false);
}
}
@Override
public void seekTo(int timeMillis) {
if(mExoPlayer != null) {
long seekPosition = Math.min(Math.max(0, timeMillis), getDuration());
mExoPlayer.seekTo(seekPosition);
}
}
@Override
public boolean canPause() {
return true;
}
@Override
public boolean canSeekBackward() {
return true;
}
@Override
public boolean canSeekForward() {
return true;
}
}
Copy link

ghost commented Jun 14, 2016

Did you manage to make it work with a forgroundService mate?
If so, it'll be nice if you can share the code or at least give us some tips.
Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment