Android ground service

Update : I did not find the correct solution to the problem. I came up with a method to automatically reconnect to a previous Bluetooth device at any time when the connection is lost. This is not perfect, but it seems to work quite well. I would like to hear more suggestions on this subject.

I have the same problem as in this question: A service killed while retaining a lock during a call and after calling startForeground , including a device (Asus Transformer), (30-45 minutes), using track lock, using startForeground () and that The fact that the problem does not occur if the application is open when the screen turns off.

My application supports the Bluetooth connection with another device and sends data between them, so it must be active at any time to listen to the data. The user can start and stop the service at his discretion, and in fact this is the only way I implemented the start or stop of the service. As soon as the service restarts, the Bluetooth connection with the other device will be lost.

According to the answer in the related question, startForeground () reduces the likelihood that the service will be killed, but will not prevent it. "I understand that, for example, I saw many examples of other applications that do not have this problem (for example, Tasker) .

The usefulness of my application will be greatly reduced without the ability to start the service until the user stops. Is there any way to avoid this?

I see this in my logcat whenever the service is stopped:

ActivityManager: No longer want com.howettl.textab (pid 32321): hidden #16 WindowManager: WIN DEATH: Window{40e2d968 com.howettl.textab/com.howettl.textab.TexTab paused=false ActivityManager: Scheduling restart of crashed service com.howettl.textab/.TexTabService in 5000ms 

EDIT: I should also note that this is not like the other device I'm connected to: HTC Legend works with Cyanogen

EDIT: Here is the result of adb shell dumpsys activity services :

 * ServiceRecord{40f632e8 com.howettl.textab/.TexTabService} intent={cmp=com.howettl.textab/.TexTabService} packageName=com.howettl.textab processName=com.howettl.textab baseDir=/data/app/com.howettl.textab-1.apk resDir=/data/app/com.howettl.textab-1.apk dataDir=/data/data/com.howettl.textab app=ProcessRecord{40bb0098 2995:com.howettl.textab/10104} isForeground=true foregroundId=2 foregroundNoti=Notification(contentView=com.howettl.textab/0x1090087 vibrate=null,sound=null,defaults=0x0,flags=0x6a) createTime=-25m42s123ms lastActivity=-25m42s27ms executingStart=-25m42s27ms restartTime=-25m42s124ms startRequested=true stopIfKilled=false callStart=true lastStartId=1 Bindings: * IntentBindRecord{40a02618}: intent={cmp=com.howettl.textab/.TexTabService} binder=android.os.BinderProxy@40a9ff70 requested=true received=true hasBound=true doRebind=false * Client AppBindRecord{40a3b780 ProcessRecord{40bb0098 2995:com.howettl.textab/10104}} Per-process Connections: ConnectionRecord{40a76920 com.howettl.textab/.TexTabService:@40b998b8} All Connections: ConnectionRecord{40a76920 com.howettl.textab/.TexTabService:@40b998b8} 

And the output of adb shell dumpsys activity :

 * TaskRecord{40f5c050 #23 A com.howettl.textab} numActivities=1 rootWasReset=false affinity=com.howettl.textab intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.howettl.textab/.TexTab} realActivity=com.howettl.textab/.TexTab lastActiveTime=4877757 (inactive for 702s) * Hist #1: ActivityRecord{40a776c8 com.howettl.textab/.TexTab} packageName=com.howettl.textab processName=com.howettl.textab launchedFromUid=2000 app=ProcessRecord{40bb0098 2995:com.howettl.textab/10104} Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.howettl.textab/.TexTab } frontOfTask=true task=TaskRecord{40f5c050 #23 A com.howettl.textab} taskAffinity=com.howettl.textab realActivity=com.howettl.textab/.TexTab base=/data/app/com.howettl.textab-1.apk/data/app/com.howettl.textab-1.apk data=/data/data/com.howettl.textab labelRes=0x7f060000 icon=0x7f020000 theme=0x0 stateNotNeeded=false componentSpecified=true isHomeActivity=false configuration={ scale=1.0 imsi=0/0 loc=en_CA touch=3 keys=2/1/1 nav=1/2 orien=L layout=0x10000014 uiMode=0x11 seq=6} launchFailed=false haveState=true icicle=Bundle[mParcelledData.dataSize=1644] state=STOPPED stopped=true delayedResume=false finishing=false keysPaused=false inHistory=true visible=false sleeping=true idle=true fullscreen=true noDisplay=false immersive=false launchMode=2 frozenBeforeDestroy=false thumbnailNeeded=false connections=[ConnectionRecord{40a76920 com.howettl.textab/.TexTabService:@40b998b8}] 

...

 Proc #15: adj=prcp /F 40e75070 959:android.process.acore/10006 (provider) com.android.providers.contacts/.ContactsProvider2<=Proc{40bb0098 2995:com.howettl.textab/10104} Proc #16: adj=bak+2/F 40bb0098 2995:com.howettl.textab/10104 (foreground-service) 

They show that the service is running in the foreground.

+63
android service foreground
Jul 11 '11 at 2:23
source share
2 answers

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 #31: adj=prcp /FS trm= 0 2205:tunein.service/u0a10068 (fg-service) 

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 #31: adj=bak /FS trm= 0 2205:tunein.service/u0a10068 (fg-service) 

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 
+160
Jan 12 '13 at
source share

If he says "no longer wants ...", then this process does not have an active service in it, which is currently in startForeground () state. Make sure that your call actually succeeds - that you see the notification sent, there are no messages in the log complaining about anything, etc. Also use the "adb shell dumpsys activity services" to look at the status of your service and make sure that it is really marked as foreground. In addition, if this is correct, then in the output “Adb dumpsys activity dumpsys” you will see in the section showing that the OOM-solution of processes, which your process is at the foreground because of this service.

+5
Jul 11 2018-11-11T00:
source share



All Articles