What you say is what you search

Many of you have searched the web by speaking since the launch of voice search in 2008. In fact, one in every four searches from an Android phone in the US is by voice. In certain situations, voice search just works much better than typing. It’s a lot faster than typing on a small phone screen. You can search things even when you don’t know the correct spelling. It’s more fun as you can share what you’re doing with your friends. And it’s safer when you’re walking around. Once you start using voice search, you start discovering all sorts of new ways to use it.

We’ve thought of a few interesting uses for voice search and made some short videos out of them. Check them out on our new YouTube channel. But we know you can do better. What are some of your most frequent or unusual voice search queries? Leave us a comment below or on our YouTube channel.



Posted by Heaven Kim, Product Marketing, Google Mobile

Screen Geometry Fun

The recent announcement of the Samsung Galaxy Tab should be a wake-up call for Android developers. What’s scary is that we’ve never seen a screen like this on an Android device before. What’s reassuring is that most apps Just Work (in fact, a lot of the ones I’ve tried so far have looked terrific) and the potential problems are easy to avoid. Here’s what you need to do to take advantage of not just the Tab, but all the new form factors that are coming down the pipe.

Let’s consider the Tab as a “teachable moment”:

  • Its screen is 1024x600; no compatible device’s screen has ever had a thousand pixels in any dimension before.

  • A lot of people are going to want to hold it sideways, in “landscape” mode, most of the time.

We recommend spending quality time with the Developers’-guide discussion of supporting multiple screens; we'll be revising that regularly when required as the device landscape changes. Also, this blog recently ran Dan Morrill’s One Screen Turn Deserves Another, which should help out in handling the landscape default.

What density means

When you build your app, you can provide layouts and assets (graphics) which vary by screen density, screen size, and landscape or portrait orientation. Clearly, pulling these together is not as much fun as designing groovy layouts and clever Intent filters; but there’s no way around it.

In this context, the Samsung has another little surprise: If you do the arithmetic, its screen has 170 DPI, which is far from the densest among Android devices. Still, it declares itself as “hdpi” (and as having a “large” screen size). The reason is simple: It looks better that way.

Samsung found that if you rendered your graphical resources bit-for-bit using medium-density sources, they looked great, but most large-screen designs ended up looking sparse, with too much space between buttons and icons. At high resolution, the framework scales up the resources an amount that turns out to be just enough.

As a photography hobbyist, I’m reminded of how you juggle aperture and shutter speed and ISO sensitivity. If, for example, you want a fast shutter speed to capture a dancer in mid-leap, you’d better compensate with a wider aperture or more sensitivity. Similarly, the Galaxy Tab’s screen is at the large end of “large”, so declaring it as high-density applies a useful compensation.

The good news is that the scaling code in the framework is smart enough and fast enough that it comes out well; the graphics in my own apps look remarkably good on the Tab. Here is the front page of my “LifeSaver 2” app; first the Nexus One, then the Galaxy Tab, resized for presentation here. Different densities, different geometries, and the only important difference is that the version on the big screen looks prettier.

Your take-away should be what I said above: Make sure you provide your graphics at all three resolutions, and chances are the Android framework will find a way to make them look great on a huge variety of devices.

Other Ways To Go Wrong

As I noted, most apps work just fine on this kind of device, out of the box, no changes required. However, we have run across a few Worst Practices that can make your app look dorky or even broken; for example:

  • Using AbsoluteLayout; this is a recipe for trouble.

  • Using absolute rather than density-independent pixels.

  • One member of my group ran across a couple of apps that suffered a Null Pointer Exception because they were calculating screen size when their Activity started, and doing their own resource loading rather than letting the framework take care of it. The problem was that they hadn't built in handling for the 1024x600 screen. The problem would vanish if they'd hand the work to the framework (or at least make sure that all their switch statements had default cases).

Escape the Shoebox

