104 Photos - May 12, 2013
Photo: Making Apps Work Like Magic. Presented by Reto Meier at Google I/O 2013.Photo: In the world of technology we don't measure age in the passing of years, but in the number of transistors we can fit on an integrated circuit. let's call it Moore's age.Photo: In tech years I'm old. A little over 131 *thousand* years old.Photo: I'm old enough that I grew up with my Dad selling and servicing these office machines.Photo: Back in my youth "IBM Compatible" meant these golf-ball print heads that fit into IBM Selectric 2 typewriters.Photo: Our challenge: Building apps sufficiently advanced to appear magical.Photo: I'm an engineer -- so even as a BBS operator in the mid-90's, playing Doom ][ on my LAN, I didn't believe in magic.Photo: Predicting the future is hard. 5 years ago, there was no Android. 3 years ago I predicted it would take 10 years for augemented reality and voice input to start replacing keyboards. Now we have Glass and I already look short-sighted.Photo: When sci-fi like communicators, tablets, and VISORs, set 300 years in the future becomes reality within 20 years, building apps advanced enough to be magical is difficult.Photo: To build magical apps, we need to move beyond the implausible technology of sci-fi, and create apps that leave people asking "how did you do that".Photo: An app is sufficiently advanced enough to appear magical when an engineer asks you if it's actually doing anything, or if it's just a mock.Photo: Development is all about compromize. What looks good on a design doc, can look very different once it's implemented. The trick is knowing which compromizes are necessary to ship, and which ones will lessen your app's magic.Photo: Basing your product plans on what your competitors today is skating to where the puck was.Photo: In December, 56% of respondents to our Android Developer Survey said they were planning to increase their investment in Android.Photo: Of those who were planning to increase their investment, nearly 70% said they were planning to invest in new apps, improving quality, and adding new features to their apps.Photo: In the 6 months you spent working on your new app, you collected more competitors, and your existing competitors improved the quality and feature set of their apps.Photo: These platform distribution graphs represent where the puck was. They tell you only which devices have been popular, but say nothing about the future composition of the Android ecosystem.Photo: While you wait for a particular slice of the distribution pie to pass a specific number, your competitors are already building for new device hardware and integrating new platform features.Photo: If you concentrate on the individual pie slices, it's easy to forget that the whole pie keeps getting bigger. The proportion of new device activations is significantly larger than the proportion of those devices represented in this pie. That means hundreds of thousands of new users every day running the latest version of Android, eager to take advantage of the latest hardware and software features.Photo: Create the best experience you can for all your users, rather than developing only features that everyone can use. Owners of the newest devices running the latest platform release are looking for magical experiences, and will associate platform magic with your app.Photo: Configuring Android Beam is straight forward. This boiler-plate code lives within onResume and simply calls createMessage to create a new Android Beam payload to send when Android Beam is initiated with this Activity in the foreground.Photo: The payload should provide the contextual information necessary for your app to be able to navigate to a particular place within your app when it receives this message.Photo: To receive Android Beam messages, add this Intent Filter to your Activity's manifest tag.Photo: Whenever you receive a new Android Beam Intent for your Activity, extract the payload and use it to navigate to the right book / movie / song / radio station / recipe etc. You can even use it to initiate a multiplayer game.Photo: Allowing your homescreen widget to be added to the lockscreen requires only one line of XML.Photo: Customize your widget layouts for the lockscreen. The lockscreen is prime real-estate -- create an awesome lock-screen experience now to claim it for your app.Photo: Use context to help create magical, personalized experiences for your users.Photo: To create a truly magical app, context isn't important -- it's critical.Photo: Imagine if I asked you to give your unlocked phone to a stranger, would you do it?Photo: I'd rather share my home address and vacation schedule than give anyone my unlocked device.Photo: You wouldn't share your phone because it knows your context. It knows where you live, when you're on vacation, what you read, watch, listen too, and what games you play. As developers, we have an opportunity to use this context to create rich, personalized experiences for our users.Photo: Location is one of the most fundmental peices of user context available to us as developers.Photo: I talked about how to create efficient location-based apps in detail at Google I/O 2011.Photo: I also wrote "A Deep Dive Into Location" that highlighted best practices for using Android's Location Based Services APIs.Photo: To support my I/O talk and blog post, I created a sample project that implemented the best practice patterns I talked about.Photo: The resulting sample project contained dozens of classes in order to codeify best practice, handle edge cases, and maintain backwards compatibility. The location team took a look at this and decided they could do one better, creating a new Location Based Services API as part of Google Play services.Photo: In order to use the new location-based services client, you confirm that Google Play services are available on the device, and if so, create a new LocationClient and connect to it. This happens asynchronously, so you need to wait until the onConnected handler is triggered before you start making your location requests.Photo: To request location updates using the new Location Based Services API, simply specify the update interval you require and the relative priority of accurary and battery efficiency. The Fused Location Provider will ensure you get the best, most efficient results from whichever location provider sources are currently available.Photo: Geofencing allows you to specify a particular location and radius, and if you're interested in users entering or exiting that boundary. Unlike the old Proximity Alerts API, Geofences will use distance to the boundary to select the location provider to use, and the frequency with which to perform updates. This allows you to use location context within your app without needing to get constant updates.Photo: Activity Recognition tells your app not just where your user is, but what they're doing. Use their current activity context to provide an optimized UX, or to improve your app's efficiency.Photo: In this example, the app is reporting on nearby points of interest. When we're standing still, we can pause updates -- but if we're a passenger in a vehicle we should get updates more frequently.Photo: In this example, we're refreshing sports scores. If the app is open and the user is standing still, we should increase the rate of updates -- conversly, if the user is on a bike we can pause updates until they're performing an activity that would increase the likelihood of them needing up-to-date data.Photo: If we're talking about using Google Play services to determine context, we have to mention Google+ signin. You can leverage the fact that most Android device owners will be logged in to Google+ to greatly simplify your login process to a simple click + authorization step. Once they're logged in you can use their name and photo to customize their experience. Beyond that, you now also have access to the context of their circle of friends.Photo: You can use the context of a user's circles to personalize their user experience. That can mean surfacing books, movies, restaurants, or music that your friends are enjoying, or triggering breaking news alerts based on what news articles your friends are reading. Alternatively, you can use the same information to make prioritize what data you're prefetching to make it more efficient.Photo: There is a risk associated with using context in a way that causes your users an unpleasant surprise. Using context is a powerful way to personalize their user experience, but you have to be careful to ensure you're never betraying an implicit trust.Photo: When using sensistive information, always make it clear what you're doing, why you're doing it, and where appropriate - offer a choice to opt-out.Photo: Requesting fine-location and Internet permissions doesn't imply to users that you'll be transferring their location information to your servers! Make sure that if you're using sensitive information you're doing so responsibly and in a way that's transparent to your users. Use the app's description and privacy policy to make it clear how user data will be used, and be especially careful to take steps to protect any sensitive information used by your app. Trust is hard to establish, easy to lose, and one gone - impossible to win back.Photo: A magical experience is one that delights.Photo: Rob Foster of mysterious trousers recently wrote that "Introducing visceral elements into an app..will make it speak to the subconcious."Photo: When we sit down for a meal it's about more than consuming calories and taking in nutrition. It's about the experience -- the sight, smell, taste, and texture of the food creates a visceral reaction that speaks to our subconcious.Photo: As app developers, we've often pondered why someone is willing to spend $5 on a cup of flavoured water every day without question, but will write an angry comment about your app if you charge $1.49 instead of 99c. One of the reasons is that a cup of coffee delivers that visceral reward: The smell of the brew, the warmth of the mug, the sound of coffee filling your cup, and the taste of that first cup in the morning.Photo: Creating a sensory experience is a big deal. Companies like ScentAir create aroma delivery systems that can make the sidewalk in front of your ice cream store smell like freshly baked waffle cones.Photo: Until Google Nose creates a public API, creating that sensory experience for your app will be more challenging.Photo: We have five senses that could potentially be leveraged. Taste, smell, sound, sight, and touch.Photo: Unfortunately, for now -- taste and smell aren't possible to leverage within your app, so let's concentrate on sight, sound, and touch. We want to create a unique, delightful experience -- that means building something that delights. To do that, we need to take a risk -- understand the rules of UX design well enough that we can risk breaking them in order to create that unique experience.Photo: To understand the rules, visit http://developer.android.com/design to learn the vision behind the Android design guidelines. You should use this as a baseline and inspiration for creating your own, unique user experience.Photo: Use Text To Speech to create an engaging experience like Google Now, by having your app talk to your users.Photo: Start by ensuring the TTS Data is installed.Photo: Once that's done, it's a line of code to have your app start speaking. This gives you the opportunity to create unique experiences that can make your app indespensible. Imagine two news apps of similar quality, but one can read me my morning news during my commute. Suddenly the relative features of each app becomes irrelevant -- I can only use the one that functions hands-free.Photo: If your app can talk to you, it's only fair that it should also listen. To get voice inputs for your app, start a new Activity using an Intent that uses extras to specify parameters such as langage and input prompt.Photo: Once you have the results, use the context of your app to pick the most likely voice input form the String Array based on what you're expecting the user to say.Photo: When it comes to touch, make sure your touch targets are all touchable. That means following a 48dp rythym. 48dp corresponds to 9mm of physical space -- right in the sweet spot of what you can accurately press with your index finger on a screen.Photo: People prefer interacting with *real* things, that means creating a tactile experience. Real things react when you touch them. Use a statelist drawable to ensure the look of your controls changes when they're touched (and tells you when they can't be touched).Photo: You can utilize the default selectable item background from within the framework resources.Photo: For controls that aren't transparent, use the selectable item background as a foreground element on a FrameView.Photo: Ensure the experience for visually impaired users is just as rich by adding descriptive content descriptions for every on screen element. It should describe the purpose of the control -- not describe what the control is. "Button" isn't useful -- "Add Contact" or "Send" is.Photo: When building your own custom Views, be sure to dispatch accessibility events when the content of the visual control changes.Photo: Real objects can be interactived with in more ways than touching them with a finger. Use gestures to create a tactile experience that speaks to our senses.Photo: What would I do with ten-finger touch support? Input from two hands at the same time. Create experiences where users can move, twist, and resize mutliple objects on screen at once and they'll never be able to return to a mouse and keyboard.Photo: When you create vicersal responses it's just as easy to create strong negative reactions as positive ones -- particularly if you change functionality to which your users have become... attached.Photo: The new Beta Testing feature in the Google Play Developer Console lets you experiment with changes to your app with a selected circle, or a proportion of your users. Use this insight to discover what's working, and what isn't.Photo: When deciding which features to implement and how to improve your user experience, remember that not all your users are equally valuable.Photo: For my own app, the largest proportion of users come from smartphones.Photo: However, tablet users spend significantly more time using the app. Understand what behavior is most valuable to you, and optimize your app to best serve those users.Photo: Use the analytics provided by the Google Play Developer Console to get an idea of the people who make up your user-base.Photo: To better understand the journey your users are making within your app, use a more powerful analytics tool such as Google Analytics for Mobile Applications. This will allow you to understand not only what they're doing, but their path through your app. This can be a powerful way to understand which features are working, and what causes people to exit your app.Photo: A magician never reveals their tricks -- and neither should you, or you'll ruin the magic. Your users should never be aware of how your app is possible, they should simply take it for granted.Photo: Banish the refresh button! Create an app that keeps its data fresh so that users are never looking to hit refresh.Photo: Last year I talked about the "Big Cookie Model" of data transfers -- batching, bundling, and prefetching as a way to ensure your data transfers are low latency and battery efficient.Photo: This year I'm looking at some of the techniques and APIs you can use to implement those best practices.Photo: All server-side updates should be triggered within your app using Google Cloud Messaging.Photo: You should use GCM for server-initiated updates, because everytime you set a recurring Alarm to poll your server, Sundar kills a Bugdroid.Photo: For cross-device updates, you can use the new Upstream API from Google Cloud Messaging. This lets you use the GCM infrastructure to efficiently send notifications from your app to your server, or from your app on one device to the same app running on other devices.Photo: The client-side use of the upstreaming API is simple. Get a Google Cloud Messaging client and call send -- specifying either a ProjectID to transmit a message to your server, or a NotificationID to transmit messages to your app running on other devices.Photo: For client-side updates, there's an excellent - if under-used - API called the SyncAdapter. It's relatively simple to implement, just extend the AbstractThreadedSyncAdapter and override the onPerformSync method. The SyncAdapter will handle threading, queuing, and batching to ensure your syncs happen, and happen efficiently.Photo: The SyncAdapter needs to be wrapped in a service that will bind it, providing a process within which the sync can occur.Photo: SyncAdapter was designed to synchronize a Content Provider associated with an Account, so there is some complexity associated with requiring that you have one of both before you can execute a sync. Start by creating an Account. If your app doesn't support or require accounts, you can use this code to explicitely create a pseudo account.Photo: Your Account Authenticator also needs to run in a Service.Photo: Finally, you need to create an XML config file for your account authenticator, specifying meta-data such as the account type you're creating. Take note of this as you'll need it for later steps.Photo: You also require a Content Provider. If you don't already have a Content Provider within your app, you can create a stubbed out implementation as shown here.Photo: When you add your Content Provider to your manifest, take note of the authority to which it's associated.Photo: With your Account Authenticator and Content Provider created, you can create your SyncAdapter config file. Note that we associate the authority defined for your Content Provider, and the Account Type specified by your Account Authenticator.Photo: Finally, you add the Account Authenticator and Sync Adapter Services to your manifest, including meta-data tags to associate the config files for each.Photo: While the plumbing is non-trivial, it's mainly boiler-plate code. Once done, requesting a sync is easy. Call requestSync on the Content Resolver, specifying the authority and account type you defined. The Sync Manager will batch requests from multiple apps, and handle things like batching, time shifting, and changes in connectivity status to ensure your sync happens quickly and efficiently.Photo: By default, the SyncAdapter will be synchronized every 24 hours. You can use the addPeriodicSync method to intitiate a regular sync over a different interval.Photo: Be cautious about scheduling repeating syncs at as particular time. If you have an app that pings your server every day at 2am, every device will wake up and initiate the connection at the same time -- resulting in a server traffic spike that looks like this.Photo: If your app wakes the device at the same time every day, every other app that's waiting until the phone wakes up before transmitting will also transmit pending data transfers at exactly the same time.Photo: If you combine your traffic, and the traffic associated with every other app running on devices on which your app is installed, people working for the carrier networks will get paged every day at the exact same time. This is a bad thing.Photo: Vary the time at which your app wakes the device. This is particularly important for data transfers, but is relevant to any alarm that will cause the device to come out of standby -- thereby triggering every other app that's waiting to transfer. Add randomized jitter to your alarms to spread the load across a wider time range.Photo: Better than using a time window, perform your syncs based on personalized routine of your users. You might determine that they get up every morning around 7am and schedule your updates to happen between 30 and 60 minutes before that. Or use the new Activity Recognition APIs to perform a sync when the device is first picked up.Photo: For time-sensitive on-demand transfers, utilize the SyncAdapter to ensure that you are bundling all your transfers in one place and allowing the system to bundle them together with other apps.Photo: To create truly magical experiences, you need to stop developing apps for the future, and start defining the future itself.Photo: Presented by Reto Meier (Google) at Google I/O 2013 (May 17th 2013). Graphics and animations provided by Pandamusk, with additional music by Joel Alford "Bliss".Photo: