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
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
switchstatements withifstatements.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.
Licensing Server News
It’s been reported that someone has figured out, and published, a way to hack some Android apps to bypass our new Android Market licensing server. We’ll be saying more on this, but there are a few points that deserve to be made right now:
The licensing service, while very young, is a significant step forward in terms of protection over the plain copy-protection facility that used to be the norm. In the how-to-pirate piece, its author wrote: “For now, Google’s Licensing Service is still, in my opinion, the best option for copy protection.”
The licensing service provides infrastructure that developers can use to write custom authentication checks for each of their applications. The first release shipped with the simplest, most transparent imaginable sample implementation, which was written to be easy to understand and modify, rather than security-focused.
Some developers are using this sample as-is, which makes their applications easier to attack. The attacks we’ve seen so far are also all on applications that have neglected to obfuscate their code, a practice that we strongly recommend. We’ll be publishing detailed instructions for developers on how to do this.
The number of apps that have migrated to the licensing server at this point in time is very small. It will grow, because the server is a step forward.
100% piracy protection is never possible in any system that runs third-party code, but the licensing server, when correctly implemented and customized for your app, is designed to dramatically increase the cost and difficulty of pirating.
The best attack on pirates is to make their work more difficult and expensive, while simultaneously making the legal path to products straightforward, easy, and fast. Piracy is a bad business to be in when the user has a choice between easily purchasing the app and visiting an untrustworthy, black-market site.
Android Market is already a responsive, low-friction, safe way for developer to get their products to users. The licensing server makes it safer, and we will continue to improve it. The economics are already working for the developers and against the pirates, and are only going to tilt further in that direction.
A Little Too Popular
A couple of weeks ago, we arranged that registered developers could buy an unlocked Nexus One via their publisher page in Android Market. We think it’s a good development platform and a nice phone. Apparently, you agree. Somewhat too many of you, in fact; we blew through the (substantial) initial inventory in almost no time, and they’re back-ordered from HTC, who are doing a pretty good job of managing runaway success amid a worldwide AMOLED shortage. Everyone appreciates that it’s important to the platform to get phones in the hands of developers, so we’re working hard on re-stocking the shelves; stand by.
Two Simple Questions
And the answers to them, posted here and there by senior Android engineers.
How much memory is my app using?
Over at Stack Overflow, our own Dianne Hackborn takes this up in detail. There's no simple answer, but Dianne does offer lots of useful information.
How do I make a ScrollView behave?
This one does have a simple answer, and our Romain Guy offers it in ScrollView’s handy trick. It's easy enough to do once you know how, which is harder to find out than you might think, because there's one useful XML attribute that's there in the examples but missing in the docs. Oops!
Powering Chrome to Phone with Android Cloud to Device Messaging