I've observed that a certain number of applications appear “shoeboxed”, running in a handset-like number of pixels in the center of the screen, surrounded by a wide black band. They work fine, but this is silly, and easy to avoid. It turns out that this happens when you have a targetSdkVersion value less than four; this is interpreted to mean that you’re targeting the legacy Cupcake flavor of Android, which only supported HVGA.

In any case, if you want to make 100% sure that your app doesn’t get pushed into the shoebox, the supports-screens element is your friend; here’s what we recommend:

<supports-screens android:largeScreens="true" android:anyDensity="true" />

(Both those attributes default to "false" for API levels less than 4.) Given a chance, the framework gets a good result on almost any Android screen imaginable.

Testing

When a device comes along that’s different in one way or another from what’s been available before, and you don’t have one, the only way to be sure your app will treat it properly is to run it on an Android emulator; the emulator code is flexible enough to model anything we’ve seen or know is coming down the pipe.

In the case of the Galaxy Tab, Samsung will be providing an add-on including a custom AVD and skin as an SDK add-on, to make your life easier; I used a pre-release to make the LifeSaver screenshot above.

Why All the Extra Work?

Because, as 2010 winds down, Android isn’t just for phones, and isn’t just for things that fit in your pocket. The minor effort required to deal with this should pay off big-time in terms of giving your apps access to a universe of new kinds of devices.

One Screen Turn Deserves Another

[This post is by Dan Morrill, Open Source & Compatibility Program Manager. — Tim Bray]

Android has an API for accessing a variety of sensor types, such as an accelerometer or light sensor. Two of the most commonly-used sensors are accelerometers and magnetometers (that is, compasses.) Applications and devices frequently use these as forms of user input, and to determine which way to orient the screen.

However, there’s a new wrinkle: recently, a few devices have shipped (see here and here) that run Android on screens that are naturally landscape in their orientation. That is, when held in the default position, the screens are wider than they are tall. This introduces a few fairly subtle issues that we’ve noticed causing problems in some apps. Now, part of the reason for this is that the Android SDK docs on the sensor API left a couple things unsaid, leading many developers to use them incorrectly. Even a couple of our own samples did the wrong thing. Sorry about that!

Fortunately, using these APIs correctly is pretty simple, if you keep three rules in mind:

  • The sensor coordinate system used by the API for the natural orientation of the device does not change as the device moves, and is the same as the OpenGL coordinate system.


  • Applications must not assume that the natural orientation is portrait. That's not true on all devices.


  • Applications that match sensor data to on-screen display must always use android.view.Display.getRotation() to map sensor coordinates to screen coordinates — even if their manifest specifies portrait-only display.


If you have a strong background in math, the three rules above may be all you need to work out the rest. But if that’s not you, the rest of this post explains things step-by-step, and gives some tips for using sensors correctly.

The Basic Problem

Before we dive in, here’s a tip that I personally have found to be helpful: always remember that the sensor data’s coordinate system never changes. Ever. The rest of this post is going to talk about coordinate systems and rotations and so on. But sometimes when your head is deep in 3D transforms, you can get disoriented, so I’ve found it helps to frequently remind myself that no matter what is happening to the screen, the sensor coordinate system never changes.

Now with that tip in mind, we need an example to talk about. Let’s consider a simple app that draws an arrow that always points in the direction of gravity, animating the arrow as the user moves the phone around, like a plumb-bob. When a typical phone is held normally, the arrow points down, as shown in Figure A:

(Note: In the figures in this post, the letter “G” means the direction of gravity in the sensor coordinate system. In Figure A, for example, “G = -y” means that gravity is aligned with the device’s negative-Y axis, as measured by the accelerometer. And remember — the sensor coordinate system never changes!)

This app is pretty straightforward to implement in OpenGL: you simply need to draw an arrow on a GL SurfaceView, after rotating the coordinate space in response to the sensor data returned by the accelerometer. This “just works” because — in this basic case — the OpenGL screen coordinate system lines up with the sensor coordinate system.

So, this technique works, and the arrow will always point down — until you turn the phone too far.

