在Android应用的所有活动中播放背景音乐

时间:2014-12-20 11:31:25

标签: android background playback

我花了大约20个小时到现在,我的问题仍然存在。 我正在创建一个具有多个活动的android应用程序(mainMenu,aboutUs,setting)。 我按照下面链接的最佳答案,那是O.K。 Music played using asyncTask isn't stopping by using cancel

当我运行我的应用程序时,(我的代码在mainActivity中),音乐开始并且在导航到其他活动时不会停止。这很好。 但我在我的setting_activity活动中放了一个 ToggleButton ,我希望这个按钮启动并停止播放音乐。现在我的问题是如何从setting_activity中再次停止和/或启动音乐?

在另一个解决方案中: 我创建了一个类MusicManager,我称之为开始和停止。 但这也是几个问题:

  1. 音乐在mainMenu_activity中开始,但只播放约15秒然后停止。
  2. 我无法停止来自其他活动的音乐。这次我在mainMenua_ctivity中播放音乐作为此行代码:

    MusicManager mm = new MusicManager(this, R.raw.background_sound);
    mm.play();
    
  3. 我怎么能停止播放?  当我导航到其他活动时,音乐停止了。

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

    最后,我想在没有停止/开始音乐的所有活动中播放背景音乐。 我该怎么办?

5 个答案:

答案 0 :(得分:8)

您可以将音乐播放器置于服务中。这将使其独立于活动,您仍然可以通过意图控制回放。

以下是一些代码示例:https://stackoverflow.com/a/8209975/2804473 下面的代码由Synxmax在StackOverflow上编写,并在上面的链接中介绍:

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() {

    }
}

答案 1 :(得分:0)

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

答案 2 :(得分:0)

 @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 :(得分:0)

最正确的答案是正确的,但是您必须将服务添加到清单文件中。

 <service android:enabled="true" android:name="BackgroundSoundService" />

答案 4 :(得分:0)

上述西蒙的答案是正确的。我遇到类似的问题,即我的片段带有音乐播放器,并且需要单击按钮返回到该UI。您的情况类似,但是您想控制回放而不是返回UI。这是我为应用程序所做的。这需要播放音频列表,包括随机播放和重复播放功能。这样也可以在通知栏中显示媒体控件。

  1. 使用以下代码创建服务MusicPlayerService


    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
<service android:name=".service.MediaPlayerService" />