Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Service onStartCommand being called once activity ends

Tags:

android

I start my service when I click the play button to play a song and bundle the song mp3 with it and receive that in the onStartCommand. The problem is that when my activity that starts the service ends, my service calls onStartCommand again. When it goes to receive that bundle it's not there because the activity did not start it this time. Because of this I'm getting an illegalstateexception when preparing my mediaplayer. I am not binding my service.

Why does the onStartCommand get called when my activity ends?

Starting the service:

Intent i = new Intent(SongList.this,MyService.class);
i.putExtra("songURL", user.songurlz);
i.putExtra("songNAME", songplay_name);
startService(i);

The service class:

public class MyService extends Service {

    static MediaPlayer mediaPlayer;
    static int pauseplay;
    static NotificationManager notificationManagerPlay;
    static CharSequence tickerText;
    static Notification notification4;//Notification variable(for song playing)
    TelephonyManager telephonyManager;
    PhoneStateListener listener;
    static Notification notification;
    static NotificationManager mNotificationManager;
    String songurl;
    String songname;

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mediaPlayer = new MediaPlayer();
        pauseplay = 1;
        MainMenu.serviceRunning = 1;
        telephonyManager = (TelephonyManager) getSystemService(
                Context.TELEPHONY_SERVICE);
        // Create a new PhoneStateListener
        listener = new PhoneStateListener() {

            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                switch (state) {
                case TelephonyManager.CALL_STATE_IDLE:
                    break;
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    break;
                case TelephonyManager.CALL_STATE_RINGING:
                    if (mediaPlayer.isPlaying() == true && mediaPlayer != null){
                        pauseSong();
                    }
                    break;
                }
            }
        };
        // Register the listener wit the telephony manager
        telephonyManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
    }

    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        if (intent != null) {
            Bundle bundle = intent.getExtras();
            //Retrieve your data using the name
            songurl = bundle.getString("songURL");
            Bundle bundle2 = intent.getExtras();
            //Retrieve your data using the name
            songname = bundle2.getString("songNAME");
        }
        Toast toast = Toast.makeText(getApplicationContext(), "Now Playing: "
                + songname, Toast.LENGTH_LONG);
        toast.show();
        // configure the intent
        Intent playIntent = new Intent(MyService.this, SongList.class);
        final PendingIntent pendingIntent = PendingIntent.getActivity(
                MyService.this, 0, playIntent, 0);
        notification = new Notification(R.drawable.playicon, "Buffering...",
                System.currentTimeMillis());
        notification.contentView = new RemoteViews(getPackageName(),
                R.layout.custom_notification2);
        notification.contentIntent = pendingIntent;
        if (SongList.bitmap != null) {
            notification.contentView.setImageViewBitmap(R.id.notifimage,
                    SongList.bitmap);
        } else {
            notification.contentView.setImageViewResource(R.id.notifimage,
                    R.drawable.icon);
        }
        notification.contentView
                .setTextViewText(R.id.notiftitle, "Now Playing");
        notification.contentView.setTextViewText(R.id.notiftext, songname);
        notification.flags = notification.flags
                | Notification.FLAG_ONGOING_EVENT;
        mNotificationManager = (NotificationManager) getApplicationContext()
                .getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(4, notification);
        mediaPlayer.reset();
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        try {
            mediaPlayer.setDataSource(songurl);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // register an error listener via MediaPlayer's setOnErrorListener
        mediaPlayer.setOnErrorListener(new OnErrorListener() {

            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                Log.e("MEDIAPLAYER ERRORS", "what: " + what + "  extra: "
                        + extra);
                mediaPlayer.reset();
                mNotificationManager.cancel(4);
                return false;
            }
        });
        mediaPlayer.prepareAsync();
        mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

            @Override
            public void onPrepared(MediaPlayer mp) {
                mediaPlayer.start();
            }
        });
        mediaPlayer
                .setOnCompletionListener(new MediaPlayer.OnCompletionListener(){

                    public void onCompletion(MediaPlayer mp) {
                        stopSelf();
                    }
                });
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        MainMenu.serviceRunning = 0;
        mNotificationManager.cancel(4);
    }

    public static void pauseSong() {
        if (mediaPlayer.isPlaying() == true) {
            mediaPlayer.pause();
            mNotificationManager.cancel(4);
            pauseplay = 0;
        }
    }

    public static void playSong() {
        if (pauseplay == 0) {
            mNotificationManager.notify(4, notification);
            mediaPlayer.start();
            pauseplay = 1;
        }
    }
}
like image 310
Nick Nelson Avatar asked Feb 22 '12 17:02

Nick Nelson


People also ask

What is onStartCommand service?

onStartCommand() is called every time a client starts the service using startService(Intent intent) . This means that onStartCommand() can get called multiple times. You should do the things in this method that are needed each time a client requests something from your service.

How to stop foreground service from activity?

To start a foreground service, call startForeground() . To stop it, call stopForeground() .

How do I contact onStartCommand?

startService() then the system will retrieve the service (creating it and calling its onCreate() method if needed) and then call its onStartCommand(Intent, int, int) method with the arguments supplied by the client. The service will at this point continue running until Context. stopService() or stopSelf() is called.

How to call Android service?

A service is started when an application component, such as an activity, starts it by calling startService(). Once started, a service can run in the background indefinitely, even if the component that started it is destroyed. A service is bound when an application component binds to it by calling bindService().


2 Answers

Why does the onStartCommand get called when my activity ends?

Either you are calling startService() when your "activity ends" (whatever that means), or Android is restarting your service for some reason due to your use of START_STICKY.

Personally, for a music player, I argue that START_NOT_STICKY is the right answer. If your service is stopped for whatever reason, the user should be in charge of starting it up again.

like image 62
CommonsWare Avatar answered Sep 21 '22 15:09

CommonsWare


I know that this answer might not be useful anymore, but I had the same issue and by checking the documentation of this return code for onStartCommand I found that it will solve the issue.

EDIT:

Your onStartCommand should be like this:

public int onStartCommand(Intent intent, int flags, int startId)
{
    //the same code
    //......
    //then return the new code which I'm pointing to
    return START_REDELIVER_INTENT;
}

Here's what the documentation say about this return code:

public static final int START_REDELIVER_INTENT

Constant to return from onStartCommand(Intent, int, int): if this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), then it will be scheduled for a restart and the last delivered Intent re-delivered to it again via onStartCommand(Intent, int, int).

Using this return code will make the OS resend the Intent every time the method onStartCommand recalled (for whatever reason might cause this).

like image 41
Mohamed M. Abd ElHafiz Avatar answered Sep 22 '22 15:09

Mohamed M. Abd ElHafiz