这是我的音频播放器通知问题列表:
这是我的代码:
MediaPlayerService.java:
public class MediaPlayerService extends Service implements MediaPlayer.OnCompletionListener,
MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnSeekCompleteListener,
MediaPlayer.OnInfoListener, MediaPlayer.OnBufferingUpdateListener,
AudioManager.OnAudioFocusChangeListener {
// Binder given to clients
private final IBinder iBinder = new LocalBinder();
public MediaPlayer mediaPlayer;
//path to the audio file
private String mediaFile;
public int resumePosition;
private AudioManager audioManager;
//Handle incoming phone calls
private boolean ongoingCall = false;
private PhoneStateListener phoneStateListener;
private TelephonyManager telephonyManager;
public static final String ACTION_PLAY = "com.example.mili.musicplayer2.ACTION_PLAY";
public static final String ACTION_PAUSE = "com.example.mili.musicplayer2.ACTION_PAUSE";
public static final String ACTION_PREVIOUS = "com.example.mili.musicplayer2.ACTION_PREVIOUS";
public static final String ACTION_NEXT = "com.example.mili.musicplayer2.ACTION_NEXT";
public static final String ACTION_STOP = "com.example.mili.musicplayer2.ACTION_STOP";
//MediaSession
private MediaSessionManager mediaSessionManager;
private MediaSessionCompat mediaSession;
private MediaControllerCompat.TransportControls transportControls;
//AudioPlayer notification ID
private static final int NOTIFICATION_ID = 101;
@Override
public void onCreate() {
super.onCreate();
// Perform one-time setup procedures
// Manage incoming phone calls during playback.
// Pause MediaPlayer on incoming call,
// Resume on hangup.
callStateListener();
//ACTION_AUDIO_BECOMING_NOISY -- change in audio outputs -- BroadcastReceiver
registerBecomingNoisyReceiver();
//Listen for new Audio to play -- BroadcastReceiver
}
@Override
public IBinder onBind(Intent intent) {
return iBinder;
}
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
//Invoked indicating buffering status of
//a media resource being streamed over the network.
}
@Override
public void onCompletion(MediaPlayer mp) {
//Invoked when playback of a media source has completed.
stopMedia();
//stop the service
stopSelf();
}
//Handle errors
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
//Invoked when there has been an error during an asynchronous operation
switch (what) {
case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
Log.d("MediaPlayer Error", "MEDIA ERROR NOT VALID FOR PROGRESSIVE PLAYBACK " + extra);
break;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
Log.d("MediaPlayer Error", "MEDIA ERROR SERVER DIED " + extra);
break;
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
Log.d("MediaPlayer Error", "MEDIA ERROR UNKNOWN " + extra);
break;
}
return false;
}
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
//Invoked to communicate some info.
return false;
}
@Override
public void onPrepared(MediaPlayer mp) {
//Invoked when the media source is ready for playback.
playMedia();
}
@Override
public void onSeekComplete(MediaPlayer mp) {
//Invoked indicating the completion of a seek operation.
}
@Override
public void onAudioFocusChange(int focusState) {
//Invoked when the audio focus of the system is updated.
switch (focusState) {
case AudioManager.AUDIOFOCUS_GAIN:
// resume playback
if (mediaPlayer == null) initMediaPlayer();
else if (!mediaPlayer.isPlaying()) mediaPlayer.start();
mediaPlayer.setVolume(1.0f, 1.0f);
break;
case AudioManager.AUDIOFOCUS_LOSS:
// Lost focus for an unbounded amount of time: stop playback and release media player
if (mediaPlayer.isPlaying()) mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
// Lost focus for a short time, but we have to stop
// playback. We don't release the media player because playback
// is likely to resume
if (mediaPlayer.isPlaying()) mediaPlayer.pause();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// Lost focus for a short time, but it's ok to keep playing
// at an attenuated level
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) {
//Focus gained
return true;
}
//Could not gain focus
return false;
}
private boolean removeAudioFocus() {
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
audioManager.abandonAudioFocus(this);
}
public class LocalBinder extends Binder {
public MediaPlayerService getService() {
return MediaPlayerService.this;
}
}
private void initMediaPlayer() {
mediaPlayer = new MediaPlayer();
//Set up MediaPlayer event listeners
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnSeekCompleteListener(this);
mediaPlayer.setOnInfoListener(this);
//Reset so that the MediaPlayer is not pointing to another data source
mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
// Set the data source to the mediaFile location
mediaPlayer.setDataSource(mediaFile);
} catch (IOException e) {
e.printStackTrace();
stopSelf();
}
mediaPlayer.prepareAsync();
}
private void playMedia() {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
private 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.isPlaying()) {
mediaPlayer.seekTo(resumePosition);
mediaPlayer.start();
}
}
//The system calls this method when an activity, requests the service be started
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
//An audio file is passed to the service through putExtra();
mediaFile = intent.getExtras().getString("media");
} catch (NullPointerException e) {
stopSelf();
}
//Request audio focus
if (requestAudioFocus() == false) {
//Could not gain focus
stopSelf();
}
if (mediaFile != null && mediaFile != "")
initMediaPlayer();
if (mediaSessionManager == null) {
try {
initMediaSession();
initMediaPlayer();
} catch (RemoteException e) {
e.printStackTrace();
stopSelf();
}
buildNotification(PlaybackStatus.PLAYING);
}
//Handle Intent action from MediaSession.TransportControls
handleIncomingActions(intent);
return super.onStartCommand(intent, flags, startId);
}
//Becoming noisy
private BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//pause audio on ACTION_AUDIO_BECOMING_NOISY
pauseMedia();
buildNotification(PlaybackStatus.PAUSED);
}
};
private void registerBecomingNoisyReceiver() {
//register after getting audio focus
IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
registerReceiver(becomingNoisyReceiver, intentFilter);
}
//Handle incoming phone calls
private void callStateListener() {
// Get the telephony manager
telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
//Starting listening for PhoneState changes
phoneStateListener = new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
//if at least one call exists or the phone is ringing
//pause the MediaPlayer
case TelephonyManager.CALL_STATE_OFFHOOK:
case TelephonyManager.CALL_STATE_RINGING:
if (mediaPlayer != null) {
pauseMedia();
ongoingCall = true;
}
break;
case TelephonyManager.CALL_STATE_IDLE:
// Phone idle. Start playing.
if (mediaPlayer != null) {
if (ongoingCall) {
ongoingCall = false;
resumeMedia();
}
}
break;
}
}
};
// Register the listener with the telephony manager
// Listen for changes to the device call state.
telephonyManager.listen(phoneStateListener,
PhoneStateListener.LISTEN_CALL_STATE);
}
@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();
//unregister BroadcastReceivers
unregisterReceiver(becomingNoisyReceiver);
}
private void initMediaSession() throws RemoteException {
if (mediaSessionManager != null) return; //mediaSessionManager exists
// Create a new MediaSession
mediaSession = new MediaSessionCompat(getApplicationContext(), "AudioPlayer");
//Get MediaSessions transport controls
transportControls = mediaSession.getController().getTransportControls();
//set MediaSession -> ready to receive media commands
mediaSession.setActive(true);
//indicate that the MediaSession handles transport control commands
// through its MediaSessionCompat.Callback.
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
//Set mediaSession's MetaData
updateMetaData();
// Attach Callback to receive MediaSession updates
mediaSession.setCallback(new MediaSessionCompat.Callback() {
// Implement callbacks
@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();
//Stop the service
stopSelf();
}
@Override
public void onSeekTo(long position) {
super.onSeekTo(position);
}
});
}
private void updateMetaData() {
Bitmap albumArt = BitmapFactory.decodeResource(getResources(),
R.drawable.image); //replace with medias albumArt
// Update the current metadata
mediaSession.setMetadata(new MediaMetadataCompat.Builder()
.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt)
.build());
}
private void skipToNext() {
Toast.makeText(this, "Next Song", Toast.LENGTH_SHORT).show();
}
private void skipToPrevious() {
Toast.makeText(this, "Next Song", Toast.LENGTH_SHORT).show();
}
private void buildNotification(PlaybackStatus playbackStatus) {
int notificationAction = android.R.drawable.ic_media_pause;//needs to be initialized
PendingIntent play_pauseAction = null;
//Build a new notification according to the current state of the MediaPlayer
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.drawable.image); //replace with your own image
// Create a new Notification
NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setShowWhen(false)
.setAutoCancel(false)
.setOngoing(true)
// Set the Notification style
.setStyle(new android.support.v4.media.app.NotificationCompat.MediaStyle()
// Attach our MediaSession token
.setMediaSession(mediaSession.getSessionToken())
// Show our playback controls in the compact notification view.
.setShowActionsInCompactView(0, 1, 2))
// Set the Notification color
.setColor(getResources().getColor(R.color.colorPrimary))
// Set the large and small icons
.setLargeIcon(largeIcon)
.setSmallIcon(android.R.drawable.stat_sys_headset)
// Set Notification content information
.setContentInfo("I'm Content Info")
.setContentTitle("My notification")
.setContentText("Hello World!")
// 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 void removeNotification() {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(NOTIFICATION_ID);
}
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 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();
}
}
}
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private MediaPlayerService player;
boolean serviceBound = false;
ArrayList<Audio> audioList;
ImageButton playBtn, forwardBtn, backwardBtn;
TextView currentPosText, totalTimeText;
SeekBar seekBar;
private double startTime = 0;
private double finalTime = 0;
private Handler myHandler = new Handler();
private int forwardTime = 15000;
private int backwardTime = 15000;
public static int oneTimeOnly = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
player = new MediaPlayerService();
playBtn = findViewById(R.id.playBtn);
forwardBtn = findViewById(R.id.forwardBtn);
backwardBtn = findViewById(R.id.backwardBtn);
currentPosText = findViewById(R.id.currentPosText);
totalTimeText = findViewById(R.id.totalTimeText);
seekBar = findViewById(R.id.seekBar);
seekBar.setClickable(true);
playBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
playAudio("https://upload.wikimedia.org/wikipedia/commons/6/6c/Grieg_Lyric_Pieces_Kobold.ogg");
doSomeJob();
}
});
playAudio("https://upload.wikimedia.org/wikipedia/commons/6/6c/Grieg_Lyric_Pieces_Kobold.ogg");
}
private void doSomeJob(){
finalTime = getDuration();
startTime = getCurrentPosition();
if (oneTimeOnly == 0) {
seekBar.setMax((int) finalTime);
oneTimeOnly = 1;
}
totalTimeText.setText(String.format("%d min, %d sec",
TimeUnit.MILLISECONDS.toMinutes((long) finalTime),
TimeUnit.MILLISECONDS.toSeconds((long) finalTime) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) finalTime)))
);
currentPosText.setText(String.format("%d min, %d sec",
TimeUnit.MILLISECONDS.toMinutes((long) startTime),
TimeUnit.MILLISECONDS.toSeconds((long) startTime) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) startTime)))
);
myHandler.postDelayed(UpdateSongTime, 100);
seekBar.setProgress((int) startTime);
forwardBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int temp = (int) startTime;
if ((temp + forwardTime) <= finalTime) {
startTime = startTime + forwardTime;
player.mediaPlayer.seekTo((int) startTime);
} else {
startTime = finalTime;
player.mediaPlayer.seekTo((int) startTime);
}
}
});
backwardBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int temp = (int) startTime;
if ((temp - backwardTime) > 0) {
startTime = startTime - backwardTime;
player.mediaPlayer.seekTo((int) startTime);
} else {
startTime = 0;
player.mediaPlayer.seekTo((int) startTime);
}
}
});
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(player.mediaPlayer != null && fromUser){
startTime = progress;
player.mediaPlayer.seekTo((int) startTime);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
//Binding this Client to the AudioPlayer Service
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
MediaPlayerService.LocalBinder binder = (MediaPlayerService.LocalBinder) service;
player = binder.getService();
serviceBound = true;
Toast.makeText(MainActivity.this, "Service Bound", Toast.LENGTH_SHORT).show();
}
@Override
public void onServiceDisconnected(ComponentName name) {
serviceBound = false;
}
};
private void playAudio(String media) {
//Check is service is active
if (!serviceBound) {
Intent playerIntent = new Intent(this, MediaPlayerService.class);
playerIntent.putExtra("media", media);
startService(playerIntent);
bindService(playerIntent, serviceConnection, Context.BIND_AUTO_CREATE);
playBtn.setImageResource(android.R.drawable.ic_media_pause);
} else if (serviceBound && player.mediaPlayer.isPlaying()) {
player.pauseMedia();
playBtn.setImageResource(android.R.drawable.ic_media_play);
} else if (serviceBound && !player.mediaPlayer.isPlaying()) {
player.resumeMedia();
playBtn.setImageResource(android.R.drawable.ic_media_pause);
}
}
private void loadAudio() {
ContentResolver contentResolver = getContentResolver();
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC + "!= 0";
String sortOrder = MediaStore.Audio.Media.TITLE + " ASC";
Cursor cursor = contentResolver.query(uri, null, selection, null, sortOrder);
if (cursor != null && cursor.getCount() > 0) {
audioList = new ArrayList<>();
while (cursor.moveToNext()) {
String data = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
// Save to audioList
audioList.add(new Audio(data));
}
}
cursor.close();
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean("ServiceState", serviceBound);
super.onSaveInstanceState(savedInstanceState);
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
serviceBound = savedInstanceState.getBoolean("ServiceState");
}
@Override
protected void onDestroy() {
super.onDestroy();
if (serviceBound) {
unbindService(serviceConnection);
//service is active
player.stopSelf();
}
}
public float getDuration() {
if (player == null)
return 0.0f;
if (serviceBound)
return player.mediaPlayer.getDuration();
else
return 0.0f;
}
public float getCurrentPosition() {
if (player == null)
return 0.0f;
if (serviceBound)
return player.mediaPlayer.getCurrentPosition();
else
return 0.0f;
}
private Runnable UpdateSongTime = new Runnable() {
public void run() {
startTime = getCurrentPosition();
currentPosText.setText(String.format("%d min, %d sec",
TimeUnit.MILLISECONDS.toMinutes((long) startTime),
TimeUnit.MILLISECONDS.toSeconds((long) startTime) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.
toMinutes((long) startTime)))
);
seekBar.setProgress((int) startTime);
myHandler.postDelayed(this, 100);
}
};
}
感谢您的时间♥