Errata

Learning Android

Errata for Learning Android

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released. If the error was corrected in a later version or reprint the date of the correction will be displayed in the column titled "Date Corrected".

The following errata were submitted by our customers and approved as valid errors by the author or editor.

Color key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted By Date submitted Date corrected
Printed, PDF, , Other Digital Version
Page xvi
Under the URL where ""We have a web page for this book, where we list errata, examples, and any additional information. You can access this page at:"


Add this:

"The author maintains a copy of the example code at the following site, as well: https://github.com/marakana/LearningAndroidYamba"

Anonymous  Jun 02, 2011  Jun 03, 2011
PDF, Other Digital Version
Page 5
first line in the 3rd paragraph, under the graph.

Where says: "You may notice that there are not a lot of users of Android 1.5 and 1.6." should be "You may notice that there are a lot of users of Android 1.5 and 1.6." to be in according with the graph (more than 60% uses Android 1.5 or 1.6)

marcelo medina  Mar 26, 2011  Jun 03, 2011
PDF
Page 5
Figure 1-1

Though it said it used the January 2011 Graph. I know from previously looking at it on Google, that is wrong picture. It is also reflected in paragraph 3.

Note from the Author or Editor:
I did update the picture closer to book coming out and I may not have updated all there references to it. The actual numbers are not as important as is the fact that we have mixed bag of versions out there. But should be update to just be sample of distribution at some point in time.

darkfire  Apr 02, 2011  Aug 19, 2011
Printed
Page 8
Figure 2-1

On Android runtime box there are two boxes: Core libs and Delvik VM.
Delvik is a typo, it should be Dalvik.

Enrico Baccianini  Apr 23, 2011  Jun 03, 2011
PDF, Other Digital Version
Page 9
Note about GNU libc

GNU libc is *not* licensed under the GPL license as stated in the text.

It is licensed under the *LGPL* (Lesser General Public License), which is a _weak-copyleft_ license, i.e. a _compromise_ between strong-copyleft licenses such as the GPL and permissive licenses such as Apache/MIT or BSD.

Enrique Matias Sanchez  Mar 23, 2011  Jun 03, 2011
Printed
Page 9
Indented line immediately following the text "OpenSSL" about one third from the top of the page

OpenSSL is described as Secure Locket Layer rather than Secure Socket Layer.

Note from the Author or Editor:
Typo

dblanchard  May 31, 2011  Jun 03, 2011
Printed
Page 12
3rd paragraph

"An APK file roughly has three main components. An API consists of the following major components"

The term API is incorrectly used (typo for APK?), and the two sentences repeat the same meaning.

Note from the Author or Editor:
Yes, API should be APK. Typo

Anonymous  May 23, 2011  Jun 03, 2011
PDF
Page 15
second paragraph in bear paws callout

"everything should be pretty much for different operating systems" should be "everything should be pretty much *the same* for different operating systems"

Anonymous  Apr 03, 2011  Jun 03, 2011
PDF
Page 16
Setting Up PATH to Tools, 1st paragraph

Says:

~/android-skd/platform-tools/

Must say;

~/android-sdk/platform-tools/

Note from the Author or Editor:
Correct!

Alonso Quiroz  Apr 02, 2011  Jun 03, 2011
25
...

I wouldn't call this a "technical error", but more of a content issue.

The "Quick Start" chapter has you enter the entire HelloWorld application. Then it tells you how to start the emulator. Then the chapter ends. Nowhere does it even suggest RUNNING the HelloWorld application and seeing it in the emulator. That's a pretty wimpy "Quick Start" if that's really what you intended.

Note from the Author or Editor:
There should be a sentence that says: To run this application on the emulator, select the HelloWorld project in the Eclipse's Package Explorer window, right click on it, and choose Run As > Android Application.

David M. Karr  Mar 27, 2011  Jun 03, 2011
PDF
Page 29
Figure 4-1

