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-

synchronized-stopwatch-demo

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/

index.html

The Google Play Developer Console: https://play.google.com/apps/publish

Resources for Google Play distribution: http://developer.android.com/google/play/dist.

html

The Google Mobile Ads SDK downloads and documentation: https://developers.google.com/

mobile-ads-sdk

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