Wednesday, December 22, 2010

More Payment Options in Android Market

[This post is by Eric Chu, Android Developer Ecosystem. —Dirk Dougherty]



A key to a great purchasing experience is providing users with simple and fast payment methods. The Android Market team has been working hard to deliver more forms of payment to further reduce purchase friction.


Today, I am pleased to announce the availability of AT&T Direct Carrier Billing for Android users on the AT&T network. AT&T Android users can now easily charge their Android Market purchases to their monthly accounts with only a few clicks. With the combination of Android Market’s new app discovery features and a carrier-backed frictionless payment method, users will find it significantly easier to discover and purchase applications of their choice.


We’ve been rolling out Direct Carrier Billing to all AT&T users over the past several days, as part of a general update to the Market service. Also in the update, please watch for the arrival of new features we announced recently, including the 15-minute refund window, dynamic Wallpaper and Widget categories, new 50MB max .apk size, and more. In addition, we’ve added even more categories to make it easier to find great apps in popular categories, such as “Media & Video”, “Music & Audio”, “Business”, “Sports” (in "Games"), and more. If you have one or more published apps on Android Market, please take a look at these new categories and decide if they are more suitable for your products.


We strongly believe carrier billing is a great way to make it easy for users to purchase and pay for applications. In addition to the availability of AT&T and T-Mobile US carrier billing, we’ll continue to partner with more carriers to offer carrier billing options for their subscribers.


2010 has been an awesome year for Android due in large part to your support. We have seen tremendous growth in Android Market both in terms of application volume and quality. In 2011, we remain committed to making Android Market the best mobile application store possible. As always, please don’t hesitate to continue giving us feedback through Market Help Center.


Best wishes for the new year!

Monday, December 20, 2010

It’s not “rooting”, it’s openness

[This post is by Nick Kralevich, an engineer on the Android Security Team. — Tim Bray]

“Nexus S has been rooted, let the madness commence!” proclaims Engadget. “This is only possible because Android's security is crap and it's exploited easily to gain root priviledges [sic]” adds a commenter.

You’ll have to excuse me if I strongly disagree.

The Nexus S, like the Nexus One before it, is designed to allow enthusiasts to install custom operating systems. Allowing your own boot image on a pure Nexus S is as simple as running fastboot oem unlock. It should be no surprise that modifying the operating system can give you root access to your phone. Hopefully that’s just the beginning of the changes you might make.

Legitimately gaining root access to your device is a far cry from most rooting exploits. Traditional rooting attacks are typically performed by exploiting an unpatched security hole on the device. Rooting is not a feature of a device; rather, it is the active exploitation of a known security hole.

Android has a strong security strategy, backed by a solid implementation. By default, all Android applications are sandboxed from each other, helping to ensure that a malicious or buggy application cannot interfere with another. All applications are required to declare the permissions they use, ensuring the user is in control of the information they share. And yes, we aggressively fix known security holes, including those that can be used for rooting. Our peers in the security community have recognized our contribution to mobile security, and for that, we are extremely grateful.

Unfortunately, until carriers and manufacturers provide an easy method to legitimately unlock devices, there will be a natural tension between the rooting and security communities. We can only hope that carriers and manufacturers will recognize this, and not force users to choose between device openness and security. It’s possible to design unlocking techniques that protect the integrity of the mobile network, the rights of content providers, and the rights of application developers, while at the same time giving users choice. Users should demand no less.

Thursday, December 16, 2010

Android Browser User-Agent Issues

[This post is by Bart Sears, who manages the Android Browser team. —Tim Bray]

This posting describes some issues when browsing websites with mobile variants using large-form-factor Android devices. This posting will be of interest both to OEMs (with recommendations on how to set the User Agent string for the device) and to web site designers/administrators (with recommendations on how to decide to provide either a mobile version, a desktop version, or a large-form-factor touch device version of the site).

Details

With the advent of Android devices with larger form factors, we’ve been evaluating the best way for web sites to provide a UI appropriate for the various Android devices that are now available to consumers. We have received feedback that consumers using larger-form-factor devices often prefer the “full” or “desktop” version of the site over the “mobile” version. Most websites providing “mobile” versions key off of the HTTP User-Agent header field to determine whether to provide the full site or a mobile version.

While large-form-factor Android devices could use “User Agent Spoofing” to provide a desktop User Agent in the HTTP header, we recommend against this. There may be site customizations needed for Android devices (for example changes in the way that mouseover is used) and the site would be unable to provide these customizations if it receives a spoofed User Agent that did not indicate that this was an Android device.

Currently, Android devices provide the following (in addition to standard info) in the User-Agent: "Android", a version number, a device name, a specific build, Webkit version info, and "Mobile". For example, Froyo on a Nexus One has the following User Agent:

Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1