There are two "Stopped" states in the diagram instead of "Stopped" and "Paused".

Note from the Author or Editor:
Correct! The "Stopped" on right side should be "Paused".

bz7  Mar 25, 2011  Jun 03, 2011
PDF
Page 43
Timeline Activity

The paragraph ends with:

Finally, we'll get it right by introducing Lists and Adapters to the mix. Finally, we'll get it right by introducing Lists and Adapters to the mix and use them to tie the data to our user interface.

It seems to be a typo.

Note from the Author or Editor:
Should be just: Finally, we'll get it right by introducing Lists and Adapters to the mix to use them to tie the data to our user interface.

Alonso Quiroz  Apr 02, 2011  Jun 03, 2011
Printed, PDF, , Other Digital Version
Page 51
Last paragraph

Change: "In our case, the app will be able to work on API level 4 (Android 1.6), so enter 4 here." to
"In our case, the app will be able to work on API level 5 (Android 2.0), so enter 5 here."

Anonymous  Jun 02, 2011  Jun 03, 2011
Printed, PDF, , Other Digital Version
Page 51
Last paragraph


Change: "In our case, the app will be able to work on API level 4 (Android 1.6), so enter 4 here." to
"In our case, the app will be able to work on API level 5 (Android 2.0), so enter 5 here."

Also update the Fig 6-2 to say 5 instead of 4 for minimum SDK version.

Anonymous  Jun 02, 2011  Jun 03, 2011
PDF
Page 56
2nd paragraph in "The StatusActivity Java Class"

On page 51 in the chosen package name is "com.marakana.yamba" ("I'm going to use "com.marakana.yamba" ") but in page 56 (and in the source code presented later) the package name changes to "com.marakana.yamba1"



Note from the Author or Editor:
For code manageability reasons, I started numbering packages in the actual code, so there's no collision. In the book, I might have missed it in this place.

bz7  Mar 28, 2011  Jun 03, 2011
Printed, PDF, Other Digital Version
Page 57, 58 in print version
Last paragraph

You pass this as an argument to setOnClickListener [...]

In this sentence, "this" is a Java reserved word, and should be formatted as code. The sentence is hard to understand as it is.

Enrique Matias Sanchez  Mar 23, 2011  Jun 03, 2011
60
note

The Twitter constructor as provided in the text is deprecated in the Winterwell jar. The note mentions "the jtwitter.jar library provided with this code has been slightly modified from the official Winterwell version to make it work" but at least in Safari Books Online, I see no provision to download a special version of this jar.

Note from the Author or Editor:
The code for the modified version of JTwitter library is available here: https://github.com/marakana/LearningAndroidYamba

Michael Lindsey  Mar 15, 2011  Aug 19, 2011
60
Figure 6.3

In the example code,

editText = (EditText) findViewById(R.id.editText);

should read:

editText = (EditText) findViewById(R.id.editStatus);

Note from the Author or Editor:

Not sure what page this is on - it's not on page 60 in Safari (Figure 6.3 isn't on page 60 and doesn't show that code.) The code "editText = (EditText) findViewById(R.id.editText);" is used in a couple of places. Need more explicit information on exactly where the erratum is.

John Murphy  May 19, 2011  Aug 19, 2011
PDF, Other Digital Version
Page 61
Midpage

at the bottom that says AnddroidManifest.xml

One `d' in Addroid should be removed.


In the previous paragraph he filename is correctly spelled, but its formatting is wrong.

Enrique Matias Sanchez  Mar 23, 2011  Jun 03, 2011
PDF
Page 62
1st tip

Ctrl-O is listed as the shortcut for "Organize Imports." The actual shortcut is Ctrl-Shift-O. This is in the Eclipse IDE for Java Developers.

Note from the Author or Editor:
It should be Ctrl-Shift-O.

Joel Harris  Mar 26, 2011  Jun 03, 2011
PDF, Other Digital Version
Page 69
Figure 6.11

In Figure 6.11, the contents of the EditText and the title of the app doesn't match the code (ie, `140-characeter tweet' should be `140-character status').

