9781449390501
Android_Preferences.html

Chapter 7. Preferences, File System, Options Menu, and Intents

If you're new to the Android mobile operating system, Learning Android is the perfect way to master the fundamentals. This gentle introduction shows you how to use Android's basic building blocks to develop user interfaces, store data, and more. Buy the print book or ebook.

In this chapter, you will learn how to create preferences for your application, how the file system is organized, and how to use intents and the options menu to jump from one activity to another.

Preferences

Preferences are user-specific settings for an application. Preferences usually consist of some configuration data as well as a user interface to manipulate that data.

From user interface point of view preferences can be simple text values, checkboxes, selections from a pull-down menu, or similar. From data point of view, preferences is a collection of name-value pairs, also known as key-value or attribute-value pairs. The values are basic data types, such as integers, booleans, strings, and similar.

Our micro-blogging applications needs to connect to specific server in the cloud using specific user account information. For that, Yamba needs to know username and password for that account as well as the URL of the server it’s connecting to. This URL is also knowns as API root. So, in our case, we’ll have three fields where user can enter and edit username, password and API root. This data will be stored as strings.

To enable our app to handle user-specific preferences, we’d have to build a screen to enter the information, a Java code to validate and process that information, and some kind of storage mechanism to store this information.

While all this sounds like a lot of work, Android provides a framework to help streamline working with user preferences. First, we’ll define what our preference data looks like in a Preference resource file.

The steps to creating preferences for our application will be to:

  1. Create Preference resource file prefs.xml.
  2. Implement PrefsActivity.java file that inflates that resource file.
  3. Register this new activity with the AndroidManifest.xml file.
  4. Provide a way to start that activity from the rest of the application.

Prefs Resource

We are going to start by creating the prefs.xml - a resource file that outlines what our preference screen will look like. The easiest way to create it would be to use New Android XML File tool in Eclipse. To start the New Android XML File dialog, go to File→New→Android XML File, or click on the little a+ icon in the top menu bar of Eclipse:

Figure 7.1. New Android XML File

New Android XML File

The key is to give the new file the name, in this case prefs.xml and to choose Preference for the type of resource. The tool should automatically suggest that this new file should be created in /res/xml folder and that the root element for the XML file should be PreferenceScreen. Just like discussed before in the section called “Alternative Resources”, we could create alternative versions of this same resource by applying various qualifiers such as screen size and orientation, language and region, etc.

Note

We’re using Eclipse tools where applicable to get the job done quicker. If you were to use another tool, you’d have to create this file manually and put it in the right folder.

Once you click on Finish, Eclipse will create a new file for you and open it up. Eclipse typically opens the XML files it knows about in its developer-friendly view.

In this view, you can create the username preference entry by selecting PreferenceScreen on the left, and then choosing Add→EditTextPreference On the right hand side, expand Attributes from Preferences section. Eclipse will offer you number of attributes to set for this EditTextPreference.

Not all attributes are equally important. Typically, you will care about the following:

Key
A unique identifier for each preference item. This is how we’ll look up particular preference later.
Title
The name of this preference that user will see. It should be a short name that fits on a single line of the preference screen.
Summary
A short description of this preference item. This is optional but highly recommended.

For username preference, we’ll put username for key. We will define Title and Summary in strings.xml as this is the best practice.

Instead of modifying strings.xml file directly, you can use an Eclipse shortcut. Here’s how it goes:

  1. Click on Browse and select New String…. This will open a dialog to create a new string resource.
  2. Enter titleUsername for R.string. value and Username for String value.
  3. Click Ok and this will insert a new string resource in strings.xml resource.
  4. You can now pick that value from the list of resources.

The above describes how to add Username preference item. You can now repeat the same steps for Password and API Root items.

To switch to the actual XML code by clicking on the tab on the bottom of this window:

Figure 7.2. Prefs.xml in Developer-friendly view

Prefs.xml in Developer-friendly view

The raw XML for the preference resource looks like this:

Example 7.1. res/xml/prefs.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

  <EditTextPreference android:title="@string/titleUsername"
    android:summary="@string/summaryUsername" android:key="username"></EditTextPreference>

  <EditTextPreference android:title="@string/titlePassword"
    android:password="true" android:summary="@string/summaryPassword"
    android:key="password"></EditTextPreference>

  <EditTextPreference android:title="@string/titleApiRoot"
    android:summary="@string/summaryApiRoot" android:key="apiRoot"></EditTextPreference>

