Android从MusicService通知返回主要活动

时间:2014-08-28 16:28:11

标签: android android-fragments android-music-player

我正在开发一款适用于Android的音乐播放器,而且我遇到了这个问题。

现在我可以播放带有musicservice的歌曲并将其发送到后台,我还会显示当前播放歌曲的通知。

我需要的是从歌曲通知中重新打开主要活动并继续播放歌曲,它实际上启动了所需的活动,但音乐服务被重新创建并停止当前播放的歌曲。

这是我的代码。

MusicService.java

public class MusicService extends Service implements
    MediaPlayer.OnPreparedListener,
    MediaPlayer.OnErrorListener,
    MediaPlayer.OnCompletionListener {

private final IBinder musicBind = new MusicBinder();

//media player
private MediaPlayer player;

//song list
private ArrayList<SongModel> songs;

//current position
private int songPosition;

public MusicService() {
}

public void onCreate() {
    //create the service
    super.onCreate();

    //initialize position
    songPosition = 0;

    //create player
    player = new MediaPlayer();

    initMusicPlayer();
}

public void initMusicPlayer() {
    //set player properties
    player.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
    player.setAudioStreamType(AudioManager.STREAM_MUSIC);
    player.setOnPreparedListener(this);
    player.setOnCompletionListener(this);
    player.setOnErrorListener(this);

}

public void setList(ArrayList<SongModel> theSongs) {
    songs = theSongs;
}

public class MusicBinder extends Binder {
    public MusicService getService() {
        return MusicService.this;
    }
}

@Override
public IBinder onBind(Intent intent) {
    return musicBind;
}

@Override
public boolean onUnbind(Intent intent) {
    player.stop();
    player.release();
    return false;
}

public int getPosition() {
    return player.getCurrentPosition();
}

public int getCurrenListPosition() {
    return songPosition;
}

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

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

public void pausePlayer() {
    player.pause();
}

public void stopPlayer() {
    player.stop();
}

public void seekToPosition(int posn) {
    player.seekTo(posn);
}

public void start() {
    player.start();
}

public void playSong() {
    try {
        //play a song
        player.reset();

        SongModel playSong = songs.get(songPosition);
        String trackUrl = playSong.getFileUrl();

        player.setDataSource(trackUrl);
        player.prepareAsync();

    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
public void onCompletion(MediaPlayer mp) {
    if (mp.getCurrentPosition() == 0) {
        mp.reset();
    }
}

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

@Override
public void onPrepared(MediaPlayer mp) {
    //start playback
    mp.start();

    SongModel playingSong = songs.get(songPosition);

    Intent intent = new Intent(this, NavDrawerMainActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
            PendingIntent.FLAG_UPDATE_CURRENT);

    Notification.Builder builder = new Notification.Builder(this);

    builder.setContentIntent(pendingIntent)
            .setSmallIcon(R.drawable.ic_action_playing)
            .setTicker(playingSong.getTitle())
            .setOngoing(true)
            .setContentTitle(playingSong.getTitle())
            .setContentText(playingSong.getArtistName());

    Notification notification = builder.build();
    startForeground((int) playingSong.getSongId(), notification);
}

@Override
public void onDestroy() {
    stopForeground(true);
}

public void setSong(int songIndex) {
    songPosition = songIndex;
}

}

DiscoverSongsFragment.java

public class DiscoverSongsFragment extends Fragment
    implements MediaController.MediaPlayerControl {

JazzyGridView songsContainer;
SongsHelper songsHelper;
SongsAdapter songsAdapter;
ArrayList<SongModel> songsArrayList;
ConnectionState connectionState;

Context mContext;
private static View rootView;

SongModel currentSong;
SeekBar nowPlayingSeekBar;
final Handler handler = new Handler();

// this value contains the song duration in milliseconds.
// Look at getDuration() method in MediaPlayer class
int mediaFileLengthInMilliseconds;

View nowPlayingLayout;
boolean nowPlayingLayoutVisible;

TextView nowPlayingTitle;
TextView nowPlayingArtist;
ImageButton nowPlayingCover;
ImageButton nowPlayingStop;

private MusicService musicService;
private Intent playIntent;
private boolean musicBound = false;
private boolean playbackPaused = false;

private int mCurrentTransitionEffect = JazzyHelper.SLIDE_IN;

public static DiscoverSongsFragment newInstance() {
    return new DiscoverSongsFragment();
}

public DiscoverSongsFragment() {
    // Required empty public constructor
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    rootView = inflater.inflate(R.layout.fragment_discover_songs, container, false);
    mContext = rootView.getContext();
    setupViews(rootView);

    return rootView;
}

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

    if (playIntent == null) {
        playIntent = new Intent(mContext, MusicService.class);
        mContext.bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
        mContext.startService(playIntent);
    }
}

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

    if (isPlaying()) {
        showNowPlayingLayout();
        primarySeekBarProgressUpdater();
    }
}

@Override
public void onDestroy() {
    mContext.stopService(playIntent);
    musicService = null;
    super.onDestroy();
}

private void hideNowPlayingLayout() {
    nowPlayingLayoutVisible = false;
    nowPlayingLayout.setVisibility(View.GONE);

    Animation animationFadeIn = AnimationUtils.loadAnimation(mContext, R.anim.fade_out);
    nowPlayingLayout.startAnimation(animationFadeIn);
}

private void showNowPlayingLayout() {
    nowPlayingLayoutVisible = true;
    nowPlayingLayout.setVisibility(View.VISIBLE);

    Animation animationFadeIn = AnimationUtils.loadAnimation(mContext, R.anim.fade_in);
    nowPlayingLayout.startAnimation(animationFadeIn);
}

private void setupViews(View rootView) {
    songsHelper = new SongsHelper();
    songsArrayList = new ArrayList<SongModel>();
    connectionState = new ConnectionState(mContext);
    songsAdapter = new SongsAdapter(mContext, songsArrayList);

    nowPlayingLayout = rootView.findViewById(R.id.nowPlayingLayout);
    nowPlayingLayout.setVisibility(View.GONE);
    nowPlayingLayoutVisible = false;

    songsContainer = (JazzyGridView) rootView.findViewById(R.id.songsContainerView);
    songsContainer.setTransitionEffect(mCurrentTransitionEffect);
    songsContainer.setAdapter(songsAdapter);
    songsContainer.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

            musicService.setSong(position);
            musicService.playSong();

            if (playbackPaused) {
                playbackPaused = false;
            }

            currentSong = songsArrayList.get(position);

            // gets the song length in milliseconds from URL
            mediaFileLengthInMilliseconds = getDuration();

            if (currentSong != null) {
                nowPlayingTitle.setText(currentSong.getTitle());
                nowPlayingArtist.setText(currentSong.getArtistName());
                nowPlayingCover.setImageBitmap(currentSong.getCoverArt());
            }

            primarySeekBarProgressUpdater();

            if (!nowPlayingLayoutVisible) {
                showNowPlayingLayout();
            }
        }
    });

    nowPlayingSeekBar = (SeekBar) rootView.findViewById(R.id.nowPlayingSeekbar);
    nowPlayingSeekBar.setMax(99);

    nowPlayingTitle = (TextView) rootView.findViewById(R.id.nowPlayingTitle);
    nowPlayingArtist = (TextView) rootView.findViewById(R.id.nowPlayingArtist);
    nowPlayingStop = (ImageButton) rootView.findViewById(R.id.nowPlayingStop);
    nowPlayingStop.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (isPlaying()) {

                currentSong = null;
                playbackPaused = false;
                musicService.stopPlayer();
                mediaFileLengthInMilliseconds = 0;
                nowPlayingSeekBar.setProgress(0);
                hideNowPlayingLayout();

            }
        }
    });

    nowPlayingCover = (ImageButton) rootView.findViewById(R.id.nowPlayingCover);
    nowPlayingCover.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            try {
                Intent intent = new Intent(mContext, SongDetailsActivity.class);
                intent.putExtra("Title", currentSong.getTitle());
                intent.putExtra("Artist", currentSong.getArtistName());
                intent.putExtra("Album", currentSong.getAlbumName());
                intent.putExtra("Genre", currentSong.getGenre());
                intent.putExtra("CoverUrl", currentSong.getCoverArtUrl());

                startActivity(intent);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });

    getSongs();
    hideNowPlayingLayout();
}