Enrique Matias Sanchez  Mar 24, 2011  Jun 03, 2011
PDF, Other Digital Version
Page 73
Last paragraph

implementation.Figure 6-12 shows [...]

There should be a space after the period.

Enrique Matias Sanchez  Mar 24, 2011  Jun 03, 2011
PDF, Other Digital Version
Page 74
Last paragraph

"PNG is preferred to the GIF standard because PNG is lossless and doesn't require any patent licenses."

While GIF did require patent licenses in the past, Unisys patent expired on 2003/2004 (depending for which country), and IBM patent expired on 2006.

Since 5 years ago, employment of the GIF format doesn't require any patent license.

On the other hand, PNG provides true-color, alpha transparency and better compression.

Note from the Author or Editor:

Enrique Matias Sanchez  Mar 24, 2011  Aug 19, 2011
PDF
Page 79
1st paragraph

"You might want multiple versions of same resource" should be " You might want multiple versions of *the* same resource"

Anonymous  Apr 03, 2011  Jun 03, 2011
PDF
Page 79
4th paragraph

"if the user in France" should be "if the user *is* in France"

Anonymous  Apr 03, 2011  Jun 03, 2011
PDF
Page 80
last paragraph

"it is worth keeping in mind few optimization points" should be "it is worth keeping in mind **a** few optimization points"

Anonymous  Apr 03, 2011  Jun 03, 2011
PDF
Page 87
1st paragraph under section PrefsActivity

From the text : "You may recall from <<Activities> that every
screen in an Android app is an activity."

Perhaps "<<Activities>" should be a link to another section. As it is, it is unclear what is meant.

Note from the Author or Editor:
This is a bug in Asciidoc. <<Activities> should have been <<Activities>> and would have become a link.

Joel Harris  Mar 28, 2011  Jun 03, 2011
PDF
Page 95
First paragraph

The text reads that the onClick method requires updating and shows the updated onClick method. However, the onClick method doesn't set the status. It does this:

new PostToTwitter().execute(status);

The method that should be updated instead is PostToTwitter.doInBackground()

The downloadable sample code shows this.

Note from the Author or Editor:
That is correct - we did add AsyncTask in Chapter 6. So, we should say:

... So, doInBackground() in PostToTwitter task becomes:

protected String doInBackground(String... statuses) {
try {
Twitter.Status status = getTwitter().updateStatus(statuses[0]);
return status.text;
} catch (TwitterException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
return "Failed to post";
}
}

Joel Harris  Mar 28, 2011  Aug 19, 2011
PDF
Page 95
after first code block

the following sentence makes no sense in context:

"Note that although we moved the code where we initialize our connection to the cloud, we still need the AsyncTask to deal with the fact that this call is still blocking and may take a while to complete, as it's subject to network availability and latency."

we didn't move the initialization to the cloud; we simply moved it to a different function (a function that isn't in the cloud). also, the word "still" is repeated unnecessarily.

Note from the Author or Editor:
Should be:
Note that we need AsyncTask to deal with the fact that this call is blocking and may take a while to complete, as it's subject to network availability and latency.

Anonymous  Apr 03, 2011  Jun 03, 2011
PDF, Other Digital Version
Page 102
3rd and 4th paragraphs

Saying "to create our own instance of this object" meaning "to subclass" is confusing, at best.

An object is an instance of a class, but a class is not an instance of an object.

Note from the Author or Editor:
"We are going to create our own instance of this object and call it YambaApplication." should say: "We are going to create our own subclass of Application class and call it YambaApplication."

Enrique Matias Sanchez  Mar 30, 2011  Jun 03, 2011
PDF, Other Digital Version
Page 102
Last paragraph

`it also provides the onTerimante() callback'

It should be `onTerminate()'.

Enrique Matias Sanchez  Mar 30, 2011  Jun 03, 2011
PDF
Page 107
inside the onStartCommand() method