</PreferenceScreen>

<PreferenceScreen> is the root element that defines our main preference screen. It has three children, all <EditTextPreference>. This is simply a piece of editable text. Other common elements here could be <CheckBoxPreference>, <ListPreference>, and so on.

The main property of any of these elements is the key. The key is how we’ll look up these values later on. Remember, preferences is just a set of name-value pairs at the end of the day.

Like we said couple of times earlier, while Eclipse does provide a developer-friendly tools to manage XML files, you often run into certain limitations with with Eclipse. For example, we would like to hide the actual text that the user types in the password field as it’s commonly done with passwords. Android does provide support for that but Eclipse tools haven’t integrated it in there yet. Since we can always edit the XML directly, in this case we to that to add android:password="true" property to our password property. This will cause the password to be masked while user is typing it in.

PrefsActivity

Now that we have the preferences defined in their own XML resource file, we can create the activity to display these preferences. You may recall from <<Activities> that every screen in an Android app is an activity. So, to display the screen where user enters username and password for their online account, we’ll create an activity to handle that screen. This activity will be a special preference-aware activity.

To create an activity, we create a new Java class. To do so, in Eclipse, select your package under your src folder, right-click on the package and select New→Class. A New Java Class window will pop up. You just need to enter PrefsActivity for the Name and click Finish. This will create PrefsActivity.java file under your package in your source folder.

Our PrefsActivity class going to be a very simple Java file. This is because we inherit from PreferenceActivity, an Android framework provided class that knows how to handle preferences.

Example 7.2. PrefsActivity.java

package com.marakana.yamba2;

import android.os.Bundle;
import android.preference.PreferenceActivity;

public class PrefsActivity extends PreferenceActivity { // 1

  @Override
  protected void onCreate(Bundle savedInstanceState) { // 2
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.prefs); // 3
  }

}

1

Unlike regular activities, PrefsActivity will subclass (i.e. extend) PreferenceActivity class.

2

Just like any other activity, we override onCreate() method to initialize the activity.

3

Unlike regular activities that usually call setContentView(), preference activity will set its content from the prefs.xml file via a call to addPreferencesFromResource().

Tip

If you didn’t want to type the long signature of onCreate() and other methods that we often have to implement or override, you could use an Eclipse tool to help you with that. While in your PrefsActivity.java and after you have added ... extends PreferenceActivity..., you can choose Source→Override/Implement Methods…. This will bring up a dialog box with appropriate selection of methods you could override or implement given that you are subclassing PreferenceActivity class. In here, you can choose onCreate() and Eclipse will insert the stub for this method into your code.

Update Manifest File

Whenever we create one of these main building blocks (Activities, Services, Broadcast Receivers, Content Providers) we need to define them in AndroidManifest.xml file. In this case, we have a new PrefsActivity and we must add it to the manifest file.

Just like with any Android XML file, opening AndroidManifest.xml in Eclipse will typically bring up the developer-friendly view of that file. In this file, you could choose Application tab, then under Application Nodes choose Add→Activity and for its Name type .PrefsActivity.

However, we can also do this straight from the raw XML by clicking on AndroidManifest.xml tab on the bottom of this window. I find that while Eclipse is useful when it comes to creating XML files, often editing raw XML is faster and gives you much more control.

Tip

When editing code in Eclipse, you can use Ctrl+Space key shortcut to invoke type-ahead feature of Eclipse. This is every useful both for XML and Java code and is context-sensitive, meaning Eclipse is smart enough to know what could possibly be entered at that point in code. Using Ctrl+Space makes your life as programmer much easier as you don’t have to remember long method names and tags, plus it helps avoid typos.

So after adding our manifest file now looks like this:

Example 7.3. AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  android:versionCode="1" android:versionName="1.0" package="com.marakana.yamba2">
  <application android:icon="@drawable/icon" android:label="@string/app_name">

    <activity android:name=".StatusActivity" android:label="@string/titleStatus">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>

    <activity android:name=".PrefsActivity" android:label="@string/titlePrefs" /> <!-- 1 -->

  </application>
  <uses-sdk android:minSdkVersion="4" />

  <uses-permission android:name="android.permission.INTERNET" />
