with relatively low latency.
However, you still need a smart strategy for sending messages between participants in a game. Although
the name of the service implies real-time aspects, that’s not altogether the case. There may be hundreds
of milliseconds or even seconds in latency between two players, depending on their respective network
configuration.
The goal is to send as few messages as possible and only with data that’s absolutely necessary. For instance, in
the case of a multiplayer racing game, you need to communicate two things from a participant: current velocity
(speed and direction) and current position. Each instance of the game then calculates the position of the
local player’s cars and updates the view accordingly. The position of the different players won’t match exactly
between the players, but it will be close enough for the game to feel consistent.
Chapter 19: Google Play Services 387
When a player changes the speed or direction of his car, your game will send an update with this information to
the other participants. Because this will change frequently, these messages should be sent as unreliable messages
to reduce latency. When receiving one of these messages, the game will update the speed and direction of the
local representation of that participant accordingly. Because the order for these messages isn’t guaranteed, they
should also contain a sequence number so that your game can discard messages that arrive out of order.
Because unreliable messages might also be lost, you also need to send a few reliable messages that can be used
as more reliable checkpoints in the game. This way, even if one participant drops a number of messages with
speed and direction updates, the other players will eventually receive the correct position for that player.
The following example uses the class Car to represent each participant in the racing game:
class Car {
String participantId;
Point position;
Point velocity;
}
public static final byte POSITION_DATA = 1;
public static final byte VELOCITY_DATA = 2;
private HashMap<String, Car> mCars = new HashMap<String, Car>();
@Override
public void onRealTimeMessageReceived(RealTimeMessage realTimeMessage) {
String participantId = realTimeMessage.getSenderParticipantId();
Car car = mCars.get(participantId);
byte[] messageData = realTimeMessage.getMessageData();
switch (messageData[0]) {
case POSITION_DATA:
car.position.set(messageData[1], messageData[2]);
break;
case VELOCITY_DATA:
car.velocity.set(messageData[1], messageData[2]);
break;
}
}
public void simpleRaceGameLoop() {
for (Car car : mCars.values()) {
car.position.offset(car.velocity.x, car.velocity.y);
}
SystemClock.sleep(100);
}
Whenever a message arrives, you check the first byte to see if it’s an update to a car’s position or its velocity.
Here, you update the state of the variable for that Car.
Meanwhile, the simpleRaceGameLoop()loops continuously during the game and updates the position
of each car using the last known velocity. This method is called dead-reckoning and is used in many types of
multiplayer games.
388 Part III: Pushing the Limits
For a real game, you need to add additional information to these messages and also implement some logic to
handle the cases when the player crashes the car. Also, you need to have a separate message to determine who
the winner is, and in this case, the easiest way is to let each participant game calculate his finishing time and
broadcast it. This way, each participant constructs the final result using the input from the other participants.
The preceding example uses the raw byte array directly for the necessary data, which can work fine if you have
only a small variation of your messages and don’t send complex data structures. However, as soon as your
messages increase in complexity, I highly recommend that you use Google Protocol Buffers. See Chapter 9 for
details on how to integrate this into your application.
Implementing real-time multiplayer games is usually very complicated. But with the new Google Play Game
Services APIs, implementation has now became much easier. You no longer need to deal with all the difficult
aspects of networking and can focus on the actual game content, thus I expect a lot of really innovative
multiplayer games to appear.
Summary
By adding a cloud backend to your application, you can greatly enhance the user experience. Many users have
more than one device, and by utilizing the online services available for syncing data or interacting with existing
Google services, your application can fit more seamlessly into the entire ecosystem.
The Google Play Services APIs for Android provide a set of very powerful APIs for authorization, real-time
multiplayer integration, and push notifications using GCM, to name a few. You can select the parts of these
services and APIs that are most appropriate for your application.
Because most of these services have a free tier on the Google Cloud Platform, you can start experimenting to
get a better understanding of how they work and what they can provide.
Further Resources
Websites
Main site for Google Play Services: http://developer.android.com/google/index.html
Main site for Google Cloud Platform: https://cloud.google.com
Google Play Game Services samples and helper libraries: https://github.com/
playgameservices/android-samples
Multiplayer API for Google Play Games Services: https://developers.google.com/games/
services/common/concepts/realtimeMultiplayer
Synchronized stopwatch demo using Google Cloud Endpoints and Cloud Messaging: http://
bradabrams.com/2013/06/google-io-2013-demo-android-studio-cloud-endpoints-