The value START_STICKY is returned from the onStartCommand() method. This value occurs 4 times in the book, but is never explained.

Note from the Author or Editor:
START_STICKY is used as a flag to indicate this service is started and stopped explicitly, which is our case.

Joel Harris  Mar 28, 2011  Aug 19, 2011
PDF
Page 107
Bullet point #4

"stated" should be "started"

vkurup  Apr 21, 2011  Jun 03, 2011
PDF
Page 110
1st paragraph and first figure

The text says to look at figure 8-2 for an example of what the Running services activity looks like on the android, but instead it shows essentially the same diagram as is shown in figure 8-1

Note from the Author or Editor:
What is Figure 8-3 should be in place of Figure 8-2. Figure 8-3 should be replaced with what was originally yamba-3.png before designer re-did them.

Joel Harris  Mar 28, 2011  Jun 03, 2011
PDF
Page 110
1st paragraph under "Looping in the Service"

"an then go back to "sleep" for some time"
should be
"and then go back to "sleep" for some time"

Joel Harris  Mar 28, 2011  Jun 03, 2011
PDF, Other Digital Version
Page 111
source code

Putting Thread#start() in Service#onStartCommand(Intent, int, int) which may be invoked few times will result in IllegalThreadStateException.

Note from the Author or Editor:
That is correct. I ended up moving all the code from onStartCommand() on onCreate() and getting rid of onStartCommand() completely. Alternatively, one could catch IllegalThreadStateException.

Bart&#322;omiej Piech  Apr 24, 2011  Aug 19, 2011
Printed
Page 114
Example 8-6

You declare a flag, runFlag, to check if service is running. However, you don't used it later in any method.

In next version of class UpdaterService (Example 9-2 / p.124), it appears in method onStartCommand. The same code should be in the Example 8-6 (p. 114)

Note from the Author or Editor:
We use this flag later on...

Anonymous  May 20, 2011  Aug 19, 2011
PDF
Page 117
Figure 8-3

Figure 8-3 does not display what it says it displays

Note from the Author or Editor:
Yes, this is a wrong picture. It should be image called yamba-3.png, but for some reason it got replaced somewhere.

Joel Harris  Mar 28, 2011  Jun 03, 2011
PDF
Page 122
2nd paragraph in Cursors section

"it's" should be "its"

vkurup  Apr 26, 2011  Jun 03, 2011
PDF
Page 123
Example 9-1: onCreate method code

The create table SQL statement does not include the "source" column (which is referenced later in the chapter)

Note from the Author or Editor:
Change this line to look like this:

String sql = "create table " + TABLE + " (" + C_ID + " int primary key, " + C_CREATED_AT + " int, " + C_SOURCE + " text, " + C_USER + " text, " + C_TEXT + " text)"; //

bz7  Apr 16, 2011  Jun 03, 2011
PDF
Page 124
Bullet point 4

"...define these as constants to that we can refer to them..."
should be
"...define these as constants so that we can refer to them..."

Joel Harris  Mar 28, 2011  Jun 03, 2011
Printed
Page 126
inside for loop near bottom

values.put(DbHelper.C_SOURCE, status.source);

This throws an SQLiteException, trying to use the column because it isn't in the "create table" statement on page 123. Either remove from this loop, or add to the create statement.

Daniel Welsh  Apr 14, 2011  Aug 19, 2011
129
paragraph just before Database Constraints section

This is more an omission than mistake.
Last sentence: We can also verify that the data is indeed in the database by using sqlite3.
This can be done with the dump command at the sqlite3 prompt:
sqlite> .dump

Chong Lim Kim  Apr 09, 2011  Aug 19, 2011
PDF
Page 133
point 2 in Example 9-4

Hi ,

the method was wrote like this :
public StatusData getStatusData() { //
return statusData;
}

this will lead to NullPointerException when you run the application