</manifest>

1

Defines the new PrefsActivity.

We now have a new preference activity, but no good way of getting to it yet. We need a way to launch this new activity. For that, we use options menu.

Options Menu

Options menu is an Android user interface component that provides standardized menus to applications. The menus appear at the bottom of the screen when the user presses Menu button on the device.

To add support for options menu to an application, we need to do the following:

  1. Create menu.xml resource where we specify what the menu consists of.
  2. Add onCreateOptionsMenu() to the activity that we want to provide this menu. This is where we inflate the menu.xml resource.
  3. Provide handling of menu events in onOptionsItemSelected().

We start by defining the menus in an XML resource for the options menu. Just like with other Android XML files, we can use the little a+ icon in the Eclipse toolbar or choose File→New…→Android XML to launch New Android XML File dialog. In this dialog, for File enter menu.xml and for Type select Menu. Click Finish button and Eclipse will create a new folder /res/menu with menu.xml file in it. It will also open this file in developer-friendly view.

In this view, you can click on Add→Item. This will add a new menu item to your menu. In the Attributes section on the right, you can see over a dozen various attributes that we can set for this menu item. Just like before, not all attributes are equally important.

Id
The unique identifier of this resource. Just as when we designed the layout in Chapter 6, Android User Interface, this identifier is typically of form @+id/someId where someId is the name that you give it. This name should contain only letters, numbers and underscore.
Title
The tile of this menu as it will appear when displayed. Keep in mind that space on the screen is typically limited so keep the title short. Alternatively, you can provide Title condensed attribute for shorter version of the title that will be shown instead of Title if space is limited. Just like before, best practice is to define the actual text value of the title in strings.xml resource and just reference it here.
Icon
The icon that shows along with the menu item’s title. While is is not required, it is a very useful visual cue from usability point of view. However, in this case it illustrates how to point to Android system resources.

The next section describes these resources in more detail.

Android System Resources

Just like your application can have its resources so can Android system as well. Like most other operating systems, Android comes with some preloaded images, graphics, sound clips, and other types of resources. Recall that our app resources are in /res/. To refer to Android system resources prefix them with with android: keyword in XML, for example @android:drawable/ic_menu_preferences. If you are referring to an Android system resource from Java, then you use android.R instead the usual R reference.

Tip

The actual resource files are in your SDK, inside specific platform folder. For example, if you are using Android 9 (Gingerbread), the location of the resource folder would be android-sdk/platforms/android-9/data/res/.

Figure 7.3. Menu.xml in Developer-friendly view

Menu.xml in Developer-friendly view

The raw XML of menu.xml is shown here:

Example 7.4. res/menu/menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:id="@+id/itemPrefs" android:title="@string/titlePrefs"
    android:icon="@android:drawable/ic_menu_preferences"></item>
</menu>

As you can see, there’s just one <item> element within our <menu> element making this a single menu item menu.

Update StatusActivity to Load Menu

Recall that the options menu is loaded by your activity when user clicks on the Menu button on the device. First time menu button is pressed, system will call activity’s onCreateOptionsMenu() method to inflate the menu from the menu.xml resource. This process is similar to inflating user interface from layout resources that we discussed in the section called “StatusActivity Java Class”. Basically, the inflater reads the XML code and for every element, it creates a corresponding Java object and for each attribute in XML is sets that object’s properties accordingly.

From that point on, the menu is in memory and onCreateOptionsMenu() doesn’t get called again until the activity is destroyed. Each time user selects a menu item though, onOptionsItemSelected() gets called to process that click. We’ll talk about this in the next section.

We need to update the StatusActivity to load up the options menu. To do that, add onCreateOptionsMenu() method to StatusActivity. This method gets called only first time when user clicks on the menu button.

// Called first time user clicks on the menu button
@Override
public boolean onCreateOptionsMenu(Menu menu) {
  MenuInflater inflater = getMenuInflater();   // 1
  inflater.inflate(R.menu.menu, menu);         // 2
  return true; // 3
}

1

We get the MenuInflater object from the context.

2

Use the inflater to inflate the menu from the XML resource.

3

We must return true for this menu to be displayed.

Update StatusActivity to Handle Menu Events

We also need a way to handle various clicks on the menu items. To do that, we add another callback method, onOptionsItemSelected(). This method is called every time user clicks on a menu item.