private void getSongs() {

    if (!connectionState.isConnectedToInternet()) {

    }

    songsAdapter.clear();

    String songsUrl = Constants.getAPI_SONGS_URL();
    JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(songsUrl, new Response.Listener<JSONArray>() {
        @Override
        public void onResponse(JSONArray jsonArray) {

            if (jsonArray != null) {

                for (int i = 0; i < jsonArray.length(); i++) {
                    try {

                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                        SongModel song = songsHelper.getSongFromJson(jsonObject);
                        songsAdapter.add(song);

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                }
            }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError volleyError) {
        }
    });

    AppController.getInstance().addToRequestQueue(jsonArrayRequest);
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
}

@Override
public void onDetach() {
    super.onDetach();
}

/**
 * Method which updates the SeekBar primary progress by current song playing position
 */
private void primarySeekBarProgressUpdater() {
    nowPlayingSeekBar.setProgress((int) (((float) getCurrentPosition() / getDuration()) * 100));

    //if (isPlaying()) {
    Runnable runnable = new Runnable() {
        public void run() {
            primarySeekBarProgressUpdater();
        }
    };
    handler.postDelayed(runnable, 1000);
    //}
}

@Override
public void start() {
    musicService.start();
}

@Override
public void pause() {
    playbackPaused = true;
    musicService.pausePlayer();
}

@Override
public int getDuration() {
    if (musicService != null && musicBound && musicService.isPlaying()) {
        return musicService.getDuration();
    }
    return 0;
}

@Override
public int getCurrentPosition() {
    if (musicService != null && musicBound && musicService.isPlaying()) {
        return musicService.getPosition();
    }
    return 0;
}

public int getCurrentListPosition() {
    if (musicService != null && musicBound && musicService.isPlaying()) {
        return musicService.getCurrenListPosition();
    }
    return 0;
}

@Override
public void seekTo(int pos) {
    musicService.seekToPosition(pos);
}

@Override
public boolean isPlaying() {
    if (musicService != null && musicBound && musicService.isPlaying()) {
        return musicService.isPlaying();
    }
    return false;
}

@Override
public int getBufferPercentage() {
    return 0;
}

@Override
public boolean canPause() {
    return true;
}

@Override
public boolean canSeekBackward() {
    return true;
}

@Override
public boolean canSeekForward() {
    return true;
}

@Override
public int getAudioSessionId() {
    return 0;
}

//connect to the service
private ServiceConnection musicConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        MusicService.MusicBinder binder = (MusicService.MusicBinder) service;
        //get service
        musicService = binder.getService();
        //pass list
        musicService.setList(songsArrayList);
        musicBound = true;
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        musicBound = false;
    }
};

}