it suppose to be like this :
public StatusData getStatusData()
{ statusData = new StatusData(this);
return statusData;
}

Note from the Author or Editor:

I would actually improve it like this instead:

public StatusData getStatusData() {
if (statusData==null) {
statusData = new StatusData(this);
}
return statusData;
}

Sherif  May 24, 2011  Jun 03, 2011
Printed
Page 149
Example 10-8

Missing the following line:

import android.widget.SimpleCursorAdapter.ViewBinder;

There are several ViewBinder classes, and if the wrong one is chosen when Eclipse offers to import one for you it won't compile.

Note from the Author or Editor:
Correct. In general, I tried to leave imports out of the book as they are more/less automatic in Eclipse, however in this case there are a view choices making it a potential issue.

Daniel Welsh  Apr 15, 2011  Aug 19, 2011
Printed
Page 149
ViewBinder section, 4th para

"In our final iteration of TimelineAdapter..."

The caption for Example 10-8 says "TimelineActivity.java."

These can't both be correct.

Note from the Author or Editor:
Yes, it should say just "adapter" not TimelineAdapter.

Daniel Welsh  Apr 15, 2011  Jun 03, 2011
Printed
Page 150
Updating the Manifest File

Wouldn't moving this section prior to the Adapter discussion make more sense? There are several iterations that are not testable until the manifest has been updated (e.g., the entire TimelineAdapter class is built, then refactored out before it can be used).

Note from the Author or Editor:
Sure, that would make sense. Whenever there's refactoring, there's a lot of moving code around, which is easier to do, than explain to others. And while this is happening, code is generally broken. That's why refactoring is best done in small steps.

Daniel Welsh  Apr 15, 2011  Aug 19, 2011
PDF
Page 152
Code block under Initial App Setup

No indication is given as to which onCreate() method is being modified.

Note from the Author or Editor:
I would add a title to that block of code that says:

onCreate() in TimelineActivity

Joel Harris  Mar 29, 2011  Aug 19, 2011
PDF
Page 152
code block in 'Initial App Setup'

This block needs a little more setup. The variable 'yamba' has not yet been defined in TimelineActivity.java. There is also no previous definition of the getPrefs() function.

vkurup  Apr 27, 2011  Aug 19, 2011
Printed
Page 155
middle of code

((YambaApplication) getApplication()).getStatusData().delete();

The delete() method was not described in the StatusData class on pp. 130-133 or added in the intervening pages.

In fact, the capability of Yamba to delete status data is not even mentioned in the text.

Note from the Author or Editor:
It is added in the code but not discussed in the book, correct.

Daniel Welsh  Apr 15, 2011  Aug 19, 2011
157
onCreate() method of TimelineActivity class

getPrefs() method is not defined for yamba object in code line:

