在Android上绑定服务与启动服务以及如何执行这两项操作

ang*_*rge 9 java service binding android

我问的是一个棘手的问题(部分地,在我看来)在这里这里提到.让我们说在许多例子中我们想要创建一个音乐应用程序,使用(比如说)单个活动和服务.我们希望在停止或销毁Activity时服务保持不变.这种生命周期建议启动服务:

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

好的,但我们也希望能够与服务进行通信,因此我们需要一个服务绑定.没问题,我们有一个绑定和启动服务,因为这个答案表明:

到目前为止一切都很好,但问题是由于活动开始时我们不知道服务是否存在.它可能已经开始,或者可能没有.答案可能是这样的:

  • 在启动时,尝试绑定到服务(使用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");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我们得到的是每次成功的绑定:

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
Run Code Online (Sandbox Code Playgroud)

全球性问题是"我是否误解了已启动的服务以及如何使用它们?" 更具体的问题是:

  • 认为零标志传递给bindService()"不要启动服务" 是对文档的正确理解吗?如果没有,bindService()没有启动服务就没有办法打电话?
  • 即使服务没有运行,为什么还要bindService()返回true?在这种情况下,基于Log呼叫,似乎服务尚未启动.
  • 如果前一点是正确/预期的行为bindService(),是否有解决方法(即以某种方式确保startService仅在服务未运行时才调用?)

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

Hoa*_*yen 2

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

如果在onCreate中startService,然后在onResume中bindService,在onPause中unbindService,应该不会有任何问题。