Tuesday, March 13, 2012

Unifying Key Store Access in ICS

[This post is a group effort by Tony Chan, Fred Chung, Brian Carlstrom, and Kenny Root. — Tim Bray]



Android 4.0 (ICS) comes with a number of enhancements that make it easier for people to bring their personal Android devices to work. In this post, we’re going to have a look at the key store functionality.

Back in Android 1.6 (Donut), a system key store was added for use by VPN. Although this was later expanded to support WiFi authentication, applications weren’t able to access it.

In the past, it was common practice for apps to maintain their own key store if they needed to authenticate a secure SSL web server, or authenticate the user to a server via a client certificate. While this works, it can present manageability issues in an enterprise environment where multiple certificates may be shared across a number of apps such as Email and Browser.

New in ICS: KeyChain

To bridge the gap in ICS, there’s a new API named KeyChain that regulates application access to the system key store and allows users to grant application access to the credentials stored there. Additionally, this API enables applications to initiate installation of credentials from X.509 certificates and PKCS#12 key stores.

The KeyChain API is rather simple. To install a key store or a certificate, you retrieve an install intent, supply the raw bytes of the credentials, and use the intent to launch a system installation dialog. If it’s a keystore, as in the example below, you’ll need provide the data in PKCS#12 format, and the user will have to know the PKCS#12 password.

  byte[] keystore = . . (read from a PKCS#12 keystore)

Intent installIntent = KeyChain.createInstallIntent();
installIntent.putExtra(KeyChain.EXTRA_PKCS12, keystore);
startActivityForResult(installIntent, INSTALL_KEYSTORE_CODE);

The install intent launches a system dialog that prompts the user to enter the password for the keystore.

This can also be used for installing organizational CA certificates which will then be trusted by all applications to authenticate to non-public servers with certificates issued by the same CA.

In ICS, Android no longer requires a separate password to protect the system credential storage. Rather, it uses the screen lock password for this purpose, and the Android Device Administration API can be used for central policy enforcement. This means, for example, that the screen lock password can’t be removed as long as the secured credentials remain on the device.

Accessing System Key Store Credentials

Once the system key store is configured, the KeyChain API offers functions such as requesting a client certificate for authenticating with an SSL server. The first time an application requests access, the user is prompted with a list of available certificates and can select one to grant access to that certificate to the application. If the user chooses to allow access to a certificate, a string alias name for the certificate is returned to the application. The application can then use the alias to access the certificate in the future without further user involvement.

The code below illustrates how an application can prompt the user to select a credential alias and grant access to the application. KeyChain will remember this selection such that the same application can save the credential alias selection and have access to the same certificate in future. For example, the Email application for ICS has implemented this feature in its Server Settings screen.

  KeyChain.choosePrivateKeyAlias(this,
new KeyChainAliasCallback() {

public void alias(String alias) {
// Credential alias selected. Remember the alias selection for future use.
if (alias != null) saveAlias(alias);
}
},
new String[] {"RSA", "DSA"}, // List of acceptable key types. null for any
null, // issuer, null for any
"internal.example.com", // host name of server requesting the cert, null if unavailable
443, // port of server requesting the cert, -1 if unavailable
null); // alias to preselect, null if unavailable

Once an application has been granted access to the certificate, it can access the private key through the getPrivateKey() method. It is worth noting that as with any PrivateKey objects, the application should not make assumptions about the encoding. For example, on some implementations the PrivateKey object may just be an opaque representation of a key stored in a hardware key store.

Here’s a sample code snippet that demonstrates the use of private key retrieved from the key store for signing:

    PrivateKey privateKey = KeyChain.getPrivateKey(context, savedAlias);
if (privateKey != null) {
...
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(privateKey);
...
}

A common use of the private key is for SSL client authentication. This can be implemented by using an HttpsURLConnection with a custom X509KeyManager that returns the PrivateKey retrieved from the KeyChain API. The open source Email application for ICS uses KeyChain with an X509ExtendedKeyManager. To learn more, have a look at the source code (in SSLUtils.java).

This API provides a unified way to access the system key store credentials. If your application uses client certificates (take note: enterprise email client or web browser developers) you should definitely look into the KeyChain API for your next update!

Tuesday, March 6, 2012

Introducing Google Play



[This post is by Kenneth Lui, Android Developer Ecosystem. —Dirk Dougherty]

For more than a year we’ve been focused on expanding the reach, content, and monetization opportunities of Android Market. We started by extending the store to users on the web and then went on to add books, movies, and music. The number of people who have visited, registered, and downloaded from the store has been amazing.



Today we’re launching Google Play, an integrated destination for apps, books, movies, and music, accessible to users on Android devices and to anyone on the Web. As part of this launch, Google Play replaces and extends Android Market — users everywhere can now find their favorite apps and games in Google Play, with other digital content, all in one place.



We believe that with a strong brand, compelling offerings, and a seamless purchasing and consumption experience, Google Play will drive more traffic and revenue to the entire ecosystem.



We’ll be investing in the brand to bring Google Play to as many people as possible, and we’ll also invest in the latest digital content to keep Google Play fresh, relevant, and engaging. Apps and games remain the core of Google Play, so we’ll continue investing in new ways to connect users with their favorite apps, and developers with new customers.







As we grow and promote Google Play around the world, we’ll be marketing your apps and games at the same time. Our policies have not changed and our goal is still the same — to create a great, open marketplace for distributing Android apps.



Google Play is built on the same infrastructure as Android Market, so the transition for users and developers will be seamless. Users can sign into their existing accounts with the same credentials as before and purchase content using the same payment methods. As a developer, there’s no change needed to your published products and you can continue to use the same publishing tools to put your app in front of hundreds of millions of Android users. If your app was in Android Market yesterday, it’s in Google Play today.



We’ll be rolling out Google Play to devices in a phased OTA update, starting today and continuing over the days to come. With the update, the Android Market app will upgrade to the Play Store app and the Music, Videos, and Books apps will upgrade to Play Music, Play Movies, and Play Books. This update is for devices running Android 2.2 or higher, and users on other devices will continue to have the same access to your apps as before.



You can start sending customers to your products in Google Play right away. Check out the updated “Get it on Google Play” badges and look for an email with more details on the transition. In the meantime, you can check out the Google Play web site at the link below and join the discussion on +Android Developers.



http://play.google.com

Monday, March 5, 2012

Android Apps Break the 50MB Barrier

Android applications have historically been limited to a maximum size of 50MB. This works for most apps, and smaller is usually better — every megabyte you add makes it harder for your users to download and get started. However, some types of apps, like high-quality 3D interactive games, require more local resources.

So today, we’re expanding the Android app size limit to 4GB.

The size of your APK file will still be limited to 50MB to ensure secure on-device storage, but you can now attach expansion files to your APK.

  • Each app can have two expansion files, each one up to 2GB, in whatever format you choose.

  • Android Market will host the files to save you the hassle and cost of file serving.

  • Users will see the total size of your app and all of the downloads before they install/purchase.

On most newer devices, when users download your app from Android Market, the expansion files will be downloaded automatically, and the refund period won’t start until the expansion files are downloaded. On older devices, your app will download the expansion files the first time it runs, via a downloader library which we’ve provided below.

While you can use the two expansion files any way you wish, we recommend that one serve as the initial download and be rarely if ever updated; the second can be smaller and serve as a “patch carrier,” getting versioned with each major release.

Helpful Resources

In order to make expansion file downloading as easy as possible for developers, we're providing sample code and libraries in the Android SDK Manager.

  • In the Google Market Licensing package, an updated License Verification Library (LVL). This minor update mostly adds the ability to obtain expansion file details from the licensing server.

  • From the Google Market APK Expansion package, the downloader service example. The library makes it relatively simple to implement a downloader service in your application that follows many of our best practices, including resuming downloads and displaying a progress notification.

Because many developers may not be used to working with one or two large files for all of their secondary content, the example code also includes support for using a Zip file as the secondary file. The Zip example implements a reasonable patching strategy that allows for the main expansion file to “patch” the APK and the patch file to “patch” both the APK and the main expansion file by searching for asset files in all three places, in the order patch->main->APK.

Expansion File Basics

Expansion files have a specific naming convention and are located in a specific place for each app. As expansion files are uploaded to the publisher site, they are assigned a version code based upon the version of the APK that they are associated with. The naming convention and location are as follows:

Location: <shared-storage>/Android/obb/<package-name>/
Filename: [main|patch].<expansion-version>.<package-name>.obb
Example: /sdcard/Android/obb/com.example.myapp/main.5.com.example.myapp.obb

Expansion files are stored in shared storage. Unlike APK files, they can be read by any application.

Downloading and Using the Expansion Files

When the primary activity for the app is created, it should check to make sure the expansion files are available. The downloader library provides helper functions (for example the “Helpers” class in the code below) to make this easy.

boolean expansionFilesDelivered() {
// get filename where main == true and version == 3
String fileName = Helpers.getExpansionAPKFileName(this, true, 3);
// does the file exist with FILE_SIZE?
if (!Helpers.doesFileExist(this, fileName, FILE_SIZE, false)) {
return false;
}
return true;
}

If the file does not exist, fire up the downloader service with DownloaderClientMarshaller.startDownloadServiceIfRequired(). The downloader will perform an LVL check against the server. This check will deliver the names of the files, file sizes, and the file URLs.

Once that check has been completed, it will begin downloading the files. You don’t have to use our download solution, but you might want to because we:

  • Include a notification UI that provides progress and estimated completion time in layouts customized for ICS and pre-ICS devices

  • Resume large files safely

  • Handle redirection with appropriate limits

  • Run in the background as a service

  • Pause and resume downloads when WiFi is not available

Enjoy! We can’t wait to see what kinds of things developers do with this! For more information about how to use expansion files with your app, read the APK Expansion Files developer guide.

[This post wasn’t actually written by anyone, but bashed out by a posse of engineering and product-management people. Heavy bashers included Dan Galpin, Ilya Firman, Andy Stadler, Michael Siliski, and Ellie Powers.]

Wednesday, February 29, 2012

Android Design V2: Now with stencils

[This post is by Android designer Alex Faaborg, on behalf of the entire User Experience team. —Tim Bray]

When we initially released Android Design, by far the number one request we received was for us to release stencils as well. The fine folks on the Android User Experience team are pleased today to release some official Android Design stencils for your mockup-creating pleasure.

With these stencils you can now drag and drop your way to beautifully designed Ice Cream Sandwich (Android 4.0) applications, with grace and ease. The stencils feature the rich typography, colors, interactive controls, and icons found throughout Ice Cream Sandwich, along with some phone and tablet outlines to frame your meticulously crafted creations.

Currently we have stencils available for those venerable interactive design powerhouses Adobe® Fireworks®, and Omni® OmniGraffle® and we may expand to other applications® in the future. The source files for the various icons and controls are also available, created in Adobe® Photoshop®, and Adobe® Illustrator®. Here are the downloads.

We’ll be updating these stencils over time so, as always, please send in your feedback!

Happy mockup making,

— Your friendly Android Design Droids

Tuesday, February 28, 2012

New App Stats for Publishers on Android Market



If you've published an app on Android Market, you’ve probably used Application Statistics to help tune your development and marketing efforts. Application Statistics is a set of dashboards in the Developer Console that shows your app’s installation performance across key dimensions such as countries, platform versions, device models, and others. Today we are making Application Statistics even more powerful for publishers, adding new metrics, new ways to analyze your data, and a redesigned UI that’s much easier to use.

First, we are adding important new installation metrics to the dashboards. You can now see your installations measured by unique users, as well as by unique devices. For user installations, you can view active installs, total installs, and daily installs and uninstalls. For devices, you can see active installs as well as daily installs, uninstalls, and upgrades.



Along with the new metrics, we’re also introducing two new data dimensions — Carrier and App Version. You can use them to track your app’s installation trends across mobile operators or monitor the launch metrics of specific app updates.



To give you visibility over your installation data over time, we’re adding timeline charts for all metrics and dimensions. At a glance, these charts highlight your app’s installation peaks and longer-term trends, which you can correlate to promotions, app improvements, or other factors. You can even focus in on data inside a dimension by adding specific points (such as individual platform versions or languages) to the timeline.



Finally, we’re bringing you all of the new metrics, dimensions, and timelines in a completely redesigned UI that is faster, more compact, and easier to use. Each dimension is now displayed in dedicated tab, making it easier to click through your stats daily or as often as needed. If you track your stats in another tool, we’re also adding an export capability that lets you download your stats in a single CSV file.



Check out the new Application Statistics next time you visit the Android Market Developer Console. We hope they’ll give you new insight into your app’s user base and installation performance. Watch for related announcements soon — we are continuing to work on bringing you the reporting features you need to manage your products successfully on Android Market.



Please feel free to share any new insights or tips on +Android Developers!

Thursday, February 9, 2012

Share With Intents

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

[Please join the discussion on Google+.]

Intents are awesome. They are my favorite feature of Android development. They make all sorts of stuff easier. Want to scan a barcode? In the olden platforms, if you were lucky, this involved time and effort finding and comparing barcode-scanning libraries that handled as much as possible of camera interaction, image processing, an internal database of barcode formats, and UI cues to the user of what was going on. If you weren’t lucky, it was a few months of research & haphazard coding to figure out how to do that yourself.

On Android, it’s a declaration to the system that you would like to scan a barcode.

public void scanSomething() {
// I need things done! Do I have any volunteers?
Intent intent = new Intent("com.google.zxing.client.android.SCAN");

// This flag clears the called app from the activity stack, so users arrive in the expected
// place next time this application is restarted.
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);

intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
startActivityForResult(intent, 0);
}
...
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == 0) {
if (resultCode == RESULT_OK) {
// The Intents Fairy has delivered us some data!
String contents = intent.getStringExtra("SCAN_RESULT");
String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
// Handle successful scan
} else if (resultCode == RESULT_CANCELED) {
// Handle cancel
}
}
}

