Android MediaPlayer to play video stream in Service screen rotation - android

I would like to create Activity with video player to play online stream using MediaPlayer class and SurfaceView to display. I'm creating MediaPlayer in separate Service so after screen rotation player don't have to be created again and don't have to connect to stream. My problem is that I don't know how to write Activity so my service wouldn't start every time after screen rotation.
My code below, in onStart() I start service but I don't know how to change it so it didn't start every time.
public class VideoPlayerActivity extends Activity implements SurfaceHolder.Callback {
private String path;
private SurfaceHolder vidHolder;
private SurfaceView vidSurface;
private VideoService videoService;
private Intent playIntent;
private boolean videoBound = false;
private ServiceConnection musicConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
VideoService.VideoBinder binder = (VideoService.VideoBinder) service;
videoService = binder.getService();
videoService.setUrl(path);
videoBound = true;
if (vidHolder != null && videoService.getMediaPlayer() != null) {
videoService.getMediaPlayer().setDisplay(vidHolder);
videoService.playVideo();
}
}
#Override
public void onServiceDisconnected(ComponentName name) {
videoBound = false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
path = "https://archive.org/download/ksnn_compilation_master_the_internet/ksnn_compilation_master_the_internet_512kb.mp4"; //TODO tmp
playIntent = new Intent(this, VideoService.class);
bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
startService(playIntent);
vidSurface = (SurfaceView) findViewById(R.id.surfView);
vidHolder = vidSurface.getHolder();
vidHolder.addCallback(VideoPlayerActivity.this);
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
if (videoService != null && videoService.getMediaPlayer() != null) {
videoService.getMediaPlayer().setDisplay(vidHolder);
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
Log.d("ServiceConnection", "surfaceChanged " + i + " " + i1 + " " + i2);
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Log.d("ServiceConnection", "surfaceDestroyed");
}
#Override
protected void onDestroy() {
super.onDestroy();
unbindService(musicConnection);
stopService(playIntent);
videoService = null;
}
}
Service class:
public class VideoService extends Service implements OnPreparedListener {
private MediaPlayer player;
private String path;
private final IBinder musicBind = new VideoBinder();
#Override
public void onCreate() {
Log.d("VideoService", "onCreate");
super.onCreate();
player = new MediaPlayer();
initMusicPlayer();
}
#Override
public IBinder onBind(Intent intent) {
return musicBind;
}
#Override
public boolean onUnbind(Intent intent){
player.stop();
player.release();
return false;
}
public void initMusicPlayer() {
player.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnPreparedListener(this);
}
public void playVideo() {
try {
player.setDataSource(path);
player.prepareAsync();
} catch (IOException e) {}
}
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
public void setUrl(String url) {
path = url;
}
public MediaPlayer getMediaPlayer() {
return player;
}
public class VideoBinder extends Binder {
public VideoService getService() {
return VideoService.this;
}
}
}

You could either check for savedInstanceState being null to only start the service if the Activity is freshly created
if (savedInstanceState == null) {
startService...
}
or handle screen rotation yourself by adding
android:configChanges="orientation|keyboardHidden|screenSize"
to your Activity in manifest. Like this onCreate will not be called on rotation any more.

Related

Android background audio with a live audio stream

