Adding sample on activity instrumentation testing

Currently doesn't use Gradle, since support for tests in Gradle is
not yet implemented. We'll need to update the build system for this
project once that work has been completed.

Change-Id: Iaab38d7fba265ad4745760a650747342aa9c38d3
diff --git a/testing/ActivityInstrumentationSample/AndroidManifest.xml b/testing/ActivityInstrumentationSample/AndroidManifest.xml
new file mode 100644
index 0000000..783fc0c
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2013 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!--
+     This manifest describes the application which we'll be testing. The actual instrumentation
+     tests are build a second APK, loaded alongside this one on the device.
+
+     See also: //tests/AndroidManifest.xml
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.example.android.activityinstrumentation"
+          android:versionCode="1"
+          android:versionName="1.0">
+
+    <uses-sdk android:minSdkVersion="7"/>
+
+    <!-- This is just a standard activity. -->
+    <application
+            android:label="@string/app_name"
+            android:icon="@drawable/ic_launcher"
+            android:theme="@style/AppTheme">
+        <activity
+                android:name="MainActivity"
+                android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/testing/ActivityInstrumentationSample/proguard-project.txt b/testing/ActivityInstrumentationSample/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/testing/ActivityInstrumentationSample/res/drawable-hdpi/ic_launcher.png b/testing/ActivityInstrumentationSample/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/testing/ActivityInstrumentationSample/res/drawable-ldpi/ic_launcher.png b/testing/ActivityInstrumentationSample/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..9923872
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/testing/ActivityInstrumentationSample/res/drawable-mdpi/ic_launcher.png b/testing/ActivityInstrumentationSample/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/testing/ActivityInstrumentationSample/res/drawable-xhdpi/ic_launcher.png b/testing/ActivityInstrumentationSample/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/testing/ActivityInstrumentationSample/res/layout/activity_main.xml b/testing/ActivityInstrumentationSample/res/layout/activity_main.xml
new file mode 100644
index 0000000..2b7a4d1
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/res/layout/activity_main.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2013 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                xmlns:tools="http://schemas.android.com/tools"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:paddingLeft="@dimen/activity_horizontal_margin"
+                android:paddingRight="@dimen/activity_horizontal_margin"
+                android:paddingTop="@dimen/activity_vertical_margin"
+                android:paddingBottom="@dimen/activity_vertical_margin"
+                tools:context=".MainActivity">
+
+    <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/instructions"
+            android:id="@+id/instructions"/>
+
+    <Spinner
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/spinner"
+            android:layout_below="@+id/instructions"
+            android:layout_centerHorizontal="true"/>
+
+</RelativeLayout>
diff --git a/testing/ActivityInstrumentationSample/res/values-sw720dp-land/dimens.xml b/testing/ActivityInstrumentationSample/res/values-sw720dp-land/dimens.xml
new file mode 100644
index 0000000..0dfce6a
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/res/values-sw720dp-land/dimens.xml
@@ -0,0 +1,21 @@
+<!--
+  ~ Copyright 2013 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources>
+    <!-- Customize dimensions originally defined in res/values/dimens.xml (such as
+         screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here. -->
+    <dimen name="activity_horizontal_margin">128dp</dimen>
+</resources>
diff --git a/testing/ActivityInstrumentationSample/res/values-v11/styles.xml b/testing/ActivityInstrumentationSample/res/values-v11/styles.xml
new file mode 100644
index 0000000..1b39428
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/res/values-v11/styles.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2013 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>
diff --git a/testing/ActivityInstrumentationSample/res/values-v14/styles.xml b/testing/ActivityInstrumentationSample/res/values-v14/styles.xml
new file mode 100644
index 0000000..219b706
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/res/values-v14/styles.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2013 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
diff --git a/testing/ActivityInstrumentationSample/res/values/dimens.xml b/testing/ActivityInstrumentationSample/res/values/dimens.xml
new file mode 100644
index 0000000..4afc9dd
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/res/values/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2013 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources>
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/testing/ActivityInstrumentationSample/res/values/strings.xml b/testing/ActivityInstrumentationSample/res/values/strings.xml
new file mode 100644
index 0000000..8bf4747
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2013 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources>
+    <string name="app_name">Activity Instrumentation Sample</string>
+    <string name="instructions">The value of the spinner below should be persisted when this activity is destroyed.</string>
+</resources>
diff --git a/testing/ActivityInstrumentationSample/res/values/styles.xml b/testing/ActivityInstrumentationSample/res/values/styles.xml
new file mode 100644
index 0000000..bdd3ba5
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/res/values/styles.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2013 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
diff --git a/testing/ActivityInstrumentationSample/src/com/example/android/activityinstrumentation/MainActivity.java b/testing/ActivityInstrumentationSample/src/com/example/android/activityinstrumentation/MainActivity.java
new file mode 100644
index 0000000..39a7e37
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/src/com/example/android/activityinstrumentation/MainActivity.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.activityinstrumentation;
+
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.app.Activity;
+import android.preference.PreferenceManager;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Spinner;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Basic activity with a spinner. The spinner should persist its position to disk every time a
+ * new selection is made.
+ */
+public class MainActivity extends Activity {
+
+    /** Shared preferences key: Holds spinner position. Must not be negative. */
+    private static final String PREF_SPINNER_POS = "spinner_pos";
+    /** Magic constant to indicate that no value is stored for PREF_SPINNER_POS. */
+    private static final int PREF_SPINNER_VALUE_ISNULL = -1;
+    /** Values for display in spinner. */
+    private static final String[] SPINNER_VALUES = new String[] {
+            "Select Weather...", "Sunny", "Partly Cloudy", "Cloudy", "Rain", "Snow", "Hurricane"};
+
+    // Constants representing each of the options in SPINNER_VALUES. Declared package-private
+    // so that they can be accessed from our test suite.
+    static final int WEATHER_NOSELECTION = 0;
+    static final int WEATHER_SUNNY = 1;
+    static final int WEATHER_PARTLY_CLOUDY = 2;
+    static final int WEATHER_CLOUDY = 3;
+    static final int WEATHER_RAIN = 4;
+    static final int WEATHER_SNOW = 5;
+    static final int WEATHER_HURRICANE = 6;
+
+    /** Handle to default shared preferences for this activity. */
+    private SharedPreferences mPrefs;
+    /** Handle to the spinner in this Activity's layout. */
+    private Spinner mSpinner;
+
+    /**
+     * Setup activity state.
+     *
+     * @param savedInstanceState
+     */
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Inflate UI from res/layout/activity_main.xml
+        setContentView(R.layout.activity_main);
+
+        // Get handle to default shared preferences for this activity
+        mPrefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
+
+        // Populate spinner with sample values from an array
+        mSpinner = (Spinner) findViewById(R.id.spinner);
+        mSpinner.setAdapter(
+                new ArrayAdapter<String>(
+                        this,                                                   // Context
+                        android.R.layout.simple_list_item_1,                    // Layout
+                        new ArrayList<String>(Arrays.asList(SPINNER_VALUES))    // Data source
+                ));
+
+        // Read in a sample value, if it's not set.
+        int selection = mPrefs.getInt(PREF_SPINNER_POS, PREF_SPINNER_VALUE_ISNULL);
+        if (selection != PREF_SPINNER_VALUE_ISNULL) {
+            mSpinner.setSelection(selection);
+        }
+
+        // Callback to persist spinner data whenever a new value is selected. This will be the
+        // focus of our sample unit test.
+        mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+
+            // The methods below commit the ID of the currently selected item in the spinner
+            // to disk, using a SharedPreferences file.
+            //
+            // Note: A common mistake here is to forget to call .commit(). Try removing this
+            // statement and running the tests to watch them fail.
+            @Override
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                mPrefs.edit().putInt(PREF_SPINNER_POS, position);
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> parent) {
+                mPrefs.edit().remove(PREF_SPINNER_POS).commit();
+            }
+        });
+    }
+}
diff --git a/testing/ActivityInstrumentationSample/tests/AndroidManifest.xml b/testing/ActivityInstrumentationSample/tests/AndroidManifest.xml
new file mode 100644
index 0000000..1547109
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/tests/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2013 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.example.android.activityinstrumentation.tests"
+          android:versionCode="1"
+          android:versionName="1.0">
+    <!-- We add an application tag here just so that we can indicate that
+         this package needs to link against the android.test library,
+         which is needed when building test cases. -->
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+    <!--
+    This declares that this application uses the instrumentation test runner targeting
+    the package of com.example.android.foohe tests use the command:
+    "adb shell am instrument -w com.example.android.foooid.test.InstrumentationTestRunner"
+    -->
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.example.android.activityinstrumentation"
+                     android:label="Tests for com.example.android.UnitTestSample"/>
+</manifest>
diff --git a/testing/ActivityInstrumentationSample/tests/proguard-project.txt b/testing/ActivityInstrumentationSample/tests/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/tests/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/testing/ActivityInstrumentationSample/tests/src/com/example/android/activityinstrumentation/MainActivityTest.java b/testing/ActivityInstrumentationSample/tests/src/com/example/android/activityinstrumentation/MainActivityTest.java
new file mode 100644
index 0000000..fcffb01
--- /dev/null
+++ b/testing/ActivityInstrumentationSample/tests/src/com/example/android/activityinstrumentation/MainActivityTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.activityinstrumentation;
+
+import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase2;
+import android.widget.Spinner;
+
+/**
+ * This is a simple framework for a test of an Application.  See
+ * {@link android.test.ApplicationTestCase ApplicationTestCase} for more information on
+ * how to write and extend Application tests.
+ *
+ * <p>To run this test, you can type:
+ * adb shell am instrument -w \
+ * -e class com.example.android.activityinstrumentation.MainActivityTest \
+ * com.example.android.activityinstrumentation.tests/android.test.InstrumentationTestRunner
+ *
+ * <p>Individual tests are defined as any method beginning with 'test'.
+ *
+ * <p>ActivityInstrumentationTestCase2 allows these tests to run alongside a running
+ * copy of the application under inspection. Calling getActivity() will return a
+ * handle to this activity (launching it if needed).
+ */
+public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
+
+    public MainActivityTest() {
+        super("com.example.android.activityinstrumentation", MainActivity.class);
+    }
+
+    /**
+     * Test to make sure that spinner values are persisted across activity restarts.
+     *
+     * <p>Launches the main activity, sets a spinner value, closes the activity, then relaunches
+     * that activity. Checks to make sure that the spinner values match what we set them to.
+     */
+    // BEGIN_INCLUDE (test_name)
+    public void testSpinnerValuePersistedBetweenLaunches() {
+    // END_INCLUDE (test_name)
+        final int TEST_SPINNER_POSITION_1 = MainActivity.WEATHER_PARTLY_CLOUDY;
+
+        // BEGIN_INCLUDE (launch_activity)
+        // Launch the activity
+        Activity activity = getActivity();
+        // END_INCLUDE (launch_activity)
+
+        // BEGIN_INCLUDE (write_to_ui)
+        // Set spinner to test position 1
+        final Spinner spinner1 = (Spinner) activity.findViewById(R.id.spinner);
+        activity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // Attempts to manipulate the UI must be performed on a UI thread.
+                // Calling this outside runOnUiThread() will cause an exception.
+                //
+                // You could also use @UiThreadTest, but activity lifecycle methods
+                // cannot be called if this annotation is used.
+                spinner1.requestFocus();
+                spinner1.setSelection(TEST_SPINNER_POSITION_1);
+            }
+        });
+        // END_INCLUDE (write_to_ui)
+
+        // BEGIN_INCLUDE (relaunch_activity)
+        // Close the activity
+        activity.finish();
+        setActivity(null);  // Required to force creation of a new activity
+
+        // Relaunch the activity
+        activity = this.getActivity();
+        // END_INCLUDE (relaunch_activity)
+
+        // BEGIN_INCLUDE (check_results)
+        // Verify that the spinner was saved at position 1
+        final Spinner spinner2 = (Spinner) activity.findViewById(R.id.spinner);
+        int currentPosition = spinner2.getSelectedItemPosition();
+        assertEquals(TEST_SPINNER_POSITION_1, currentPosition);
+        // END_INCLUDE (check_results)
+
+        // Since this is a stateful test, we need to make sure that the activity isn't simply
+        // echoing a previously-stored value that (coincidently) matches position 1
+        final int TEST_SPINNER_POSITION_2 = MainActivity.WEATHER_SNOW;
+
+        // Set spinner to test position 2
+        activity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                spinner2.requestFocus();
+                spinner2.setSelection(TEST_SPINNER_POSITION_2);
+            }
+        });
+
+        // Close the activity
+        activity.finish();
+        setActivity(null);
+
+        // Relaunch the activity
+        activity = this.getActivity();
+
+        // Verify that the spinner was saved at position 2
+        final Spinner spinner3 = (Spinner) activity.findViewById(R.id.spinner);
+        currentPosition = spinner3.getSelectedItemPosition();
+        assertEquals(TEST_SPINNER_POSITION_2, currentPosition);
+    }
+}