// Called when an options item is clicked
@Override
public boolean onOptionsItemSelected(MenuItem item) {
  switch (item.getItemId()) {                              // 1
  case R.id.itemPrefs:
    startActivity(new Intent(this, PrefsActivity.class));  // 2
  break;
  }

  return true;  // 3
}

1

Since the same method is called regardless which item user clicked on, we need to figure out the id of that item and based on that switch to a specific case to handle each item. At this point, we only have one menu item, but that might change in the future. Switching on item ID is a very scalable approach and will adapt nicely as our application grows in complexity.

2

startActivity() method in context allows us to launch a new activity. In this case, we are creating a new intent specifying to start PrefsActivity class.

3

Return true to consume the event here.

Tip

Just like before, you could use Eclipse shortcut Source→Override/Implement Methods to add both onCreateOptionsMenu() and onOptionsItemSelected().

Strings Resource

Our updated strings.xml now looks like this:

Example 7.5. res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="app_name">Yamba 2</string>
  <string name="titleYamba">Yamba 2</string>

  <string name="hintText">Please enter your 140-character status</string>
  <string name="buttonUpdate">Update</string>

  <string name="titleStatus">Status Update</string>
  <string name="titlePrefs">Prefs</string>
  <string name="titleUsername">Username</string>
  <string name="titlePassword">Password</string>
  <string name="titleApiRoot">API Root</string>

  <string name="summaryUsername">Please enter your username</string>
  <string name="summaryPassword">Please enter your password</string>
  <string name="summaryApiRoot">URL of Root API for your service</string>
</resources>

You should be able to run your application at this point and and see the new PrefsActivity by clicking on Menu→Prefs in StatusActivity. Try changing your username and password, then reboot your phone, restart the app, and verify that the information is still there.

Figure 7.4. PrefsActivity

PrefsActivity

Shared Preferences

Now that we have Preference Activity, and a way to save our username, password and the API root, it is time to make use of it. To programmatically access your preferences, we’ll use SharedPreference class provided by the Android framework.

The fact that this class is called SharedPreference refers to the fact that this preference is easily accessible from anywhere in this application. So, any component of an Android application, such as Activities, Services, Broadcast Receivers, and Content Providers.

In StatusActivity, add definition for prefs object globally to the class:

 SharedPreferences prefs;

Now, to get the preference object, add the following to onCreate():

@Override
        public void onCreate(Bundle savedInstanceState) {
                ...
                // Setup preferences
                prefs = PreferenceManager.getDefaultSharedPreferences(this); // 1
                prefs.registerOnSharedPreferenceChangeListener(this);   // 2
        }

1

Each application has its own shared preferences that all components of this application context share. To get the instance of this SharedPreferences, we use PreferenceManager.getDefaultSharedPreferences() and pass it this as the current context for this app. The name "shared" could be confusing - it means that this preference object contains data that is shared by various parts of this application only. It doesn’t mean any of this data is shared with any other application.

2

Preferences can and do change by the user. So we need a mechanism to notify this activity that old values are stale. To do that, we register this, meaning our StatusActivity with our shared preferences. For this to work, we’ll need to add ...implements OnSharedPreferenceChangeListener to our class definition as well as implement the required onSharedPreferenceChanged() method. This method will be explained in a bit.

Now that we have username, password and API root coming from user-defined preferences, we can refactor our twitter code so it no longer hard-codes them. To do that, we add a private method to StatusActivity that is responsible for returning valid twitter object. This method lazily initializes twitter meaning if twitter exists it returns it as-is, otherwise creates it.

private Twitter getTwitter() {
        if (twitter == null) {  // 1
                String username, password, apiRoot;
                username = prefs.getString("username", "");     // 2
                password = prefs.getString("password", "");
    apiRoot = prefs.getString("apiRoot", "http://yamba.marakana.com/api");

                // Connect to twitter.com
                twitter = new Twitter(username, password);      // 3
                twitter.setAPIRootUrl(apiRoot); // 4
        }
        return twitter;
}

1

Only if twitter is null, i.e. undefined, we create it.

2

