8 ms·
If You're Programming a Cell Phone Like a Server, You're Doing it Wrong
- doublerebel 13y agoActual title "If You're Programming A Cell Phone Like A Server You're Doing It Wrong" is a much more accurate statement, and a different topic. On topic, this is why I prefer native (or at least non-webview) apps. The control over the connection and app lifecycle provides a better experience and better analytics.
- kevinbowman 13y agoGiven the "preload any data the user might need in the next 2-5 mins" statement, how do people suggest we handle live streaming of updates (eg commentary on a sports event)? Presumably websockets are ok as it's more of a "push" model for the network than a "poll" model?
- jaytaylor 13y ago> Presumably websockets are ok as it's more of a "push" model for the network than a "poll" model? This is seems incorrect - as I understand it, a websocket holds open a TCP connection indefinitely, which would require the radio to stay in its active state as long as the websocket remained open. See also: http://stackoverflow.com/questions/4456407/iphone-keep-websocket-open-in-background http://stackoverflow.com/questions/4456407/iphone-keep-webso...
- kevinbowman 13y agoThat's true, although I guess it's mostly listening as opposed to sending, which is possibly better? Although I realise there's probably some kind of "are you still there?" message from the cell tower.
- ryanpetrich 13y agoI can't speak for websockets, but holding a TCP connection open indefinitely does not require that the radio stay in its active state. On iOS, setting the kCFStreamNetworkServiceTypeVoIP property on the connection allows the radio to return to the idle state and reawake when it receives data on the socket. Android may have similar APIs.
- sliverstorm 13y agoWouldn't the radio have to wake on a timer to scan? How else will you notice there is data waiting on the other side of the connection?
- ryanpetrich 13y agoThe radio is in a low power idle state, the same state used to wait for incoming phone calls and text messages.
- mikeash 13y agoI think the radios are down at the IP level and have no concept of a TCP connection, so an open but idle connection won't keep the radio from shutting off. For example, Apple recommends that VoIP apps on iPhones keep a TCP socket permanently open and use it to receive notifications of new calls and similar: https://developer.apple.com/library/ios/documentation/iphone/conceptual/iphoneosprogrammingguide/AdvancedAppTricks/AdvancedAppTricks.html#//apple_ref/doc/uid/TP40007072-CH7-SW12 https://developer.apple.com/library/ios/documentation/iphone...
- tjohns 13y agoThis is outside my area of expertise, but I've heard that there's a keepalive timeout for open sockets set by the cell carriers. (Again, don't know the details.) So, there is a small cost to keep a TCP connection open, in order to avoid this timeout. Also, as I mentioned in my previous comment: Even if keeping the socket open is free, every time you send a packet there's a cost -- both for the actual data transmission, as well as a medium-power state the radio enters for a bit before really going to sleep. And given the number of apps that use background data, background traffic on a phone can get quite chatty. This is why it's important to synchronize background activity across apps. If you implement your own push channel, there's no way for the OS to do any sort of synchronization.
- tjohns 13y agoGCM is the recommended solution for anything that's trying to "push" data to Android: http://developer.android.com/google/gcm/index.html http://developer.android.com/google/gcm/index.html We (Android) usually don't recommend developers try to implement push themselves. Using GCM allows the Android servers to schedule and collate data transmissions, so push messages from different apps get sent as part of the same transmission. Anything you roll yourself won't be able to do this.
- kevinbowman 13y agoWhat about for a webapp, even an offline one? Is there a hook into GCM from Javascript or something like that?
- tjohns 13y agoI suppose you could use the Java-to-JS bridge, if you're using WebView inside a native app. However, there's not really any "mobile-friendly" push solution available as part of HTML5 right now. I wish there was. There's "GCM for Chrome" (http://developer.chrome.com/apps/cloudMessaging.html http://developer.chrome.com/apps/cloudMessaging.html), but that's both Chrome-only and only available on the desktop.
- jheriko 13y agoof course, if you program for anything like you do for "real man hardware" - by which i mean targetting hardware and not a software platform e.g. a games console or a proper native app, part of the 'web stack' etc.... you never have a problem like this. :P eventually you realise that C isn't fast enough and you can make it faster, but nobody else cares because they spunk clock cycles and bytes everywhere like they have billions of them (which of course they do... :D) ...and suddenly every language and platform is solving problems you never had because you just weren't a bad programmer to start with, and instead of solving your problems they are just tying your hands to prevent other people from shooting themselves in the feet.
- canthonytucci 13y ago> Every decision you make should be based on minimizing the number of times the radio powers up. This is lunacy. Ok, lunacy is a bit strong. But I disagree with this and am throwing a "premature optimization" flag. Modern phone batteries last plenty long, and the radio being on is nothing compared to the big bright screen. /edit Given the opportunity to chose, I know I would gladly sacrifice a few minutes per charge battery life for a better user experience, especially since my phone never gets below 20%. Your users will be better served by you fixing bugs or adding features. Really, unless you're a huge team with a huge budget, there's other stuff to worry about in your app experience before "maximizing battery life" should be a responsibility you want to help the OS/device maker with.(If you're one of the lucky ones who has the time and money to do both, by all means, go nuts.) Being conservative with resource usage is sound advice. Making battery usage the prime concern for most apps is overkill. Games and other applications that you know users will have open for extended periods of time, and/or that are already eating up battery should give this issue some thought, everyone else, really, don't worry about it.
- ultimoo 13y agoMaybe a good mobile app can determine its optimization/ux strategy depending on what level the battery is currently at. I am not sure whether apps can query for battery levels though.
- canthonytucci 13y agoAt least on iOS you can indeed. It's available from UIDevice. And if you're doing something that sucks up battery, you should know about it and act accordingly. If you're not doing heavy lifting, It's just not something you should have to think about as an app developer, there are so many other areas to focus on to keep users happy. Apple has a few WWDC sessions that talk about it I think. Here's what they have to say in their "performance tuning" section: https://developer.apple.com/library/ios/documentation/iphone/conceptual/iphoneosprogrammingguide/PerformanceTuning/PerformanceTuning.html#//apple_ref/doc/uid/TP40007072-CH8-SW1 https://developer.apple.com/library/ios/documentation/iphone...
- ultimoo 13y agoGreat article, made me explicitly aware of something I had at the back of mind as a web developer. Another point that struck me is that when I briefly used Android more than a year ago, there was a nifty tool that showed which app drained what %-age of the battery. If I am having troubles with my battery life on Android, I am likely to uninstall (or not use) an app that consumes more than its fair share of the battery. I haven't seen an equivalent statistics pane in iOS, I wonder whether Apple will introduce it at some point to encourage app developers to author more efficient apps.
- gardarh 13y agoThe problem with the battery statistics is that even though an app that is causing battery drain it might not be registered with that app. Imagine an app that sends a 1kb probe message every 15 seconds in the background thus keeping the radio alive the entire time (i.e. never allowing it to idle). I believe that the battery drain caused by the radio usage would count towards "Android System" and not the app when in reality the app would be shortening your phone battery lifetime significantly. Assigning battery usage to apps is a hard thing as there are so many grey areas. OTOH you will notice apps that are stuck in CPU expensive loops that will not terminate, however this is not that common in my experience. The Android battery statistics are nice but they usually don't provide me with a useful answer to the question: Which app is really draining my battery.
- DougWebb 13y agoThe last thing I'd want is for my apps to each be downloading several MB of data they think I might need in the next few minutes. I can easily control how much battery life is remaining on my phone by plugging it in. I can't control how much of my data plan an app is using, except by uninstalling the app. Besides, in my experience the biggest drains on battery life aren't data transfers, they're (a) having the screen on, especially when bright, and (b) being slightly out of range of a cell tower, and constantly dropping and reacquiring a 3G connection. The latter turns my phone into a hand-warmer and chews up my power.
- king_jester 13y ago> The last thing I'd want is for my apps to each be downloading several MB of data they think I might need in the next few minutes. I can easily control how much battery life is remaining on my phone by plugging it in. I can't control how much of my data plan an app is using, except by uninstalling the app. Prefetching isn't applicable to every situation, but in some circumstances it makes apps more enjoyable to use. The trick is to analyze and understand the high volume usage patterns for your app and to target those for improvement. If you see that the vast majority of your users will take a next step to view content that must be web loaded, it may make sense to prefetch when the wi-fi or cell radio is already on so you can piggy back on the high power state and avoid waking the hardware. > Besides, in my experience the biggest drains on battery life aren't data transfers, they're (a) having the screen on, especially when bright, and (b) being slightly out of range of a cell tower, and constantly dropping and reacquiring a 3G connection. As someone who has encountered apps with bugs that do constantly make or maintain network connections, these kinds of bugs are a much more severe drain on battery compared to the screen. We're talking about bugs that are constantly powering your wifi or cell radio hardware 90% of the time. This will kill your battery in no time, screen on or off.
- tjohns 13y agoForeground prefetching aside, there are controls that let users disable background data prefetching/syncing. In fact, it's even one of the buttons on the standard "power control" widget. While the screen is definitely a huge power drain, it's easily controlled by the user. Poorly behaved apps will drain battery regardless of what the user does, and definitely _can_ be a huge drain. These used to be a lot more common when Android first came out -- many of these apps got better when users got better visibility of battery usage and started complaining to app developers. And in general, we're talking kilobytes of data here. Not megabytes. Prefetching is good for metadata and text content; image content and other large assets should be an opt-in feature. (Android's "News and Weather" app was a good example of how to do this right.)
- thibauts 13y agoThe author talks about Google Cloud Messaging to avoid polling. I've been researching the topic and gave it a try with websockets without much success. TCP connections tend to hang on cell tower switching and I suspect TCP keepalives keep turning the radio on. I really wonder how to implement push to client on the html5 platform. I even wonder if this is possible at all for now.
- fulafel 13y agocell tower switching is transparent to TCP except for delayed packets. TCP keepalives are off by default and the default interval is 2 hours.
- AsymetricCom 13y agoJust another bugle call for developers and users to forfeit more of their rights to our mighty big data and cloud land owners. Is your app ready for the "Internet of Things"?
- kintamanimatt 13y agoA few months ago I'd have been happily hitting the downvote button along with everyone else, mumbling to myself about how crazy you sound. Today, however, I wish you weren't being downvoted because you're half way to being right. I strongly doubt the intent of things like Google Cloud Messaging is to intercept all your data and siphon it off to the NSA, GHCQ, and others. GCM is an incredibly useful service that has been designed to make it easier to write apps that use less power by eliminating polling. When you don't have to poll you can keep the mobile radio in a low power state. But the trouble is, you are indeed passing data (possibly even sensitive data!) through Google data centers when you're using GCM and it's equivalents. The tech industry seems to trust Google less today than it did this time last year in light of the Snowden leaks, and quite rightly so.
- AsymetricCom 13y agoI'm not even considering that perspective. I'm just wary of the neofuedalist movement of technology in the last ten years or so, fueled by the mobile platforms being subject to regulatory capture. The fact that data being captured by intelligence communities already shows you who owns this "land" and considers the "natural resources" theirs for the pillaging, this is a great example of the kind of neofeudalism this proposed platform is building. We just rent the internet, the data that it generates is for the kings and gods. The fact that these so called mobile platforms leave so much complexity to be managed by the developer just goes to show that these so called platforms are simply land grabs and don't actually offer anything to the developer except his software locked down to a single platform. They don't need to offer any service, just a rent collecting system for their captured land.
- lucb1e 13y agoOh, shit. apt-get remove apache2 php5 ... And here I thought running Debian (for ARM cpus) on your phone was cool. Apparently I'm Doing it Wrong. Puns aside, good article. If everyone did this (for example caching for 2-5 minutes ahead) things would run a lot better! Next time I'm going to code an app, I'll read through everything on this page first.
- minimax 13y agoHow does the power usage of the wifi radio compare to the cell radio? Does it use more or less power?
- sliverstorm 13y agoWiFi is supposed to be around the power of 2G, while 3G consumes a lot more power than either.
- kintamanimatt 13y agoVastly less. I can save a few percent of battery life an hour just by using wifi instead of the mobile radio for data.
- jchrisa 13y agoShameless plug for Couchbase Lite, our embedded database for iOS and Android, with built-in sync. Let us optimize the network traffic so you can write features. Dev info: http://mobile.couchbase.com http://mobile.couchbase.com
- Zigurd 13y ago> Every decision you make should be based on minimizing the number of times the radio powers up. It doesn't have to be "every decision" if you architect the app to not do CRUD-over-mobile-data and do sync instead. This not only improves battery life, it has a strong positive effect on perceived performance and interactivity. Fortunately, there will soon be a book all about that (ISBN 1118183495).
- csense 13y agoSince Android is an open system, would it be possible to write an app that runs on a phone and forces applications to batch transfers? I'm thinking of a "limiter" app that runs locally on the phone, and disables TCP/IP transmissions every 18 minutes out of 20. That way things like email you can still get relatively quickly, but the radio's only on 10% of the time. Developers and users both being aware of the problem and trying to fix it might mean their solutions collide. E.g. a badly behaved app that tries to access the network once every 30 seconds will always get through during the 2-minute window, but a well-behaved app that only hits the internet every 10 minutes might miss the window entirely. So maybe the limiter should intercept outgoing TCP/IP connections, lie to the initiating app and tell it the connection happened but the remote end isn't sending any data, then connect the outgoing app to the real remote end when the radio switches on. Of course if there's an application-controlled timeout interval on the connection, it'll trigger and the 10-minute-interval app would miss the window. You might get around that problem by using whatever UNIX signal Ctrl+Z generates, to lock up an app entirely when it tries to open an outgoing connection, then resume it when the radio's on. Of course, this'll probably lock the app's UI too, so it'll become totally unusable. Although if the limiter acts like a screensaver and goes away whenever the user's recently given any touch or keyboard input, that doesn't really matter, does it? Or maybe Google should make an API where an app can say, "I want to make a connection, and I'm willing to wait if turning the radio on right now wouldn't be good for the user."
- mike_esspe 13y agoYou can do similar to what you want right now: pass to AlarmManager flag ELAPSED_REALTIME, and your event won't be delivered, until device is waked up.
- marcosdumay 13y agoMy phone (Android 2.3) shipped with something similar. I don't know how to find it on more modern phones, but it's probably there.
- zmmmmm 13y agoSo what happens in a situation like long polling? Suppose no data is being transferred for 60 seconds ... is the radio kept on at maximum power? Or does it power down in between? Or does it turn off and break the poll (abort the TCP connection)?
- joeframbach 13y agoThe article is specific for native apps. Is there something I can do to bundle requests together on browser-based sites? Does it matter there? I asked stackoverflow but nothing came of it yet: http://stackoverflow.com/q/18909185/1253312 http://stackoverflow.com/q/18909185/1253312