我有一个音乐播放器活动来控制歌曲的播放。我已阅读有关管理音频焦点的文档,并在btnPlay
和playSong
函数中实现了该文档。这是我的代码:
public class MusicPlayerActivity extends Activity implements MediaPlayer.OnCompletionListener, SeekBar.OnSeekBarChangeListener {
private boolean notRunning = false;
private boolean wasRunning = false;
private BroadcastReceiver receiver;
private static final int NOTIFICATION_ID = 69;
private static final String TAG = "museNotification";
private ImageButton btnPlay;
private ImageButton btnForward;
private ImageButton btnBackward;
private ImageButton btnNext;
private ImageButton btnPrevious;
private ImageButton btnPlaylist;
private ImageButton btnRepeat;
private ImageButton btnShuffle;
private SeekBar songProgressBar;
private TextView songTitleLabel;
private TextView songCurrentDurationLabel;
private TextView songTotalDurationLabel;
// Media Player
private static MediaPlayer mp;
// Handler to update UI timer, progress bar etc,.
private Handler mHandler = new Handler();;
private SongsManager songManager;
private Utilities utils;
private int seekForwardTime = 5000; // 5000 milliseconds
private int seekBackwardTime = 5000; // 5000 milliseconds
private int currentSongIndex = 6;
private boolean isShuffle = false;
private boolean isRepeat = false;
private ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
private ViewPager viewPager;
private int remember = 223;
public static String songName="Choose a song";
@Override
public void onResume() {
super.onResume();
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancelAll();
if (mp.isPlaying()) {
if (mp != null) {
btnPlay.setImageResource(R.drawable.btn_pause);
}
else {
if (mp != null)
btnPlay.setImageResource(R.drawable.btn_play);}
}
else
btnPlay.setImageResource(R.drawable.btn_play);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_music_player);
// All player buttons
btnPlay = (ImageButton) findViewById(R.id.btnPlay);
// btnForward = (ImageButton) findViewById(R.id.btnForward);
//btnBackward = (ImageButton) findViewById(R.id.btnBackward);
btnNext = (ImageButton) findViewById(R.id.btnNext);
btnPrevious = (ImageButton) findViewById(R.id.btnPrevious);
btnPlaylist = (ImageButton) findViewById(R.id.btnPlaylist);
btnRepeat = (ImageButton) findViewById(R.id.btnRepeat);
btnShuffle = (ImageButton) findViewById(R.id.btnShuffle);
songProgressBar = (SeekBar) findViewById(R.id.songProgressBar);
songTitleLabel = (TextView) findViewById(R.id.songTitle);
songCurrentDurationLabel = (TextView) findViewById(R.id.songCurrentDurationLabel);
songTotalDurationLabel = (TextView) findViewById(R.id.songTotalDurationLabel);
viewPager = (ViewPager)findViewById(R.id.viewPager);
// Mediaplayer
mp = new MediaPlayer();
songManager = new SongsManager();
utils = new Utilities();
// Listeners
songProgressBar.setOnSeekBarChangeListener(this); // Important
mp.setOnCompletionListener(this); // Important
// Getting all songs list
songsList = songManager.getPlayList(this);
/**
* Play button click event
* plays a song and changes button to pause image
* pauses a song and changes button to play image
* */
btnPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED){
// check for already playing
if (mp.isPlaying()) {
if (mp != null) {
mp.pause();
// Changing button image to play button
btnPlay.setImageResource(R.drawable.btn_play);
}
}
else {
//RISH
Context mContext = getApplicationContext();
AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
AudioManager.OnAudioFocusChangeListener afChangeListener = new AudioManager.OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
notRunning = true;
mp.pause();
length = mp.getCurrentPosition(); //lol
}
}
};
// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
// Use the music stream.
AudioManager.STREAM_MUSIC,
// Request permanent focus.
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE);
//RISH
// Resume song
if (mp != null) {
mp.start();
// Changing button image to pause button
btnPlay.setImageResource(R.drawable.btn_pause);
}
}
//}
}
});
/**
* Next button click event
* Plays next song by taking currentSongIndex + 1
* */
btnNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if(isShuffle){
// shuffle is on - play a random song
Random rand = new Random();
remember = currentSongIndex;
currentSongIndex = rand.nextInt((songsList.size() - 1) - 0 + 1) + 0;
playSong(currentSongIndex);
} else{
// no repeat or shuffle ON - play next song
if(currentSongIndex < (songsList.size() - 1)){
playSong(currentSongIndex + 1);
currentSongIndex = currentSongIndex + 1;
}else{
// play first song
playSong(0);
currentSongIndex = 0;
}
}
}
});
/**
* Back button click event
* Plays previous song by currentSongIndex - 1
* */
btnPrevious.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if(isShuffle){
if(remember!=223)
{currentSongIndex = remember;
remember=223;}
else
{Random rand = new Random();
currentSongIndex = rand.nextInt((songsList.size() - 1) - 0 + 1) + 0;
playSong(currentSongIndex);}
playSong(currentSongIndex);
}
else {
if (currentSongIndex > 0) {
playSong(
currentSongIndex - 1);
currentSongIndex = currentSongIndex - 1;
} else {
// play last song
playSong(songsList.size() - 1);
currentSongIndex = songsList.size() - 1;
}
}
}
});
/**
* Button Click event for Repeat button
* Enables repeat flag to true
* */
btnRepeat.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if(isRepeat){
isRepeat = false;
Toast.makeText(getApplicationContext(), "Repeat Turned OFF", Toast.LENGTH_SHORT).show();
btnRepeat.setImageResource(R.drawable.btn_repeat);
}else{
// make repeat to true
isRepeat = true;
Toast.makeText(getApplicationContext(), "Single Repeat Turned ON", Toast.LENGTH_SHORT).show();
// make shuffle to false
isShuffle = false;
btnRepeat.setImageResource(R.drawable.btn_repeat_focused);
btnShuffle.setImageResource(R.drawable.btn_shuffle);
}
}
});
/**
* Button Click event for Shuffle button
* Enables shuffle flag to true
* */
btnShuffle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if(isShuffle){
isShuffle = false;
Toast.makeText(getApplicationContext(), "Shuffle is OFF", Toast.LENGTH_SHORT).show();
btnShuffle.setImageResource(R.drawable.btn_shuffle);
}else{
// make repeat to true
isShuffle= true;
Toast.makeText(getApplicationContext(), "Shuffle is ON", Toast.LENGTH_SHORT).show();
// make shuffle to false
isRepeat = false;
btnShuffle.setImageResource(R.drawable.btn_shuffle_focused);
btnRepeat.setImageResource(R.drawable.btn_repeat);
}
}
});
/**
* Button Click event for Play list click event
* Launches list activity which displays list of songs
* */
btnPlaylist.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
Intent i = new Intent(getApplicationContext(), MainActivity.class);
startActivity(i);
//viewPager.setCurrentItem(0);
}
});
Bundle extras = getIntent().getExtras();
if(extras!=null){
mp.reset();
currentSongIndex = extras.getInt("songPath");
// play selected song
if(mp != null)
if(mp.isPlaying())
{
mp.prepareAsync();
mp.start();
mp.seekTo(0);
// start your new song
}else{
playSong(currentSongIndex);
// start your new song
}
}
}
/**
* Function to play a song
* */
int length;
public void playSong(int songIndex){
notRunning=false;
//Rish -- THIS BLOCK STOPS MUSIC IF ANOTHER APP GETS THE FOCUS OF MEDIAPLAYER
Context mContext = getApplicationContext();
AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
AudioManager.OnAudioFocusChangeListener afChangeListener = new AudioManager.OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT){
btnPlay.setImageResource(R.drawable.btn_play);
notRunning=true;
mp.pause();
length = mp.getCurrentPosition(); //lol
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
notRunning=false;
mp.seekTo(length);//lol
mp.start();
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
mp.pause();
notRunning=true;
length = mp.getCurrentPosition(); //lol
}
}
};
// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
// Use the music stream.
AudioManager.STREAM_MUSIC,
// Request permanent focus.
AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
// Play song
try {
mp.reset();
mp.setDataSource(songsList.get(songIndex).get("songPath"));
mp.prepare();
mp.start();
// Displaying Song title
String songTitle = songsList.get(songIndex).get("songTitle");
songTitleLabel.setText(songTitle);
// setNotification(songTitle);
songName =songTitle;
// Changing Button Image to pause image
btnPlay.setImageResource(R.drawable.btn_pause);
// set Progress bar values
songProgressBar.setProgress(0);
songProgressBar.setMax(100);
// Updating progress bar
updateProgressBar();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//Setting miniPlayer that is displayed in the bottom of main activity
Intent i = new Intent(getApplicationContext(),MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK| Intent.FLAG_ACTIVITY_SINGLE_TOP);
i.putExtra("songTitle",songName);
i.setAction("dummy3");
//Setting miniPlayer that is displayed in the bottom of main activity
}
//Rish
/**
* Update timer on seekbar
* */
public void updateProgressBar() {
mHandler.postDelayed(mUpdateTimeTask, 100);
}
/**
* Background Runnable thread
* */
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
if((mp != null)) { //Attempting to prevent app crash on swipe
long totalDuration = mp.getDuration();
long currentDuration = mp.getCurrentPosition();
// Displaying Total Duration time
songTotalDurationLabel.setText("" + utils.milliSecondsToTimer(totalDuration));
// Displaying time completed playing
songCurrentDurationLabel.setText("" + utils.milliSecondsToTimer(currentDuration));
// Updating progress bar
int progress = (int) (utils.getProgressPercentage(currentDuration, totalDuration));
//Log.d("Progress", ""+progress);
songProgressBar.setProgress(progress);
// Running this thread after 100 milliseconds
mHandler.postDelayed(this, 100);
}
}
};
/**
*
* */
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
}
/**
* When user starts moving the progress handler
* */
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// remove message Handler from updating progress bar
// mHandler.removeCallbacks(mUpdateTimeTask);
}
/**
* When user stops moving the progress hanlder
* */
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// mHandler.removeCallbacksAndMessages(mUpdateTimeTask);
int totalDuration = mp.getDuration();
int currentPosition = utils.progressToTimer(seekBar.getProgress(), totalDuration);
// forward or backward to certain seconds
mp.seekTo(currentPosition);
// update timer progress again
updateProgressBar();
}
/**
* On Song Playing completed
* if repeat is ON play same song again
* if shuffle is ON play random song
* */
@Override
public void onCompletion(MediaPlayer arg0) {
// check for repeat is ON or OFF
if(isRepeat){
// repeat is on play same song again
playSong(currentSongIndex);
} else if(isShuffle){
// shuffle is on - play a random song
remember = currentSongIndex;
Random rand = new Random();
currentSongIndex = rand.nextInt((songsList.size() - 1) - 0 + 1) + 0;
playSong(currentSongIndex);
} else{
// no repeat or shuffle ON - play next song
if(currentSongIndex < (songsList.size() - 1)){
playSong(currentSongIndex + 1);
currentSongIndex = currentSongIndex + 1;
}else{
// play first song
playSong(0);
currentSongIndex = 0;
}
}
}
/*
//The method below minimizes the app if Back key is pressed ; i.e same as the method below
public boolean onKeyDown(int keyCode, KeyEvent event)
{
setNotification(songName);//Notification start
Intent i = new Intent(getApplicationContext(), MainActivity.class);
startActivity(i);
return super.onKeyDown(keyCode, event);
}
*/
//Above method works same as this
@Override
public void onBackPressed(){
Intent i = new Intent(getApplicationContext(), MainActivity.class);
startActivity(i);
//super.onBackPressed();
}
@Override
public void onPause(){
setNotification(songName);
startService(new Intent(this, MyService.class)); //trying to cancel notification on app swipe
super.onPause();
}
@Override
public void onDestroy(){
if (receiver != null) {
unregisterReceiver(receiver);
receiver = null;
}
super.onDestroy();
mp.release();
}
//NOTIFICATION START
static @SuppressWarnings("deprecation")
Notification notification = new Notification(R.drawable.ic_launcher, null, System.currentTimeMillis());
@SuppressLint("NewApi")
public void setNotification(String songName) {
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager notificationManager = (NotificationManager)getSystemService(ns);
RemoteViews notificationView = new RemoteViews(getPackageName(), R.layout.notification_mediacontroller);
notificationView.setTextViewText(R.id.textView1, songName);
Notification.Builder mNotifyBuilder = new Notification.Builder(this);
notification = mNotifyBuilder.setContentTitle("some string")
.setContentText("Slide down on note to expand")
.setSmallIcon(R.drawable.ic_launcher)
// .setAutoCancel(true)
// .setLargeIcon()
.build();
notification.contentView = notificationView;
//the intent that is started when the notification is clicked (works)
Intent notificationIntent = new Intent(this, MusicPlayerActivity.class);
//set some dummy action on the Intent, otherwise extras are dropped And cause problems like unnecessary new instance of activity
notificationIntent.setAction("dummy");
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingNotificationIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_ONE_SHOT);
notification.contentView = notificationView;
notification.contentIntent = pendingNotificationIntent;
notification.flags |= Notification.FLAG_NO_CLEAR;
notification.flags |= Notification.PRIORITY_MAX;
notification.flags |= Notification.FLAG_ONGOING_EVENT;//Dont know why using this flag.
notification.flags |= Notification.FLAG_AUTO_CANCEL;
//this is the intent that is supposed to be called when the button is clicked
Intent switchIntent = new Intent("com.dmmet.musicplayer.ACTION_PLAY");
PendingIntent pendingSwitchIntent = PendingIntent.getBroadcast(this, 0, switchIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notificationView.setOnClickPendingIntent(R.id.btnPlay2, pendingSwitchIntent);
notificationManager.notify(TAG,NOTIFICATION_ID, notification);
Intent closeIntent = new Intent("com.dmmet.musicplayer.ACTION_CLOSE");
PendingIntent pendingCloseIntent = PendingIntent.getBroadcast(this, 0, closeIntent, 0);
notificationView.setOnClickPendingIntent(R.id.btnClose, pendingCloseIntent);
notificationManager.notify(TAG,NOTIFICATION_ID, notification);
Intent nextIntent = new Intent("com.dmmet.musicplayer.ACTION_NEXT");
PendingIntent pendingNextIntent = PendingIntent.getBroadcast(this, 0, nextIntent, 0);
notificationView.setOnClickPendingIntent(R.id.btnNext, pendingNextIntent);
notificationManager.notify(TAG,NOTIFICATION_ID, notification);
Intent previousIntent = new Intent("com.dmmet.musicplayer.ACTION_PREVIOUS");
PendingIntent pendingPreviousIntent = PendingIntent.getBroadcast(this, 0, previousIntent, 0);
notificationView.setOnClickPendingIntent(R.id.btnPrevious, pendingPreviousIntent);
notificationManager.notify(TAG,NOTIFICATION_ID, notification);
}
//NOTIFICATION START
public static class MyService extends Service {
@Override
public void onCreate()
{
super.onCreate();
}
@Override
public void onTaskRemoved(Intent rootIntent){
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(TAG,NOTIFICATION_ID);
notificationManager.cancelAll();
// mp.release();
mp = null; //Trying to avoid app crash on swipe
//stop service
stopSelf();
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
}
它应该像任何其他音乐播放器一样工作,即:遵循以下规则: 1-如果其他应用正在播放音频,则获得音频焦点。 2-如果某个其他应用程序在播放音频时尝试播放音频,则会丢失音频焦点。 3 - 播放新歌曲时停止上一首播放歌曲。 4-手机响铃时暂停歌曲。
需要帮助解决这个问题..
答案 0 :(得分:2)
要在电话响铃时暂停歌曲,您可以使用PhoneStateListener侦听呼叫状态的变化。您可以在TelephonyManager中注册侦听器:
PhoneStateListener phoneStateListener = new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
if (state == TelephonyManager.CALL_STATE_RINGING) {
//Incoming call: Pause music
} else if(state == TelephonyManager.CALL_STATE_IDLE) {
//Not in call: Play music
} else if(state == TelephonyManager.CALL_STATE_OFFHOOK) {
//A call is dialing, active or on hold
}
super.onCallStateChanged(state, incomingNumber);
}};
TelephonyManager mgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
if(mgr != null) {
mgr.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
查看文档here