See that? That’s nothing. That’s 5 minutes of coding, 3 of which were just to look up the name of the result you wanted to pull. And that was made possible because the Barcode Scanner application is designed to be able to scan barcodes for whatever other applications may need it.

More important, our app is completely decoupled from the BarcodeScanner app. There’s no integration- in fact, neither application is checking to verify that the other exists. If the user preferred, they could remove “Barcode Scanner” and replace it with a competing app. As long as that app supported the same intent, functionality would remain the same. This decoupling is important. It’s the easy way. It’s the lazy way. It’s the Android way.

Sharing Data Using Intents

One of the most inherently useful Android intents is the Share intent. You can let the user share data to any service they want, without writing the sharing code yourself, simply by creating a share intent.

Intent intent=new Intent(android.content.Intent.ACTION_SEND);
intent.setType("text/plain");
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);

// Add data to the intent, the receiving app will decide what to do with it.
intent.putExtra(Intent.EXTRA_SUBJECT, “Some Subject Line”);
intent.putExtra(Intent.EXTRA_TEXT, “Body of the message, woot!”);

... and starting it with a chooser:

startActivity(Intent.createChooser(intent, “How do you want to share?”));

With these 5 lines of code, you get to bypass authenticating, credential storage/management, web API interaction via http posts, all sorts of things. Where by “bypass”, I mean “have something else take care of.” Like the barcode scanning intent, all you really had to do was declare that you have something you’d like to share, and let the user choose from a list of takers. You’re not limited to sending text, either. Here’s how you’d create an intent to share an image:

