我正在创建一个音乐播放器应用程序,我正在使用Aidl服务。当我第一次播放歌曲时,它的工作效果很好。当我选择要播放的其他歌曲(我还在同一个活动中)时,它仍然会播放上一首歌曲。我正在使用Sharedprefrence(使用Gson)来保存当前的歌曲。 I System.out我的arraylist保存在共享prefrence中,它在Activity中正确保存。服务中的i i system.out,它从prefrence(1首歌曲)中选择缓存的歌曲,而我在保存前清除sharedpref缓存。
我甚至试图在播放我的2首歌之前清除服务中的缓存(onDestroy方法),它也可以正常工作!
服务类代码:
public class MediaPlayerService extends Service implements MediaPlayer.OnCompletionListener,
MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnSeekCompleteListener,
MediaPlayer.OnInfoListener, MediaPlayer.OnBufferingUpdateListener,
AudioManager.OnAudioFocusChangeListener {
public static final String ACTION_PLAY = "com.valdioveliu.valdio.audioplayer.ACTION_PLAY";
public static final String ACTION_PAUSE = "com.valdioveliu.valdio.audioplayer.ACTION_PAUSE";
public static final String ACTION_PREVIOUS = "com.valdioveliu.valdio.audioplayer.ACTION_PREVIOUS";
public static final String ACTION_NEXT = "com.valdioveliu.valdio.audioplayer.ACTION_NEXT";
public static final String ACTION_STOP = "com.valdioveliu.valdio.audioplayer.ACTION_STOP";
private MediaPlayer mediaPlayer;
//MediaSession
private MediaSessionManager mediaSessionManager;
private MediaSessionCompat mediaSession;
private MediaControllerCompat.TransportControls transportControls;
private static final int NOTIFICATION_ID = 101;
private int resumePosition;
private AudioManager audioManager;
private final IBinder iBinder = new LocalBinder();
private ArrayList<String> audioList = new ArrayList<>();
private int audioIndex = -1;
private int pos = 0;
private String activeAudio;
private boolean ongoingCall = false;
private PhoneStateListener phoneStateListener;
private TelephonyManager telephonyManager;
SharedPreferenceMusic sharedPreferenceMusic;
@Override
public IBinder onBind(Intent intent) {
return new IPhoneBookService.Stub() {
@Override
public boolean PauseMedia() throws RemoteException {
pauseMedia();
return false;
}
@Override
public boolean ResumeMedia() throws RemoteException {
resumeMedia();
return false;
}
@Override
public boolean NextMedia() throws RemoteException {
skipToNext();
return false;
}
@Override
public boolean PreviousMedia() throws RemoteException {
skipToPrevious();
return false;
}
@Override
public boolean StopMedia() throws RemoteException {
stopMedia();
return false;
}
};
}
public class LocalBinder extends Binder {
public MediaPlayerService getService() {
return MediaPlayerService.this;
}
}
@Override
public void onCreate() {
super.onCreate();
callStateListener();
registerBecomingNoisyReceiver();
register_playNewAudio();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
StorageUtil storage = new StorageUtil(getApplicationContext());
audioList.clear();
audioList = storage.loadAudio();
audioIndex = storage.loadAudioIndex();
sharedPreferenceMusic = new SharedPreferenceMusic(getApplicationContext());
if (audioIndex != -1 && audioIndex < audioList.size()) {
activeAudio = audioList.get(audioIndex);
} else {
stopSelf();
}
} catch (NullPointerException e) {
stopSelf();
}
//Request audio focus
if (requestAudioFocus() == false) {
stopSelf();
}
if (mediaSessionManager == null) {
try {
initMediaSession();
initMediaPlayer();
} catch (RemoteException e) {
e.printStackTrace();
stopSelf();
}
buildNotification(PlaybackStatus.PLAYING);
}
handleIncomingActions(intent);
return Service.START_STICKY;
}
private void initMediaPlayer() {
if (mediaPlayer != null) {
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = null;
}
if (mediaPlayer == null)
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnSeekCompleteListener(this);
mediaPlayer.setOnInfoListener(this);
mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
sharedPreferenceMusic.set_MUSIC_POS("0");
mediaPlayer.setDataSource(audioList.get(audioIndex));
sharedPreferenceMusic.set_PLAY("yes");
} catch (Exception e) {
e.printStackTrace();
stopSelf();
}
try{
}catch (Exception e){}
mediaPlayer.prepareAsync();
}
@Override
public boolean onUnbind(Intent intent) {
stopService(intent);
Log.e("unbind","unbind");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) {
stopMedia();
mediaPlayer.release();
}
removeAudioFocus();
//Disable the PhoneStateListener
if (phoneStateListener != null) {
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
}
removeNotification();
unregisterReceiver(becomingNoisyReceiver);
unregisterReceiver(playNewAudio);
stopSelf();
}
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
}
@Override
public void onCompletion(MediaPlayer mp) {
if (audioIndex == audioList.size() - 1) {
stopMedia();
stopSelf();
} else {
activeAudio = audioList.get(++audioIndex);
new StorageUtil(getApplicationContext()).storeAudioIndex(audioIndex);
sharedPreferenceMusic.set_MUSIC_POS(String.valueOf(audioIndex));
stopMedia();
mediaPlayer.reset();
initMediaPlayer();
Intent i = new Intent("android.intent.action.MAIN").putExtra("some_msg", audioIndex+"");
this.sendBroadcast(i);
}
stopMedia();
removeNotification();
stopSelf();*/
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
switch (what) {
case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
break;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
break;
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
break;
}
return false;
}
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
return false;
}
@Override
public void onPrepared(MediaPlayer mp) {
playMedia();
}
@Override
public void onSeekComplete(MediaPlayer mp) {
}
@Override
public void onAudioFocusChange(int focusState) {
switch (focusState) {
case AudioManager.AUDIOFOCUS_GAIN:
if (mediaPlayer == null) initMediaPlayer();
else if (!mediaPlayer.isPlaying()) mediaPlayer.start();
mediaPlayer.setVolume(1.0f, 1.0f);
break;
case AudioManager.AUDIOFOCUS_LOSS:
if (mediaPlayer.isPlaying()) mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
if (mediaPlayer.isPlaying()) mediaPlayer.pause();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
if (mediaPlayer.isPlaying()) mediaPlayer.setVolume(0.1f, 0.1f);
break;
}
}
private boolean requestAudioFocus() {
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
return true;
}
return false;
}
private boolean removeAudioFocus() {
if (audioManager != null) {
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
audioManager.abandonAudioFocus(this);
}else{
return false;
}
}
public void playMedia() {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
public void stopMedia() {
if (mediaPlayer == null) return;
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
}
public void pauseMedia() {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
resumePosition = mediaPlayer.getCurrentPosition();
}
}
public void resumeMedia() {
if(mediaPlayer!=null) {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.seekTo(resumePosition);
mediaPlayer.start();
}
}
}
public void skipToNext() {
if (audioIndex == audioList.size() - 1) {
audioIndex = 0;
activeAudio = audioList.get(audioIndex);
} else {
activeAudio = audioList.get(++audioIndex);
}
new StorageUtil(getApplicationContext()).storeAudioIndex(audioIndex);
Intent i = new Intent("android.intent.action.MAIN").putExtra("some_msg", audioIndex+"");
this.sendBroadcast(i);
stopMedia();
mediaPlayer.reset();
initMediaPlayer();
}
public void skipToPrevious() {
if (audioIndex == 0) {
audioIndex = audioList.size() - 1;
activeAudio = audioList.get(audioIndex);
} else {
//get previous in playlist
activeAudio = audioList.get(--audioIndex);
}
new StorageUtil(getApplicationContext()).storeAudioIndex(audioIndex);
sharedPreferenceMusic.set_MUSIC_POS(String.valueOf(audioIndex));
Intent i = new Intent("android.intent.action.MAIN").putExtra("some_msg", audioIndex+"");
this.sendBroadcast(i);
stopMedia();
mediaPlayer.reset();
initMediaPlayer();
}
private BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
pauseMedia();
buildNotification(PlaybackStatus.PAUSED);
}
};
private void registerBecomingNoisyReceiver() {
IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
registerReceiver(becomingNoisyReceiver, intentFilter);
}
private void callStateListener() {
telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
phoneStateListener = new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
case TelephonyManager.CALL_STATE_RINGING:
if (mediaPlayer != null) {
pauseMedia();
ongoingCall = true;
}
break;
case TelephonyManager.CALL_STATE_IDLE:
if (mediaPlayer != null) {
if (ongoingCall) {
ongoingCall = false;
resumeMedia();
}
}
break;
}
}
};
telephonyManager.listen(phoneStateListener,
PhoneStateListener.LISTEN_CALL_STATE);
}
private void initMediaSession() throws RemoteException {
mediaSessionManager = (MediaSessionManager) getSystemService(Context.MEDIA_SESSION_SERVICE);
mediaSession = new MediaSessionCompat(getApplicationContext(), "AudioPlayer");
transportControls = mediaSession.getController().getTransportControls();
mediaSession.setActive(true);
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
updateMetaData();
// Attach Callback to receive MediaSession updates
mediaSession.setCallback(new MediaSessionCompat.Callback() {
@Override
public void onPlay() {
super.onPlay();
resumeMedia();
buildNotification(PlaybackStatus.PLAYING);
}
@Override
public void onPause() {
super.onPause();
pauseMedia();
buildNotification(PlaybackStatus.PAUSED);
}
@Override
public void onSkipToNext() {
super.onSkipToNext();
skipToNext();
updateMetaData();
buildNotification(PlaybackStatus.PLAYING);
}
@Override
public void onSkipToPrevious() {
super.onSkipToPrevious();
skipToPrevious();
updateMetaData();
buildNotification(PlaybackStatus.PLAYING);
}
@Override
public void onStop() {
super.onStop();
removeNotification();
stopSelf();
}
@Override
public void onSeekTo(long position) {
super.onSeekTo(position);
}
});
}
private void updateMetaData() {
Bitmap albumArt = BitmapFactory.decodeResource(getResources(),
R.mipmap.icon); //replace with medias albumArt
mediaSession.setMetadata(new MediaMetadataCompat.Builder()
.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt)
.build());
}
private void buildNotification(PlaybackStatus playbackStatus) {
int notificationAction = android.R.drawable.ic_media_pause;//needs to be initialized
PendingIntent play_pauseAction = null;
if (playbackStatus == PlaybackStatus.PLAYING) {
notificationAction = android.R.drawable.ic_media_pause;
//create the pause action
play_pauseAction = playbackAction(1);
} else if (playbackStatus == PlaybackStatus.PAUSED) {
notificationAction = android.R.drawable.ic_media_play;
//create the play action
play_pauseAction = playbackAction(0);
}
Bitmap largeIcon = BitmapFactory.decodeResource(getResources(),
R.mipmap.icon); //replace with your own image
NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setShowWhen(false)
.setStyle(new NotificationCompat.MediaStyle()
.setMediaSession(mediaSession.getSessionToken())
.setShowActionsInCompactView(0, 1, 2))
.setColor(getResources().getColor(R.color.colorAccent))
// Set the large and small icons
.setLargeIcon(largeIcon)
.setSmallIcon(android.R.drawable.stat_sys_headset)
// Set Notification content information
/*.setContentText(activeAudio.getArtist())
.setContentTitle(activeAudio.getAlbum())
.setContentInfo(activeAudio.getTitle())*/
// Add playback actions
.addAction(android.R.drawable.ic_media_previous, "previous", playbackAction(3))
.addAction(notificationAction, "pause", play_pauseAction)
.addAction(android.R.drawable.ic_media_next, "next", playbackAction(2));
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID, notificationBuilder.build());
}
private PendingIntent playbackAction(int actionNumber) {
Intent playbackAction = new Intent(this, MediaPlayerService.class);
switch (actionNumber) {
case 0:
// Play
playbackAction.setAction(ACTION_PLAY);
return PendingIntent.getService(this, actionNumber, playbackAction, 0);
case 1:
// Pause
playbackAction.setAction(ACTION_PAUSE);
return PendingIntent.getService(this, actionNumber, playbackAction, 0);
case 2:
// Next track
playbackAction.setAction(ACTION_NEXT);
return PendingIntent.getService(this, actionNumber, playbackAction, 0);
case 3:
// Previous track
playbackAction.setAction(ACTION_PREVIOUS);
return PendingIntent.getService(this, actionNumber, playbackAction, 0);
default:
break;
}
return null;
}
private void removeNotification() {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(NOTIFICATION_ID);
}
private void handleIncomingActions(Intent playbackAction) {
if (playbackAction == null || playbackAction.getAction() == null) return;
String actionString = playbackAction.getAction();
if (actionString.equalsIgnoreCase(ACTION_PLAY)) {
transportControls.play();
} else if (actionString.equalsIgnoreCase(ACTION_PAUSE)) {
transportControls.pause();
} else if (actionString.equalsIgnoreCase(ACTION_NEXT)) {
transportControls.skipToNext();
} else if (actionString.equalsIgnoreCase(ACTION_PREVIOUS)) {
transportControls.skipToPrevious();
} else if (actionString.equalsIgnoreCase(ACTION_STOP)) {
transportControls.stop();
}
}
private BroadcastReceiver playNewAudio = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//Get the new media index form SharedPreferences
sharedPreferenceMusic = new SharedPreferenceMusic(context);
audioIndex = new StorageUtil(getApplicationContext()).loadAudioIndex();
StorageUtil storage = new StorageUtil(context);
audioList = storage.loadAudio();
if (audioIndex != -1 && audioIndex < audioList.size()) {
activeAudio = audioList.get(audioIndex);
} else {
stopSelf();
}
stopMedia();
if(mediaPlayer!=null) {
mediaPlayer.reset();
}
initMediaPlayer();
updateMetaData();
buildNotification(PlaybackStatus.PLAYING);
}
};
private void register_playNewAudio() {
IntentFilter filter = new IntentFilter(MainNavMusicianActivity.Broadcast_PLAY_NEW_AUDIO);
registerReceiver(playNewAudio, filter);
}
}
在共享的Pref和播放音频中保存数据
private void loadAudio(String url,String name,String vibe,String id) {
if(playerIntent!=null){
stopService(playerIntent);
}
unbindService(syncAndTradeServiceConnection);
new StorageUtil(DescMusicianDiscoverActivity.this).clearCachedAudioPlaylist();
audioList = new ArrayList<>();
audioListName = new ArrayList<>();
audioListVibe = new ArrayList<>();
audioListId = new ArrayList<>();
audioList.add(url);
audioListName.add(name);
audioListVibe.add(vibe);
audioListId.add(id);
playAudio(0);
}
private void playAudio(int audioIndex) {
sharedPreferenceMusic.set_MUSIC_POS(String.valueOf(audioIndex));
StorageUtil storage = new StorageUtil(DescMusicianDiscoverActivity.this);
storage.clearCachedAudioPlaylist();
storage.storeAudio(audioList,audioListName,audioListVibe,audioListId);
storage.storeAudioIndex(audioIndex);
playerIntent = new Intent(DescMusicianDiscoverActivity.this, MediaPlayerService.class);
storage.clearCachedAudioPlaylist();
storage.storeAudio(audioList,audioListName,audioListVibe,audioListId);
storage.storeAudioIndex(audioIndex);
startService(playerIntent);
bindService(playerIntent, syncAndTradeServiceConnection, Context.BIND_AUTO_CREATE);
}