The "Mobile" string in the User Agent indicates that this device would prefer a version of the website optimized for Mobile (small form factor devices), if available.

We recommend that manufactures of large-form-factor devices (where the user may prefer the standard web site over a mobile optimized version) remove "Mobile" from the User Agent (and keep the rest of the User Agent as currently implemented). Web sites can then key off "Mobile" in the User Agent to decide on which UI version to present to the device. So a large screen device running Froyo would have a User Agent similar to:

Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; device Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Safari/533.1

Where "device" would be replaced with the actual name of the new device. Sites can continue to use “Android” in the User Agent to optimize for Android specific features and can also key off of “Mobile” to determine which UI to present.

Tuesday, December 14, 2010

Analytics for Android Apps

[This post is by Alexander Lucas, an Android Developer Advocate bent on saving the world 5 minutes. —Tim Bray]

With the addition of custom variables to the Mobile Analytics SDK for Android, it strikes me as a good time to cover something many of you might not have known was possible — using Google Analytics to easily track app usage. Using the mobile SDK is a handy way to get real data on how users interact with your Android apps. So today I'm going to explain how to track usage of your application with Google Analytics.

Prereqs Ahoy!

Before you take off running with this shiny new toy, there’s a few things you’ll need to set up first:

  • Download the mobile SDK. Download and installation instructions are available in the getting started section of the Mobile SDK docs, but the summarized version is:

    • Download the zip file from the download page

    • Put the libGoogleAnalytics.jar file in your project’s /libs directory

    • Be sure the following lines are in your AndroidManifest.XML file:
      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

  • You’re going to need a Google Analytics account. Go to google.com/analytics and set up an account if you don’t already have one. Then set up a profile for your Android application. When you’re done you’ll see a javascript snippet to insert into your “site”. Copy the part that looks like UA-XXXXXXX-X. You’ll use this in the Android application to tell Analytics which profile the data is being sent for.

Get Tracking

Previous Google Analytics users are going to find a lot of this familiar. In fact, we’ve made a point of keeping the interface as familiar as possible.

First, get your tracker object, and initialize it using the UA code for the Analytics profile you want to track. It makes the most sense to do this in the onCreate() method for your activity main, so it only fires when your application starts up.

GoogleAnalyticsTracker tracker;
protected void onCreate(Bundle savedInstanceState) {
...
tracker = GoogleAnalyticsTracker.getInstance();
tracker.start(“UA-1234-1”, this);

}

The mobile SDK provides support for the 3 main types of data sent to the Google Analytics servers: Pageviews, events, and custom variables.

Pageviews

A pageview is a standard means to measure traffic volume to a traditional website. Given that this is going into an Android app and not a website, it’s going to be up to you to decide what a “pageview” means. Depending on the type of app, each Activity or different views within the same activity (for instance, different tabs within a TabActivity) could count as a pageview.

Whenever you want to trigger a pageview, call the trackPageView() method. It only takes one parameter, the URL you want a pageview counted towards.

tracker.trackPageView("/HomeScreen");

Pageviews make the most sense as full screen transitions, which in most cases will mean “one pageview per Activity.” Therefor it makes the most sense to put the call to trackPageView in the onCreate() method for each activity in your application. An exception would be if you were using a TabActivity, or other scenario where there were multiple full-screen transitions which all occurred within the same Activity, and conceptually mapped to seperate full-screen “pages” being viewed.

Events

In Analytics, events are designed to track user interaction to that doesn’t map to pageviews, like hitting play/pause/stop in a multimedia app. This maps very well to Android usage — Any form of interaction, from hitting certain buttons to adding/removing data from the datastore, can be tracked using Events.

Events are a little more complicated than pageviews, but just slightly. Instead of 1 parameter, you have 4: Category, Action, Label (optional), Value (optional).

To see how to make use of these, let’s imagine you had a media player application, and wanted to track how many times play, pause, and stop were clicked. The code would look like this:

   playButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
...
tracker.trackEvent(
"Media Player", // Category
"Click", // Action
"Play", // Label
0); // Value
}
});

pauseButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
...
tracker.trackEvent(
"Media Player", // Category
"Click", // Action
"Pause", // Label
0); // Value
});

stopEventButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
...
tracker.trackEvent(
"Media Player", // Category
"Click", // Action
"Stop", // Label
currentVideo.getPositionInSeconds()); // Value
});