// Check if preferences have been set
if (yamba.getPrefs().getString("username", null) == null) {

I added following code in YambaApplication.java, which seems to work

public SharedPreferences getPrefs() {
return prefs;
}

(Note: the code snippet containing yamba.getPrefs() first appeared on page 152.)

Note from the Author or Editor:
Yes, that is a possible fix. Another one is to make prefs be package-visible, i.e. remove "private" declaration.

Chong Lim Kim  Apr 10, 2011  Aug 19, 2011
158
last paragraph

Omits to say that StatusActivity.java must be refactored to extend BasicActivity instead of Activity; otherwise, Options Menu cannot be called from the Status Update screen. The following line seems to work ok for me.

public class StatusActivity extends BaseActivity implements OnClickListener, TextWatcher {
...
}

Note from the Author or Editor:
Correct. This is true for StatusActivity same way it is true for TimelineActivity.

Chong Lim Kim  Apr 10, 2011  Aug 19, 2011
164
Example 11-4. TimelineActivity.java with TimelineReceiver inner class

Android reference for requery() in Cursor class says:
"This method is deprecated. Don't use this. Just request a new cursor, so you can do this asynchronously and update your list view once the new cursor comes back."

So instead of
@Override
public void onReceive(Context context, Intent intent) { // 2
cursor.requery(); // 3
adapter.notifyDataSetChanged(); // 4
Log.d("TimelineReceiver", "onReceived");

I tried following, which seems to work ok, and I don't see "ERROR/Cursor(145): Invalid statement in fillWindow()" in LogCat
@Override
public void onReceive(Context context, Intent intent) { // 2
cursor = yamba.getStatusData().getStatusUpdates();
adapter.changeCursor(cursor);
adapter.notifyDataSetChanged(); // 4
Log.d("TimelineReceiver", "onReceived");

Chong Lim Kim  Apr 20, 2011  Aug 19, 2011
167
The Network Receiver

Adding a network receiver as in Example 11-8 requires a code change in the UpdaterService.java class. The downloadable example code reflects this change needed, but there is no mention of that in the book.

The code change is required because the onReceive() callback in NetworkReceiver also starts the UpdaterService as seen in the following code snippet.
...
} else {
Log. d(TAG, "onReceive: connected, starting UpdaterService");
context. startService(new Intent(context, UpdaterService.class));
}

Trying to start the inner class Updater object (is-a Thread) a second time results in an Exception and a force close of the program. So the following change is required in the UpdaterService.java class, as shown below, to check whether the service is already running and if so, not to start updater again.

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);

if (!runFlag) { // swCL: otherwise Exception thrown when NetworkReceiver calls startService(); in downloaded code, not in book
this.runFlag = true;
this.updater.start();
this.yamba.setServiceRunning(true);

Log.d(TAG, "onStarted");
}
return Service.START_STICKY;
}

Chong Lim Kim  Apr 23, 2011  Aug 19, 2011
Printed, PDF, , Other Digital Version
Page 173
Yamba images

The word "recorder" should have been "receiver" when describing Boot and Network receivers.

Marko Gargenta
Marko Gargenta
 
Apr 06, 2011  Jun 03, 2011
Printed
Page 176
Example 12-1, second bullet

Part B, com.marakana.yamba.provider

should match the URI given.

Daniel Welsh  Apr 16, 2011  Jun 03, 2011
Printed
Page 177
3rd paragraph

StatusData statusData;

No initialization is provided in the book. The reader is left to examine the downloaded example code for:

@Override
public boolean onCreate() {
statusData = new StatusData(getContext());
return false;
}

Daniel Welsh  Apr 16, 2011  Aug 19, 2011
177
Inserting Data section

The issue is actually in the StatusData.java class, but surfaces here in the code to override the insert() method
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = statusData.dbHelper.getWritableDatabase();
...

In StatusData.java class, the access level modifier for the member field dbHelper was 'private':
private final DbHelper dbHelper;
but that should be changed to 'no modifier' or package-private:
final DbHelper dbHelper;
in order for statusData.dbHelper to be visible in other classes such as StatusProvider here.

The change is made in the downloadable code, but not mentioned in the book.

Note from the Author or Editor:
Correct.

Chong Lim Kim  Apr 23, 2011  Aug 19, 2011
183
Example 12-2. YambaWidget.java

The code pointed to by Note #3 of example 12-2:
Cursor c =
context.getContentResolver().query(StatusProvider.CONTENT_URI,
null, null, null, null);
does not sort the dataset returned. Changing the code to the following worked for me:
Cursor c =
context.getContentResolver().query(StatusProvider.CONTENT_URI,
null, null, null, StatusData.C_CREATED_AT+" DESC");

