在启动服务后的某个时间,列表在Android服务中获取为空

时间:2017-10-04 06:36:52

标签: android service android-mediaplayer media

我正在开发Android MusicPlayer。我创建了服务类扩展服务。在我的Main_activity中,我使用 startService()方法调用服务类,同时使用 Intent传递音乐列表

private void sendDatatoService() {
    if (playIntent == null) {
        playIntent = new Intent(this, MusicService.class);
        playIntent.putParcelableArrayListExtra("songList",list);
        bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);

        startService(playIntent);
    }
}

private final ServiceConnection musicConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {

        MusicService.PlayerBinder binder = (MusicService.PlayerBinder) service;
        serviceMusic = binder.getService();
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

        Log.e("serviceMusic::","onServiceDisconnected");
    }
};

我的MusicPlayer工作正常,但是当我暂停一段时间并尝试再播放一些歌曲时,它崩溃说我的歌曲列表是空的。这里发生了什么,当Android杀死我的服务时,我应该从START_STICKY或其他任何一种服务开始保持我的数据可用于服务或重新获得列表?

@Override
public void onCreate() {
    super.onCreate();
    notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    // TODO: Done // creating a channel before creating a notification, needs channel to show notification in Android-O+ OS
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        initChannel();
    }
    //initializing media player, to play the music using MediaPlayer Api/class we need it to play the music
    initMediaPlayer();
    notificationCompatBuilder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID);
    initNoisyReceiver();
}


public void initMediaPlayer() {
    if (mPlayer == null) {
        mPlayer = new MediaPlayer();
        mPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
        mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mPlayer.setOnPreparedListener(this);
        mPlayer.setOnCompletionListener(this);
        mPlayer.setOnErrorListener(this);
    }
}

public void updateNotification(String updatedSongName, int songPos) {

    setBitmapImage(mListOfSongs.get(songPos).getAlbumArt());
    mNotification = notificationCompatBuilder
            .setSmallIcon(R.drawable.play_logo)
            .setLargeIcon(bitmapImage)
            .setOngoing(true)
            .setColorized(true)
            .setStyle(new NotificationCompat.DecoratedCustomViewStyle())
            .setDefaults(Notification.DEFAULT_ALL)
            .build();

    mNotification.contentView.setTextViewText(R.id.notify_song_name, updatedSongName);
    notificationManager.notify(NOTIFICATION_ID, mNotification);

    String updatedAlbumName = mListOfSongs.get(songPos).getSongAlbumName();
    String updatedArtistName = mListOfSongs.get(songPos).getSongArtist();
    String updatedAlbumArt = mListOfSongs.get(songPos).getAlbumArt();
    String updatedSongDuration = mListOfSongs.get(songPos).getSongDuration();

    mCallback.onupdateClick(songPos, updatedSongName, updatedAlbumName, updatedArtistName, updatedAlbumArt, updatedSongDuration);
}


public class PlayerBinder extends Binder {
    public MusicService getService() {
        Log.d("test", "getService()");
        return MusicService.this;
    }
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    Log.d("test", "onBind Called");
    return musicBind;
}

@Override
public boolean onUnbind(Intent intent) {


    if (mgr != null) {
        mgr.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
    }
    //mAudioManager.abandonAudioFocus(this);

    notificationManager.cancel(NOTIFICATION_ID);
    return false;
}

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


    if (intent != null) {
        mListOfSongs = intent.getParcelableArrayListExtra("songList");
        String Action = intent.getAction();
        if (!TextUtils.isEmpty(Action)) {
            switch (Action) {
                case ACTION_PAUSE:
                    playPauseSong();
                    break;
                case ACTION_NEXT:
                    nextSong();
                    break;
                case ACTION_PREVIOUS:
                    previousSong();
                    break;
                case ACTION_STOP:
                    stopSong();
                    stopSelf();
                    break;
            }
        }
    }
    return START_STICKY;
}

private void stopSong() {

    if (mgr != null) {
        mgr.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
    }
    if (mPlayer != null) {
        if (mPlayer.isPlaying()) {
            mPlayer.stop();
            mPlayer.release();
        } else {
            mPlayer.release();
        }
    }
    NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    manager.cancel(NOTIFICATION_ID);
    System.exit(0);
}

public void previousSong() {
    try {
        if (SONG_POS == 0) {
            Toast.makeText(this, "No Previous Song", Toast.LENGTH_SHORT).show();
            return;
        }
        SONG_POS--;
        startSong(Uri.parse(mListOfSongs.get(SONG_POS).getSongUri()), mListOfSongs.get(SONG_POS).getSongName(), SONG_POS);
    } catch (Exception e) {

    }
}

