我正在为mediaPlayer App使用媒体播放器服务,我在一个活动中使用该媒体播放器的实例 . 现在,当我使用按钮或通知更改音乐时,currentmedia Player对下一首歌无效 . 新mediaPlayer的信息更新实际上有延迟 .

当我使用2000ms的handler.postDelayed时,我可以从Service获得正确的mediaPlayer,但是没有延迟它没有给出实例 .

问题是:使用媒体会话控件时为什么会出现延迟?对于手动更换轨道等情况也是如此 .


Class Name : MediaPlayerSerice

public class MediaPlayerService extends Service implements MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnSeekCompleteListener,
        MediaPlayer.OnInfoListener, MediaPlayer.OnBufferingUpdateListener,
        AudioManager.OnAudioFocusChangeListener,AsyncInterface {

    public static final String TAG = MediaPlayerService.class.getSimpleName();

    public static final String ACTION_PLAY = "com.natit.kambo.ACTION_PLAY";
    public static final String ACTION_PAUSE = "com.natit.kambo.ACTION_PAUSE";
    public static final String ACTION_PREVIOUS = "com.natit.kambo.ACTION_PREVIOUS";
    public static final String ACTION_NEXT = "com.natit.kambo.ACTION_NEXT";
    public static final String ACTION_STOP = "com.natit.kambo.ACTION_STOP";

    public static final String ACTION_PLAY_NOTIFICATION = "com.natit.kambo.ACTION_PLAY_NOTIFICATION";
    public static final String ACTION_PAUSE_NOTIFICATION = "com.natit.kambo.ACTION_PAUSE_NOTIFICATION";
    public static final String ACTION_PREVIOUS_NOTIFICATION = "com.natit.kambo.ACTION_PREVIOUS_NOTIFICATION";
    public static final String ACTION_NEXT_NOTIFICATION = "com.natit.kambo.ACTION_NEXT_NOTIFICATION";
    public static final String ACTION_STOP_NOTIFICATION= "com.natit.kambo.ACTION_STOP_NOTIFICATION";

    public static final String GLOBAL_AUDIO_PLAYING= "com.natit.kambo.ACTION_GLOBAL_AUDIO_PLAYING";
    public static final String GLOBAL_AUDIO_PAUSED= "com.natit.kambo.ACTION_GLOBAL_AUDIO_PAUSED";
    public static final String GLOBAL_AUDIO_COMPLETED= "com.natit.kambo.ACTION_GLOBAL_AUDIO_COMPLETED";
    public static final String GLOBAL_AUDIO_BUFFERING= "com.natit.kambo.ACTION_GLOBAL_AUDIO_BUFFERING";
    public static final String GLOBAL_AUDIO_NOT_BUFFERING= "com.natit.kambo.ACTION_GLOBAL_AUDIO_NOT_BUFFERING";
    public static final String GLOBAL_MEDIA_PLAYER_PREPARED = "com.natit.kambo.ACTION_GLOBAL_MEDIA_PLAYER_PREPARED";
    public static final String GLOBAL_MEDIA_PLAYER_NEW_SONG_STARTED = "com.natit.kambo.ACTION_GLOBAL_MEDIA_PLAYER_NEW_SONG_STARTED";


    private MediaSessionManager mediaSessionManager;
    private MediaSessionCompat mediaSession;
    private MediaControllerCompat.TransportControls transportControls;
    private Bitmap bitmapImage;
    AsyncInterface asyncInterface;

    private static final int NOTIFICATION_ID = 47;

    private MediaPlayer mediaPlayer ;
    private AudioManager audioManager;

    private boolean ongoingCall = false;

    private PhoneStateListener phoneStateListener;
    private TelephonyManager telephonyManager;

    //List of available Audio files
    private ArrayList<OfflineSong> audioList;

    private int audioIndex = -1;

    private OfflineSong activeAudio; //an object of the currently playing audio

    //Used to pause/resume MediaPlayer
    private int resumePosi;

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

        mediaPlayer = new MediaPlayer();
        asyncInterface = this;

        callStateListener();

        registerReceiver(becomingNoisyReceiver, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
        registerReceiver(playNewAudioBr, new IntentFilter(HomeActivity.Broadcast_PLAY_NEW_AUDIO));
        registerReceiver(pauseBr, new IntentFilter(HomeActivity.ACTION_PAUSE1));
        registerReceiver(playBr, new IntentFilter(HomeActivity.ACTION_PLAY1));
        registerReceiver(onPlayNextBr, new IntentFilter(HomeActivity.ACTION_PLAY_NEXT1));
        registerReceiver(onPlayPrevBr, new IntentFilter(HomeActivity.ACTION_PLAY_PREV1));

    }


    /**************************
     *  READY MEDIA PLAYER
     ***************************/

    private void readyMediaPlayer() {

        //Set up MediaPlayer event listeners
        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 {
            mediaPlayer.setDataSource(activeAudio.getFilename());

        } catch (IOException e)
        {
            //stopSelf();
        }

        mediaPlayer.prepareAsync();
    }

    /******************
     * ON PREPARED
     ******************/

    @Override
    public void onPrepared(MediaPlayer mp) {

        playMedia();

        sendBroadcast(new Intent(GLOBAL_MEDIA_PLAYER_PREPARED));

    }

    /***********************************
     * ON START COMMAND,from service class
     ************************************/

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        try {

            StoragePreference storage = new StoragePreference(getApplicationContext());
            audioList = storage.loadAudio();
            audioIndex = storage.loadAudioIndex();

            if (audioIndex != -1 && audioIndex < audioList.size())
            {
                activeAudio = audioList.get(audioIndex);
            }
            else
            {
                stopSelf();
            }
        }
        catch (NullPointerException e) {
            stopSelf();
        }

        if (!requestAudioFocus())
        {
            stopSelf();
        }

        if (mediaSessionManager == null)
        {
            try
            {
                initMediaSession();
                readyMediaPlayer();

            }
            catch (RemoteException e)
            {
                e.printStackTrace();
                stopSelf();
            }

            buildNotification(PlaybackStatus.PLAYING);
        }

        handleIncomingActions(intent); //\\ INTENTS FROM BUTTONS //\\

        return super.onStartCommand(intent, flags, startId);
    }


    private void playMedia() {
        if (!mediaPlayer.isPlaying()) {
            mediaPlayer.start();

            sendBroadcast(new Intent(GLOBAL_AUDIO_PLAYING));
        }
    }

    private void stopMedia() {
        if (mediaPlayer == null) return;
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
        }
    }

    private void pauseMedia() {
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.pause();
            resumePosi = mediaPlayer.getCurrentPosition();
            sendBroadcast(new Intent(GLOBAL_AUDIO_PAUSED));

        }
    }

    private void resumeMedia() {
        if (!mediaPlayer.isPlaying()) {
            mediaPlayer.seekTo(resumePosi);
            mediaPlayer.start();
            sendBroadcast(new Intent(GLOBAL_AUDIO_PLAYING));

        }
    }

    @Override
    public void getBitMap(Bitmap bitmap) {

        bitmapImage = bitmap;

    }




    /************************************************************
     * BINDER FOR ATTACHING TO OTHER ACTIVITIES, From Service Class
     *************************************************************/

    private final IBinder iBinder = new MusicServiceBinder();


    public class MusicServiceBinder extends Binder // implementing the abstruct class Binder
    {
        public MediaPlayerService getService()
        {
            return MediaPlayerService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {

        return iBinder;
    }

    /************************
     * BUFFER DETECTION
     *************************/

    @Override
    public void onBufferingUpdate(MediaPlayer mp, int percent) {

        //sendBroadcast(new Intent(GLOBAL_AUDIO_BUFFERING));
    }

    /******************************
     * MEDIA PLAYER ON COMPLETION
     *******************************/

    @Override
    public void onCompletion(MediaPlayer mp) {

        Log.e(TAG, "onCompletion: is called");

        stopMedia();

        sendBroadcast(new Intent(GLOBAL_AUDIO_COMPLETED));
    }

    /************************
     * ON AUDIO FOCUS CHANGE
     ************************/

    @Override
    public void onAudioFocusChange(int focusChange) {
        //Invoked when the audio focus of the system is updated.

        switch (focusChange) {
            case AudioManager.AUDIOFOCUS_GAIN:
                // resume playback
                if (mediaPlayer == null) readyMediaPlayer();
                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;
        }

    }

    /************************
     * REQUEST FOCUS
     ************************/

    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;
        }
        else {
            return false;
        }
    }

    /************************
     * REMOVE FOCUS
     ************************/

    private boolean removeAudioFocus() {

        return AudioManager.AUDIOFOCUS_REQUEST_GRANTED == audioManager.abandonAudioFocus(this);
    }





    //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);
    }

    /*****************************
     * For Responding to BROADCAST
     *****************************/

     BroadcastReceiver playNewAudioBr = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            audioIndex = new StoragePreference(getApplicationContext()).loadAudioIndex();

            if (audioIndex != -1 && audioIndex < audioList.size()) {

                activeAudio = audioList.get(audioIndex);

            } else {
                stopSelf();
            }

            stopMedia();
            mediaPlayer.reset();
            readyMediaPlayer();
            updateMetaData();
            buildNotification(PlaybackStatus.PLAYING);
        }
    };


     BroadcastReceiver playBr = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            playMedia();
            updateMetaData();
            buildNotification(PlaybackStatus.PLAYING);


        }
    };


     BroadcastReceiver pauseBr = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            pauseMedia();
            buildNotification(PlaybackStatus.PAUSED);

        }
    };

     BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            //pause audio on ACTION_AUDIO_BECOMING_NOISY
            pauseMedia();
            // buildNotification(PlaybackStatus.PAUSED);
        }
    };

    BroadcastReceiver onPlayNextBr = new BroadcastReceiver() {
        public void onReceive(Context ctxt, Intent intent) {

            skipToNext();
            updateMetaData();
        }
    };


    BroadcastReceiver onPlayPrevBr = new BroadcastReceiver() {
        public void onReceive(Context ctxt, Intent intent) {

            skipToPrevious();
            updateMetaData();
        }
    };




    /************************************
     * ON DESTROY, from  service Class
     ***********************************/

    @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(playNewAudioBr);
        unregisterReceiver(pauseBr);
        unregisterReceiver(playBr);
        unregisterReceiver(onPlayNextBr);
        unregisterReceiver(onPlayPrevBr);


        //clear cached playlist
        new StoragePreference(getApplicationContext()).clearCachedAudioPlaylist();
    }

    /*********************
     * INIT MEDIA SESSION
     *********************/

    private void initMediaSession() throws RemoteException {

        if (mediaSessionManager != null)
            return;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            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();

        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();
                //Stop the service
                stopSelf();
            }

            @Override
            public void onSeekTo(long position) {
                super.onSeekTo(position);
            }
        });
    }

    /************************
     * META DATA UPDATE
     ************************/
    private void updateMetaData() {

        new DownloadImageTask(activeAudio.getArtwork(),MediaPlayerService.this).execute(activeAudio.getArtwork());

       Bitmap albumArt = bitmapImage;

        mediaSession.setMetadata(new MediaMetadataCompat.Builder()
                .putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt)
                .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, activeAudio.getArtistName())
                .putString(MediaMetadataCompat.METADATA_KEY_ALBUM, activeAudio.getAlbumName())
                .putString(MediaMetadataCompat.METADATA_KEY_TITLE, activeAudio.getName())
                .build());


    }

    /************************
     * SKIP TO NEXT
     ************************/

    private void skipToNext() {

        if (audioIndex == audioList.size() - 1) {
            //if last in playlist
            audioIndex = 0;
            activeAudio = audioList.get(audioIndex);
        } else {
            //get next in playlist
            activeAudio = audioList.get(++audioIndex);
        }

        //Update stored index
        new StoragePreference(getApplicationContext()).storeAudioIndex(audioIndex);

        stopMedia();
        //reset mediaPlayer
        mediaPlayer.reset();
        readyMediaPlayer();
        updateMetaData();
    }

    /************************
     * SKIP TO PREVIOUS
     ************************/

    private void skipToPrevious() {

        if (audioIndex == 0) {
            //if first in playlist
            //set index to the last of audioList
            audioIndex = audioList.size() - 1;
            activeAudio = audioList.get(audioIndex);
        } else {
            //get previous in playlist
            activeAudio = audioList.get(--audioIndex);
        }

        //Update stored index
        new StoragePreference(  getApplicationContext()).storeAudioIndex(audioIndex);

        stopMedia();
        //reset mediaPlayer
        mediaPlayer.reset();
        readyMediaPlayer();

    }

    /************************
     * NOTIFICATION BUILDER
     ************************/

    private void buildNotification(PlaybackStatus playbackStatus) {

        int notificationIcon = android.R.drawable.ic_media_pause;

        PendingIntent pedningIntent = null;

        if (playbackStatus == PlaybackStatus.PLAYING) {

            notificationIcon = android.R.drawable.ic_media_pause;
            pedningIntent = playbackAction(1);

        }
        else if (playbackStatus == PlaybackStatus.PAUSED) {

            notificationIcon = android.R.drawable.ic_media_play;
            //create the play action
            pedningIntent = playbackAction(0);
        }

        Bitmap largeIcon = BitmapFactory.decodeResource(getResources(),
                R.drawable.ic_placeholder); //replace with your own image

        // Create a new Notification
        NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
                .setShowWhen(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
                .setContentText(activeAudio.getArtistName())
                .setContentTitle(activeAudio.getAlbumName())
                .setContentInfo(activeAudio.getName())
                // Add playback actions

                .addAction(android.R.drawable.ic_media_previous, "previous", playbackAction(3))
                .addAction(notificationIcon, "pause", pedningIntent)
                .addAction(android.R.drawable.ic_media_next, "next", playbackAction(2));


        ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID, notificationBuilder.build());
    }

    /************************
     * REMOVE NOTIFICATION
     ************************/

    private void removeNotification() {
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.cancel(NOTIFICATION_ID);
    }


    /************************
     * PENDING INTENTS
     ************************/

    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;
    }

    /**************************************************************************************************************
     *USING TRANSPORT CONTROL FOR CONTROLLING MEDIA PLAYBACKS,AND SENDING BROADCASTS FOR OTHER ACTIVITIES.
     ***************************************************************************************************************/

    private void handleIncomingActions(Intent playbackAction) {

        if (playbackAction == null || playbackAction.getAction() == null)
            return;

        String actionString = playbackAction.getAction();

        if (actionString.equalsIgnoreCase(ACTION_PLAY)) {

            transportControls.play();
            sendBroadcast( new Intent(ACTION_PLAY_NOTIFICATION));


        } else if (actionString.equalsIgnoreCase(ACTION_PAUSE)) {

            transportControls.pause();
            sendBroadcast(new Intent(ACTION_PAUSE_NOTIFICATION));


        } else if (actionString.equalsIgnoreCase(ACTION_NEXT)) {

            transportControls.skipToNext();
            sendBroadcast(new Intent(ACTION_NEXT_NOTIFICATION));


        } else if (actionString.equalsIgnoreCase(ACTION_PREVIOUS)) {

            transportControls.skipToPrevious();
            sendBroadcast(new Intent(ACTION_PREVIOUS_NOTIFICATION));


        } else if (actionString.equalsIgnoreCase(ACTION_STOP)) {

            transportControls.stop();
            sendBroadcast(new Intent(ACTION_STOP_NOTIFICATION));

        }
    }

    public MediaPlayer getMediaPlayer() {
        return mediaPlayer;
    }

    public int getAudioIndex(){
        return audioIndex;
    }

    public MediaControllerCompat.TransportControls getTransportControls() {
        return transportControls;
    }

    public OfflineSong getActiveAudio() {
        return activeAudio;
    }

    public AudioManager getAudioManager() {
        return audioManager;
    }
}

现在在音乐活动中,我正在绑定服务,然后使用服务类的mediaplayer实例 . (getMediaPlayer()) .

当尝试更新持续时间等事情时会产生如下所示的问题:

现在每次播放新歌时都会出现错误:

08-14 11:59:25.596 31091-31091 / com.natit.kambo E / MediaPlayer:尝试在没有有效媒体播放器的情况下调用getDuration