myMediaPlayer.setFinishedListener(new FinishedListener() {
@Override
public void onFinished(View v) {
...
tracker.trackEvent(
"Media Player", // Category
"Video Finished", // Action
"Stop", // Label
currentVideo.getLengthInSeconds()); // Value
});

Remember that in the Google Analytics web interface, this data is displayed hierarchically — For instance, if you click on Categories in the left nav, and then on “Media Player”, you’ll see a list of all the different possible values of “Action” which have happened in the “media Player” category. Clicking on “Click” will show all the labels which were sent in the Media Player category with an action of “Click”.

The 4th parameter, “value”, is optional, and behaves differently from the others. It’s meant to be cumulative; In this example, I’m sending the amount of video watched when a video is either stopped or allowed to finish. This is aggregated server-side, and when I go to look at my data I’ll be able to see the total time people have spent watching videos using my application.

Custom Variables

The new hotness! Custom variables are name-value pair tags that you can insert in your tracking code in order to refine Google Analytics tracking. The easiest way to think of this is as meta-data accompanying your pageviews and events. Using this metadata, it becomes easy to split off and look at segments of your data, much the same way you use labels in Gmail. One Android-specific example would be to have a “AppType” status with “Full” or “Lite” depending on whether the user has the full version of the app or not. You could then use the Analytics web interface to look at only the “Lite” users, and see how their usage / userbase differs from the “Full” segment. Custom variables are a ridiculously powerful analytical tool, but they’re also a deep topic. I heartily recommend giving the docs a once-through before implementing them in your Android application. Especially make sure to read the section on scoping. Twice. I’m mean it... I’ll wait.

There are 4 parameters in a custom variable: Index (1 to 5 inclusive), Name, Value, and Scope (Optional, defaults to Page Scope).

The place in your code where setCustomVar() will be called depends largely on what scope that variable will be:

  • Visitor scope: Call once the first time your application is run on a device. Don’t create any custom variables at the same index, or they will overwrite the first one. Useful for sending data about which version of the app is being used, what kind of phone, lite vs full version of the app, or anything that won’t change during the lifetime of the installation of that application.

  • Session scope: Call once at the beginning of every Activity startup. Will apply to all pageviews and events for the lifecycle of the activity, unless a different custom variable is created at the same index.

  • Page scope: Call right before trackEvent or trackPageView that the custom variable should apply to, every time that method is called. If no scope is specified, this is the default.

The call to set a custom variable will look like the following:

// Scopes are encoded to integers:  Visitor=1, Session=2, Page=3
tracker.setCustomVar(1, "Navigation type", "Button click", 3);

Choose a Dispatch Mode

In order to optimize for battery life, a request isn’t actually sent out to the server every time you fire a pageview or custom variable. Instead, all the pageviews, events, and their associated custom variables are stored in a local SQLITE database until they’re dispatched as a group to the server. You can set this up to happen one of two ways: Either have the dispatch occur automatically every n seconds, or manually when you call “dispatch” in code. The mode is chosen when you call the start method on your tracker.

Manual dispatch looks like this:

// No time increment sent as a parameter
tracker.start(“UA-1234-1”, this);

// Call this when you want to send the entire event queue to the server
tracker.dispatch();

The timed automatic dispatch looks similar, but sends an extra parameter (the number of seconds between dispatches). In timed dispatch, you never have to manually call dispatch.

// Dispatch all queued pagevies/events every 300 seconds (5 minutes)
tracker.start("UA-YOUR-ACCOUNT-HERE", 300, this);

It’s important to remember that Google Analytics uses the timestamp for when it receives your data, not when the actual pageview/event occurred. This can potentially lead to inaccurate Analytics data, since events can be sent on different days than when they occurred, so take care to dispatch regularly.

The end result

Let’s go back to that onCreate() method we used to instantiate the tracker earlier, and see what it looks like with all the pieces in place:

GoogleAnalyticsTracker tracker;

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

tracker = GoogleAnalyticsTracker.getInstance();
tracker.start(“UA-1234-1”, this);

if(isFirstTimeRunningApplication()) {
tracker.setCustomVar(1, “App Type”, “Demo”, 1);
}
tracker.trackPageView("/HomeScreen");


}

How to look at all this data

There are two ways you can approach this. First, Google Analytics has a pretty snazzy web interface, which does a very good job of surfacing useful information for you. If you’re new to Analytics and don’t really know what you’re looking for yet, the web interface is a great way to explore your data and understand your users.

If you already have a strong idea of the questions you want to ask (app usage across versions of the Android platform, growth rates, time-in-app per demo user vs full user, how many people beat level 3 on their first try, etc), and just want to automate the asking, Google Analytics also has a swanky data export API, with client libraries to facilitate the querying of your data in Java, Python, JavaScript, and C#.

Abiding by the TOS

Google Analytics comes with its own TOS, and it’s important to read and abide by it. The important bit, especially since this will be used inside Android applications, is that you cannot send personally identifying information to Analytics servers. This is a big deal. It means, for instance, that a visitor-level custom variable cannot contain a phone number, first name, or email address. Less intuitively, but still important, it means that if this application is a client to a web application (say, CRM software or a shopping site), you also cannot store information in Analytics which can be combined with your own backend software to identify the user, such as user ID or a transaction ID identical to the one stored on your web backend.

