9

我在问一个已经(部分,在我看来)herehere解决的烦恼问题。假设在许多示例中,我们想要创建一个音乐应用程序,使用(比如说)单个活动和服务。我们希望服务在 Activity 停止或销毁时持续存在。这种生命周期建议启动服务:

当应用程序组件(例如活动)通过调用 startService() 启动服务时,服务被“启动”。一旦启动,服务可以无限期地在后台运行,即使启动它的组件被销毁

好的,但是我们还希望能够与服务进行通信,所以我们需要一个服务绑定。没问题,正如这个答案所暗示的那样,我们既有绑定服务也有启动服务:

到目前为止一切顺利,但问题在于,当活动开始时,我们不知道服务是否存在。它可能已经开始,也可能尚未开始。答案可能是这样的:

  • 在启动时,尝试绑定到服务(使用不带BIND_AUTO_CREATE标志的bindService() )
  • 如果失败,则使用 启动服务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仅在服务未运行时才调用它?)

PS我已经从我自己的代码中的问题继续前进:我startService()无论如何都会发出调用,因为重复startService()的只是被忽略了。但是,我仍然想更好地理解这些问题。

4

1 回答 1

2
  1. 如果您使用 0 标志绑定服务,则该服务将不会启动。您可以使用 BIND_AUTO_CREATE 标志绑定服务,如果服务未启动,它将被启动。但是,当您取消绑定服务时,该服务将被销毁。
  2. 带有 0 标志的 bindService 始终返回 true。
  3. 您可以随时调用 startService。如果服务已经在运行,则不会创建新服务。将调用正在运行的服务 onStartCommand。

如果在 onCreate 中 startService,然后在 onResume 中 bindService,在 onPause 中 unbindService,应该没有问题。

于 2013-04-23T06:28:49.987 回答