问题
I spend about 20 hours until now and my problem there still is . I am creating an android application that has several Activities (mainMenu , aboutUs,setting). I followed the best answered of below link and that was O.K . Music played using asyncTask isn't stopping by using cancel
When i run my app,(my code is in mainActivity ), the music begin and it does not stop when navigate to other Activities . This is GOOD . But i put a ToggleButton in my setting_activity Activity that i hope this Button starts and stops this music. NOW my question is how can i stop and/or start music again from setting_activity ?
in another solution : I create a class MusicManager and i call it`s start and stop . But this was several problems too :
- Music started in mainMenu_activity but only play for about 15 seconds and then stopped.
I could not stop the music from another activities.At this time i play music in mainMenua_ctivity as this line codes :
MusicManager mm = new MusicManager(this, R.raw.background_sound); mm.play();
How can i stop playing that ? 3. The music stopped when i navigate to other activities .
public class MusicManager implements OnPreparedListener {
static MediaPlayer mPlayer;
Context context;
private int mySoundId;
public MusicManager(Context ctx, int musicID) {
context = ctx;
mySoundId = musicID;
mPlayer = MediaPlayer.create(context, mySoundId);
mPlayer.setOnPreparedListener(this);
}
public void play() {
mPlayer = MediaPlayer.create(context, mySoundId);
}
public void stop() {
mPlayer.stop();
mPlayer.release();
}
@Override
public void onPrepared(MediaPlayer player) {
player.start();
mPlayer.setLooping(true);
mPlayer.setVolume(25, 25);
}
}
Finally i want to play a background music in all activities without stop/start music . How can i do it ?
回答1:
You could put the music player in a service. This would make it independent from the Activities and you would still be able to control the playback through intents.
Here are some code example about it: https://stackoverflow.com/a/8209975/2804473 The code below is written by Synxmax here at StackOverflow, and covered in the link above:
public class BackgroundSoundService extends Service {
private static final String TAG = null;
MediaPlayer player;
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.idil);
player.setLooping(true); // Set looping
player.setVolume(100,100);
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return 1;
}
public void onStart(Intent intent, int startId) {
// TO DO
}
public IBinder onUnBind(Intent arg0) {
// TO DO Auto-generated method
return null;
}
public void onStop() {
}
public void onPause() {
}
@Override
public void onDestroy() {
player.stop();
player.release();
}
@Override
public void onLowMemory() {
}
}
回答2:
@Override
public void onCreate (){
super.onCreate();
Player = MediaPlayer.create(this, R.raw.jingle);
mPlayer.setOnErrorListener(this);
if(mPlayer!= null)
{
mPlayer.setLooping(true);
mPlayer.setVolume(100,100);
}
mPlayer.setOnErrorListener(new OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int
extra){
onError(mPlayer, what, extra);
return true;
}
});
}
回答3:
public class serv extends Service{
MediaPlayer mp;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
public void onCreate()
{
mp = MediaPlayer.create(this, R.raw.b);
mp.setLooping(false);
}
public void onDestroy()
{
mp.stop();
}
public void onStart(Intent intent,int startid){
Log.d(tag, "On start");
mp.start();
}
}
回答4:
The top answer is correct, however you have to add the service to the manifest file.
<service android:enabled="true" android:name="BackgroundSoundService" />
回答5:
Simon's answer above is correct. I had similar problem where I have fragments which had music player and I needed to go back to that UI on click of a button. Your case is similar but instead of going back to UI, you want to control playback. Here is what I did for my application. This takes care of playback of audio list including shuffle and repeat functionality. This takes care of showing media controls in notification bar too.
- Create a service
MusicPlayerService
with following code:
public class MediaPlayerService extends Service implements MediaPlayer.OnCompletionListener,
MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnSeekCompleteListener,
MediaPlayer.OnInfoListener, MediaPlayer.OnBufferingUpdateListener,
AudioManager.OnAudioFocusChangeListener {
public static final String ACTION_PLAY = "pkg_name.ACTION_PLAY";
public static final String ACTION_PAUSE = "pkg_name.ACTION_PAUSE";
public static final String ACTION_PREVIOUS = "pkg_name.ACTION_PREVIOUS";
public static final String ACTION_NEXT = "pkg_name.ACTION_NEXT";
public static final String ACTION_STOP = "pkg_name.ACTION_STOP";
private MediaPlayer mediaPlayer;
//MediaSession
private MediaSessionManager mediaSessionManager;
private MediaSessionCompat mediaSession;
private MediaControllerCompat.TransportControls transportControls;
//AudioPlayer notification ID
private static final int NOTIFICATION_ID = 101;
//Used to pause/resume MediaPlayer
private int resumePosition;
// Binder given to clients
private final IBinder iBinder = new LocalBinder();
//List of available Audio files
private ArrayList audioList;
private int audioIndex = -1;
//Handle incoming phone calls
private boolean ongoingCall = false;
private PhoneStateListener phoneStateListener;
private TelephonyManager telephonyManager;
private Bitmap albumArtBitmap;
private boolean shuffle = false;
private boolean repeat = false;
private Random rand;
/**
* Service lifecycle methods
*/
@Override
public IBinder onBind(Intent intent) {
return iBinder;
}
@Override
public void onCreate() {
super.onCreate();
// Perform one-time setup procedures
// Manage incoming phone calls during playback.
// Pause MediaPlayer on incoming call,
// Resume on hangup.
callStateListener();
//ACTION_AUDIO_BECOMING_NOISY -- change in audio outputs -- BroadcastReceiver
registerBecomingNoisyReceiver();
//Listen for new Audio to play -- BroadcastReceiver
register_playNewAudio();
rand = new Random();
StorageUtil storage = new StorageUtil(getApplicationContext());
shuffle = storage.loadShuffleRepeat("Shuffle");
repeat = storage.loadShuffleRepeat("Repeat");
}
//The system calls this method when an activity, requests the service be started
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
//Load data from SharedPreferences
StorageUtil storage = new StorageUtil(getApplicationContext());
audioList = storage.loadAudio();
audioIndex = storage.loadAudioIndex();
if (audioIndex != -1 && audioIndex ready to receive media commands
mediaSession.setActive(true);
//indicate that the MediaSession handles transport control commands
// through its MediaSessionCompat.Callback.
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
//Set mediaSession's MetaData
updateMetaData();
// Attach Callback to receive MediaSession updates
mediaSession.setCallback(new MediaSessionCompat.Callback() {
// Implement callbacks
@Override
public void onPlay() {
super.onPlay();
resumeMedia();
}
@Override
public void onPause() {
super.onPause();
pauseMedia();
}
});
}
private void updateMetaData() {
fetchBitmapOfAlbum();
// Update the current metadata
mediaSession.setMetadata(new MediaMetadataCompat.Builder()
.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArtBitmap)
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, "")
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, activeAudio.getAlbumName())
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, activeAudio.getTrackName())
.build());
}
private Target target = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
albumArtBitmap = bitmap;
}
@Override
public void onBitmapFailed(Exception e, Drawable errorDrawable) {
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
private void fetchBitmapOfAlbum() {
Picasso.get().load(activeAudio.getAlbumArt())
.placeholder(R.drawable.rotate_animation)
.error(R.drawable.ic_blank)
.into(target);
}
private 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);
}
fetchBitmapOfAlbum(); //replace with your own image
String channelId = "";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
channelId = "APP_MUSIC";
}
// Create a new Notification
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
// Hide the timestamp
.setShowWhen(false)
// Set the Notification style
.setStyle(new androidx.media.app.NotificationCompat.MediaStyle()
// Attach our MediaSession token
.setMediaSession(mediaSession.getSessionToken())
// Show our playback controls in the compat view
.setShowActionsInCompactView(0, 1, 2))
// Set the Notification color
.setColor(ContextCompat.getColor(this.getApplicationContext(), R.color.colorAccent))
// Set the large and small icons
.setLargeIcon(albumArtBitmap)
.setSmallIcon(R.drawable.ic_stat_notifications)
// Set Notification content information
.setContentText(activeAudio.getTrackName())
.setTicker(activeAudio.getAlbumName() + "-" + activeAudio.getTrackName())
.setOngoing(true)
.setContentTitle(activeAudio.getAlbumName())
.setContentInfo(activeAudio.getTrackName())
// Add playback actions
.addAction(notificationAction, "pause", play_pauseAction)
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID, notificationBuilder.build());
}
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);
default:
break;
}
return null;
}
private void removeNotification() {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(NOTIFICATION_ID);
}
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();
}
}
/**
* Play new Audio
*/
private BroadcastReceiver playNewAudio = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//Get the new media index form SharedPreferences
audioIndex = new StorageUtil(getApplicationContext()).loadAudioIndex();
if (audioIndex != -1 && audioIndex
- Add the service to your manifest
<service android:name=".service.MediaPlayerService" />
- Bind the service in MainActivity and declare methods to call the service
public class MainActivity { private MediaPlayerService player; boolean serviceBound = false; public static final String Broadcast_PLAY_NEW_AUDIO = "pkg_name.PlayNewAudio"; //Binding this Client to the AudioPlayer Service private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // We've bound to LocalService, cast the IBinder and get LocalService instance MediaPlayerService.LocalBinder binder = (MediaPlayerService.LocalBinder) service; player = binder.getService(); serviceBound = true; } @Override public void onServiceDisconnected(ComponentName name) { serviceBound = false; } }; // Call this method to play track public void playAudio(int audioIndex, ArrayList updatedList) { //Check is service is active audioList = updatedList; if (!serviceBound) { Intent playerIntent = new Intent(this, MediaPlayerService.class); startService(playerIntent); bindService(playerIntent, serviceConnection, Context.BIND_AUTO_CREATE); } else { //Service is active //Send a broadcast to the service -> PLAY_NEW_AUDIO Intent broadcastIntent = new Intent(Broadcast_PLAY_NEW_AUDIO); sendBroadcast(broadcastIntent); } } // Additional methods for control public void start() { player.playMedia(); } public void pause() { player.pauseMedia(); } public boolean isPlaying() { if (player != null && serviceBound) { return player.isPlaying(); } return false; } }
来源:https://stackoverflow.com/questions/27579765/play-background-music-in-all-activities-of-android-app