【问题标题】:How to play music in the background through out the App continuously?如何通过App在后台连续播放音乐?
【发布时间】:2014-04-17 06:58:48
【问题描述】:

我的 android 应用程序中有 4 个活动。创建第一个活动时,它会在后台播放音乐。现在,当用户从第一个活动转到第二个活动时,我希望歌曲继续播放而不会中断。只有当用户离开应用程序时,歌曲才会停止。

现在音乐在我退出一项活动时停止,并在下一项活动中从头开始。

【问题讨论】:

  • 我会使用本地绑定服务:developer.android.com/guide/components/services.html
  • 那么你必须实现一个Service并从那里控制MediaPlayer实例
  • @KenWolf 我认为您不应该使用 bindService。当您解除绑定时,它将被销毁。您可以更好地使用 startService(然后绑定到它)。
  • @RvdK 从技术上讲,它仍然是一个绑定服务,因为您绑定到它并调用公共方法。你只是没有通过绑定启动它。但我同意你的看法:)

标签: android android-music-player


【解决方案1】:

将播放器作为静态参考保持在后台。然后让它知道您是在应用程序内还是在应用程序外移动。这是我将如何做到的。为此,我使用了一个名为 DJ 的类。

public class DJ { 
private static MediaPlayer player;
private static boolean keepMusicOn;

public static void iAmIn(Context context){
if (player == null){
player = MediaPlayer.create(context, R.raw.music1);
player.setLooping(true);

try{
player.prepare();
}
catch (IllegalStateException e){}
catch (IOException e){}
}

if(!player.isPlaying()){
player.start();
}

keepMusicOn= false;
}

public static void keepMusicOn(){
keepMusicOn= true;
}

public static void iAmLeaving(){

if(!keepMusicOn){
player.pause();
}
}
}

现在从你的活动中像这样给 DJ 打电话。(让他知道你是否想继续播放音乐)

public void onPause() {
super.onPause();
DJ.iAmLeaving();
}

public void onResume(){
super.onResume();
DJ.iAmIn(this); 
}

public void buttonOnClick(View view){
DJ.keepMusicOn();
Intent intent = new Intent(this, TheOtherActivity.class);
startActivity(intent);
}

【讨论】:

    【解决方案2】:

    我是这样做的,我对结果很满意:

    第一次创建服务:

    public class LocalService extends Service
    {
        // This is the object that receives interactions from clients. See RemoteService for a more complete example.
        private final IBinder mBinder = new LocalBinder();
        private MediaPlayer player;
    
        /**
         * Class for clients to access. Because we know this service always runs in
         * the same process as its clients, we don't need to deal with IPC.
         */
        public class LocalBinder extends Binder
        {
            LocalService getService()
            {
                return LocalService.this;
            }
        }
    
        @Override
        public void onCreate()
        {
    
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId)
        {
            // We want this service to continue running until it is explicitly stopped, so return sticky.
            return START_STICKY;
        }
    
        @Override
        public void onDestroy()
        {
            destroy();
        }
    
        @Override
        public IBinder onBind(Intent intent)
        {
            return mBinder;
        }
    
    
        public void play(int res)
        {
            try
            {
                player = MediaPlayer.create(this, res);
                player.setLooping(true);
                player.setVolume(0.1f, 0.1f);
                player.start();
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    
    
        public void pause()
        {
            if(null != player && player.isPlaying())
            {
                player.pause();
                player.seekTo(0);
            }
        }
    
    
        public void resume()
        {
            try
            {
                if(null != player && !player.isPlaying())
                {
                    player.start();
                }
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    
    
        public void destroy()
        {
            if(null != player)
            {
                if(player.isPlaying())
                {
                    player.stop();
                }
    
                player.release();
                player = null;
            }
        }
    
    }
    

    第 2 次​​strong>,创建一个基础活动,并在你希望从中播放背景音乐的女巫中扩展所有活动:

    public class ActivityBase extends Activity
    {
        private Context context = ActivityBase.this;
        private final int [] background_sound = { R.raw.azilum_2, R.raw.bg_sound_5 };
        private LocalService mBoundService;
        private boolean mIsBound = false;
    
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            doBindService();
        }
    
        @Override
        protected void onStart()
        {
            super.onStart();
    
            try
            {
                if(null != mBoundService)
                {
                    Random rand = new Random();
                    int what = background_sound[rand.nextInt(background_sound.length)];
                    mBoundService.play(what);
                }
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    
        @Override
        protected void onStop()
        {
            super.onStop();
            basePause();
        }
    
    
    
        protected void baseResume()
        {
            try
            {
                if(null != mBoundService)
                {
                    mBoundService.resume();
                }
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    
    
        protected void basePause()
        {
            try
            {
                if(null != mBoundService)
                {
                    mBoundService.pause();
                }
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    
    
    
        private ServiceConnection mConnection = new ServiceConnection()
        {
            public void onServiceConnected(ComponentName className, IBinder service)
            {
                // This is called when the connection with the service has been
                // established, giving us the service object we can use to
                // interact with the service. Because we have bound to a explicit
                // service that we know is running in our own process, we can
                // cast its IBinder to a concrete class and directly access it.
                mBoundService = ((LocalService.LocalBinder) service).getService();
    
                if(null != mBoundService)
                {
                    Random rand = new Random();
                    int what = background_sound[rand.nextInt(background_sound.length)];
                    mBoundService.play(what);
                }
            }
    
            public void onServiceDisconnected(ComponentName className)
            {
                // This is called when the connection with the service has been
                // unexpectedly disconnected -- that is, its process crashed.
                // Because it is running in our same process, we should never
                // see this happen.
                mBoundService = null;
    
                if(null != mBoundService)
                {
                    mBoundService.destroy();
                }
            }
        };
    
        private void doBindService()
        {
            // Establish a connection with the service. We use an explicit
            // class name because we want a specific service implementation that
            // we know will be running in our own process (and thus won't be
            // supporting component replacement by other applications).
    
            Intent i = new Intent(getApplicationContext(), LocalService.class);
            bindService(i, mConnection, Context.BIND_AUTO_CREATE);
            mIsBound = true;
        }
    
        private void doUnbindService()
        {
            if (mIsBound)
            {
                // Detach our existing connection.
                unbindService(mConnection);
                mIsBound = false;
            }
        }
    
    
        @Override
        protected void onDestroy()
        {
            super.onDestroy();
            doUnbindService();
        }
    }
    

    就是这样,现在您在从 ActivityBase 扩展的所有活动中都有背景声音了。

    您甚至可以通过调用 basePause()/baseResume() 来控制暂停/恢复功能。

    不要忘记在清单中声明服务:

    <service android:name="com.gga.screaming.speech.LocalService" />
    

    【讨论】:

      【解决方案3】:

      这个想法是您不应该播放活动本身的音乐。在 Android 上,活动和其他上下文具有生命周期。这意味着他们将活着……然后死去。而当他们死了,他们就不能再做任何事了。

      因此,如果您想让音乐的寿命更长,就必须找到生命周期不止一个活动的东西。

      最简单的解决方案是 Android 服务。你可以在这里找到一个好帖子:Android background music service

      【讨论】:

        猜你喜欢
        • 2013-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-06
        • 1970-01-01
        • 2022-09-30
        • 1970-01-01
        • 2013-07-23
        相关资源
        最近更新 更多