Can I use getApplicationContext() object for synchronizing? - android

When I have a small single block of code that should not get executed in parallel in my application (eg. when an Activity gets killed and restarted when the user turns the device), would it be possible to put it into a code block synchronized to the Application Context?
As far as I understood, this should work as long as the application context object stays the same over the full lifecycle of the app – but does it? I haven't found anything about its lifecycle.
synchronized (getApplicationContext()) {
if (piCacheFileDoesNotExist() == true) {
calculatePIandStoreToCacheFile(); // This is an example only...
}
}
Would that example be a possible way (especially when the task is too small to create an extra Service for it) or would it be a bad idea because of anything I've missed?

I believe you're trying to solve the wrong problem with the wrong tools.
syncrhonization: This is often use to make some code "thread-safe-ish" by ensuring an "object" (any) can act as a gatekeeper. If you can guarantee that there's only one instance of some object, then multiple threads could ask said unique object "are you free so I can run this code?" if the answer is yes, then the code is executed on that thread, otherwise, the thread must wait until the object frees it. Think of a semaphore.
synchronized(XXX) { ... } is doing that. It ensures ... is not executed until XXX says so. (note: this is an oversimplification).
It's often used like so:
private val lock = Object()
fun doSomething() {
synchronized(lock) { ... }
}
This means the code ... will only be executed by one thread at a time...
Now this has nothing to do with Android Lifecycle, App Lifecycle, and more specifically, Android Activity Lifecycle.
Your problem is an architecture problem. You have a UI (Activity) that can and will be destroyed by the Android OS at will (or when your users leave your app either explicitly or by performing a different action like turning the screen off).
You also have a block of code that -and I quote- "should not get executed in parallel in my application". Now this is a bit misleading. Do you not want this code to be run multiple times at the same time (in parallel, that is) or do you only want to run this code "once" in your app and never do it again until certain condition is fulfilled?
Depending on which case you need, the solutions may be different, but in all cases, the actual code that needs execution should not be part of an activity, because as we know, Activities are meant to be created and destroyed at all times. This then raises the question of: Where do I put this information that I want to persist for LONGER than what my activity does?
And here you have many options... from using a ViewModel (that can live a bit longer) to using a use-case/interactor/repository/etc. that can store this "information" in a more persistent way, and be able to provide it to the (new) activity when it is restored.
I suggest you spend some time reading about MVVM, Android Jetpack, Android Lifecyle, and, because your block of code appears to be "long work" you execute in a background thread, invest time in learning the basics of Kotlin Coroutines, LiveData and/or Flow/StateFlow, as they will make your modern Android life easier.
when I turn the device and back, each time the current Activity gets ended and a new one starts
This means the data that would let the code/activity decide what to do, should not live in the activity, otherwise it would get lost when the inevitable Activity Destroy/Recreate happens. Think of this: You wouldn't store your car keys inside the car... would you? ;)
This is why ViewModels, Respositories, etc. can help you overcome this. In truth, you may or may not like the extra complexity, code, boiler-plate stuff, etc, that comes with this, but when you're developing an Android app, you have to abide by its idiosyncrasies (and bad decisions sometimes). Try telling an iOS dev that you don't want to use ViewControllers and that you're gonna build your own... they are going to scream at you: "Don't fight the framework!!!!!!!"...
Well, this is similar. Do your best to learn the Android way.

Related

Starting singleTask activity every few seconds gives ANR in Android

In the app I have an activity which has launch mode as singleTask. There are number of use cases which pass through this activity and hence it's called number of times. On stress testing the app by running monkeyrunner script and calling this activity every few seconds causes ANR's.
I guess, the way it's designed where most of the use cases pass through this activity is not correct but I am not in a position to change this design.
Is there anyway ANR's can be suppressed? I mean, adding UI operations to event queue so that it doesn't block main UI thread and doesn't give ANR.
It is unclear from the question what your activity is (or should be) doing. Probably you need a service instead.
It is common to perform time-consuming operations in background threads and deliver the results to the UI thread.
You may use the classes Handler/Looper (it it easir to send Runnables rather than messages), or use an AsyncTask. The AsyncTask is nevertheless tricky, this is discussed here: Is AsyncTask really conceptually flawed or am I just missing something? . AFAIK Google tried to fix the typical bugs and made the new behavior incompatible with the old one (namely, I have seen some misbehavior on the newer Androids that may be explained by the assumption that since some version threads doing asynctask jobs get killed after the activity that started them goes out of the screen).
I can guess that singleTask is your way to fight the fact that an activity dies when the screen turns, and a new one comes. I suggest you use singletons (they survive screen rotation but do not survive a process restart, one more thing that sometimes happens in Android). (The user switches to an app like Camera, takes a big photo, returns back -- and the activity is restarted because Camera needed memory. Have seen this in practice, but that time I did not try to find out if the whole process was restarted.)
Anyway, please add logging telling you when your activity in entered and left, including onNewIntent() and other lifecycle functions (to be on the safe side, I recommend to print the thread names as well). Then you will probably see what is going on.