So What’s the Problem?

Most Android devices use the accelerometer to detect when the device is being held sideways, and rotate the screen accordingly. This normally causes the apps to display horizontally, from the point of view of the user.

What this reorientation actually does is remap the X and Y axes, causing the app to draw itself horizontally. However, the Android sensor APIs define the sensor coordinate space to be relative to the top and side of the device — not the short and long sides. When the system reorients the screen in response to holding the phone sideways, the sensor coordinate system no longer lines up with the screen’s coordinate system, and you get unexpected rotations in the display of your app. Figure B shows an example:

There are are a couple different fixes for this problem that are commonly used today, but we’ve noticed that these often don’t work properly on landscape-default devices.

A common first attempt to solve the auto-rotation problem is to simply lock the screen to portrait mode, via the android:screenOrientation attribute in AndroidManifest.xml. This prevents the system from performing a screen coordinate system remap in response to device orientation, and so the sensor and screen coordinate systems remain in sync. However, locking the screen to portrait mode this way prevents the coordinate systems from getting out of sync on portrait-default devices, but causes them to become out of sync on landscape-default devices. This is because it forces a screen reorientation on those devices.

The second common technique is to detect when the device is in landscape mode, and compensate for it by adding a rotation to the graphics that are displayed. Unfortunately, this technique is often only a partial fix, because if you aren’t careful about detecting landscape mode, you will again cause an unnecessary compensation on landscape-default devices.

The Correct Fix

So what’s a poor developer to do? This seems like a catch-22: you can’t prevent screen reorientation, but you can’t compensate for it, either.

Or can you? Actually, you can compensate — you just have to make sure you’re correctly detecting when compensation is necessary. The question is, how does the device tell you that it’s been reoriented? And the answer is: android.view.Display.getRotation().

That method will return one of four values, indicating that either the device has not been reoriented (ROTATION_0), or that it has been reoriented by 90 degrees, 180 degrees, or 270 degrees (which respectively are ROTATION_90, ROTATION_180, and ROTATION_270.)

Pay special attention to those last two. ROTATION_180 and ROTATION_270 mean that each device actually has two portrait and two landscape modes: normal portrait and landscape, and the upside-down versions of each. Some Android devices that do “360 reorientation” will use these rotation modes as well, so you need to handle this generally, beyond just accounting for portrait or landscape mode.

Once you have the screen orientation info in hand, you can treat it as a rotation around the screen’s Z axis when rendering graphics. By applying the rotation to the values you get from your SensorEventListener, you can correctly and reliably compensate for screen reorientations on all devices.

Note that Display.getRotation() will tell you if the screen has been reoriented at all, not that it was reoriented specifically in response to the accelerometer. For example, even if you disable accelerometer-based reorientation by using android:screenOrientation=”nosensor", your app might still be reoriented if the user has opened a hard keyboard on the device.

Because handling all this involves some math that can be a bit of a chore, as a convenience we’ve provided the android.hardware.sensor.SensorManager.remapCoordinateSystem() method to do much of this remapping work for you. If you choose not to do use this method, you can achieve a similar effect by essentially swapping axes, along with the rule of thumb that 2 axis swaps requires that you negate the third axis. (Since this is a bit error-prone, we do recommend that you use remapCoordinateSystem() when you can.)

Recipes for Sensuous Delights

Okay, now we’ve got a technique that we can rely on to work on all devices. But how do you update your app? To give you a more explicit helping hand on how to fix your apps, I’ve whipped up a few recipes for updating your apps.

Apps That Never Draw Sensor Data

Apps that never display graphics derived from sensor data usually don’t need to make any changes. Examples of this type of app are those that detect for bumps to the device, those that use sensors for gesture input, apps that monitor g-forces (watching for free-fall or acceleration), and so on. These apps aren’t drawing images that vary according to the device’s orientation.

