Errata


#1

(Bill - Hi! Welcome to the errata thread! If you have an apparent problem in the book, please post it to the forum in the relevant chapter. Brian or I will then verify that it’s an issue, and then add it to the errata here. That will help us keep this thread a bit more tidy and searchable. Thanks!)

[size=150]Chapter 1[/size]

Page 26: In the 2nd to last line the URL for the developer site link has an extra “http://” at the front. (Print only) (Thanks totalblackout)


#2

[size=150]Chapter 2[/size]

1- pg. 37 - Figure 2.7 “Button image”

It shows android:text="@string/next_question_button"

but it should be

android:text="@string/next_button"

:slight_smile:

EDIT: The same error is repeated on page 51 of the same chapter. (Thanks to GrandAdmiral for the tip)

2- A passage in the chapter says,

The middle item should omit “res/”. (Thanks to JimmyBMSU!)


#3

(ebook version)

Chapter 2: pg. 39 - Listing 2.6 “Adding variables and a TrueFalse array (QuizActivity.java)”

Missing comma when creating the array:

private TrueFalse[] mQuestionBank = new TrueFalse[] { new TrueFalse(R.string.question_oceans, true), new TrueFalse(R.string.question_mideast, false), new TrueFalse(R.string.question_africa, false) <-- comma needed at end of this line new TrueFalse(R.string.question_americas, true), new TrueFalse(R.string.question_asia, true), };


#4

In Chapter 2, Android and Model-View-Controller, the instance variable for the list of questions is called mQuestionBank. In Chapters 3, 4, and 5, though, this variable is called mAnswerKey.

Go with the name you originally typed in - mQuestionBank. Chapters 3, 4, and 5 are incorrect.


#5

In Chapter 5, a few paragraphs under figure 5.5 (page 93 in the print edition), a passage says, “You can just create a new file named fragment_crime.xml…” The “fragment_crime.xml” filename should be “activity_cheat.xml” instead.


#6

In Chapter 5 Listing 5.2 (pg 94, print edition), the android:text attribute for the first TextView is shown as “@string/warning_text_view”. This should be “@string/warning_text”.


#7

[size=150]Chapter 8[/size]

1- Just underneath Listing 8.5 (pg 152, print edition), a passage says,

“Organize your imports to resolve the references to DatePicker and CheckBox.”

There is no DatePicker in the listing, so the passage should not mention DatePicker at all.

2- In Listing 8.3, the EditText includes two new margin attributes that were not previously present. These two attributes should be marked bold in the text.


#8

In Chapter 21 Implicit Intents, Listing 21.2 (pg348 in print), the toJSON() method includes the following line in bold:

The bracing is correct around this line; the indentation, however, is not. This line should be indented one indentation level to the left, to be even with “return json;” on the following line.


#9

Chapter 18, Context Menus and Contextual Action Mode

1- In Listing 18.7 (pg290 in print), the listing as a whole looks like this:

        ...
        listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
        listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
            ...[lots of code here]...
        });
            
        return v;
    }

It should be inside an else statement, though. So the listing should actually look like this:

            ...
        } else {
            listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
            listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
                ...[lots of code here]...
            });
        }

        return v;
    }

2- Figure 18.1 and 18.2 both show “Delete Crime” for the menu text. Both should say “Delete” instead.

3- The ActionBarSherlock challenge omits one key step - you must change the theme for your app to one of the ABS themes (Theme.Sherlock, Theme.Sherlock.Light, or Theme.Sherlock.Light.DarkActionBar), or to a custom theme that inherits from one of those themes. Without this step, your app will not run on older devices. (Thanks to RickDroid for noticing this error.)


#10

[size=150]Chapter 22[/size]

1- In Chapter 22, Two-Pane Master-Detail Interfaces, Listing 22.13 (pg 370 in print), you see the following code listing:

    public void onCrimeUpdated(Crime crime) {
        FragmentManager fm = getSupportFragmentManager();
        CrimeListFragment listFragment = (CrimeListFragment)
                fm.findFragmentById(R.id.fragmentContainer);
        listFragment.updateUI();
    }

This listing is missing some context - there is no implementation of the interface. The complete listing should be as follows:

public class CrimeListActivity extends SingleFragmentActivity 
    implements CrimeListFragment.Callbacks, CrimeFragment.Callbacks {

    ..

    public void onCrimeUpdated(Crime crime) {
        FragmentManager fm = getSupportFragmentManager();
        CrimeListFragment listFragment = (CrimeListFragment)
                fm.findFragmentById(R.id.fragmentContainer);
        listFragment.updateUI();
    }
}

CrimeFragment.Callbacks at the top and the entire onCrimeUpdated(Crime) implementation should be bolded.

2- In addition, in Listing 22.8, the override for getLayoutResId() looks like this:

@Override protected int getLayoutResId() { return R.layout.activity_twopane; }

This disagrees with earlier code, which asked you to use R.layout.activity_masterdetail. The earlier code is correct, and activity_masterdetail should be used.

3- Just under Figure 22.6, the text says the following:

Don’t have any code that does that? You’re not crazy - the text is incorrect here. No such code has been specified in the text so far. (thanks to glenng)

4- If you tap the Home button on a tablet, the app will crash. The issue is that CrimeListActivity has no parent activity.

To fix, add the following code to CrimeFragment.onCreateView:

    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_crime, parent, false);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB &&
        		NavUtils.getParentActivityIntent(getActivity()) != null) {
            getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
        }

#11

In Chapter 23, More About Intents and Tasks, Listing 23.4, the reference to “pm” in the line:

…will not work, because the “pm” variable is neither an instance variable, nor is it final.

The listing can be fixed by adding a line inside getView() that retrieves the PackageManager, similar to Listing 23.3:

        setListAdapter(new ArrayAdapter<ResolveInfo>(getActivity(), android.R.layout.simple_list_item_1, 
            activities) {
            public View getView(int pos, View convertView, ViewGroup parent) {
                PackageManager pm = getActivity().getPackageManager();

                View v = super.getView(pos, convertView, parent);
                TextView tv = (TextView)v;
                ResolveInfo ri = getItem(pos);
                tv.setText(ri.loadLabel(pm));
                return v; 
            }
        });

#12

In Chapter 27, Loopers, Handlers, and HandlerThread, Listing 27.6 and Listing 27.7 (pg447 in print) are missing some generic type information.

In Listing 27.6, the class declaration at top should appear as follows:

In Listing 27.7, the ThumbnailDownloader constructor invocation is missing the generic parameter. Your final code should appear as follows:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        setRetainInstance(true);
        new FetchItemsTask().execute();
        
        mThumbnailThread = new ThumbnailDownloader<ImageView>(new Handler());
        mThumbnailThread.setListener(new ThumbnailDownloader.Listener<ImageView>() {
            public void onThumbnailDownloaded(ImageView imageView, Bitmap thumbnail) {
                if (isVisible()) {
                    imageView.setImageBitmap(thumbnail);
                }
            }
        });
        mThumbnailThread.start();
        mThumbnailThread.getLooper();
    }

#13

In Chapter 31, Browsing The Web & WebView, Figure 31.2 (pg 508 in print), the widgets appear in the wrong order. The diagram shows ProgressBar first, TextView second, and WebView last.

Instead, WebView should appear first, TextView second, and ProgressBar should appear at the bottom.


#14

[size=150]Chapter 17[/size]

1- The constructor for CrimeLab is missing the initialization of the mSerializer instance variable. In Figure 17.3, the code should read:

private CrimeLab(Context appContext) {
  mAppContext = appContext;
  mCrimes = new ArrayList<Crime>();
  mSerializer = new CriminalIntentJSONSerializer(mAppContext, FILENAME);
}

The last line is not included until figure 17.7 in the book.

The preceding paragraph should also say “in its constructor” instead of “in onCreate(…)”.

Thanks pmcconnell (and paupac for the textual note).

2- If a null title is saved, an exception will be thrown when the crimes JSON is reloaded. That is due to a missing if statement in Figure 17.5:

public Crime(JSONObject json) throws JSONException { mId = UUID.fromString(json.getString(JSON_ID)); if (json.has(JSON_TITLE)) { mTitle = json.getString(JSON_TITLE); } mSolved = json.getBoolean(JSON_SOLVED); mDate = new Date(json.getLong(JSON_DATE)); }

Thanks to RickDroid for the correction and the code.


#15

In Chapter 12, Dialogs, Listing 12.6 (pg219 in print), the non-bolded text includes a method call to updateDate().

Ignore this line - you will make this change later, in listing 12.11.

(thanks to bofredo for pointing out the issue)


#16

In Chapter 32, Custom Views And Touch Events, there are a couple of corrections to the text.

1- On pg515 in the printed edition, immediately prior to Listing 32.2, the text says to use ListFragment for the superclass. This is incorrect - instead, use Fragment, as listing 32.2 shows. Thanks to pmcconnell for pointing out the error.

2- On pg519 in the printed edition, immediately prior to Listing 32.5, the text says:

The method should be onTouchEvent(…), and it logs a message, not a method. (Thanks to android77 for the correction.)

3- Listing 32.6 (pg 520 in the printed edition) omits the getCurrent() method, later referred to in Listing 32.9. Implement getCurrent() as a standard getter method:

public PointF getCurrent() { return mCurrent; }

Thanks to pmcconnell for pointing out the error.

4- For the first challenge, a significant detail is omitted - for onSaveInstanceState to be called, your view must have an id.

5- In some places in this chapter, the list of boxes is called mBoxen, and in others it is referred to as mBoxes. mBoxen is grammatically incorrect, but Bill maintains that it is correct regardless. Thanks to android77 for pointing out the error!


#17

In Chapter 12, Dialogs, on page 223 (print) the text mentions a “private updateDate() method” and the code sample shows the method as public.


#18

In Chapter 9, Figure 9.12, the arrow from titleTextView to solvedCheckBox is labeled incorrectly. It labeled layout_below, but should instead say layout_toLeftOf.

Thanks to android77 for the tip.


#19

[size=150]Chapter 16[/size]

1- In Listing 16.1, a string named crime_date_label is shown.

This string is not used, and may be safely omitted.

2- In Listing 16.3, the non-bolded code is incorrect. It should instead read as it was implemented earlier in the book:

   @Override
   public void onResume() {
      super.onResume();
      ((CrimeAdapter)getListAdapter()).notifyDataSetChanged();
   }

3- In Listing 16.13, TargetApi(11) is shown in bold. It should not be bolded (it already appeared in listing 16.8). (Thanks to conxorxa for the tip!)


#20

[size=150]Chapter 19, Viewfinder[/size]

1- This exercise asks that you import the Camera class. There are actually two Camera classes - android.hardware.Camera and android.graphics.Camera.

You want android.hardware.Camera, not android.graphics.Camera. android.graphics.Camera is used to position a virtual camera in 3d space, so it is not what you need.

2- Listing 19.12 says to check for the presence of a camera by checking for front and back facing cameras in the package manager.

This doesn’t work on emulators that don’t have cameras, though. These devices falsely claim to have cameras they do not have! Later SDKs will throw an exception when you try to acquire the camera, though. (I’m not sure what SDK this starts happening - I can tell you that SDK 9 doesn’t throw, and SDK 17 does, but I don’t have the time to test all the SDKs in between. Let me know if you find out the answer to this!)

To fix this, use the following code instead of Listing 19.12:

        // if camera is not available, disable camera functionality
        PackageManager pm = getActivity().getPackageManager();
        boolean hasACamera = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA) ||
                pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT) || 
                Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD ||
                Camera.getNumberOfCameras() > 0;
        if (!hasACamera) {
            mPhotoButton.setEnabled(false);
        }

Thanks to RickDroid for pointing out the issue.

3- All of Listing 19.5 should be bold. (Thanks to glenng for pointing out the mistake.)

4- Figures 19.8 and 19.9 both use the fill_parent constant in some places. This is out of date, and very silly. Use match_parent instead - the two behave identically, but fill_parent is deprecated. (Thanks to drumerboi for the catch.)