Get the username and password from the shared preference object. The first parameter in getString() is the key we assigned to each preference item, such as username and password. The second argument is the default value in case such preference is not found. Keep in mind that first time user runs your application, the preference file doesn’t exist so defaults will be used. So, if user hasn’t went to PrefsActivity to setup her preferences, this code will attempt to login with empty username and password, and thus fail. The failure however is going to happen when try try to do the actual status update because that’s how jtwitter library is designed.

3

We login to twitter service with user-defined preferences.

4

Remember that we need to update the actual service that we using by updating the API root URL for that service.

Now, we don’t use twitter object directly any more, but call getTwitter() to get it instead. So, onClick() becomes like this:

public void onClick(View v) {

        // Update twitter status
        try {
                getTwitter().setStatus(editText.getText().toString());
        } catch (TwitterException e) {
                Log.d(TAG, "Twitter setStatus failed: " + e);
        }
}

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.

Now, as we mentioned before when updating onCreate() and registering for preference updates, we need to handle what happens when user changes username or password. By registering prefs.registerOnSharedPreferenceChangeListener(this) in onCreate() and implementing OnSharedPreferenceChangeListener, we got a callback method onSharedPreferenceChanged() that system will invoke whenever preferences change. In this method, we simply invalidate the twitter object so next time it is needed, getTwitter() will recreate it.

public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
        // invalidate twitter object
        twitter = null;
}

File System, Explained

So, where are these preferences stored on the device? How secure is my username and password? To answer that, we need to look at how Android filesystem is organized.

Exploring File System

There are two ways for you to access the file system on an Android device. One way is using Eclipse, the other command line.

In Eclipse, we use File Explorer view to access the file system. To open up the File Explorer view, go to Window→Show View→Other…→Android→File Explorer. You can also access File Explorer view via DDMS Perspective. Select DDMS Perspective in the top-right corner of your Eclipse or go to Window→Open Perspective→Other…→DDMS. If you have multiple devices connected to your workstation, make sure you select which one you are working with in the Devices view. You should now be able to navigate through the file system of the device.

If you prefer the command line, you can always use adb shell to get to the shell of the device. From there you can explore the file system like you would on any other Unix platform.

File System Partitions

There are three main parts of the file system on every Android device. They are:

  • System partition at /system/
  • SDCard at /sdcard/
  • User Data partition at /data/

Figure 7.5. File System as seen via File Explorer in Eclipse

File System as seen via File Explorer in Eclipse

System Partition

System partition is where your entire Android operating system is. This is the main partition containing all your preinstalled applications, system libraries, Android framework, linux command line tools, and so on.

System partition is mounted read-only, meaning you as developer have very little influence over it. As such, this partition is of limited interest to us.

The system partition in the Emulator corresponds to system.img file in your platform images directory, located in android-sdk/platforms/android-8/images/ folder.

SDCard Partition

SDCard partition is a free-for-all mass storage. Your app can read files from this partition as well as write files to it if it holds WRITE_TO_EXTERNAL_STORAGE permission. This is a great place to store large files, such as music, photos, videos and similar.

Note that since FroYo version of Android, /sdcard mount point appears in Eclipse File Explorer under /mnt/sdcard location. This is because of the new feature in FroYo to allow for storing and running applications on the SDCard as well.

As an app developer, SDCard partition is very useful and important to you. At the same time, this partition is not very structured.

This partition typically corresponds to sdcard.img in your Android Virtual Device (AVD) directory. This directory is in you ~/.android/avd/ folder and will have a subdirectory for each specific virtual device. On the physical device, it is an actual SD card.

User Data Partition

As user and app developer, the most important partition is the User Data partition. This is where all your user data is stored, all the downloaded apps are located, and most importantly, all apps' data is. This includes both preinstalled apps as well as user-downloaded apps.

So, while user apps are stored in /data/app/ folder, the most important folder to us as app developer is /data/data/ folder. More specifically, within this folder there’s a subfolder corresponding to each app. This folder is identified by the Java package that this app used to sign itself. Again, this is why Java packages are important to Android security.

Android framework provides number of handy methods as part of context that help you access user data file system from within your application. Take a look at getFilesDir() for example.

This partition typically corresponds to user-data.img in your Android Virtual Device (AVD) directory. As before, this directory is in your ~/.android/avd/ folder and will have a subdirectory for each specific virtual device.