Is System.exit(0) really that dangerous?

An application background service updates sqlite database. Therefore my activities are becoming outdated. Activity intents also contain outdated params so onCreate, onResume will crash the application. An easiest solution is to restart whole application. I don't want to add IFs to all onCreate, onResume methods in all activities to handle one special case.
I noticed that ACRA has following code executed after an exception has been handled.
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(10);
However many people discourage use of System.exit(0). Is System.exit(0) really that dangerous for an Android application data integrity? Of course my code will close the database before existing.
Update:
I known how to use finish(), content providers, send broadcasts, read many answers here on SO, etc. However each of these approaches requires additional thousands lines of code. I implemented solution with System.exit(0) in ten minutes. The restart is so fast that it is indistinguishable from ordinary startActivity action. The db update/restart is done after longer user inactivity so the app is already suspended by the system. My app doesn't require real time syncing. During tests the application behaves correctly. This is quick and dirty solution.
Therefore I asked the question about possible side effects of System.exit(0). Not how I can do the design differently. I know that current design is not perfect.
System.exit(0) is an artifact from Java runtime, it isn't meant for Android. So in any cases using it would be worst solution.
Why don't you use Activity.finish() gracefully?
If you terminate the process you are living in, you'll loose most of the caching and restart time (~resume in the eyes of the user) for it next time will be higher.
Read more in Activity Lifecycle documentation on Android Developers.
Killing the process will not clean up any registered resources from outside the process. BroadcastReceivers, for example. This is a leak and the device will tell you as much.
You really shouldn't be updating the database schema from a background service. Do it when your activities resume.
If you are just updating your data, resuming an activity should validate the data specified by the Intent and tell the user if, for example, Item X is no longer there.
No tool is that dangerous if used carefully and for a specific, well thought off purpose.
However, In your case I do not believe System.exit() is the right way to go. If your application depends on data from a database, create a background service (or a few, depending on what you need) that will inform your application of changes and update the data. It is, in my opinion the right way to handle changes.
As for scenarios when you want to use System.exit() I personally sometimes use it when I can't recover from a critical error and no graceful degradation is possible. In those cases it is better to force all resources associated with your application to cease rather than just leave loose ends tangling around. To clarify, you should always use error handling before doing anything radical. Proper error handling is often the way to go.
But this is a very delicate topic and you are likely to receive quite a few diverging answers.
Therefore my activities are becoming outdated.
Use a ContentProvider and ContentObserver (or the Loader framework), or use a message bus (LocalBroadcastManager, Otto, etc.) to update the activities in situ.
Activity intents also contain outdated params so onCreate, onResume will crash the application
Copy the relevant "params" to data members of the activities. Update those data members as needed (e.g., from the handlers from the message bus-raised events). Hold onto that data as part of your instance state for configuration change (e.g., onSaveInstanceState()). Use this data from onCreate(), onResume(), etc.
An easiest solution is to restart whole application
It is not easiest, if you value your users, as your users will not appreciate your app spontaneously evaporating while they are using it. Do you think that Gmail crashes their own app every time an email comes in?
Next, you will propose writing a Web app that uses some exploit to crash the browser, because you cannot figure out how to update a Web page.
I noticed that ACRA has following code executed after an exception has been handled.
A top-level exception handler is about the only sensible place to have this sort of code, and even there, the objective is for this code to never run (i.e., do not have an unhandled exception).
There's an existing answer HERE that might give you some help as to why people say it's bad to use System.Exit().

How to make Android app recover from pause and resume gracefully

