0

I am streaming music in a background service. Everything works fine except when I remove the app from recent app list the service destroyed . The approach I used to make the service run as sticky work fine when there is no mediaplayer . Here is my code

public class StreamListenerService extends Service implements MediaPlayer.OnPreparedListener,
        MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener {

    public static MediaPlayer mMediaPlayer;
    private String streamUrl;
    public static boolean isPlaying = false;


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        streamUrl = intent.getStringExtra("streamUrl");



        mMediaPlayer = new MediaPlayer();
        mMediaPlayer.reset();
        mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);


        try {
            mMediaPlayer.setDataSource(streamUrl);
        } catch (IOException e) {
            e.printStackTrace();
        }


        mMediaPlayer.setOnPreparedListener(this);
        mMediaPlayer.setOnErrorListener(this);
        mMediaPlayer.prepareAsync();
        mMediaPlayer.setOnCompletionListener(this);

        isPlaying = true;

        return Service.START_STICKY_COMPATIBILITY;
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        Log.d("StreamListenerService", "onDestroy");
        if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
            mMediaPlayer.stop();
            mMediaPlayer.reset();
            isPlaying = false;
        }
        super.onDestroy();

    }


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onPrepared(MediaPlayer mediaPlayer) {
        mMediaPlayer.start();
        isPlaying = true;
    }

    @Override
    public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {

        Toast.makeText(this, R.string.text_problem_in_playing_audio_stream, Toast.LENGTH_SHORT).show();

        mMediaPlayer.stop();
        mMediaPlayer.reset();

        //Toast.makeText(this, R.string.text_problem_in_playing_stream,Toast.LENGTH_SHORT).show();

        this.onDestroy();
        return false;
    }


    @Override
    public void onCompletion(MediaPlayer mp) {
        Toast.makeText(this, R.string.text_stream_finished, Toast.LENGTH_SHORT).show();
        mMediaPlayer = mp;
        mMediaPlayer.stop();
        mMediaPlayer.reset();
        this.onDestroy();
    }
}
mSapps
  • 601
  • 9
  • 24
  • 1
    As far as I know when you swipe away an app in the recents list it can kill everything relating to your app. This includes any services. See here: http://stackoverflow.com/questions/30936888/differentiate-between-android-killing-the-app-and-user-swiping-it-off-on-the-rec – FrankR Jan 18 '17 at 14:30
  • This is a serious problem and the answers below suggesting using foreground service as a solution are not a solution because despite the foreground service we still see this buggy behavior. I assume it is a bug in Android relating to the use of mediaplayer and should be reported. –  Jul 09 '21 at 09:15

2 Answers2

2

You need to specify that the service runs in its own process in your app manifest, by adding the attribute android:process=":whatever" to the service tag. This will ensure that the service isn't killed when your app's main process is, i.e. when the app is removed from the apps list.

If you want to make a service run until the user wants to stop, start it as a foreground service. You do this by calling startForeground in the service at some point. You need to pass a notification id (integer of your own choosing) and a Notification to startForeground. The notification will stay in the task bar until the user stops the service. You should, of course, provide a PendingIntent to stop the service in the notification or in one of the notification's actions.

Haem
  • 929
  • 6
  • 15
  • 31
1

When your application gets destroyed, any of your services stop as well. The problem is that you probably start your service only with startService and stop it with stopService. What you have to do is start your service with startForeground method inside onStartCommand in your service class.

@Override
    public int onStartCommand(Intent i, int flags, int startId) {

        Intent resultIntent = new Intent(SOME_INTENT_ACTION);
        PendingIntent resultPendingIntent = PendingIntent.getBroadcast(this, 0, resultIntent, 0);

        Notification noti = new Notification.Builder(getApplicationContext())
                .setContentTitle(TITLE)
                .setContentText(CONTENT_TEXT)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentIntent(resultPendingIntent)
                .build();

        startForeground(12345, noti);

        return Service.START_STICKY;
    }

Then your service is going to run on another thread and will work even if your application gets killed. It is important that you show local notification for the user to point out that some background service is running.