I have come along in leaps and bound with my first android app in the last three days. This is my last hurdle. How do I get my app to run a background Service that will allow the audio to keep playing? I have tried several examples I could find but they are based on playing a local (or streamed) mp3 file as opposed to a live (Icecast) mp3 stream.
Here's my code currently, everything works except background audio.
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
private ImageButton btn;
private ImageView img;
private boolean playPause;
private MediaPlayer mediaPlayer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = findViewById(R.id.playPause);
img = findViewById(R.id.radioTower);
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int extra) {
mp.reset();
return false;
}
});
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
//mp.start();
}
});
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!playPause) {
if(!mediaPlayer.isPlaying()) {
mediaPlayer.start();
btn.setBackgroundResource(R.drawable.ic_rounded_pause_button);
img.setImageResource(R.drawable.ic_toweron);
img.setAlpha(1.0f);
playPause = true;
}
} else {
if(mediaPlayer.isPlaying()) {
mediaPlayer.pause();
btn.setBackgroundResource(R.drawable.ic_play_button);
img.setImageResource(R.drawable.ic_toweroff);
img.setAlpha(0.3f);
playPause = false;
}
}
}
});
try {
mediaPlayer.setDataSource("http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio2_mf_p");
mediaPlayer.prepareAsync();
} catch (Exception e) {
e.printStackTrace();
}
}
protected void onStop() {
super.onStop();
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.release();
mediaPlayer = null;
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.release();
mediaPlayer = null;
}
}
}
Any help would be much appreciated.
use service to play audio file instant of activity.
here is simple code how to use media player in service.
public class MusicService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener, MediaPlayer.OnBufferingUpdateListener {
//region "member variable"
boolean isServiceRunning = false;
ArrayList<Song> PlayerList = new ArrayList<>();
MediaPlayer mediaPlayer;
int position = 0;
MainActivity mainActivity;
private final IBinder mBinder = new LocalBinder();
int playingMood;
private final static int MAX_VOLUME = 15;
Toast toast;
public static MusicService objService;
//endregion
//region "service method"
#Override
public void onCreate() {
objService = this;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
isServiceRunning = true;
if (intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION)) {
// showNotification(false);
} else if (intent.getAction().equals(Constants.ACTION.PREV_ACTION)) {
playPrevious();
} else if (intent.getAction().equals(Constants.ACTION.PLAY_ACTION)) {
play();
} else if (intent.getAction().equals(Constants.ACTION.NEXT_ACTION)) {
playNext();
} else if (intent.getAction().equals(
Constants.ACTION.STOPFOREGROUND_ACTION)) {
stop();
stopForeground(true);
stopSelf();
}
} catch (Exception ex) {
ex.printStackTrace();
}
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
isServiceRunning = false;
objService = null;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
//returns the instance of the service
public class LocalBinder extends Binder {
public MusicService getServiceInstance() {
return MusicService.this;
}
}
public void registerClient(MainActivity activity) {
mainActivity = activity;
}
//endregion
//region "Media player"
public void SongRequest() {
try {
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
}
//Handel UI on main activity
mainActivity.showPlayer();
mediaPlayer = new MediaPlayer();
mainActivity.updatePlayerUI();
prepareMediaPlayer(PlayerList.get(position).getUrl());
} catch (Exception ex) {
ex.printStackTrace();
}
}
void showToast(String text) {
if (toast != null)
toast.cancel();
toast = Toast.makeText(App.getContext(), text, Toast.LENGTH_LONG);
toast.show();
}
#Override
public void onPrepared(MediaPlayer mp) {
// try {
mediaPlayer.start();
mainActivity.checkPlaying(true);
} catch (Exception ex) {
ex.printStackTrace();
}
}
#Override
public void onCompletion(MediaPlayer mp) {
try {
mainActivity.sentUpdateBroadcast(true);
if (playingMood == 1) {
mediaPlayer.start();
}
if (playingMood == 2) {
playNext();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
if (mainActivity != null)
mainActivity.updateProgressBuffer(percent);
if (percent == 1)
mainActivity.showPlayer();
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
try {
Log.i("MediaPlayer", "error");
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
void startPrepare(String url) {
prepareMediaPlayer(url);
}
void prepareMediaPlayer(String url) {
try {
mediaPlayer.setDataSource(url);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnPreparedListener(MusicService.this);
mediaPlayer.setOnErrorListener(MusicService.this);
mediaPlayer.setOnCompletionListener(MusicService.this);
mediaPlayer.setOnBufferingUpdateListener(MusicService.this);
mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
//endregion
//region "media player method"
public boolean play() {
if (mediaPlayer != null) {
switchButton();
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
return false;
} else {
mediaPlayer.start();
return true;
}
}
return false;
}
void switchButton() {
mainActivity.checkPlaying(!mediaPlayer.isPlaying());
}
public void stop() {
try {
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
}
isServiceRunning = false;
if (mainActivity != null) {
mainActivity.ShowPlayer(0);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void playNext() {
if (position < PlayerList.size() - 1) {
position++;
mediaPlayer.stop();
SongRequest();
}
}
public void playPrevious() {
if (position > 0) {
position--;
mediaPlayer.stop();
SongRequest();
}
}
public void onError() {
}
public void onCompletion() {
}
public void onCleanMemory() {
}
public void initilizePlayerList(ArrayList<Song> list, int position) {
this.PlayerList = list;
this.position = position;
}
public boolean isplaying() {
return mediaPlayer == null ? false : mediaPlayer.isPlaying();
}
public boolean isRunning() {
return isServiceRunning;
}
public Song getCurrentSong() {
if (PlayerList != null && PlayerList.size() != 0 && PlayerList.size() >= position) {
return PlayerList.get(position);
}
return null;
}
public MediaPlayer getMediaPlayer() {
return mediaPlayer;
}
public void seekTo(int duration) {
if (mediaPlayer != null) {
mediaPlayer.seekTo(duration);
}
}
public int getMood() {
return playingMood;
}
public void setMood(int mood) {
playingMood = mood;
}
public void setVolume(int soundVolume) {
if (mediaPlayer != null) {
final float volume = (float) (1 - (Math.log(MAX_VOLUME - soundVolume) / Math.log(MAX_VOLUME)));
mediaPlayer.setVolume(volume, volume);
}
}
//endregion
}
you can start your service from activity like this.
public void startMusicService() {
Intent serviceIntent = new Intent(MainActivity.this, MusicService.class);
serviceIntent.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
startService(serviceIntent);
bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
}
for stop service use this code
public void stopMusicService() {
if (service != null) {
try {
service.stop();
unbindService(mConnection);
stopService(new Intent(MainActivity.this, service.getClass()));
service = null;
} catch (IllegalArgumentException ex) {
stopService(new Intent(MainActivity.this, service.getClass()));
service = null;
ex.printStackTrace();
}
}
}
for bind service with activity use this
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder _service) {
MusicService.LocalBinder binder = (MusicService.LocalBinder) _service;
service = binder.getServiceInstance(); //Get instance of your service!
service.registerClient(MainActivity.this); //Activity register in the service as client for callabcks!
if (listHolder != null) {
initilizeSongsList(listHolder.list, listHolder.position);
}
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
}
};
where service is music service object in activity MusicService service;
So this is the working service for a single live stream URL thanks to asim.
public class StreamService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener {
public static final String ACTION_PLAY = "com.example.action.PLAY";
private static final String STREAM_URL = "...";
private static final String TEST_URL = "https://www.nasa.gov/mp3/586447main_JFKwechoosemoonspeech.mp3";
MainActivity mainActivity;
MediaPlayer mediaPlayer = null;
WifiManager.WifiLock wifiLock;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
public class LocalBinder extends Binder {
public StreamService getServiceInstance() {
return StreamService.this;
}
}
#Override
public void onCreate() {
super.onCreate();
}
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(ACTION_PLAY)) {
mediaPlayer = new MediaPlayer();
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
wifiLock = ((WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE))
.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "mylock");
wifiLock.acquire();
try {
// Set the stream URL location
mediaPlayer.setDataSource(TEST_URL);
// prepareAsync must be called after setAudioStreamType and setOnPreparedListener
mediaPlayer.prepareAsync();
} catch (Exception e) {
e.printStackTrace();
}
}
return START_STICKY;
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// ... react appropriately ...
// The MediaPlayer has moved to the Error state, must be reset!
return false;
}
void switchButton() {
mainActivity.checkPlaying(!mediaPlayer.isPlaying());
}
public boolean play() {
if (mediaPlayer != null) {
//switchButton();
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
return false;
} else {
mediaPlayer.start();
return true;
}
}
return false;
}
public void stop() {
try {
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
/** Called when MediaPlayer is ready */
public void onPrepared(MediaPlayer player) {
//player.start();
}
#Override
public void onDestroy() {
super.onDestroy();
if( wifiLock != null) wifiLock.release();
if (mediaPlayer != null) mediaPlayer.release();
}
public void registerClient(MainActivity activity) {
mainActivity = activity;
}
public boolean isplaying() {
return mediaPlayer == null ? false : mediaPlayer.isPlaying();
}
}
Which is implemented in the main activity:
public class MainActivity extends AppCompatActivity {
private ImageButton btn; // Play | Pause toggle button
private ImageView img; // Radio tower image that alternates between on and off
StreamService service;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Bind the view buttons to local variables
btn = findViewById(R.id.playPause);
img = findViewById(R.id.radioTower);
startStream();
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (service.isplaying()) {
Log.d("pause","Pause Playback");
} else {
Log.d("play", "Start Playback");
}
}
});
}
public void startStream() {
Intent serviceIntent = new Intent(MainActivity.this, StreamService.class);
serviceIntent.setAction(StreamService.ACTION_PLAY);
startService(serviceIntent);
bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
}
public void stopStream() {
if (service != null) {
try {
service.stop();
unbindService(mConnection);
stopService(new Intent(MainActivity.this, service.getClass()));
service = null;
} catch (IllegalArgumentException ex) {
stopService(new Intent(MainActivity.this, service.getClass()));
service = null;
ex.printStackTrace();
}
}
}
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder _service) {
StreamService.LocalBinder binder = (StreamService.LocalBinder) _service;
service = binder.getServiceInstance(); //Get instance of your service!
service.registerClient(MainActivity.this); //Activity register in the service as client for callabcks!
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
}
};
}
Service starts just fine, I just need to learn how to access the service object to implement the play pause functionality.

