├── README.md
├── chap04_interactions
├── ex2_toast.txt
├── ex3_list_view_clicks.txt
└── ex1_click_handlers.txt
├── chap07_advanced_views
├── ex3_timepicker.txt
├── ex1_toast_inputs.txt
├── ex5_gridview.txt
├── ex2_spinner_toast.txt
└── ex4_progressbar.txt
├── chap03_view
├── ex2_basic_views.txt
├── ex1_layout_gravity.txt
├── ex3_view_attributes.txt
└── ex4_simple_list_view.txt
├── chap01_app_fundamentals
├── ex2_textview.txt
├── ex5_size_units.txt
├── ex3_strings.txt
├── ex4_lifecycle.txt
├── ex1_manifest.txt
└── ex0_new_project.txt
├── chap02_user_interface
├── ex3_layout_params.txt
├── ex2_linear.txt
└── ex1_launcher.txt
├── chap06_networking
├── ex3_async_http_client.txt
├── ex2_async_task.txt
└── ex1_image_download.txt
├── chap05_user_flows
├── ex1_explicit_intents.txt
├── ex4_action_bar.txt
├── ex2_implicit_intents.txt
└── ex3_intent_with_results.txt
├── chap08_preferences
└── ex1_persist_settings.txt
└── chap09_content_providers
└── ex1_contact_list.txt
/README.md:
--------------------------------------------------------------------------------
1 | intro_android_exercises
2 | =======================
3 |
4 | Step by step exercises for learning Android
5 |
--------------------------------------------------------------------------------
/chap04_interactions/ex2_toast.txt:
--------------------------------------------------------------------------------
1 | Goal: To display a toast message.
2 |
3 | Description:
4 | A toast is a text view that appears in the bottom half of the screen that automatically fades away after a short delay. It is used to display transient messages.
5 |
6 | Directions:
7 | 1) In the onClick method of a button, display a message using a Toast.
8 |
9 |
10 | ## Snippets
11 |
12 | // Use Toast to show message in methods
13 | Toast.makeText(MyActivityClass.this, "firstButton clicked via XML handler", Toast.LENGTH_SHORT).show();
14 |
--------------------------------------------------------------------------------
/chap07_advanced_views/ex3_timepicker.txt:
--------------------------------------------------------------------------------
1 | Goal: Explore using a TimePicker view.
2 |
3 | Description:
4 | This is a basic exercise using the TimePicker view.
5 |
6 | Directions:
7 | 1) Create an Activity with a TimePicker view.
8 | 2) Add a button. In the click handler,
9 | a) Display a toast of the current selected time.
10 |
11 |
12 | ## Snippets
13 |
14 | // Java Activity
15 | public void displayTime(View v) {
16 | String time = tpTime.getCurrentHour() + ":" + tpTime.getCurrentMinute();
17 | Toast.makeText(this, time, Toast.LENGTH_SHORT).show();
18 | }
19 |
--------------------------------------------------------------------------------
/chap03_view/ex2_basic_views.txt:
--------------------------------------------------------------------------------
1 | Goal: Explore the basic views of an Android application.
2 |
3 | Description:
4 | While an Android application has many complex views, most complex views are comprised of the basic views, TextView, EditText, Button, ImageView, and ImageButton.
5 |
6 | Directions:
7 |
8 | 1) Open the layout XML.
9 | 2) Ensure that the root layout is a vertical LinearLayout.
10 | 3) Add an EditText input field.
11 | 4) Add a Button.
12 | 5) Add an ImageView.
13 | 6) Add an ImageButton
14 | 7) Set the android:layout_margin property to 20dp to create some space between the elements.
15 |
16 |
17 | ## Snippets
18 |
19 | // Hint: Switch to Graphical Layout and
20 | // drag the inputs from the left-hand palette
21 |
--------------------------------------------------------------------------------
/chap01_app_fundamentals/ex2_textview.txt:
--------------------------------------------------------------------------------
1 | Goal: Explore the XML layout of an Activity.
2 |
3 | Description:
4 | Every activity has an associated XML layout file specified in the onCreate method. The XML file is responsible for describing the elements (TextViews, Buttons, etc) that will be on the screen for that activity.
5 |
6 | Every element has XML properties that describes various behavior such as layout, alignment, color, etc.
7 |
8 | Directions:
9 |
10 | 1) Open the XML layout file (e.g., res/layout/activity_hello_world.xml)
11 | 2) Switch to the text mode.
12 | 3) If there is not already a TextView in the layout, add one.
13 | 4) Modify the android:text property, as shown below.
14 |
15 |
16 | ## Snippets
17 |
18 |
--------------------------------------------------------------------------------
/chap01_app_fundamentals/ex5_size_units.txt:
--------------------------------------------------------------------------------
1 | Goal: Explore size units.
2 |
3 | Description:
4 | Android devices have a variety of screen resolutions. In other words, any given physical inch of the screen may contain 100 pixels, 200 pixels, or more, depending on the resolution. Therefore, if we specify measurements in pixels, the element (e.g., a TextView or Button) will appear to be different sizes on different devices.
5 |
6 | Never use px for distance or pt for font size. Instead, use dp for distance and sp for font size.
7 |
8 | Directions:
9 |
10 | 1) Open the layout XML.
11 | 2) For the TextView, add the property android:textSize and set it to 20sp.
12 |
13 |
14 | ## Snippets
15 |
16 |
--------------------------------------------------------------------------------
/chap01_app_fundamentals/ex3_strings.txt:
--------------------------------------------------------------------------------
1 | Goal: Modify strings in the strings.xml file.
2 |
3 | Description:
4 | The primary purpose of the strings.xml file is for internationalization. Any string that is ultimately shown to the user (e.g., in a text field, button, or navigation) should be added to the strings.xml file. That way, to add support for a new language simply requires adding an additional strings.xml file for the new language.
5 |
6 | In XML, refer to strings described in the strings.xml file using the syntax @string/my_string.
7 |
8 | Directions:
9 |
10 | 1) Open the XML layout file.
11 | 2) If you have any android:text values that do not refer to an @string, hover your mouse over the warning and read what it says.
12 | 3) Add new strings to the strings.xml file. Note: the keys may not include spaces.
13 | 4) Modify all android:text properties to refer to a string
14 |
15 |
16 | ## Snippets
17 |
18 |
--------------------------------------------------------------------------------
/chap03_view/ex1_layout_gravity.txt:
--------------------------------------------------------------------------------
1 | Goal: Explore layout gravity.
2 |
3 | Description:
4 | In Chapter 2, we explored the gravity property. Layout gravity specifies the gravity of an element with respect to its parent. The easiest way to understand this is to try a few layout gravity options and see what happens.
5 |
6 | Directions:
7 |
8 | 1) Open the layout XML.
9 | 2) Add at least three TextViews in a vertical LinearLayout.
10 | 3) For each TextView, add the android:padding property and set it to 30dp. This will create some space between the TextViews.
11 | 4) Set the android:layout_gravity property of the first TextView to "left".
12 | 5) Set the android:layout_gravity property of the second TextView to "center".
13 | 6) Set the android:layout_gravity property of the third TextView to "right".
14 |
15 |
16 | ## Snippets
17 |
18 | // In activity, have three TextViews similar to below
19 |
25 |
26 |
--------------------------------------------------------------------------------
/chap07_advanced_views/ex1_toast_inputs.txt:
--------------------------------------------------------------------------------
1 | Goal: Experiment with three basic input views: EditText, CheckBox, and RadioGroup.
2 |
3 | Description:
4 | This is a basic exercise in the usage of a few common input views.
5 |
6 | Directions:
7 | 1) Create a new Activity with an EditText, a CheckBox, and a RadioGroup.
8 | 2) In the onCreate method, find and store each view into an instance variable.
9 | 3) Add a button to the activity and implement a click handler.
10 | a) In the click handler, display a Toast of the current values of the EditText, CheckBox, and RadioGroup.
11 |
12 |
13 | ## Snippets
14 |
15 | @Override
16 | protected void onCreate(Bundle savedInstanceState) {
17 | // ...
18 | etVal = (EditText) findViewById(R.id.etVal);
19 | chkVal = (CheckBox) findViewById(R.id.chkVal);
20 | rdgVal = (RadioGroup) findViewById(R.id.rdgVal);
21 | }
22 |
23 | public void toastInputs(View v) {
24 | int selected = rdgVal.getCheckedRadioButtonId();
25 | RadioButton b = (RadioButton) findViewById(selected);
26 |
27 | String text = etVal.getText() + " | " + chkVal.isChecked() + " | " + b.getText();
28 | Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
29 | }
30 |
--------------------------------------------------------------------------------
/chap02_user_interface/ex3_layout_params.txt:
--------------------------------------------------------------------------------
1 | Goal: Explore layout widths.
2 |
3 | Description:
4 | There are 3 options for layout width: match_parent, wrap_content, and a dp value. match_parent sets the width to be the same width as the container. wrap_content will size the container to be just large enough to fit its content. A dp value will specify the exact width.
5 |
6 | Directions:
7 |
8 | 1) Open the layout XML.
9 | 2) Add at least 3 TextViews to the vertical LinearLayout.
10 | 3) Set the android:background property to #00FF00, as below.
11 | 4) Set the first TextView width to be wrap_content.
12 | 5) Set the second TextView width to be match_parent.
13 | 6) Set the third TextView width to be 50dp.
14 |
15 |
16 | ## Snippets
17 |
18 |
23 |
24 |
29 |
30 |
35 |
--------------------------------------------------------------------------------
/chap02_user_interface/ex2_linear.txt:
--------------------------------------------------------------------------------
1 | Goal: Explore LinearLayout.
2 |
3 | Description:
4 | Layouts (ViewGroups) are containers for Views (e.g., TextViews, Buttons, etc) and may also contain other Layouts. Different layout types have different options for configuring how their contained Views are laid out.
5 |
6 | The easiest to use and the most common Layout type is LinearLayout. LinearLayout either lays out its contained Views in a row or a column, depending on the orientation property.
7 |
8 | Note: the gravity property specifies the alignment of the contained views (e.g., left, center, right, etc). This is different from layout_gravity, which specifies the alignment of the entire container with respect to its parent.
9 |
10 | Directions:
11 |
12 | 1) Open the XML layout.
13 | 2) Change the root layout to be a LinearLayout.
14 | 3) Add the android:orientation property and set it to "vertical".
15 | 4) Add the android:gravity property and set it to "center".
16 |
17 |
18 | ## Snippets
19 |
20 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/chap02_user_interface/ex1_launcher.txt:
--------------------------------------------------------------------------------
1 | Goal: Create a new activity and set it to be the default activity.
2 |
3 | Description:
4 | Every activity in the project must be listed in AndroidManifest.xml, in the application node. Only one of them should contain an intent filter with an action set to MAIN and a category of LAUNCHER. That activity will be the default activity.
5 |
6 | Directions:
7 | 1) Create a new activity.
8 | a) Click on File->New->Activity->Blank Activity
9 | b) The wizard will automatically create the activity, add it to AndroidManifest.xml, create a layout file, and create a menu file. If you want to delete an activity, you should remove the corresponding layout and menu file manually.
10 | 2) Modify the new activity's layout file so that you can recognize it as the second activity.
11 | 3) Modify AndroidManifest.xml to change the default activity.
12 | 4) Run the application and confirm that it starts with the second activity.
13 |
14 |
15 | ## Snippets
16 |
17 | // Android Manifest.xml
18 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/chap06_networking/ex3_async_http_client.txt:
--------------------------------------------------------------------------------
1 | Goal: Download an image asynchronously.
2 |
3 | Description:
4 | Using the built-in URLConnection class and AsyncTasks, it's possible to download images from the internet asynchronously. However, third party libraries exist to provide this functionality in a more convenient way. A popular third party library is AsyncHttpClient, which makes all its network requests asynchronously.
5 |
6 | This library uses anonymous classes to receive the desired method from the developer.
7 |
8 | Directions:
9 | 1) Create an Activity with an ImageView.
10 | 2) Find the URL of an image to test.
11 | 3) In the onCreate method, call downloadImageFromUrl(String address)
12 | 4) Implement downloadImageFromUrl(String address) like the snippet below
13 |
14 | Reference:
15 |
16 | Download the library from: http://loopj.com/android-async-http/
17 |
18 |
19 | ## Snippets
20 |
21 | // In Java
22 | private void downloadImageFromUrl(String address) {
23 | AsyncHttpClient client = new AsyncHttpClient();
24 | client.get(address, new
25 | BinaryHttpResponseHandler() {
26 | @Override
27 | public void onSuccess(byte[] image) {
28 | Bitmap bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);
29 | ImageView img = (ImageView) findViewById(R.id.ivSmartImage);
30 | img.setImageBitmap(bitmap);
31 | }
32 | }
33 | );
34 | }
35 |
--------------------------------------------------------------------------------
/chap01_app_fundamentals/ex4_lifecycle.txt:
--------------------------------------------------------------------------------
1 | Goal: Explore the Activity lifecycle.
2 |
3 | Description:
4 | The Activity lifecycle is automatically managed by the Android framework. If a user taps on something that switches them into a new activity, the previous activity is paused. The activity is also paused if the user receives a phone call.
5 |
6 | The 3 most commonly implemented activity lifecycle methods are onCreate, onPause, and onResume. Note: if you implement an activity lifecycle method, you MUST call the super implementation.
7 |
8 | Directions:
9 | 1) Open the Activity java file (e.g., src/codepath/HelloWorldActivity.java)
10 | 2) Implement the onCreate, onPause, and onResume methods.
11 | 3) In each method, call the super method.
12 | 4) Add a Log.d message to each method, as shown below.
13 | 5) Run the application and observe the LogCat.
14 | a) In the emulator, click the Home button. Did you see the activity pause in the LogCat?
15 |
16 |
17 | ## Snippets
18 |
19 | protected void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | setContentView(R.layout.activity_basic_text_view);
22 | Log.d("DEBUG", "onCreate was just called!");
23 | }
24 |
25 | protected void onResume() {
26 | super.onResume();
27 | Log.d("DEBUG", "onResume was just called!");
28 | }
29 |
30 | protected void onPause() {
31 | super.onPause();
32 | Log.d("DEBUG", "onPause was just called!");
33 | }
--------------------------------------------------------------------------------
/chap04_interactions/ex3_list_view_clicks.txt:
--------------------------------------------------------------------------------
1 | Goal: Implement handling a click on a row in a ListView.
2 |
3 | Description:
4 | ListViews display a collection of data, which it accesses via an Adapter. Each item in the collection can be rendered in a custom view. In this exercise, we will create a simple ListView with a default view and handle clicks on a row.
5 |
6 | Directions:
7 | 1) In a new Activity, create a ListView that fills the screen.
8 | 2) In the onCreate method of the Activity
9 | a) Create a string Array of countries.
10 | b) Instantiate an array adapter with the string array and a default XML layout, android.R.layout.simple_list_item_1.
11 | c) Set the adapter of the ListView to the array adapter.
12 | d) Set the onItemClickListener of the ListView to display a toast upon clicking on the row. The toast should indicate which country was selected.
13 |
14 |
15 | ## Snippets
16 |
17 | String[] myCountries = { "United States", "Canada", "Mexico", "Japan" };
18 | adapter = new ArrayAdapter(this,
19 | android.R.layout.simple_list_item_1, myCountries);
20 |
21 | ListView listView = (ListView) findViewById(R.id.lvDemo);
22 | listView.setAdapter(adapter);
23 |
24 | listView.setOnItemClickListener(new OnItemClickListener() {
25 | @Override
26 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
27 | String country = adapter.getItem(position);
28 | Toast.makeText(ListViewClicksActivity.this, country, Toast.LENGTH_SHORT).show();
29 | }
30 |
31 | });
32 |
--------------------------------------------------------------------------------
/chap01_app_fundamentals/ex1_manifest.txt:
--------------------------------------------------------------------------------
1 | Goal: Explore the AndroidManifest file.
2 |
3 | Description:
4 | Every Android application has a file called AndroidManifest.xml that controls application-wide settings such as the display name, icon, theme, and default Activity.
5 |
6 | Directions:
7 |
8 | 1) Open AndroidManifest.xml
9 | a) Change the version code and name to 2 and 2.0. Reminder: version code is an integer value that you can programatically inspect in your application. Version name is displayed to the user.
10 | b) Change the application name
11 | c) Change the application icon
12 | i) Find and download an image, e.g., from Google Images.
13 | ii) Create various resolution sizes for your image. Tip: Use a tool to automatically create the resolution sizes: http://android-ui-utils.googlecode.com/hg/asset-studio/dist/icons-launcher.html
14 | iii) Place the various resolutions into the respective drawable folders.
15 | iv) In AndroidManifest.xml, point to the new drawable.
16 |
17 |
18 | ## Snippets
19 |
20 | // AndroidManifest.xml
21 |
25 |
26 |
27 |
28 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/chap05_user_flows/ex1_explicit_intents.txt:
--------------------------------------------------------------------------------
1 | Goal: Launch other activities in the application via explicit intents.
2 |
3 | Description:
4 | An explicit intent is how to launch one Activity in an application from another Activity in the same application. The intent's primary role is to specify which Activity class is to be launched. However, it can also pass along data which the new Activity can read.
5 |
6 | All activities are associated with an originating intent. Retrieve the originating intent at any time using the method getIntent().
7 |
8 | Directions:
9 | 1) Add a button to the default activity and label it "Launch".
10 | 2) Register a click handler via XML or Java
11 | 3) In the click handler method,
12 | a) Create an intent, initializing it with the Activity to be launched.
13 | b) Put a string "extra" in the intent.
14 | c) Start the second activity.
15 | 4) In the second Activity,
16 | a) Get the originating intent using getIntent()
17 | b) Get the string "extra" from the intent.
18 | c) Set the text of a TextView to the string "extra".
19 |
20 |
21 | ## Snippets
22 |
23 | // In Activity
24 | Button btnLaunchSecond = (Button) findViewById(R.id.btnLaunchSecond);
25 | btnLaunchSecond.setOnClickListener(new OnClickListener() {
26 | @Override
27 | public void onClick(View v) {
28 | Intent i = new Intent(getBaseContext(), SimpleBundleDemoActivity.class);
29 | i.putExtra("text", "Passed String Extra!");
30 | startActivity(i);
31 | }
32 | });
33 |
34 | // In Launched Activity
35 | String initialText = getIntent().getStringExtra("text");
36 | TextView tvDisplayText = (TextView) findViewById(R.id.tvDisplayText);
37 | tvDisplayText.setText(initialText);
38 |
--------------------------------------------------------------------------------
/chap04_interactions/ex1_click_handlers.txt:
--------------------------------------------------------------------------------
1 | Goal: Add a click handler to a button.
2 |
3 | Description:
4 | Click handlers are methods that will be called when a button is called. Click handlers can be registered either in the XML or in Java. Whenever possible, add the click handler in XML. However, in some situations, such as dynamically created buttons, the click handler must be registered in Java using anonymous classes.
5 |
6 | Directions:
7 | 1) Create a view that has two buttons.
8 | 2) For the first button,
9 | a) Add the android:onClick property as in the snippet below, and set it to "firstButtonClicked"
10 | b) Add the method "void firstButtonClicked(View view)"
11 | c) Log the button click.
12 | 3) For the second button,
13 | a) In the onCreate method of the activity, get a handle to the second button using findViewById, and set the OnClickListener.
14 | b) Log the button click.
15 |
16 |
17 | ## Snippets
18 |
19 | // First button with xml onClick
20 |
26 |
27 |
28 | // Java Activity
29 | protected void onCreate(Bundle savedInstanceState) {
30 | // ...
31 | Button secondButton = (Button) findViewById(R.id.btnClick2);
32 | secondButton.setOnClickListener(new View.OnClickListener() {
33 | @Override
34 | public void onClick(View v) {
35 | secondButtonClicked(v);
36 | }
37 | });
38 | }
39 |
40 | public void firstButtonClicked(View v) {
41 | // ...
42 | }
43 |
44 |
45 | public void secondButtonClicked(View v) {
46 | // ...
47 | }
48 |
--------------------------------------------------------------------------------
/chap03_view/ex3_view_attributes.txt:
--------------------------------------------------------------------------------
1 | Goal: Explore view attributes and getting a handle to the view from Java.
2 |
3 | Description:
4 | Views have many different properties to configure their appearance and behavior. In this exercise, we will experiment with a few basic properties, such as setting the background color and playing with margin and padding.
5 |
6 | XML is used to describe the static aspects of an Activity. However, we will often need to manipulate or access the views in Java as well. For example, if the user enters some input in an EditText view, we need to be able to access that EditText to find out what they entered.
7 |
8 | For views that need to be accessed from Java, add a unique id label, using @+id/some_id. ONLY assign an id to views that need to be accessed from Java.
9 |
10 | Directions:
11 |
12 | 1) Open the layout XML.
13 | 2) Set the properties of a TextView
14 | a) android:background="#06327a"
15 | b) android:textColor="#cbd9f0"
16 | c) android:padding="15dp"
17 | d) android:layout_margin="10dp"
18 | e) android:layout_centerHorizontal="true"
19 | f) android:layout_centerVertical="false"
20 | 3) Add a unique id to the TextView
21 | a) android:id = "@+id/main_text_view"
22 | b) save the XML file to commit the ID changes
23 | 4) In the activity's Java file
24 | a) Get a handle to the TextView, as shown in the snippet below
25 | b) Hover your mouse over TextView and Toast and click the option to automatically import packages.
26 |
27 |
28 | ## Snippets
29 |
30 | // Java code in Activity
31 | protected void onCreate(Bundle savedInstanceState) {
32 | // ...
33 | TextView tvMain = (TextView) findViewById(R.id.main_text_view);
34 | Toast.makeText(this, tvMain.getText().toString(), Toast.LENGTH_SHORT).show();
35 | }
36 |
--------------------------------------------------------------------------------
/chap05_user_flows/ex4_action_bar.txt:
--------------------------------------------------------------------------------
1 | Goal: Build an action bar with 2 icons.
2 |
3 | Description:
4 | Google is encouraging application developers to adopt the action bar, which is a title bar at the top of the screen with buttons. This is meant to be a replacement for the context menu used in early versions of Android.
5 |
6 | In this exercise, we will add 2 action buttons. One will simply display a Toast and the other will launch another Activity.
7 |
8 | Directions:
9 | 1) Open the menu XML for the default Activity (e.g., res/menu/my_activity.xml). Note that this different than the layout XML.
10 | 2) Add 2 menu items, as shown in the snippet below.
11 | 3) Override the onOptionsItemSelected method in the Activity.
12 | a) Add a switch statement for the MenuItem.
13 | b) Either create a Toast for launch the next activity.
14 |
15 |
16 | ## Snippets
17 |
18 | // res/menu/my_activity.xml
19 |
32 |
33 | // In Java Activity
34 | @Override
35 | public boolean onOptionsItemSelected(MenuItem item) {
36 | switch (item.getItemId()) {
37 | case R.id.menu_toast:
38 | Toast.makeText(this, "Toasted", Toast.LENGTH_SHORT).show();
39 | break;
40 | case R.id.menu_launch:
41 | Intent i = new Intent(this, SimpleBundleDemoActivity.class);
42 | startActivity(i);
43 | break;
44 | default:
45 | break;
46 | }
47 | return true;
48 | }
49 |
--------------------------------------------------------------------------------
/chap05_user_flows/ex2_implicit_intents.txt:
--------------------------------------------------------------------------------
1 | Goal: Launch a browser using implicit intents.
2 |
3 | Description:
4 | When launching another activity in the same application, use explicit intents to designate the activity to launch. However, in order to launch other applications, one must use implicit intents which does not specify a specific activity. An implicit intent uses a combination of an action, data, and a category to determine which application to launch. In some cases, more than one application may have an "intent filter" that matches the criteria of the implicit intent.
5 |
6 | Although there are many rules to matching implicit intents with intent filters, the most common implicit intents specify and action (e.g., ACTION_VIEW) and data with a URL, like http:// or loc:// or contacts://. Android uses the protocol, e.g., http, to match with the appropriate application, like the browser, maps, calendar, contacts, phone, etc.
7 |
8 | Directions:
9 | 1) In a new activity, add an EditText and Button view.
10 | 2) In the button click handler,
11 | a) Create a Uri based on the text in the EditText field.
12 | b) Create an intent w/ the ACTION_VIEW action and the url data.
13 | c) Start an activity with the implicit intent.
14 |
15 |
16 | ## Snippets
17 |
18 | // In Java Activity
19 | public void visitUrlAddress(View v) {
20 | Uri url = getUriToVisit();
21 | if (url != null) {
22 | Intent i = new Intent(Intent.ACTION_VIEW);
23 | i.setData(url);
24 | startActivity(i);
25 | }
26 |
27 | }
28 |
29 | public Uri getUriToVisit() {
30 | String urlAddress = ((TextView) findViewById(R.id.txtUrlAddress)).getText().toString();
31 | if (urlAddress != null) {
32 | if (!urlAddress.startsWith("http://"))
33 | urlAddress = "http://" + urlAddress;
34 | return Uri.parse(urlAddress);
35 | } else {
36 | return null;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/chap05_user_flows/ex3_intent_with_results.txt:
--------------------------------------------------------------------------------
1 | Goal: Use an intent that passes back a result.
2 |
3 | Description:
4 | Sometimes, when launching an activity, it's convenient to give the originating activity some result. An example of this use case is when the launched activity is gathering some information from the user in a form.
5 |
6 | Directions:
7 | 1) In a new Activity,
8 | a) Add a TextView and a Button.
9 | b) In the button click handler, launch another activity using startActivityForResult
10 | c) Override onActivityResults
11 | i) Set the text of the TextView to the returned data.
12 | 2) In the second Activity,
13 | a) Create an EditText and a Button
14 | b) In the button click handler,
15 | i) Create an intent and add string extra into it.
16 | ii) Call setResult(RESUILT_OK, intent)
17 | iii) Call finish() to dismiss the current Activity
18 |
19 |
20 | ## Snippets
21 |
22 | // In Activity
23 | final static int GET_RESULT_TEXT = 0;
24 |
25 | public void enterText(View v) {
26 | startActivityForResult(
27 | new Intent(IntentWithResultActivity.this, SimpleReturnResultActivity.class),
28 | GET_RESULT_TEXT);
29 | }
30 |
31 | // Handle the result once the activity returns a result, display contact
32 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
33 | if (requestCode == 0) {
34 | if (resultCode == RESULT_OK) {
35 | TextView tvResult = (TextView)findViewById(R.id.txtDisplayResult);
36 | tvResult.setText(data.getStringExtra("result"));
37 | Toast.makeText(this, data.getStringExtra("result"), Toast.LENGTH_SHORT).show();
38 | }
39 | }
40 | }
41 |
42 | // Returning Activity
43 | public void sendResult(View v) {
44 | String result = ((EditText) findViewById(R.id.txtRandomResultText)).getText().toString();
45 | Intent i = new Intent();
46 | i.putExtra("result", result);
47 | setResult(RESULT_OK, i);
48 | finish();
49 | }
50 |
--------------------------------------------------------------------------------
/chap07_advanced_views/ex5_gridview.txt:
--------------------------------------------------------------------------------
1 | Goal: Create a GridView to display 6 images.
2 |
3 | Description:
4 | Like ListView and Spinner, GridView is an adapter view. In other words, it displays the data that it finds in its attached adapter. In this exercise, we will display 6 images in a grid using a GridView.
5 |
6 | Adapters can specify an XML file to display each item. However, to customize the view, one must subclass the ArrayAdapter class and override the getView method.
7 |
8 | Directions:
9 | 1) Create a new Activity with a GridView that fills the entire screen.
10 | 2) Download and copy 6 images into the drawables folder. You only need to copy the images into one of the drawables folders.
11 | 3) Create a new class called GridImageAdapter that is a subclass of ArrayAdapter.
12 | a) Override the getView method to create a custom view.
13 | b) Set the appropriate image based on the index.
14 | 4) In the onCreate method, create a GridImageAdapter and set it to the GridView.
15 |
16 |
17 | ## Snippets
18 |
19 | GridView gvImages;
20 | GridImageAdapter adapter;
21 |
22 | protected void loadGridViewImages() {
23 | gvImages = (GridView) findViewById(R.id.gvImages);
24 | String[] numbers = new String[] { "ad", "ae", "af", "ag", "ai", "al"};
25 | adapter = new GridImageAdapter(this,
26 | android.R.layout.simple_list_item_1, numbers);
27 | gvImages.setAdapter(adapter);
28 | }
29 |
30 | class GridImageAdapter extends ArrayAdapter {
31 |
32 | public GridImageAdapter(Context context, int textViewResourceId, String[] numbers) {
33 | super(context, textViewResourceId, numbers);
34 | }
35 |
36 | public View getView(int position, View convertView, ViewGroup parent) {
37 | ImageView v = new ImageView(GridViewDemoActivity.this);
38 | int resId = getResources().getIdentifier(getItem(position), "drawable", getPackageName());
39 | v.setImageDrawable(getResources().getDrawable(resId));
40 | return v;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/chap03_view/ex4_simple_list_view.txt:
--------------------------------------------------------------------------------
1 | Goal: Explore a simple ListView.
2 |
3 | Description:
4 | Aside from the basic views, the ListView is the most common view when developing Android applications. If you think about the apps that you use, like Mail, Facebook, Twitter, Instagram, etc, so many views involve scrolling a list of custom views.
5 |
6 | ListViews work in two parts: an adapter that provides access to an array of data, and a custom view template to style each individual item.
7 |
8 | Android provides a simple default view template that is just a simple TextView, which is shown in the snippet below and referenced using R.layout.simple_list_view_item. This is fine for testing, but in the future we will use our own custom template.
9 |
10 | Directions:
11 |
12 | 1) Create a new activity and set it to be the default launch activity.
13 | 2) In the layout XML
14 | a) Add a ListView, setting the width and height to be match_parent.
15 | 3) In the activity's Java file
16 | a) Modify the onCreate method
17 | i) Define an array of data
18 | ii) Create an adapter, specifiying the view template and the data array.
19 | iii) Attach the adapter to the ListView
20 | 4) Run the application
21 |
22 |
23 | ## Snippets
24 |
25 | // res/layout/simple_list_view_item.xml
26 |
27 |
34 |
35 |
36 | // In Activity
37 | protected void onCreate(Bundle savedInstanceState) {
38 | // ...
39 | String[] myStringArray = { "Bruce", "Wayne", "Bill" };
40 | ArrayAdapter adapter = new ArrayAdapter(this,
41 | R.layout.simple_list_view_item, myStringArray);
42 |
43 | ListView listView = (ListView) findViewById(R.id.lvDemo);
44 | listView.setAdapter(adapter);
45 | }
46 |
--------------------------------------------------------------------------------
/chap07_advanced_views/ex2_spinner_toast.txt:
--------------------------------------------------------------------------------
1 | Goal: Use a Spinner to select one of a few choices.
2 |
3 | Description:
4 | A spinner is a control used by things like alarm clocks. Upon clicking a Spinner, it will display a pull down menu of different options to choose between.
5 |
6 | Similar to ListView, Spinner is also an adapter view. In other words, it displays the data that it finds in its attached adapter. There are many ways to create adapters that a Spinner can use. In this exercise, we will use an ArrayAdapter that is initialized using an XML string array.
7 |
8 | Like a ListView, each item in a Spinner can be rendered using a custom view. In this exercise, we will use a built-in view called android.R.layout.simple_spinner_item.
9 |
10 | Directions:
11 | 1) Create an XML file called spinner_values.xml in res/values
12 | 2) Create a new Activity that includes a Spinner.
13 | 3) In the onCreate method
14 | a) Create an ArrayAdapter with the XML array and a default spinner layout.
15 | b) Set the dropDownViewResource to a default dropdown layout.
16 | c) Set the adapter on the spinner to the newly created ArrayAdapter.
17 | 4) Add a button to the activity. In the click handler,
18 | a) Fetch the current value of the Spinner and display a Toast of the current value
19 |
20 |
21 | ## Snippets
22 |
23 | // res/values/spinner_values.xml
24 |
25 |
26 |
27 | Red
28 | Orange
29 | Yellow
30 | Green
31 | Blue
32 | Indigo
33 | Violet
34 |
35 |
36 |
37 | // In Java Activity
38 | private void loadSpinner() {
39 | ArrayAdapter adapter = ArrayAdapter.createFromResource(this,
40 | R.array.spinner_options, android.R.layout.simple_spinner_item);
41 | // Set layout style during dropdown
42 | adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
43 | // Load data from adapter
44 | spinner.setAdapter(adapter);
45 | }
46 |
--------------------------------------------------------------------------------
/chap08_preferences/ex1_persist_settings.txt:
--------------------------------------------------------------------------------
1 | Goal: Persist settings across application launches.
2 |
3 | Description:
4 | There are a variety of ways to save data, and one of the simplest ways is to leverage the built-in SharedPreferences class. SharedPreferences is simply a HashMap that saves its keys and values to disk automatically.
5 |
6 | In this exercise, we will add some values to the SharedPreferences class and retrieve them later.
7 |
8 | Directions:
9 | 1) In a new Activity, create an EditText and CheckBox.
10 | 2) In the onCreate method, retrieve the saved values for previous EditText and CheckBox views and configure the current EditText and CheckBox views.
11 | a) Get the SharedPreferences using getSharedPreferences()
12 | b) Store the SharedPreferences Editor to be used later.
13 | c) Retrieve the saved values for EditText and CheckBox from the SharedPreferences using keys that you have chosen.
14 | 3) Add a button, and in the click handler:
15 | a) Using the previously created Editor, save the EditText and CheckBox values using keys that you have chosen.
16 | b) Call the commit() method on the Editor that will trigger the Editor to save the new values to disk.
17 | c) Display a Toast confirming that the changes have been saved.
18 | 4) Close the Activity.
19 | 5) Confirm that opening the Activity properly restores the saved values.
20 |
21 |
22 | ## Snippets
23 |
24 | // In Java Activity
25 | SharedPreferences prefs;
26 | Editor edits;
27 | TextView txtPersist;
28 | CheckBox chkPersist;
29 |
30 | public void populateValues() {
31 | prefs = getSharedPreferences("view", 0);
32 | edits = prefs.edit();
33 | String persistedText = prefs.getString("txtVal", "None Stored Yet");
34 | boolean isChecked = prefs.getBoolean("chkState", false);
35 | txtPersist.setText(persistedText);
36 | chkPersist.setChecked(isChecked);
37 | }
38 |
39 | public void persistValues(View v) {
40 | edits.putString("txtVal", txtPersist.getText().toString());
41 | edits.putBoolean("chkState", chkPersist.isChecked());
42 | edits.commit();
43 | Toast.makeText(this, "Persisted!", Toast.LENGTH_SHORT).show();
44 | }
45 |
--------------------------------------------------------------------------------
/chap01_app_fundamentals/ex0_new_project.txt:
--------------------------------------------------------------------------------
1 | Goal: Create a new Android project
2 |
3 | Description:
4 |
5 | Welcome to Android development! We're going to explore Android concepts by following the various instructions in these text files. In this first step, we will create the Android project that we will use for the rest of these exercises.
6 |
7 | The "New Project" wizard will contain options not specified below. Unless the directions below say otherwise, you may accept the default options.
8 |
9 | Directions:
10 |
11 | 1) Open Eclipse, and select File->New->Android Application Project
12 | 2) Choose an application name, as you want it to appear when it is installed on a phone.
13 | a) Note: It's ok to keep the default com.example prefix for now.
14 | 3) Choosing SDK versions
15 | a) Minimum required SDK: In the world, Android phones are running many different versions of Android. You need to select the minimum version that you will support. The lower the version, the more difficult it is to support because it will not have features of later versions. Unfortunately, many phones are unable to update their Android versions.
16 |
17 | Use this site to help choose what the minimum required SDK version should be: http://developer.android.com/about/dashboards/index.html
18 |
19 | As of right now, 45% of phones use API level 10. If you choose to only support API level 16, only 12% of phones will be able to install your application.
20 |
21 | Therefore, set your minimum required SDK to 10.
22 | b) Target SDK: This should be set to the highest possible value. For new projects, it should match the "Compile With" property. This is an indication to the operating system that you've tested your application with a particular version. If the user upgrades their phone's OS past your indicated target SDK, the phone will run your app in a compatibility mode.
23 | c) Compile With: This should be set to the highest possible value.
24 | d) When you create the Activity, you should use the default template, a Blank Activity.
25 | 4) Run your application
26 | a) It should launch in the emulator and display "Hello World" on a white screen.
27 | 5) You're done!
28 |
29 |
--------------------------------------------------------------------------------
/chap06_networking/ex2_async_task.txt:
--------------------------------------------------------------------------------
1 | Goal: Background a task using AsyncTasks.
2 |
3 | Description:
4 | For the most part, application code should run in the primary thread for simplicity. However, slow tasks such network access or disk access should be run in a background thread.
5 |
6 | Android provides the AsyncTask class which handles much of the complexity of creating and managing threads. In the Activity that has a task to be backgrounded, implement one or more subclasses of AsyncTask as a private, inner class. AsyncTask is a generic class, whose parameters are the input type, output type, and metric for tracking progress. In this example, we will implement an AsyncTask that has no input and output, so those parameters will be Void.
7 |
8 | An AsyncTask has a few methods, but the most commonly implemented are the doInBackground() and onPostExecute() methods. Any code that is in the doInBackground() method is automatically run in the background thread. Upon completion of the doInBackground method(), the AsyncTask will call the onPostExecute() method and run it in the main thread. This is useful because all UI methods MUST be run in the main thread or the application will crash.
9 |
10 | In this exercise, we will simply count to 100,000 and display a Toast message when we're done counting.
11 |
12 | Directions:
13 | 1) In the default Activity, implement MyAsyncTask as a subclass of AsyncTask
14 | a) In doInBackground, print out the numbers 0 to 100,000.
15 | b) In onPostExecute, display a Toast message.
16 | 2) In the onCreate method, instantiate an object of MyAsyncTask and call the execute() method.
17 | 3) Run the application and note that the Toast message will appear after some delay. If there is not a noticeable delay, increase the counter to 1,000,000 or more.
18 |
19 |
20 | ## Snippets
21 |
22 | // In Activity
23 | @Override
24 | protected void onCreate(Bundle savedInstanceState) {
25 | // ...
26 | new MyAsyncTask().execute();
27 | }
28 |
29 | public void doneCounting() {
30 | Toast.makeText(this, "Done Counting to 100000", Toast.LENGTH_SHORT).show();
31 | }
32 |
33 | private class MyAsyncTask extends AsyncTask {
34 | public Void doInBackground(Void... params) {
35 | for (long i=0; i < 100000; i++) {
36 | System.out.println(i);
37 | }
38 | return null;
39 | }
40 |
41 | protected void onPostExecute(Void result) {
42 | doneCounting();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/chap06_networking/ex1_image_download.txt:
--------------------------------------------------------------------------------
1 | Goal: Download an image.
2 |
3 | Description:
4 | When making network requests, there are a couple of requirements: permissions and threading.
5 |
6 | Android requires an application to request permissions for certain things, such as accessing the internet, the call log, the contact book, etc. Permissions are requested by listing them in AndroidManifest.xml.
7 |
8 | Android is mostly single threaded. This is by design because it is easy to introduce undesirable behavior with multiple threads. However, accessing the network or the disk in the main thread will cause the main thread to be unresponsive to user interaction. Android added a concept called StrictMode that enforces the rule that network requests must never be made on the main thread. In the next lesson, we will learn how to move the network request to a background thread. For now, we will disable the StrictMode rule and download the image in the main thread.
9 |
10 | Directions:
11 | 1) Modify AndroidManifest.xml to request the INTERNET permission.
12 | 2) Create a new Activity with an ImageView.
13 | 3) In the onCreate,
14 | a) Disable StrictMode for network access.
15 | b) Call a method, downloadImageFromUri(String address)
16 | 4) Implement downloadImageFromUri(String address)
17 | a) Create the URL from the string.
18 | b) Open a URLConnection.
19 | c) Get an InputStream from the connection.
20 | d) Decode the image using the BitmapFactory.
21 | e) Set the bitmap of the ImageView.
22 |
23 |
24 | ## Snippets
25 |
26 | // Manifest
27 |
28 |
29 | // In Activity
30 |
31 | @Override
32 | protected void onCreate(Bundle savedInstanceState) {
33 | // ...
34 | StrictMode.setThreadPolicy(
35 | new StrictMode.ThreadPolicy.Builder().permitNetwork().build());
36 | downloadImageFromUri("http://...some/image/url");
37 | }
38 |
39 |
40 | private void downloadImageFromUri(String address) {
41 | URL url;
42 | try {
43 | url = new URL(address);
44 | } catch (MalformedURLException e1) {
45 | url = null;
46 | }
47 |
48 | URLConnection conn;
49 | InputStream in;
50 | Bitmap bitmap;
51 | try {
52 | conn = url.openConnection();
53 | conn.connect();
54 | in = conn.getInputStream();
55 | bitmap = BitmapFactory.decodeStream(in);
56 | in.close();
57 | } catch (IOException e) {
58 | bitmap = null;
59 | }
60 |
61 | if (bitmap != null) {
62 | ImageView img = (ImageView) findViewById(R.id.ivBasicImage);
63 | img.setImageBitmap(bitmap);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/chap09_content_providers/ex1_contact_list.txt:
--------------------------------------------------------------------------------
1 | Goal: To access the contact list on the phone.
2 |
3 | Description:
4 | Content providers are used when data needs to be shared between applications. Data in a content provider is represented as a collection of simple tables. In this exercise, we will access the contact list via the Contacts content provider. In order to do this, we must request the READ_CONTACTS permission in AndroidManifest.xml.
5 |
6 | Directions:
7 | 1) Use the Contacts app in the emulator to add several contacts for debugging.
8 | 2) Modify AndroidManifest.xml to request the READ_CONTACTS permission.
9 | 3) Create an Activity with a full screen ListView.
10 | 4) Create an instance variable of type ArrayList to store the contact names.
11 | 5) Initialize the contacts
12 | a) Get a cursor to the contacts table.
13 | b) Iterate through the cursor, setting names into the ArrayList.
14 | 6) Create an ArrayAdapter with the contact names ArrayList.
15 | 7) Add an OnItemClickListener and display the selected contact in a Toast.
16 |
17 |
18 | ## Snippets
19 |
20 | // Manifest
21 |
22 |
23 | // Activity
24 | private void populateListView() {
25 | ArrayAdapter adapter = new ArrayAdapter(this,
26 | android.R.layout.simple_list_item_1, names);
27 |
28 | ListView listView = (ListView) findViewById(R.id.lvContacts);
29 | listView.setAdapter(adapter);
30 | listView.setOnItemClickListener(new OnItemClickListener() {
31 | @Override
32 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
33 | Toast.makeText(ContactListActivity.this, names.get(position), Toast.LENGTH_SHORT).show();
34 | }
35 | });
36 | }
37 |
38 | @SuppressLint("NewApi")
39 | private void loadContacts() {
40 | Uri allContacts = Uri.parse("content://contacts/people");
41 | CursorLoader cursorLoader = new CursorLoader(this, allContacts,
42 | null, // the columns to retrive
43 | null, // the selection criteria
44 | null, // the selection args
45 | null // the sort order
46 | );
47 |
48 | Cursor c = cursorLoader.loadInBackground();
49 | if (c.moveToFirst()) {
50 | do {
51 | // Get Contact ID
52 | int idIndex = c.getColumnIndex(ContactsContract.Contacts._ID);
53 | String contactID = c.getString(idIndex);
54 |
55 | // Get Contact Name
56 | int nameIndex = c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
57 | String contactDisplayName = c.getString(nameIndex);
58 | names.add(contactDisplayName);
59 |
60 | Log.d("debug", contactID + ", " + contactDisplayName);
61 | } while (c.moveToNext());
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/chap07_advanced_views/ex4_progressbar.txt:
--------------------------------------------------------------------------------
1 | Goal: Create a ProgressBar that reflects the progress of some network requests.
2 |
3 | Description:
4 | In this exercise, we will leverage some additional features of the AsyncTask class, notably the ability to report incremental progress. This involves calling the method publishProgress in the doInBackground() method, which triggers a call to onProgressUpdate() method. The reason it must be done like this is that UI updates may not be done in the background thread. The onProgressUpdate() method is called in the main thread.
5 |
6 | Directions:
7 | 1) Create a new Activity with a horizontal ProgressBar, a TextView, and a Submit button.
8 | 2) Create an ArrayList to store the first line of each network response.
9 | 3) Implement a private, inner class called DelayTask.
10 | a) In onPreExecute(), show the hiddent ProgressBar.
11 | b) In doInBackground, download the 4 sites and call publishProgress after each site completes its download.
12 | c) In onProgressUpdate, update the ProgressBar.
13 | d) In onPostExecute, update the TextView with the downloaded responses.
14 |
15 |
16 | ## Snippets
17 |
18 | ProgressBar pb;
19 | TextView tvResult;
20 | ArrayList lines = new ArrayList();
21 |
22 | public void startFourUrlAsync(View v) {
23 | new DelayTask().execute();
24 | }
25 |
26 | public class DelayTask extends AsyncTask {
27 | int count = 0;
28 | @Override
29 | protected void onPreExecute() {
30 | pb.setVisibility(ProgressBar.VISIBLE);
31 | }
32 |
33 | @Override
34 | protected String doInBackground(Void... params) {
35 | String res = loadUrlBody("http://google.com");
36 | lines.add(res.split("\n")[0]);
37 | publishProgress(25);
38 | res = loadUrlBody("http://yahoo.com");
39 | lines.add(res.split("\n")[0]);
40 | publishProgress(50);
41 | res = loadUrlBody("http://twitter.com");
42 | lines.add(res.split("\n")[0]);
43 | publishProgress(75);
44 | res = loadUrlBody("http://facebook.com");
45 | lines.add(res.split("\n")[0]);
46 | publishProgress(100);
47 | return "complete";
48 | }
49 |
50 | @Override
51 | protected void onProgressUpdate(Integer... values) {
52 | pb.setProgress(values[0]);
53 | }
54 |
55 | @Override
56 | protected void onPostExecute(String result) {
57 | Toast.makeText(ProgressBarActivity.this, "Completed!", Toast.LENGTH_SHORT).show();
58 | tvResult.setText(lines.toString());
59 | }
60 |
61 | protected String loadUrlBody(String address) {
62 | HttpClient httpclient = new DefaultHttpClient();
63 | HttpResponse response = null;
64 | String responseString = null;
65 | try {
66 | response = httpclient.execute(new HttpGet(address));
67 | StatusLine statusLine = response.getStatusLine();
68 | if(statusLine.getStatusCode() == HttpStatus.SC_OK){
69 | ByteArrayOutputStream out = new ByteArrayOutputStream();
70 | response.getEntity().writeTo(out);
71 | out.close();
72 | responseString = out.toString();
73 | } else{
74 | response.getEntity().getContent().close();
75 | throw new IOException(statusLine.getReasonPhrase());
76 | }
77 | } catch (ClientProtocolException e) {
78 | // nothing
79 | } catch (IOException e) {
80 | // nothing
81 | }
82 | return responseString;
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------