What could make a BroadcastReceiver to get its intents so late? - android

Background
We have a large app that has various features, uses multiple libraries, and handles phone calls using a BroadcastReceiver:
<receiver android:name="....PhoneBroadcastReceiver">
<intent-filter >
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
<intent-filter >
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
The problem
Recently I've noticed that if we close the app using the recent-tasks, the BroadcastReceiver receives intents quite a lot of time (3-5 seconds) after the phone starts ringing.
This is a problem, because the app needs to handle the phone calls right away.
What I've tried and found
In a POC, it seems to work just fine. Even on one of my repositories (here), which is meant for phone call recording, if I add logs in the BroadcastReceiver instead of the real logic, I can see it gets handled right away. I even added all of the permissions of the large app into this sample app I've made (and granted them), and it still worked perfectly fine. Adding the libraries the large app uses could take a lot of time to add and test, sadly
I was thinking that maybe the class that extends from Application (or MultiDexApplication, to be precise) was taking too much time, so I added a log there (beginning of onCreate). It does indeed take a bit of time (a second or so), but the log is shown after a while, and the difference between it and the log of the BroadcastReceiver is very small. So the issue should be caused by something much deeper than the Application or the BroadcastReceiver.
I thought that maybe it's because we use multi-dexing. I tried to disable it but it didn't help. I don't think it can even affect it, as I've tried it on Android P on Pixel 2.
I tried to set the priority of the BroadcastReceiver. Tried to set it to 999 (which is the max allowed), and even to 2147483647 , but none of those helped.
I thought that maybe the OS is allocating a lot of memory for the app, which could take some time, but I know that other apps that listen to the same Intents (such as TrueCaller) work fine even after I close the app from the recent tasks. I also tested how much memory the app uses, and how much TrueCaller uses. The app uses average 33MB of total RAM on my Pixel 2, while TrueCaller uses 2MB . I got these values from the developer options screen, of "memory usage". Weird thing is that it tells the max RAM usage is huge (around 1GB) even when starting the app from scratch, but I never saw it in the profiler, not even close (around 200MB). I think this screen it not a reliable way to check the memory usage.
I thought that maybe excluding the app from battery optimizations could help, but it didn't. Even TrueCaller, which request this from users, don't really need it in this scenario. It works fine there without setting it.
The only thing that I think could be the reason for this, it the libraries the app uses. And there are a lot, but I wonder what could affect the app even before the class that extends Application is being called... Sadly there are so many that it would take a lot of time to add them all into POC project. I think I will do it, but I wonder if it can actually be the reason.
The questions
What could possibly affect the BroadcastReceiver to get its intent so late? Is it one of the things I've mentioned perhaps?
Why does the "memory usage" screen seem so unreliable and contradicting what I see on the profiler of the IDE ? Could it be the reason for the late Intent (huge memory allocation of the OS) ?
EDIT: I've noticed that some libraries initializations took too much time in the onCreate call of the class that extends Application, so I've put some of them in background threads, and some I've even removed.
Seems it's better, but still, the problem is that the app gets triggered too late after the phone rings, and so the issue still exists.

OK, seems that I was wrong, and that this Intent can be received a bit late, depending on the OS and maybe on how light the app is.
The reason that I think this way now, is that I've noticed that even TrueCaller doesn't always appear immediately. Sometimes it can take them a very long time too.
So the only way I think it's safe to listen to those intents, is programmatically and not via the manifest.
Meaning something like that in a foreground service:
telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
telephonyManager!!.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE)
What I can say, is that if the app has notification access permission granted, it has a very large chance of always being alive, so it won't need a foreground service.

Related

Android 6: App uses more memory each time it's started