This isn’t a hard and fast rule; there probably are some apps out there that do need to take screen orientation into consideration, even though they don’t draw graphics depicting the sensor data. But, if your app just uses sensors in the background, there’s a good chance you won’t need to make any changes.

Apps That Work in Both Portrait and Landscape

Most Android apps work fine in both portrait and landscape, using the standard tools. If your app is one of these and you also use sensors, the only change your app probably requires is a tweak to use the behavior I outlined above. That is:

  • Don’t assume that portrait is the default mode.


  • Don’t assume that locking your app to portrait mode solves this issue.


  • Don’t assume that disabling sensor-based reorientation solves this issue (since reorientations also occur on some devices when the user opens a keyboard.)


  • Check for the current device orientation via getRotation(), and compensate accordingly, as detailed earlier.


Apps That Only Work in One Orientation

Some apps — notably, many games — only work well (or at all!) in either portrait or landscape mode. It’s perfectly okay, of course, for such apps to lock themselves to the appropriate mode, and doing so simplifies the sensors quite a bit.

However, because Android devices actually support two landscape and two portrait modes, these apps still need to check the current orientation. That is, if an app locks itself to landscape mode, it will need to perform a compensation on portrait-default devices, but not on landscape-default devices. And of course — are you sick of hearing this yet? — this can be accomplished by checking the result of getRotation().

Phew! Quite a mouthful for what is a fairly straightforward notion, once you understand what’s going on. But if I had to distill all that down into a single sentence, it would be this: android.view.Display.getRotation() is your friend.

I hope you’ve found this information useful; what’s more, I hope you’ve found it practical. We’ll keep improving our SDK and docs, and I hope you’ll keep improving your apps.

Happy coding!

Walk this way

Whether you’re going for an urban hike or wandering from your hotel to find that restaurant you passed earlier, you won’t have to flag down a local if you’ve got Google Maps for mobile 4.5 on Android. Maps already had Navigation and walking directions, and today we’re happy to share the perfect marriage of the two: Walking Navigation (Beta). If you need help deciding where to walk (or drive), you can now also use Street View smart navigation or the new Google Maps search bar to guide your choice.

Walking Navigation
Walking Navigation lets you use GPS navigation with walking directions that are more direct and use pedestrian pathways when we know about them. To try it now, choose the “Walking” option from the Navigation icon. Walking Navigation has a few changes that help when you’re on your feet. For example, your phone will vibrate when you need to make a turn. You can even turn off voice guidance and just use these notifications while soaking in the sights and sounds around you. To help you orient yourself with your surroundings, the map will rotate with you as you turn the phone, and walking mode uses satellite view by default. Use it like a virtual compass with satellite imagery to look ahead or help pick out landmarks along the way.


Choose the “Walking” option after selecting the Navigation icon (left) to use Walking Navigation (right).


Keep in mind that Walking Navigation is still in beta, and Google Maps may not always have up-to-date information or optimal walking routes. Whether you’re walking or driving with Google Maps Navigation, you should always be safe and pay attention to road signs, follow signals, and use good judgment about routes that can’t be walked.

Street View smart navigation
If you want a sneak preview of where you’re going, use the new Street View on Google Maps with smart navigation and updated imagery. Just like with Street View smart navigation on your computer, you no longer have to slowly move down a street by tapping arrows along roads repeatedly. Now you can quickly navigate Street View by dragging Pegman from the corner and highlighting where you want to go with a lightly shaded “pancake” on roads or a rectangle on buildings. Let go of the screen when highlighting the front of a building, and you’ll fly there and turn to face it. With a swipe of your finger, you can hop rivers and scale buildings.




You’ll need to download an update for the “Street View on Google Maps” app in Android Market separately from Google Maps. Once you update, access Street View just like before: open Maps, search for a place or long-press the map, and choose the Street View option if available.

New Google Maps search bar
At the top of the map, you’ll find the new Google Maps search bar always available for easy access. Tap it to quickly start searching, open Places, use the Layers menu, or find yourself on the map with My Location. Here are more new features that may be helpful when you’re looking for nearby places:
  • Filter search results by distance or ratings
  • View prices categorized with dollar signs
  • See cross streets for places.
