I am currently developing an Application for Android. One of the requirements is extensive logging about how the application is used. More specifically there should be logging about when the user closes the app. This logging consists of a server interaction. With respect to that specific requirement I stumbled onto:
Detect Application Exit(1) and Detect application Exit (2)
Both questions have an accepted answer relying on Service#onTaskRemoved(Intent).
In my case however this solution does not seem to work, i.e. AsyncTasks that are started in this method are only occasionally executed. More specifically, the onPreExecute is executed always but the doInBackground is not. I tested this on a Nexus 5 with Android 6 (Marshmallow) installed.
public class SomeService extends Service {
#Override
public IBinder onBind( Intent aIntent ) {
return null;
}
#Override
public void onTaskRemoved(Intent aRootIntent ) {
new DoSomethingTask().executeOnExecutor( Asyntask.THREAD_POOL_EXECUTOR );
}
private static final class DoSomethingTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
Log.e( DoSomethingTask.class.getName(), "This is executed always");
}
#Override
protected Void doInBackground( Void... aParams ) {
Log.e( DoSomethingTask.class.getName(), "This appears to be executed only sometimes... ");
// here an actual call to a Rest API should be made to inform the server that the user has closed the application.
}
#Override
protected void onCancelled( Void result ) {
super.onCancelled( result );
Log.e( DoSomethingTask.class.getName(), "Never invoked" );
}
#Override
protected void onCancelled() {
super.onCancelled();
Log.e( DoSomethingTask.class.getName(), "Never invoked" );
}
}
}
Here is an overview of everything I tried in addition to the above code sample:
I have tried various onStartCommand options (START_STICKY, START_NOT_STICKY, etc.) without success.
I have also tried restarting the service in the onTaskRemoved method and then executing the AsyncTask in the onStartCommand.
Starting an IntentService in the onTaskRemoved method (which starts the AsyncTask in its onHandleIntent method) solves the problem neither.
using a BroadcastReceiver in combination with a local broadcast (LocalBroadcastManager#sendBroadcast) does also not work (I double checked that the broadcast receiver is effectively registered as receiver for the sent broadcast).
EDIT:
I have also taken a look at the callbacks in the Application class:
- onTerminate : this method is only invoked in emulated environments and hence useless
- onTrimMemory(int) : this method can be used for detecting when the app goes to the background, but it has no distinct case for when the app exits.
I could keep an activity stack (which would be updated in Activity#onPause(), etc.). But this requires quite a lot of work in every single Activity instead of the above Service approach which only involves interference at a single place.
First of all: in Android you cannot guarantee execution for your requirement. Period. The system is free to gc your classes or kill your process at any time. Also the Android concept does not really have the concept of "closing app" actions the same way websites don't have it. So before you continue reading I urge you to rethink your requirements.
That being said. Here are some tips:
My understanding of Service#onTaskRemoved(Intent) is that it is only executed if you kill the app through task switcher, so I don't know if this is useful to you. In your instance I would keep a activity ref counter in the application object (+1 for every onResume(), -1 for every onPause() of any activity). With this you can check if your user has active UIs. Usually if you pressed back on the last activity that comes as close to the paradigm "closing" an app. Then just start your task at that point from the application object (this will probably be the last to get gc) or if that doesn't work try an unbound service the most uncoupled component you can generate.
Another, very very bad solution is overriding the finalize() method in an object (e.g. your activity). There are only very, very few reasons to use it since it will trigger an additional gc cycle and your code will be run on the main thread, but it is a way to execute code if the object is about to be gc'ed. Therefore it is discouraged to use by the android team, only use it if you have a gun up your head.
Related
I have some fragments loaded in a ViewPager, where each "page" is loaded from a row in a cursor. Each fragment shows an image (JPEG) on the device. When the user dismisses the fragment (i.e swipe/page change, hits back/up, or just closes the app entirely) I want to invoke a method which opens the JPEG file for writing and does an update of its metadata. The actual work is eventually handled by the Apache Commons Imaging library.
I've implemented this by invoking my saveToFile() method from each fragment's life cycle onStop() handler. Does this mean the entire file operation ends up running on the UI thread? Should I definitely set up an AsyncTask for this?
Say the file write for some reason suddenly (for some jpeg) should take a long time, eg 2 minutes. What would then happen? Would the UI just wait (freeze) at this page/fragment before resuming? Or would the process (write to file) carry on "in the background" somehow? Or would the process just be killed, stopped short mid-process?
The way I have this wired up currently (onStop invoking saveToFile(), which calls up the imaging library and then updates the file) seems to work as it should. Even if I end the app, I still see my Toast text popping up, saying "Writing to file..." Seemingly, the process is never disturbed, and I can't say I'm experiencing any UI lag.
onStop() handler. Does this mean the entire file operation ends up
running on the UI thread? Should I definitely set up an AsyncTask for
this?
YES
An AsyncTask has several parts: a doInBackground method that does, in fact, run on a separate thread and the onPostExecute method that runs on the UI thread.
You can also use some sort of observer pattern such as EventBus to run async and post results to the UI.
Say the file write for some reason suddenly (for some jpeg) should
take a long time, eg 2 minutes. What would then happen? Would the UI
just wait (freeze)
The application will crash because Android will forcefully close it due to ANR (Application Not Responding).
Refer to the official documentation for details on this: https://developer.android.com/training/articles/perf-anr.html
Android applications normally run entirely on a single thread by
default the "UI thread" or "main thread"). This means anything your
application is doing in the UI thread that takes a long time to
complete can trigger the ANR dialog because your application is not
giving itself a chance to handle the input event or intent broadcasts.
Therefore, any method that runs in the UI thread should do as little
work as possible on that thread. In particular, activities should do
as little as possible to set up in key life-cycle methods such as
onCreate() and onResume(). Potentially long running operations such as
network or database operations, or computationally expensive
calculations such as resizing bitmaps should be done in a worker
thread (or in the case of databases operations, via an asynchronous
request).
The most effective way to create a worker thread for longer operations
is with the AsyncTask class.
Here is what I recommend though. Use the above mentioned, EventBus and create a BaseActivity which will automatically save the data for you onClose() by firing an event that runs Async. You then extend that base activity in all the places where you need autosave capabilities.
Here's what I mean with an example that uses EventBus.
public abstract class BaseActivity extends Activity{
#Override
protected void onResume(){
if(!EventBus.getDefault().isRegistered(this))
EventBus.getDefault().register(this);
super.onResume();
}
#Override
protected void onDestroy() {
if(EventBus.getDefault().isRegistered(this))
EventBus.getDefault().unregister(this);
super.onDestroy();
}
#Override
protected void onStop() {
super.onStop();
//We fire event and pass the current parent class that inherited this base.
EventBus.getDefault().post(new EventBusProcessMySaveData(this.getClass()));
}
}
//Your model class to use with EventBus
public final class EventBusProcessMySaveData{
private final Class className;
public EventBusProcessMySaveData(final Class className){
this.className = className;
}
public Class getClassName(){
return this.className;
}
}
public class MyMainActivity extends BaseActivity{
//Do you standard setup here onCreate() and such...
//Handle Event for Saving Operation, async.
//This will fire everytime theres an onClose() IN ANY activity that
//extends BaseActivity, but will only process if the class names match.
#Subscribe(threadMode = ThreadMode.ASYNC)
public void methodNameDoesNotReallyMatterHere(final EventBusProcessMySaveData model){
//We make sure this is the intended receiving end by comparing current class name
//with received class name.
if(model.getClassName().equals(this.getClass())){
//Do whatever you need to do that's CPUintensive here.
}
}
}
Is there any way to know your application is running ?
I want to run a piece of code when Android app is just closed. Any suggestion will be appreciated.
Just to answer my own question now after so much time. When user close the app, the process is terminated with no notice. onDestroy is not guaranteed to be called. only when you explicitly call finish().
I suggest you to make a custom application class and note store the visibility of application wether it is running in background or not.obviously if you don't close the application like this
How to close Android application?
have a look at this so that you don't close it from background and perform the visibility check like this.
public class MyApplication extends Application {
public static boolean isActivityVisible() {
return activityVisible;
}
public static void activityResumed() {
activityVisible = true;
}
public static void activityPaused() {
activityVisible = false;
}
private static boolean activityVisible;
}
and this is how you register you application class to the manifest file.
<application
android:name="your.app.package.MyApplication"
android:icon="#drawable/icon"
android:label="#string/app_name" >
and override these two methods like this.
#Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
}
#Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}
now check this status and perform what you like if it is running in background.You can take help of Booleans to check if the application is not closed by other reasons.
In general, there's no such thing as closing applications in Android: the user just stops using the app. It's up to the programmer to make sure that the user does not mention process creation and termination.
Please note that Android may kill the application process when it lacks memory and restart the application later.
For example, one of old office-like apps had the following bug: the user wanted to insert a photo, the office application invoked the Camera app, and Android killed the office app. The office app was not ready for a restart and lost all document changes (which was the bug). Apparently, the buggy app ignored the bundle passed to onCreate().
So the process life cycle and the application life cycle are different things. The process restart is visible to the application: the static variables get reset to their initial values (most likely, null). So it is possible to have a non-null bundle and null static data structures.
One example of executing a piece of code when the process dies may be found below:
Android camera locked after force close .
The problem solved in that post was that Android by itself does not close the camera when the process dies. I cannot tell from your post whether or not your problem is similar to this one.
If you uses, in your Activity, an object derivated from the class: ViewModel, you can capture the event: onCleared(); which is called always, after onDestroy().
See: https://developer.android.com/topic/libraries/architecture/viewmodel
I noticed that sometimes Async task does not work properly , Actually its doInBackground() method does not get called , this happens mostly when any service run in background for that activity.
For Example , when music runs in background with service, the Async task does not parse XML in background as its doInBackground does not work that time and the progress Dialog or progressBar kept spinning.
I read in few articles that AsyncTask.THREAD_POOL_EXECUTOR can help in these issues like :
if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
new Test().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
new Test().execute();
}
but that did not help in my case. Having the same issue after the above implmentation.
Here I am giving just a bit of my sample code to understand what I am doing::
public class TestAct extends Activity {
ImageButton play,forward,backward;
private ListView mList;
// many more variables
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_layout);
//binding the service here
// start service is called
init();
}
private void init(){
play=(ImageButton)findViewById(R.id.playBtn);
forward=(ImageButton)findViewById(R.id.forward);
backward=(ImageButton)findViewById(R.id.backward);
mList=(ListView)findViewById(R.id.list);
new GetData().execute();
play.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// calling the play() method of ServiceConnection here
}
});
// adding header to Listview
// other code and click listeners
}
class GetData extends AsyncTask<Void, Void, Void>{
#Override
protected void onPreExecute() {
super.onPreExecute();
// starting the progress Bar
// initializing the Arraylist,Maps etc
}
#Override
protected Void doInBackground(Void... params) {
//parsing the XML here
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// stop the ProgressBar
// Updating my UI here
// setting Adapter for ListView
}
}
}
This works fine generally but hangs when Service runs in backgound (I mean when music is playing in back).
I am not getting the exact reason behind this problem of Async task.
Will mannual thread implementation help in this case ...??
Well, I think the problem is because "Service runs in main thread so when it runs, it blocks my AsyncTask to run"... So I think If we can run Service in background thread then that can help . Thats why I tried IntentService for running service in separate thread but I am in doubt... if IntentService can run for indefinite time similar to Service ... and Also IntentService blocks AsyncTask few times.
So I dont't think its 100% perfect solutions for this kind of problem.
Can anyone help me to sort out this problem and understand the complete scenario.
Thanks in advance.
Sometimes you will want more control over your service's lifecycle than what IntentService gives you, in those cases you can just create a thread in the service and run your background code in that. Actually, to be more specific, create a HandlerThread which includes a Looper so you can use the standard android method for communication (messages) between your main thread and the background thread.
Answered here
I think the problem is starting another GetData AsyncTask before the previous one has been finished. Before executing another task make sure that previous one is complete. To do this use following code:
// make sure we don't collide with another pending AsyncTask
if (getDataTask == null || getDataTask.getStatus() == AsyncTask.Status.FINISHED || getDataTask.isCancelled()) {
getDataTask= new GetData();
getDataTask.execute();
}
Also make sure that you have a reference for running tasks. You can use subclass of Application class for doing this while your application is running or override onSaveInstanceState(Bundle outState)
and receive a reference to it in onCreate(Bundle savedInstanceState).
Read all the problem and Answers which has been posted here. correct me if i am wrong your scenario is you are parsing the xml and getting the list of songs and when user select any song you want that to be played with service right?
if the Scenario is correct then we can implement it in the much simpler way.
In the Activity, onResume() method parse the XML file and get the list of songs and update the list view(do not start anything related to service here)
when user click on the song then pass the particular key/string to the service with intent and start the service
In the service's OnStartCommand() method get the identifier and start the song as with normal media APIs
That will actually do the work for you.
Regarding the problem of
if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
new Test().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
new Test().execute();
}
This is for different behavior of the AsyncTask on Different version of the Android.
Looking at your code what is being done is in the Activity you are initializing the service hence the service is running in the background without doing anything fruitful.
and when user click on play you are calling play function of service which created problme here.
so to call the function of service from Activity you should right AIDL which you have not mentioned. and if you have wrote so it should be perfect.
but here recommendation is pass the song id to service and it should play from service should not call Service's function in activity.
if you want to update the Song List in the onResume of the activity then you must write AIDL and accomplish the scenario
Hope this will help.
I noticed that sometimes Async task does not work properly , Actually
its doInBackground() method does not get called , this happens mostly
You know that there is a limit of AsyncTasks that can be executed at a time? I had once an issue where a task did't start/work properly and this was because I exceeded that number. Check Android AsyncTask threads limits? for more on that topic.
when any service run in background for that activity. For Example ,
when music runs in background with service, the Async task does not
parse XML in background as its doInBackground does not work that time
and the progress Dialog or progressBar kept spinning.
Have you checked the possibilities of dead locks (in particular, if you're using wait() and notify())?
Well, I think the problem is because "Service runs in main thread so
when it runs, it blocks my AsyncTask to run"... So I think If we can
run Service in background thread then that can help . Thats why I
The things you are going to do in a service should run in an own thread anyway. That way you can be sure that nothing is going to be blocked. If you have something to populate you could use a receiver, for instance.
Hope I could help a bit ...
Here is a hint, How I finally solved my Problem ::
1) I used IntentService instead of Service as Service runs in mainThread while IntentService runs in a separate Thread than mainThread to make sure that my background Service does not effect my current task . Also , I am using AIDL for communication between my UI and background Thread (this was already working for Service , so nothing new in this part).
2) I used painless thread instead of AsyncTask, I interrupt the thread in onDestroy() method to make sure that the Thread does continue indefinitely.
App seems to perform much better than Earlier now.
Hope this will help others too :)
Per the Threading Rules section of the Android Developer AsyncTask document, the AsyncTask has to be created and launched on the UI thread, so if you are launching it from a background thread in a Service, that would account for the faulty behavior.
http://developer.android.com/reference/android/os/AsyncTask.html
You really shouldn't be using AsyncTasks in general :) There is a pretty good explanation here . Think about what will happen if the user rotates the device, while your task is running. The Activity is recreated, but the task runs in the background and holds a reference to the "old" activity. There are ways to get around this, and they are surely still some cases where an AsyncTasks is the correct approach.
However, your really should consider switching to a Loader or (if you feel adventurous) try RoboSpice :)
I am confused with respect to design of my app. I need to continuously poll a server to get new data from it. I am confused whether Async Task running at fixed interval or Service running is background is better option. The thread will run only when the app is running
You have already some answers to your question, but I think it worths a summary ...
What you need
When you want to run a peice of code that takes some time to complete you should always run it in a separate thread from the UI thread.
You can achieve that in 2 ways:
Using Thread:
This is the simplest one, if you don't need a lot of communication from the new thread to the UI thread. If you need the communication, you will probably have to use a Handler to do it.
Using AsyncTask:
Also runs in a separate thread and already implements some communications channels with the UI thread. So this one is preferable if you need this communication back to the UI.
What you don't need
Service
This serves mainly to keep some code running even after you exit the main application, and it will run in the UI thread unless you spawn a new thread using the options described above. You said that your thread are suposed to terminate when you exit application, so this is not what you need.
IntentService
This can be activated by an external event (i.e. BroadcastReceiver) that can start a piece of code defined by you, even if your application is not running. Once again, based on your requirements, this is not what you are looking for.
Regards.
an Android Service is not in a background thread.
Therefore you should have a Service running that will start an ASyncTask each time you want to poll.
Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work. More information on this can be found in Processes and Threads. The IntentService class is available as a standard implementation of Service that has its own thread where it schedules its work to be done.
Service should not be compared to AsyncTask. I guess you most likely meant IntentService here - and this is slightly different thing than Service, despite the common name.
As for periodical fetching, I'd stick with recurrent alarm (using AlarmManager) and (most likely) use IntentService to do the fetching.
Here you got with AsyncTask fundamentals and some tutorials
And here you got with IntentService fundamentals and tutorials
Note, that IntentService jobs are queued by design, while AsyncTasks can run fully paralel. However be aware of regression related to AsyncTask handling in newer APIs. Not a big deal as workaround is just a few more code lines, however it's worth knowing that.
EDIT
There's misunderstanding floating among many concerning AsyncTask lifecycle being bond to Activity's life cycle. This is WRONG. AsyncTask is independent from an Activity. Finishing Activity does not do anything to any AsyncTasks, unless you are cleaning them up from onDestroy() by your code. Yet, if an activity's process is being killed while it is in the background, then AsyncTask will also be killed as well, as part of the entire process being killed
If you want to "continuously poll", an asyncTask won't do. The task stops when your app gets stopped by Android. A Service by itself won't do either, as Blundell already pointed out. A Service runs in the main thread, and you don't want to do polling in the main thread. There's two ways of doing it: you create a Service that spawns its own thread to do the stuff you want it to do, or you let it schedule polls that are executed in an AsyncTask or in a separate thread. I try not to have polling in my app, but if you have to, creating a special thread in your service that does the polling seems best to me.
Depending on what your app does and what the polling is about, you can give the separate thread a lower priority, so it doesn't get in the way of other processing.
The thread will run only when the app is running
Then AsyncTask will be the simplest solution. Send data periodically to app thread using publishProgress() from background thread. Set desired interval using Thread.sleep() in doInBackground(). Also, make sure you start a new task in onResume() method of Activity, and end this task in onPause() method of Activity.
Example:
public class MyActivity extends Activity {
private AsyncTask<Void,String,Void> mAsyncTask;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
super.onResume();
mAsyncTask = new MyTask();
mAsyncTask.execute();
}
#Override
protected void onPause() {
super.onPause();
if(mAsyncTask != null){
mAsyncTask.cancel(true);
}
}
private void onServerResponse(String response){
Toast.makeText(this, "Got response !", Toast.LENGTH_SHORT).show();
}
private final class MyTask extends AsyncTask<Void,String,Void>{
#Override
protected Void doInBackground(Void... voids) {
while (!isCancelled()){
String response = "";
//server query code here
publishProgress(response);
Log.i("TEST", "Response received");
//sleep for 5 sec, exit if interrupted ,likely due to cancel(true) called
try{
Thread.sleep(5000);
}catch (InterruptedException e){
return null;
}
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
if(values.length > 0){
onServerResponse(values[0]);
}
}
}
}
I'm asking for help so my life, and more importantly my user's lives will not be ruined by me not knowing how to use Services and Threads correctly.
I'm not asking for a long explanation, but more of a confirmation. It's fine if I'm dead wrong. I'm here to learn.
If I understand correctly:
1. a service runs in the background (no UI).
2. a service theoretically will run forever until it kills itself (I'm taking a big guess here)
3. a service will continue to run even when the main Activity is not visible (how about even destroyed?)
So here's my coding question.
I've got my service setup and a thread. Everything works great, but it only works once. I need it to loop and keep checking back. Once it's done run() how do I go about telling it to run() again?
public class NotifyService extends Service{
private long mDoTask;
NoteThread notethread;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
mDoTask = System.currentTimeMillis();
notethread = new NoteThread();
notethread.start();
}
public class NoteThread extends Thread {
NotificationManager nManager;
Notification myNote;
#Override
public synchronized void start() {
super.start();
//init some stuff
}
#Override
public void run() {
//If it's been x time since the last task, do it again
//For testing set to every 15 seconds...
if(mDoTask + 15000 < System.currentTimeMillis()){
//Take care of business
mDoTask = System.currentTimeMillis();
}
}
}
}
From the Android docs:
A Service is an application component
representing either an application's
desire to perform a longer-running
operation while not interacting with
the user or to supply functionality
for other applications to use. Each
service class must have a
corresponding declaration in
its package's AndroidManifest.xml.
Services can be started with
Context.startService() and
Context.bindService().
Note that services, like other
application objects, run in the main
thread of their hosting process. This
means that, if your service is going
to do any CPU intensive (such as MP3
playback) or blocking (such as
networking) operations, it should
spawn its own thread in which to do
that work. More information on this
can be found in Processes and Threads.
The IntentService class is available
as a standard implementation of
Service that has its own thread where
it schedules its work to be done.
You can find a detailed discussion
about how to create services in the
Services document.
In other words, a service does NOT run in the background unless you put it in a thread. If you put a service that never ends in your application without manually threading the service, then it WILL block.
Android provides an API to do background tasks for you without having to poke around with Java threads; it's called AsyncTask and it's one of the few GOOD design decisions that the Android team has ever made.
EDIT I forgot to address your question about multithreading. You don't want to make a thread execute its run() method more than once. Either instantiate a new thread or put a while loop around the contents of the run logic that you would like to have repeated.
To understand threads better, read "Java Concurrency In Practice" by Brian Goetz.
To understand services better, I think you should write them to be single threaded and let the Java EE container you deploy them to handle threading issues. A pooled servlet is a better solution than having your code shoulder the burden of managing threads for users.