0

I have an activity that, as far as I can tell, is happily binding to a service every time the activity is created. The first time the activity is created, it also starts the service with the startService command, as follows:

    private fun attachRecorderService() {
       val intent = Intent(this, AudioRecorderService::class.java)
       bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE)
       if (!mBooleanRecorderServiceStarted) {
           startService(intent)
           mBooleanRecorderServiceStarted = true
       }
    }

That activity's fragments all get a reference to that service in their onActivityCreated() function as follows:

    override fun onActivityCreated(savedInstanceState: Bundle?) {
       super.onActivityCreated(savedInstanceState)
       val parentActivity = activity as MainActivity
       mAudioRecorderService = parentActivity.mAudioRecorderService

That works fine the first time the fragment is created, but as soon as the screen is rotated I get an error telling me the service hasn't been initialised in the activity.

lateinit property mAudioRecorderService has not been initialized

As far as I can tell, onActivityCreated() in the fragment is racing with onCreate() in the activity, and trying to get the reference before onCreate() initialises it.

Which I don't understand. I thought onActivityCreated() waited until after onCreate() had completed.

What am I doing wrong? Should I use some sort of callback in the fragment, that only triggers when the activity has bound to the service? I've seen mention of that, but I have no idea how to do it.

The question Communication between Activity and Service deals with Activities and Services. I'm asking about the Fragments that are attached to the Activity, and how they can access a service that the Activity has already bound to.

John
  • 5,581
  • 6
  • 29
  • 46
  • Possible duplicate of [Communication between Activity and Service](https://stackoverflow.com/questions/20594936/communication-between-activity-and-service) – Zoe Aug 15 '18 at 08:08
  • That question deals with Activities and Services. I'm asking about the Fragments that are attached to the Activity, and how they can access a service that the Activity has already bound to. I don't see where that question is addressed in any of the answers. – John Aug 15 '18 at 10:28
  • It's still the same system – Zoe Aug 15 '18 at 10:32
  • It may turn out my question duplicates this though: https://stackoverflow.com/questions/40750712/how-to-access-service-functions-from-fragment-which-is-bound-to-parent-activity It contains an answer that looks like it might solve my problem. – John Aug 15 '18 at 10:50

1 Answers1

1

The service is not available directly after calling bindService. Use a ServiceConnection. When onServiceConnected is called the service is ready to use

private val connection = object : ServiceConnection {
    override fun onServiceDisconnected(p0: ComponentName?) {

    }

    override fun onServiceConnected(p0: ComponentName, binder: IBinder) {

    }
}

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    application.bindService(Intent(application, MyService::class.java), connection, Context.BIND_AUTO_CREATE)
}
JPLauber
  • 1,361
  • 1
  • 14
  • 22
  • Thanks Sativa. I am using onServiceConnected in the activity. But it's apparently completing after onCreate() finishes in the activity, hence the race with onActivityCreated() in the fragment. So how do I use the onServiceConnected() callback from the fragment, to avoid the race? – John Aug 15 '18 at 10:22
  • You can just call bindService in the Activity in onCreate to use the service in the activity and in the Fragment in onActivityCreated to use it in the fragment. The Service will only have one instance. It can be bound to as many Activities, Fragments as you want – JPLauber Aug 15 '18 at 12:24
  • Thanks. I guess I will have to do that. I was trying to bind to the service just the one time, in the Activity, and then pass a reference to that binding to the fragments. But it seems to create a race between the onActivityCreated() callback and the onServiceConnected() callback. I might also try binding to the application context as outlined here: https://stackoverflow.com/questions/15235773/bind-service-to-fragmentactivity-or-fragment – John Aug 15 '18 at 13:07