Samsung Galaxy S6 with Android 6.0.0 and 6.0.1
My app runs fine, code analysis shows no mem leaks. SmartManager shows that the app uses ~40MB of memory. I kill the app (using the "currently running apps" overview--- not sure how that's called in English, sorry. The key on the bottom left of the phone, that shows a list of miniatures of all running apps...), then start it again.
Now SmartManager no longer shows ~40MB of memory for my app, but ... more. 50. 100. 400. It varies, but growing each time. After awhile, my app actually crashes with an OutOfMemoryException. Sometimes even with "out-of-memory while trying to throw an OutOfMemoryException"...
I have to de-install and re-install the app in order to reset its memory consumption. The same APK behaves correctly on all other phones I've tested with (e.g. S5 with Android 5.0). No idea what's causing this. No idea what could be causing this! Any help/hints/suggestions...?
Edit: Same behaviour on S5 with Android 6.0.1, but not on S5 with Android 5.0!
Edit2: Thanks, everyone who contributed. I still don't have an answer that I'm satisfied with, but a few ideas were mentioned that I will look into. Most people were focusing on the MemLeak issue, and while that sounds reasonable I'd like to stress that there is no leak occuring on Android 4 or 5, only 6. (I have yet to test 7.) Also, the leak only occurs when I forcefully kill the app (which I need to do at times to test proper shutdown and re-start behaviour), and only without a debugger attached (which makes testing/debugging this behaviour a pain in the backside).
The app starts one service as a bound service. Bound to the application context--- which according to the docs should clean itself up when the app stops.
Unfortunetely, time for this bounty is running out. So far, the above mentioned service seems to be the most likely source of my problem. As such, I will award Qamar the bounty, as he was the first to mention this both in the comments and his answer. The rest of you, a big THANK YOU and up-vote.
In Android Studio, click Android Monitor at the bottom of your screen. Click the tab Monitors. You see a graph of the memory that your app uses. Now click the item Dump Java Heap which is next to the garbage van. The system starts collecting the info and creates a dump file. You can open the file in the Analyze Tasks tab in the upper right of your Android Studio window. Press the green arrow to find classes that leak memory. When you click a leaking activity, you'll see a window Reference Tree. Go through the tree, finding the member that has depth zero. That's the memory leak.
Analyse your code and images if anything wrong you are doing itself. Like very large images of drawables. make sure you correctly implement recycler or list views.
The following links may helpful to you.
Use leakcanary library to detect and make sure there is not leaks
Detect when user kill app from reccent apps
Invoke gc from memory monitor comes with Android Studio for correct value of memory usage cause gc not run frequently.
Use large heap size. <application android:largeHeap="true" in manifest
Use app context to start servicesstartService(new Intent(getApplicationContext(),MyService.class));
Your application has some threads are timer tasks that are creating again and again and they are utilizing many resources related to networks so your heap size is consistently increasing and at sometime your app is out of memory and crashes.
Some people think that task killers are important on Android. By closing apps running in the background, you’ll get improved performance and battery life – that’s the idea, anyway. In reality, task killers can reduce your performance.Android isn’t Windows and doesn’t manage processes like Windows does. Unlike on Windows, where there’s an obvious way to close applications, there’s no obvious way to “close” an Android application. This is by design and isn’t a problem.When you leave an Android app, going back to your home screen or switching to another app, the app stays “running” in the background. In most cases, the app will be paused in the background, taking up no CPU or network resources. Some apps will continue using CPU and network resources in the background, of course – for example, music players, file-downloading programs, or apps that sync in the background.When you go back to an app you were recently using, Android “unpauses” that app and you resume where you left off. This is fast because the app is still stored in your RAM and ready to be used again,hence consuming no further resources.
Task killers like smart manager think they know better than Android. They run in the background, automatically quitting apps and removing them from Android’s memory. They may also allow you to force-quit apps on your own, but you shouldn’t have to do this normally.If a task killer removes an app from your RAM and you open that app again, the app will be slower to load as Android is forced to load it from your device’s storage.Further s6 has Smart Manager and could be used as a widget or shortcut to battery and storage settings,however you should avoid using the Clean All optimization feature. This feature is said to improve device performance – as the Clean Master app aims to do – but its actual impact is questionable.
Meaning while still sometimes you kill an app it can still leave the traces on heap so next time when you start it ,it will show varyingly more amount of storage used which also fails the notion of default maxMemory() and the app ultimately might crash.Further such leaks are difficult to track as they aren't directly associated to app you killed in first instance.But still sometimes even after killing app, certain features like resources attained may keep running in background without even the app even knowing about them.i.e unnoticeable leaks.Thus you may want to use maxMemory()
which can be invoked (e.g., in your main activity's onCreate() method) as follows:
Runtime rt = Runtime.getRuntime();
long maxMemory = rt.maxMemory();
Log.v("onCreate", "maxMemory:" + Long.toString(maxMemory));
This method tells you how many total bytes of heap your app is allowed to use.
Optimal Behaviour:
An app can stay "running" in the background without any processes eating up your phone's resources. Android keeps the app in its memory so it launches more quickly and returns to its prior state. When your phone runs out of memory, Android will automatically start killing tasks on its own, starting with ones that you haven't used in awhile.
What You Should Do Instead
That said, not all apps are created equal. Many of you have used task killers in the past and actually found that after freeing up memory, your phone works a bit better. It's more likely that this is because you've killed a bad app that was poorly coded, and (for example) keeps trying to connect to the internet even when it shouldn't. Any performance increase you experience is more likely because you killed the right app, not because you freed up loads of memory (or, in many cases, it's just placebo). Instead of killing all those apps, find out which ones are actually causing the problems.using a task killer to deal with a misbehaving app is like using a shotgun to kill a fly – you may fix your problem, but you’re inflicting a lot of other damage in the process.Now
since S6 has 3 gigs of ram,it should'nt have problems,however implementation of smart manager can cause problems with some apps and isnt necessarily android version dependent.Also bare that heapsize tends to be based more on screen resolution, as higher-resolution screens tend to want to manipulate larger bitmaps.
Instead of using a task killer in this situation, you should identify the bad app and uninstall it,or debug it, replacing it with an app that works properly. To pin down the app that’s misbehaving, you can try the
Watchdog Task Manager app
– it will show you which apps are actually using CPU in the background, not which apps are harmlessly being stored in memory.
Captivating Fact:
CyanogenMod, the popular community-developed Android ROM, won’t even
accept bug reports from users using task killers, saying that they
cause more problems than they solve.
A probable cause of issue
if you can try following at once,first of all go to settings >sounds and notifications > App notifications > select smart manager and select hide content on lock screen
then again back to settings go to lockscreen and security >Device security >Disable KNOX active protection and deactivate the anti malware option below KNOX active protection
in lock screen and security go to other security settings > disable send security reports and go down to ussage data access> disable smart manager so after that restart your device.Now see if the app works Also see performace concerns with s6

Can an Android Webview keeps alive on background?

I have the following situation and I dont know exactly what it could be:
I have a webview in my app wich among other things periodically sends and ajax request to a server which response may trigger the play of a sound.
This work perfect, the only weird thing is that, sometimes when the app is on background the sound is played, it would seem that the webview is still executing, but I thought that it would be killed when the app goes to background.
The most weird thing is that sometimes the app has been on background for several hours before the sound is played(so I assume that it is restarted somehow)
I think that the issue is related with the RAM and the system deciding to it free or not. Because it happens mostly in newer devices which are used mostly for testing(a lot of RAM) and also in old devices with fewer RAM it does not happen.
Now, is possible to prevent this?
Thanks!
The best thing to do is to stop all the periodic actions your application does on OnPause and start them again on OnResume. Override these methods on your fragment and it should work.

Don't keep activities - What is it for?

The title is pretty self-explanatory. I understand what this developer option does.
What I don't understand are the following points:
Why was that option introduced, in the first place?
After all the changes that the framework has seen throughout the years, is it still useful?
I am eager to know the reasons behind this option.
I believe it's a feature used for debugging purpose.
From the Titanium doc:
Don't keep activities under the Developer Options menu. When this
option is enabled, the Android OS will destroy an activity as soon as
it is stopped. It is intended to help developers debug their apps. For
example, it can simulate the case that Android will kill an activity
in the background due to memory pressure. In normal use, it is not
recommended to turn this option on because this may lead to unexpected
issues on the apps, such as freezes, force closes and reboots.
It sounds like it basically helps testing deterministically how your app behaves when the OS shuts it down due to any reason (out of memory and so on).
So, this replied to point 1. Point 2 is: Yes, I guess :)
EDIT: further references
On SO How to know "Don't keep activities" is enabled in ICS?
an interesting thread about that on androidcentral (reply from MagouyaWare)
The Android framework may destroy your activity any time it's in the background or backstack, and you should write your activities so they behave correctly when this happens. Exactly what that entails varies depending on what the activity does, but it generally includes implementing onSaveInstanceState(...) and restoring any previous state in onCreate(...).
The "don't keep activities" developer option simply changes the framework's behavior so it will always destroy your activity when it goes into the background or backstack. This allows you to test how your activity responds to what is normally a rare occurrence.
A link cited in another answer says:
In normal use, it is not recommended to turn this option on because this may lead to unexpected issues on the apps, such as freezes, force closes and reboots.
This is incorrect. If your activities are written properly, the only effect of having "don't keep activities" turned on should be (possibly) slightly higher battery and CPU usage from constantly saving and restoring persistent state. Any apps that exhibit "unexpected issues" or force closes when this option is on are broken and need to be fixed. As a developer, I habitually leave "don't keep activities" turned on all the time. I've seen a lot of buggy apps, even some of Google's own. But it's never caused a reboot, and I don't think there's any way it could.
I had at least two issues when this was enabled:
1) I was getting an error "Unable to complete previous operation due to low memory" that prevented uploading of any attachment to a website using Chrome, but not with Firefox. I found elsewhere that enabling the "Don't keep activities open" option could have been the problem - it was.
2) I was unable to move files to the SD card. Disabling the "Don't keep activities open" option got round this problem.
Also found elsewhere it can slow things up generally because caching is compromised.
Sometimes apps that I had moved to the SD card suddenly 'greyed out' and became inaccessible. Rebooting solved this, but was becoming an irritation. Too soon to tell if that was another problem caused by this 'feature'.
These problems (and issues with the microphone in Zoom) all started within the last month. I don't know how DKAO ever got enabled, but it's a no-no as far as I'm concerned.

