I've been digging the web in quest of finding nice, androidish solution for this concrete problem, but havent found one, so here I am, posting my first question on StackOverflow.
To elaborate on my problem, I have a full-fledged aidl service, to which some other processes bind. My service will allocate some resources for each of process connecting to it, and I want to make this statement bold, the resource allocation is made for process, I make some kind of a session tracking, where getCallingPid() and getCallingUid() play a role of session identifiers.
So the problem here is that Android will never tell us if an application which was bound to us went away for some reason, so the system resources allocated for that destroyed process would be wasted away by being held by our service.
One solution that I found somewhat feasible is just to poll ActivityManager.getRunningAppProcesses and calculate set difference between current and previous snapshots, but this method looks really dirty.
Could anyone suggest some better method to do this? I'd be really grateful!
Thanks,
Giorgi
As far as I'm aware, Android won't tell you when processes are killed.
I suspect the only method is to get a list of running applications every x seconds or minutes, and keep track of the applications that way. I think this is what you already suggested in the question as well.
It's not pretty, but it's likely one of the only ways to do it.
Related
There is a solution for an android application to hold two sockets, which, from my point of view, is a very bad solution. Because sockets strongly devour all the resources of the phone. Does anyone have arguments for and against this decision?
answering question: yes, it's possible to keep multiple socket connections
and quoting from question:
sockets strongly devour all the resources
Thats simply not true... Probaly your code isn't well written and need some optimisation, put some logs and check all your operations aren't called multiple/too much times and collections keeping items aren't growing infinitely. And last, but maybe most important: be aware of memory leaks, you may occur/introduce some. Use LeakCanary for inspecting this
Alright so I'm going to try to explain one problem at a time so you can understand the issues I'm having and hopefully someone will be able to tell me hoe to fix it. So my app runs perfectly but my users have been complaining of high ram usage and on average it runs any where from 120mb to 200mb IDLE which I agree isn't right so I went ahead and remembered a trick I used in a previous project and that was this line of code android:hardwareAccelerated="false". This removes about 10mb of ram per activity but I'm still sitting at about 90mb of usage so i went and looked a little harder and found this android:process=":ProcessName"> which takes my app from using 100mb to a mere 8mb of ram. But I'm facing a problem while doing this and that is the fact that I have a LocalBroadcastManager in a service activity that sends data to my MainActivity and when these two have different processes they don't communicate with each other, and if I combine them into the same process the usage spikes yet again. So I'm kinda stuck what to do at this point and I refuse to use the Android Memory debugger because it doesn't tell me jack crap about what my code is doing wrong. Quite literally I have 5 text views and an imageview inside of my MainActivity so I know its not that intensive by any means! If anyone needs code please let me know but I figured someone really didn't need to look at the code to answer this!
You wrote:
But I'm facing a problem while doing this and that is the fact that I have a LocalBroadcastManager in a service activity that sends data to my MainActivity and when these two have different processes they don't communicate with each other, and if I combine them into the same process the usage spikes yet again.
You can keep your Service in a separate process and bind to it from your app's first process, via IPC, inter-process communication.
See:
http://developer.android.com/guide/components/bound-services.html
There are different ways to do IPC. The Messenger option might be a good starting point for you:
http://developer.android.com/guide/components/bound-services.html#Messenger
From the documentation:
If you need your service to communicate with remote processes, then you can use a Messenger to provide the interface for your service. This technique allows you to perform interprocess communication (IPC) without the need to use AIDL.
Is there any way the android system can inform a service that an activity or a task in the system(not only my activities/tasks!) has somehow changed (e.g. another activity is brought to the front or is stopped)? This is to avoid polling the same information, of course.
There is an identical question here, but it was asked 3 years ago, so in the meantime, maybe someone has an answer to this? As a supplement to this question: If the answer is no, is there any way someone could enhance this feature by, let's say, low-level programming or something?
No, there is no general solution. You can only record this information in the lifecycle methods of your own activities. And starting in Android 5, even polling does not work. ActivityManager#getRecentTasks() was nerfed. From the docs:
This method was deprecated in API level 21. As of LOLLIPOP, this method is no longer available to third party applications: the introduction of document-centric recents means it can leak personal information to the caller. For backwards compatibility, it will still return a small subset of its data: at least the caller's own tasks (though see getAppTasks() for the correct supported way to retrieve that information), and possibly some other tasks such as home that are known to not be sensitive.
Since this is considered a security issue, you can bet that if there is a low-level way to do it, Google will eventually find out and break it.
Isn't what you want covered already by the activity lifecycle events?
Aren't onPause() and onResume() sufficient?
i am feeling lazy sorry, try this logic.
check this post. what you would want to achieve here is record all the Tasks running currently; and in a loop you keep checking, you will be notified when a task die by checking the overall running Task, loop through and you will know who died- but this is limited not all versions, and some people will tell you, it is not meant for that.
I am doing some sort of benchmark for sqlite android. If I were to pre-load total of 120k before executing, will most device have enough memory? While the queries are executing, there are also other threads that are going on so memory might be the problem. How can I make use of the onLowMemory() method? There doesn't seem to be much examples on using that method. Thanks for any advice.
Making use of the method is as easy as overriding it in your Activity.
However, read the documentation carefully:
This is called when the overall system is running low on memory, and
would like actively running process to try to tighten their belt.
While the exact point at which this will be called is not defined,
generally it will happen around the time all background process have
been killed, that is before reaching the point of killing
processes hosting service and foreground UI that we would like to
avoid killing.
Applications that want to be nice can implement this method to
release any caches or other unnecessary resources they may be holding
on to. The system will perform a gc for you after returning from
this method.
I'm not sure (and the docs don't define) if "background process" includes AsyncTask instances and services, or just backgrounded applications, but I would guess so.
So, when this method is called (if it is ever called) the System has already killed everything it could (with lower priorities than your Activity) and now asks you to release any unnecessary resources in memory.
So, If you want to react on low memory, this might be too late already.
As for the general question if most Android devices would run out of memory, I don't know. The problem is, that devices vary a lot.
I also find it hard to imagine any real live situation, in which you would need to pre-load (or stack) 120k queries before executing. You could easily stack 200 and commit those, than stack another 200 and so on.
I'm not sure why you need to benchmark this, but please don't execute 120k queries for default entries in your applications database.
You can deliver your application with a filled database and copy it over from the assets/-folder. See android-sqlite-asset-helper
I've an application that has some foreground activities and also a service that updates some widgets.
The problem is that, as the process remains for the service, the memory from the other activities ,if they are opened, is never reclaimed.
Looking at that response from Roman Guy it seems that can be normal. But it is? For how much time android keeps the resources of not used activities? They can live for hours?
How can I know easily if the activities are leaked or are simple not reclaimed? I've tried with a program from AndroidMarket (FreeMemoryRecover) and it's cleared but I suspect that it kills the process and then restart the service...
Any help or suggestion will be heavily appreciated.
Note 1: I've investigated with a HeapDump + Eclipse MAT and I don't see strange references holding my activities
Note 2: I've already asked some questions about this problem:
Post 1
Post 2
The ability for Android to have multiple Activities, in different states, is a design principle as it allows users to quickly switch between activities without consciously having to shutdown whatever they were doing before. They can then quickly return to a previous activity.
If Android needs to pause an Activity, and quickly unpause it, it's going to need to keep the Activity's resources available to it.
If the memory is part of a terminated Activity, then it's leaked (very unlikely as the Linux kernel will reclaim all memory that was used when the process terminates), else it's either being actively used or is potentially about to be used.
What is that concerns you about this memory?
I would try the following :
Launch your app play with it to be sure it is fully loaded and use as much memory as it can.
Then hit the home button and launch the navigator, open techcrunch.com, lemonde.fr, youtube.com, dailymotion.com, launch a video from youtube, open up and play angry bird and last but not least open up a pdf document.
After that Android will have needed the memory back quite for sure. If your app is still there, you might have a problem, if its not, then everything went smoothly.
By the way, good on you to put so much concern in being a good citizen in AndroidLand !!
See my comment below your question.
See Romain Guy's post about Android memory leaks.
Specifically, look at the comment on the solution in the Launcher app. (look at unbindDrawables code here)
Use Context.getApplicationContext() whenever possible instead of your activity's context.