使用活动滑动销毁Startforeground服务在

时间:2018-06-11 04:42:57

标签: android

因此,我正在通过通知制作播客播放器并在前台运行媒体服务。一切顺利,除了我清除最近的应用程序。除非我事先使用了通知按钮(播放,暂停等),否则当我这样做时服务就会消失。我已经查看了所有内容以及我所得到的内容。任何帮助将非常感激。我已经包含了服务的整个代码,但实际上我认为问题位于buildNotification方法中。

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

private static MediaPlayer pp;
private static Episode episode = new Episode("", "49731298537982742984232", "", "", "", "", "");
private static Bitmap bitmap;

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

public static Boolean isBound = true;

private AudioManager audioManager;

private boolean shouldStart = true;

public static final String ACTION_PLAY = "com.campbellyamane.podantic.ACTION_PLAY";
public static final String ACTION_PAUSE = "com.campbellyamane.podantic.ACTION_PAUSE";
public static final String ACTION_PREVIOUS = "com.campbellyamane.podantic.ACTION_PREVIOUS";
public static final String ACTION_NEXT = "com.campbellyamane.podantic.ACTION_NEXT";
public static final String ACTION_STOP = "com.campbellyamane.podantic.ACTION_STOP";

//MediaSession
private MediaSessionManager mediaSessionManager;
private MediaSession mediaSession;
private MediaController.TransportControls transportControls;

//AudioPlayer notification ID
private static final int NOTIFICATION_ID = 101;
private static Notification notification;

//Callbacks
private static Callbacks activity;

@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 (pp == null) {
                initMediaPlayer();
            } else if (!pp.isPlaying() && shouldStart) {
                pp.start();
            }
            pp.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 (pp.isPlaying()) {
                pp.pause();
                shouldStart = true;
            }
            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 (pp.isPlaying()) {
                pp.pause();
                shouldStart = true;
            }
            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 (pp.isPlaying()) {
                pp.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);
}

// Binder given to clients
private final IBinder iBinder = new LocalBinder();

@Override
public IBinder onBind(Intent intent) {
    isBound = true;
    return iBinder;
}

public class LocalBinder extends Binder {
    public PodcastService getService() {
        return PodcastService.this;
    }
}

private void initMediaPlayer() {
    if (pp == null) {
        pp = new MediaPlayer();
        //Set up MediaPlayer event listeners
        pp.setOnCompletionListener(this);
        pp.setOnErrorListener(this);
        pp.setOnPreparedListener(this);
        pp.setOnBufferingUpdateListener(this);
        pp.setOnSeekCompleteListener(this);
        pp.setOnInfoListener(this);
        pp.setAudioStreamType(AudioManager.STREAM_MUSIC);
    }
}

public Boolean exists() {
    return pp != null;
}

public Episode getPlaying() {
    return episode;
}

public void playMedia(Episode e) {
    activity.cbPreLoad();
    if (requestAudioFocus()) {
        episode = e;
        try {
            //Reset so that the MediaPlayer is not pointing to another data source
            pp.reset();
            pp.setDataSource(episode.getMp3());
            pp.prepareAsync();
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (IllegalStateException ex) {
            try {
                pp.setDataSource(episode.getMp3());
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            pp.prepareAsync();
        }
    }
}

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

public boolean isPlaying() {
    return pp.isPlaying();
}

public void pauseMedia() {
    if (pp.isPlaying()) {
        pp.pause();
        resumePosition = pp.getCurrentPosition();
        shouldStart = false;
        activity.cbSetPlay(false);
        buildNotification(PlaybackStatus.PAUSED);
    } else if (!pp.isPlaying()) {
        pp.start();
        activity.cbSetPlay(true);
        buildNotification(PlaybackStatus.PLAYING);
    }
}

public void rwMedia() {
    if (pp != null) {
        pp.seekTo(pp.getCurrentPosition() - 10000);
    }
}

public void ffMedia() {
    if (pp != null) {
        pp.seekTo(pp.getCurrentPosition() + 10000);
    }
}

public int getDuration() {
    return pp.getDuration();
}

public int getCurrentPosition() {
    try {
        return pp.getCurrentPosition();
    } catch (Exception e) {
        return 0;
    }
}

public void seekTo(int ms) {
    pp.seekTo(ms);
}

@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 void onPrepared(MediaPlayer mp) {
    //Invoked when the media source is ready for playback.
    Thread thread = new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                URL url = new URL(episode.getArt());
                bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
            } catch (Exception e) {
                e.printStackTrace();
            }
            activity.cbOnLoad();
            buildNotification(PlaybackStatus.PLAYING);
            pp.start();
        }
    });
    pp = mp;
    thread.start();
}

@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
    //Invoked indicating buffering status of
    //a media resource being streamed over the network.
}

@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
    //Invoked to communicate some info.
    return false;
}

@Override
public void onSeekComplete(MediaPlayer mp) {
    //Invoked indicating the completion of a seek operation.
}

//The system calls this method when an activity, requests the service be started
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    initMediaPlayer();
    try {
        initMediaSession();
    } catch (RemoteException e) {
        e.printStackTrace();
    }
    handleIncomingActions(intent);
    return super.onStartCommand(intent, flags, startId);
}

private void initMediaSession() throws RemoteException {
    if (mediaSessionManager != null) return; //mediaSessionManager exists

    mediaSessionManager = (MediaSessionManager) getSystemService(Context.MEDIA_SESSION_SERVICE);
    // Create a new MediaSession
    mediaSession = new MediaSession(getApplicationContext(), "PodcastPlayer");
    //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(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);

    //Set mediaSession's MetaData
    updateMetaData();

    // Attach Callback to receive MediaSession updates
    mediaSession.setCallback(new MediaSession.Callback() {
        // Implement callbacks
        @Override
        public void onPlay() {
            super.onPlay();
            pauseMedia();
        }

        @Override
        public void onPause() {
            super.onPause();
            pauseMedia();
        }

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

public enum PlaybackStatus {
    PLAYING,
    PAUSED
}

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

    // Create a new Notification
    Notification.Builder notificationBuilder = (Notification.Builder) new Notification.Builder(this)
            .setShowWhen(false)
            // Set the Notification style
            .setStyle(new Notification.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(bitmap)
            .setSmallIcon(android.R.drawable.stat_sys_headset)
            // Set Notification content information
            .setContentText(episode.getPodcast())
            .setContentTitle(episode.getTitle())
            .setContentInfo(episode.getDate())
            .setPriority(Notification.PRIORITY_MAX)
            // 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));

    notificationBuilder.setOngoing(true);
    notification = notificationBuilder.build();
    ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID, notification);
    startForeground(NOTIFICATION_ID, notification);
}

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

private PendingIntent playbackAction(int actionNumber) {
    Intent playbackAction = new Intent(this, PodcastService.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();
    }
}

private void updateMetaData() {
    // Update the current metadata
    mediaSession.setMetadata(new MediaMetadata.Builder()
            .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, bitmap)
            .putString(MediaMetadata.METADATA_KEY_ARTIST, episode.getPodcast())
            .putString(MediaMetadata.METADATA_KEY_ALBUM, episode.getDate())
            .putString(MediaMetadata.METADATA_KEY_TITLE, episode.getTitle())
            .build());
}

public void registerCallbacks(Activity activity) {
    this.activity = (Callbacks) activity;
}

//callbacks interface for communication with service clients!
public interface Callbacks {
    public void cbSetPlay(boolean play);

    public void cbOnLoad();

    public void cbPreLoad();
}

}

0 个答案:

没有答案