Today we're announcing a new version of the Android platform — Android 2.3 (Gingerbread). It includes many new platform technologies and APIs to help developers create great apps. Some of the highlights include:
Enhancements for game development: To improve overall responsiveness, we’ve added a new concurrent garbage collector and optimized the platform’s overall event handling. We’ve also given developers native access to more parts of the system by exposing a broad set of native APIs. From native code, applications can now access input and sensor events, EGL/OpenGL ES, OpenSL ES, and assets, as well a new framework for managing lifecycle and windows. For precise motion processing, developers can use several new sensor types, including gyroscope.
Rich multimedia: To provide a great multimedia environment for games and other applications, we’ve added support for the new video formats VP8 and WebM, as well as support for AAC and AMR-wideband encoding. The platform also provides new audio effects such as reverb, equalization, headphone virtualization, and bass boost.
New forms of communication: The platform now includes support for front-facing camera, SIP/VOIP, and Near Field Communications (NFC), to let developers include new capabilities in their applications.
For a complete overview of what’s new in the platform, see the Android 2.3 Platform Highlights.
Alongside the new platform, we are releasing updates to the SDK Tools (r8), NDK, and ADT Plugin for Eclipse (8.0.0). New features include:
Simplified debug builds: Developers can easily generate debug packages without having to manually configure the application’s manifest, making workflow more efficient.
Integrated ProGuard support: ProGuard is now packaged with the SDK Tools. Developers can now obfuscate their code as an integrated part of a release build.
HierarchyViewer improvements: The HierarchyViewer tool includes an updated UI and is now accessible directly from the ADT Plugin.
Preview of new UI Builder: An early release of a new visual layout editor lets developers create layouts in ADT by dragging and dropping UI elements from contextual menus. It’s a work in progress and we intend to iterate quickly on it.
To get started developing or testing applications on Android 2.3, visit the Android Developers site for information about the Android 2.3 platform, the SDK Tools, the ADT Plugin and the new NDK.
Check out the video below to learn more about the new developer features in Android 2.3.
[This post is by Eric Chu, Android Developer Ecosystem. —Tim Bray]
Providing users with more information about applications on Android Market has been a top request from Android users. Starting in a few weeks, we will be showing content ratings for all applications on Android Market. This new capability will provide users with additional information to help them select the best applications for them.
Android Market’s content policy remains the same as before: applications will be rated according to four content rating levels: All, Pre-teen, Teen, & Mature. Details on the rating levels can be found at Android Market Help Center.
To prepare for this launch, starting next week, developers submitting new or updated applications will be required to include a rating for all applications and games uploaded onto Android Market. In addition, developers will have the next several weeks to add a rating to their existing applications and games. Once content rating is visible to users, any applications or games that do not include a rating will be treated as “Mature”.
We are working hard to rapidly deliver improvements and upgrades to Android Market. Please look for more Android Market upgrades in the coming weeks. Thanks for your continued support and please don’t hesitate to give us feedback on what else we can do to make you more successful with Android and Android Market.
We’ve had quite a bit of discussion in this space recently about how to make sure that your app is visible in Android Market to any device that can run it, and only to those devices. In particular, check out two recent pieces by Reto Meier, Future-Proofing Your App and The Five Steps to Future Hardware Happiness.
As Reto points out, Market used to infer some <uses-feature> settings for older apps that were uploaded before certain device features arrived. This hasn’t been the case for applications uploaded since June of this year; developers have had to be careful about <uses-feature> and its android:required attribute. From what we see, it looks like most of you have got this sorted out and things are working smoothly.
<uses-feature>
android:required
However, there are still apps that haven’t been re-uploaded since June. In preparation for introducing some new Market features (that we think you’ll like), we’re about to launch a re-scan of all those legacy apps, looking at their Android Manifests and updating Market’s database. This means that if you have an app that you haven’t updated since June, and it lacks up-to-date <uses-feature> settings, it may stop being visible on certain devices.
We think the set of apps that will have this problem will be small, if only since most successful apps are updated regularly. If you want to be sure, check Reto’s advice here under "Android Market Rule #2”.
We’ve said it before but it bears repeating: There are a lot of different sizes and shapes and flavors of Android devices in the product pipeline, and you want your app available on every one that can possibly run it. So this is an area that is going to be requiring attention from developers on a continuing basis.
Almost instantly after I joined Google, it became obvious to me that the number-one area where Android developers wanted to see action and progress was in Android Market; your concerns in this area vastly outweighed whatever issues might be bothering you about the handsets and the framework and the programming tools. In recent months there has been a steady, quiet, incremental flow of improvements and upgrades. They add up. This is by way of a glance back at developments since the arrival of Froyo last summer.
First, we introduced error reporting to Market, so developers can see if their apps are locking up or crashing; and if so, exactly where.
Second, we upgraded the Market publisher site to include user comments, so you can read what people are saying about you, or at least what they’re saying in a language you understand.
Third, we added the licensing server, which, when used properly, tilts the economics of Android apps toward you, the developer, and against the pirates.
Fourth, we cranked up the number of countries people can buy and sell apps in: as of now, you can sell them in 29 countries and buy them in 32.
Fifth, we rolled in a “recent changes” feature, a place for developers to put their release notes. Android Market has a zero-friction process for app update, and the really great apps have followed the “release early, release often” philosophy. As a developer, I like having a place to write down what’s behind an app release, and as a person who downloads lots of apps, I like to know what the goodies are in each new update.
Sixth, Market now has a “draft upload” feature; this removes a lot of the tension and strain from the app-update process. Get your screenshots and feature graphics and text and APK all squared away with as much editing as you need to, then update them all with one click.
You’ll notice that I didn’t say “Sixth and last”, because this is a team on a roll and I expect lots more goodness from them; if you care about the larger Android ecosystem, or are already a developer, or are thinking of becoming one, stay tuned to this channel.
[This post is by Roman Nurik, who is passionate about icons. —Tim Bray]
With thousands of new apps being published in Android Market every week, it’s becoming more and more important to proactively work at breaking through the clutter (hooray for marketing jargon!). One way of improving your app’s visibility in the ecosystem is by deploying well-targeted mobile advertising campaigns and cross-app promotions. However, there’s another time-tested method of fueling the impression-install-ranking cycle: improve the product!
A better app can go a very long way: a higher quality app will translate to higher user ratings, generally better rankings, more downloads, and higher retention (longer install periods). High-quality apps also have a much higher likelihood of getting some unanticipated positive publicity such as being featured in Android Market or social media buzz.
The upside to having a higher-quality app is obvious. However, it’s not always clear how to write a so called ‘better app.’ The path to improving app quality isn’t always well-lit. The term ‘quality’, and its close cousins ‘polish’ and ‘fit and finish’ aren’t always well-defined. In this post, we’ll begin to light the path by looking at a couple of key factors in app quality, and furthermore, look at ways of improving your app along these dimensions.
Given that pretty much any measure of the ‘success’ of an app involves user-related metrics such as number of downloads, daily actives, retention rates, etc., it’s a good idea to start thinking of your app’s quality as it relates back to your users.
The most obvious way to listen to users is by reading and addressing comments on your app in Android Market. Although the comments aren’t always productive or constructive, some will provide valuable insight on aspects of your app that you may not have consciously considered before. It’s important to remember that users have the opportunity to change their ratings and comments about an app as much as they’d like.
Now, since Android Market doesn’t currently provide a bidirectional communication medium for developers and their users, you should set up your own support and discussion destination(s). There are some great support tools out there that can put you in touch with your users directly such as Google Groups, Zoho Discussions, getsatisfaction.com and uservoice.com. Once you get set up with such a tool, make sure to fill in the support link in your Android Market listing -- users do click through to these.
Another way to better listen to your users is by having a public beta or trusted tester program. It’s crucial to have some amount of real user testing before releasing something in Android Market. Fortunately, you can distribute your apps to users outside of Market via a website; this website can require a login or be publicly accessible — it’s entirely up to you. Take advantage of this opportunity by offering your next planned update to some early adopters, before submitting to Market. You’ll be surprised by how many little, yet impactful, improvements can come out of crowd-sourced, real-user testing.
I won’t go into detail about why this is important, because hopefully it’s obvious. And hopefully you’ve been reading this blog and following the best practices outlined in previous posts, so you have a solid idea on how to improve in this arena.
One noteworthy and yet relatively underused tool for catching stability issues like crashes, is the UI/Application Exerciser Monkey (aka Monkey). Monkey will send random UI events to your app’s activitie, allowing you to trigger user flows that can uncover stability problems.
Also, with the new error reporting features in Android 2.2, users now have the ability to report application crashes to developers. These show up in aggregate in the Android Market developer console. Make sure to read these reports and act on them appropriately.
Lastly, keep an external bug and feature request tracker. This will enable your users to engage with the app at a closer level, by following features and bugs that affect them. User frustration with app problems can be effectively managed with diligent issue tracking and communication. Some of the community support tools listed above offer issue tracking features, and if your project is open source, most popular repository hosting sites such as Google Code and GitHub will offer this as well.
One sure-fire way to tick off your users is to have a slow UI. Research has shown that speed matters... for any interface, be it desktop, web, or mobile. In fact, the importance of speed is amplified on mobile devices since users often need their information on the go and in a hurry.
As Brad Fitzpatrick mentioned in his Google I/O 2010 talk, Writing Zippy Android Apps, you can improve your apps’s UI responsiveness by moving long-running operations off the application’s main thread. See the talk for detailed recommendations and debugging tips.
One way to improve UI performance is to minimize the complexity of your layouts. If you open up hierarchyviewer and see that your layouts are more than 5 levels deep, it may be time to simplify your layout. Consider refactoring those deeply nested LinearLayouts into RelativeLayout. As Romain Guy pointed out in his World of ListView talk at Google I/O, View objects cost around 1 to 2 KB of memory, so large view hierarchies can be a recipe for disaster, causing frequent VM garbage collection passes which block the main (UI) thread.
Lastly, as Tim pointed out in Traceview War Story, tools like traceview and ddms can be your best frends for improving performance by profiling method calls and monitoring VM memory allocations, respectively.
More resources:
Designing for Performance
Designing for Responsiveness
I’ll say it again here, listen to your users! Ask a handful of real Android device users (friends, family, etc.) to try out your application and observe them as they interact with it. Look for cases where they get confused, are unsure how to proceed, or are surprised by certain behaviors. Minimize these cases by rethinking some of the interactions in your app, perhaps working in some of the user interface patterns the Android UI team discussed at Google I/O.
In the same vein, two problems that currently plague Android user interfaces are small tap targets and overly small font sizes. These are generally easy to fix and can make a big impact. As a general rule, optimize for ease of use and legibility, while minimizing, or at least carefully balancing, information density.
Another way to incrementally improve usability, based on real-world data, is to implement Analytics throughout your app to log usage of particular sections. Consider demoting infrequently used sections to the options menu, or removing them altogether. For oftenly-used sections and UI elements, make sure they’re immediately obvious and easily accessible in your app’s UI so that users can get to them quickly.
Lastly, usability is an extensive and well-documented subject, with close ties to interface design, cognitive science, and other disciplines. If you’re looking for a crash-course, start with Donald Norman’s The Design of Everyday Things.
There’s no substitute for a real user interface designer — ideally one who’s well-versed in mobile and Android, and ideally handy with both interaction and visual design. One popular venue to post openings for designers is jobs.smashingmagazine.com, and leveraging social connections on Twitter and LinkedIn can surface great talent.
If you don’t have the luxury of working with a UI designer, there are some ways in which you can improve your app’s appearance yourself. First, get familiar with Adobe Photoshop, Adobe Fireworks, or some other raster image editing tool. Mastering the art of the pixel in these apps takes time, but honing this skill can help build polish across your interface designs. Also, master the resources framework by studying the framework UI assets and layouts and reading through the new resources documentation. Techniques such as 9-patches and resource directory qualifiers are somewhat unique to Android, and are crucial in building flexible yet aesthetic UIs.
The recently-published Android UI Design Tips slide deck contains a few more best practices for your consideration.
Having the right set of features in your app is important. It’s often easy to fall into the trap of feature-creep, building as much functionality into your app as possible. Providing instant gratification by immediately showing the most important or relevant information is crucial on mobile devices. Providing too much information can be as frustrating (or even more so) than not providing enough of it.
And again, listen to your users by collecting and responding to feature requests. Be careful, though, to take feature requests with grains of salt. Requests can be very useful in aggregate, to get a sense of what kinds of functionality you should be working on, but not every feature request needs to be implemented.
A great way to deliver a delight user experience is to integrate tightly with the operating system. Features like app widgets, live folders, global search integration, and Quick Contacts badges are fairly low-hanging fruit in this regard. For some app categories, basic features like app widgets are par for the course. Not including them is a sure-fire way to tarnish an otherwise positive user experience. Some apps can achieve even tighter OS integration with the new contacts, accounts and sync APIs available in Android 2.0 and later. A few sample apps that show how to use these APIs are SampleSyncAdapter (bundled with the SDK samples) and JumpNote.
Third-party integrations can provide even more user delight and give the user a feeling of device cohesiveness. It’s also a really nice way of adding functionality to your app without writing any extra code (by leveraging other apps’ functionalities). For example, if you’re creating a camera app, you can allow users to edit their photos in Photoshop Express before saving them to their collection, if they have that third-party application installed. More information on this subject is available in the Can I Use this Intent? article.
Designing for seamlessness
One particular detail I’ll call out is in icon quality and consistency. Make sure your app icons (especially your launcher icon) are crisp and pixel-perfect at all resolutions, and follow the icon guidelines, at least in spirit if not in letter. If you’re having trouble or don’t have the resources to design the icons yourself, consider using the new Android Asset Studio tool (a project I’ve recently open-sourced) to generate a set.
Along with this blog, make sure to follow @AndroidDev on Twitter — we’re constantly collecting and sharing tips and tricks on Android application development that you won’t always find anywhere else. And of course, don’t be afraid to ask questions in our support forums on Stack Overflow and Google Groups.
Thanks for reading!
I recently took my first serious look at Traceview, and it occurred to me, first, that there are probably a few other Android developers who haven’t used it and, second, that this is an opportunity to lecture sternly on one of my favorite subjects: performance improvement and profiling. This is perhaps a little bit Android-101; If you already know all about Traceview, you can stop here and go back to coding.
Here’s a belief that I think I share with most experienced developers: For any app that is even moderately complex, you’re not smart enough to predict what the slow parts are going to be, because nobody is smart enough to predict where software bottlenecks will turn up.
So the smart way to write a fast app is to build it in the simplest way that could possibly work, avoiding egregiously-stupid thing like order-N-squared algorithms and doing I/O on the Android UI thread. Who knows, it might be fast enough, and then you’re done!
If it isn’t fast enough, don’t guess why. Measure it and find out, using a profiler. Actually I’ve been known to do this, when backed into a corner, using things like System.err.println("Entered at" + System.currentTimeMillis()); Fortunately, Android comes with a reasonably decent profiler, so you don’t have to get ugly like that.
System.err.println("Entered at" + System.currentTimeMillis());
I have this little utility in Android Market called LifeSaver 2, the details are on my personal blog. At one point, it reads the SMS and phone-call logs out of the system and persists them in a JSON text file on the SD card. Since this is kind of slow, it shows a nice dynamic progress bar. It occurred to me to wonder why it was kind of slow to write a few hundred records into a text file on a device that, after all, has a gigahertz processor.
Somebody who foolishly disregarded my advice above might assume that the slowdown had to be due to the ContentProvider Cursor machinery reading the system logs, or failing that, the overhead of writing to the SD card. A wiser person would instrument the code and find out. Let’s do that.
I went into Saver.java and bracketed the code in its run() method like so:
run()
public void run() { android.os.Debug.startMethodTracing("lsd"); // ... method body elided android.os.Debug.stopMethodTracing(); }
The first call turns tracing on, the argument "lsd" (stands for Life Saver Debug, of course) tells the system to put the trace log in /sdcard/lsd.trace. Remember that doing this means you have to add the WRITE_EXTERNAL_STORAGE permission so you can save the trace info; don‘t forget to remove that before you ship.
"lsd"
/sdcard/lsd.trace
WRITE_EXTERNAL_STORAGE
[Update:] Android engineer Xavier Ducrohet writes to remind me: “DDMS has a start/stop profiling button in the ‘device view’. Upon clicking stop it launches TraceView with the trace file. This is not as fine grained as putting start/stopMethodTracing in your code but can be quite useful. For VMs earlier than froyo, the permission is required as well (DDMS basically automate getting the trace from the sd card and saving it locally before calling traceview). For Froyo+ VMs, the VM is able to send the trace file through the JDWP connection and the permission is not needed anymore (which is really useful).” Thanks, Xav!
Then you run your app, then you copy the output over to your computer, and fire up Traceview.
540> adb pull /sdcard/lsd.trace 541> traceview lsd
At this point, you will have noticed three things. First, turning tracing on really slows down your app. Second, the tracefile is big; in this case, 8.6M for a run that took like four seconds. Third, that traceview looks pretty cool.
The bars across the top show the app’s threads and how they dealt out the time; since the Nexus One is single-threaded CPU, they have to take turns. Let’s zero in on one 100-msec segment.
The top line is where my app code is running (the red segment is GC happening), the middle line is the UI thread and the bursts of activity are the ProgressBar updating, and I have no idea what the third thread, named HeapWorker, does, but it doesn’t seem a major contributor to the app’s runtime, so let’s ignore it.
The bottom of the screen is where the really interesting data is; it shows which of your methods burned the time, and can be sorted in a bunch of different ways. Let’s zero in on the first two lines.
Translated into English, this tells us that the top-level routine consumed 100% of the time if you include everything it called (well, yeah), but only 0.9% of the time itself. The next line suddenly starts to get real interesting: java.io.PrintStream.println(Object) and whatever it calls are using 65.2% of the app’s time. This is the code that writes the JSON out to the SD card. Right away, we know that apparently the task of pulling the data out of the phone’s ContentProviders doesn’t seem to be very expensive; it’s the output that’s hurting.
java.io.PrintStream.println(Object)
Can we conclude that the app is limited by the sluggish write performance of the SD card? Let’s drill down, which is done in the most obvious point-and-click way imaginable.
Ooh, there’s a nasty surprise. Of course, println calls (in effect) toString() on all its arguments. It looks like turning the arguments to strings is taking over half the time, before it even dispatches from println(Object) to println(String).
println
toString()
println(Object)
println(String)
I’ll skip the step of drilling down into println(String) but it does suggest that yes, there is some slow I/O happening there, to the SD card. But let’s look inside that String.valueOf() call.
String.valueOf()
There’s your smoking pistol. It turns out that org.json.JSONObject.toString() is what we professional programmers call a, well, this is a family-friendly operation so I won’t go there. You can poke around inside it, but it’s just depressing.
org.json.JSONObject.toString()
What you can do, however, is sort all the routines by their “Exclusive” times, as in the number of CPU circles burned right there in the routine. Here are all of them that use 1% or more of the total execution time.
There’s a little bit of GC and Android framework View-wrangling stuff in there, but the display is dominated by org.jason and java.lang.StringBuilder code.
org.jason
java.lang.StringBuilder
The real conclusion is that in the case of this app, I actually don’t care about the performance. A user runs it a grand total of two times, once on the old phone and once on the new phone, and it’s got lots of eye candy, so I just don’t think there’s a problem.
If I did want to speed this up, it’s obvious what to do. First, either stop using JSON, or find a cheaper way to serialize it. Second, do fewer println() calls; glom the data together in one big buffer and just blast it out with a single I/O call. But, and here’s the key point, if I’d guessed where the bottlenecks were, I’d have been wrong, mostly.
println()
Traceview is a nice tool, and if you don’t already know it, you owe it to yourself to learn it.
[This post is by Reto Meier AKA @retomeier, who wrote the book on Android App development. —Tim Bray]
Two questions I regularly get asked are “Why isn’t my app visible on the Market on the (insert device name here)?” and “How can I prepare for GoogleTV and Android tablets?” If you care about how broadly your app is available, pay attention now. Seriously. I don’t want to hear anyone telling me they weren’t told. [Seems a little combative? -Ed. Take it up a notch! -RM]
By now you’ve probably heard of Google TV, the Samsung Galaxy Tab, and the Dell Streak. These are only the vanguard — Android is quickly moving to hardware that is increasingly different from the smartphone devices we’re used to. The variations in hardware — including lack of features like GPS, accelerometers, and video cameras — means it’s time for you to think about what hardware your app needs, and what it can function without.
To make life easier every API includes a FEATURE_* constant. To control your app’s availability on the Android Market, you specify the features required for your app to work. I’d like to encourage you to add manifest Feature nodes for every API you use, specifying them as optional, or not, as appropriate using a manifest uses-feature nodes as shown below:
<uses-feature android:name="android.hardware.microphone" android:required="true"/>
My earlier post on future proofing your apps describes a process of feature inferring that used your app’s permissions to help us ensure apps were only visible on the appropriate hardware.
This process has evolved over time. From now on Market won’t be inferring future API features and we have no way to infer some previously available APIs (eg. sensors). As a result you’ll need to specify your mandatory and optional feature requirements — or risk your app either breaking or not being available for some users.
Specify a uses-feature node for every API feature used by your app. This forces you to think about what your app uses, allowing you to:
Decide which features are necessary for your app to be useful and mark those featured with the attribute required=true. This lets Market hide your app from any device that doesn’t support the hardware features your app requires.
required=true
<uses-feature android:name="android.hardware.telephony" android:required="true"/>
For features that aren’t strictly required, set required=false.
required=false
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
Then go in to your code and find where you have used the optional features. Use the hasSystemFeature method from the PackageManager to determine if the hardware is available and provide alternative paths for your code as appropriate.
PackageManager pm = getPackageManager();boolean hasCompass = pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_COMPASS);
Now you can sleep soundly in the knowledge that no matter what variation in Android compatible hardware comes to market, your app will always (and only) be available on those it supports.
You can find more details on how the Android Market uses filters to determine whether to show your application to a user who is browsing or searching for applications on a given device at the Market Filters page on the Android Developer Site.