When you create a new app, you assign your Java code to a specific package. Typically, this package follows the Java convention of reverse domain name plus app name. For example, Yamba app is in com.marakana.yamba package. So, once installed, Android creates a special folder just for this app under /data/data/com.marakana.yamba/. This folder is the cornerstone of our private secured file system dedicated to each app.

There will be sub-folders in /data/data/com.marakana.yamba2/, but they are well-defined. For example, the preferences are in /data/data/com.marakana.yamba2/shared_prefs/. As a matter of fact, if you open up DDMS perspective in your Eclipse and select File Explorer, you can navigate to this partition. You will probably see com.marakana.yamba2_preferences.xml file in there. You could pull this file and exam in it, or you could use adb shell.

adb shell is another one of those common adb subcommands to access the shell of your device (either physical or virtual). For instance, you could just open up your command line terminal and type:

[user:~]> adb shell
# cd /data/data/com.marakana.yamba2/shared_prefs
# cat com.marakana.yamba2_preferences.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="password">password</string>
<string name="apiRoot">http://yamba.marakana.com/api</string>
<string name="username">student</string>
</map>
#

This XML file represents the storage for all our preference data for this application. As you can see, our username, password and API root are all stored in there.

File System Security

So, how secure is this? This is a common question by security folks. Username and password stored in clear text always raises eyebrows.

To answer this question, I usually compare it to finding someone’s laptop on the street. While indeed we can easily gain access to the "hard-drive" via adb tool, that doesn’t mean we have a way of reading its data. Each folder under /data/data/ is going to belong to a separate user account. This user account is managed by Linux. Unless our app is that app, it won’t have access to that folder. So, short of us reading byte-by-byte on the physical device, even clear-text data is secure.

On the Emulator, we have root permissions meaning we can explore entire file system. This is useful for development purposes.

Summary

At this point, the user can specify the username and password for the micro-blogging site. This makes the app usable to way more people than the the version that had this information previously hard-coded.

Figure 7.6, “Yamba Completion” illustrates what we have done so far as part of the design outlined in Figure 5.4, “Yamba Design Diagram”:

Figure 7.6. Yamba Completion

Yamba Completion

Site last updated on: April 8, 2011 at 12:51:47 PM PDT
Cover for Learning Android

View 3 comments

  1. Clemens Hladek – Posted Jan. 31, 2011

    If correct, add: They are stored in a file called ...

  2. Clemens Hladek – Posted Jan. 31, 2011

    Do you mean:

    in this case we DO THAT BY ADDING ... - ???

  3. Clemens Hladek – Posted Jan. 31, 2011

    Sorry (again) - the web browser on my Pocketbook IQ set my second comment next to a totally wrong paragraph...

Add a comment

View 1 comment

  1. schrickl – Posted Sept. 19, 2010

    When I click on the a+ icon, I get a window to create a new project.

Add a comment

View 3 comments

  1. fmaker – Posted Sept. 21, 2010

    Note that you can select the configuration you want this to be valid for (i.e screen size, language, region, etc.) in this screen as well.

  2. Anna Teittinen – Posted Jan. 3, 2011

    Just a small typo:

    ...and to choose Preferences for the type of resource.

    SHOULD BE:

    ...and to choose Preference for the type of resource.

  3. Francisco Correa – Posted May 17, 2011

    When you say, "The key is to" does it means that a preference file should be named prefs.xml and not anything else? if so please emphasize. Also using the word "key" in this context may be confusing with the "key" of each element in the following paragraphs. You can say something like "It is crucial to name the file ..."

Add a comment

View 1 comment

  1. schrickl – Posted Sept. 19, 2010

    Remove select from the first line.

Add a comment

View 1 comment

  1. Francisco Correa – Posted May 17, 2011

    The figure title capitalizes the P on prefs.xml

Add a comment

View 2 comments

  1. Anna Teittinen – Posted Jan. 3, 2011

    'password' is not part of the attributes listed in the EditTextPreference screen.

    When I put a value of 'true' into the 'Default value' textfield, the element below shows in the pref.xml file:

    android:defaultValue="true"

    not the one mentioned in the section below:

    android:password="true"

  2. Frank Maker – Posted Jan. 3, 2011

    Could remove the empty end tags ex: . Even though the tool creates them, just for clarity.

Add a comment

View 1 comment

  1. Stuart Jackson – Posted Nov. 23, 2010

    It has three children, not two.

