From 1bf84322656fe342dfa8fc95f0c19bb2c4d37d23 Mon Sep 17 00:00:00 2001 From: Artur Dryomov Date: Sat, 21 Jun 2014 02:48:03 +0300 Subject: [PATCH] Move audio playback to service. --- src/main/AndroidManifest.xml | 7 + .../activity/ServerFileAudioActivity.java | 181 ++++++++++-------- .../amahi/anywhere/service/AudioService.java | 102 ++++++++++ 3 files changed, 206 insertions(+), 84 deletions(-) create mode 100644 src/main/java/org/amahi/anywhere/service/AudioService.java diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 8527da4d6..3395f79bf 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -39,6 +39,9 @@ + + + + + diff --git a/src/main/java/org/amahi/anywhere/activity/ServerFileAudioActivity.java b/src/main/java/org/amahi/anywhere/activity/ServerFileAudioActivity.java index 386d090aa..a5c086840 100644 --- a/src/main/java/org/amahi/anywhere/activity/ServerFileAudioActivity.java +++ b/src/main/java/org/amahi/anywhere/activity/ServerFileAudioActivity.java @@ -20,10 +20,14 @@ package org.amahi.anywhere.activity; import android.app.Activity; -import android.media.AudioManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; +import android.os.IBinder; import android.view.MenuItem; import android.view.View; import android.view.animation.Animation; @@ -43,18 +47,20 @@ import org.amahi.anywhere.server.client.ServerClient; import org.amahi.anywhere.server.model.ServerFile; import org.amahi.anywhere.server.model.ServerShare; +import org.amahi.anywhere.service.AudioService; import org.amahi.anywhere.task.AudioMetadataRetrievingTask; import org.amahi.anywhere.util.AudioAlbumArtDownloader; import org.amahi.anywhere.util.Intents; -import java.io.IOException; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import javax.inject.Inject; -public class ServerFileAudioActivity extends Activity implements MediaController.MediaPlayerControl, MediaPlayer.OnPreparedListener +public class ServerFileAudioActivity extends Activity implements ServiceConnection, + MediaPlayer.OnPreparedListener, + MediaController.MediaPlayerControl { public static final Set SUPPORTED_FORMATS; @@ -67,30 +73,17 @@ public class ServerFileAudioActivity extends Activity implements MediaController )); } - private static final class SavedState - { - private SavedState() { - } - - public static final String AUDIO_TIME = "audio_time"; - } - @Inject ServerClient serverClient; - private MediaPlayer audioPlayer; - + private AudioService audioService; private MediaController audioControls; - private int audioTime; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_server_file_audio); - setUpSavedState(savedInstanceState); - setUpInjections(); setUpHomeNavigation(); @@ -98,14 +91,6 @@ protected void onCreate(Bundle savedInstanceState) { setUpAudio(); } - private void setUpSavedState(Bundle savedState) { - if (savedState == null) { - return; - } - - audioTime = savedState.getInt(SavedState.AUDIO_TIME); - } - private void setUpInjections() { AmahiApplication.from(this).inject(this); } @@ -174,20 +159,35 @@ private void setUpAudioAlbumArt() { protected void onStart() { super.onStart(); - setUpAudioPlayer(); + setUpAudioService(); + setUpAudioServiceBind(); + } + + private void setUpAudioService() { + Intent intent = new Intent(this, AudioService.class); + startService(intent); + } + + private void setUpAudioServiceBind() { + Intent intent = new Intent(this, AudioService.class); + bindService(intent, this, Context.BIND_AUTO_CREATE); + } + + @Override + public void onServiceDisconnected(ComponentName serviceName) { + } + + @Override + public void onServiceConnected(ComponentName serviceName, IBinder serviceBinder) { + setUpAudioServiceBind(serviceBinder); + setUpAudioControls(); + setUpAudioPlayback(); } - private void setUpAudioPlayer() { - try { - audioPlayer = new MediaPlayer(); - audioPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); - audioPlayer.setDataSource(this, getAudioUri()); - audioPlayer.setOnPreparedListener(this); - audioPlayer.prepareAsync(); - } catch (IOException e) { - throw new RuntimeException(e); - } + private void setUpAudioServiceBind(IBinder serviceBinder) { + AudioService.AudioServiceBinder audioServiceBinder = (AudioService.AudioServiceBinder) serviceBinder; + audioService = audioServiceBinder.getAudioService(); } private void setUpAudioControls() { @@ -197,22 +197,27 @@ private void setUpAudioControls() { audioControls.setAnchorView(findViewById(R.id.animator)); } + private void setUpAudioPlayback() { + if (audioService.isStarted()) { + showAudio(); + } else { + audioService.startAudio(getAudioUri(), this); + } + } + @Override - public void onPrepared(MediaPlayer mediaPlayer) { - setUpAudioTime(); + public void onPrepared(MediaPlayer audioPlayer) { start(); showAudio(); - showAudioControls(); } - private void setUpAudioTime() { - if (audioPlayer.getCurrentPosition() == 0) { - audioPlayer.seekTo(audioTime); - } + private void showAudio() { + showAudioMetadata(); + showAudioControls(); } - private void showAudio() { + private void showAudioMetadata() { ViewAnimator animator = (ViewAnimator) findViewById(R.id.animator); View content = findViewById(R.id.layout_content); @@ -223,15 +228,27 @@ private void showAudio() { } private void showAudioControls() { - Animation showAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_up_view); - audioControls.startAnimation(showAnimation); + if (areAudioControlsAvailable() && !audioControls.isShowing()) { + Animation showAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_up_view); + audioControls.startAnimation(showAnimation); + + audioControls.show(0); + } + } + + private boolean areAudioControlsAvailable() { + return audioControls != null; + } - audioControls.show(0); + private void hideAudioControls() { + if (areAudioControlsAvailable()) { + audioControls.hide(); + } } @Override public void start() { - audioPlayer.start(); + audioService.getAudioPlayer().start(); } @Override @@ -241,7 +258,7 @@ public boolean canPause() { @Override public void pause() { - audioPlayer.pause(); + audioService.getAudioPlayer().pause(); } @Override @@ -256,22 +273,22 @@ public boolean canSeekForward() { @Override public void seekTo(int time) { - audioPlayer.seekTo(time); + audioService.getAudioPlayer().seekTo(time); } @Override public int getDuration() { - return audioPlayer.getDuration(); + return audioService.getAudioPlayer().getDuration(); } @Override public int getCurrentPosition() { - return audioPlayer.getCurrentPosition(); + return audioService.getAudioPlayer().getCurrentPosition(); } @Override public boolean isPlaying() { - return audioPlayer.isPlaying(); + return audioService.getAudioPlayer().isPlaying(); } @Override @@ -281,65 +298,61 @@ public int getBufferPercentage() { @Override public int getAudioSessionId() { - return audioPlayer.getAudioSessionId(); + return audioService.getAudioPlayer().getAudioSessionId(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem menuItem) { + switch (menuItem.getItemId()) { + case android.R.id.home: + finish(); + return true; + + default: + return super.onOptionsItemSelected(menuItem); + } } @Override protected void onResume() { super.onResume(); - BusProvider.getBus().register(this); + showAudioControls(); - audioPlayer.start(); + BusProvider.getBus().register(this); } @Override protected void onPause() { super.onPause(); - BusProvider.getBus().unregister(this); - hideAudioControls(); - } - private void hideAudioControls() { - audioControls.hide(); + BusProvider.getBus().unregister(this); } @Override protected void onStop() { super.onStop(); - audioTime = getCurrentPosition(); - - tearDownAudioPlayer(); + tearDownAudioServiceBind(); } - private void tearDownAudioPlayer() { - audioPlayer.stop(); - audioPlayer.release(); + private void tearDownAudioServiceBind() { + unbindService(this); } @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); + protected void onDestroy() { + super.onDestroy(); - tearDownSavedState(outState); - } - - private void tearDownSavedState(Bundle savedState) { - savedState.putInt(SavedState.AUDIO_TIME, getCurrentPosition()); + if (isFinishing()) { + tearDownAudioService(); + } } - @Override - public boolean onOptionsItemSelected(MenuItem menuItem) { - switch (menuItem.getItemId()) { - case android.R.id.home: - finish(); - return true; - - default: - return super.onOptionsItemSelected(menuItem); - } + private void tearDownAudioService() { + Intent intent = new Intent(this, AudioService.class); + stopService(intent); } } diff --git a/src/main/java/org/amahi/anywhere/service/AudioService.java b/src/main/java/org/amahi/anywhere/service/AudioService.java new file mode 100644 index 000000000..f529c8e31 --- /dev/null +++ b/src/main/java/org/amahi/anywhere/service/AudioService.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014 Amahi + * + * This file is part of Amahi. + * + * Amahi is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Amahi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Amahi. If not, see . + */ + +package org.amahi.anywhere.service; + +import android.app.Service; +import android.content.Intent; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.net.Uri; +import android.os.Binder; +import android.os.IBinder; +import android.os.PowerManager; + +import java.io.IOException; + +public class AudioService extends Service +{ + private MediaPlayer audioPlayer; + + private Uri audioSource; + + @Override + public IBinder onBind(Intent intent) { + return new AudioServiceBinder(this); + } + + @Override + public void onCreate() { + super.onCreate(); + + setUpAudioPlayer(); + } + + private void setUpAudioPlayer() { + audioPlayer = new MediaPlayer(); + + audioPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + audioPlayer.setWakeMode(this, PowerManager.PARTIAL_WAKE_LOCK); + } + + public boolean isStarted() { + return audioSource != null; + } + + public void startAudio(Uri audioUri, MediaPlayer.OnPreparedListener audioListener) { + try { + audioSource = audioUri; + + audioPlayer.setDataSource(this, audioUri); + audioPlayer.setOnPreparedListener(audioListener); + audioPlayer.prepareAsync(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public MediaPlayer getAudioPlayer() { + return audioPlayer; + } + + @Override + public void onDestroy() { + super.onDestroy(); + + tearDownAudioPlayer(); + } + + private void tearDownAudioPlayer() { + audioPlayer.reset(); + audioPlayer.release(); + } + + public static final class AudioServiceBinder extends Binder + { + private final AudioService audioService; + + public AudioServiceBinder(AudioService audioService) { + this.audioService = audioService; + } + + public AudioService getAudioService() { + return audioService; + } + } +}