Sunday, December 12, 2010

New Gingerbread API: StrictMode

[This post is by Brad Fitzpatrick, an Android Software Engineer who worries unreasonably about responsiveness. —Tim Bray]

Back Story

One great thing about Google is “20% time”: spending 20% of your time working on projects outside your main focus area. When I joined Google, I bounced all over the place, often joking that I had seven 20% projects. One project I kept coming back to was Android. I loved its open nature, giving me access to do whatever I wanted, including opening my garage door when I approached my house on my motorcycle. I really wanted it to succeed but I worried about one thing: It wasn’t always super smooth. Animations would sometimes stutter and UI elements weren’t always immediately responsive to input. It was pretty obvious that things were sometimes happening on the wrong thread.

As a heavy SMS user, one of my 20% projects during the Cupcake (Android 1.5) release was speeding up the Messaging app and making it feel smoother. I got the app to a happy state and then continued bouncing between other 20% projects. When the Donut (Android 1.6) release came out, I noticed that a few of my Messaging optimizations had been accidentally broken. I was sad for a bit but then I realized what Android really needed was always-on, built-in, pervasive performance monitoring.

I joined the Android team full-time just over a year ago and spent a lot of time investigating Froyo performance issues, in particular debugging ANRs (those annoying dialogs you get when an application stalls its main thread’s Looper). Debugging ANRs with the tools at hand was painful and boring. There wasn’t enough instrumentation to find the causes, especially when multiple processes were involved (doing Binder or ContentResolver operations to Services or ContentProviders in other processes). There had to be a better way to track down latency hiccups and ANRs...

Enter StrictMode

“I see you were doing 120 ms in a 16 ms zone...”



StrictMode is a new API in Gingerbread which primarily lets you set a policy on a thread declaring what you’re not allowed to do on that thread, and what the penalty is if you violate the policy. Implementation-wise, this policy is simply a thread-local integer bitmask.

By default everything is allowed and it won’t get in your way unless you want it to. The flags you can enable in the thread policy include:

  • detect disk writes


  • detect disk reads


  • detect network usage


  • on a violation: log


  • on a violation: crash


  • on a violation: dropbox


  • on a violation: show an annoying dialog


In addition, StrictMode has about a dozen hooks around most of the places that hit the disk (in java.io.*, android.database.sqlite.*, etc) and network (java.net.*) which check the current thread’s policy, reacting as you’ve asked.

StrictMode’s powerful part is that the per-thread policies are propagated whenever Binder IPC calls are made to other Services or Providers, and stack traces are stitched together across any number of processes.

Nobody wants to be slow

You might know all the places where your app does disk I/O, but do you know all the places where the system services and providers do? I don’t. I’m learning, but it’s a lot of code. We’re continually working to clarify performance implications in the SDK docs, but I usually rely on StrictMode to help catch calls that inadvertently hit the disk.

Background on disks on phones

Wait, what’s wrong with hitting the disk? Android devices are all running flash memory, right? That’s like a super-fast SSD with no moving parts? I shouldn’t have to care? Unfortunately, you do.

You can’t depend on the flash components or filesystems used in most Android devices to be consistently fast. The YAFFS filesystem used on many Android devices, for instance, has a global lock around all its operations. Only one disk operation can be in-flight across the entire device. Even a simple “stat” operation can take quite a while if you are unlucky. Other devices with more traditional block device-based filesystems still occasionally suffer when the block rotation layer decides to garbage collect and do some slow internal flash erase operations. (For some good geeky background reading, see lwn.net/Articles/353411)

The take-away is that the “disk” (or filesystem) on mobile devices is usually fast, but the 90th percentile latencies are often quite poor. Also, most filesystems slow down quite a bit as they get more full. (See slides from Google I/O Zippy Android apps talk, linked off code.google.com/p/zippy-android)

The “main” Thread

Android callbacks and lifecycle events all typically happen on the main thread (aka “UI thread”). This makes life easier most of the time, but it’s also something you need to be careful of because all animations, scrolls, and flings process their animations by callbacks on the main thread.

If you want to run an animation at 60 fps and an input event comes in (also on the main thread), you have 16 ms to run your code reacting to that input event. If you take longer than 16 ms, perhaps by writing to disk, you’ve now stuttered your animation. Disk reads are often better, but they can also take longer than 16 ms, especially on YAFFS if you’re waiting for the filesystem lock that’s held by a process in the middle of a write.

