Android 服务和MediaPlayer-控制屏幕旋转和应用程序退出

Android 服务和MediaPlayer-控制屏幕旋转和应用程序退出,android,service,android-service,android-mediaplayer,status,Android,Service,Android Service,Android Mediaplayer,Status,已解决-请参阅答案 我正在处理一个使用MediaPlayer类播放音乐的服务的应用程序 我在屏幕旋转和离开应用程序时遇到问题。我丢失了MediaPlayer对象或服务本身的引用或状态。我花了这么多时间在这上面,真的不知道出了什么问题 我在活动的onResume中启动并绑定到服务: @Override protected void onResume() { Intent intent=new Intent(getApplicationContext(), M

已解决-请参阅答案

我正在处理一个使用MediaPlayer类播放音乐的服务的应用程序

我在屏幕旋转和离开应用程序时遇到问题。我丢失了MediaPlayer对象或服务本身的引用或状态。我花了这么多时间在这上面,真的不知道出了什么问题

我在活动的
onResume
中启动并绑定到服务:

    @Override
    protected void onResume()
    {
        Intent intent=new Intent(getApplicationContext(), MusicService.class);
        bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);

        super.onResume();
    }
    private ServiceConnection serviceConnection=new ServiceConnection()
    {
        public void onServiceConnected(ComponentName className, IBinder binder)
        {
            service=((MusicService.MyBinder)binder).getService();
        }

        public void onServiceDisconnected(ComponentName className)
        {
            service=null;
        }
    };
@Override
protected void onDestroy()
{
    unbindService(serviceConnection);
    super.onDestroy();
}
我通过
ServiceConnection
获取对服务的引用:

    @Override
    protected void onResume()
    {
        Intent intent=new Intent(getApplicationContext(), MusicService.class);
        bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);

        super.onResume();
    }
    private ServiceConnection serviceConnection=new ServiceConnection()
    {
        public void onServiceConnected(ComponentName className, IBinder binder)
        {
            service=((MusicService.MyBinder)binder).getService();
        }

        public void onServiceDisconnected(ComponentName className)
        {
            service=null;
        }
    };
@Override
protected void onDestroy()
{
    unbindService(serviceConnection);
    super.onDestroy();
}
此时,我可以从我的服务调用任何方法:
service.playMusic()并且工作正常

我在
onDestroy
中解除绑定:

    @Override
    protected void onResume()
    {
        Intent intent=new Intent(getApplicationContext(), MusicService.class);
        bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);

        super.onResume();
    }
    private ServiceConnection serviceConnection=new ServiceConnection()
    {
        public void onServiceConnected(ComponentName className, IBinder binder)
        {
            service=((MusicService.MyBinder)binder).getService();
        }

        public void onServiceDisconnected(ComponentName className)
        {
            service=null;
        }
    };
@Override
protected void onDestroy()
{
    unbindService(serviceConnection);
    super.onDestroy();
}
这是我的服务课:

public class MusicService extends Service
{
    private final IBinder binder=new MyBinder();
    private MediaPlayer player;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        return Service.START_REDELIVER_INTENT;
    }

    @Override
    public IBinder onBind(Intent intent)
    {
        player=MediaPlayer.create(getApplicationContext(), R.raw.tumbler);
        player.setLooping(true);
        player.setVolume(80, 80);

        return binder;
    }

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

    public void play()
    {
        player.start();
        Log.d("MUSIC SERVICE", "play!");
    }
}
所以,问题是:

  • 当我退出时,服务和音乐继续播放。我想阻止它。如果我再次进入应用程序,相同的服务将再次启动,音乐将播放两次。我想阻止它

  • 当我旋转屏幕时,MediaPlayer会继续播放(如我所愿),但我无法再调用pause()、start()等,因为它的状态已更改(我收到消息“MediaPlayer”)﹕ 在状态8'和'MediaPlayer'中调用暂停﹕ 在状态0')中调用start

求你了,需要帮忙。提前谢谢

@Override
public IBinder onBind(Intent intent) {
    player=MediaPlayer.create(getApplicationContext(), R.raw.tumbler);
    player.setLooping(true);
    player.setVolume(80, 80);

    return binder;
}
每次绑定到服务时,您都在初始化
MediaPlayer
,并且从未停止上一个实例。不要在
onBind()
中启动媒体,等待服务发出启动/停止媒体播放器的命令。服务比活动寿命长(这就是它们的设计目的),因此,在活动被破坏后,它继续运行也就不足为奇了。除非你特别告诉它,否则这是预期的行为。如果您希望媒体播放器在活动打开时继续运行,您可能希望使用无头片段来保留一个保留片段,该片段可以在
onCreate()
/
onDestroy()
中为您管理
MediaPlayer

我脑子里乱七八糟的(还有代码),但最后它还是起作用了。
如果这不是正确的方法,请让我知道

我的第一个问题是:当应用程序退出时,服务没有被破坏,MediaPlayer正在播放,直到我强制关闭应用程序。如果我没有强制关闭,在应用程序重新启动时,我有两个MediaPlayer同时播放,以此类推

原因:我没有手动终止服务。
解决方案:在活动的
ondestory()
上,调用
unbindService()
stopService()

第二个问题是:当屏幕旋转时,我丢失了MediaPlayer的对象引用,音乐失去了控制,因为我无法访问对象。
原因:设计不好。我正在将MediaPlayer设置为服务的onBind()方法感谢@kcopock。他注意到了。因此,当屏幕旋转时,调用了Activity的onCreate(),其中包含bindService(),从而创建了新的MediaPlayer对象,甚至没有清理以前的实例。
解决方案:只需将该代码移到另一个未自动调用的部分,并在应用程序启动时手动调用一次,而不是每次通过configChanges重新创建活动时

所以,基本上我就是这样修复的,希望对其他用户有所帮助。

干杯。

在他的情况下,他没有启动服务(他只是用BIND_AUTO_CREATE标志调用了bindService),因此当活动被销毁时,服务将被销毁。创建多个实例是正确的。我修正了这个问题,但是当我旋转屏幕时,MediaPlayer的引用变为null,我得到了相应的异常。此外,我尝试在服务被破坏时停止播放器(onDestroy),它在我退出应用程序时工作,也在我旋转屏幕时工作。我只想在退出时停止。我也修复了null引用,返回START\u STICKY并在绑定之前调用startService()。所以现在我只需要知道如何在轮换时继续比赛,而不是在退出时。请帮忙。