(当浏览抽屉菜单项时,片段也会重新创建)

我希望有人可以帮助我实现这一目标。我不知道如何在重新启动MainActivity时维护状态(顺便说一下,我使用navdrawer来保存片段)

1 个答案:

答案 0 :(得分:0)

在通知意图中包含当前播放的歌曲。歌曲改变时更新意图。包括清除顶部的标志和更新通知意图中当前的标志。 :( 抱歉 IDK,如果我的旗帜适合您的情况,但您可以进行更多的研究。

在您创建通知意图的服务中。

        // link the notifications to the recorder activity
        Intent resultIntent = new Intent(context, KmlReader.class);
        resultIntent
                .setAction(ServiceLocationRecorder.INTENT_COM_GOSYLVESTER_BESTRIDES_LOCATION_RECORDER);
        resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent resultPendingIntent = PendingIntent
                .getActivity(context, 0, resultIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder.setContentIntent(resultPendingIntent);

        return mBuilder.build();
    }

然后在主onCreate中检查包中当前正在播放的歌曲的名称并显示它。请注意我在使用之前如何检查是否存在捆绑密钥。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Intent intent = getIntent();

    String intentaction = intent.getAction();

    // First Run checks
    if (savedInstanceState == null) {
        // first run init

...

    } else {
        // get the saved_Instance state
        // always get the default when key doesn't exist
        // default is null for this example
        currentCameraPosition = savedInstanceState
                .containsKey(SAVED_INSTANCE_CAMERA_POSITION) ? (CameraPosition) savedInstanceState
                .getParcelable(SAVED_INSTANCE_CAMERA_POSITION) : null;

...