Chapter 20
Distributing Applications
on Google Play Store
Publishing Android applications has become very easy thanks to all the improvements made to the Google
Play Store. Google provides a number of useful tools, guides, and checklists that will help you in the process
of getting your application out to your users. In order to gain access to the Google Play Console, you must
first register for a publisher account and set up a Google Wallet Merchant Account if you want to sell apps
or support in-app purchases. You do this through the Google Play Developer Console, which you can find at
https://play.google.com/apps/publish (see Figure 20-1).
Figure 20-1 The Google Play Developer Console after a successful sign-up
390 Part III: Pushing the Limits
Google Play supports additional features such as an advanced In-app Billing service that lets you sell digital
content from within your application and provides the means by which users can sign up for a subscription for a
service within your application. Both of these features are managed by the In-app Billing APIs that I cover in this
chapter.
If you don’t want to charge for your application or for digital in-app content but still want to have some revenue
from your application, you can integrate ads. You do so by using the Google AdMob Ads SDK, which lets you
place ad banners in your application as standard Android View objects.
In some situations, you may want to verify that your paid application is licensed to run on the most current
device. To support this, Google provides the Google Play Licensing Service, which lets you perform automatic
verifications on the purchase state of an application. You’ll find a guide for integrating this service in this
chapter.
Android limits APK files distributed through Google Play to 50MB. Some games and apps require resources that
exceed this limit, which is why Google Play supports the use of APK extension files. I provide a guide for using
this service in the section, "APK Expansion Files," later in this chapter.
In-app Billing
Although selling your application is the most obvious way of monetizing your application, sometimes it’s more
efficient to provide your application for free and rely on users purchasing additional content from within your
application. This is handled by an In-app Billing service that lets users buy digital content or subscriptions for a
specific application.
To get started with in-app purchases, you need a valid Google Wallet Merchant Account, which you find in the
Google Play Developer Console. Once you get this set up, you need to enable billing for your application and
upload it to the Google Play Store. (Note that you don’t need to publish the app to enable in-app billing.)
Start by adding the following permission to your manifest, which allows your application to perform in-app
purchases:
<uses-permission android:name=”com.android.vending.BILLING” />
Next, you must copy the file IInAppBillingService.aidl from the play_billing directory in the
Android SDK extras and place it in the package com.android.vending.billing under the aidl sources
directory of your application. I also recommend that you copy the util package from the sample application
TrivialDrive found in the play_billing directory. These classes will make it much easier to implement the
In-app Billing API in your own application.
You also need to define the product IDs (also known as SKUs) for your different in-app products. Each product
that the user can purchase must have a unique SKU, and you define them in the Google Play Developer Console
as follows:
Chapter 20: Distributing Applications on Google Play Store 391
public static final String APPLE_SKU = “apple”;
public static final String BANANA_SKU = “banana”;
public static final String ORANGE_SKU = “orange”;
public static final String AVOCADO_SKU = “avocado”;
public static final String LIME_SKU = “lime”;
public static final String[] FRUIT_SKUS = new String[] {APPLE_SKU,
BANANA_SKU,
ORANGE_SKU,
AVOCADO_SKU,
LIME_SKU};
private Inventory mInventory;
private Set<String> mOwnedFruits = new HashSet<String>();
When your application starts, you create the IabHelper class that you copied from the TrivialDrive samples
application, as shown in the following code:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHelper = new IabHelper(this, BASE_64_PUBLIC_KEY);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
@Override
public void onIabSetupFinished(IabResult result) {
if(!result.isSuccess()) {
// TODO Error handling of In-App Billing integration!
}
}
});
}
Load the current Inventory for all the products, as shown next. This class is also part of the utility
package that you copied from the samples. This query also allows you to check whether the current user has
purchased a specific SKU.
private void loadFruitInventory() {
mHelper.queryInventoryAsync(true,
new IabHelper.QueryInventoryFinishedListener() {
@Override
public void onQueryInventoryFinished(IabResult result,
Inventory inventory) {
if(result.isSuccess()) {
mInventory = inventory;
mOwnedFruits.clear();
for (String fruitSku : FRUIT_SKUS) {
if(inventory.hasPurchase(fruitSku)) {
mOwnedFruits.add(fruitSku);
}
}
}
}
});
}
392 Part III: Pushing the Limits
In-app purchases are asynchronous because they will start an Activity in the Google Play Store application.
The following is the code for launching the purchase flow for buying a fruit. Note that you also have to
implement onActivityResult() and call handleActivityResult() on the helper class.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent
data) {
if(!mHelper.handleActivityResult(PURCHASE_FRUIT, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
private void purchaseFruit(String sku) {
// User doesn’t own this fruit yet
if (!mOwnedFruits.contains(sku)) {
mHelper.launchPurchaseFlow(this, sku, PURCHASE_FRUIT,
new IabHelper.OnIabPurchaseFinishedListener() {
@Override
public void onIabPurchaseFinished(IabResult result,
Purchase info) {
if (result.isSuccess()) {
mOwnedFruits.add(info.getSku());
} else {
// TODO Error handling!
}
}
}, mBase64UserId);
}
}
Consuming Products
Once a product is purchased, it can be “consumed.” Using consumable objects is useful in games—for example,
virtual coins or, in this case, virtual fruit. The following example shows how to “consume” such a virtual fruit that
the user has purchased:
private void consumeFruit(String sku) {
mHelper.consumeAsync(mInventory.getPurchase(sku),
new IabHelper.OnConsumeFinishedListener() {
@Override
public void onConsumeFinished(Purchase purchase, IabResult result)
{
if(result.isSuccess()) {
Log.d(TAG, “Purchase successful!”);
mOwnedFruits.remove(purchase.getSku());
}
}
});
}
Chapter 20: Distributing Applications on Google Play Store 393
In-app Subscriptions
It’s also possible to implement subscriptions as part of the In-app Billing API. Doing so allows users to confirm a
recurring charge to their Google Play account. The recurrence is either monthly or yearly (this might change in
the future), and the API also supports a first-time free trial for your subscriptions.
Starting the subscription purchase flow works the same way that it does with normal in-app purchases, as
shown in the following example:
private void subcribeToUnlimitedFruit() {
if (mHelper.subscriptionsSupported()) {
mHelper.launchSubscriptionPurchaseFlow(this,
UNLIMITED_FRUIT_SUBSCRIPTION,
SUBSCRIBE_UNLIMITED_FRUIT,
new IabHelper.OnIabPurchaseFinishedListener() {
@Override
public void onIabPurchaseFinished(IabResult result,
Purchase info) {
if (result.isSuccess() &&
UNLIMITED_FRUIT_SUBSCRIPTION.
equals(info.getSku())) {
mUnlimitedFruits = true;
} else {
// TODO Error handling...
}
}
});
}
}
How you decide to utilize the In-app Billing API in your application depends on what your application or games
do. The preceding example uses fruit, and you treat the fruit as consumables that will be removed from the
user’s purchased items once the fruit is consumed. If you provide an In-app Billing service for removing ads or
upgrading to a Pro version of your applications, then you should not treat the purchases as consumables.
In-app subscriptions aren’t supported in all countries, which is why you should always check whether they’re
available before presenting them to the user. Also, remember that subscriptions involve your commitment to
continue to deliver content or services for users who sign up.
Ads in Android Applications
Although selling your application or integrating in-app purchases are ways of monetizing your work, doing so
may not always be a viable choice. For example, if you wish to provide the application for free to increase the
number of users, you can instead integrate ads that will give you a way to monetize your application while still
providing it free-of-charge to your users. Google supports in-app ads through its AdMob services. To use this
service, you need to sign up with AdMob at http://www.google.com/ads/admob.
394 Part III: Pushing the Limits
Ironically, by combining ads with an in-app purchase that allows users to get rid of the ads, you can create
an additional method for monetizing on your application. In this section, I show how you can integrate ads
through the AdMob service provided by Google and also how you can provide the option for removing those
ads through an in-app purchase.
To start, you need to download the AdMob SDK for Android, which you can find at https://developers.
google.com/mobile-ads-sdk. Unzip the archive and copy the file GoogleAdMobAdsSdk-6.4.1.jar
to the libs directory of your project. Next, add the following dependency in your Gradle build script:
compile files(‘libs/GoogleAdMobAdsSdk-6.4.1.jar’)
You now have the AdMob SDK for Android integrated into your project.
Next, you add the permissions as well as the AdActivity to your manifest, as shown here:
<uses-permission android:name=”android.permission.INTERNET” />
<uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE” />
<application
android:allowBackup=”true”
android:icon=”@drawable/ic_launcher”
android:label=”@string/app_name”
android:theme=”@style/AppTheme”>
<activity android:name=”com.google.ads.AdActivity”
android:configChanges=”keyboard|keyboardHidden|
orientation|screenLayout|
uiMode|screenSize|
smallestScreenSize”/>
The simplest way to integrate ads in your application is by using the class com.google.ads.AdView. You
can use this class either in your XML layouts or programmatically in Java.
Here is a simple example of using the AdView in your XML layout:
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:ads=”http://schemas.android.com/apk/lib/com.google.
ads”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
tools:context=”.AdDemo”>
<com.google.ads.AdView
android:id=”@+id/adView”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
ads:adUnitId=”AD_UNIT_ID”
ads:adSize=”SMART_BANNER”
ads:testDevices=”DEVICE_ID_FOR_TESTING”
ads:loadAdOnCreate=”true”/>
</LinearLayout>
Chapter 20: Distributing Applications on Google Play Store 395
The first ads attribute, adUnitId, is your AdMob publisher ID. The adSize attribute decides how large your
ad will be. A SMART_BANNER will adapt itself to the screen size. You can find the full list of supported banner
sizes for AdMob SDK at https://developers.google.com/mobile-ads-sdk/docs/admob/
intermediate#android-sizes. You need to set the testDevices attribute to the device ID for your development device. (An example of retrieving the device ID is in the section “Application Licensing” later in
this chapter.) Doing so enables you to debug and test the AdMob integration, which otherwise wouldn’t be
possible.
In the earlier example with the XML layout, the ads are loaded automatically when the View is loaded. This
may not always be what you want, so when you need more fine-grained control over when ads are loaded, you
can use the approach shown in the following method. You can also use this method to refresh the ad manually,
which will load a new banner.
private void loadAds() {
AdView adView = (AdView) findViewById(R.id.adView);
adView.loadAd(new AdRequest());
}
Targeting Ads
You can target the ads by giving the AdRequest a number of parameters, which you may want to do if you can
define the context and user preferences. The following code shows how to define gender, location, birthday and
a set of keywords to the AdRequest:
private void targetAdd(boolean isMale,
Location location,
Date birthday,
Set<String> keywords) {
AdRequest adRequest = new AdRequest();
adRequest.setGender(isMale ?
AdRequest.Gender.MALE : AdRequest.Gender.FEMALE);
adRequest.setLocation(location);
adRequest.setBirthday(birthday);
adRequest.setKeywords(keywords);
AdView adView = (AdView) findViewById(R.id.adView);
adView.loadAd(adRequest);
}
Another important aspect of targeting ads is determining whether the ads need to comply with the Children’s
Online Privacy Protection Act (COPPA). You can use this in your application to ensure that all ads displayed are
“child safe” according to COPPA.
You can add the following code to indicate that your ads should be displayed according to COPPA. If you want
to indicate that the ads should not be treated according to COPPA, change the value from 1 to 0.
AdMobAdapterExtras adMobAdapterExtras = new AdMobAdapterExtras();
adMobAdapterExtras.addExtra(“tag_for_child_directed_treatment”, 1);
adRequest.setNetworkExtras(adMobAdapterExtras);
396 Part III: Pushing the Limits
Ad Colors
You can also change the overall color scheme of the ads, which is especially useful when you want to adapt the
look and feel of the ads to the color scheme of your application.
The following example shows how to set a color scheme for the ads:
AdMobAdapterExtras adColor = new AdMobAdapterExtras();
adColor.addExtra(“color_bg”, “AAAAFF”);
adColor.addExtra(“color_bg_top”, “FFFFFF”);
adColor.addExtra(“color_border”, “FFFFFF”);
adColor.addExtra(“color_link”, “000080”);
adColor.addExtra(“color_text”, “808080”);
adColor.addExtra(“color_url”, “008000”);
adRequest.setNetworkExtras(adColor);
Use this with care, as a bad color combination can annoy the user and make them abandon your application.
Interstitial Ads
If you think banner ads aren’t suitable for your application, you can instead use interstitial ads. These ads allow
you to display a full-screen ad in your application that the user can either interact with or dismiss when it times
out. Although more intrusive than banner ads, interstitial ads won’t affect your own Views in the same way
banners do.
The following code illustrates how to load an interstitial ad and display it once it’s ready. All you need to do is
implement the logic in onDismissScreen() where you move to the next screen in your app or game.
private void loadInterstitialAd() {
mInterstitialAd = new InterstitialAd(this,
MY_INTERSTITIAL_AD_UNIT_ID);
mInterstitialAd.setAdListener(new AdListener() {
@Override
public void onReceiveAd(Ad ad) {
mInterstitialAd.show();
}
@Override
public void onFailedToReceiveAd(Ad ad,
AdRequest.ErrorCode errorCode) {
}
@Override
public void onPresentScreen(Ad ad) { }
@Override
public void onDismissScreen(Ad ad) {
// TODO User dismissed the ad, show next screen...
}

Chapter 20: Distributing Applications on Google Play Store 397
@Override
public void onLeaveApplication(Ad ad) { }
});
mInterstitialAd.loadAd(new AdRequest());
}
Application Licensing
When you sell your application on the Google Play Store, you have a clear way of monetizing on your
application. However, because it’s possible to extract an APK file from a device, there is a risk that your
application will be distributed through channels you haven’t approved. The many alternative app stores for
Android make it virtually impossible for developers to check all of them.
Once you set up the project and library correctly, you need to add the correct permission to your manifest, as
shown next. This allows your application to perform licensing checks.
<uses-permission android:name=”com.android.vending.CHECK_LICENSE” />
Performing a license check is easy:
private void checkLicense() {
String deviceId = Settings.Secure.
getString(getContentResolver(),
Settings.Secure.ANDROID_ID);
LicenseChecker licenseChecker =
new LicenseChecker(this,
new ServerManagedPolicy(this,
new AESObfuscator(SALT,
getPackageName(),
deviceId)),
BASE_64_PUBLIC_KEY);
licenseChecker.checkAccess(mLicenseCheckerCallback);
}
The SALT parameter must be a byte array of 20 random bytes. BASE_64_PUBLIC_KEY must be the full
licensing key found in your Google Play Developer Console for your application, as shown in Figure 20-2.
Figure 20-2 The Base64 encoded public RSA key for the licensing service shown in the Google Play Developer Console
398 Part III: Pushing the Limits
In the callback for the licensing check shown here, you simply display a Toast if the user isn’t licensed to use
this application:
class MyLicenseCheckerCallback implements LicenseCheckerCallback {
@Override
public void allow(int reason) {
Log.d(TAG, “License check passed!”);
}
@Override
public void dontAllow(int reason) {
Log.e(TAG, “License check failed - notify user!”);
Toast.makeText(MainActivity.this,
R.string.licensing_failed_message,
Toast.LENGTH_LONG).show();
// TODO Open Google Play Store for this application and quit
}
@Override
public void applicationError(int errorCode) {
Log.e(TAG, “Application error: “ + errorCode);
finish();
}
}
For each application that uses the licensing service, you have a number of different choices. You can notify the
user about a missing license, open Google Play Store for your application, and finish the Activity. Another
option is to perform a graceful degradation of the enabled features.
APK Expansion Files
When your game (or application) comes with a huge amount of content, the 50MB limit of APK files may not
be sufficient. In that case, you can use the APK Expansion Files feature to distribute up to 4GB of additional
data. This data will be stored on the shared storage where it will be available to all applications, so if the data is
sensitive, you need to encrypt it yourself (refer to Chapter 12 for more on this topic). The exact location of the
expansion files is <shared-storage>/Android/obb/<package-name>, where <shared-storage>
is the same path as returned by Environment.getExternalStorageDirectory().
You can have two expansion files, each with a maximum file size of 2GB, and they can contain any kind of data.
The first file is named main, and the second file, which is optional, is named patch. The name of the file uses
the following scheme:
[main|patch].<expansion-version>.<package-name>.obb
The first component of the name determines which file (main or patch) it is. The second part must match the
attribute android:versionCode in the manifest of your application. The final part is the package name of
your application.
Chapter 20: Distributing Applications on Google Play Store 399
Creating Expansion Files
The expansion files can be of any format, but I recommend using the ZIP file format because the Expansion
Library provides some helper classes to read files from such an archive. If your expansion file will contain media
files that you’ll be loading with MediaPlayer or SoundPool, package them without additional compression; that
way, you can simply load them with the standard APIs using their offset in the ZIP file.
The following command shows how you can create a ZIP file with your additional content:
$ zip –n .mp4;.ogg <expansion-file> <media files>
The –n parameter tells the zip command not to compress files with those extensions. <expansion-file>
is the filename of your expansion file, and <media files> is a list of all the files you want to include.
Downloading Expansion Files
In most situations, the expansion files are downloaded automatically by the Google Play client and placed in
external storage. However, in some situations, the files must be downloaded by your application. This is usually
the case when the user has swapped the SD card used for the external storage or deletes the contents of the
external storage manually.
In this situation, you need to perform a request using the Application Licensing service (as shown in the earlier
section “Application Licensing”) that will respond with the URLs for the expansion files. As a result, you must
include the License Verification Library, even if your application is free and otherwise wouldn’t require the
Application Licensing service. Also, because it needs to perform some network operations, your application
must declare the android.permission.INTERNET permission.
To simplify the manual download process, a Download Library is included in the Google Play APK Expansion
Library package that makes integration of the service easier.
Start by extending the class DownloaderService, as shown here, and add the public key form the licensing
service (see previous section):
public class MyDownloaderService extends DownloaderService {
public static final String BASE64_PUBLIC_KEY = “<Base64
LicensingKey>”;
public static final byte[] SALT = new byte[32];
@Override
public void onCreate() {
super.onCreate();
new Random().nextBytes(SALT);
}
@Override
public String getPublicKey() {
return BASE64_PUBLIC_KEY;
}
400 Part III: Pushing the Limits
@Override
public byte[] getSALT() {
return SALT;
}
@Override
public String getAlarmReceiverClassName() {
return DownloadAlarmReceiver.class.getName();
}
}
The following is an example of the broadcast receiver that is used for starting the DownloaderService in
case it is terminated unexpectedly:
public class DownloadAlarmReceiver extends BroadcastReceiver {
private static final String TAG = “DownloadAlarmReceiver”;
public void onReceive(Context context, Intent intent) {
try {
DownloaderClientMarshaller.
startDownloadServiceIfRequired(context,
intent,
MyDownloaderService.
class);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, “Cannot find MyDownloaderService.”, e);
}
}
}
Finally, add a method in your main Activity that checks whether the correct expansion files have been
downloaded. The following is an example of such a method that you can build upon. You should probably
extend this method with additional checks of the content, just to be sure the file isn’t modified.
private void performDownloadIfNeeded() {
String fileName = Helpers.
getExpansionAPKFileName(this, true, EXPANSION_FILE_VERSION);
if (!Helpers.doesFileExist(this, fileName,
EXPANSION_FILE_SIZE, true)) {
Intent notifierIntent =
new Intent(this, MainActivity.class);
notifierIntent.
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent =
PendingIntent.getActivity(this, 0,
notifierIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
Chapter 20: Distributing Applications on Google Play Store 401
try {
DownloaderClientMarshaller.
startDownloadServiceIfRequired(this,
pendingIntent,
MyDownloaderService.class);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, “Cannot find downloader service.”, e);
}
}
}
This method shows how you can add expansion files to your application on Google Play, how to verify that
you have them available, and how to initiate download them when needed. Use the expansion files as the first
solution for dealing with content that doesn’t fit within the maximum size allowed for APK files.
Summary
In this final chapter, I covered some of the features related to the Google Play Store. The features available
for developers presented in this chapter can help you monetize your application as well as deliver additional
content that doesn’t fit within the 50MB size limit for APK files. You can generate income for your application
three ways: You can sell it, add in-app purchases, or integrate ads.
Carefully consider which strategy to use when you decide to monetize your application. Although simply selling
your application may seem like the simplest solution, you’ll probably gain a larger user base by providing the
application for free and offering users the opportunity to buy virtual goods instead. Ads are easy to include but
will consume screen space in your application or game. They might also be considered too intrusive by some
users. Consider all aspects before deciding on which solution works best for each application because changing
your strategy at a later point may be difficult.
Further Resources
Websites
Distributing apps on the Google Play Store: http://developer.android.com/distribute/
The Google Play Developer Console: https://play.google.com/apps/publish
Resources for Google Play distribution: http://developer.android.com/google/play/dist.
The Google Mobile Ads SDK downloads and documentation: https://developers.google.com/
Google AdMob service: www.google.com/ads/admob
Index
A
version 4.0 (ICS), 239, 320
ABI (application binary interface), 267, 269
version 4.1, 357
abortBroadcast(), 154, 345
version 4.2, 292
AccountPicker.
version 4.3, 108, 224, 349, 352
newChooseAccountIntent(), 370
Android API level 5, 278
action strings, 13, 152, 156
Android Code Style Guidelines, 315
Activity class, 59, 93–95
Android contribution discussion forum, 315
Activity component, 57, 58, 158, 194–196
Android Design Guidelines, 85
Activity lifecycle, 112
Android Developers site, 268
Activity method, 44, 47, 50
Android networking, 319–346
Activity.getPreference(), 166
Android Open Accessory Protocol, 349
ActivityInstrumentationTestCase2, 194
Android Open Source Project (AOSP), 299, 302,
Activity.onConfigurationChanged(), 162
303–304, 308, 315–316
Activity.onPause(), 93
Android projects, 309–310
Activity.onResume(), 93
Android SDK, 9, 10, 291
ActivityRecognitionClient, 262–264
Android Studio, 9, 14, 22, 24, 83, 201, 376
ActivityRecognitionResult.
Android UI design, 77, 79–81
extractResult(), 264
android.app.func_name, 269
Activity.startActivityForResult(), 336
android.app.NativeActivity, 269
ActivityUnitTestCase, 194
android:backupAgent, 66, 187
AdapterView, 60
android:configChanges, 162
adb (Android Debug Bridge), 10–12, 304
android:description, 66
addCallback() method, 142
android:enabled=”false,” 66, 157
Address object, 258
android:exported, 67, 148, 171
ad-free version of game, 73
android.graphics, 104
ADK (Accessory Development Kit), 349
android.hardware.usb, 350
AdMob, 393
android:installLocation, 63
ads, 393–396
android.intent.category.DEFAULT, 68
advanced string resources, 70–71
android.jar, 287, 291, 292
AES algorithm, 236
android:label, 66
AIDL (Android Interface Definition Language), 115,
android:largeHeap, 66
132, 134, 137–141, 145, 311, 312
android.location, 310
alarm clock application, 159
AndroidManifest.xml, 60, 62, 64, 148, 187,
AlarmManager API, 343
232, 314
Allow Mock Locations option, 31
android:maxSdkVersion, 65
am command, 12, 13
android_metadata, 174
ancestral navigation, 79
android:minSdkVersion, 65
Android. See also specific topics
Android.mk, 268, 269, 276, 277, 278, 280, 310
version 2.2 (Froyo), 34
android:name, 60, 65
version 2.3 (Gingerbread), 167, 357
android_native_app.glue, 269, 270
version 3.0 (Honeycomb), 59, 77, 108, 319
android.net.nad, 356
404 Index
android:onClick, 196
Location Manager, 249–250
android:parentActivityName, 79
Messenger class, 142–145
android:permission, 67, 148, 157, 216, 233, 296,
official, 287–288
305, 314
platform, 293
android.priority, 154
Reflections, 290, 293–294, 320
android:process, 66
Restlet, 362–365
android.provider, 295
securing remote ones, 148–149
AndroidRuntime:*, 11
that require compile-time linking, 290
android:sharedUserId, 63, 235
wrapping with library projects, 145–148
android:sharedUserLabel, 63
APK (application package), 62, 63, 69, 94, 250,
android:targetSdkVersion, 65
305, 390
android.telephony, 151
APK expansion files, 398–401
android.test, 191
App Engine, 376
AndroidTestCase, 192
application architecture, 61–62
android:theme, 66
Application component, 57, 60–61, 65, 162
android.uid.system, 306, 307
application data backup, 187–188
android.unit.suitebuilder, 202
application element, 65–69
android:value, 187
Application Exerciser Monkey (Monkey), 13–14
android:versionCode, 63
Application Manager, 12
android:versonName, 63
application manifest, 62–69
android.widget, 81
Application method, 44
AndroidXRef, 288–289, 290, 297
Application.mk, 269
ANR (Application Not Responding) message, 31
applications
ANSI C, 268
Android NDK build scripts, 268–269
Ant scripts, 14
auto-starting, 158–159
AOSP (Android Open Source Project), 299, 302,
calling a Java method from native, 273–276
303–304, 308, 315–316
distributing of on Google Play Store, 389–401
Apache Harmony, 35
licensing of, 397–398
Apache License v2, 310
native activities, 269–270
API key, 187
native-only, 268
API levels, 65
platform certificates, 305–306
ApiCallback, 147
writing of in C, 268–270
ApiInterfaceV1, 140
writing signature-signed applications, 306–308
APIs
writing system applications, 305–308
AIDL overview, 137–141
apply(), 167, 168
AlarmManager, 343
APP_Platform, 269
Android native, 276–278
apps folder (packages project), 309
from Apache Harmony, 35
AR (augmented reality), 207, 222
for audio playback, 207–210
arbitrary binary files, 325
callbacks with AIDL, 141–142
Arduino Uno board, 5
designing, 137–148
arg1, 48
Device Management, 244–247
arg2, 48
Facebook, 337
Arial font, 84
finding, 340
ARM ABI, 278
Game Cloud Save, 373
ARM architecture, 267
Geofence, 261
ARM CPUs, 267
Google Maps, 250
armeabi (basic 32-bit ARM support) ABI, 267
Google Static Maps, 332
armeabi-v7a (ARMv7a) ABI, 267
Graph, 337
ARMv7, 267
hidden, 288–298
ArrayAdapter, 71
Location, 262
ArrayList, 38
Index 405
Arrays.sort(), 273
bootloader, 300, 301
Assert class, 191
Bornstein, Dan (developer), 33
asserting the result, 191
Bouncy Castle Crypto APIs, 236
AssetManager, 74
bouncycastle.odex, 292
assets, 69, 74
bqPlayerCallback(), 211
asterisk (*), 11
broadcast events, 151
asynchronous Service interaction, 114
BroadcastIntents, 59, 66
AsyncTask class, 46–47, 52, 59, 121, 125, 127
BroadcastReceiver component
atomic operations, 39
asynchronous communication, 124
AT&T Bell Labs, 268
auto-starting applications, 158–159
AttachCurrentThread(), 276
device configuration changes, 162
audio applications, advanced, 207–218
directed broadcasts, 157
AudioRecord API, 209
enabling/disabling receivers, 157–158
AudioTrack, 112, 208, 209
local BroadcastReceivers, 153–154
authentication, 331, 332–337, 340, 341
network and connectivity changes, 160–162
authorization, 247, 333, 334, 337, 341, 349, 369–372
normal and ordered broadcasts, 154–156
Autoconf, 278
one of four types of components, 57
auto-generated debug key, 231
overview, 58–59, 152–153
Automake, 278
registering/unregistering, 112, 113
automated tests, 13, 192
sticky broadcasts, 156–157
automatic memory management, 40–41
system broadcast intents, 158–162
auto-starting applications, 158–159
user presence and screen state, 159–160
AXIS_PRESSURE (pressure axis), 106
BroadcastReceiver method, 44
BSSID, 160
B
bugs, fixing, 315
background threads, 111–112, 113, 125
Builder, 186
background_sorting, 274
Builder.build(), 186
BackupAgentHelper class, 188
build.gradle file, 14
backups, 66, 187–188
buildInsert(), 177
banner ads, 396
buildTransfer(), 351
Base64 utility class, 236
bulkInsert(), 176
BaseGameUtils library project, 383
Bundle, 48, 52
battery drain, 342
ByteBuffer, 185
Be Inc., 131
byte-code, 33
Be Operation System (BeOS), 131
beginUserInitiatedSignIn(), 384
C
binary data, storage of, 165, 177–179
C header file, 271, 280
Binder, 115, 123, 132–134, 142, 234
C library (libc), 276–277
Binder IP (Inter-Process Communication), 131–137
C programming language, 211, 267, 268, 276
Binder.onTransact(), 133, 134
C++, 268
bindService(). See Context.
C89, 268
bindService()
C90 : C99 : C11, 268
Bitmap, 178
callback interfaces, 141, 142, 320
Bloch, Joshua (author)
callback method, 93
Bluetooth
callbacks, 44, 47, 49, 52, 59, 112, 141–142
Low Energy (BLE) devices, 5, 349, 352–356
call-block thread, 39
overall, 131, 310, 349
calling applications, verifying, 234–235
Smart technology, 349, 352
CallVoidMethod(), 276
Working Group, 356
Camera, 222
bmgr command-line tool, 188
camera applications, 207
boolean value, 166
camera processing, 222–223
406 Index
canonical perspective, 86
ConnectivityManager, 160, 161
categories, 68
Constants, 167
ccache, 303, 315
constants, extracting, 27, 28
cellular network, 160
consumer/producer pattern, 38
CELT codec, 278
consuming products, 392
certificate authorities, 239
ContactsProvider, 172
certificates, 239–243
ContentProvider component
Change Method Signature task, 29
configuration changes, 162
CHANGE_WIFI_STATE permission, 307
creating and upgrading databases, 172–174
ChatClient, 330
database design, 171–172
CI (continuous integration), 192, 202
database transactions, 176–177
Cipher, 236, 237
enabling/disabling components for, 158
circles, drawing, 255
high-performance, 171–179
Class.getMethod(), 294
implementing query methods, 174–175
ClassNotFoundException, 293
one of four types of components, 57
cleanup operations, 93, 97, 112, 113
reading SMS messages, 295
click listeners, 167, 194–196, 216, 263
SQLite databases wrapped in, 165
client-server model, 132
storing data in, 61, 177–179
client-side data encryption, 235–239
testing, 198–201
Cloud Datastore, 376
ContentResolver, 66, 174, 179
cloud-storage service, 165
ContentValues, 183
code, decompiling/obfuscating, 17
Context, 49
code files, 5
Context.bindService(), 113, 114, 118, 123, 147
code libraries, 17
Context.enforceCallingPermission(), 313
Collection objects, 38
Context.getApplication(), 61
Collection of Task objects, 182
Context.getMainLooper(), 44
Collections.sort(), 273
Context.getService(), 160
color blindness, 85
Context.getSharedPreference(), 166
colors, 84–85, 396
Context.getSystemService(), 131, 310, 311
com.android.internal, 288, 289
Context.MODE à, 234
com.android.server, 312, 313
Context.openFileInput(), 234
com.android.vending.billing, 390
Context.openFileOutput(), 233
com.google.ads.AdView, 394
Context.registerReceived(), 60
commands, 12, 13, 280, 300, 304
Context.registerReceiver(), 153
commit(), 167, 168
Context.sendBroadcast(), 152, 153, 155
community-supported firmwares, 302
Context.sendStickyBroadcast(), 156, 157
compile-time linking, 290
Context.startActivity(), 59
component attributes/elements, 66–67
Context.startService(), 59, 113, 114, 118,
ComponentName, 113, 132, 157, 171
121, 123, 152, 194, 196
components. See Activity component;
Context.stopService(), 118
BroadcastReceiver component;
Context.unbindService(), 118
ContentProvider component; Service
contract, 198
component
COPPA (Children’s Online Privacy Protection Act), 395
compress/decompress feature, 343
CORBA, 35
Compute Engine, 376
CountryDetector class, 289
configuration changes, 162
CPU architecture, 267
Configuration objects, 162
create, 282
connect(), 359
createDriveService(), 374
connectedInstrumentTest task, 201
createFromParcel(), 136
connectivity changes, 160–162
Crypto API, 236
connectivity technologies, 349–350
Cursor, 183, 296
Index 407
custom firmware, 300, 301, 304
Device Administration API, 244, 246
custom permissions, 232
device configuration changes, 162
custom views, 97–103
Device Management API, 244–247
CustomData.aidl, 138
device_filter.xml, 350
custom-streaming music clients, 207
DeviceInfoEndpoint, 381
CyanogenMod, 302
devices, unlocking, 300–302
DEX, 34, 292
D
dex binary format, 17
Dalvik Java, 33–35
dex2Jar tool, 292
Dalvik virtual machine (VM), 17, 23, 33, 36, 66, 131,
dimensions (of UI elements), recommended, 83
272, 292
directed broadcasts, 157
dangerous protection level, 232
directional types, 137
data encryption, client-side, 235–239
Display class, 95
data messaging, 386
DisplayManager, 95–96
data partition, 63
DNS-SD standard, 356
data storage/serialization
doEnableWifiTethering(), 308
advanced JSON handling with Gson, 181–184
doInsert(), 178
application data backup, 187–188
doLongRunningOperation(), 125
creating and upgrading databases, 172–174
Don’t Keep Activities option, 31
database design, 171–172
Don’t Make Me Think (Krug), 87
database transactions, 176–177
doSpeechRecognition(), 216
Google Protocol Buffers, 184–186
doStartActivityRecognition(), 263
high-performance ContentProviders, 171–179
DownloaderService class, 399, 400
implementing query methods, 174–175
dp (density-independent pixel) unit, 82, 83
JavaScript Object Notation (JSON), 179–184
drawable-xhdpi directory, 69
persistence options, 165
Drawing option, 31
preference files, 166–169
Dropbox, 165, 232
serializing data for persistence, 179–186
DSL (Domain-Specific Language), 14
storing binary data, 177–179
dx tool, 34
user options and settings UI, 169–171
dynamic translation, 34
data URI and type, 68
database normalization, 171
E
databases, creating and upgrading, 172–174
Eclipse, 22, 308
dbus mechanism, 131
EDGE connection, 151
dead-reckoning, 387
edge detection effect, 223
debug key, 231, 250
Editor, 167
debugging, 22–24, 31
Effective Java (Bloch), 42
decode, 283
EGL, 224, 226–228, 277
decodeOpus(), 280
empty classes, 287
decrypting data, 237
encode, 284
default, components enabled by, 66
encodePcm(), 280
default test keys, 305
encoding media, 224–228
delete(), 172, 177, 234
encryptClearText(), 237
@ deprecated, 147
encryption, client-side data, 235–239
descendant navigation, 79
enqueueNextSample(), 212
deserialization, 179
enumerations, type-safe (enum), 36, 182, 184
destroy(), 280, 284
errata, updates on errors in sample codes, 5
Developer Menu options, 29–31
error handling, for modified SDK, 293
Developer Options menu, 30
ExecutorService, 47, 52, 121, 123
developer settings, understanding, 30–31
expansion files, 398–401
408 Index
Expansion Library, 399
GestureDetector class, 106
Extract Constant task, 27, 28
gestures, 106
Extract Method task, 29
GetArrayLength, 273
GetIntArrayElements, 273
F
GetMethodID(), 276
face recognition, 87
GetObjectClass(), 276
Facebook, 87, 337–341
getQuantityString, 71
factory image for devices, 301
getReadableDatabase(), 172
fastboot commands, 300
getService(), 197
features, list of, 64
getString, 70
FileBackupHelper class, 188
getWritableDatabase(), 172
files, uploading to server, 322–324
Git (version control system), 20
filters, 64–65
Git repositories, 309, 324
fixSelectionArgs(), 175
GitHub, 21, 145, 326
fixSelectionString(), 175
gitolite server, 20
flashing, 300, 301, 303–304
GLES20.GL_TEXTURE2D, 220
float value, 166
GL_OES_EGL_image_external, 220
fonts, 81–82, 84
GL_TEXTURE_EXTERNAL_OES, 219, 220
for-loop, 37–38
Gmail, 232, 305
Foursquare API, 89, 332–337
GNU makefiles, 268, 278
Fragment class, 93–95
Google+, 305, 383
fragment shader, 219, 220, 221, 222
Google AdMob Ads SDK, 390
Fragments API, 59
Google AdMob services, 393
framework.odex, 292
Google API Console, 250, 251
frameworks project, 289
Google Cloud Console, 381
frameworks/base project, 309
Google Cloud Platform, 376
FreeXperia Project, 302
Google IO conference 2013, 22, 249, 383
fused Location Manager, 249–250, 258
Google Maps, 103, 106, 250–259, 305
Google Nexus, 5
G
Google Play, 63, 64–65, 66, 73
Google Play App State, 383
Galaxy Nexus, 299, 300, 301, 303, 310
Google Play Developer Console, 389, 390
Game Cloud Save API, 373
Google Play Game Management, 383
game engines, 109
Google Play Services
games
ads in Android applications, 393–397
ad-free versions of, 73
APK expansion files, 398–401
APK extension files, 390
application licensing, 397–398
consumable objects, 392
authorization, 369–372
multiplayer. See multiplayer games
consuming products, 392
multi-touching, 103
data messaging, 386
native applications, 268
Google Cloud endpoints, 376–379
OpenGL ES (Embedded Subsystem), 108, 109, 218
Google Cloud Messaging (GCM) service, 379–383
sound effects, 112, 207
Google Drive application data, 372–376
gamification, 88–90
Google Play Game Services, 383–386
garbage collector (GC), 33, 40–41, 43
In-app Billing, 390–392
GATT profile, 349
In-app subscriptions, 393
GCM client, 379–383
messaging strategy, 386–388
geocoding, 258–259
Google Play Store, 267, 287, 305, 306, 389–401
geofencing, 260–262
Google Protocol Buffers, 179, 184–186, 328
geons, 86–87
Google Static Maps, 331–332
Gerrit tool, 21–22
Index 409
Google Translator Toolkit, 72
IBinder.transact(), 133, 134
Google Wallet Merchant Account, 389, 390
icons, 83–84, 85–86, 88, 158
GoogleAuthUtil class, 371
IDE, 22–29, 308
GoogleCloudMessaging.register(), 380
IDL (Interface Definition Language), 137
GoogleMap object, 254, 260, 261
IETF working group, 326
GoogleMaps class, 258
IInAppBillingService.aidl, 390
GoogleMap.setOnMarkerClickListener(),
IllegalArgumentException, 194
254
ImageIO, 35
Gosling, James (developer), 33
images, 85–86
Gradle build system, 14–17, 181, 192, 201–202, 231
Imagination Technologies, 303
Graph API, 337
in directional type, 137
graphics, scene graphs, 109
In-app Billing, 390–392
greenDAO (library), 184
In-app subscriptions, 393
Groovy DSL (Domain-Specific Language), 14
include directory, 280
Gson, 181–184, 238
include statements, 277
gzip-compressed, 343
init functions, 282
inout directional type, 137
H
inputmethods folder (packages project), 309
Hackborn, Dianne (developer), 131
InputStream, 180, 181, 185, 322
hacking, 300–302, 309–315
insert(), 172, 234
handle(), 365
install-dir, 278
handleActivityResult(), 392
instrumentaiton tests, 191
handleMessage, 48, 49
int, 148, 166, 271, 273, 276
Handler, using MainLooper with, 51–52
IntelliJ IDEA CE (Community Edition), 22, 308–309
Handler class, 37, 47–49, 52, 59, 120, 142
Intent (“pdus”), 295
Handler object, 48, 49, 51, 112
Intent action, 59, 156, 159, 295, 297, 298
HandlerThread, 47, 52
intent filtering, 68–69
hard-coded strings and values, 69
intent-filter, 68, 113, 121, 148, 154, 157,
hidden APIs, 288–298
295, 345
hidden settings, 297–298
Intents, 66, 68, 112, 113, 114, 121, 123–125,
@hide, 287, 288
132, 148, 152, 153, 154, 157, 158–162, 171
Holo theme, 77
IntentService, 120–121, 123–124, 137, 261,
HomeDetector, 310, 311, 312
263, 264
home-screen application tray, 158
interfaces
host mode, 350
application binary interface (ABI), 267, 269
HTC, 299, 302
callback, 141, 142, 320
HTTP(S), 244, 324, 326
IBinder, 116, 132
HTTP GET requests, 321–322, 327
JNI (Java Native Interface), 210, 267, 270–273
HTTP POST requests, 322
Parcelable, 135, 136, 179
HTTP-based communication, 319, 326
Radio Interface Layer (RIL), 131
HttpsURLConnection, 244
RoomStatusUpdateListener, 385
HttpUrlClient, 320
RoomUpdateListener, 385
HttpUrlConnection, 35, 320–324, 326, 343
Runnable, 44, 45, 46
hyper-threading, 304
tests for, 192
user, 79–81, 192
I
interstitial ads, 396
invalidateKey(), 103
IBinder, 116, 132, 144, 147, 197
Ippel, Dennis (developer), 109
IBinder.DeathRecipient, 136
isWifiApEnabled(), 296
IBinder.linkToDeath(), 136
Ivy, 14
IBinder.pingBinder(), 137
410 Index
J
Google Maps v2, 250, 252
JAR files, 17–18, 138, 145, 287, 290
hidden setting keys, 298
Java code, 36–40
public and private, 242, 243, 399
Java compiler, 34
release key, 250
Java EE (Enterprise Edition), 33, 36
security concept, 231–232
Java ME (Micro Edition), 33
keystore files, 232, 306
Java method, calling of from native, 273–276
keytool application, 231, 232, 239
Java SDK, 210, 271
keyword native, 271
Java SE (Standard Edition), 33–35
Khronos Group, 210, 277–278
Java VM, 273, 274, 276
Krug, Steve (author)
javah tool, 271, 273, 280
java.util.concurrent, 39
L
javax.crypto, 236
languages, 69, 71, 72
“Jazz Hands” multi-touch, 64
LastPass, 235
JCE 1.2.1., 236
lateral navigation, 79
jclass, 276
LatLng, 254, 257
Jenkins CI, 202
launcher icon, 83, 84
jint pointer, 273
layout, 82
jintArray, 273, 275
LCD screens, compared to paper, 84–85
JIT compiler (Just in Time), 34–35, 36
libc (C library), 276–277
jmethodID, 276
libopus directory, 279
JMX, 35
libopus.so, 280
-jN argument, 304
library projects, 17, 18–19, 137, 138, 145–148, 383
JNI (Java Native Interface), 210, 267, 270–273
licensing, of applications, 397–398
jni directory, 268, 271, 279, 280
lifecycles, 97–98, 112–113
JNI function, 272
link to death, 132, 136–137
JNI module for native library, 280–284
LinkedList block, 39
JNI version 1.6, 272
linkToDeath(), 136, 142
JNI_COMMIT, 275
lint tool, 24, 62, 71
JNIEnv, 273, 276
lint warnings, 25–26
JNI_OnLoad, 272, 274, 282
Linux, 5, 9, 131, 278, 303
jobject, 273, 274, 276
List objects, 136
JPG photo, storage of, 177–179
ListFragment, 296
JSON (JavaScript Object Notation), 179–184, 238, 328
ListView, 71
JSONArray, 181
lite Java variant (Google Protocol Buffers), 184, 185
JSONObject class, 181, 182, 184, 322
Loader, 52
JsonReader API, 180
local binder, 114, 125
JsonWriter class, 181
LocalBinder, 125
JUnit, 191
LocalBroadcastManager, 153–154, 320
JVM, 271, 273
localization, 69, 71–72
LOCAL_MODULE, 269
K
Location and Activity API, 249
kernel driver, 131, 132
Location API, 258, 262
key chain management, 239–244
location API utilities, 257
KeyChain.choosePrivateKeyAlias(), 241
location-based APIs, 249
keys
LocationClient class, 258–260
API, 187
lock screen, 159–160
debug key, 231, 250
locks, 38, 39–40
default test keys, 305
log messages, 11
generating, 236
logcat, 10, 11
Index 411
LoginButton, 340
mMainHandler, 52
long value, 166
MNC (mobile network code), 73
long-running operations, 46, 47, 58, 111, 120, 125,
mobile Wi-Fi hotspots, 296
127, 128
mock classes/objects, 192
Looper, 44, 47, 51, 52, 313
MODE_STATIC, 209
low-latency audio, 207–210, 214
MODE_STREAM, 209
LTE, 160, 161
Monitoring options, 31
lunch command, 304
Monkey (Application Exerciser Monkey), 13–14
Monkeyrunner API, 14
M
MotionEvent class, 43, 103, 104, 106
main thread (UI thread), 44, 52, 111, 112, 120, 319
Motorola devices, 302
MainActivityTest, 201
MP3, 121
make command, 280
MP4, 224
make install command, 280
mRegistrationListsner, 356
Makefile, 279
mSurface, 226
Manage Apps menu, 375
multiplayer games, 10, 350, 357, 383–388
manifest element, 62–64
multiple devices, 10–11
manifest file, 60, 62
multiple screens, 95–97
manifest tag, 63
multithreading, 44, 46–52
MarkerOptions object, 254
multi-touching, 103–108
markers, 254
MyDatabaseHelper, 172, 174
master/detail flow UI, 94, 95
MyKeyStore.pfx, 240
Math.atan2(), 108
MyLocalService.Callback, 127
Math.toDegrees(), 108
Maven, 14, 18, 184, 326
N
MCC (mobile country codes), 73
native activities, 269–270
McCandles, David (developer), 85
native Android logging, 277
mDNS standard, 356
native APIs, 276–278
media, encoding, 224–228
native C code, 207, 210, 267
MediaCodec, 224
native libraries, 267, 269, 278–284
MediaFormat, 224
native OpenGL ES 2.0, 277
MediaMuxer, 224
NativeActivity, 269
MediaPlayer, 112, 118, 208, 220
native-only applications, 268
MediaRecorder API, 209
nativeSort(), 271
memory leaks, 41
NDK (Android Native Development Kit), 210, 267,
memory management, 40–43
268–269, 276, 278, 279
Message, 43, 48, 49, 52
NDK documentation, 276
MessageQueue class, 44
network calls, 343
messages, 184
network changes, 160–162
messaging strategy, 386–388
network operations, 112
Messenger class, 137, 142–145
network polling, 343
metadata, 79, 187, 269
network service discovery, 356–357
Method object, 293
networking, Android, 319–346
method signature, 27, 28
new MyAsyncTask(), 47
methods, 29, 39. See also specific methods
NewGlobalRef(), 275
MIME type, 68
Nexus binaries, 303
minimum buffer size, 209
Nexus devices, 293, 299, 300, 303
mips (MIPS32 revision 1) ABI, 267
non-primitive parameters, 137
Miracast receiver, 95
normal broadcasts, 154–156
mm (millimeter) unit, 83
normal form (number rule), 171
412 Index
normal protection level, 232
onStop(), 162
normalized, 171
onSurfaceChanged(), 227
NoSuchMethodException, 293
onSurfaceCreated(), 219
NsdManager, 356, 357
onTouchEvent(), 101
onX methods, 44
O
OpenBinder, 131
OAuth 2, 332–337, 371
openFileHelper(), 178
OAuthRequest, 337
openFileOutput(), 234
OAuthService.getAccessToken(), 334
OpenGL ES (Embedded Subsystem), 108–109, 207,
obj field, 52
218–228, 277
object allocations, reducing, 41–43
OpenSL ES, 207, 210–214, 277–278
Object-Relational-Mapping (ORM) library, 184
operating systems, 9
obtain method, 43
Opus codec, 278–280, 282–284
ODEX files, 292
opus_decode, 283
official APIs, 287–288
OpusDecoder, 282
OkHttp, 326–327
OpusEncoder, 282
OkHttpClient, 327
opus_jni directory, 280
onActivityResult(), 336, 339, 372, 392
ordered broadcasts, 154–156
onAttachedToWindows(), 100
OrmLight (library), 184
onBind(), 115, 116, 125, 140, 142
OS X, 5, 9, 303
onClick(), 167
out directional type, 137
onClose(), 330
OutOfMemory exception, 41, 324
onCompletion(), 118
OutputStream, 181, 186
onConnected(), 260
overhead, 34
onConnectStateChange(), 354
onCreate(), 52, 112, 142, 172, 258, 339
P
onDestroy(), 112, 113, 162, 258, 339
package attribute, 63
on-device web services, 361–367
package name, 63
onDismissScreen(), 396
PackageManager, 12, 13, 157
onDraw(), 100, 101
PackageManager.DONT_KILL_APP, 158
onDrawFrame(), 220, 222, 228
packages directory, 310
onHandleIntent(), 120
packages project, 309
onLayout(), 100, 101
Pair objects, 41, 43
online web services, 340
Parcel, 43, 134–135
onMapClick(), 255
Parcelable, 135, 136, 138, 145, 179
onMeasure(), 101
ParcelFileDescriptor, 178
onOpen(), 330
Parcel.readStringList(), 136
onPartialResult(), 218
parcels, 134
onPause(), 50, 51, 61, 112, 115, 116, 127, 153, 159,
passwords, 232, 237
162, 339
patches, 315–316
onPostExecute, 47
Path class, 104, 105
onPreExecute, 47
PCM, 209, 278, 283
onProgressUpdate, 47
Pelling, Nick (programmer), 89
onReceive(), 59, 155
PendingIntent, 261, 263
onResult(), 218
permissions. See also specific permissions
onResume(), 44, 50, 61, 115, 153, 159, 339, 351
custom permissions, 232
onServiceConnected(), 116, 127, 128, 136
Google Play, 64–65
onServiceDisconnected(), 116, 128
in-app purchases, 390
onSignInFailed(), 384
securing remote APIs, 148–149
onSignInSucceeded(), 384
signatures and keys, 231–233
onStartCommand(), 44, 113, 114, 117
uses-permission, 67
Index 413
persistence, 165, 179–186
Qualcomm, 299
personas, 78
query(), 172, 174, 234
PianoKeyboard class, 100
queues, 38, 39
pinch-zoom gesture, 106
quicksort(), 276
pingServer(), 50, 51
PING_SERVER, 49, 51
R
platform certificates, 305–306
Rajawali (3D engine), 109
platform development cycle, 314–315
Rajlich, Nathan (developer) (TooTallNate), 328
platform-tools folder, 10
readability, 82, 85
playback, 207
READ_SMS, 294, 295
play_billing directory, 390
readStreamToString() method, 322
plug-ins, 137, 155, 157
real-time scenarios, 207
pm command, 12, 13
receivers, enabling/disabling, 157–158, 159
Point, 103
RECEIVE_SMS, 294
Pointer Location option, 31
recording, 207
PointerCoordinates, 106–108
recycle, 43
pointer-related interactions, 104
ReentrantReadWriteLock, 40
POJOs (Plain Old Java Objects), 182, 183, 184, 377
refactoring, 22, 27–29, 192
polygons, drawing, 256–257
Reflections API, 290, 293–294, 320
power consumption, 342–346
region, 69
preference files, 165
register-based machine, 34
PreferenceActivity, 61, 169, 170
regression-testing solution, 14
PreferenceFragment, 169, 170
regular expressions, 237
PreferenceManager, 166, 169, 170, 187
relational database, 171
PreferenceScreen, 169, 170
release(), 226
prepareEncoder(), 226
release key, 250
Presentation, 95, 97
ReleaseIntArrayElements, 273, 275
preSharedKey, 296, 297
removeCallback(), 142
pressure axis (AXIS_PRESSURE), 106
replyTo, 142, 144
primitive parameters, 138
repo sync, 303
processSms(), 344
resolutions, 83
product IDs (SKUs), 390
resource feature, 69–70, 73
ProgressBar, 52
resource qualifiers, 69, 72–74
ProGuard tool, 17
resources, advanced string, 70
project number, 381
Resources objects, 71
projection, 174
REST-based web service, 362
protection levels, 148, 232, 287, 305
RESTful web services, 362
protobuf, 184, 185–186
Restlet API, 362–365
providers folder (packages project), 309
restoration (of data), 187
ProviderTestCase2, 198
return values, 113
pt (points) unit, 83
RIL (Radio Interface Layer), 131
pthread, 212, 274, 275, 276
Ritchie, Dennis (developer), 268
PublicKey, 243
RMI, 35
publishProgress, 47
Roboto font, 82
“Pure Android,” 81
RoomStatusUpdateListener interface, 385
push notification services, 343, 344
RoomUpdateListener interface, 385
PUT, 167
rotation gesture, 106
px (pixel) unit, 83
run(), 313, 314
Python, for executing Monkey, 14
Runnable interface, 44, 45, 46
Q
414 Index
runOnUiThread, 44, 46, 51
service types, 112
RuntimeException, 294
starting Services, 113–114
staying alive, 116–117
S
stopping Services, 117–119
*:s filter, 11
testing, 196–197
salt, 236
understanding Service lifecycle, 112–113
ScaleGestureDetector class, 106
when and how to use, 111–112
scene graphs, 109
service discovery, 356–357
screens, 64, 69, 79, 159–160
Service lifecycle, 112–113
screensavers folder (packages project), 309
Service method, 44
Scribe library, 333, 337
ServiceConnection.
scripts, build, 268–269
onServiceDisconnected(), 137
SDK (Android), 9, 10, 287, 291
ServiceManager, 133, 142
SecretKey, 236, 237
Service.onBind(), 132
SecureRandom class, 236
Service.onStartCommand(), 123
security
Service.startForeground(), 116, 121
client-side data encryption, 235–239
Service.stopForeground(), 118, 121
concepts, 231–235
Service.stopSelf(), 118, 119
Crypto API, 236
ServiceTestCase class, 196–197
declaring custom permissions, 232–233
Set of String objects (string arrays) value, 166
decrypting data, 237
setComponentEnabled Setting(), 158
Device Management API, 244–247
setData, 48, 52
encrypting data, 236–239
setHomeWifi(), 314
generating key, 236
setInexactRepeating(), 344
key chain management, 239–244
SET_PROGRESS, 51
permissions, 232–233
setResultCode(), 154
protecting user data, 233–234
setResultData(), 154, 345
for published Services and other
Settings class, 297, 298
components, 148
Settings.java, 297
signatures and keys, 231–232
setupService(), 197
verifying calling applications, 234–235
setWifiApEnabled(), 308
working with encrypted data, 237–239
SHA1 value, 250
selection, 174, 175
SharedPreferences, 60, 165, 166
selectionArgs, 174, 175
sharedUserId, 306, 307
semaphores, 39
shell, running of on Android device, 12
sendPair, 41
shouldOverrideUrlLoading(), 334
serialization, 165, 179
Show options, 31
server-side push, 344, 346
signature protection level, 231, 232, 287, 305
Service component
signatureOrSystem protection level, 232
asynchronous messaging with Intents, 123–125
signatures, 231–232
binding Services, 114–116
signature-signed applications, 306–308
communicating with Services, 123–128
SILK codec, 278
configuration changes, 162
SimpleCursorAdapter, 296
creation and destruction, 112–113
simpleRaceGameLoop(), 387
enabling/disabling components for, 158
single-touch gestures, 106
IntentService, 120–121
sizes (of UI elements), 82–84
locally bound Services, 125–128
SKUs (product IDs), 390
one of four types of components, 57
Skype, 278
overview, 58
Smali tool, 292
parallel execution, 121–123
SMS messages, 155, 287, 294–296, 344
running in background, 120–123
SMS push notifications, 344–345
Index 415
SmsManager, 287
Swing/AWT packages, 35
SmsMessage, 287
SYNC_DATA, 49, 51
Sony Mobile, 299, 302
synchronization, 38, 39–40
sortIntegers(), 271
synchronized block and keyword, 39
sortOrder, 174
system protection level, 232, 287
sound effects, 112, 207
system services, adding, 310–314
soundfx directory, 74
SystemServer.run(), 312
SoundPool, 74, 100, 208
source code, 5, 19–22, 288, 290, 302–304
T
sp unit, 82
tablets, 64
SPDY protocol, 326–327
targeting ads, 395
speech recognition, 207, 216–218
Task objects, 185, 186
SpeechRecognizer, 216
TaskInfoEndpoint.insertTakeInfo(), 382
SQLite API, 60
TaskProvider, 179, 184, 198
SQLite databases, 60, 165, 171, 172, 176, 233, 239
TCP communication, 319
SQLiteDatabase, 172, 177
TDD (Test Driven Development), 191, 194
SQLiteException.endTransaction(), 177
Telephony, 151, 292, 295
SQLiteOpenHelper, 172, 174, 233
TelephonyManager, 160, 161
Square, Inc., 326
temp directory, 278
src/main directory, 271
temporal navigation, 79
SSD, 304
test case, 192
SSID, 160
test suite, 192
stack-based machine, 34
testBinder(), 197
startActivity(), 68
testDevices, 395
startActivityForResult(), 372
testIfButtonHasClickListener(), 195
startBackgroundJob(), 194
testIfClickListenerStarts
startForeground(), 117, 118, 127, 128
ServiceCorrectly(), 195
startId, 114
testing, 13–14, 24, 191–202
startService(), 66
Texas Instruments, 299
stateless, 59
text, 81–82, 84
static code analysis, 13, 22, 24–26
third-party applications, 137
static factory method, 42
third-party libraries, 17, 18
static final Creator object, 135
Thread class, 44–46, 52
static library module, 280
3D, 109
Stay Awake option, 31
3G, 160, 161
sticky broadcasts, 156–157
toolchains, 278, 279
stopForeground(), 117, 127
tools folder, 10
streaming music, 209
touch screens, 64
streaming texture, 218
transactions, 133, 176–177
stress-testing, of application’s UI, 13–14
transcoding media, 121
Strict Mode Enabled option, 31
translation, 71–72
String, 70, 132, 166, 295
TTS (text-to-speech), 207, 214–216
string arrays value, 166
Twitter, 87
string resources, 70, 71
2:3:4:6 ratio, 83
strings, hard-coded, 69
type signatures, 276
strings.xml, 69, 70
struct, 270, 274, 275, 276
U
structthread_args, 275
supports-screens element, 64
UDP, 319, 356
Surface object, 220
UI thread (main thread), 44, 52, 111, 112, 120, 319
SurfaceTexture, 220, 221, 222
UID (User ID), 234
416 Index
UiLifecycleHelper class, 339
View.onMeasure(), 97, 98
unbindService(), 116
views, custom, 97–103
unit tests, 191, 192–194
Vischeck, 85
Unity Technology, 109
visual cues, 88
UNIX operating systems, 268, 278, 279
Voice over Internet Protocol (VoIP), 207, 208, 282
unlocking devices, 300–302
Volley library, 324–325
update(), 172, 177, 234
vTextureCoord, 220
updateGameState(), 385
updateSurface, 220
W
uploadPhoto(), 124
waitForPlayerCallback(), 212
Uri, 112, 175, 177, 178, 179, 200, 290, 296
wallpapers folder (packages project), 309
URLEncoder.encode(), 332
warning box, 301
usability, 87–88
warranties, 300
USB Debugging option, 31, 300
WAV, 121
USB On-The-Go (OTG), 5
web services, integrating, 331–341
USB technology, 349, 350–352
Web Sockets, 327–331, 346, 365–367
UsbDevice, 351
WebSocketClient, 330
user data, protecting, 233–234
WebView, 79
user IDs, 63, 66, 233, 234
WebViewCient, 334
user interfaces, 79–81, 192
what value of a Message, 49
user presence, 159–160
WHERE clause, 175
user stories, 77–78
while loop, 227
userdebug configuration, 304
widgets, 81, 97
UserRecoverableAuthException, 372
Wi-Fi, 160–161, 310, 349, 356–361
users, 78, 88–90
Wi-Fi Alliance, 356, 357
uses-features, 64
WiFi Direct, 349, 350, 356, 357–361
uses-permission, 67, 232
Wi-Fi tethering, 296–297, 306–308, 349
uses-sdk, 65, 269
WifiConfiguration, 296, 308
uSTMatrix uniform, 220
WifiManager, 160, 289, 296, 308
Util class, 193
WifiP2p, 358, 359
Windows, 5, 9
V
wrappers, 131, 138, 145–148, 172
values, hard-coded, 69
Writing Style section, 81
values-<language qualifier> directory, 70
Wuala, 235
vendor directory, 309
vendor extensions, 310
X
vendor-specific platform projects, 309
x, y coordinates, 106
Verdana font, 84
x86 (32-bt Intel x86 or IA-32) ABI, 267
version control, 19–22
XDA Developers forum, 302
version information, 63
X-height, 84
versioning, AIDL files, 138
Xiph.org, 278
video processing, 218–222
View, 82, 84, 95, 97–98
Y
VIEW action, 68
View Source link, 289, 290
YouTube, 232
View.onAttachedToWindow(), 97, 98
View.onDetachedFromWindow(), 97
Z
View.onDraw(), 97, 98
zygote, 35
View.onLayout(), 97, 98