I am very familiar with the Android activity lifecycle, but I feel like I am missing something that should be pretty obvious here.
I have a multi-activity Android app; it uses static variables (in the application class) to keep a handle on the various objects that are used across the different views. The problem occurs when the app is paused (exited) and Android (presumably) cleans up memory to maintain foreground processes. When the user resumes the app, it occasionally (not always) seems to come back and resume in the Activity that the user left, but with the static variables nulled. Even worse, the activity sometimes seems to resume with the static variables still present, but with internal variables in objects nulled.
I eventually implemented a simple sanity check, which checks that the statics are not nulled (and also the most vital inner variables of relevant objects) and returns the app to start if it fails. This did cut down on a lot on the problems, but I still see the occasional issues with this, as it is simply not practical to check everything for every resume().
What I really need is for the app to restart from scratch if the Android OS decides it needs to clean anything non-GC from memory while the app is inactive. I feel there should be a graceful way to do this, but haven't noticed anything in the documentation.
Any thoughts? How do others avoid this problem?
Using the Application class for preserving state can result in unexpected behaviour if Android decides to kill your process completely. Check out this answer to a similar question
i.e. you should probably use some sort of persistence (SharedPreferences or some DB) in your Activity lifecycle callbacks.

Android App Exit Button

I'm not sure whether I need to add an exit button to my app. Is there any point to doing this? And if on exiting one activity or service is not .finish() or closed properly could this cause a lot of damage?
You don't need to add en exit button. If you don't, your activity will just be kept in memory until the system reclaims it. It will not consume any cpu.
Of course, if you have any worker threads running you should stop them in onStop() or onPause(), depending on what your threads are doing.
Many applications add an exit button, for some reason. I guess the reason is that they don't trust themselves to write proper code or they don't trust the Android OS to clean up properly.
Not going through the correct finish procedures will not cause any damage to others than yourself.
Anyone who says you don't need an exit button is right but putting one in never hurts. Users like to see a way to exit to the application, it's not about bad programming, it's actually about proper programming, give the user an exit button and if they never use it great and if it's there even better.
You don't need an exit button in your app. This is how android works. The user is not given any way to actually exit the application.
When you call 'finish', the application stack is just pushed to the background. It still exists in the memory. Android itself decides when to close the application(i.e. remove its instance from the memory) and generally this is done when your application becomes the oldest application which was not used for the longest time.
No, you don't. Read up on the activity lifecycle at developer.android.com
On older versions of android you had to be careful not to accidentally leave a background service running and holding resources but that's been reworked.
Guys you're righteous, but there are some cases when Exit button may have a sense. Let's say you're keeping some application-wide global data in YourApplication class (child of Application), e.g. some sensitive data or so. When user closes final activity and it's destroyed Application won't be terminated. As read Android developer resource - developer should not rely on Application.onTerminate() method. You can easily check it - even in case when all activities closed Application still alive. Whenever Application instance alive it's relatively easy to get access to those object and collect data.
I have found 2 ways how to kill Application class instance:
null'ate all object references (which is hardly possible for large projects) then call garbage collection
call
android.os.Process.killProcess(android.os.Process.myPid());
So Exit button may have function to finish all activities, call garbage collection then call killProcess() - which will guarantee safe removing of global data stored in Application.
I agree with above post by barmaley.
Long story short, you don't need to exit your application if your concerns are related to the Android system itself. Don't worry, be happy. And that applies especially for lazy users (remember the old Symbian days).
However, if you have something in mind about your application itself, then please go ahead and do it. You can finish the activity, nullify and kill. Just be reasonable because, as always, common sense is going to be better than all the tutorials and references in the world.
Anyway, just my 2c.
From a technical perspective, no, you don't need to add a quit button for all the very good reasons listed here.
Unfortunately users aren't informed in this way and regularly drop review scores because they have to 'use a task killer' or 'force close' your app.
It is a regular request and criticism in reviews/feedback for my app. So it may be necessary to appease users.
I think an exit button can provide the user with assurance that your app is closed.
I know, that it still doesn't mean that the app is definitely closed, but if the user feels more in control with an exit button then I say it is a good idea.
When I first started coding for Android, I thought it was a good idea to manually exit my main activity. What I discovered is that closing the activity via stopSelf leads to corrupt instanceState data, which caused a lot of ANRs when the activity was opened again.
The Activity Lifecycle document is information directly from the Google framework engineers. Every word is for a reason.
Consider that garbage collection takes cpu. This may seem trivial, but in designing a framework for a mobile platform, wouldn't you try to cache as much in memory as possible in case it was needed again, as cpu time = battery, and loading from flash is expensive?
GCing an entire app is non-trivial. Especially when the activity might be used repeatedly. The design had to consider all possible use cases. Cacheing makes sense. The system is designed with this principle.
I would say that not following the Activity Lifecycle document is asking for problems.
Some apps alter the configuration of the device while running or consume lots of CPU or data. You may want to give users an option to Exit the app altogether.
There are proper usecases for an Exit button.
For example, an app i made also needs to manage WiFi networks: the device configuration is changed continuously. Terrific and all while app is in active use, in this case a user would expect the behavior to effectively stop after exiting the application.
So my application has an Exit button mainly to cleanup the WiFi configs it created. I could make a button Stop and Cleanup, but no user would understand. They just want to turn the app off, thus Exit.
App running: wifi managed by app.
App exited: diy/android wifi.
Right now, choosing Exit in my application does the cleanup followed by a finish(), but the application itself lingers in the background. Functionally ok but confusing users. I could make a toggle action named "wifi feature on/off" but that wont make things simpler.

