I'm designing a news app where I need to download fresh articles and their detailed stories whenever user opens my app. I'm doing all of this a background thread. My prime focus was that the background thread should stop as soon as user exits the app so as to prevent user for incurring extra download charges.
To achieve this, I initiate background download in my splash screen and I keep on checking for flag variable that lets the background process know if the app is still running.
Now my question is: I'm very clear about initialization of this flag variable. I've initialized it in onCreate() of Application subclass since it is the point where application starts. But I've no idea where to clear it. I tried doing it in onDestroy() of my MainActivity. However, I found that onDestroy() is often called on transition between one activity to another if system needs to free memory. So, doing so there would stop my background thread even when I'm switching across screens and not actually closing the app. How should I deal with this scenario ? Is there a smarter way of handling this ?
I don't think you have to do that : either the user is pressing the "Home" button (which most people do) and then it's common for apps to keep running in background, and as so to still be easily accessible to the user in the state they left it. Either you provide a "close app" button which really kills the app, which will also kill every kind of thread created by the app and you don't have to worry.
If you really want, you could capture the "Home" clicks, and use those to kill the app before returning to home, which is a nice thing to do if your app has 0 initialization time.
But I've no idea where to clear it. I tried doing it in onDestroy() of my MainActivity.
In order to know if the activity is destroyed because the user finished it (with Back) or Android will re-create it, you could use isFinishing();
Something like:
protected void onDestroy() {
super.onDestroy();
if(isFinishing()) {
// stop the news feed download
}
}
Or better, stop the feed download in finish():
public void finish() {
// stop the news feed download
super.finish();
}
To go back to what you said above with:
I'm very clear about initialization of this flag variable. I've initialized it in onCreate() of Application subclass since it is the point where application starts.
Even if the activity is finished, the application is very probable to still live. The Android OS will decide when to kill it. So you will initialize the download once the app starts, then you will stop it on onDestroy() or on finish() within Activity, depending on your desire, but if the application doesn't stop (most probable) and you're re-entering again in the news activity you should be starting the news download.
I would rather initiate the download in the background in onCreate(Bundle savedInstance), but when savedInstance is null (so I know this is the first create of this activity) and stop it (if hasn't stopped already by itself) in finish();
Hope it helps!
To begin with for downloading datas from webservice (json or xml) you should use AsyncTask (easy to use)
so what i mean was, to clear your flag with ondestroy(), for when the application is exited, and maybe you can catch when the home button is pressed
Override the below method in your Activity,
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);
}
And now handle the key event like this,
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_HOME)
{
//do something
}
if(keyCode==KeyEvent.KEYCODE_BACK)
{
//do something
finish();
}
return false;
}
Related
On Android, I'm trying to catch the event where my app comes back to the foreground from the background. In other words, the app was active, then the user minimized it (by clicking the home button or starting another app or something), and then the user runs the app again.
I can add the onRestart() method to an activity as follows:
#Override
public void onRestart() {
super.onRestart();
Log.d("MAIN", "onRestart called.");
}
But this only works when that specific activity is the active one when the user minimizes the app.
Is there a way to catch this for the whole app somehow? Or do I need to add onRestart to every single activity I have? (I suppose I could create a superclass on which all the other activities are based).
Thanks!
Is there a way to catch this for the whole app somehow?
No, because there is no concept of an app "restarting".
Or do I need to add onRestart to every single activity I have?
Presumably. Or, find a way to avoid needing to "catch the event where [your] app comes back to the foreground from the background".
I think the method you need is void onResume()
here is there android developers page for activities , check the "Implementing the lifecycle callbacks" part of the page .
http://developer.android.com/guide/components/activities.html
hope this helps.
I have an android application that uses Threads. Application waits for some time, then executes a function.
Things go pretty well if user waits for some time. After the predefined time t ends, the function gets executed.
However, if the user clicks on back button of the device and return to main screen, after the time t ends, the application appears again.
How can I understand if the user pressed back, or closed my application? How can I stop the thread and release everything if I get the leaving message -let's say USER_EXITED?
in your activity when the activity is going to end you can check if it is finishing like this and take care of things to do with your threads
#Override
public void onPause() {
if(isFinishing()){
//put the correct checks or shutdowns
{
super.onPause();
}
I think that you need to create a Service.
http://developer.android.com/reference/android/app/Service.html
I'm developing an android app using bluetooth communication (using a propetary protocol) and I need to catch the moment when the app is killed.
I wanted to use the "onDestroy()" method but it isn't called every time the app is killed.
I noticed that it is called when I press the back button and, only sometimes, when I kill the app from the task manager.
The question is: How can I catch the moment before the app is killed?
Here is the code I tried to use:
#Override
public void onDestroy() {
sendMessage(msg);
Log.d("SampleApp", "destroy");
super.onDestroy();
}
#Override
public void finish(){
sendMessage(msg);
Log.d("SampleApp", "finish");
super.finish();
}
Unfortunately finish() is never called and onDestroy isn't called every time I close the app from the task manager.
How can I handle this?
As stated in the documentation here, there is no guarantee that onDestroy() will ever be called. Instead, use onPause() to do the things you want to do whenever the app moves into the background, and leave only that code in onDestroy() that you want run when your app is killed.
EDIT:
From your comments, it seems that you want to run some code whenever your app goes into the background, but not if it went into the background because you launched an intent. AFAIK, there is no method in Android that handles this by default, but you can use something like this:
Have a boolean like:
boolean usedIntent = false;
Now before using an intent, set the boolean to true. Now in your onPause(), move the code for the intent case into an if block like this one:
if(usedIntent)
{
//Your code
}
Finally, in your onResume(), set the boolean to false again so that it can deal with your app being moved into the background by a non intent means properly.
Your application will not receive any additional callbacks if the process it terminated by external means (i.e. killed for memory reasons or the user Force Stops the application). You will have to make do with the callbacks you received when you app went into the background for your application cleanup.
finish() is only called by the system when the user presses the BACK button from your Activity, although it is often called directly by applications to leave an Activity and return to the previous one. This is not technically a lifecycle callback.
onDestroy() only gets called on an Activity as a result of a call to finish(), so mainly only when the user hits the BACK button. When the user hits the HOME button, the foreground Activity only goes through onPause() and onStop().
This means that Android doesn't provide much feedback to an Activity to differentiate a user going Home versus moving to another Activity (from your app or any other); the Activity itself simply knows it's no longer in the foreground. An Android application is more a loose collection of Activities than it is a tightly integrated singular concept (like you may be used to on other platforms) so there are no real system callbacks to know when your application as a whole has been brought forward or moved backward.
Ultimately, I would urge you to reconsider your application architecture if it relies on the knowledge of whether ANY Activity in your application is in the foreground, but depending on your needs, there may be other ways more friendly to the framework to accomplish this. One option is to implement a bound Service inside of your application that every Activity binds to while active (i.e. between onStart() and onStop()). What this provides you is the ability to leverage the fact that a bound Service only lives as long as clients are bound to it, so you can monitor the onCreate() and onDestroy() methods of the Service to know when the current foreground task is not part of your application.
You might also find this article written by Dianne Hackborn to be interesting covering in more detail the Android architecture and how Google thinks it ought to be used.
I just resolved a similar kind of issue.
Here is what you can do if its just about stopping service when application is killed by swiping from Recent app list.
Inside your Manifest file, keep flag stopWithTask as true for Service. Like:
<service
android:name="com.myapp.MyService"
android:stopWithTask="true" />
But as you say you want to unregister listeners and stop notification etc, I would suggest this approach:
Inside your Manifest file, keep flag stopWithTask as false for Service. Like:
<service
android:name="com.myapp.MyService"
android:stopWithTask="false" />
Now in your MyService service, override method onTaskRemoved. (This will be fired only if stopWithTask is set to false).
public void onTaskRemoved(Intent rootIntent) {
//unregister listeners
//do any other cleanup if required
//stop service
stopSelf();
}
Refer this question for more details, which contains other part of code, too.
Start service like below
startService(new Intent(this, MyService.class));
Hope this helps.
I have a START and STOP button in the main screen of an App. there are some GUI and threads that are instantiated when I click on START. When I click on stop, I want everything to be stopped and the activity should come back to its origin state. To the state that is exactly same like when launched (when we tapped on App icon in mobile).
Is it possible to do this? I tried with finish() , this killed the app and exited . I don't want to exit from main screen. rather, on clicking STOP I want app to come back to origin or born state. Thanks.
How are you running your threads? Are they vanilla threads or subclasses of AsyncTask?
If these are instances of an AsyncTask object, you can use the cancel() method to cancel it and then inside your doInBackground() method, you could check the isCancelled() method to see if it has indeed been canceled, and then exit gracefully.
Pseudo code below:
private YourTask taskRef;
public void btnStartHandler() {
taskRef = new YourTask();
taskRef.execute();
}
public void btnStopHandler() {
taskRef.cancel();
}
and then, in your AsyncTask:
public Void doInBackground(Void... arg0) {
// Background loop start
if (this.isCancelled()) {
return;
}
// Background loop continue...
}
If you're using threads, you can interrupt them and catch the exception and handle it there. Furthermore, you could create a method that you call from onCreate() called initApp() or something that initializes everything. You could also use that initApp() from the STOP button click handler to reset values back to startup defaults.
You can restart the activity with finish() and then call startActivity(getIntent());. This will effectively restart your activity and put it in its default state, no matter how it was started.
Before doing that make sure to cancel all threads or AsyncTasks as TJF suggested (you can and should do this in the onDestroy overload).
For more info about restarting an activity, and a discussion about pros and cons, see this question: Reload activity in Android
I have an app that starts playing sounds and begins/resumes gameplay in the onResume() method, but what I'm noticing is that if my app was the last run application when I put the phone into standby (screen off), and I just press the Menu button to check the time, then the phone starts playing the game and sounds in the background (the app isn't actually visible, only the screen with the date/time is, yet onResume must have been called in my app). What am I to do here? Is there a way to discern what is reactivating the app, and then add a conditional statement that only starts the game when the app is actually visible?
Here is a snippet from my onResume:
#Override
protected void onResume()
{
mySaveGame = Utilities.loadSavegame(this);
//check the savegame
if(mySaveGame!=null)
{
//start game using savegame values
this.startFromSavedGame(mySaveGame.getIsLevelComplete());
}
else
{
//run the 1st-run components
this.startFirstRun();
}
super.onResume();
}
The only thing I can think of doing to prevent the game from starting whenever the screen gets turned on (even when the app isn't visible) is to put this.finish() as the last line in onPause()... but that forces you to restart the app every time you want to go back to it because the precess itself was killed (which is fine because my onPause saves persistent data, but it's not an elegant solution).
Please help.
Have you considered switching to onStart() and onStop(), rather than onResume() and onPause()?
I was having the same problem (I had my music player resume/pause at onResume()/onPause()) and the best solution I found is to pause and resume my activity when it is on the foreground which you can get with public void onWindowFocusChanged (boolean hasFocus) callback.
Edit: This in an old and slightly incorrect answer - correct response is described in the Android Developers Blog: making android games that play nice