public void nextSong() {

    // TODO: 10/1/2017  check if  mListOfSongs is not empty otherwise it will show an error
    if (mListOfSongs == null) {
        Toast.makeText(this, "Restart the App", Toast.LENGTH_SHORT).show();
        return;
    }
    if (SONG_POS >= mListOfSongs.size() - 1) {
        SONG_POS = -1;
    }
    try {
        SONG_POS++;
        startSong(Uri.parse(mListOfSongs.get(SONG_POS).getSongUri()), mListOfSongs.get(SONG_POS).getSongName(), SONG_POS
        );
    } catch (Exception e) {
        Toast.makeText(this, "No Next Song", Toast.LENGTH_SHORT).show();
        startSong(Uri.parse(mListOfSongs.get(SONG_POS).getSongUri()), mListOfSongs.get(SONG_POS).getSongName(), SONG_POS);
    }
}

public void startSong(Uri parseSongUri, String songName, int SONG_POS) {

    //checkAudioFocus();

    if (!successfullyRetrievedAudioFocus()) {
        return;
    }
    mPlayer.reset();
    mState = STATE_PLAYING;
    mSongUri = parseSongUri;

    try {
        mPlayer.setDataSource(getApplicationContext(), mSongUri);
    } catch (Exception e) {
        Log.e("MUSIC SERVICE", "ERROR SETTING DATA SOURCE", e);
    }
    mPlayer.prepareAsync();
    updateNotification(songName, SONG_POS);
}


public void playPauseSong() {
    if (mPlayer == null) {
        initMediaPlayer();
    }
    if (mState == STATE_PAUSED) {
        mState = STATE_PLAYING;
        mPlayer.start();

    } else {
        mState = STATE_PAUSED;
        mPlayer.pause();
    }
}

//starting media player when media player is ready
@Override
public void onPrepared(MediaPlayer mp) {
    mPlayer.start();
}

@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
    mp.reset();
    return false;
}

@Override
public void onCompletion(MediaPlayer mp) {
    mPlayer.reset();

    try {
        if (SONG_POS < mListOfSongs.size() - 1) {
            nextSong();
        } else {
            SONG_POS = 0;
            mPlayer.setDataSource(getApplicationContext(), Uri.parse(mListOfSongs.get(SONG_POS).getSongUri()));
        }
    } catch (Exception e) {
        Log.e("MUSIC SERVICE", "Error setting data source", e);
    }

}


@Override
public void onAudioFocusChange(int focusChange) {

    switch (focusChange) {
        case AudioManager.AUDIOFOCUS_LOSS: {
            if (mPlayer.isPlaying()) {
                mPlayer.stop();
            }
            break;
        }
        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: {
            mPlayer.pause();
            break;
        }
        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: {
            if (mPlayer != null) {
                mPlayer.setVolume(0.3f, 0.3f);
            }
            break;
        }
        case AudioManager.AUDIOFOCUS_GAIN: {
            if (mPlayer != null) {
                if (!mPlayer.isPlaying()) {
                    mPlayer.start();
                }
                mPlayer.setVolume(1.0f, 1.0f);
            }
            break;
        }
    }
}


private void setSongURI(Uri mSongUri) {
    this.mSongUri = mSongUri;
}

private void setBitmapImage(String albumArt) {
//        Drawable img = Drawable.createFromPath(albumArt);
    if (!albumArt.equals("null")) {
        bitmapImage = BitmapFactory.decodeFile(albumArt);
    } else {
        bitmapImage = BitmapFactory.decodeResource(getResources(), R.drawable.beat_box_logo);
    }
}

 public void setSelectedSong(int pos, int notification_id, Context     context, UpdateFromService listner) {
    SONG_POS = pos;
    this.mCallback = listner;
    NOTIFICATION_ID = notification_id;

    setSongURI(Uri.parse(mListOfSongs.get(SONG_POS).getSongUri()));

    setBitmapImage(mListOfSongs.get(SONG_POS).getAlbumArt());

    ShowNotification();
    startSong(Uri.parse(mListOfSongs.get(SONG_POS).getSongUri()), mListOfSongs.get(SONG_POS).getSongName(), SONG_POS);
}