MediaPlayer.isPlaying throws an IllegalStateException Exception when screen goes off

AudioService initializes a MediaPlayer in the constructor, and exposes it to Activity.
public class AudioService extends Service implements MediaPlayer.OnPreparedListener {
private static final String TAG = "AudioService";
MediaPlayer mMediaPlayer = new MediaPlayer();
private final IBinder mBinder = new AudioBinder();
public void onCreate () {
mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mMediaPlayer.setOnPreparedListener(this);
}
/** Called when MediaPlayer is ready */
public void onPrepared(MediaPlayer player) {
player.start();
}
public AudioService() {}
public boolean initPlayer(final String section){
try {
AssetFileDescriptor afd = getAssets().openFd("records/"+section+".mp3");
mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mMediaPlayer.prepareAsync();
return true;
}catch (IOException e){
e.printStackTrace();
return false;
}
}
public MediaPlayer getPlayer(){
return mMediaPlayer;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onDestroy() {
if (mMediaPlayer != null) mMediaPlayer.release();
}
public class AudioBinder extends Binder {
AudioService getService() {
return AudioService.this;
}
}
}
I don't know if it is OK to manipulate MediaPlayer directly from Activity.
public class PageActivity extends FragmentActivity {
String TAG = "PageActivity";
MediaPlayer player;
Handler handler = new Handler();
Button toggle;
boolean isSeekBarDragging = false;
String section;
AudioService audioService;
public ServiceConnection myConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder binder) {
audioService = ((AudioService.AudioBinder)binder).getService();
if(audioService.initPlayer(section)){
player = audioService.getPlayer();
}else {
seekBar.setEnabled(false);
}
}
#Override
public void onServiceDisconnected(ComponentName className) {
audioService = null;
player = null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_page);
//bind service
bindService(new Intent(this, AudioService.class), myConnection, Context.BIND_AUTO_CREATE);
}
private void initButtons() {
toggle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//!!! Exception is thrown here.
if(player.isPlaying()){
player.pause();
}else {
player.start();
}
}
});
}
#Override
protected void onStop(){
if(player.isPlaying()) player.stop();
handler.removeCallbacks(updater);
super.onStop();
}
}