Google Maps for mobile 4.5 and Street View smart navigation are available now for Android 1.6+ everywhere they’re currently available. Search for Google Maps (tap here on your phone) and then Street View on Google Maps (tap here) in Android Market to update both.

Visit our Help Center to learn more or tell us your feedback and questions in our Help Forum. Give us suggestions and vote on other people’s on the Mobile Product Ideas page.

Fast Access to Google Voice with Android Widgets

(Cross-posted from the Google Voice blog)

Mobile is all about getting super fast access to what you’re looking for and Google Voice is no exception. So, today we’re releasing an update to the Android app, which gives you immediate access to your Google Voice Inbox and settings via two new home screen widgets.

The Google Voice Inbox widget brings your most recent voicemails and text messages to your home screen. With the widget, you can now quickly flip through messages in your Inbox, and if you choose to select a message preview, it will open in the Google Voice app.



The Settings widget
gives you quick access to four handy features.

Get instant access to the full Google Voice app by clicking the Google Voice icon.



Quickly compose and send free text messages.




Change what calls to place via Google Voice on the fly. You can have your phone use Google Voice for all calls, or just some of them.



Select Do Not Disturb and all calls to your Google number will be sent straight to Voicemail.



Plus, your credit balance is displayed so you know when it’s time to add a quarter or two.

The widgets can be used together or individually, and are part of the new Google Voice app, available for download from Android Market today. To add the widgets to a home screen panel, press the menu button from the home screen and select “Add>Widgets>Google Voice Inbox or Google Voice Settings”. You will need a valid Google Voice account to use them, and Google Voice is available free to anyone in the US.


Brace for the Future

[This post is by Dan Morrill, Open Source & Compatibility Program Manager. — Tim Bray]

Way back in November 2007 when Google announced Android, Andy Rubin said “We hope thousands of different phones will be powered by Android.” But now, Android’s growing beyond phones to new kinds of devices. (For instance, you might have read about the new 7” Galaxy Tab that our partners at Samsung just announced.) So, I wanted to point out a few interesting new gadgets that are coming soon running the latest versions of Android, 2.1 and 2.2.

For starters, the first Android-based non-phone handheld devices will be shipping over the next few months. Some people call these Mobile Internet Devices or Personal Media Players — MIDs or PMPs. Except for the phone part, PMP/MID devices look and work just like smartphones, but if your app really does require phone hardware to work correctly, you can follow some simple steps to make sure your app only appears on phones.

Next up are tablets. Besides the Samsung Galaxy Tab I mentioned, the Dell Streak is now on sale, which has a 5” screen and blurs the line between a phone and a tablet. Of course, Android has supported screens of any size since version 1.6, but these are the first large-screen devices to actually ship with Android Market. A tablet’s biggest quirk, of course, is its larger screen.

It’s pretty rare that we see problems with existing apps running on large-screen devices, but at the same time many apps would benefit from making better use of the additional screen space. For instance, an email app might be improved by changing its UI from a list-oriented layout to a two-pane view. Fortunately, Android and the SDK make it easy to support multiple screen sizes in your app, so you can read up on our documentation and make sure your app makes the best use of the extra space on large screens.

Speaking of screen quirks, we’re also seeing the first devices whose natural screen orientation is landscape. For instance, Motorola’s CHARM and FLIPOUT phones have screens which are wider than they are tall, when used in the natural orientation. The majority of apps won’t even notice the difference, but if your app uses sensors like accelerometer or compass, you might need to double-check your code.

Now, the devices I’ve mentioned so far still have the same hardware that Android phones have, like compass and accelerometer sensors, cameras, and so on. However, there are also devices coming that will omit some of this hardware. For instance, you’ve probably heard of Google TV, which will get Android Market in 2011. Since Google TV is, you know, a stationary object, it won’t have a compass and accelerometer. It also won’t have a standard camera, since we decided there wasn’t a big audience for pictures of the dust bunnies behind your TV.