[This post is by Dave Burke, who's an Engineering Manager 80% of the time. — Tim Bray]
Android Cloud to Device Messaging (C2DM) was launched recently as part of Android 2.2. C2DM enables third-party developers to push lightweight data messages to the phone. C2DM created a nice opportunity for us to pull together different Google developer tools to create a simple but useful application to enable users to push links and other information from their desktop / laptop to their phone. The result was Chrome to Phone - a 20-percent time project at Google.
Chrome to Phone comprises a Chrome Extension, an Android Application, and a Google AppEngine server. All of the code is open sourced and serves as a nice example of how to use C2DM.
The message flow in Chrome to Phone is fairly typical of a push service:
The Android Application registers with the C2DM service and gets a device registration ID for the user. It sends this registration ID along with the user's account name to the AppEngine server.
The AppEngine server authenticates the user account and stores the mapping from account name to device registration ID.
The Chrome Extension accesses the URL and page title for the current tab, and POSTs it to the AppEngine server.
The AppEngine server authenticates the user and looks up the corresponding device registration ID for the user account name. It then HTTP POSTs the URL and title to Google's C2DM servers, which subsequently route the message to the device, resulting in an Intent broadcast.
The Android application is woken by its Intent receiver. The Android application then routes the URL to the appropriate application via a new Intent (e.g. browser, dialer, or Google Maps).

An interesting design choice in this application was to send the payload (URL and title) as part of the push message. A hash of the URL is used as a collapse_key to prevent multiple button presses resulting in duplicate intents. In principle the whole URL could have been used, but the hash is shorter and avoids unnecessarily exposing payload data. An alternative approach (and indeed the preferred one for larger payloads) is to use the push message service as a tickle to wake up the application, which would subsequently fetch the payload out-of-band, e.g. over HTTP.
The code for Chrome to Phone is online. Both the AppEngine and Android Application include a reusable package called com.google.android.c2dm that handles the lower-level C2DM interactions (e.g. configuration, task queues for resilience, etc).
Chrome to Phone is useful, but maybe it’s most interesting as an example of how to use Android C2DM.
Nexus One Developer Phone
We've always offered unlocked phones for direct sale to registered Android Developers. As of today, the Developer Phone is the Nexus One, at a price of $529. To see the details or order a phone, you need to sign in to your Android developer account and click on the "Development Phones" link.
The Nexus One combines an up-to-the-minute platform (Android 2.2), modern hardware, and the pure Android software suite. It's a good choice both for people who want to build Android applications using either the SDK or the NDK, and those who want to experiment with modified versions of the Android platform. Note that the Nexus One still ships with Android 2.1 but will download 2.2 soon after you turn it on; make sure you’re near a fast network.
As well as being an outstanding developer platform, it's a really nice everyday phone; we're really happy to have connected the right dots to make this happen.
[Update]: A bunch of people have spoken up wondering about Nexus One accessories. They are available right now in HTC's European online store. When we get more news, we'll pass it along.
[Update, Aug 6th]: The HTC US store now has accessories too.
Best Practices for Handling Android User Data

[This post is by Nick Kralevich, an engineer on the Android Security Team. — Tim Bray]
As the use of mobile applications grows, people are paying more attention to how these applications use their data. While the Android platform contains extensive permissions designed to protect users, application developers are ultimately responsible for how they handle users’ information. It’s important for developers to understand the code they include, and consider the permissions they request, as mishandling these issues can result in users perceiving a violation of trust.
Maintaining a healthy and trustworthy ecosystem is in every Android developer’s best interest.
Here are a few tips for writing trustworthy Android applications:
Maintain a privacy policy
Minimize permissions
Give your users a choice regarding data collection
Don’t collect unnecessary information
Don’t send data off the device
... but if you have to, use encryption and data minimization
Don’t use code you don’t understand
Don’t log device or user specific information.
Maintain a privacy policy
Trustworthy applications are up-front about the data they collect and the reasons for collecting it. Users are generally happy to share information via such apps if they believe they will personally benefit. A clear and concise privacy policy, with details about the type of information collected and how it’s used, goes a long way towards generating trust and good will.

Minimize permissions
Android is unique among mobile operating systems for its simple, straightforward, operating-system-enforced permission model. All Android applications must declare the permissions they require, and users must approve these permissions before the application is installed. Users tend to distrust applications that require excessive permissions.
For example, a user installing this tic-tac-toe game might reasonably wonder why it needs to take pictures.

Give your users a choice regarding data collection
It’s called the paradox of privacy [PDF, 890K]. Users are often happy to share their information, but they want control over that sharing. Trustworthy applications give users control over their information. For example, the Android Browser has privacy settings which enable users to control how their information is shared.

Don’t collect unnecessary information
Trustworthy applications limit the kinds of data they collect. Collecting unnecessary information, especially if you never use it, just invites suspicion. When in doubt, don’t collect it.
Don’t send data off the device
If you have to handle user data, ensure that the data remains on the device whenever possible. Users are comforted knowing that their private information strictly resides in the phone. Sending data outside the phone, even if done for the user’s benefit, tends to draw suspicion.
... but if you have to, use encryption and data minimization
Sometimes, the collection of data is necessary. In that case, applications need to ensure that it is handled safely. A privacy policy will avoid leading to surprised and irritated users; in some cases, it may be advisable to prompt the user before transmitting data off-device.
First, minimize the amount of data you collect. Do you really need the user’s full phone number, or would the area code be sufficient? Can you use a one-way cryptographic hash function on the data before sending it to the server to help protect the user’s confidential information?
A case study: User Favorites
Suppose you want your app to maintain a list of “favorites” for each of your users, without going through a full registration process. In theory, you could do this by sending your server some combination of their phone number, device ID, or SIM ID. But why take the chance of worrying people about privacy issues; why not send a one-way hashed signature of whatever the identifying information is? Or even better, create a random unique id and store it on the phone, and use this unique id as the registration key for your application.
In the end, you’ll will still be able to retrieve their favorites, but you won’t need to send or store anything sensitive.
Second, encryption is critical to the safe handling of user data. Phones often operate on untrusted networks where attackers can sniff confidential traffic. Encrypting data in transit is a critical part of protecting user information.
Finally, when communicating with a server over HTTP, it’s a good idea to avoid encoding user information in a URL that is used with HTTP GET; rather, POST it in a message body. While using POST doesn’t guarantee that your information won’t be sniffed, putting it in the URL increases the likelihood that it will be automatically logged; out of the box, most web server software logs all the URLs that are received.
Don’t use code you don’t understand
In the open-source Android environment, it’s common (and good) practice to rely heavily on other people’s code, in the form of libraries and frameworks. But if that code is handling your users’ information inappropriately, it’s your problem. So make a point of checking code before you rely on it.
Don’t log user or device specific information
Application developers should be careful about on-device logs. Android makes it easy to write to the phone’s log, and anyone who has looked at “logcat” output knows that it is full of important but seemingly random debugging information from many applications. In Android, logs are a shared resource, and are available to an application with the READ_LOGS permission (only with user consent, of course!). Even though the phone log data is temporary and erased on reboot, inappropriate logging of user information could inadvertently leak user data to other applications.
Licensing Service Technology Highlights
We’ve just announced the introduction of a licensing server for Android Market. This should address one of the concerns we’ve heard repeatedly from the Android developer community.
The impact and intent, as outlined in the announcement, are straightforward. If you want to enable your app to use the licensing server, there’s no substitute for reading the authoritative documentation: Licensing Your Applications. Here are some technical highlights.
This capability has been in the Android Market client app since 1.5, so you don’t have to be running the latest Android flavor to use it.
It’s secure, based on a public/private key pair. Your requests to the server are signed with the public key and the responses from the server with the private key. There’s one key pair per publisher account.
Your app doesn’t talk directly to the licensing server; it IPCs to the Android Market client, which in turn takes care of talking to the server.
There’s a substantial tool-set that will ship with the SDK, the License Verification Library (LVL). It provides straightforward entry points for querying the server and handling results. Also, it includes modules that you can use to implement certain licensing policies that we expect to be popular.

LVL is provided in source form as an Android Library project. It also comes with a testing framework.
There’s a Web UI on the publisher-facing part of the Market’s Web site for key management; it includes setup for production and testing.
Obviously, you can’t call out to the server when the device is off-network. In this situation you have to decide what to do; one option is to cache licensing status, and LVL includes prebuilt modules to support that.
We think this is a major improvement over the copy-protection option we’ve offered up to this point, and look forward to feedback from developers.
Licensing Service For Android Applications
[This post is by Eric Chu, Android Developer Ecosystem. — Tim Bray]
In my conversations with Android developers, I often hear that you’d like better protection against unauthorized use of your applications. So today, I’m pleased to announce the release of a licensing service for applications in Android Market.
This simple and free service provides a secure mechanism to manage access to all Android Market paid applications targeting Android 1.5 or higher. At run time, with the inclusion of a set of libraries provided by us, your application can query the Android Market licensing server to determine the license status of your users. It returns information on whether your users are authorized to use the app based on stored sales records.

This licensing service operating real time over the network provides more flexibility in choosing license-enforcement strategies, and a more secure approach in protecting your applications from unauthorized use, than copy protection.
The licensing service is available now; our plan is for it to replace the current Android Market copy-protection mechanism over the next few months. I encourage you to check out the Licensing Your Applications section of our Developer Guide and the Android Market Help Center to learn how you can take advantage of this new service immediately.
























































