Okey dokey. I went through hell and returned to this problem. Here's how to act. There are mistakes. This publication describes how to analyze implementation errors and solve problems.
Just to summarize, here's how it should work. The launch of the services will be regularly cleaned and terminated every 30 minutes or so. Services that want to stay alive longer than this should call Service.startForeground, which places a notification in the notification panel, so that users know that your service is constantly running and can potentially absorb battery life. Only 3 maintenance processes can designate themselves as foreground services at any given time. If there are more than three front-end services, Android will designate the oldest service as a candidate for cleanup and completion.
Unfortunately, there are bugs in Android regarding the prioritization of front-end services, which are triggered by various combinations of service binding flags. Although you have correctly designated the service as the foreground service, Android may terminate the service in any case if any connections to the services in your process have ever been made with certain combinations of binding flags. Details are given below.
Please note that very few services must be front services. As a rule, you only need to be a front-end service if you have a permanent or long-term Internet connection that can be turned on and off or canceled by users. Examples of services that require foreground status are: UPNP servers, long downloads of very large files, Wi-Fi file system synchronization, and music playback.
If you just periodically conduct a survey or wait on system broadcast receivers or system events, you would be better off not waking up your service on a timer or in response to broadcast receivers, and then letting your ministry die after completion. This is the so-called behavior for services. If you just have to stay alive then keep reading.
By checking flags on well-known requirements (for example, by calling Service.startForeground), the next place to look for is the flags that you use in calls to Context.bindService. The flags used for binding affect the priority of the target maintenance process in various unexpected ways. In particular, using certain bind flags may cause Android to incorrectly reduce your front-end service to a regular service. The code used to prioritize the process has been heavily modified. It is noteworthy that there are changes in API 14+ that can cause errors when using old binding flags; and in 4.2.1 there are certain errors.
The friend in all of this is the sysdump utility, which can be used to determine what priority the activity manager has assigned to your service, and to identify cases where it has assigned the wrong priority. Start the service and run the following command from a command prompt on your computer:
Adb shell dumpys activity processes> tmp.txt
Use notepad (not WordPad / Record) to examine the contents.
First, make sure that you have successfully completed your service in the foreground state. The first section of the dumpsys file describes the ActivityManager properties for each process. Find a line similar to the following that matches your application in the first section of the dumpsys file:
APP UID 10068 ProcessRecord {41937d40 2205: tunein.service / u0a10068}
Make sure foregroundServices = true in the next section. Do not worry about hidden and empty settings; they describe the state of activity in the process and do not seem particularly relevant for processes with services in them. If foregroundService is incorrect, you need to call Service.startForeground to make it true.
The next thing you need to look at is the section at the end of the file called "LRU Process List (sorted by oom_adj):". The entries in this list allow you to determine whether Android has truly classified your application as a front-end service. If your process is at the bottom of this list, it is the main candidate for the final extermination. If your process is at the top of the list, it is virtually indestructible.
Look at the line in this table:
Proc
This is an example of a foreground service that did everything right. The key field here is the "adj =" field. This indicates the priority that your process has been assigned to ActivityManagerService after everything has been said. You want it to be "adj = prcp" (visible foreground function); or "adj = vis" (a visible process with activity) or "fore" (a process with foreground activity). If it is “adj = svc” (maintenance process) or “adj = svcb” (deprecated service?) Or “adj = bak” (empty background process), then your process is a likely candidate for termination and will be terminated at least every 30 minutes, even if there is no pressure to restore memory. The other flags on the line are mostly diagnostic debugging information for Google engineers. Termination decisions are made based on adj fields. In short, / FS indicates the foreground service; / FA indicates the foreground process with activity. / B indicates background service. A label at the end indicates a general rule according to which a process is given priority. Usually it should match the adj = field; but adj = may be adjusted up or down in some cases due to bind flags when binds are active with other services or activities.
If you encounter an error with the binding flags, the dumpsys line will look like this:
Proc
Please note that the value of the adj field is incorrectly set to "adj = bak" (empty background process), which roughly corresponds to "please, please stop me now so that I can end this meaningless existence" for the purpose of the garbage collection process. Also note the (fg-service) flag at the end of the line, which indicates that “ground service rules were used to define the adj setting. Although the fg-service rules were used, this process was assigned a bak setting and he won’t live long.
So, the goal is for your process to always get "adj = prcp" (or better). And the method to achieve this goal is to set the anchor flags until you manage to avoid errors when assigning priority.
Here are the errors that I know of. (1) If ANY service or activity is ever associated with a service using Context.BIND_ABOVE_CLIENT, you risk that the adj = parameter will be lowered to "bak" even if this binding is no longer active. This is especially true if you also have bindings between services. Manifest error in the sources 4.2.1. (2) Definitely never use BIND_ABOVE_CLIENT to bind a service to a service. Do not use it to connect to work. The flag used to implement the BIND_ABOVE_CLIENT behavior is apparently set on the basis of each process, and not for each connection, so it triggers errors with service bindings, even if there is no active activity for servicing the binding with the flag set. There are also problems with prioritization when several services with service bindings are present in the process. Using Context.BIND_WAIVE_PRIORITY (API 14) in service bindings can help. Context.BIND_IMPORTANT seems like a more or less good idea when binding from Activity to a service. This leads to the fact that the priority of the process exceeds one level higher if the activity is in the foreground, without any obvious damage to the suspension or completion of the operation.
But in general, the strategy is to configure the bindService flags until sysdump indicates that your process has received the correct priority.
For my purposes, using Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT for action bindings for maintenance and Context.BIND_AUTO_CREATE | The .BIND_WAIVE_PRIORITY context for service-to-service bindings seems to be doing the right thing. Your mileage may vary.
My application is quite complicated: two help desks, each of which can independently support the state of service of the foreground, as well as the third, which can also accept the state of service of the foreground; two of these services are conditionally related to each other; the third is associated with the first, always. In addition, Activites run in a separate process (makes the animation smoother). Performing actions and services in the same process did not seem to make any difference.
The implementation of the rules for cleaning processes (and the source code used to create the contents of the sysdump files) can be found in the main android file
frameworks\base\services\java\com\android\server\am\ActivityManagerService.java.
Random chance.
PS: Here's the interpretation of sysdump strings for Android 5.0. I did not work with them, so make of them what you want. I believe that you want 4 to be “A” or “S”, and 5 to be “IF” or “IB”, and 1 to be as low as possible (probably below 3, since only 3 are supported three front service modes plan in the default configuration).
Example: Proc # : prcp F/S/IF trm: 0 31719: neirotech.cerebrum.attention:blePrcs/u0a77 (fg-service) Format: Proc # {1}: {2} {3}/{4}/{5} trm: {6} {7}: {8}/{9} ({10} 1: Order in list: lower is less likely to get trimmed. 2: Not sure. 3: B: Process.THREAD_GROUP_BG_NONINTERACTIVE F: Process.THREAD_GROUP_DEFAULT 4: A: Foreground Activity S: Foreground Service ' ': Other. 5: -1: procState = "N "; ActivityManager.PROCESS_STATE_PERSISTENT: procState = "P "; ActivityManager.PROCESS_STATE_PERSISTENT_UI:procState = "PU"; ActivityManager.PROCESS_STATE_TOP: procState = "T "; ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND: procState = "IF"; ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND: procState = "IB"; ActivityManager.PROCESS_STATE_BACKUP:procState = "BU"; ActivityManager.PROCESS_STATE_HEAVY_WEIGHT: procState = "HW"; ActivityManager.PROCESS_STATE_SERVICE: procState = "S "; ActivityManager.PROCESS_STATE_RECEIVER: procState = "R "; ActivityManager.PROCESS_STATE_HOME: procState = "HO"; ActivityManager.PROCESS_STATE_LAST_ACTIVITY: procState = "LA"; ActivityManager.PROCESS_STATE_CACHED_ACTIVITY: procState = "CA"; ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: procState = "Ca"; ActivityManager.PROCESS_STATE_CACHED_EMPTY: procState = "CE"; {6}: trimMemoryLevel {8} Process ID. {9} process name {10} appUid