This is so that the next couple of lines of code will work
....
try {
if (c.moveToFirst())
...
since the dataset would then be sorted in descending order of time created, and the first record would be the last 'post.'

Note from the Author or Editor:
That is correct - to sort the cursor:
Cursor c = context.getContentResolver().query(StatusProvider.CONTENT_URI, null, null, null, null);

should be:

Cursor c =

context.getContentResolver().query(StatusProvider.CONTENT_URI,

null, null, null, StatusData.C_CREATED_AT+" DESC");

Chong Lim Kim  May 10, 2011  Jun 03, 2011
Printed
Page 185
Creating the XML Layout

@color/edit_text_background is undefined.

Note from the Author or Editor:
It is defined in res/values/colors.xml, but not explained in the book.

Daniel Welsh  Apr 16, 2011  Aug 19, 2011
Printed, PDF, , Other Digital Version
Page 187
Yamba image

The word "recorder" should have been "receiver" when describing Boot and Network receivers.

Marko Gargenta
Marko Gargenta
 
Apr 06, 2011  Jun 03, 2011
Other Digital Version
193
"Testing the Service"

In Chapter 8, when testing the UpdaterService on the emulator, the app crashes when you try to start the service using the menu. It appears that onStartCommand is not available in SDKVersion 4 so in order to fix this you need to change your AndroidManifest.xml file to:

<uses-sdk android:minSdkVersion="5" />

Note from the Author or Editor:
Yes, that's correct, the minimumSdkVersion should be 5 so that onStartCommand() is available. Version 4 didn't have it.

bkurzius  May 26, 2011  Aug 19, 2011
Printed
Page 203
onResume method

if (!YambaApplication.LOCATION_PROVIDER_NONE.equals(provider)) { // 4
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); // 5
}

To prevent problems when location preference is on, then turned off, should clear location member variables as follows:

else {
locationManager = null;
location = null;
}

Daniel Welsh  Apr 17, 2011  Aug 19, 2011
Printed
Page 204
top of page

yamba.getTwitter().setMyLocation(latlong);

The location is never cleared in situations where location preference is on, and then turned off.

Maybe call setMyLocation(null) in an else?

Note from the Author or Editor:
That should work.

Daniel Welsh  Apr 17, 2011  Aug 19, 2011
205
Before second last paragraph

App will crash if reader forgets to add uses-permission elements in the AndroidManifest.xml file for Yamba (just as for the standalone WhereAmI app discussed in the previous section).
<manifest ...>
...
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>

Note from the Author or Editor:
That's correct. I thought this is explained in the book prior to this example already.

Chong Lim Kim  Apr 24, 2011  Aug 19, 2011
205
Second last paragraph

Useful information when simulating location updates/provider in an emulator (my target virtual device was for API Level 8, Android 2.2):

1. On phone's Home page > Menu > Settings >
a. Location & security: Set at least Use GPS satellites (maybe also set Use wireless networks, although using network didn't work for me; see below)
b. Application > Development > set Allow mock locations

2. In Eclipse with the Android plugins (ADT and DDMS) > Window > Show View > Other... > Android folder > Emulator Control > scroll to Location Controls to enter Longitude and Latitude > Send


If reader is having trouble getting the emulator's location provider to work, try the following.
a. For preference, I could only make the location provider accept the lat and lon values entered in the emulator location controls when I selected "GPS via satellites!", and not when I selected "Mobile Network will do."
b. For debugging, I also changed the LOCATION_MIN_TIME to something much shorter, say 10000 (10 seconds).

Note from the Author or Editor:
Correct. Useful clarification.

Chong Lim Kim  Apr 24, 2011  Aug 19, 2011
211
Note 2

Similar to the omission in Note 1, does not remind reader here that the static final field INTERVAL_NEVER has to be defined in YambaApplication.java (snippet below is from the downloadable example code).

public class YambaApplication extends Application implements
OnSharedPreferenceChangeListener {
...
public static final long INTERVAL_NEVER = 0;
...
}

Chong Lim Kim  Apr 24, 2011  Aug 19, 2011
211
code in Example 13-14. BootReceiver.java updated with Alarm service calls...

Above code does not appear to work; no alarm call is triggered.

The problem appears to be a mismatch of the first two parameters. Replace this line of code
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, System
.currentTimeMillis(), interval, pendingIntent);
with this line
alarmManager.setInexactRepeating(AlarmManager.RTC, System
.currentTimeMillis(), interval, pendingIntent);

