So, I have an app with a splash screen that starts another activity once it's done loading. When the user hits the home button while it's loading, the application goes to the background and then comes back to the foreground once that activity is started. Is there any way to stop that from happening?
Two things:
First, make sure you're tearing down the reference to the location service in onPause. I assume you're using Google's API Client. If you're not, you really should be. So in onPause, make sure you unregister the listeners:
#Override
public void onPause()
{
// Tear down Google API Client.
if (googleApiClient != null)
{
if (googleApiClient.isConnected())
{
// Turn off location polling.
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
}
// Avoid leaks by making sure callbacks get unregistered.
googleApiClient.unregisterConnectionCallbacks(this);
googleApiClient.unregisterConnectionFailedListener(this);
googleApiClient.disconnect();
}
}
BUT: I think you're over thinking the solution on this one. Why have two activities? Why not one, and have a "wait state" until you get the location fix? Your wait state could be anything. Or a full screen splash as you say (Use a RelativeLayout and stack the views). When you get the fix, fade out the splash.
Then stash the location to the savedInstanceState bundle. When your activity's state changes, you'll know to not display the splash again.
Related
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;
}
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 created an application that has a 'geolocation' feature responsible for spotting a user on the Google map like many other applicatons. I used "LocationManager.NETWORK_PROVIDER" to locate the user and at the same time I instantiate and start "MyLocationOverlay" (in the onLocationChanged() method) to get the location. Because of the second one, the GPS turns on (blinking on the top) which is OK.
The problem is, after the application is closed (back button or through task manager), the GPS feature is still hanging there, trying to get the updates.
How to turn it off after the user leaves the activity? I tried suggestions from here and other forums like putting locationManager.removeUpdates(this); and locationManager.removeUpdates(mMyLocationOverlay); within the methods onPause(), onStop(), onDestroy(). The method OnPause looks like this:
#Override
protected void onPause() {
super.onPause();
locationManager.removeUpdates(this);
locationManager.removeUpdates(mMyLocationOverlay);
}
('this' references my class that implements LocationListener)
Please, can someone help me to turn off GPS updates after leaving the activity (it's a class that extends MapActivity) but not turn off the GPS feature on the phone itself?
Interesting thing is that when I remove the part with MyLocationOverlay, GPS will not start of course and therefore no problem. So I'm pretty sure that mMyLocationOverlay is the listener that "won't stop" and producing a problem.
googleMap.setMyLocationEnabled(false); in onPause() solved my issue. And I'm setting that to true in OnCreate(). Hope this may help others.
If you want to close (or end) the application you can use
System.exit(0);
so when the application is closed, all the services you use will close.
Set your LocationListener equal to null and re-instantiate onResume()
I.e I would like to know when user interact with my application and when not.
I have tried do it using ActivityManager.getRecentTasks(). I have checked root activity at a top task to detect interact user with my application or not.
I have forced to check it in separated thread each second or two.
This way is bad for me. There is another way to detect when any activity of my app are opening or closed?
Have a look at the lifecycle of an Activity.
There are callback methods (onStart, onResume, onPause, onDestroy, ...) that are invoked by the system whenever your activity is created, becomes active or inactive etc.
You might create your own application class (just inherit from android.app.Application) and do your tracking there. The application will be around as long as your app is running.
For example you could put a flag or a counter there and set it from the activities' callbacks. A simple example for that could be:
public void onResume() {
super.onResume();
((MyApplication)getApplication()).active = true;
}
public void onDestroy() {
super.onDestroy();
((MyApplication)getApplication()).destroyed += 1;
}
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