I'm writing an android app that involves one AudioTrack and one AudioRecord. They run in two different threads, and both of them need to continue to run and not being killed when low memory/CPU even if the app is running in the background. I searched about this and I know I could probably use AsyncTask (just like in music streaming app). However, I'm no exactly sure how to do it because the thread that runs AudioTrack is first created (once a certain button on the main activity is pressed), then this thread will create another thread that runs AudioRecord (by creating a Runnable).
I searched about this and I know I could probably use AsyncTask (just like in music streaming app)
No. Your issue is not the threads, but the process.
both of them need to continue to run and not being killed when low memory/CPU even if the app is running in the background
Strictly speaking, that is not possible. The closest that you will get will be to use a Service that in turn uses startForeground() to indicate that it has foreground priority. That will minimize the probability that Android will terminate your process due to low memory conditions, but it will not eliminate it.
Also, please note that you will need the CPU to be powered on to perform your audio tasks. That, in turn, will require a WakeLock. This is going to seriously hammer the user's battery, to the point where you should advise users to keep the device on a charger. That will be particularly important in the future, where the "Doze mode" of the upcoming "M" Android release will block your use of WakeLocks if the device is idle, unmoving, and not on a charger.
Related
It is meant for Services, Activities, Fragments and so on. Does it only occur in the case of some heavy operations in the UI thread?
Also just wondering - which method of those components can throw/rise ANR?
In Android, the system guards against applications that are insufficiently responsive for a period of time by displaying a dialog that says your app has stopped responding. At this point, your app has been unresponsive for a considerable period of time so the system offers the user an option to quit the app
Generally, the system displays an ANR if an application cannot respond to user input. For example, if an application blocks on some I/O operation (frequently a network access) on the UI thread so the system can't process incoming user input events. Or perhaps the app spends too much time building an elaborate in-memory structure or computing the next move in a game on the UI thread. It's always important to make sure these computations are efficient, but even the most efficient code still takes time to run.
In Android, application responsiveness is monitored by the Activity Manager and Window Manager system services. Android will display the ANR dialog for a particular application when it detects one of the following conditions:
No response to an input event (such as key press or screen touch events) within 5 seconds.
A BroadcastReceiver hasn't finished executing within 10 seconds.
Picked out the parts which are relevant to your question.
But for more information, check out the android doc where I got this from.
And ANR usually occurs when you are running long running operations (ex. networking) on the main thread.
I have a max priority thread running inside a service which constantly reads data from a BluetoothSocket InputStream. The thread also normally works and should work while the screen is locked.
But, since Lollipop, I started experiencing "stalls" and "slow-downs" in the thread at the moment the screen gets unlocked (wake up), which causes me to lose data from the Bluetooth device I communicate with. Even running service as a foreground service doesn't help. Is there any solution for this, or maybe even somebody from Google I could talk to about the changes introduced in Lollipop.
Also to note, since my app is used in experimental conditions by very small amount of people (it's not even on PlayStore), a partial solution for my problem would be completely preventing the phone to be locked by the power button, if possible. Thanks.
Here's how my application works:
The Launcher activity starts a service in the foreground which monitors clipboard changes and fires up the launcher activity everytime a specific kind of string is copied. I'm new to Java programming, I've tried to use all the best practices in the application(using worker threads and keeping the UI thread from hiccupping) and so far everything is butter smooth. The problem is RAM consumption, on a fresh start of the app(after Service is started) the app reports 24M memory consumption in the android running processes. Here's where the erroneous behavior lies:
- The Memory Monitor in Android Studio reports something else
- So does the adb shell dumpsys meminfo mypackage command
Screenshots of both have been attached
These behaviors are incomprehensible for me. 50M is a lot of RAM. Also whenever the Launcher activity is launched by the Service, the app consumes around 1M more memory than it is already using. Can anyone help me debug this?
Thanks
The problem is likely a result of how Android handles Services and
Activities running in the same application process:
As long as a (started) Service is running in the process, the "memory
priority" of the whole process is elevated above other processes that
are only running (background) Activities.
However, since Activities
are never recycled by Android even under memory pressure (contrary to
some statements in the official docs),
this effectively keeps your Activity alive much longer than necessary. This is essentially a shortcoming of Android's process model.
If your memory usage drops to a few megabytes after you force-kill your application process (and Android subsequently relaunches your Service), or if the memory usage is different depending on whether you leave your activity by pressing the home or back button, this confirms that you are facing this problem.
If you really depend on your Service continuously running in the background and want to minimize memory usage, you could try to move it to its own process (where memory-intensive UI resources like Views in Activities would never be loaded).
Of course, this also increases overhead; you might be better off by just keeping your implementation the way it is. Android will still kill your process under memory pressure, and will later relaunch your Service (but not your Activities), which will minimize your memory usage without any intervention.
Save the heapdump as a HPROF file and convert it to an extension that Java Profiler can read
Then you will be able to see what is using so much ram
I need to test serialization\deserialization of application in next cases:
app was in background a lot of time (idle mode) and was killed by GC;
app was in background and was killed by GC by reason of resources (memory\cp) lack;
On some devices it can be simulated by launching 1-2 games.
But on quad-core devices with 1gb memory it's very-very hard with 4-10 heavy games and takes a lot of time.
I try to implement some demo where emulating loading on resources:
create bitmaps arrays
create objects arrays
launch a lot of services
launch a lot of activities
But no result, application still works (even on old devices) and my demo is crashed with OutOfMemoryException.
How can i simulate high load in demo application?
Thanks!
Well, the "GC" is actually abused "Out Of Memory Killer" and that kills the applications as if by signal 9. In rooted device you should be able to invoke kill(1) command from shell or kill(2) function from native library (I am not sure whether it's bound to Java) and kill your application whenever you want.
The system normally calls onStop in the Activity when it's going to background and than kills the application without further warning and without chance to react. So if you leave the application and kill it, it's appropriate simulation of it being OOM-killed.
Install any memory cleaner on play store. I install this : easymemorycleaner
once u cleaned your memory. Your stored variable inside memory will be gone. Unless you stored data in Parcelable. It will be persistent.
I need my Android app to save it's state to disk when its activity is put in the background or killed. It's been suggested that I start a thread when onPause() is called and perform any expensive I/O procedures there (see Saving/loading document state quickly and robustly for image editor).
In what situations will the OS kill the thread and how commonly do these situations occur?
I assume it will be like how Activities are dealt with where the OS can arbitrary decide to kill the thread but will mostly only do this when resources are extremely limited. It would be nice to find some specific documentation of this though.
From playing around, with some test code, a background thread started in onPause() will run indefinitely in the background on my device (I tried loading lots of apps and couldn't get it to be killed).
For my specific app, I'm writing a bitmap editor where I'm using the Command pattern and the Memento pattern to allow undo and redo of edits. I'd like the user to be able to undo/redo their edits even e.g. the user gets a phone call and the activity is killed when it is put in the background. The best solution I can think of is to use a background thread to constantly save my command and memento objects to disk during application use and to finish up saving any objects that are left in a background thread if onPause is called. In the worse case, if the thread is killed I'll only lose some edits.
In what situations will the OS kill the thread and how commonly do these situations occur?
The OS will not kill the thread, unless it is killing the process -- Android does not do anything with threads you create yourself. If you are the foreground process, you will not be killed. The odds of Android killing the process within a few seconds of you losing the foreground (after onPause()) are miniscule. The documentation on process lifetime -- what there is of it -- can be found here.
Your thread may be killed at any time after the activity is destroyed, or it may never be killed. Depending upon such a thread is very bad form -- you could end up with a half-completed operation, or with a thread that sticks around forever.
If you wish to perform a background operation that continues even when there is no foreground activity, you almost always want to run it inside a Service. On the other hand, the service is less likely to be killed, but there's no guarantee unless you use "startForeground". This will end up displaying a notification to the user that something is happening in the background, but as far as I know it's the only way of running an asynchronous background thread that is guaranteed not to be killed.
Honestly, the right answer is to make sure that there is never any temporary process state that will take a long time to save. If you are having to write a large file to reflect a few user changes, consider maintaining a "transaction log" which you can use to create a restartable save operation. Given this, you can safely run your saves in a service and know that even if it gets killed, it will be automatically restarted when resources become available.
Normally, saving your state in onPause is the right thing to do if it's quick. I don't think it's clearly documented when a process is killed, but you sometimes see it in logcat when you run some demanding apps (say, after running Google Earth and Browser).
There's also an option in the Android DevTools to automatically destroy activities as you navigate away from them, although that probably doesn't extend to the process. (DevTools are on the emulator, and on some rooted phones).
I think your approach sound reasonable - use a low-priority thread to constantly update the save data, and give it normal priority in onPause, and set a flag in onPause that tells it to terminate after it finishes.
Obviously, you'll need to make sure you don't run into synchronization issues if you get to onResume immediately after onPause (i.e. while the thread is still busy saving).