Play background music in all activities of Android app

会有一股神秘感。 提交于 2019-12-28 06:56:46

问题


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 :

  1. Music started in mainMenu_activity but only play for about 15 seconds and then stopped.
  2. 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.

  1. 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 
  1. Add the service to your manifest <service android:name=".service.MediaPlayerService" />
  2. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!