2

I have an Android foreground service that contains a map of session (key, session). In my activities, I receive a key and I want to get the session from the service. So I bind each of my activities to the service and I can ask the service to get my session with my key. But doing this means that I have to wait for onServiceConnected() to get the session.

Is it a good idea to bind the service once in my application class and put my service in a static variable, then all my activities can access the service directly in their onCreate() instead of waiting for the call of onServiceConnected()? But is it sure that my static variable will always be there? Do you know if Android can delete that static variable if it needs resources? I guess the application instance is never deleted, am I right? So it could be a good idea to keep my service in a static variable. What do you think?

Hussein El Feky
  • 6,627
  • 5
  • 44
  • 57

3 Answers3

1

What you are trying to do sounds like a dirty implementation of some sort of dispatcher from React, I have being tempt to do it my self, but haven't because of lack of time. Please let us know your results.

I would suggest to use a Messager, the doc have information about it, so no need for static https://developer.android.com/guide/components/bound-services.html?hl=en-419

And yes, Android OS can clean anything, it can kill the service, it can null the variables. Most of the time this doesn't happen because it will be done only to prioritize the foreground app. So if a user opens 10 apps and your is on backgound it probably will. Which seems ok to me. From time to tome I have also experienced variables become null in a Fragment, but then I reduced the variable scope and that fix it.

Also if you are considering this, try with EventBus library or by using ReactJava, maybe Realm ORM or even Firebase could help you.

cutiko
  • 9,887
  • 3
  • 45
  • 59
  • My application allow you to open a session on a remote desktop and share the desktop. Those sessions, I can't accept Android to delete them. This is why my service is running in the foreground because I have to keep my sessions alive. So all my open session is kept in the service. But when I open an activity to show the screen of a specific session, I have to get the session. To do that, I bind my activity on the service then I ask the session. But I would like the session right away when I open the activity and not waiting the service to get my session. This is why I wanted to keep it static – François Dubois Aug 11 '17 at 15:49
  • I'm insisting that the communication must be done using a Mesenger https://developer.android.com/guide/components/bound-services.html?hl=en-419#Messenger Then you have to use persistence, for this I would recommend using the SharedPreference, simple key-value data you only need the context, which you have because the Service can use this as context https://developer.android.com/training/basics/data-storage/shared-preferences.html?hl=es-419 In the Service store the session in the SharedPrefference the Activity ask to the Messenger this get it from the SharedPrefference – cutiko Aug 11 '17 at 17:01
  • Android can kill the OS process hosting the app, but then all of the app components will be killed. Once the `Application` object is instantiated, it will never be removed (garbage collected). It acts as a singleton and the only way Android will get rid of it is to kill the OS process hosting the app. – David Wasser Aug 12 '17 at 10:49
1

You can bind to the Service in your Application class. The Application instance is basically a singleton and will live as long as the OS process hosting your app is alive. At some point, Android will kill the OS process hosting your app, and then all your app components will go away (Application instance, Service, Activity instances, etc.). If the user returns to your app, Android will create a new OS process, instantiate a new Application instance and then instantiate your app components as needed.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
0

Application itself doesn't have a lifecycle as other Android components, so if you call bindService() during its onCreate() callback, there is no guaranteed point to call unbindService(), which may lead to memory leaks and unpredictable states. Others have also pointed that here.

Instead, you could start your service in the foreground (displaying a notification like "Remote Desktop Manager is running"), which should keep your app alive, and make the map<key, session> a static variable in your Application. In this way, Activities can retrieve sessions without the connection delay. Just don't forget to stop the service by either calling stopService(Intent intent) or stopSelf() when all sessions get closed.

By the way, it should work even considering background restrictions of Android O.

Perazzo
  • 1,127
  • 13
  • 24
  • What do you mean, there is no lifecycle? What about onCreate and onTerminate – cutiko Aug 12 '17 at 11:39
  • onTerminate is practically never called, you can't rely on it. – Perazzo Aug 12 '17 at 15:09
  • You can't neither rely on onDestroy, but is still part of the lifecyle of the Activity. However I see your point and I lile the pragmatism of it. Then the question is, what about if we don't care about un binding the service? We can alternatvely use any onStop from any Activity to send a Message to the service and then perform what we need – cutiko Aug 12 '17 at 15:14
  • I agree with you, we can alternatively call onStop on the last closing activity, but I think we will need to do that anyway. About don't care if we unbind the service or not, I get it the way of thinking, especially if we were fixing a crash or something on last minute. But it seems he is designing the solution from scratch and design something already accepting its flaws as absolute truths it doesn't seem a good way to start something. – Perazzo Aug 12 '17 at 15:40
  • Yes! that is why I also suggested looking at other solutions like EventBus, ReactJava, Realm, or Firebase. – cutiko Aug 12 '17 at 16:01