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

2024-02-15

我问的是一个令人烦恼的问题,该问题已经(在我看来部分地)得到解决here https://stackoverflow.com/questions/5243562/lifecycle-of-service-that-is-started-and-bound and here https://stackoverflow.com/questions/3514287/android-service-startservice-and-bindservice。假设像在许多示例中一样,我们想要创建一个音乐应用程序,使用(比如说)单个活动和服务。我们希望当 Activity 停止或销毁时服务能够持续存在。这种生命周期建议启动服务:

当应用程序组件(例如 Activity) 通过调用 startService() 来启动它。一旦启动,服务 可以无限期地在后台运行,即使该组件 开始它被摧毁

好的,但是我们还希望能够与服务通信,因此我们需要服务绑定。没问题,我们已经绑定并启动了服务这个答案表明 https://stackoverflow.com/questions/3514287/android-service-startservice-and-bindservice:

  • 在活动启动时(或其他某个点),我们调用启动服务() http://developer.android.com/reference/android/content/Context.html#startService%28android.content.Intent%29
  • 之后我们打电话绑定服务() http://developer.android.com/reference/android/content/Context.html#bindService%28android.content.Intent,%20android.content.ServiceConnection,%20int%29以获得IBinder http://developer.android.com/reference/android/os/IBinder.html界面,然后从那里继续。

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

  • 启动时,尝试绑定到服务(使用绑定服务() http://developer.android.com/reference/android/content/Context.html#bindService%28android.content.Intent,%20android.content.ServiceConnection,%20int%29没有绑定_自动_创建 http://developer.android.com/reference/android/content/Context.html#BIND_AUTO_CREATE flag)
  • 如果失败,则使用启动服务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() return true即使服务没有运行?在这种情况下,该服务似乎尚未启动,基于Log calls.
  • 如果上一点是正确/预期的行为bindService(),是否有解决方法(即以某种方式确保startService仅当服务未运行时才调用?)

附:我已经解决了我自己代码中的问题:我发出startService()不管怎样,因为重复了startService()就被简单地忽略了。不过,我还是想更好地理解这些问题。


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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 上的绑定服务与启动服务以及如何同时执行这两项操作 的相关文章

随机推荐