简体   繁体   中英

Android service with mediaplayer destroyed when app detached from widow

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();
    }
}

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, ie 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM