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.
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ł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 |
|
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 |
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 |
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 |