After pressing back button on MainActivity (which calls it's onDestroy()), the media plays in the background (using foreground service).
But after opening the app again ((which calls it's onCreate()), and if I try to play another song, the first song is not stopped. Both songs play together. How do I solve this?
Any help is appreciated.
This is my MusicService class:
public void onCreate() {
super.onCreate();
Log.i(TAG3, "onCreate");
songPosn=0;
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mAudioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
player = new MediaPlayer();
initMusicPlayer();
rand=new Random();
}
//initializes the MediaPlayer class
public void initMusicPlayer(){
Log.i(TAG3, "initMusicPlayer");
player.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnPreparedListener(this);
player.setOnCompletionListener(this);
player.setOnErrorListener(this);
}
public void setList(ArrayList<Song> theSongs){
songs=theSongs;
}
//We will call this when the user picks a song from the list.
public void setSong(int songIndex){
songPosn=songIndex;
}
public class MusicBinder extends Binder {
MusicService getService() {
return MusicService.this;
}
}
//Let's now set the app up to play a track
public void playSong(){
Log.i(TAG3, "playSong");
player.reset();
//get song
Song playSong = songs.get(songPosn);
songTitle=playSong.getTitle();
//get id
long currSong = playSong.getID();
//set uri
Uri trackUri = ContentUris.withAppendedId(
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
currSong);
try{
player.setDataSource(getApplicationContext(), trackUri);
}
catch(Exception e){
Log.e("MUSIC SERVICE", "Error setting data source", e);
}
player.prepareAsync();
}
public void playPrev(){
songPosn--;
if(songPosn<0) songPosn=songs.size()-1;
playSong();
}
//skip to next
public void playNext(){
if(repeat){playSong();}
else if(shuffle){
int newSong = songPosn;
while(newSong==songPosn){
newSong=rand.nextInt(songs.size());
}
songPosn=newSong;
playSong();
}
else{
songPosn++;
if(songPosn>=songs.size()) songPosn=0;
playSong();
}
}
public int getPosn(){
return player.getCurrentPosition();
}
public int getDur(){
return dr;
}
public boolean isPng(){
return player.isPlaying();
}
public void pausePlayer(){
player.pause();
}
public void seek(int posn){
player.seekTo(posn);
}
public void go(){
player.start();
}
public void setShuffle(){
if(shuffle) shuffle=false;
else {shuffle=true;repeat=false;}
}
public void setRepeat(){
if(repeat) repeat=false;
else {repeat=true;shuffle=false;}
}
//When the MediaPlayer is prepared, the onPrepared method will be executed.
#Override
public void onPrepared(MediaPlayer mp) {
Log.i(TAG3, "onPrepared");
//start playback
mp.start();
dr = player.getDuration();
Intent notIntent = new Intent(this, MainActivity.class);
notIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendInt = PendingIntent.getActivity(this, 0,
notIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder builder = new Notification.Builder(this);
builder.setContentIntent(pendInt)
.setSmallIcon(R.drawable.play)
.setTicker(songTitle)
.setOngoing(true)
.setContentTitle("Playing").setContentText(songTitle);
Notification not = builder.build();
startForeground(NOTIFY_ID, not);
}
#Override
public void onCompletion(MediaPlayer mp) {
Log.i(TAG3, "onCompletion");
if(player.getCurrentPosition()>0){
mp.reset();
playNext();
}
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.i(TAG3, "onError");
mp.reset();
return false;
}
#Override
public void onAudioFocusChange(int focusChange) {
if(focusChange<=0) {
//LOSS -> PAUSE
player.pause();
} else {
//GAIN -> PLAY
player.start();
}
}
#Override
public IBinder onBind(Intent intent) {
Log.i(TAG3, "onBind");
return musicBind;
}
#Override
public boolean onUnbind(Intent intent){
Log.i(TAG3, "onUnbind");
return false;
}
#Override
public void onDestroy() {
Log.i(TAG3, "onDestroy");
mAudioManager.abandonAudioFocus(this);
stopForeground(true);
}
Note; I had removed player.stop(); player.release(); from the onUnbind() since the playback gets stopped on pressing backbutton on MainActivity.
The back button should not call onDestroy when pressed.
I found it here:
https://stackoverflow.com/a/5868534/6737655
Related
I'm creating a music player app and whenever i pause a song the seekbar and a textview which contains the current time of the song resets to 0 but resumes from the time it was paused at when i press play.
This is code the for my seekbar and textview in MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
seekBar.setProgress(getCurrentPosition());
}
},0,1);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
seekTo(progress);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
public void currentSongTime() {
int songCurrentTime = getCurrentPosition();
#SuppressLint("DefaultLocale")
String currTime = String.format("%2d:%02d",
TimeUnit.MILLISECONDS.toMinutes(songCurrentTime),
TimeUnit.MILLISECONDS.toSeconds(songCurrentTime) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(songCurrentTime))
);
startTime.setText(currTime);
}
and this is the code for my MusicService class
public class MusicService extends Service implements
MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener,
MediaPlayer.OnCompletionListener {
private MediaPlayer player;
private ArrayList<Song> songs;
private Random rand;
public boolean shuffleOn;
public int songPosn;
NowPlaying nowPlaying;
Song currentSong;
private final IBinder musicBind = new MusicBinder();
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return musicBind;
}
#Override
public boolean onUnbind(Intent intent){
return false;
}
#Override
public void onCompletion(MediaPlayer mp) {
if(player.getCurrentPosition()>0){
mp.reset();
playNext();
}
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mp.reset();
return false;
}
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
nowPlaying.updateTitleArtistAndPlayButton(currentSong);
}
public void onCreate(){
super.onCreate();
songPosn=0;
player = new MediaPlayer();
rand = new Random();
initMusicPlayer();
}
public void initMusicPlayer(){
player.setWakeMode(getApplicationContext(),
PowerManager.PARTIAL_WAKE_LOCK);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnPreparedListener(this);
player.setOnCompletionListener(this);
player.setOnErrorListener(this);
}
public void setList(ArrayList<Song> theSongs){
songs=theSongs;
}
public class MusicBinder extends Binder {
public MusicService getService() {
return MusicService.this;
}
}
public void playNext(){
if (shuffleOn) {
int newSong = songPosn;
while (newSong == songPosn) {
newSong = rand.nextInt(songs.size());
}
songPosn = newSong;
} else {
songPosn++;
if (songPosn >= songs.size()) songPosn = 0;
}
playSong();
}
public void playPrev(){
songPosn--;
if(songPosn <0) songPosn=songs.size()-1;
playSong();
}
public void setShuffle(){
if (shuffleOn) shuffleOn = true;
else shuffleOn = false;
}
public void playSong(){
player.reset();
Song playSong = songs.get(songPosn);
currentSong = playSong;
long currSong = playSong.getID();
Uri trackUri = ContentUris.withAppendedId(
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
currSong);
try{
player.setDataSource(getApplicationContext(), trackUri);
}
catch(Exception e){
Log.e("MUSIC SERVICE", "Error setting data source", e);
}
player.prepareAsync();
}
public void setSong(int songIndex, NowPlaying nowPlaying){
songPosn=songIndex;
this.nowPlaying = nowPlaying;
}
public int getPosn(){
return player.getCurrentPosition();
}
public int getDur(){
return player.getDuration();
}
public boolean isPng(){
return player.isPlaying();
}
public void pausePlayer(){
player.pause();
}
public void seek(int posn){
player.seekTo(posn);
}
public void go(){
player.start();
}
}
Thanks
EDIT
#Override
public int getCurrentPosition() {
if (musicSrv != null && musicBound && musicSrv.isPng())
return musicSrv.getPosn();
else return 0;
}
When I play the music and come on home the music is running, but when I kill the app music is restart. I want to run the music when I kill the app instead of it restarting.
Please help me.
My code is:----
MainActivity.java
public class MainActivity extends ActionBarActivity {
Context context;
private Button mPlay, mStop;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPlay = (Button) findViewById(R.id.button1);
mStop = (Button) findViewById(R.id.button2);
mPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent service = new Intent(MainActivity.this, Myservice.class);
startService(service);
}
});
mStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent name = new Intent(MainActivity.this, Myservice.class);
stopService(name);
}
});
}
}
And my service class is:---
public class Myservice extends Service implements
MediaPlayer.OnErrorListener{
private final IBinder mBinder = new ServiceBinder();
MediaPlayer mPlayer;
private int length = 0;
public Myservice() { }
public class ServiceBinder extends Binder {
Myservice getService()
{
return Myservice.this;
}
}
#Override
public IBinder onBind(Intent arg0){return mBinder;}
#Override
public void onCreate (){
super.onCreate();
mPlayer = MediaPlayer.create(this, R.raw.follow);
mPlayer.setOnErrorListener(this);
if(mPlayer!= null)
{
mPlayer.setLooping(true);
mPlayer.setVolume(100,100);
}
mPlayer.setOnErrorListener(new OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int
extra){
onError(mPlayer, what, extra);
return true;
}
});
}
#Override
public int onStartCommand (Intent intent, int flags, int startId)
{
mPlayer.start();
return START_STICKY;
}
public void pauseMusic()
{
if(mPlayer.isPlaying())
{
mPlayer.pause();
length=mPlayer.getCurrentPosition();
}
}
public void resumeMusic()
{
if(mPlayer.isPlaying()==false)
{
mPlayer.seekTo(length);
mPlayer.start();
}
}
public void stopMusic()
{
mPlayer.stop();
mPlayer.release();
mPlayer = null;
}
#Override
public void onDestroy ()
{
super.onDestroy();
if(mPlayer != null)
{
try{
/*mPlayer.stop();
mPlayer.release();*/
Toast.makeText(getApplicationContext(), "ondestroy", 2000).show();
}finally {
mPlayer = null;
}
}
}
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast.makeText(this, "music player failed", Toast.LENGTH_SHORT).show();
if(mPlayer != null)
{
try{
mPlayer.stop();
mPlayer.release();
}finally {
mPlayer = null;
}
}
return false;
}
}
Add the below method in your service and call the method when media starts playing. Foreground service are high priority service which are not killed by android system often, starting a foreground service needs a notification. you can manually stop foreground service by calling stopForeground(true). Please watch for basics of Media Playback State of Media Playback (Android Dev Summit 2015)
private static final String NOTIFICATION_ID = 91;
private void runAsForeground(){
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent=PendingIntent.getActivity(this, 0,
notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);
Notification notification=new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentText("Media is playing")
.setContentIntent(pendingIntent).build();
startForeground(NOTIFICATION_ID, notification);
}
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.
Am still new to android, but i followed a tutorial online in developing a radio Application, now this is the problem am encountering, i want this radio to keep playing, so that the app user can keep using the app or other application while the radio plays in the background. The radio stops playing when the user leave the streaming page.
private void startPlaying() {
buttonStopPlay.setEnabled(true);
buttonPlay.setEnabled(false);
player.start();
}
private void initializeMediaPlayer() {
player = new MediaPlayer();
try {
player.setDataSource(" radio URL");
player.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
player.start();
}
});
player.prepareAsync();
buttonStopPlay.setEnabled(true);
buttonPlay.setEnabled(true);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
player.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {
public void onBufferingUpdate(MediaPlayer mp, int percent) {
playSeekBar.setSecondaryProgress(percent);
Log.i("Buffering", "" + percent);
}
});
}
#Override
protected void onPause() {
super.onPause();
if (player.isPlaying()) {
player.pause();
buttonStopPlay.setEnabled(false);
buttonPlay.setEnabled(true);
}
}
refer this link
Intent svc=new Intent(this, BackgroundSoundService.class);
startService(svc);
public class BackgroundSoundService extends Service {
private static final String TAG = null;
MediaPlayer player;
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.idil);
player.setLooping(true); // Set looping
player.setVolume(100,100);
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return 1;
}
public void onStart(Intent intent, int startId) {
// TO DO
}
public IBinder onUnBind(Intent arg0) {
// TO DO Auto-generated method
return null;
}
public void onStop() {
}
public void onPause() {
}
#Override
public void onDestroy() {
player.stop();
player.release();
}
#Override
public void onLowMemory() {
}
}
I did a small simulation of background music play on Android, but it doesnt work... there's the code:
[my activity, in onCreate]
Intent music = new Intent(this, MusicService.class);
startService(music);
[and there's the class MusicService]
public class MusicService extends Service implements MediaPlayer.OnErrorListener {
private final IBinder mBinder = new ServiceBinder();
MediaPlayer mPlayer;
private int length = 0;
public class ServiceBinder extends Binder {
MusicService getService()
{
return MusicService.this;
}
}
#Override
public IBinder onBind(Intent arg0){
return mBinder;
}
#Override
public void onCreate () {
super.onCreate();
mPlayer = MediaPlayer.create(this, R.raw.song1);
mPlayer.setOnErrorListener(this);
if(mPlayer!= null)
{
mPlayer.setLooping(true);
mPlayer.setVolume(100,100);
}
mPlayer.setOnErrorListener(new OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int extra){
onError(mPlayer, what, extra);
return true;
}
});
}
#Override
public int onStartCommand (Intent intent, int flags, int startId)
{
mPlayer.start();
return START_STICKY;
}
public void pauseMusic()
{
if(mPlayer.isPlaying())
{
mPlayer.pause();
length=mPlayer.getCurrentPosition();
}
}
public void resumeMusic()
{
if(mPlayer.isPlaying()==false)
{
mPlayer.seekTo(length);
mPlayer.start();
}
}
public void stopMusic()
{
mPlayer.stop();
mPlayer.release();
mPlayer = null;
}
#Override
public void onDestroy ()
{
super.onDestroy();
if(mPlayer != null)
{
try{
mPlayer.stop();
mPlayer.release();
}
finally {
mPlayer = null;
}
}
}
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast.makeText(this, "music player failed", Toast.LENGTH_SHORT).show();
if(mPlayer != null)
{
try{
mPlayer.stop();
mPlayer.release();
}
finally {
mPlayer = null;
}
}
return false;
}
}
I can't hear any song in the emulator. I did complete the Manifest file like this:
<service
android:name="MusicService"
android:enabled="true">
</service>
Is there something else to add to the Manifest, is there a problem with my code or with my emulator?
Thank you!
I am shearing my code on background music play on Android. It will be solve your problem.
I head created two classes first one is MainActivity and second one is MyService.
MainActivity code is
public class MainActivity extends Activity implements OnClickListener {
private static final String TAG = "MainActivity";
Button play, stop;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
play = (Button) findViewById(R.id.play);
stop = (Button) findViewById(R.id.stop);
play.setOnClickListener(this);
stop.setOnClickListener(this);
}
#Override
public void onClick(View src) {
switch (src.getId()) {
case R.id.play:
Log.d(TAG, "onClick: starting srvice");
startService(new Intent(this, MyService.class));
break;
case R.id.stop:
Log.d(TAG, "onClick: stopping srvice");
stopService(new Intent(this, MyService.class));
break;
}
}
}
Now the MyService code is
public class MyService extends Service {
private static final String TAG = "MyService";
MediaPlayer player;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
player = MediaPlayer.create(this, R.raw.braincandy);
player.setLooping(false); // Set looping
}
#Override
public void onDestroy() {
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
player.stop();
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
player.start();
}
}
U have to create a "raw" folder in your "res" folder than paste your music file in that raw folder.