The network is especially slow and inconsistent, so you should never do network requests on your main thread. In fact, in the upcoming Honeycomb release we’ve made network requests on the main thread a fatal error, unless your app is targeting an API version before Honeycomb. So if you want to get ready for the Honeycomb SDK, make sure you’re never doing network requests on your UI thread. (see “Tips on being smooth” below.)

Enabling StrictMode

The recommended way to use StrictMode is to turn it on during development, learn from it, and turn it off before you ship your app.

For example, in your application or component’s onCreate():

 public void onCreate() {
if (DEVELOPER_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build());
}
super.onCreate();
}

Or, simply:

    public void onCreate() {
if (DEVELOPER_MODE) {
StrictMode.enableDefaults();
}
super.onCreate();
}

That latter form was specifically added so you can target pre-Gingerbread API versions but still easily enable StrictMode using reflection or other techniques. For instance, you could be targeting Donut (Android 1.6) but still use StrictMode if you’re testing on a Gingerbread device or emulator, as long as you use enough Reflection to call StrictMode.enableDefaults().

Watching StrictMode

If you’re using penaltyLog(), the default, just run adb logcat and watch the terminal output. Any violations will be logged to your console, slightly rate-limited for duplicate elimination.

If you want to get fancier, turn on penaltyDropbox() and they’ll be written to the DropBoxManager, where you can extract them later with

adb shell dumpsys dropbox data_app_strictmode --print

Tips on being smooth

In addition to Thread and java.util.concurrent.*, check out some of the Android APIs such as Handler, AsyncTask, AsyncQueryHandler, and IntentService.

Our Experience

During Android development we have a new “dogfood” build each day that the whole team uses. Throughout the development of Gingerbread we set up our daily dogfood builds to enable StrictMode logging and upload all found violations for analysis. Every hour a MapReduce job runs and produces an interactive report of all the event loop stalls, their stack traces (including cross-process ones), their latency percentiles, which processes/packages they appear in, etc.

Using the data from StrictMode we fixed hundreds of responsiveness bugs and animation glitches all across the board. We made performance optimizations in the Android core (e.g. system services and providers) so all apps on the system will benefit, as well as fixing up tons of app-specific issues (in both AOSP apps and Google apps). Even if you’re using Froyo today, the recent updates to GMail, Google Maps, and YouTube all benefited from StrictMode data collection gathered on Gingerbread devices.

Where we couldn’t automatically speed up the system, we instead added APIs to make certain patterns easier to do efficiently. For example, there is a new method SharedPreferences.Editor.apply(), which you should be using instead of commit() if you don’t need commit()’s return value. (It turns out almost nobody ever checks it.) You can even use reflection to conditionally use apply() vs. commit() depending on the user’s platform version.

Googlers who switched from Froyo to Gingerbread without seeing all the baby steps between were shocked at how much more responsive the system became. Our friends on the Chrome team then recently added something similar. Of course, StrictMode can’t take all the credit. The new concurrent garbage collector in Gingerbread also greatly reduces latency hiccups.

The Future

The StrictMode API and its capabilities will continue to expand. We have some good stuff lined up for StrictMode in Honeycomb but let us know what else you’d like to see! I’ll be answering questions on stackoverflow.com for questions tagged “strictmode”. Thanks!

Friday, December 10, 2010

Android Market Client Update

[This post is by Eric Chu, Android Developer Ecosystem. —Dirk Dougherty]

The Android Market engineering team has been hard at work on improving the Android Market experience for users and developers. Today, I’m pleased to announce a significant update to the Android Market client. Over the next two weeks, we’ll be rolling out a new Android Market client to all devices running Android 1.6 or higher.

This new Market client introduces important features that improve merchandising of applications, streamline the browse-to-purchase experience, and make it easier for developers to distribute their applications.

With a focus on improving discoverability and merchandising, we’ve introduced a new carousel on the home and category screens. Users can quickly flip through the carousel to view promoted applications and immediately go to the download page for the application they want. Developers have been very active in creating great Widgets and Live Wallpapers. To make it easier for users to find their favorites, we’re introducing two new categories for Widgets and Live Wallpapers. Applications that include Widgets and Wallpapers will be automatically added to those new categories. We’ll also be adding more categories for popular applications and games in the weeks ahead. In addition, the app details page now includes Related content, which makes it easier for users to quickly find apps of similar interest.




To streamline the browse-to-purchase experience, users can now access all the information about an application on a single page without the need to navigate across different tabs. We’re also introducing application content rating to provide users with more information about applications they are interested in. Since most users who request a refund do so within minutes of purchase, we will reduce the refund window on Market to 15 minutes. This change will be largely transparent to buyers, but will help developers manage their businesses more effectively.



To make it easier for developers to distribute and manage their products, we will introduce support for device targeting based on screen sizes and densities, as well as on GL texture compression formats. We are also increasing the maximum size for .apk files on Market to 50MB, to better support richer games.

