1. Welcome
Introduction
The Android SDK includes the Android Support Library, which is a collection of several libraries. These libraries provide features that aren't built into the Android framework, including the following:
- Backward-compatible versions of framework components, so that apps running on older versions of the Android platform can support features made available in newer versions of the platform
- Additional layout and user interface elements
- Support for different device form factors, such as TV devices or wearables
- Components to support Material Design elements
- Other features, including palette support, annotations, percentage-based layout dimensions, and preferences
What you should already know
You should be able to:
- Create an Android Studio project.
- Use the layout editor to work with
EditText
andButton
elements. - Build and run your app in Android Studio, on both an emulator and on a device.
- Navigate the Project > Android pane in Android Studio.
- Find the major components of an Android Studio project, including
AndroidManifest.xml
, resources, Java files, and Gradle files.
What you'll learn
- How to verify that the Android Support Library is available in your Android Studio installation.
- How to indicate support library classes in your app.
- How to tell the difference between the values for
compileSdkVersion
,targetSdkVersion
, andminSdkVersion
. - How to recognize deprecated or unavailable APIs in your code.
- More about the Android support libraries.
What you'll do
- Create a new app with one
TextView
and oneButton
. - Verify that the Android Support Repository (containing the Android Support Library) is available in your Android Studio installation.
- Explore the
build.gradle
files for your app project. - Manage class or method calls that are unavailable for the version of Android your app supports.
- Use a compatibility class from the support library to provide backward-compatibility for your app.
2. App overview
In this practical you'll create an app called HelloCompat with one TextView
that displays "Hello World" on the screen, and one Button
that changes the color of the text. There are 20 possible colors, defined as resources in the color.xml
file, and each button click randomly picks one of those colors.
The methods to get a color value from the app's resources have changed with different versions for the Android framework. This example uses the ContextCompat
class in the Android Support Library, which allows you to use a method that works for all versions.
3. Task 1: Set up your project to use support libraries
For this task you'll set up a new project for the HelloCompat app and implement the layout and basic behavior.
1.1 Verify that the Android Support Repository is available
The Android Support Library is downloaded as part of the Android SDK, and available in the Android SDK manager. In Android Studio, you'll use the Android Support Repository—the local repository for the support libraries—to get access to the libraries from within your Gradle build files. In this task you'll verify that the Android Support Repository is downloaded and available for your projects.
- In Android Studio, select Tools > Android > SDK Manager, or click the SDK Manager
icon.
The Android SDK Default Preferences pane appears.
- Click the SDK Tools tab and expand Support Repository, as shown in the figure below.
- Look for Android Support Repository in the list.
If Installed appears in the Status column, you're all set. Click Cancel.
If Not installed or Update Available appears, click the checkbox next to Android Support Repository. A download icon should appear next to the checkbox. Click OK.
- Click OK again, and then Finish when the support repository has been installed.
1.2 Set up the project and examine build.gradle
- Create a new project called HelloCompat.
On the Target Android Devices page, API 15: Android 4.0.3 (IceCreamSandwich) is selected for the minimum SDK. As you've learned in previous lessons, this is the oldest version of the Android platform your app will support.
- Click Next, and choose the Empty Activity template.
- Click Next, and ensure that the Generate Layout file and Backwards Compatibility (App Compat) options are checked. The latter option ensures that your app will be backwards-compatible with previous versions of Android.
- Click Finish.
Explore build.gradle (Module:app)
- In Android Studio, make sure the Project > Android pane is open.
- Expand Gradle Scripts and open the build.gradle (Module: app) file.
Note that build.gradle
for the overall project (build.gradle (Project: helpcompat)
) is a different file from the build.gradle
for the app module. In the build.gradle (Module: app)
file.
- Locate the
compileSdkVersion
line near the top of the file. For example:
compileSdkVersion 26
The compile version is the Android framework version your app is compiled with in Android Studio. For new projects the compile version is the most recent set of framework APIs you have installed. This value affects only Android Studio itself and the warnings or errors you get in Android Studio if you use older or newer APIs.
- Locate the
minSdkVersion
line in thedefaultConfig
section a few lines down.
minSdkVersion 15
The minimum version is the oldest Android API version your app runs under. It's the same number you chose in Step 1 when you created your project. The Google Play store uses this number to make sure that your app can run on a given user's device. Android Studio also uses this number to warn you about using deprecated APIs.
- Locate the
targetSdkVersion
line in thedefaultConfig
section. For example:
targetSdkVersion 26
The target version indicates the API version your app is designed and tested for. If the API of the Android platform is higher than this number (that is, your app is running on a newer device), the platform may enable compatibility behaviors to make sure that your app continues to work the way it was designed to. For example, Android 6.0 (API 23) provides a new runtime permissions model. If your app targets a lower API level, the platform falls back to the older install-time permissions model.
Although the target SDK can be the same number as the compile SDK, it is often a lower number that indicates the most recent version of the API for which you have tested your app.
- Locate the
dependencies
section of build.gradle, near the end of the file. For example:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation
'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation
'com.android.support.test.espresso:espresso-core:3.0.1'
}
The dependencies
section for a new project includes several dependencies to enable testing with Espresso and JUnit, as well as the v7 appcompat support library. The version numbers for these libraries in your project may be different than those shown here.
The v7 appcompat support library provides backward-compatibility for older versions of Android all the way back to API 9. It includes the v4 compat library as well, so you don't need to add both as a dependency.
- Update the version numbers, if necessary.
If the current version number for a library is lower than the currently available library version number, Android Studio highlights the line and warns you that a new version is available ("A newer version of com.android.support:appcompat-v7 is available"). Edit the version number to the updated version.
- Update the
compileSdkVersion
number, if necessary.
The major version number of the support library (the first number) must match your compileSdkVersion
. When you update the support library version, you may also need to update compileSdkVersion
to match.
- Click Sync Now to sync your updated Gradle files with the project, if prompted.
- Install missing SDK platform files, if necessary.
If you update compileSdkVersion
, you may need to install the SDK platform components to match. Click Install missing platform(s) and sync project to start this process.
4. Task 2: Implement the layout and MainActivity
For this task you'll implement the layout and basic behavior for the MainActivity
class.
2.1 Change the layout and colors
In this task you will modify the activity_main.xml
layout for the app.
- Open activity_main.xml in the Project > Android pane.
- Click the Design tab (if it is not already selected) to show the layout editor.
- Select the "Hello World"
TextView
in the layout and open the Attributes pane. - Change the
TextView
attributes as follows:
Attribute field | Enter the following: |
|
|
|
|
| Center the paragraph icon |
|
|
This adds the android:id
attribute to the TextView
with the id
set to hello_textview
, changes the text alignment, makes the text bold, and sets a larger text size of 100sp
.
- Delete the constraint that stretches from the bottom of the
hello_textview
TextView
to the bottom of the layout, so that theTextView
snaps to the top of the layout, and choose 8 (8dp) for the top margin as shown below.
- Drag a
Button
to the bottom of the layout, and add constraints to the left and right sides and bottom of the layout, as shown in the figure below.
- Change the layout_width attribute in the Attributes pane for the
Button
to match_constraint. - Change the other attributes in the Attributes pane for the
Button
as follows:
Attribute field | Enter the following: |
|
|
|
|
The Button
should now appear in the layout as shown below:
- In a previous lesson you learned how to extract a string resource from a literal text string. Click the Text tab to switch to XML code, and extract the
"Hello Text!"
and"Change Color"
strings in theTextView
andButton
, and enter string resource names for them. - Add the following
android:onClick
attribute to theButton
:
android:onClick="changeColor"
- To add colors, expand res and values in the Project > Android pane, and open colors.xml.
- Add the following color resources to the file:
<color name="red">#F44336</color>
<color name="pink">#E91E63</color>
<color name="purple">#9C27B0</color>
<color name="deep_purple">#673AB7</color>
<color name="indigo">#3F51B5</color>
<color name="blue">#2196F3</color>
<color name="light_blue">#03A9F4</color>
<color name="cyan">#00BCD4</color>
<color name="teal">#009688</color>
<color name="green">#4CAF50</color>
<color name="light_green">#8BC34A</color>
<color name="lime">#CDDC39</color>
<color name="yellow">#FFEB3B</color>
<color name="amber">#FFC107</color>
<color name="orange">#FF9800</color>
<color name="deep_orange">#FF5722</color>
<color name="brown">#795548</color>
<color name="grey">#9E9E9E</color>
<color name="blue_grey">#607D8B</color>
<color name="black">#000000</color>
These color values and names come from the recommended color palettes for Android apps defined at Material Design - Style - Color. The codes indicate color RGB values in hexadecimal.
2.2 Add behavior to MainActivity
In this task you'll finish setting up the project by adding private
variables and implementing onCreate()
and onSaveInstanceState()
.
- Open MainActivity.
- Add a
private
variable at the top of the class to hold theTextView
object.
private TextView mHelloTextView;
- Add the following color array just after the private variable:
private String[] mColorArray = {"red", "pink", "purple", "deep_purple",
"indigo", "blue", "light_blue", "cyan", "teal", "green",
"light_green", "lime", "yellow", "amber", "orange", "deep_orange",
"brown", "grey", "blue_grey", "black" };
Each color name corresponds to the name of a color resource in color.xml
.
- In the
onCreate()
method, usefindViewById()
to get a reference to theTextView
instance and assign it to that private variable:
mHelloTextView = findViewById(R.id.hello_textview);
- Also in
onCreate()
, restore the saved instance state, if any:
// restore saved instance state (the text color)
if (savedInstanceState != null) {
mHelloTextView.setTextColor(savedInstanceState.getInt("color"));
}
- Add the
onSaveInstanceState()
method toMainActivity
to save the text color:
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// save the current text color
outState.putInt("color", mHelloTextView.getCurrentTextColor());
}
Task 2 solution code
The following is the solution code for the XML layout and a code snippet in the MainActivity
class for the HelloCompat app so far.
XML layout
The XML layout for the activity_main.xml
file is shown below. The changeColor
click handler for the android:onClick
attribute for the Button
is underlined in red because it hasn't yet been defined. You define it in the next task.
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.android.myapplication.MainActivity">
<TextView
android:id="@+id/hello_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/hello_world"
android:textAlignment="center"
android:textSize="100sp"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/color_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="@string/change_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:onClick="changeColor"/>
</android.support.constraint.ConstraintLayout>
MainActivity
The MainActivity
class includes the following private
variables at the top of the class:
// Text view for Hello World.
private TextView mHelloTextView;
// array of color names, these match the color resources in color.xml
private String[] mColorArray = {"red", "pink", "purple", "deep_purple",
"indigo", "blue", "light_blue", "cyan", "teal", "green",
"light_green", "lime", "yellow", "amber", "orange", "deep_orange",
"brown", "grey", "blue_grey", "black" };
The MainActivity
class includes the following onCreate()
and onSaveInstanceState()
methods:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHelloTextView = findViewById(R.id.hello_textview);
// restore saved instance state (the text color)
if (savedInstanceState != null) {
mHelloTextView.setTextColor(savedInstanceState.getInt("color"));
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// save the current text color
outState.putInt("color", mHelloTextView.getCurrentTextColor());
}
5. Task 3: Implement Button behavior
The Change Color button in the HelloCompat app picks one of the 20 colors from the color.xml
resource file at random and sets the color of the text to that color. In this task you'll implement the behavior for the Button
click handler.
2.1 Add the changeButton() click handler
- Open activity_main.xml, if it is not already open. Click the Text tab to show the XML code.
- Click on
"changeColor"
in theandroid:onClick
attribute inside theButton
element. - Press
Alt+Enter
(Option+Enter
on a Mac), and select Create onClick event handler. - Choose MainActivity and click OK.
This creates a placeholder method stub for the changeColor()
method in MainActivity
:
public void changeColor(View view) {
}
2.2 Implement the Button action
- Switch to MainActivity.
- In the
changeColor()
method, create a random number object by using theRandom
class (a Java class) to generate simple random numbers.
Random random = new Random();
- Use the
random
instance to pick a random color from themColorArray
array:
String colorName = mColorArray[random.nextInt(20)];
The nextInt()
method with the argument 20 gets another random integer between 0 and 19. You use that integer as the index of the array to get a color name.
- Get the resource identifier (an integer) for the color name from the resources:
int colorResourceName = getResources().getIdentifier(colorName,
"color", getApplicationContext().getPackageName());
When your app is compiled, the Android system converts the definitions in your XML files into resources with internal integer IDs. There are separate IDs for both the names and the values. This line matches the color strings from the colorName
array with the corresponding color name IDs in the XML resource file. The getResources()
method gets all the resources for your app. The getIdentifier()
method looks up the color name (the string) in the color resources ("color"
) for the current package name.
- Get the integer ID for the actual color from the resources and assign it to a
colorRes
variable, and use thegetTheme()
method to get the theme for the current application context.
int colorRes =
getResources().getColor(colorResourceName, this.getTheme());
The getResources()
method gets the set of resources for your app, and the getColor()
method retrieves a specific color from those resources by the ID of the color name. However, getColor()
has a red underlined highlight.
If you point at getColor()
, Android Studio reports: "Call requires API 23 (current min is 15)". Because your minSdkVersion
is 15, you get this message if you try to use any APIs that were introduced after API 15. You can still compile your app, but because this version of getColor()
is not available on devices prior to API 23, your app will crash when the user taps the Change Color button.
At this stage you could check for the platform version and use the right version of getColor()
depending on where the app is running. A better way to support both older and newer Android APIs without warnings is to use one of the compatibility classes in the support library.
- Change the
colorRes
assignment line to use theContextCompat
class:
int colorRes = ContextCompat.getColor(this, colorResourceName);
ContextCompat
provides many compatibility methods to address API differences in the application context and app resources. The getColor()
method in ContextCompat
takes two arguments: the current context (here, the Activity
instance, this
), and the name of the color.
The implementation of this method in the support library hides the implementation differences in different versions of the API. You can call this method regardless of your compile SDK or minimum SDK versions with no warnings, errors, or crashes.
- Set the color of the
TextView
to the color resource ID:
mHelloTextView.setTextColor(colorRes);
- Run the app on a device or emulator, and click the Change Color
Button
.
The Change Color Button
should now change the color of the text in the app, as shown below.
6. Solution code
MainActivity solution
The following is the changeColor()
click handler in MainActivity
:
/**
* This method handles the click of the Change Color button by
* picking a random color from a color array.
*
* @param view The view that was clicked
*/
public void changeColor(View view) {
// Get a random color name from the color array (20 colors).
Random random = new Random();
String colorName = mColorArray[random.nextInt(20)];
// Get the color identifier that matches the color name.
int colorResourceName = getResources().getIdentifier(colorName,
"color", getApplicationContext().getPackageName());
// Get the color ID from the resources.
int colorRes = ContextCompat.getColor(this, colorResourceName);
// Set the text color.
mHelloTextView.setTextColor(colorRes);
}
Android Studio project
Android Studio project: HelloCompat
7. Coding challenge
Challenge: Rather than using ContextCompat to
get the color resource, use a test of the values in the Build
class to perform a different operation if the app is running on a device that supports a version of Android older than API 23.
8. Summary
Installing the Android Support Library:
- Use the SDK Manager to install the Android Support Repository. Choose Tools > Android > SDK Manager, click the SDK Tools tab, and expand Support Repository.
- If Installed appears in the Status column for Android Support Repository, click Cancel; if Not installed or Update Available appears, click the checkbox. A download icon should appear next to the checkbox. Click OK.
Android uses three directives to indicate how your app should behave for different API versions:
minSdkVersion
: the minimum API version your app supports.compileSdkVersion
: the API version your app should be compiled with.targetSdkVersion
: the API version your app was designed for.
To manage dependencies in your project:
- Expand Gradle Scripts in the Project > Android pane, and open the build.gradle (Module: app) file.
- You can add dependencies in the
dependencies
section.
The ContextCompat
class provides methods for compatibility with context and resource-related methods for both old and new API levels.
9. Related concept
The related concept documentation is in 3.3: The Android Support Library.
10. Learn more
Android Studio documentation:
Android developer documentation:
- Android Support Library (introduction)
- Support Library Setup
- Support Library Features
- Supporting Different Platform Versions
- Package Index (all API packages that start with android.support)
Other:
11. Homework
This section lists possible homework assignments for students who are working through this codelab as part of a course led by an instructor. It's up to the instructor to do the following:
- Assign homework if required.
- Communicate to students how to submit homework assignments.
- Grade the homework assignments.
Instructors can use these suggestions as little or as much as they want, and should feel free to assign any other homework they feel is appropriate.
If you're working through this codelab on your own, feel free to use these homework assignments to test your knowledge.
Run an app
Open the HelloCompat app you created in the practical on using support libraries.
- Set a debugger breakpoint on the line in the
changeColor()
method that actually changes the color:
int colorRes = ContextCompat.getColor(this, colorResourceName);
- Run the app in debug mode on a device or emulator that's running an API version 23 or newer. Click Step Into to step into the
getColor()
method and follow the method calls deeper into the stack. Examine how theContextCompat
class determines how to get the color from the resources, and which other framework classes it uses.
Some classes may produce a warning that the "source code does not match the bytecode." Click Step Out to return to a known source file, or keep clicking Step Into until the debugger returns on its own.
- Repeat the previous step for a device or emulator running an API version older than 23. Note the different paths that the framework takes to accomplish getting the color.
Answer these questions
Question 1
Which class appears when you first Step Into the ContextCompat.getColor()
method? Choose one:
MainActivity
ContextCompat
AppCompatActivity
Context
Question 2
In the class that appears, which statement is executed if the build version is API version 23 or newer? Choose one:
return context.getColor(id);
return context.getResources().getColor(id);
throw new IllegalArgumentException("permission is null");
return mResources == null ? super.getResources() : mResources;
Question 3
If you change the ContextCompat.getColor()
method back to the getColor()
method, what will happen when you run the app? Choose one:
- If your
minSdkVersion
is 15, the wordgetColor
is underlined in red in the code editor. Hover your pointer over it, and Android Studio reports "Call requires API 23 (current min is 15)". - The app will run without error on emulators and devices using API 23 or newer.
- The app will crash when the user taps Change Color if the emulator or device is using API 17.
- All of the above.
Submit your app for grading
Guidance for graders
No app to submit for this homework assignment.
12. Next codelab
To find the next practical codelab in the Android Developer Fundamentals (V2) course, see Codelabs for Android Developer Fundamentals (V2).
For an overview of the course, including links to the concept chapters, apps, and slides, see Android Developer Fundamentals (Version 2).