private void ShowNotification() {
    PendingIntent pendingIntent, pendingIntentStop;
    Intent intentStop, intentPause, intentPrevious, intentNext;

    RemoteViews notificationView = new RemoteViews(getPackageName(), R.layout.notification_mediacontroller);
    notificationView.setTextViewText(R.id.notify_song_name, mListOfSongs.get(SONG_POS).getSongName());

    intentStop = new Intent(ACTION_STOP);
    pendingIntentStop = PendingIntent.getService(getApplicationContext(), REQUEST_CODE_STOP, intentStop, PendingIntent.FLAG_CANCEL_CURRENT);

    intentPause = new Intent(ACTION_PAUSE);
    pendingIntent = PendingIntent.getService(getApplicationContext(), REQUEST_CODE_PAUSE, intentPause, PendingIntent.FLAG_UPDATE_CURRENT);
    notificationView.setOnClickPendingIntent(R.id.notify_btn_pause, pendingIntent);


    intentPrevious = new Intent(ACTION_PREVIOUS);
    pendingIntent = PendingIntent.getService(getApplicationContext(), REQUEST_CODE_PREVIOUS, intentPrevious, PendingIntent.FLAG_UPDATE_CURRENT);
    notificationView.setOnClickPendingIntent(R.id.notify_btn_previous, pendingIntent);

    intentNext = new Intent(ACTION_NEXT);
    pendingIntent = PendingIntent.getService(getApplicationContext(), REQUEST_CODE_NEXT, intentNext, PendingIntent.FLAG_UPDATE_CURRENT);
    notificationView.setOnClickPendingIntent(R.id.notify_btn_next, pendingIntent);


    //this intent and pending intent using to open the app when user click on Notification
    Intent notificationIntent = new Intent(this, MainActivity.class);
    PendingIntent notificationPendingIntent = PendingIntent.getActivity(this, NOTIFICATION_ID,
            notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);


    Intent intent = new Intent(getBaseContext(), MainActivity.class);
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(getApplicationContext());
    stackBuilder.addNextIntent(intent);
    PendingIntent pendingIntent2 = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_CANCEL_CURRENT);


    mNotification = notificationCompatBuilder
            .setColorized(true)
            .setContent(notificationView)
    /*                .setContentIntent(pendingIntent2)*/   //opens activity when user click on notification
            .setCustomContentView(notificationView)
            .setDefaults(Notification.COLOR_DEFAULT)
            .setDeleteIntent(pendingIntentStop)
            .setLargeIcon(bitmapImage)
            .setOngoing(true)
            .setSmallIcon(R.drawable.play_logo)
            .setStyle(new NotificationCompat.DecoratedCustomViewStyle())
            .build();
    startForeground(NOTIFICATION_ID, mNotification);
}


private void initChannel() {
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        notificationChannel = new NotificationChannel(CHANNEL_ID,
                CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
        notificationChannel.setVibrationPattern(new long[]{0});
        notificationChannel.setDescription("BeatBox Notification");
        notificationChannel.enableLights(false);
        notificationChannel.enableVibration(false);
        notificationChannel.canShowBadge();
        notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
        notificationManager.createNotificationChannel(notificationChannel);
    }
}

private void initNoisyReceiver() {
    //Handles headphones coming unplugged. cannot be done through a manifest receiver
    IntentFilter filter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);

    registerReceiver(mNoisyReceiver, filter);
}

private BroadcastReceiver mNoisyReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (mPlayer != null && mPlayer.isPlaying()) {
            mPlayer.pause();
        }
    }
};

private boolean successfullyRetrievedAudioFocus() {
    AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

    int result = audioManager.requestAudioFocus(this,
            AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);

    return result == AudioManager.AUDIOFOCUS_GAIN;
}

@Override
public void onDestroy() {
    super.onDestroy();
    unregisterReceiver(mNoisyReceiver);
    notificationManager.cancel(NOTIFICATION_ID);
}

@Override
public void onTaskRemoved(Intent rootIntent) {
    super.onTaskRemoved(rootIntent);

    notificationManager.cancel(NOTIFICATION_ID);
    if (mPlayer != null) {
        mPlayer.stop();
        mPlayer.release();
    }
}

2 个答案:

答案 0 :(得分:1)

您可以使用标记来降低系统杀死您的服务的可能性,但它永远不会是100%。但是,您可以使您的服务能够从持久性存储(如db或共享首选项)中获取播放列表本身。

答案 1 :(得分:0)

如果null Intent是唯一的问题,只需返回START_REDELIVER_INTENT

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

    .....
    return START_REDELIVER_INTENT;
}

onStartCommand(Intent, int, int)返回的常量:如果此服务的进程在启动时被终止(从onStartCommand(Intent, int, int)返回后),那么它将被安排重新启动并且最后一次传递意图通过onStartCommand(Intent, int, int)重新发送给它。