I have to know when my app comes back to the foreground in these situations:
Start app
Start Activity A
Home Pressed
App brought to foreground by user. (Activity A is shown)
Start app
Start Activity A
Start Activity B
Home Pressed
App brought to foreground by user. (Activity B is shown)
I cannot check this with a flag in onResume and onPause. Because this would trigger every time Activity B is loaded.
I'm not sure if this would work but try overriding the onUserLeaveHint of your Activity:
https://developer.android.com/reference/android/app/Activity.html#onUserLeaveHint()
If this one is called, set a boolean field of your Activity to true. When the onResume is called, check for this boolean. If it is true, then your Activity is coming back into the foreground (don't forget to set this boolean back to false again).
BTW: I like your KlaasVaak handle :). Are your trying to make people sleepy :)
Related
What I want to do is to start an Activity upon device restarts by sending an intent in a BroadCastReceiver listening BOOT_COMPLETED event. The Activity has a conditional moveTaskToBack in its onCreate event handler. The Activity is launchable and the only Activity of App.
When I reboot the device, App is running and I can tell Activity is hidden from screen. From logcat a 'onCreate' message is print to indicate onCreate event happens. Then I click App icon in screen, expect Activity shows up from back for onCreate shall be omitted and moveTaskToBack shall NOT run. But onCreate event handler is still executed and Activity hides again.
In another way I remove starting Activity from BroadCastReceiver, just open App by click icon in screen. At first tap App starts running and Activity hides, and when I tap icon again, the Activity shows up. From logcat the first event is onRestart, which is expected.
I am not sure what is the different between two ways of bring back Activity? Why onCreate happens twice applying BroadcastReceiver in first case?
Cheers!
I'm now aware that the activity started by broadcast receiver is in a stack, while the activity, which is as same class, started by launcher is in another stack. Thus why onCreate event happened again when I tapped App icon desktop, for App create a new stack and brand-new activity.
Thanks xvlcw for great help...
I have requirement wherein I have to display a lock screen if the user moves out of the application.
Hence, the structure is: Activity A extends Activity B.
Wherein Activity B is the deciding activity : "was application in backgound".
If so it launches the lock activity.
Now, say I am on activity A and receive a phone call. Hence the app gets into the background.
When it resumes I can see the glimpse of Activity A for a fraction of second and then comes the lock activity.
Can there be any solution to avoid that glimpse of Activity A?
You can see the lifecycle of activity from official doc
You are using activity B just to track whether activity is alive. I am not sure if it is necesary.
If activity goes to background onPause() method is called, it means activity is not visible (it might be both screen lock or home button pressed), and onResume() is called when activity is visible again. In Activity A if you override onPause method and launch your lock activity, it should work. (Or set a boolean onPause and launch lock activity on resume(you might see Activiy A though)
Good luck
Can I use any lifecycle method to check whether my activity was started by pressing the back button?
As correctly stated by shayan the onRestart method is triggered (see http://developer.android.com/reference/android/app/Activity.html) if an activity gets "restarted", i.e. started again.
All member variables will have the same state as when you left the activity. So you can use any boolean flags for anything special.
In my case, the activity I want to check for "coming back via back button" is my StartActivity, where users can login via Facebook. The Facebook button starts Facebook's LoginActivity, which then returns to my StartActivity and triggers onRestart the first time. When I then leave my StartActivity I set a boolean flag to true before I start my MainActivity. When the user now presses the back button, the StartActivity.onRestart is triggered, and I can check my previously set boolean flag to check what I wanted to know.
I have a home screen widget with a button with a pendingIntent. Click it, it bundles a boolean to indicate where it came from and it brings up my main activity.
In my main activity in onCreate, I check for a bundle, if the boolean that says it was launched from my widget is true, I perform an action.
Every time I hit my widget button, it should launch my main activity, and run through onCreate.
And it does, on the emulator. And it did, on my n1. Then suddenly it stopped on my n1. I can still get it to hit onCreate when I launch from the widget but I have force stop or reinstall and then it only does it the first time.
What is going on with this?
What's going on is the Activity lifecycle. Android will keep the same instance of your Activity around so that the user can return to it later. Monitor some of the other lifecycle methods like onStart and onResume to see this in action.
You may see a difference in behavior if the user hits the back button vs. the home button. The back button will finish the current Activity by default, whereas home will leave it alone unless Android decides to kill it for resources later.
Is there any way to tell whether an Activity is being resumed (i.e. onResume is called) from the home screen/launcher?
For example, if I have an Application with two activities, A and B.
Scenario 1:
Some user action on Activity A will invoke Activity B, bringing it into the foreground - moving Activity A into the background. As Activity A moves into the background, it goes through onPause() and onStop(). The user (now on Activity B) either finishes the Activity or hits the "back" button, bringing Activity A back to the foreground, causing an onRestart(), onStart(), onResume() sequence.
Scenario 2:
If the user hits the "home" button while Activity A is in the foreground and then re-invokes the Application from the launcher, it goes through the same lifecycle as in Scenario 1. I.e. User hits the "home" button. Activity goes through onPause() and onStop(). User launches the application again, causing Activity A go come back into the foreground, again going through the same onRestart(), onStart(), onResume() sequence as in Scenario 1.
As far as I can tell, the Activity has no way of knowing how it was resumed, it just knows it is being brought back into view. In fact, I have a feeling that there isn't really as much of a concept of an "Application" in Android - in the sense of something that has a single entry and exit point.
in Scenario 2, your activity will get an onNewIntent call, with the launcher intent passed to it.
You could capture the back button press on Activity B and pass an extra value to Activity A. If there is an extra value then the activity was resumed from pressing back on Activity B, if there is no extra value then the Activity was resumed from being hidden.
Could Acitivity A use startActivityForResult() to start Activity B and use onActivityResult() to detect that Activity B finished?
So the straightforward answer to the initial question is probably: no. Launching an activity from the home screen through an icon, or resuming it from the recents screen can not be observed from the intent it is (re)started/resumed with.
Depending on what you are trying to achieve there are some approaches though:
what #superfell suggested:
Check for whether the onNewIntent-method is called on your activity to decide if it was restarted from the launcher. As a precondition you need to set your activity to singleTask/singleTop launchMode in your Manifest:
android:launchMode="singleTask"
depending on what you're trying to achieve, this might be enough! But additionally you might have to deal with what happens when the user presses the back button. Default behavior is to finish & destroy your activity. Thus a brand new copy of it would be launched when it gets selected from the recents screen. Though onNewIntent would not be called, everything would be rebuilt from scratch. If you need to prevent this you can use:
override fun onBackPressed() {
moveTaskToBack(true)
}
finally when you navigate "back" from an activity you launched yourself onNewIntent will also not be called. If you further need to distinguish why your activity is resumed, you might want to start the 2nd activity with startActivityForResult so the onActivityResult is called when you get resumed.
Launcher activity & Intent extra
A completely different approach would be to have a "launcher" activity in your manifest that directly calls your "main" activity and finishes itself. When calling your main activity you can put an intent extra that allows your main activity to distinguish if it was just launched for the first time, or not. As the extra would be present on further onResumes, make sure to overwrite it the first time you "consume" it:
override fun onResume() {
super.onResume()
val firstLaunch = intent.getBooleanExtra(FIRST_LAUNCH, false)
intent.putExtra(FIRST_LAUNCH, false)
if (firstLaunch) {
// do something
}
}
and when starting from your "launcher" activity:
intent.putExtra(FIRST_LAUNCH, true)
startActivity(intent)