Android Service stops automatically without calling stopService()

I have made an android Service to play music, when i close my application then it keeps on playing song for few minutes and then automatically stops without even calling destroy method. I am not able to understand why is it happening.
Below is the code of my Service class.
public class MusicService extends Service implements MediaPlayer.OnSeekCompleteListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener,
MediaPlayer.OnInfoListener, MediaPlayer.OnErrorListener, MediaPlayer.OnBufferingUpdateListener {
private MediaPlayer player;
private int songPosition;
private IBinder iBinder = new LocalBinder();
private PhoneStateListener phoneStateListener;
private TelephonyManager telephonyManager;
private boolean isPaused = false;
private ArrayList<Song> songsList;
private boolean isRepeat = false;
private boolean isShuffle = false;
private Intent broadcastIntent;
public static final String BROADCAST_INTENT = "music.akumar.com.musicplayer.seekbarintent";
private Handler handler = new Handler();
public class LocalBinder extends Binder {
public MusicService getService() {
return MusicService.this;
}
}
#Override
public void onCreate() {
broadcastIntent = new Intent(BROADCAST_INTENT);
player = new MediaPlayer();
player.setOnBufferingUpdateListener(this);
player.setOnCompletionListener(this);
player.setOnSeekCompleteListener(this);
player.setOnPreparedListener(this);
player.setOnInfoListener(this);
player.setOnErrorListener(this);
player.setLooping(true);
player.reset();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
telephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
phoneStateListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch(state) {
case TelephonyManager.CALL_STATE_OFFHOOK:
case TelephonyManager.CALL_STATE_RINGING:
if (player.isPlaying()) {
pauseMedia();
isPaused = true;
}
break;
case TelephonyManager.CALL_STATE_IDLE:
if (player != null) {
if (isPaused) {
playMedia();
isPaused = false;
}
}
break;
}
}
};
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
return START_STICKY;
}
public void playMedia() {
if (player != null && !player.isPlaying()) {
player.start();
}
}
public void pauseMedia() {
if (player != null && player.isPlaying()) {
player.pause();
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (player.isPlaying()) {
player.stop();
}
player.release();
}
#Override
public IBinder onBind(Intent intent) {
return iBinder;
}
public void playSong(Song song) {
player.reset();
try {
player.setDataSource(getApplicationContext(), Uri.parse(song.getPath()));
player.prepare();
playMedia();
setHandler();
} catch (IOException e) {
e.printStackTrace();
}
}
private void setHandler() {
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 500);
}
private Runnable sendUpdatesToUI = new Runnable() {
#Override
public void run() {
logMediaPosition();
handler.postDelayed(this, 500);
}
};
private void logMediaPosition() {
}
public void playNext() {
}
public void playPrev() {
}
public boolean isPlaying() {
return player.isPlaying();
}
public int getSongPosition() {
return songPosition;
}
public void setSongPosition(int songPosition) {
this.songPosition = songPosition;
}
public ArrayList<Song> getSongsList() {
return songsList;
}
public void setSongsList(ArrayList<Song> songsList) {
this.songsList = songsList;
}
public boolean isRepeat() {
return isRepeat;
}
public void setRepeat(boolean isRepeat) {
this.isRepeat = isRepeat;
}
public boolean isShuffle() {
return isShuffle;
}
public void setShuffle(boolean isShuffle) {
this.isShuffle = isShuffle;
}
public void addSongToList(Song song) {
songsList.add(song);
}
public Song getCurrentSong() {
return songsList.get(songPosition);
}
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
}
#Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i2) {
return false;
}
#Override
public boolean onInfo(MediaPlayer mediaPlayer, int i, int i2) {
return false;
}
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
}
#Override
public void onSeekComplete(MediaPlayer mediaPlayer) {
}
}
And below the code of my activity class.
public class MusicPlayer extends FragmentActivity implements View.OnClickListener, SeekBar.OnSeekBarChangeListener {
private boolean mBound = false;
private MusicService musicService;
private ArrayList<Song> songsList = new ArrayList<Song>();
private boolean isRepeat = false;
private boolean isShuffle = false;
private int position;
private ImageButton btnPlay;
private ImageButton btnPlayNext;
private ImageButton btnPlayPrev;
private ImageButton btnRepeat;
private ImageButton btnShuffle;
private ImageButton btnFavorite;
private TextView currentSongView;
private SeekBar seekBar;
private TextView songCurrentDurationLabel;
private TextView songTotalDurationLabel;
private ViewPager viewPager;
private BroadcastReceiver broadcastReceiver;
private boolean mBroadcastIsRegistered;
ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mBound = true;
MusicService.LocalBinder localBinder = (MusicService.LocalBinder)iBinder;
musicService = localBinder.getService();
musicService.setSongsList(songsList);
musicService.setSongPosition(0);
musicService.playSong(0);
btnPlay.setImageResource(R.drawable.btn_pause);
registerReceiver(broadcastReceiver, new IntentFilter(MusicService.BROADCAST_INTENT));
mBroadcastIsRegistered = true;
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBound = false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_music_player);
songsList = prepareListOfSongsAndAlbumMap();
currentSongView = (TextView)findViewById(R.id.currentSongView);
btnPlay = (ImageButton)findViewById(R.id.btnPlay);
btnPlayNext = (ImageButton)findViewById(R.id.btnNext);
btnPlayPrev = (ImageButton)findViewById(R.id.btnPrevious);
btnRepeat = (ImageButton)findViewById(R.id.btnRepeat);
btnShuffle = (ImageButton)findViewById(R.id.btnShuffle);
btnFavorite = (ImageButton)findViewById(R.id.btnFavourite);
seekBar = (SeekBar)findViewById(R.id.SeekBar01);
songCurrentDurationLabel = (TextView)findViewById(R.id.songCurrentDurationLabel);
songTotalDurationLabel = (TextView)findViewById(R.id.songTotalDurationLabel);
viewPager = (ViewPager)findViewById(R.id.viewPagerMusicPlayer);
position = 0;
btnPlay.setOnClickListener(this);
btnPlayNext.setOnClickListener(this);
btnPlayPrev.setOnClickListener(this);
btnRepeat.setOnClickListener(this);
btnShuffle.setOnClickListener(this);
btnFavorite.setOnClickListener(this);
seekBar.setOnSeekBarChangeListener(this);
DataTransferBetweenActivity data = new DataTransferBetweenActivity(songsList, position);
MusicPlayerTabAdapter musicPlayerTabAdapter = new MusicPlayerTabAdapter(getSupportFragmentManager(), data);
viewPager.setAdapter(musicPlayerTabAdapter);
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateUI(intent);
}
};
}
private void updateUI(Intent serviceIntent) {
}
private ArrayList<Song> prepareListOfSongsAndAlbumMap() {
Uri musicUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String[] projection;
projection = null;
String sortOrder = null;
String selectionMimeType = MediaStore.Audio.Media.IS_MUSIC + " !=0";
Cursor musicCursor = getContentResolver().query(musicUri, projection, selectionMimeType, null, sortOrder);
int count = musicCursor.getCount();
if (musicCursor.moveToFirst()) {
do {
String path = musicCursor.getString(musicCursor.getColumnIndex(MediaStore.Audio.Media.DATA));
String title = musicCursor.getString(musicCursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
String album = musicCursor.getString(musicCursor.getColumnIndex(MediaStore.Audio.Media.ALBUM));
String artist = musicCursor.getString(musicCursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
int artistId = musicCursor.getInt(musicCursor.getColumnIndex(MediaStore.Audio.Media.ARTIST_ID));
int albumId = musicCursor.getInt(musicCursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
int trackId = musicCursor.getInt(musicCursor.getColumnIndex(MediaStore.Audio.Media.TRACK));
long duration = musicCursor.getInt(musicCursor.getColumnIndex(MediaStore.Audio.Media.DURATION));
Uri sArtworkUri = Uri
.parse("content://media/external/audio/albumart");
Uri albumArtUri = ContentUris.withAppendedId(sArtworkUri, albumId);
Song song = new Song(path, title, album, artist, albumId, trackId, duration, albumArtUri.toString(), artistId);
songsList.add(song);
} while (musicCursor.moveToNext());
Collections.sort(songsList, new Comparator<Song>() {
#Override
public int compare(Song song, Song song2) {
return song.getTitle().toUpperCase().compareTo(song2.getTitle().toUpperCase());
}
});
musicCursor.close();
}
return songsList;
}
#Override
protected void onStart() {
super.onStart();
Intent serviceIntent = new Intent(this, MusicService.class);
startService(serviceIntent);
bindService(serviceIntent, serviceConnection, BIND_AUTO_CREATE);
}
#Override
protected void onDestroy() {
super.onDestroy();
if (mBound) {
unbindService(serviceConnection);
mBound = false;
}
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnPlay:
break;
case R.id.btnNext:
break;
case R.id.btnPrevious:
break;
case R.id.btnRepeat:
break;
case R.id.btnShuffle:
break;
}
}
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
#Override
protected void onPause() {
if (mBroadcastIsRegistered) {
unregisterReceiver(broadcastReceiver);
mBroadcastIsRegistered = false;
}
super.onPause();
}
#Override
protected void onResume() {
if (!mBroadcastIsRegistered) {
registerReceiver(broadcastReceiver, new IntentFilter(MusicService.BROADCAST_INTENT));
mBroadcastIsRegistered = true;
}
super.onResume();
}
public void playSong(int position) {
musicService.playSong(position);
musicService.setSongPosition(position);
}
}
I am starting my service with startService() method and i am not calling stopService() or stopSelf() anywhere, but i am not able to figure out why it stops playing after sometime.
I think you should call startForeground() from your service.
Here is a sample project of a music player. I might be helpful
FakePlayer

MusicPlayer crashes on click the back button

I made a simple music player which can play some songs in the background.
Going to the homescreen and reopen the app through notification works as well.
The only Problem I have is that if I press the back button(going to parent activity) in the music player activity my app crashes. There are two classes, the activity MP3Player.java and the service MP3Service.jave.
I am getting the following error:
java.lang.RuntimeException: Unable to destroy activity {package/package.MP3Player}: java.lang.IllegalArgumentException: Service not registered: package.MP3Player$1#b135b300
Do you know any advide?
Thanks in advance!
EDIT1:
I bound my player like this in my player activity:
MP3Player.java(Activity)
playIntent = new Intent(this, MP3Service.class);
bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
startService(playIntent);
I used this tutorial and modified it.
EDIT 3:
Now I get this error:
java.lang.RuntimeException: Unable to stop service package.MP3Service#b13a6f80: java.lang.IllegalStateException
MP3Service.java
public void onCreate() {
super.onCreate();
songPosn = 0;
player = new MediaPlayer();
initMusicPlayer();
}
public void initMusicPlayer() {
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
...
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
public void setList(ArrayList<Song> theSongs) {
songs = theSongs;
}
public class MusicBinder extends Binder {
MP3Service getService() {
return MP3Service.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return musicBind;
}
#Override
public boolean onUnbind(Intent intent) {
player.stop();
player.release();
return false;
}
public void playSong() {
player.reset();
Song playSong = songs.get(songPosn);
try {
player.setDataSource(getApplicationContext(),
Uri.parse(playSong.getPath()));
} catch (Exception e) {
Log.e("MUSIC SERVICE", "Error setting data source", e);
}
player.prepareAsync();
}
public void pauseMusic() {
if (player.isPlaying()) {
player.pause();
length = player.getCurrentPosition();
}
}
public void resumeMusic() {
if (player.isPlaying() == false) {
player.seekTo(this.length);
player.start();
} else {
Toast.makeText(getApplicationContext(),
"Please select a song to play", Toast.LENGTH_LONG).show();
}
}
public void stopMusic() {
player.stop();
player.release();
player = null;
}
// set the song
public void setSong(int songIndex) {
songPosn = songIndex;
}
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
#Override
public void onDestroy() {
super.onDestroy();
if (player != null) {
try {
player.stop();
player.release();
} finally {
player = null;
}
}
}
MP3Player.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mp3_player);
getActionBar().setDisplayHomeAsUpEnabled(true);
songList = getSongList();
listAdapter = new PlayListAdapter(this, songList);
listMusic.setAdapter(listAdapter);
listMusic.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int pos,
long arg3) {
currentSongPos = pos;
musicSrv.setSong(currentSongPos);
musicSrv.playSong();
}
});
}
private ServiceConnection musicConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicBinder binder = (MusicBinder) service;
musicSrv = binder.getService();
musicSrv.setList(songList);
musicBound = true;
}
#Override
public void onServiceDisconnected(ComponentName name) {
musicBound = false;
}
};
#Override
protected void onStart() {
super.onStart();
if (playIntent == null) {
playIntent = new Intent(this, MP3Service.class);
bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
startService(playIntent);
}
}
...
protected void onDestroy() {
if (musicBound) {
stopService(playIntent);
unbindService(musicConnection);
musicSrv = null;
}
super.onDestroy();
}
Service not registered means it wasn't bound to service during unbindService() call.
Read about service lifecycle on : API Guide: Services
EDIT:
Try to add:
protected void onDestroy() {
if(musicBound){
stopService(playIntent);
unbindService(musicConnection);
musicSrv=null;
}
super.onDestroy();
}
EDIT 2:
Sorry my fault, you need to call first stopService() and then unbindService()
The Android documentation for stopService() states:
Note that if a stopped service still has ServiceConnection objects bound to it with the BIND_AUTO_CREATE set, it will not be destroyed
until all of these bindings are removed. See the Service documentation
for more details on a service's lifecycle.