Air for Android: Black Screen after device-alarm

I do have a problem and have very little to go on. I'm about to release an App (created with Air for Android As3) on the Samsung App Store and just got a list of issues that have to be resolved after the app has been tested by samsung staff before the app could be released.
I did manage to solve almost all of the issues, but 1 very important one is beyond me. They say the screen turns/stays black, when returning after the device alarm interrupted the app. This issue practivally happend on all their devices, including a group including the phones I own (e.g. Galaxy S3).
I do have "OnDeActivate" and "OnActivate" listeners in place that are there to pause the app, disable sound etc. if it loses focus, gets minimized etc., yet I checked on my devices and I can't reproduce this error. Meaning if the app gets interrupted on my device by the alarm, I can resume it without any problems. no black screens.
So the question is: Is there any way for me to fix that at all? I do have to work within AirForAndroid AS3 so I guess possibilities are limited. Any clues where I can look? Any listeners to set, or is there a way to maybe "force" the app to reinitialize or refresh the display? Or to listen for the system alarm? Help would be much appreciated. Thanks in advance!
I am trying to overcome the same issue, I read somewhere that setting the stage quality to something else on both the activate and deactivate events might solve the issue.
So just set your stage quality to medium or whatever different in the deactivate and set it back to what it needs to be in the activate.
This should make AIR snap out of that black screen for the alarm (I hope)
An app of mine is with this fix is currently undergoing testing on the Samsung App Store.
I hope it fixes it.
Good news, the dirty fix of toggling the stage quality seems to have worked for Samsung, it has not shown up in their latest certification report of my app.
by the way, this is not for a stage3D app, that's different
It's for a GPU app
When the app loses focus on Android (goes into background) it will lose the context, which among other things mean that you lose all the created graphics, cached objects and like.
You didn't specify what kind of app it is. If you're using Stage3D, that means you'll have to recreate all your textures, and if you're on plain old displaylist, you'll have to recreate any bitmaps that were created at runtime, and redraw your screen at least once (so the vector graphics get redrawn too).
Now, if you're using Starling, for example, it can take care of recreating context for you (there's a flag for enabling that), although you'll still have to recreate dynamically created bitmaps.

Android app gets stuck when I turn tablet - first timer

I'm first time developer for these types of devices, and UI in general, so I could be missing something basic and obvious.
Everything seems to work fine in the emulator, but I don't know how to simulate turning it.
So I tried running the app on my pandigital (white model - lowest of the low it seems), and each time I turn the Android, it freezes up. At least the UI freezes up, I believe the debug messages are still printing.
This is a home project, I don't have other devices to try it on.
Sorry for being so vague, it's an issue I have been a bit neglecting, trying to work on more interesting issues first, but it's an issue that is bothering me in the back of my mind.
Anyway, I have an Activity that starts up a thread, and creates a class which responds to various events, it implements: MainInterface and SurfaceHolder.Callback. Is there something else I should be handling? possibly?
Is there some specific call I get when the tablet is turned? I'd like to put a debug message in there.
My guess is that you state in your AndroidManifest.xml that this activity will handle rotation events itself (perhaps because you copied it from some project where the activity did do this), and that this statement is a lie, your activity actually makes no attempt to handle rotation.
If this is the case, a sound way to solve your problem is simply to remove the lying android:configChanges from your manifest.

Categories

Resources