2014-04-06 63 views
1

我有一项使用媒体播放器播放音乐的服务。该服务从一项活动开始,如果某件事正在播放,并且用户离开该活动,该服务应继续在后台播放。 在前台运行服务似乎可行(我可以看到通知),但是在接近所有情况下服务立即销毁(OnDestroy由系统在服务上调用)。 我知道使用startForeground并不意味着这个服务永远不会被杀死,但它会一直被破坏,所以我想只有很少的资源迫使系统杀死它,这不是原因。服务不断遭到破坏

这是我实现它的方式: 在活动的OnCreate中,我开始(在后台)并绑定服务。在的onPause我把服务的前景不被摧毁,以及:在我的服务

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_play); 

    // start service 
    startService(new Intent(this, MyService.class)); 
    // connect to service 
    bindToService(); 
    ... 
} 

@Override 
protected void onDestroy() { 
    unbindFromService(); 
    super.onDestroy(); 
}; 

@Override 
protected void onStart() { 
    super.onStart(); 
} 

@Override 
protected void onStop() { 
    super.onStop(); 
} 

@Override 
protected void onPause() { 
    super.onPause(); 

    if (MediaPlayerService.getInstance().getStatus() == MEDIA_PLAYER_STATUS.Started) { 
     // current playing something => keep service running 
     mService.startForeground(); 
    } else { 
     // stop service 
     stopService(new Intent(MainActivity.this, MyService.class)); 
    } 
} 

@Override 
protected void onResume() { 
    super.onResume(); 

    // remove service from foreground 
    if (mService != null) { 
     mService.stopForeground(); 
    } 
} 

void bindToService() { 
    // 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). 
    bindService(new Intent(MainActivity.this, MyService.class), mConnection, Context.BIND_AUTO_CREATE); 
    mIsBound = true; 
} 

void unbindFromService() { 
    if (mIsBound) { 
     // Detach our existing connection. 
     unbindService(mConnection); 
     mIsBound = false; 
    } 
} 

private final ServiceConnection mConnection = new ServiceConnection() { 
    @Override 
    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. 
     mService = ((MyService.LocalBinder) service).getService(); 
     mService.registerClient(MainActivity.this); 
    } 

    @Override 
    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. 
     mService = null; 
     mService.unRegisterClient(MainActivity.this); 
    } 
}; 

和启动/ stopForeground功能是这样的:

public void startForeground() { 
    String songName = "blabla"; 
    // assign the song name to songName 
    PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0, 
      new Intent(getApplicationContext(), MainActivity.class), 
      PendingIntent.FLAG_UPDATE_CURRENT); 
    Notification notification = new Notification(); 
    notification.tickerText = songName; 
    notification.icon = R.drawable.ic_launcher; 
    notification.flags |= Notification.FLAG_ONGOING_EVENT; 
    notification.setLatestEventInfo(getApplicationContext(), "MusicPlayerSample", 
      "Playing: " + songName, pi); 
    startForeground(NOTIFICATION_ID, notification); 
} 

public void stopForeground() { 
    stopForeground(true); 
} 

任何想法,为什么服务状态越来越如果我离开这项活动,会被摧毁吗?

回答

1

问题是onCreate/onDestroy中的bind/unbind。 我无法真正解释它,但是在该生命周期状态中的绑定会导致即使您在该活动的onCreate()中使用startService()也会销毁该服务。

此安装程序现在工作得很好:

  • 在活动的onCreate()使用startService()来获得该服务启动。
  • 的onStartCommand()服务的具有结合返回Service.START_STICKY
  • 在活动的的onResume()到服务
  • 在活动的的onPause()如果事情是玩,调用服务和取消绑定的startForeground()从中。
  • 在Activity的onDestroy()中,如果当前没有任何内容正在播放,则调用stopService()。
3

这是您的answer

绑定服务只在另一个应用程序组件绑定到它时才运行。多个组件可以立即绑定到服务,但是当它们全部解除绑定时,服务将被销毁。

您应该致电startService()

+0

您也可以将它与该icky静态数据成员结合使用。从'onPause()'调用'startService()',并让服务从'onStartCommand()'移动到前台。然后,摆脱'mService'。 – CommonsWare

+0

感谢迄今为止的答案。但是如果我不与它绑定,我该如何与服务进行交流?我需要将来自活动的命令发送到服务(例如“播放文件xy”)并且返回到“客户端”活动(例如“播放停止”)。 – Maik

+0

我搜索了一下,发现了一些答案在这里:http://stackoverflow.com/questions/5597298/getting-data-from-an-unbound-service-in-android 但事实上,这或多或少是我我在做:我调用startService(在Activity的构造函数中),然后绑定它。那么为什么服务在我结束活动后仍然会被杀死? – Maik