android - 音频焦点更改不起作用

标签 android audio android-mediaplayer

我有一个音乐播放器 Activity 来控制歌曲的播放。我已经阅读了有关管理音频焦点的文档,并在 btnPlayplaySong 函数中实现了它。这是我的代码:

    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- 电话响起时暂停歌曲。

需要帮助来解决这个问题..

最佳答案

要在电话响起时暂停歌曲,您可以使用 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

关于android - 音频焦点更改不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39990498/

相关文章:

audio - ffmpeg 提取所有音频 channel

android - 在android中,在其他人接听电话之前,是否有任何方法可以在通话哔声中播放音频?

Android make 和 chown/acct/uid_10064 : Read-only file system in emulator 失败

Android:将 GPSTimeStamp 放入 jpg EXIF 标签中

安卓新文件(路径)

ios - 通过蓝牙/wifi在2个设备之间进行音频流传输?

actionscript-3 - Flash CS5中的事件发生后,交叉淡入淡出的声音

java - 媒体播放器和服务类

android - 在单独的线程中填充 ListView

android - ArrayAdapter 的 getView() 方法在加载和滚动 ListView 时自动调用