我正在提出一个棘手的问题,这个问题已经在这里和这里部分得到了解决(在我看来)。比如说,我们想创建一个音乐应用程序,使用(比方说)一个活动和一个服务。我们希望当活动停止或销毁时,服务能够持续存在。这种生命周期建议使用启动服务:
每次我们得到的都是成功的绑定:
全局的问题是“我是否误解了绑定和启动服务以及如何使用它们?”更具体的问题是:
好的,但是我们还想能够与服务通信,所以我们需要一个服务绑定。没问题,正如这个答案所建议的,我们既有绑定服务,也有启动服务。当应用程序组件(如活动)通过startService()调用启动服务时,服务就会“启动”。一旦启动,即使启动它的组件被销毁,服务也可以无限期地在后台运行。
- 在活动启动时(或其他时间点),我们调用 startService()。
- 之后,我们调用 bindService() 来获取 IBinder 接口,并从那里继续进行。
到目前为止还不错,但问题在于当活动启动时,我们不知道服务是否存在。它可能已经启动,也可能没有启动。答案可能是这样的:
- 在启动时,尝试绑定服务(使用bindService(),不使用BIND_AUTO_CREATE标志)
- 如果失败,则使用
startService()
启动服务,然后再绑定它。
这个想法基于对bindService()
文档的特定阅读:
连接到应用程序服务,如有需要则创建它。
如果零标志表示“实际上不需要服务”,那么我们就没问题了。所以我们尝试使用以下代码来实现:
private void connectToService() {
Log.d("MainActivity", "Connecting to service");
// We try to bind to an existing service
Intent bindIntent = new Intent(this, AccelerometerLoggerService.class);
boolean bindResult = bindService(bindIntent, mConnection, 0);
if (bindResult) {
// Service existed, so we just bound to it
Log.d("MainActivity", "Found a pre-existing service and bound to it");
} else {
Log.d("MainActivity", "No pre-existing service starting one");
// Service did not exist so we must start it
Intent startIntent = new Intent(this, AccelerometerLoggerService.class);
ComponentName startResult = startService(startIntent);
if (startResult==null) {
Log.e("MainActivity", "Unable to start our service");
} else {
Log.d("MainActivity", "Started a service will bind");
// Now that the service is started, we can bind to it
bindService(bindIntent, mConnection, 0);
if (!bindResult) {
Log.e("MainActivity", "started a service and then failed to bind to it");
} else {
Log.d("MainActivity", "Successfully bound");
}
}
}
}
每次我们得到的都是成功的绑定:
04-23 05:42:59.125: D/MainActivity(842): Connecting to service
04-23 05:42:59.125: D/MainActivity(842): Found a pre-existing service and bound to it
04-23 05:42:59.134: D/MainActivity(842): onCreate
全局的问题是“我是否误解了绑定和启动服务以及如何使用它们?”更具体的问题是:
- 正确理解文档的方式是否是认为传递给
bindService()
的零标志意味着“不要启动服务”?如果不是,是否没有办法调用bindService()
而不启动服务? - 为什么
bindService()
即使服务没有运行也会返回true
?在这种情况下,基于Log
调用,似乎服务没有被启动。 - 如果前面的观点是
bindService()
的正确/预期行为,是否有解决方法(例如,确保只有在服务未运行时才调用startService
)?
P.S. 我已经解决了自己代码中的问题:我无论如何都会发出startService()
调用,因为重复的startService()
会被忽略。但是,我仍然希望更好地理解这些问题。