private Intent createShareIntent() {
...
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
shareIntent.setType("image/*");

// For a file in shared storage. For data in private storage, use a ContentProvider.
Uri uri = Uri.fromFile(getFileStreamPath(pathToImage));
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
return shareIntent;
}

Note that just by using setType() to set a MIME type, you’ve filtered down the list of apps to those that will know what to do with an image file.

Intents over Integration

Think about this for a second. By making the simple assumption that any user of any service (Task Manager, Social Network, Photo sharing site) already has some app on their phone that can share to that service, you can leverage the code that they’ve already written. This has several awesome implications:

  • Less UI — You don’t have to clog up your UI with customized, clickable badges of services you support. Just add a “share” button. It’s okay, we’ve made sure all your users know what it does [insert smiley here].

  • Leveraged UI — You can bet that every high-quality web service out there has spent serious time on the UI of their Android app’s “share” activity. Don’t reinvent the wheel! Just grab a couple and go for a ride.

  • Filtered for the user — If I don’t have a Foo-posting app on my phone, there’s a good chance I don’t care about posting to Foo. Now I won’t see Foo icons everywhere that are useless to me.

  • Client App Ecosystem — Much like an email client, anyone can write a client for any service. Users will use the ones they want, uninstall the ones they don’t. Your app supports them all.

  • Forward Compatible with new services — If some swanky new service springs up out of nowhere with an Android Application, as long as that application knows how to receive the share intent, you already support it. You don’t spend time in meetings discussing whether or not to wedge support for the new service into your impending Next Release(tm), you don’t burn engineering resources on implementing support as fast as possible, you don’t even upload a new version of anything to Android Market. Above all, you don’t do any of that again next week, when another new service launches and the whole process threatens to repeat itself. You just hang back and let your users download an application that makes yours even more useful.