Add a comment

View 3 comments

  1. schrickl – Posted Sept. 19, 2010

    In step 1 below, PrefsActivity should extends PreferenceActivity class

  2. Clemens Hladek – Posted Jan. 31, 2011

    Below:

    Is PrefsActivity un-regular BECAUSE it subclasses?

    Could we also override - and what-s the advantage here?

  3. Francisco Correa – Posted May 17, 2011

    the sample code has yamba2 (remove the "2").

    On step 1, I would elaborate: "Unlike regular activities that extend Activity ..."

Add a comment

View 1 comment

  1. fmaker – Posted Sept. 21, 2010

    Great way to explain this!!!

Add a comment

View 3 comments

  1. Anna Teittinen – Posted Jan. 3, 2011

    Do not see the Application tab when the developer-friendly view is opened.

  2. Francisco Correa – Posted May 17, 2011

    @string/titlePrefs is not mentioned in the instructions

  3. redcurry – Posted June 5, 2011

    You should explain why there is a dot before PrefsActivity.

Add a comment

View 2 comments

  1. fmaker – Posted Sept. 21, 2010

    Especially using Ctrl+SPACE completion in eclipse

  2. Frank Maker – Posted Jan. 3, 2011

    s/row/raw/

Add a comment

View 1 comment

  1. herve – Posted Sept. 11, 2010

    The UpdaterService is not introduced until next chapter so menu.xml at that stage should probably only contain the itemPrefs menu item.

Add a comment

View 1 comment

  1. fmaker – Posted Sept. 21, 2010

    Also keep in mind that ideally the view should flow nicely in either a different shape or size screen.

Add a comment

View 2 comments

  1. andyo – Posted Oct. 10, 2010

    And what preferences are controlled by that resource?

  2. Clemens Hladek – Posted Jan. 31, 2011

    "... so CAN Android as well." or is it:

    "... so DOES Android ..." - ?

Add a comment

View 1 comment

  1. schrickl – Posted Sept. 19, 2010

    For all code snippets in general, you might want to explain what the first two lines mean and that it should never change.

Add a comment

View 1 comment

  1. andyo – Posted Oct. 10, 2010

    The menu is IN memory (although that raises the question of how it gets reloaded if it is unloaded)

Add a comment

View 1 comment

  1. Benhamish Allen – Posted June 4, 2011

    using Menuinflater and Intent requires some new import statements in StatusActivity.java.

    The SDK knows this but it could perhaps be explained in your text.

Add a comment

View 2 comments

  1. herve – Posted Sept. 11, 2010

    The UpdaterService is not introduced until next chapter. The UpdaterService class does not exist yet.

  2. fmaker – Posted Sept. 21, 2010

    Mention that using the id is a very scalable approach and will adapt nicely as your application grows in complexity.

Add a comment

View 1 comment

  1. Nigel Gilbert – Posted Feb. 10, 2011

    There should be an API Root field shown in this screen capture too.

Add a comment

View 1 comment

  1. andyo – Posted Oct. 10, 2010

    Since you introduce the idea that preferences are "shared" here in the first paragraph, say what it means here (that all components of the application instance share the preferences).

Add a comment

View 2 comments

  1. Francisco Correa – Posted May 17, 2011

    "The reason for this class to be named ..." so you don't use "fact" twice.

  2. Francisco Correa – Posted May 17, 2011

    "So, any component... " what ? So, -> Something

Add a comment

View 2 comments

  1. Clemens Hladek – Posted Jan. 31, 2011

    Item 2:

    Preferences can BE and do GET changED by the user.

  2. jowett zhang – Posted April 29, 2011

    For the parameter of function getDefaultSharedPreferences(), why use "this" as the global context, is there any other exact one for it? "this" is in fact the reference of this activity class.

Add a comment