With this release, we aimed to deliver features that are most requested by users and developers. However, we’re not done yet. We plan to continue to rapidly enhance Android Market for both users and developers and make it the best content distribution service for the Android ecosystem.

Please stay tuned as we continue to deliver new capabilities in the coming weeks and months.

Thursday, December 9, 2010

Saving Data Safely

With the advent of Gingerbread, we’re going to be running a series of posts in this space about the aspects of Android 2.3 that developers should care about. One thing that developers should care about more than anything else is not losing data. The rules are changing slightly as Gingerbread arrives, so I thought that would be a good starting point. I didn’t write this; I pulled it together from the contents of an email thread involving Android engineers Brad Fitzpatrick, Dianne Hackborn, Brian Swetland, and Chris Tate.

The question is: how do you make really sure your data’s been written to persistent storage? The answer involves a low-level system call named fsync(). Old C programmers like me mostly learned this the hard way back in the Bad Old Days; in 2008 at OSCON I immensely enjoyed Eat My Data: How Everybody Gets File IO Wrong by Stewart Smith; I've included a picture I took of one of his slides.

The reason this should be of concern to Android developers is that with 2.3, an increasing proportion of devices, notably including the Nexus S, are going to be moving from YAFFS to the ext4 filesystem, which buffers much more aggressively; thus you need to be more assertive about making sure your data gets to permanent storage when you want it to.

If you just use SharedPreferences or SQLite, you can relax, because we’ve made sure they Do The Right Thing about buffering. But if you have your own on-disk format, keep in mind that your data doesn't actually consistently reach the flash chip when you write() it or even when you close() it. There are several layers of buffering between you and the hardware! And because of ext4 buffering policy, any POSIX guarantees that you thought you had before (but actually didn't), you especially don't have now.

Some Android devices are already running non-YAFFS filesystems, but as we brought up the Nexus S, buffering issues have actually bitten us a couple of times in framework code. When the Gingerbread source code becomes available, you’ll find lots of examples of how file I/O should be done.

