1

Long introduction before the question appears, however this is for the sake of giving the complete background picture.

I have created a service for doing some background work, and an activity to bind to the service to receive and display status updates from the service ( appending messages to a TextView). The service is always running but the activity can be sent to background, destroyed, reopened several times as the user wishes. Hence it is a Started Service with bidirectional communication with the Activity.

I implemented this as per instructions in https://developer.android.com/guide/components/bound-services.html#Messenger and the logic is very similar to Example: Communication between Activity and Service using Messaging; except:

  • the service handles all background work in a HandlerThread (as instructed at https://developer.android.com/guide/components/services.html#ExtendingService)
  • Service puts itself to foreground at start (with a notification)
  • IncomingHandlers in both the service and the activity are defined static & final with WeakReferences to the outer classes (Service and Activity accordingly)
  • The service receives a callback reference to a Messenger (from Activity) during onBind/onRebind, stores in an array, and removes it from the array during onUnbind.

The activity binds at resume and unbinds at pause.

The issue I faced was; when the activity is first launched after service starts, the TextView displays the status updates received from the Service perfectly fine, however when Activity is sent back and resumed the TextView does not update any longer - although debugging did not reveal any problem regarding binding, bidirectional communication or TextView.append. The UI just did not update.

After reading this answer TextView stops updating after bringing activity back to the front , I found out that the my service is trying to communicate to the old instance of the activity, because the intent received on reBind still points to the old Messenger. With this insight this I changed the activity to send a REGISTER/UNREGISTER message to the service carrying the Messenger reference right after bind/before unbind - which solved the whole issue of TextView not updating.

I will appreciate if someone could explain why the intent bundle received on reBind is pointing to the old Messenger, while both the intent sent from the Activity and Messenger received at the Service IncomingHandler are correctly pointing to the newly created Messenger..

Here is the log extract indicating this problem: Activity Messenger reference in the rebind intent is never changing (always pointing to the first bind)!

(Activity started along with the Service)
D/MyApp: MainActivity->onCreate(): called
D/MyApp: MainActivity->onResume(): sending bind request with Messenger ref in Intent bundle=1103603880
D/MyApp: MyService->onCreate() entered
D/MyApp: MyService->init() entered
D/MyApp: MyService->onStartCommand() entered
D/MyApp: MyService->onBind(): client bind request. messenger ref in intent bundle=1103603880
D/MyApp: MainActivity->onServiceConnected(): service bound. service iBinder ref=1103479656
D/MyApp: MainActivity->onServiceConnected(): sending MSG_REGISTER with messenger ref=1103603880
D/MyApp: MainActivity->onServiceConnected(): sending MSG_STATUS_BRIEF with messenger ref=1103603880
D/MyApp: MyService->handleMessage()->MSG_REGISTER: client registered. Client messenger ref=1103603880
D/MyApp: MyService->handleMessage()->MSG_STATUS_BRIEF: client asking for info. Client messenger ref=1103603880
D/MyApp: MyService->notifyClients(): 1 clients notified 0 clients were dead

(Pressed back key)
D/MyApp: MainActivity->onPause(): called.
D/MyApp: MainActivity->doUnbindService(): sending MSG_UNREGISTER with messenger ref=1103603880
D/MyApp: MainActivity->doUnbindService(): sending unbind request
D/MyApp: MyService->handleMessage()->MSG_UNREGISTER: client unregistered. Client messenger ref=1103603880
D/MyApp: MyService->onUnbind(): client left. Messenger ref in Intent bundle=1103603880
D/MyApp: MainActivity->onDestroy(): called.

(Activity started again)
D/MyApp: MainActivity->onCreate(): called
D/MyApp: MainActivity->onResume(): sending bind request with Messenger ref in Intent bundle=1104277160
D/MyApp: MainActivity->onServiceConnected(): service bound. service iBinder ref=1103479656
D/MyApp: MainActivity->onServiceConnected(): sending MSG_REGISTER with messenger ref=1104277160
D/MyApp: MainActivity->onServiceConnected(): sending MSG_STATUS_BRIEF with messenger ref=1104277160
D/MyApp: MyService->onRebind(): client bind request. messenger ref in intent bundle=1103603880
D/MyApp: MyService->handleMessage()->MSG_REGISTER: client registered. Client messenger ref=1104277160
D/MyApp: MyService->handleMessage()->MSG_STATUS_BRIEF: client asking for info. Client messenger ref=1104277160

(Pressed back key)
D/MyApp: MainActivity->onPause(): called.
D/MyApp: MainActivity->doUnbindService(): sending MSG_UNREGISTER with messenger ref=1104277160
D/MyApp: MainActivity->doUnbindService(): sending unbind request
D/MyApp: MyService->handleMessage()->MSG_UNREGISTER: client unregistered. Client messenger ref=1104277160
D/MyApp: MyService->onUnbind() entered
D/MyApp: MyService->onUnbind(): client left. Messenger ref in Intent bundle=1103603880
D/MyApp: MainActivity->onDestroy(): called.


(Activity started again)
D/MyApp: MainActivity->onCreate(): called
D/MyApp: MainActivity->onResume(): sending bind request with Messenger ref in Intent bundle=1103504064
D/MyApp: MainActivity->onServiceConnected(): service bound. service iBinder ref=1103479656
D/MyApp: MainActivity->onServiceConnected(): sending MSG_REGISTER with messenger ref=1103504064
D/MyApp: MyService->onRebind() entered
D/MyApp: MyService->onRebind(): client bind request. messenger ref in intent bundle=1103603880
D/MyApp: MyService->handleMessage()->MSG_REGISTER: client registered. Client messenger ref=1103504064
D/MyApp: MyService->handleMessage()->MSG_STATUS_BRIEF: client asking for info. Client messenger ref=1103504064
Community
  • 1
  • 1
oscar
  • 123
  • 1
  • 6
  • i assume your service and client (activity) are hosted by the same process, so why are you using `Messenger` at all? why not "local bound service" pattern? – pskink Nov 18 '16 at 17:13
  • Your assumption is right for the moment. However project will evolve to allow multiple activity binding later on. – oscar Nov 18 '16 at 18:11
  • still you can use that pattern even if you have multiple clients – pskink Nov 18 '16 at 18:21
  • Thank you for your suggestion which I would gladly consider however that would not work should I decide to run the service in a separate process. Yet, I am wondering if you have any insights regarding the question I posted above. – oscar Nov 18 '16 at 18:54

0 Answers0