如果应用关闭,如何播放音乐

时间:2016-03-25 19:20:44

标签: java android service android-mediaplayer

我想构建一个音乐应用程序,如果用户在通知中触摸停止,我的音乐播放器应该停止。

如果用户关闭应用程序,音乐不应该停止(如果可能,用户也会清除应用程序历史记录)!

我正在使用服务播放音乐:

public class MusicService extends Service
    implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener,
        AudioManager.OnAudioFocusChangeListener {

//region Variables

private MediaPlayer mediaPlayer;
private Song[] sSongs;
private int iSongPosition;

private PlayMode playMode;

private static final int NOTIFY_ID = 1;

private final IBinder musicBinder = new MusicBinder();

private AudioManager audioManager;

private Handler handler;

public ServiceInterface serviceInterface;

private Notification notification;

//endregion

//region Service-Methods

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

    mediaPlayer = new MediaPlayer();

    iSongPosition = 0;
    playMode = PlayMode.PASS;

    mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

    mediaPlayer.setOnPreparedListener(this);
    mediaPlayer.setOnCompletionListener(this);
    mediaPlayer.setOnErrorListener(this);

    audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);

    int iAudioReqResult = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);

    if (iAudioReqResult != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
        new AlertDialog.Builder(this)
                .setTitle("Sorry.")
                .setMessage("Musixs wasn't able to gain the AudioStream garanted!")
                .setCancelable(false)
                .show();
    }

    handler = new Handler();

    serviceInterface = new ServiceInterface() {

        @Override
        public void MP_PlayPause() {
            if (isPlaying()) {
                pause();
            }
            else {
                start();
            }
        }

        @Override
        public void MP_PlayPrev() {
            playPrev();
        }

        @Override
        public void MP_PlayNext() {
            playNext();
        }

        @Override
        public boolean MP_isPlaying() {
            return isPlaying();
        }

        @Override
        public int MP_getDuration() {
            return getDuration();
        }

        @Override
        public int MP_getCurrentPosition() {
            return getCurrentPosition();
        }

        @Override
        public Song MP_getActualSong() {
            return getActualSong();
        }

        @Override
        public void MP_seekTo(int pos) {
            seekTo(pos);
        }
    };
}

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

@Override
public boolean onUnbind(Intent intent) {
    mediaPlayer.stop();
    mediaPlayer.release();

    return super.onUnbind(intent);
}

@Override
public void onCompletion(MediaPlayer mp) {
    mp.reset();

    if (playMode == PlayMode.REPEAT_SINGLE) {
        playSong(iSongPosition);

        return;
    }

    if (playMode == PlayMode.SHUFFLE) {
        iSongPosition = new Random().nextInt(sSongs.length);

        playSong(iSongPosition);

        return;
    }

    iSongPosition++;

    if (iSongPosition == sSongs.length) {
        if (playMode == PlayMode.REPEAT_ALL) {
            iSongPosition = 0;

            playSong(iSongPosition);
        }
        else {
            mp.stop();
            mp.release();
        }
    }
    else {
        playSong(iSongPosition);
    }
}

@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
    mp.reset();

    return false;
}

@Override
public void onPrepared(MediaPlayer mp) {
    mp.start();

    Intent notIntent = new Intent(getApplicationContext(), PlayActivity.class);
    notIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

    PendingIntent notPendignIntent = PendingIntent.getActivity(getApplicationContext(), 0, notIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    PlayActivity.setServiceInterface(serviceInterface);

    Notification.Builder nBuilder = new Notification.Builder(this);

    nBuilder.setContentIntent(notPendignIntent)
            .setSmallIcon(android.R.drawable.ic_media_play)
            .setTicker(getActualSong().getTitle())
            .setOngoing(true)
            .setContentTitle(getString(R.string.app_name))
            .setContentText(getActualSong().getTitle());

    notification = nBuilder.build();

    startForeground(NOTIFY_ID, notification);
}

@Override
public void onDestroy() {
    super.onDestroy();

    stopForeground(true);
}

@Override
public void onAudioFocusChange(int focusChange) {
    audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
}

//endregion

//region Methods

public void setSongs(Song[] songs) {
    sSongs = songs;
}

public void setPlayMode(PlayMode mode) {
    playMode = mode;
}

public void playSong(int index) {
    mediaPlayer.reset();

    iSongPosition = index;

    Song playSong = sSongs[iSongPosition];

    long playSongID = playSong.getID();

    Uri trackUri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, playSongID);

    try {
        mediaPlayer.setDataSource(getApplicationContext(), trackUri);
    }
    catch (IOException ioe) {
        ioe.printStackTrace();
    }

    mediaPlayer.prepareAsync();
}

public void playNext() {
    iSongPosition++;

    if (iSongPosition == sSongs.length) {
        iSongPosition = 0;
    }

    playSong(iSongPosition);
}

public void playPrev() {
    iSongPosition--;

    if (iSongPosition < 0) {
        iSongPosition = sSongs.length - 1;
    }

    playSong(iSongPosition);
}

public Song getActualSong() {
    return sSongs[iSongPosition];
}

public int getActualSongPosition() {
    return iSongPosition;
}

public PlayMode getPlayMode() {
    return playMode;
}

//region MediaController-Methods

public void start() {
    mediaPlayer.start();

    startForeground(NOTIFY_ID, notification);
}

public void pause() {
    mediaPlayer.pause();

    stopForeground(true);
}

public int getDuration() {
    return mediaPlayer.getDuration();
}

public int getCurrentPosition() {
    return mediaPlayer.getCurrentPosition();
}

public void seekTo(int pos) {
    mediaPlayer.seekTo(pos);
}

public boolean isPlaying() {
    return mediaPlayer.isPlaying();
}

public int getBufferPercentage() {
    return (mediaPlayer.getCurrentPosition() * 100) / mediaPlayer.getDuration();
}

public boolean canPause() {
    return mediaPlayer.isPlaying();
}

public boolean canSeekBackward() {
    return mediaPlayer.getCurrentPosition() != 0;
}

public boolean canSeekForward() {
    return mediaPlayer.getCurrentPosition() == mediaPlayer.getDuration();
}

//endregion

//endregion

public class MusicBinder extends Binder {
    public MusicService getService() {
        return MusicService.this;
    }
}

我的服务是在MainActivity中启动的:

@Override
protected void onStart() {
    super.onStart();

    if (playIntent == null) {
        playIntent = new Intent(this, MusicService.class);

        bindService(playIntent, musicServiceConn, BIND_AUTO_CREATE);

        startService(playIntent);
    }
}

我的服务连接:

musicServiceConn = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        MusicService.MusicBinder musicBinder = (MusicService.MusicBinder) service;

        musicService = musicBinder.getService();

        bMusicServiceConnected = true;

        musicService.setSongs(sSongs);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        bMusicServiceConnected = false;
    }
};

实际上,如果我关闭应用程序(清除应用程序历史记录)或按下后退按钮,我的MediaPlayer就会停止。

完整代码: https://github.com/guger/Musixs

我希望你能帮助我! 谢谢!

1 个答案:

答案 0 :(得分:1)

您需要覆盖服务中的onStartCommand并返回START_STICKY