If the second parameter is to be System.currentTimeMillis(), then the first parameter has to be AlarmManager.RTC, which is described in the Android Reference as: "Alarm time in System.currentTimeMillis() (wall clock time in UTC). This alarm does not wake the device up; if it goes off while the device is asleep, it will not be delivered until the next time the device wakes up."

Note from the Author or Editor:
True.

Chong Lim Kim  Apr 26, 2011  Jun 03, 2011
Printed, PDF, , Other Digital Version
Page 211
2nd to last paragraph


Change ELAPSED_REALTIME () to AlarmManager.RTC.

Anonymous  Jun 02, 2011  Jun 03, 2011
216
Writing the AIDL

Might wish to remind reader explicitly to create a new Android Project in Eclipse, with a new package name com.marakana.logservice

Note from the Author or Editor:
Correct, but assumed they'd know that by this point in the book.

Chong Lim Kim  Apr 28, 2011  Aug 19, 2011
Printed, PDF, , Other Digital Version
Page 217
First paragraph after Example 14-2


"The new Java file is located in the gen folder under /gen/com/marakana/logservice/LogService.java." should say:
"The new Java file is located in the gen folder under /gen/com/marakana/logservice/ILogService.java."

(just rename LogService.java to ILogService.java)

Anonymous  Jun 02, 2011  Jun 03, 2011
218
Note 3 for Example 1 4-3. LogService.java

Note (3) This instance of IBinder is represented by ILogService.Stub(), a helper method that is generated for us in the Java stub file...

should read

Note (3) This instance of IBinder is represented by ILogService.Stub, a helper inner class that is generated for us in the Java stub file...

Chong Lim Kim  Apr 28, 2011  Jun 03, 2011
218
Note 3 for Example 1 4-3. LogService.java

typo in name of generated class file

... This code is part of /gen/com/marakana/logservice/LogService.java.

should read

... This code is part of /gen/com/marakana/logservice/ILogService.java.

Note from the Author or Editor:
Correct

Chong Lim Kim  Apr 30, 2011  Jun 03, 2011
221
Implementing the Remote Client

The following can also be inferred from looking into the LogClient folder in the Download Example Code, but was not obvious to me and caused a NoClassDefFoundError at run time before I figured out what to do.

The second paragraph says:
... However, this time around we are also going to make this project depend on the LogService project. This is important because LogClient has to find the AIDL files we created as part of LogService in order to know what that remote interface looks like...

However, I found that I needed to save the (two) .aidl files and the Message.java file in the LogClient project anyway -- as described more below. So, I believe making the LogClient project depend on the LogService project is just so that Android will know to install the LogService.apk when it is installing the LogClient.apk (to the emulator in my case.)

The Android Dev Guide on "Android Interface Definition Language (AIDL)"
http://developer.android.com/guide/developing/tools/aidl.html
says in the Defining an AIDL Interface section: "You must define your AIDL interface in an .aidl file using the Java programming language syntax, then save it in the source code (in the src/ directory) of both the application hosting the service and any other application that binds to the service."

Here's how I recall I did it:
1. In Eclipse, right click on the LogClient project > New > Package > enter Name for new package: com.marakana.logservice
2. Right click on the new package > Import... > File System | Next > Browse... > navigate to your Eclipse workspace folder | locate the folder for LogService project > src/com/marakana/logservice/ > select the files: ILogService.aidl, Message.aidl, Message.java > Finish

Note from the Author or Editor:
That is correct - you need to copy both AIDL files as well as Message.java form Server to Client preserving original package names. This is so that both projects can use the same interfaces. The reason for this copying is because one app cannot load another app's code.

The reason for making one project dependent on another in Eclipse is just to help with Eclipse installing both projects when they chance.

Chong Lim Kim  Apr 30, 2011  Aug 19, 2011