is there a way to resume back a Kivy application to most recent activity even if minimized? i mean when i am in the application ( a compiled application as .apk) and i want to open wifi for example or check other apps, my application closes and i need to restart it again by pressing on it again...so if i am in the middle of an operation in my application (a calculation or an e-mail composition) and i want to check another application ,all my operation would be cancelled if i do so and of course it is a terrible user experience...
The documentation here describes how to enable pause mode, such that your app will be resumed rather than restarted if you leave then open it again.
The main point is to add an on_pause method to your App class, and have it return True.
Note that you are never guaranteed to be able to unpause again (Android itself may kill paused apps if their memory is needed etc.), so you should also use this method to carry out any state saving you need. However, it's unlikely to be a problem for short task switches, and may rarely or never come up in newer devices with more resources.
Related
We have one very difficult to reproduce problem with an app. The use case is as follows:
User opens app
User leaves app in background
User openes 5 to 7 more apps
System kills our app
When user tries to resume app, app crashes due to NullPointerException
I was trying to use console log with Application class method onTrimMemory() and onLowMemory() but this methods are not being called. Is there any method or callback I can be listening to know when android system will kill my app due to many more apps being opened and in that case for me to do something?
You can save whatever states you need in onSaveInstanceState() and restore them in onRestoreInstanceState(). onDestroy() is what the system will most often call to clear room while your Application is in the background, but it is not guaranteed to be called, so it is better to have already saved your states in onSaveInstanceState().
Is there any method or callback I can be listening to know when android system will kill my app due to many more apps being opened and in that case for me to do something?
Not really. Depending on circumstances, onDestroy() of running activities and services will be called.
We have one very difficult to reproduce problem with an app
That should be reproducible in a matter of seconds:
Run your app.
Switch to another app.
Kill your app's process from your IDE (e.g., "Terminate Application" toolbar button in "Android Monitor" tool window).
Try returning to your app from the overview screen (a.k.a., recent-tasks list)
I am working on a project, where while being on a specific Activity we show a local sticky notification. That should also be the case when the app is minimized. What I have to accomplish is to remove the local notification whenever the app is killed (by Android, because of memory lack or by the user, with a swipe from the recent apps list).
Usually onDestroy would be called whenever Android takes the Activity to open some space. That is fine in one of the cases, however swiping an app from the recent app lists doesn't call the onDestroy and the sticky notification stays.
What I did is, I implemented an empty Service which would force the onDestroy when the app is killed (both swipe and system kill) so I can get my notification removed.
However, what I would like to do is to differentiate between the swipes and system kill.
Is this even possible?
In general, if Android wants to kill your application because it has been in the background for too long (or because it wants to reclaim resources), Android will just simply kill the OS process hosting your app. It will not call finish() or onDestroy() on any Activity or Service components. The behaviour of "swipe from recent tasks list" has changed over time and is different in different Android versions. Someone should write a book about that :-(
You can check for when the user swipe-closes the app by adding a service to your app, and implementing the onTaskRemoved method: https://stackoverflow.com/a/26882533/2441655
This is a comment I found in reddit that seems to me really interesting:
Swiping an app away will effectively "kill" most apps. You can test
this out using ADB if you have the SDK installed. Swipe everything out
of your recents list, then launch the browser.
Use ADB to run 'ps' on the device and verify that the com.google.android.browser process is
running. Go to the home screen, it's still running. Launch some other
apps, and the com.google.android.browser process is still there.
Swipe it out of the recents list, however, and the process is gone. You can
create a test app to further verify, and log the onDestroy() call in
your Activity. It's not called when you back or home out of the app,
or when you launch other apps. It does get called when you swipe the
app out of the recents list though. I do agree that the recent apps
list isn't really "multitasking".
The apps in the list aren't necessarily even running, the processes could have been killed by the
memory manager long before you try to re-open it. However, you can't
argue that the only purpose is to jump quickly to other apps when the
swiping makes the actual process go away.
This is another good answer about what happen when you swipe an app out of the recent apps list. But the part that I liked most was:
Actually, removing an entry in recent tasks will kill any background
processes that exist for the process. It won't directly causes
services to stop, however there is an API for them to find out the
task was removed to decide if they want this to mean they should stop.
This is so that removing say the recent task of an e-mail app won't
cause it to stop checking for e-mail.
If you really want to completely stop an app, you can long press on
recent tasks to go to app info, and hit force stop there. For stop is
a complete kill of the app -- all processes are killed, all services
stopped, all notifications removed, all alarms removed, etc. The app
is not allowed to launch again until explicitly requested.
By Swiping from recent task list removes only from recent tasks ..
It was also called onDestroy before android 5.0 .
Might be you are having issue above api level 20 devices.
System kill normally can not be executed in normal android activity lifecycle.
It just finishes the activity on back press event.
when swiping app to left if any Thread still run in your app Interrupted but service not stopped, when you kill handy app Thread and services are stopped.
the behavior is similar to but not exactly the same as closing an app -- in general (for apps that don't define explicit back button handling) it's the same thing as hitting back enough times from within an application that you exit out of it.check out this link discussion it has some good input on the subject
First, let's get one thing clear: Android MAY NOT CALL onDestroy(). Referring to the Activity Page, from Honeycomb onward, onPause() and onStop() are guaranteed to be called before an app is killed.
Be aware that these semantics will change slightly between applications targeting platforms starting with HONEYCOMB vs. those targeting prior platforms. Starting with Honeycomb, an application is not in the killable state until its onStop() has returned. This impacts when onSaveInstanceState(Bundle) may be called (it may be safely called after onPause() and allows and application to safely wait until onStop() to save persistent state.
So after (hopefully) clearing the air on the Android lifecycle, I think you can achieve what you want by putting the notification removing code in onStop() instead. If you end up needing it back because the user actually DOES come back to the specific Actvitiy(IE not killed), you can bring it back in onRestart().
For testing purposes I need to easily reproduce a situation when Android system decides to save a state of and kill a background application, in the same manner as it normally does for memory optimization purposes. In fact, I need also to test the restoration process of such a removed process when a user switches back to it.
The straighforward approach would be to open the application and then open more other tasks trying to allocate as much resources as possible. That's too complicated and unreliable.
I've found this question on SO, but the answer implies simply killing the process, which seems not an equivalent, because there seems no means for further automatic restoring of the killed process with a saved state, when a user decides to switch back to the application. If I understand correctly, after such explicit killing the application, if started, will run from very beginning, not from a saved state. Please, correct me, if I'm wrong.
According to Android documentation, what I need is performed by ActivityManager.killBackgroundProcesses(packageName), but this is the programmatic way of doing the thing. Is there an utility which already provides the same option from UI?
If I understand correctly, after such explicit killing the application, if started, will run from very beginning, not from a saved state.
That depends on how the app is launched. If you mean from the launcher icon, yes. However, the user could return to you via the BACK button, or via the recent tasks list, depending upon circumstances, and those would return the user to the spot they left, not the "very beginning".
Is there an utility which already provides the same option from UI?
On an Android 4.0+ device, with your app in the background, open up the recent tasks list (long-press HOME or press the dedicated RECENTS affordance), and swipe your app off to the right. This appears to basically call killBackgroundProcesses() on that package name.
I have not tried this in an emulator, but probably it does the same thing.
I would like to test out onSaveInstanceState and onRestoreInstanceState for my app on the emulator.
I have found this, which says that we could simulate this during orientation change, but I'm storing some of my variables on the application level (subclass android.app.Application), so the orientation change does not wipe out the variables.
So my question is, how can I simulate the low memory situation thus killing of my activities?
Hope I've made myself clear. Thanks
You can pause your application (by pushing the Home button, simulating a call, whatever). Then kill the app's process through adb. Since the docs say that after onPause() returns your app can be killed without any further notice, this is a fair test.
If you don't want to go through the trouble of finding the pid of your app's process, you can use adb shell am kill com.example.package_name to kill your app's process. Make sure that the app is put in the background. The docs say that this command "kills only processes that are safe to kill and that will not impact the user experience." So you might want to launch a couple of other apps before trying this one.
There's a more solid solution for this in Android 6 and newer. I've used the following method successfully on Android 6, 7, and 8:
1) Open your app, go to the activity that you want to test restoring, and then leave it by pressing the Home button
2) Open the Settings app, go to System -> Developer Options, then tap on "Running Services"
3) Tap on "Show Cached Processes" at the top right, then find your app in the list, tap on it, and then tap the "Stop" button.
4) Use the recent apps list to return to your app. It should relaunch the whole app on the activity that you had previously left it from.
I've found this to be sufficient to fully kill the app, including any app delegate stuff and the C/C++ native code state, and then test relaunching it with a saved activity state... This effectively replicates what happens when the user leaves the app for a while and then the system kills it to save memory, battery, or whatever.
To test the onSaveInstanceState and onRestoreInstanceState events you can use the SetAlwaysFinish utility (see link below). It uses a hidden system setting called Always Finish to change the behavior of the Android system. With the Always Finish option enabled, the Android OS will immediately unload any activity that moves from the foreground to the background, triggering its onSaveInstanceState event. Then, when the system needs the activity again, it is forced to reload it triggering the onRestoreInstanceState event.
The advantage of this method compared to killing the process is that it's easier and you get finer control (activity level rather than process level).
See the blog post below for more details on the tool and how to use it:
http://bricolsoftconsulting.com/how-to-test-onsaveinstancestate-and-onrestoreinstancestate-on-a-real-device/
The Always Finish feature is also present in the emulator in the DevTools app under Development Settings > Immediately destroy activities. However, the DevTools app does not work outside of the emulator.
You can use the setting "Don't keep activities" in developer settings or kill the app process by yourself.
To kill the process, open the activity you want to test, then press home button to send your app to background, and then, using the DDMS in Android Studio (Android Device Monitor), select the process and then stop the process (as seen in the image below). Your app was killed. Now, open your app again (accessing the list of open apps). Now you can test the killed state.
Lets clarify your question.
But before we do that here is a fact about onSaveInstanceState - its gets called for various reasons such as:
orientation change
going from foreground to background (by clicking home or launching another activity or clicking recents)
system is under low memory
Now, if your question is "how can i simulate the calling of onSaveInstance for just testing purposes" then Theo and Ted's answer is correct. Both changing developer settings option or pressing home will result in onSaveInstance being called.
But so would just changing orientation (as you noted in your question) - which leads me to believe you might be asking "how can i simulate calling of onSaveInstance method when system is under low memory pressure"
The short answer to this question is there is no automated way to simulate low memory condition. The above mentioned techniques only simulate calling of the onSaveInstanceState method not low memory conditions per se
Couple of caveats here.
The first caveat to this is that under extreme conditions the kernel will "uncleanly" kill your process to claim memory - meaning onSaveInstanceState will never be called. In this situations testing onSaveInstanceState is moot. There isn't much you can do about this scenario but the good news is that its a very rare event esp. for foreground activities.
The second caveat is that ActivityManager can reclaim your activity's resource by "killing it cleanly" i.e. your onSaveInstance will get called. This happens to activities that are not in foreground (i.e. not visible to the user so already in stopped state) and the system is under memory pressure.
On this second caveat, again you can't simulate this condition automatically. It can be done if you start bunch of heavy duty activities manually and hope the ActivityManager is forced to recycle one of your activities.
The bigger point to remember here is that there is no need to simulate low memory condition. As long as you are simulating how onSaveInstanceState is called you are automatically testing the condition where it might be called for low memory situations. And the easiest way to trigger this method is to change orientation on the emulator (ctrl-f11). And if you are using an actual device to temporarily change the developer settings ("Don't keep activities")
From android doc, http://developer.android.com/reference/android/content/ComponentCallbacks.html#onLowMemory()
This is triggered by the system. I think you can set the device ram size lower during creating an android virtual device. (In Hardware, choose "Device ram size")
The simplest solution which works for me is just change the orientation of the device (you can do that regardless you're using AVD, Genymotion or any other emulator). By default system will recreate Activity by calling onDestory followed by onCreate.
Ensure Activity has not defined below attribute on AndroidManifest.xml
android:configChanges="orientation"
if you have an android app that has more than one Activity, and Activity A starts B, so if Activity b crashes the process is killed but is revived by android OS and starts Activity A again instead of just shutting down the app, why ?
You're complaining that Android will attempt to recover your app's state gracefully after a crash? ;)
This is the result of Android's resource management and the Activity lifecycle at work. Keep in mind that a single task can be composed of a number of Activities that may span several processes or apps. As outlined here: http://android-developers.blogspot.com/2010/04/multitasking-android-way.html Android processes don't shut down "cleanly" in the traditional *nix process sense. Your app's components receive lifecycle events but after a certain point the app can be killed without further warning so that the system may reclaim its resources.
For example, a user might be browsing the web, click a youtube link launching the youtube app, then click a share button to launch their favorite social networking app and post the video link. This is all part of the same task; if the user presses back several times they'll come back to the page in the browser that they started from.
Once you start up the social networking app, the system might decide that it's running low on memory and it's going to kill off the browser's process to free up more. (After all, it's not in front and the user won't notice.) When the user presses the back button to return to the browser Activity it gets restarted and reconstructs the last state where the user left it. At worst the user experiences a short delay while things reinitialize.
But this same sequence of events restoring a previous Activity state can happen even within the same app in the same process. In your scenario, Activity B closed as the result of the crash. So the system does exactly what it always does - it returns to the previous Activity: Activity A. But Activity A's process isn't still around (it crashed!) so the system restarts it and it can reconstruct its previous state.