Pausing a service

i am writing a music player example using services.i am able to start and stop the service by using the activity which is in other application.but now i need to pause the player.how can i do this because their are no onpause method in services
Media Player
utilise : pause();
to restart: prepare()
start()
**LocalService.java** public class LocalService extends Service {
private NotificationManager mNM;
MediaPlayer mMediaPlayer;
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
LocalService getService() {
return LocalService.this;
}
}
#Override
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
}
#Override
public void onDestroy() {
mNM.cancel(R.string.local_service_started);
Toast.makeText(this, R.string.local_service_stopped, Toast.LENGTH_SHORT).show();
}
public void startMp3Player() {
mMediaPlayer = MediaPlayer.create(getApplicationContext(),
R.raw.abc);
mMediaPlayer.start();
}
public void mp3Stop() {
mMediaPlayer.stop();
mMediaPlayer.release();
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
**LocalServiceBinding.JAVA** public class LocalServiceBinding extends Activity {
private boolean mIsBound;
private LocalService mBoundService;
Button mPlayButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.local_service_binding);
Button button = (Button)findViewById(R.id.bind);
button.setOnClickListener(mBindListener);
button = (Button)findViewById(R.id.unbind);
button.setOnClickListener(mUnbindListener);
mPlayButton = (Button)findViewById(R.id.play);
mPlayButton.setOnClickListener(mPlayListener);
mPlayButton.setText("Play");
mPlayButton.setEnabled(false);
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mBoundService = ((LocalService.LocalBinder)service).getService();
Toast.makeText(LocalServiceBinding.this, R.string.local_service_connected,
Toast.LENGTH_SHORT).show();
}
public void onServiceDisconnected(ComponentName className) {
mBoundService = null;
Toast.makeText(LocalServiceBinding.this, R.string.local_service_disconnected,
Toast.LENGTH_SHORT).show();
}
};
private OnClickListener mBindListener = new OnClickListener() {
public void onClick(View v) {
bindService(new Intent(LocalServiceBinding.this,
LocalService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
mPlayButton.setEnabled(true);
}
};
private OnClickListener mPlayListener = new OnClickListener() {
public void onClick(View v) {
if(mPlayButton.getText() == "Play")
{
mBoundService.startMp3Player();
mPlayButton.setText("Stop");
}
else
{
mBoundService.mp3Stop();
mPlayButton.setText("Play");
}
}
};
private OnClickListener mUnbindListener = new OnClickListener() {
public void onClick(View v) {
if (mIsBound) {
unbindService(mConnection);
mIsBound = false;
mPlayButton.setEnabled(false);
}
}
};
}

Categories

Resources