Fortunately, you can use our built-in tools to handle these cases and control which devices your app appears to in Android Market. Android lets you provide versions of your UI optimized for various screen configurations, and each device will pick the one that runs best. Meanwhile, Android Market will make sure your apps only appear to devices that can run them, by matching those features you list as required (via tags) only with devices that have those features.

Android started on phones, but we’re growing to fit new kinds of devices. Now your Android app can run on almost anything, and the potential size of your audience is growing fast. But to fully unlock this additional reach, you should double-check your app and tweak it if you need to, so that it puts its best foot forward. Watch this blog over the next few weeks, as we post a series of detailed “tips and tricks” articles on how to get the most out of the new gadgets.

It’s official folks: we’re living in the future! Happy coding.

Securing Android LVL Applications


[This post is by Trevor Johns, who's a Developer Programs Engineer working on Android. — Tim Bray]

The Android Market licensing service is a powerful tool for protecting your applications against unauthorized use. The License Verification Library (LVL) is a key component. A determined attacker who’s willing to disassemble and reassemble code can eventually hack around the service; but application developers can make the hackers’ task immensely more difficult, to the point where it may simply not be worth their time.

Out of the box, the LVL protects against casual piracy; users who try to copy APKs directly from one device to another without purchasing the application. Here are some techniques to make things hard, even for technically skilled attackers who attempt to decompile your application and remove or disable LVL-related code.

  • You can obfuscate your application to make it difficult to reverse-engineer.

  • You can modify the licensing library itself to make it difficult to apply common cracking techniques.

  • You can make your application tamper-resistant.

  • You can offload license validation to a trusted server.

This can and should be done differently by each app developer. A guiding principle in the design of the licensing service is that attackers must be forced to crack each application individually, and unfortunately no client-side code can be made 100% secure. As a result, we depend on developers introducing additional complexity and heterogeneity into the license check code — something which requires human ingenuity and and a detailed knowledge of the application the license library is being integrated into.

Technique: Code Obfuscation

The first line of defense in your application should be code obfuscation. Code obfuscation will not protect against automated attacks, and it doesn’t alter the flow of your program. However, it does make it more difficult for attackers to write the initial attack for an application, by removing symbols that would quickly reveal the original structure of a compiled application. As such, we strongly recommend using code obfuscation in all LVL installations.

To understand what an obfuscator does, consider the build process for your application: Your application is compiled and converted into .dex files and packaged in an APK for distribution on devices. The bytecode contains references to the original code — packages, classes, methods, and fields all retain their original (human readable) names in the compiled code. Attackers use this information to help reverse-engineer your program, and ultimately disable the license check.

Obfuscators replace these names with short, machine generated alternatives. Rather than seeing a call to dontAllow(), an attacker would see a call to a(). This makes it more difficult to intuit the purpose of these functions without access to the original source code.

There are a number of commercial and open-source obfuscators available for Java that will work with Android. We have had good experience with ProGuard, but we encourage you to explore a range of obfuscators to find the solution that works best for you.

We will be publishing a separate article soon that provides detailed advice on working with ProGuard. Until then, please refer to the ProGuard documentation.

Technique: Modifying the license library

The second line of defense against attack from crackers is to modify the license verification library in such a way that it’s difficult for an attacker to modify the disassembled code and get a positive license check as result.

This actually provides protection against two different types of attack: it protects against attackers trying to crack your application, but it also prevents attacks designed to target other applications (or even the stock LVL distribution itself) from being easily ported over to your application. The goal should be to both increase the complexity of your application’s bytecode and make your application’s LVL implementation unique.

When modifying the license library, there are three areas that you will want to focus on:

  • The core licensing library logic.

  • The entry/exit points of the licensing library.

  • How your application invokes the licensing library and handles the license response.

In the case of the core licensing library, you’ll primarily want to focus on two classes which comprise the core of the LVL logic: LicenseChecker and LicenseValidator.

Quite simply, your goal is to modify these two classes as much as possible, in any way possible, while still retaining the original function of the application. Here are some ideas to get you started, but you’re encouraged to be creative:

  • Replace switch statements with if statements.

  • Use XOR or hash functions to derive new values for any constants used and check for those instead.

  • Remove unused code. For instance, if you’re sure you won’t need swappable policies, remove the Policy interface and implement the policy verification inline with the rest of LicenseValidator.

  • Move the entirety of the LVL into your own application’s package.

  • Spawn additional threads to handle different parts of license validation.

  • Replace functions with inline code where possible.

For example, consider the following function from LicenseValidator:

public void verify(PublicKey publicKey, int responseCode, String signedData, String signature) {
// ... Response validation code omitted for brevity ...
switch (responseCode) {
// In Java bytecode, LICENSED will be converted to the constant 0x0
case LICENSED:
case LICENSED_OLD_KEY:
LicenseResponse limiterResponse = mDeviceLimiter.isDeviceAllowed(userId);
handleResponse(limiterResponse, data);
break;
// NOT_LICENSED will be converted to the constant 0x1
case NOT_LICENSED:
handleResponse(LicenseResponse.NOT_LICENSED, data);
break;
// ... Extra response codes also removed for brevity ...
}

In this example, an attacker might try to swap the code belonging to the LICENSED and NOT_LICENSED cases, so that an unlicensed user will be treated as licensed. The integer values for LICENSED (0x0) and NOT_LICENSED (0x1) will be known to an attacker by studying the LVL source, so even obfuscation makes it very easy to locate where this check is performed in your application’s bytecode.

To make this more difficult, consider the following modification:

public void verify(PublicKey publicKey, int responseCode, String signedData, String signature) {
// ... Response validation code omitted for brevity …

// Compute a derivative version of the response code
// Ideally, this should be placed as far from the responseCode switch as possible,
// to prevent attackers from noticing the call to the CRC32 library, which would be
// a strong hint as to what we're done here. If you can add additional transformations
// elsewhere in before this value is used, that's even better.
java.util.zip.CRC32 crc32 = new java.util.zip.CRC32();
crc32.update(responseCode);
int transformedResponseCode = crc32.getValue();

// ... put unrelated application code here ...
// crc32(LICENSED) == 3523407757
if (transformedResponse == 3523407757) {
LicenseResponse limiterResponse = mDeviceLimiter.isDeviceAllowed(userId);
handleResponse(limiterResponse, data);
}
// ... put unrelated application code here ...
// crc32(LICENSED_OLD_KEY) == 1007455905
if (transformedResponseCode == 1007455905) {
LicenseResponse limiterResponse = mDeviceLimiter.isDeviceAllowed(userId);
handleResponse(limiterResponse, data);
}
// ... put unrelated application code here ...
// crc32(NOT_LICENSED) == 2768625435
if (transformedResponseCode == 2768625435):
userIsntLicensed();
}
}

In this example, we’ve added additional code to transform the license response code into a different value. We’ve also removed the switch block, allowing us to inject unrelated application code between the three license response checks. (Remember: The goal is to make your application’s LVL implementation unique. Do not copy the code above verbatim — come up with your own approach.)

For the entry/exit points, be aware that attackers may try to write a counterfeit version of the LVL that implements the same public interface, then try to swap out the relevant classes in your application. To prevent this, consider adding additional arguments to the LicenseChecker constructor, as well as allow() and dontAllow() in the LicenseCheckerCallback. For example, you could pass in a nonce (a unique value) to LicenseChecker that must also be present when calling allow().

Note: Renaming allow() and dontAllow() won’t make a difference, assuming that you’re using an obfuscator. The obfuscator will automatically rename these functions for you.

Be aware that attackers might try and attack the calls in your application to the LVL. For example, if you display a dialogue on license failure with an “Exit” button, consider what would happen if an attacker were to comment out the line of code that displayed that window. If the user never pushes the “Exit” button in the dialog (which is no not being displayed) will your application still terminate? To prevent this, consider invoking a different Activity to handle informing a user that their license is invalid, and immediately terminating the original Activity; add additional finish() statements to other parts of your code that get will get executed in case the original one gets disabled; or set a timer that will cause your application to be terminated after a timeout. It’s also a good idea to defer the license check until your application has been running a few minutes, since attackers will be expecting the license check to occur during your application’s launch.

Finally, be aware that certain methods cannot be obfuscated, even when using a tool such as ProGuard. As a key example, onCreate() cannot be renamed, since it needs to remain callable by the Android system. Avoid putting license check code in these methods, since attackers will be looking for the LVL there.

Technique: Make your application tamper-resistant

In order for an attacker to remove the LVL from your code, they have to modify your code. Unless done precisely, this can be detected by your code. There are a few approaches you can use here.

The most obvious mechanism is to use a lightweight hash function, such as CRC32, and build a hash of your application’s code. You can then compare this checksum with a known good value. You can find the path of your application’s files by calling context.GetApplicationInfo() — just be sure not to compute a checksum of the file that contains your checksum! (Consider storing this information on a third-party server.)

[In a late edit, we removed a suggestion that you use a check that relies on GetInstallerPackageName when our of our senior engineers pointed out that this is undocumented, unsupported, and only happens to work by accident. –Tim]

Also, you can check to see if your application is debuggable. If your application tries to keep itself from performing normally if the debug flag is set, it may be harder for an attacker to compromise:

boolean isDebuggable =  ( 0 != ( getApplcationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE ) );

Technique: Offload license validation to a trusted server

If your application has an online component, a very powerful technique to prevent piracy is to send a copy of the license server response, contained inside the ResponseData class, along with its signature, to your online server. Your server can then verify that the user is licensed, and if not refuse to serve any online content.

Since the license response is cryptographically signed, your server can check to make sure that the license response hasn’t been tampered with by using the public RSA key stored in the Android Market publisher console.

When performing the server-side validation, you will want to check all of the following:

  • That the response signature is valid.

  • That the license service returned a LICENSED response.

  • That the package name and version code match the correct application.

  • That the license response has not expired (check the VT license response extra).

  • You should also log the userId field to ensure that a cracked application isn’t replaying a license response from another licensed user. (This would be visible by an abnormally high number of license checks coming from a single userId.)

To see how to properly verify a license response, look at LicenseValidator.verify().

As long as the license check is entirely handled within server-code (and your server itself is secure), it’s worth nothing that even an expert cracker cannot circumvent this mechanism. This is because your server is a trusted computing environment.

Remember that any code running on a computer under the user’s control (including their Android device) is untrusted. If you choose to inform the user that the server-side license validation has failed, this must only be done in an advisory capacity. You must still make sure that your server refuses to serve any content to an unlicensed user.

Conclusion

In summary, remember that your goal as an application developer is to make your application’s LVL implementation unique, difficult to trace when decompiled, and resistant to any changes that might be introduced. Realize that this might involve modifying your code in ways that seem counter-intuitive from a traditional software engineering viewpoint, such as removing functions and hiding license check routines inside unrelated code.

For added protection, consider moving the license check to a trusted server, where attackers will be unable to modify the license check code. While it’s impossible to write 100% secure validation code on client devices, this is attainable on a machine under your control.

And above all else, be creative. You have the advantage in that you have access to a fully annotated copy of your source code — attackers will be working with uncommented bytecode. Use this to your advantage.

Remember that, assuming you’ve followed the guidelines here, attackers will need to crack each new version of your application. Add new features and release often, and consider modifying your LVL implementation with each release to create additional work for attackers.

And above all else, listen to your users and keep them happy. The best defense against piracy isn’t technical, it’s emotional.