Avoid One-Off Integrations

For each pro of the Intent approach, integrating support to post to these services one-at-a-time has a corresponding con.

  • Bad for UI — If your photo-sharing app has a Foo icon, what you might not immediately understand is that while you’re trying to tell the user “We post to Foo!” what you’re really saying is “We don’t post to Bar, Baz, or let you send the photo over email, sms, or bluetooth. If we did, there would be icons. In fact, we probably axed those features because of the space the icons would take on our home screen. Oh, and we’ll probably use some weird custom UI and make you authenticate through a browser, instead of the Foo client you already have installed.” I’m not going to name names, but a lot of you are guilty of this. It’s time to stop. (I mean it. Stop.)

  • Potentially wasted effort — Let’s say you chose one service, and integrated it into your UI perfectly. Through weeks of back-and-forth with Foo’s staff, you’ve got the API and authentication mechanisms down pat, the flow is seamless, everything’s great. Only problem is that you just wasted all that effort, because none of your user-base particularly cares for Foo. Ouch!

  • Not forward compatible for existing services — Any breaking changes in the API are your responsibility to fix, quickly, and that fix won’t be active until your users download a newer version of your app.

  • Won’t detect new services — This one really hurts. If a brand new service Baz comes out, and you’ve actually got the engineering cycles to burn, you need to get the SDK, work out the bugs, develop a sharing UI, have an artist draw up your own “edgy” (ugh) but legally distinct version of the app’s logo so you can plaster it on your home screen, work out all the bugs, and launch.