To start with, for raw data consider using one of the synchronous modes of java.io.RandomAccessFile, which take care of calling fsync() for you in the appropriate way. If you can’t, you’ll want Java code that looks something like this.

     public static boolean sync(FileOutputStream stream) {
try {
if (stream != null) {
stream.getFD().sync();
}
return true;
} catch (IOException e) {
}
return false;

In some applications, you might even want to check the return status of the close() call.

Now of course, there are two sides to this story. When you call fsync() and force the data onto storage, that can be slow; worse, unpredictably slow. So be sure to call it when you need it, but be careful not to call it carelessly.

Background reading if you want to know more:

Monday, December 6, 2010

Android 2.3 Platform and Updated SDK Tools

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.

Wednesday, November 24, 2010

Content Rating for Android Market

[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.

Thursday, November 11, 2010

Market Housekeeping Alert

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.

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.

Wednesday, November 10, 2010

Android Market Action

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.

Thursday, October 21, 2010

Improving App Quality

[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.

Listen to your users

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.

Improve stability and eliminate bugs

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.

Improve UI Responsiveness

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:

Improve usability

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.

Improve appearance and aesthetics

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.

Deliver the right set of features

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.

Integrate with the system and third-party apps

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.

More resources:

Pay attention to details...

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.

...and more...

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!

Thursday, October 14, 2010

Traceview War Story

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.

Making Apps Fast

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.

Case Study: LifeSaver 2

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.

Turning On Tracing

I went into Saver.java and bracketed the code in its run() method like so:

       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.

[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.

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).

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.

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.

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.

The Conclusion

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.

Traceview is a nice tool, and if you don’t already know it, you owe it to yourself to learn it.

Monday, October 11, 2010

The Five Steps to Future Hardware Happiness

[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"/>

Market won’t be inferring any future API features

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.

The 5 steps to future hardware happiness

  1. 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:

  2. 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.

    <uses-feature android:name="android.hardware.telephony"
                  android:required="true"/>

  3. For features that aren’t strictly required, set required=false.

    <uses-feature android:name="android.hardware.bluetooth"
                  android:required="false"/>

  4. 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);

  5. 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.

Thursday, October 7, 2010

Android Market New Country Roll-out Details

[This post is by the Android Market team. — Tim Bray]

Last week, we announced that over the next two weeks, users in 18 additional countries would gain the ability to purchase paid apps from Android Market. Effective today, users can now see paid apps in Argentina, Belgium, Brazil, Czech Republic, Denmark, Finland, Hong Kong, India, Ireland, Israel, Mexico, Norway, Poland, Portugal, Russia, Singapore, Sweden, and Taiwan.

For users to make a purchase of paid apps in these countries, they must have the latest Android Market client, which we have started to make available as a self-update and should reach all users within the next few days. This is a silent update; users will not see a notification and will not be prompted to do anything. If you want to accelerate the self-update process, launch Android Market, navigate back to the Home screen, and after 5-10 minutes, relaunch it. For more details, please refer to the Help Center.

No action is necessary if you have targeted your paid apps to be available to “All Locations” and would like to launch in these additional countries. If you have not selected “All Locations” and would like to target these additional countries, or if you have selected “All Locations” and do not want to launch your apps in these additional buyer countries, please visit the Android Market publisher site to make the necessary adjustments.

Thursday, September 30, 2010

More Countries, More sellers, More buyers

[This post is by Eric Chu, Android Developer Ecosystem. — Tim Bray]

Since we launched Android and Android Market, we have seen the population of Android users and devices expand into many countries. This widespread adoption has brought with it growing interest in Android Market’s support for the buying and selling of paid applications in these additional countries.

We have been hard at work on this and it is my pleasure to announce that effective today, developers from 20 more countries can now sell paid apps on Android Market. Additionally, over the next 2 weeks, users in 18 additional countries will be able to purchase paid apps from Android Market.

Support for paid application sales is now expanded to developers in 29 countries, with today’s additions of Argentina, Australia, Belgium, Brazil, Canada, Denmark, Finland, Hong Kong, Ireland, Israel, Mexico, New Zealand, Norway, Portugal, Russia, Singapore, South Korea, Sweden, Switzerland and Taiwan.

In addition, Android Market users from 32 countries will be able to buy apps, with the addition of Argentina, Belgium, Brazil, Czech Republic, Denmark, Finland, Hong Kong, India, Ireland, Israel, Mexico, Norway, Poland, Portugal, Russia, Singapore, Sweden, and Taiwan. No action is necessary if you have targeted your paid apps to be available to “All Locations” and would like to launch in these additional countries. If you have not selected “All Locations” and would like to target these additional countries, or if you have selected “All Locations” and do not want to launch your apps in these additional buyer countries, please visit the Android Market publisher site regularly over the next two weeks to make the necessary adjustments as the new buyer countries launch.

We remain committed to continuing to improve the buyer and seller experiences on Android Market. Among other initiatives, we look forward to bringing the Android Market paid apps ecosystem to even more countries in the coming months. Please stay tuned.

Tuesday, September 28, 2010

Reflections on G-Kenya

[This post is by Reto Meier AKA @retomeier, who wrote the book on Android App development. — Tim Bray]

Recently I visited Kenya for the three-day G-Kenya event. I was there for two reasons:

  • To talk about Android and the emerging mobile opportunities for African developers.

  • To ask questions and find out more about the reality of mobiles and writing code from the people there.

Of the countries I’ve visited to talk about Android, nowhere have people had such a close connection to their mobile phones as in Africa. While most Kenyans own feature phones, those mobiles are already used as much more than simple phones. Mobile payments are already common, and cheap data plans mean that many people access the Internet exclusively through mobile handsets.

There were two Android announcements while I was in town: a new low-cost Android handset (the Huawei U8220), and Android Market access for Kenyans. I can’t wait to see the kind of apps that come from developers who live in an environment where mobile is so pervasive.

Day 1: Students

G-Kenya was set within the beautiful campus of the Strathmore Business School, so it was fitting that day one was addressed to students.

Of the three groups, the students where the most enthusiastic about Android. This was likely influenced by their confidence that by the time they graduate, modern smartphones in Africa will have become the norm.

I love talking to student developers — without the commercial pressures of finding customers or a monetization model — they're free to innovate on whatever technology platforms they think are interesting.

Day 2: Developers

Modern smartphones are not yet prevalent in Africa, so it wasn’t surprising that many of the developers are currently focusing on feature phones. That said, it was generally acknowledged that it was a question of when rather than if smartphones would come to dominate. The trick will be picking the right time to invest in Android so that they're ready to take advantage.

Plenty of developers believe that time is right now. It was a pleasure to meet the guys behind Ushahidi, creators of an Android app created to report and record incidents during the 2008 election violence. Since their launch they’ve expanded to offer a global platform for crowd-sourced news where timeliness is critical.

I love opportunity the Android Market delivers to developers like the idea of developers like Ushahidi and Little Fluffy Toys (of London Cycle Hire fame). An app the solves a problem for your local community can easily be expanded to offer solutions to similar problems across the world.

Developer focus in Kenya seemed to follow similar lines:

  • Create products and services targeted at local communities (such as the developers creating a distributed system to help health-care workers record medical information in the field.)

  • Build robust cloud-based services that provide access to users from any mobile platform.

  • Expand from feature phones to Android to incorporate features like GPS positioning, maps, and recording video and audio.

Day 3: Entrepreneurs and Marketers

No one was surprised to see a lot of the developers from the previous day return for entrepreneur day, and the apparent lack of Android questions from Day 2 was more than made up for on day 3; the “AppEngine Challenge” on Day 2 fielded a record 30 entries, so it seems everyone was working on their entries rather than asking questions!

I didn’t speak on Day 3, but spent all day fielding questions from eager mobile developers hoping to catch the Android wave as early innovators and first movers. That included a team who were working to provide real-time public transit tracking of Matatu via GPS and Android devices.

Reflections

It’s an exciting time to be a developer in Kenya. I regularly asked developers how long they thought it would take for Android devices to become common place. Many suggested if I came back this time next year I'd see a flood of Android devices. Even the more pessimistic predicted no more than 3 years.

As I traveled back towards Jomo Kenyatta International, listening to the radio offering a free Sony Ericsson X10 Mini to one lucky caller, the future didn’t seem very far away.

Tuesday, September 21, 2010

Proguard, Android, and the Licensing Server

[This post is by Dan Galpin, an Android Developer Advocate specializing in games and comics. — Tim Bray]

The Securing Android LVL Applications blog post makes it clear that an Android developer should use an obfuscation tool such as Proguard in order to help safeguard their applications when using License Server. Of course, this does present another question. How should one integrate such a tool with the Android build process? We’re specifically going to detail integrating Proguard in this post.

Before you Begin

You must be running the latest version of the Android SDK Tools (at least v7). The new Ant build rules file included with v7 contains hooks to support user-created pre and post compile steps in order to make it easier to integrate tools such as Proguard into an Android build. It also integrates a single rules file for building against all versions of the Android SDK.

Adding an Optimization Step to build.xml

First, you’ll have to get Proguard if you don’t yet have it.

If you’ve been using Eclipse to do your development, you’ll have to switch to using the command line. Android builds are done using Apache Ant. A version of Ant ships along with Eclipse, but I recommend installing your own version.

The Android SDK can build you a starter build.xml file. Here is how it’s done:

android update project --path ./MyAndroidAppProject

If all works well, you’ll have a shiny new build.xml file sitting in your path. Let’s try doing a build.

ant release

You should end up with an unsigned release build. The command-line tools can also sign your build for you. You’ll notice that the android tool created a local.properties file in your directory. It will contain the sdk.dir property. You can have it make you a signed build by adding the location of your keystore and alias to this file.

key.store=/Path/to/my/keystore/MyKeystore.ks
key.alias=myalias

So, now you have a signed build from the command line, but still no obfuscated build. To make things easy, you’re going to want to get two helper files: add-proguard-release.xml and procfg.txt.

Copy these files into your root directory (where the build.xml file sits). To add Proguard to your build, you first need to edit your local properties file to add the location of the directory that Proguard is installed in:

proguard.dir=/Directory/Proguard/Is/Installed/In

Finally... you need to add our script to your build file and have it override a few targets. To do this, we use the XML “entity” construct. At the top of your build.xml file, add an entity that references our script file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE project [
<!ENTITY add-proguard-release SYSTEM "add-proguard-release.xml">
]>

You’re not done yet. Somewhere within the project tag add the reference to our entity to include our script.

<project name="MyProjectName" default="help">
&add-proguard-release;

That’s it! In many cases, calling

ant release

Will give you an obfuscated build. Now test and make sure that it hasn’t broken anything.

But Wait, My App is Crashing Now

Most crashes happen because Proguard has obfuscated away something that your application needs, such as a class that is referenced in the AndroidManifest or within a layout, or perhaps something called from JNI or reflection. The Proguard configuration provided here tries to avoid obfuscating most of these cases, but it’s still possible that in edge cases you’ll end up seeing something like a ClassNotFoundException.

You can make edits to the procfg.txt file to keep classes that have been obfuscated away. Adding:

-keep public class * [my classname]

should help. For more information about how to prevent Proguard from obfuscating specific things, see the Proguard manual. Specifically, the keep section. In the interest of security, try to keep as little of your application unobfuscated as possible.

The standard settings provided in procfg.txt will be good for many applications, and will catch many common cases, but they are by no means comprehensive. One of the things that we’ve done is had Proguard create a bunch of output files in the obf directory to help you debug these problems.

The mapping.txt file explains how your classes have been obfuscated. You’ll want to make sure to keep this around once you have submitted your build to Market, as you’ll need this to decipher your stack traces.

Conclusion

Tools such as Proguard make the binary of your application harder to understand, and make your application slightly smaller and more efficient at the same time, at the cost of making it slightly more challenging to debug problems in the field. For many applications, the tradeoff is more than worthwhile.