android design considerations: AsyncTask vs Service (IntentService?)

I'm designing an android app which will need to do the following steps:
user pushes a button or otherwise indicates to "sync data".
sync process will use REST web services to move data to and from the server.
the data will be stored locally in a sqlite database.
the sync process should provide status updates/messages to the UI
the user should not be allowed to wander off to other parts of the application and do more work during the sync process.
The first time the sync process runs, it may take 10-20 minutes.
After the initial sync, less data will be transferred and stored and
I expect the process to take 1-2 minutes or less.
I've been doing a lot of reading about android's AsyncTask and various examples of using a Service ... But I don't fully understand the design considerations and trade-offs of choosing one design over the other. I currently have my demo project stubbed out using an AsyncTask. After watching (most of) Developing Android REST client applications: http://code.google.com/events/io/2010/sessions/developing-RESTful-android-apps.html# I'm left confused the design patterns described here feel overly
complex, perhaps because I just "don't get it" yet.
I come from a java, spring, web and desktop application background. Thinking and designing in terms of a handheld device is quite new to me. (What happens when the screen layout is changed? What happens when the phone rings while I'm running a sync?) Taking 2 steps back, if the initial sync IS going to be such a long running process, is there a better way for me to think about the problem->solution, the user experience, the user expectations of an application running on a phone?
Would love to hear from some more experienced android developers out there who have already wrestled with these questions.
In my opinion this is the most tricky/hard part of a mainstream/average Android development. For instance on BlackBerry this is IN TIMES easier.
Definitely you need to use a Service.
AsyncTask does not suit, because it is tightly "bound" to your Activity via a Context handle (otherwise you would not be able to update UI of the Activity from your AsyncTask). However an Activity can be killed by OS once the Activity went in background. An example reason of going to background can be an incoming call - user switches to Phone application so your Activity becomes invisible. In this case (depending on the current RAM state) OS may decide to kill one of the background (invisible to the user) activities.
Some devs workaround this by arranging a static stuff for having a long-running actions inside of. Some recommend to use Application instance. This is because static stuff and Application exist while the whole app process exists. However those are incorrect workarounds. Processes in Android are also may be killed when OS decides it is time to. Android OS have its own considerations about what it can kill and in what order. All processes are devided to 5 levels of "killability". Here is the doc where those levels are specified. It is interesting to read there:
Because a process running a service is
ranked higher than one with background
activities, an activity that initiates
a long-running operation might do well
to start a service for that operation,
rather than simply spawn a thread —
particularly if the operation will
likely outlast the activity. Examples
of this are playing music in the
background and uploading a picture
taken by the camera to a web site.
Using a service guarantees that the
operation will have at least "service
process" priority, regardless of what
happens to the activity.
Your Activity where users initiate a long-running action should show a ProgressDialog to make sure user does not do anything else while the action is running. The guide is here.
Also, you'd most likely want to use the NotificationManager for notifying the user about your long-running action completion (or failure) if your Activity is currently invisible. Here is the NotificationManager info to start from.
There are multiple considerations that you must weigh in order to best decide how to approach your situation. It sounds like you need a good comparison between the two approaches... So here is a list of similarities, and differences and additional considerations that must be taken into account when working on a handheld device.
A Service is a part of your Application that has no UI. It may be called by a UI(Activity) to be started, or may be started by any other component of your Application. When developing, you have the freedom to place it on a different thread, or even run it in a different Task or Process. This allows you to ultimately separate it from your UI. Additionally, you may start the Service to run independently (startService) or bind your activity to it (bindService) depending upon your needs. By using custom Handlers, you can set callbacks to update the UI with your progress. A Service does not necessarily end if a User changes Activities, but may be ended at ANY time by the OS.
A AsyncTask is always instantiated from the UI thread. It only allows specific callbacks, but simplifies the process of multi-threading for the purposes of relatively short transactions (as compared to dedicated separate threaded services) that are inherently tied to actions performed by an Activity. Whenever a User changes Activities, the AsyncTask is put on "pause" and may even die because there is no UI thread for your Activity any longer.
The thing that I would be most concerned about is if the app is going to take 10-20 minutes the first time, I would ASSUME that the User will either change tasks temporarily or set the phone down until it completes (which can cause all of the same complications if the phone sleeps). Given this consideration, a threaded service bound to your activity may be your best choice. To protect your UI, I would make a Progress Dialog for your Activity that receives your progress callbacks. This limits user input in YOUR app and allows your service to continue the way that it needs to. Then override the Activity onResume to check the status of your Service and if it is running. Then you can reset the Dialog immediately.
Given that this is my preferred method, I would also take into account that the OS may kill the App at any time anyway. So make sure to have some way to detect an incomplete or partial sync. Then you may resume automatically when your Activity or Service restarts.
With AsyncTask if the user goes to another Activity you can't transfer that object to the other Activity so it dies. There are tricks you can play when say the user rotates the screen or something like that, but that doesn't extend to general purpose destruction. AsyncTask can randomly die.
Google Sync is run as a Service in the background because syncing can take a while to complete. You might need to follow their path and create your own sync service that you can communicate with. Here is some thoughts how to accomplish that:
http://mylifewithandroid.blogspot.com/2008/01/about-binders.html
You can definitely communicate between Service and Activity, but it's tricky to do it right.
The choice is mainly dependent on the app design. Since both AsyncTask and IntentService stands their ground, what you may want from the app(user experience) is more important and then choose either or both. Some scenarios are mentioned below (mostly what I experienced while developing apps)
Assume apps that have feeds pages - where more than one api calls are made to make the page presentable ( /getFriends, /getDates, /getPictures etc.) you can warp all such api calls to a single AsyncTask with executor which is multithreaded and the sequence of execution doesn't matter. In contrast to IntentService which runs all calls in sequence in a single worker thread. For a high end device with multi-core the call from AsyncTask is more effective. And if you start the AsyncTask on UI thread then updating IU is a piece of cakes(read less boiler plate code). And even if an user leaves the page, with intelligent use of not holding on to the context the app doesn't crash.
Assuming you are trying to write an app which doesn't need the user to be on view/activity/fragment and the total execution time to show something is not mission critical (assume sync service or user notification/alarm) then IntentService is a better choice. (no hassle to start Asynctask on UI thread so that you don't need to write a Handler to force changes on UI etc. etc. and less boiler plate code)
From my experience - write small app for both and compare the pros and cons to get a better idea. (p.s I'd suggest take a look at the iosched app from google to get a better idea - they use both Asynctask and IntentService)
I tend to prefer the IntentService + BroadcastReceiver combo because they give you a really strong degree of control
You definitely have to make sure the UI is running if you are updating something on the screen. ASyncTask crashes were at once reported to be one of the top causes of Android crashes. This can be avoided by keeping some sort of "activityIsAlive" variable and skipping or delaying a UI update if the activity is dead.
The IntentService + BroadcastReceiver combo is a little more resistant to the crash because most tutorials tell you to shut off the BroadcastReceiver onPause or onStop. If you do not do this, again you'll have to turn off the UI update. There's a runOnUiThread command somewhere that will help you do UI updates.
The IntentService + BroadcastReceiver combo is also more extensible. You can create functions and extend BroadcastReceiver to make a more elegant REST processing solution. However, it does require more plumbing vs an ASyncTask
If you do delay the UI update, you may be able to rig it on OnWindowFocusChangedListener. When that function receives true, it means that the UI is alive.
tldr; Make sure the Activity and/or Fragment is alive before updating the UI if you are running something in the background
2015 Edit: check out Loaders as well. A little harder to grasp because there's a lot going on behind the scenes

Categories

Resources