You will be judged harshly by your users. And deservedly so.

Ice Cream Sandwich makes it even easier

With the release of ICS, a useful tool for sharing called ShareActionProvider was added to the framework, making the sharing of data across Android applications even easier. ShareActionProviders let you populate lists of custom views representing ACTION_SEND targets, facilitating (for instance) adding a “share” menu to the ActionBar, and connecting it to whatever data the user might want to send.

Doing so is pretty easy. Configure the menu items in your Activity’s onCreateOptionsMenu method, like so:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Get the menu item.
MenuItem menuItem = menu.findItem(R.id.menu_share);
// Get the provider and hold onto it to set/change the share intent.
mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();

// Attach an intent to this ShareActionProvider. You can update this at any time,
// like when the user selects a new piece of data they might like to share.
mShareActionProvider.setShareIntent(yourCreateShareIntentMethod());

// This line chooses a custom shared history xml file. Omit the line if using
// the default share history file is desired.
mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
. . .
}

Note that you can specify a history file, which will adapt the ordering of share targets based on past user choices. One shared history file can be used throughout an application, or different history files can be used within the same application, if you want to use a separate history based on what kind of data the user wants to share. In the above example, a custom history file is used. If you wish to use the default history for the application, you can omit that line entirely.

This will help optimize for an important feature of the ShareActionProvider: The user’s most common ways to share float to the top of the drop-down, with the least used ones disappearing below the fold of the “See More” button. The most commonly selected app will even become a shortcut right next to the dropdown, for easy one-click access!

You’ll also need to define a custom menu item in XML. Here’s an example from the ActionBar Dev Guide.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_share"
android:title="@string/share"
android:showAsAction="ifRoom"
android:actionProviderClass="android.widget.ShareActionProvider" />
</menu>

And with that, you can have an easy sharing dropdown that will look like the screenshot here. Note that you get the nice standard three-dots-two-lines “Share” glyph for free.

Remember: Smart and Easy

The share intent is the preferred method of sharing throughout the Android ecosystem. It’s how you share images from Gallery, links from the browser, and apps from Android Market. Intents are the easiest path to writing flexible applications that can participate in a rapidly expanding ecosystem, but they’re also the smart path to writing applications that will stay relevant to your users, letting them share their data to any service they want, no matter how often their preferences change over time. So take a step back and stop worrying about if your user wants to tweet, digg, post, email, im, mms, bluetooth, NFC, foo, bar or baz something. Just remember that they want to share it. Android can take it from there.

Thursday, February 2, 2012

Android Security Update

Recently, there’s been a lot of news coverage of malware in the mobile space. Over on our Mobile blog, Hiroshi Lockheimer, VP of Android engineering, has posted Android and Security. We think most Android developers will find it interesting reading.