View 5 comments

  1. Stuart Jackson – Posted Nov. 23, 2010

    With this change to onClick the PostToTwitter AsynTask is no longer called. Doesn't this break the app?

  2. Marilyn Escue – Posted Nov. 28, 2010

    For bullet point 2 above, does this mean that during the first time through, the user's name and password won't be set and just empty strings will be passed to twitter? If no, then please explain what will happen here. If yes, you might want to state this here.

  3. Francisco Correa – Posted May 17, 2011

    Duplicated word "try try", guess it should be "you try"

  4. redcurry – Posted June 5, 2011

    You should explain why you're calling setStatus() vs. updateStatus(), which you had before. Following up on Stuart's comment, you should say something about AsyncTask to be used later, so don't delete it.

  5. Kimberley Coburn – Posted July 18, 2011

    Yes, the refactoring as presented didn't make sense to me, either. In my code, I modified PostToTwitter.doInBackground(), instead. i.e. Twitter.Status status = getTwitter().updateStatus(statuses[0]);

Add a comment

View 1 comment

  1. fmaker – Posted Sept. 21, 2010

    What about making the username/password fields hidden in the view?

Add a comment

View 2 comments

  1. schrickl – Posted Sept. 19, 2010

    very == every

  2. fmaker – Posted Sept. 21, 2010

    /sdcard isn't really a partition since it's not on the same flash as /system and /data

Add a comment

View 1 comment

  1. Nigel Gilbert – Posted Feb. 14, 2011

    A fairly minor point, but it might be better to say "...containing all of the preinstalled applications..."

    I read the "your" as possibly including my application I had installed on the device.

Add a comment

View 1 comment

  1. schrickl – Posted Sept. 19, 2010

    You === Your

Add a comment

View 2 comments

  1. schrickl – Posted Sept. 19, 2010

    (ADV) == (AVD)

  2. Nigel Gilbert – Posted Feb. 14, 2011

    "This directory is in your..."

Add a comment

View 3 comments

  1. fmaker – Posted Sept. 21, 2010

    It would be nice to mention the java method to get the string representing this directory.

  2. Frank Maker – Posted Jan. 3, 2011

    subfolder corresponding to each app which operates as individual sandboxes.

  3. Anna Teittinen – Posted Jan. 4, 2011

    In my /data/data/ folder, I see only the following subfolders:

    and con con con con (basically, lots of con subfolders) jp.c

    In my /data/app/ folder, I see lots of 'con' subfolders where the 'Info' column shows the android packages I created.

Add a comment

View 1 comment

  1. schrickl – Posted Sept. 19, 2010

    (ADV) == (AVD)

    "As before, this directory is in 'your' ~/.android/avd..."

Add a comment

View 1 comment

  1. rpfene – Posted Nov. 16, 2010

    The XML file is actually under another sub-directory. Change your cat command to the following:

    cat /data/data/com.marakana.yamba/shared_prefs/com.marakana.yamba_preferences.xml

Add a comment

View 1 comment

  1. schrickl – Posted Sept. 19, 2010

    Remove the second "a" in the second sentence.

Add a comment

View 1 comment

  1. fmaker – Posted Sept. 21, 2010

    But you're one sys bug from losing your login info, so don't do it!!!

Add a comment

View 1 comment

  1. Clemens Hladek – Posted Jan. 31, 2011

    In a German IT journal (c't) there was the strict advice that you should allow USB debugging onls when needer as your phone is vulnerable at these times.

    Anybody with root permissions can just READ password in plain text!???

Add a comment

View 1 comment

  1. herve – Posted Sept. 11, 2010

    The screenshot below does not match the "spiced-up" screenshot immediately above.

    "You can also start and stop the service at this point. The service will run although it currently still doesn’t connect to Twitter." - The UpdaterService class is not defined yet.

Add a comment

View 1 comment

  1. Francisco Correa – Posted May 17, 2011

    I found 6 occurrences of word "typically" in this page.

Add a comment

View 1 comment

  1. Frank Maker – Posted Jan. 3, 2011

    Password need to be hidden as well.

Add a comment

View 2 comments

  1. Clemens Hladek – Posted Jan. 31, 2011

    Do you mean:

    in this case we DO THAT BY ADDING ... - ???

  2. Francisco Correa – Posted May 17, 2011

    Duplicated word "with with Eclipse". If you just end the sentence after "limitations." it will be clear enough while avoiding repeating word "Eclipse" in the same sentence.

    Edited on May 17, 2011, 6:45 a.m. PDT

Add a comment

View 1 comment

  1. Frank Maker – Posted Jan. 3, 2011

    is in memory

Add a comment

View 1 comment

  1. Frank Maker – Posted Jan. 3, 2011

    Picture of the DDMS icon would be helpful.

Add a comment