I have a singleton which stores some prudent information about the user of my application. At the moment, it stores the user's login and the user's location.
1)
The location is found via a Service. At the moment, the Service references my singleton directly to stuff the longitude and latitude into it. I would like to use a BroadcastReceiver to send a broadcast that the singleton hears and uses to update the values, instead.
However, to register the BroadcastReceiver, I need a Context in my singleton. What is the slickest way to achieve what I'm wanting. Is BroadcastReceiver possibly not the appropriate object?
2)
Also, what problems am I looking at with using a singleton? I assume that Android will possibly reclaim this memory at any given time (which would obviously be bad); so how can I prevent that? Would passing in the application's Context and storing it in a member variable thwart this?
The Android documentation states: "But, the life cycle of a static is not well under your control; so to abide by the life-cycle model, the application class should initiate and tear down these static objects in the onCreate() and onTerminate() methods of the Application Class," but I'm not entirely sure how to accomplish this.
However, to register the BroadcastReceiver, I need a Context in my singleton. What is the
slickest way to achieve what I'm wanting. Is BroadcastReceiver possibly not the appropriate > object?
The "slickest way" is to not do what you are doing. Please only register a BroadcastReceiver from an Activity, Service, or maybe an Application. You must unregister this BroadcastReceiver when the Activity, Service, or Application is destroyed.
I assume that Android will possibly reclaim this memory at any given time (which would
obviously be bad); so how can I prevent that?
You don't. Android reserves the right to terminate your process at any time (e.g., to reclaim memory). Task killers on Android 2.1 and previous will terminate your process at any time. Once all components of your application are destroyed, Android may recycle your process at any time, clearing out your heap at the same time. And so on.
Only put things in memory that you don't mind losing.
It is best to think of your "application" as a basket of loosely-coupled components, not as a monolithic entity.
Would passing in the application's Context and storing it in a member variable thwart
this?
No.
The Android documentation states: "But, the life cycle of a static is not well under your
control; so to abide by the life-cycle model, the application class should initiate and
tear down these static objects in the onCreate() and onTerminate() methods of the
Application Class," but I'm not entirely sure how to accomplish this.
Create a subclass of Application and indicate in the manifest that Android should use it, via the android:name attribute on the <application> element.
Related
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?
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.
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.
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.
I have a series of activities, one of which is called UserActivity. What I'd like to do is have an object ListenerObject, that listens specifically for when UserActivity starts or stops. That is, I want UserActivity.onStart() to call ListenerObject.onActivityStart() (or some method named similarly).
I know that I can create an observer pattern set of classes to do this, but I'm wondering if there already exists such a framework within the Android API, and, more importantly, an accepted set of use patterns.
You could do this through Broadcasts:
http://developer.android.com/reference/android/content/BroadcastReceiver.html
http://developer.android.com/guide/components/intents-filters.html
In a few ways...
1) Have both activities receive and start from the same intent.
2) have activity 1 launch a broadcast to activity 2.
If ListenerObject makes sense as a static singleton you can just call the method on it during onStart() and onStop():
MySingleton.getSharedInstance().onActivityStart();
which would save you some overhead of the other valid methods mentioned.
The Android devs mention static singletons in the context of lazy creation for speed and reduced memory usage quite a bit it seems so it seems like an accepted pattern.
Depends on the required life cycle of the ListenerObject.
Seems like you want it to be around when the UserActivity isn't, but what about when you have none of your Activities on screen?
You could start a Service and then bind / unbind to it in your UserActivity's onStart / onStop. The service would likely stay alive whilst your app was in the background.
You could (un)bind to a service in all your Activities' onStart/Stop and provide an IBinder interface which asks would allow the service to ask the Activity if it is the UserAnctivity. The service would live whilst you navigate the app, but die once you put it in the background or go to another activity that doesn't bind to it (probably not what you want if you're doing something with G+ authentication / in app purchases etc).
You could (like others suggest) create a singleton, which won't die until the Application does, but won't keep it alive either.
You could have an Event Bus where the Listener subscribes to a known event published by the UserActivity.
shrug just some ideas
I am developing an Android data entry app that saves the entered data to a file. A Service (let's call it FileIOService) is launched using the filename, and loads and saves data that is passed to it from each Activity that the user accesses.
I am trying to make the whole app as robust as possible, and at the moment I feel I need to pay particular attention to the interaction between each Activity and the Service. Here are the issues I can see:
If the Service is killed by the system, it needs to restart and open the file that it had open: I can handle this by using START_REDELIVER_INTENT.
If an Activity is destroyed, for instance by an orientation change, it needs to reconnect to the Service.
The thing is, once the Activity launches the Service, there's a while before the Service finishes opening the file and becomes ready for I/O requests. To address this, in my Activity, I have both:
an inner class subclassing ServiceConnection, with its onServiceConnected() method completed
a private reference to an anonymous inner subclass of BroadcastReceiver, with its handleMessage() method completed. This gets called when the Service sends out a broadcast to indicate it's finished opening its file.
Both of these methods then call a setUpActivity() method that pulls data from the Service. This is where it starts to get ugly. Because onServiceConnected() may run before the file is ready for I/O, and handleMessage() might be called while the Service is not bound to the Activity, I have to make both handleMessage() and onServiceConnected() set boolean flags that can later be checked in setUpActivity(), like this:
if ((fileLoaded && serviceConnected))
{
//access the file data
}
As I said, this feels ugly and awkward, and relies on setting extra boolean variables.
There's another problem - if my Activity launches an external Activity, like the Camera app, upon returning to my app the Service and Activity may both have been destroyed (especially with an orientation change) and the app crashes.
My feeling is that I may be missing some overall pattern that would define how each Activity should relate to the Service, and vice versa, while remaining robust and able to cope with unexpected terminations/restarts.
Let's ignore the fact that I am skeptical that this is a valid use case for a service (a service whose existence is simply to read and write files?).
If the Service is killed by the system, it needs to restart and open the file that it had open: I can handle this by using START_REDELIVER_INTENT.
The service is not "killed by the system". The process is killed by the system. This will eradicate your activities as well as your service.
The one possible exception to this is if the user manually stops the service (and only the service) from Settings, in which case I have no clue what the expected behavior would be. This should be fairly uncommon nowadays, particularly for an app that the user had just been using. Users will be more inclined to use a task manager, such as swiping your app off the recent-tasks list, which will get rid of the entire process, not just the service.
If an Activity is destroyed, for instance by an orientation change, it needs to reconnect to the Service.
Not necessarily:
Bind using the Application context (getApplicationContext()) instead of from the Activity directly
Use a retained fragment to maintain the binding across the configuration change
My feeling is that I may be missing some overall pattern that would define how each Activity should relate to the Service, and vice versa, while remaining robust and able to cope with unexpected terminations/restarts.
This is one of the many reasons why I try to avoid the binding pattern altogether. Use a service for processing commands, sent via startService(), with results (if any) delivered by LocalBroadcastManager, or Otto, or greenrobot's EventBus, or a "real" broadcast Intent, or maybe a Messenger. Particularly when the service is an IntentService, the service nicely cleans up after itself when there is no more work to be done.
I have a foreground service that is processing gps location from the location manager. I am storing these in a generic "location controller" singleton. Currently my activity is also accessing this class. Is this acceptable? It seems more efficient then using handler messages.
There is nothing really wrong with it, so long as you are very sure that you are not going to introduce any memory leaks. Other existing message bus solutions, like LocalBroadcastManager (from the Android Support Library), Otto, and kin use a singleton behind the scenes.
I would recommend that you use LocalBroadcastManager or Otto or something than rolling your own, just because they are better supported and tested.
T
For this particular case, since you expect frequent updates of the location that should be communicated to the activity; I would say bind to the location service might be a more appropriate solution.
So basically, in your activity onResume you bind to the service and pass a listener object to the service that will be called whenever a location update exists. Also, you should unbind with the service in onPause.
Just be aware to start the service before binding so it keeps running if the activity is no longer in the foreground.
I have very similar case and this solution works very well and it gives you the ability to add a method in the service like getLastLocation() which can be invoked from the activity on demand.
I have an Android application, which makes use of an AlarmManager to schedule events. When an Intent from AlarmManager is received, domain logic has to do some work, which includes accessing a DB and broadcasting intents. Currently I use a Singleton to access the domain logic from a BroadcastReceiver (registered in the manifest) in a way:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Singleton.getInstance().onAlarmFired();
}
}
This Singleton is used in activities and services in the same way.
It works fine, but Singleton is considered to be an anti-pattern, and I would like to cover code with tests, so I am looking for a different solution.
Now the question is wouldn't it be better to use a Service instead of this Singleton? Like this:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
startService(new Intent(intent.getAction());
}
}
What are the benefits and drawbacks? And what will be the best way to communicate with the service from an Activity? I am thinking about binding to the service in MyApplication and provide reference to activities and services using getApplication() method.
Now the question is wouldn't it be better to use a Service instead of this Singleton?
Yes, very much so. The prime directive when it comes to BroadcastReceiver.onReceive() is respond spend as little time inside the metod as possible because that execution is being done on the main thread and if the BroadcastReceiver is alive for more than 10 seconds it quickly becomes a candidate for death (see the docs for more).
Calling a Service to do the work instead is a perfect replacement implementation and returns from onReceive() very quickly.
Depending on what your Service is doing you can bind it to an Activity to call methods on it, or simply continue to use Intents to send data back and forth (you might want to take a look at LocalBroadcastManager in the support library for the latter case).
I am thinking about binding to the service in MyApplication and provide reference to activities and services using getApplication() method
I would strongly urge against this. I would consider using the Application class at all in many cases also an anti-pattern. It's lifecycle is not easier to keep tabs on than a created Singleton. Instead, if you want to bind the Service in order to use it, bind it to any Activity that wants access while it is currently in the foreground.
EDIT: To your question about System Services
System Services and Application Services are very different; System Services aren't even services at all (in the SDK definition of the word). They are Singleton objects that run inside the system_server process, where they are protected from disruption, and talk to the manager objects you have access to using AIDL and IPC.
A Singleton in your application does not have the same luxury. If your application crashes, Android cannot assist in restarting your obhect. But more importantly, since it is not a registered system component, Android will not recognize your application as doing valid background work if you are executing code in the background here and you will be a more likely target for low memory killing if your application is not in the foreground.
So, while technically using a Singleton will work, moving your code into a traditional Service is considered best practice and will give you the most benefit from the platform itself.