Download XAAndroid4SecondProjectEchoingNew

Document related concepts
no text concepts found
Transcript
Android 4: Second Project,
Echoing
Kirk Scott
1
2
Introduction
• This is another set of overheads which is
largely based on the online tutorials
• Where the tutorials cover everything clearly, I
just go with what Google says
• However, there are some significant additions,
plus, where the tutorials occasionally refer
you elsewhere for more information, I go
there and included that information in the
flow of the presentation
3
Outline
• 4.1 Building the User Interface for an Echoing
Type App
• 4.2 R.java
• 4.3 Activities
• 4.4 Creating an Activity that Responds to a
Button Click
• 4.5 Code Review
4
4.1 Building the User Interface for an
Echoing Type App
5
Building a Simple User Interface
• In this lesson, you create a layout in XML that
includes a text field and a button.
• In the next lesson, your app responds when
the button is pressed by sending the content
of the text field to another activity.
6
• Commentary:
• In other words, the tutorial is going to go
through the steps of building an echoing type
program
• The user enters a string
• The user clicks a button to “send” the string to
another part of the app
• The “other part of the app” displays the string
that was entered
7
• Accomplishing this can divided into two
logically separate steps:
• Build the interface for the first part of the app,
where the user can enter a string and click a
button
• Build the functionality for sending the string
and displaying it in the second part of the app
8
• This part of the tutorial focuses on the first
half of the problem
• An important point is that the user’s input is
not a hardcoded string
• It becomes necessary to refer to that string as
a variable in the code
• The simple user interface to be developed is
shown on the following overhead
9
10
• The graphical user interface for an Android
app is built using a hierarchy of View and
ViewGroup objects.
• View objects are usually UI widgets such as
buttons or text fields.
• ViewGroup objects are invisible view
containers that define how the child views are
laid out, such as in a grid or a vertical list.
11
• Android provides an XML vocabulary that
corresponds to the subclasses of View and
ViewGroup so you can define your UI in XML
using a hierarchy of UI elements.
• Layouts are subclasses of the ViewGroup. In
this exercise, you'll work with a LinearLayout.
• [See the diagram on the following overhead.]
12
13
Alternative Layouts
• Declaring your UI layout in XML rather than
runtime code is useful for several reasons, but it's
especially important so you can create different
layouts for different screen sizes.
• For example, you can create two versions of a
layout and tell the system to use one on "small"
screens and the other on "large" screens.
• For more information, see the class about
Supporting Different Devices.
14
Commentary: The Starting Point for
this Discussion
• The tutorials don’t back up and show this, but
it’s useful
• The contents of the layout file as it currently
exists are shown on the following overhead
• Notice that this file defines a relative layout
• Notice also that it contains a TextView
• This is the “widget” that contains the text that
is shown by the app
15
•
<?xml version="1.0" encoding="utf-8"?>
<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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.kascott.myapplication.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</RelativeLayout>
16
Create a Linear Layout
• From the res/layout/ directory, open the
activity_main.xml file.
• This XML file defines the layout of your activity. It
contains the default "Hello World" text view.
• When you open a layout file, you’re first shown
the design editor in the Layout Editor.
• For this lesson, you work directly with the XML,
so click the Text tab to switch to the text editor.
• Replace the contents of the file with the following
XML:
17
•
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:orientation="horizontal">
</LinearLayout>
18
• LinearLayout is a view group (a subclass of
ViewGroup) that lays out child views in either a
vertical or horizontal orientation, as specified by
the android:orientation attribute.
• Each child of a LinearLayout appears on the
screen in the order in which it appears in the
XML.
• Two other attributes, android:layout_width and
android:layout_height, are required for all views
in order to specify their size.
19
• Because the LinearLayout is the root view in
the layout, it should fill the entire screen area
that's available to the app by setting the width
and height to "match_parent".
• This value declares that the view should
expand its width or height to match the width
or height of the parent view.
• For more information about layout properties,
see the Layout guide.
20
Commentary
• So at this point, you’ve changed the layout
• Plus you’ve eliminated the TextView
• Using different machinery for displaying the
app text is an integral part of this example
21
Add a Text Field
• In the activity_main.xml file, within the
<LinearLayout> element, add the following
<EditText> element:
22
•
<LinearLayout
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:orientation="horizontal">
<EditText android:id="@+id/edit_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/edit_message" />
</LinearLayout>
23
Here is a description of the attributes
in the <EditText> you added:
• android:id
• android:id="@+id/edit_message"
• This provides a unique identifier for the view,
which you can use to reference the object from
your app code, such as to read and manipulate
the object (you'll see this in the next lesson).
• The at sign (@) is required when you're referring
to any resource object from XML.
24
• It is followed by the resource type (id in this
case), a slash, then the resource name
(edit_message).
• The plus sign (+) before the resource type is
needed only when you're defining a resource
ID for the first time.
25
• When you compile the app, the SDK tools use
the ID name to create a new resource ID in
your project's gen/R.java file that refers to the
EditText element.
• With the resource ID declared once this way,
other references to the ID do not need the
plus sign.
26
• Using the plus sign is necessary only when
specifying a new resource ID and not needed
for concrete resources such as strings or
layouts.
• See the sidebox for more information about
resource objects.
• Commentary: I will do the sidebar at the end
of this “lesson” with additional explanations
about R.java
27
• android:layout_width and android:layout_height
• android:layout_width="wrap_content"
android:layout_height="wrap_content"
• Instead of using specific sizes for the width and height,
the "wrap_content" value specifies that the view
should be only as big as needed to fit the contents of
the view.
• If you were to instead use "match_parent", then the
EditText element would fill the screen, because it
would match the size of the parent LinearLayout.
28
• For more information, see the Layouts guide.
• Commentary:
• It’s not necessary to look at the Layouts guide this
early in the game
• For now, just follow the example given
• In general, you don’t have to study XML explicitly
• Follow the examples and extrapolate from there
• When the time comes, use the graphical
development tool, and then adapt the XML that it
generates
29
• android:hint
• android:hint="@string/edit_message"
• This is a default string to display when the text field is
empty.
• Instead of using a hard-coded string as the value, the
"@string/edit_message" value refers to a string
resource defined in a separate file.
• Because this refers to a concrete resource (not just an
identifier), it does not need the plus sign.
30
• However, because you haven't defined the string
resource yet, you’ll see a compiler error at first.
• You'll fix this in the next section by defining the
string.
• Commentary:
• This is an important point that we’ll see more of
as we go
• Because elements of an Android app are stored in
separate files, the system will show errors until all
of the files have been made consistent
31
• Note: This string resource has the same name as the
element ID: edit_message.
• android:id="@+id/edit_message"
• android:hint="@string/edit_message"
• However, references to resources are always scoped by
the resource type (such as id or string), so using the
same name does not cause collisions.
32
• Commentary:
• What the tutorials say is true: You can have
resources of different types with the same name
• On the other hand, this might not be the best
practice because it can be confusing
• Although it might be redundant, it might be
clearer to use naming conventions like this:
• edit_message_id
• edit_message_hint
33
Add String Resources
• By default, your Android project includes a
string resource file at res/values/strings.xml.
Here, you'll add two new strings.
• From the res/values/ directory, open
strings.xml.
• Add two strings so that your file looks like this:
34
•
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My First App</string>
<string name="edit_message">Enter a message</string>
<string name="button_send">Send</string>
</resources>
• Commentary:
• Remember, this is the tutorial’s code
• “edit_message” is the hardcoded string that will be displayed
to the user
• It is not the variable that refers to the string that the user will
enter
35
• For text in the user interface, always specify each string
as a resource.
• String resources allow you to manage all UI text in a
single location, which makes the text easier to find and
update.
• Externalizing the strings also allows you to localize your
app to different languages by providing alternative
definitions for each string resource.
• For more information about using string resources to
localize your app for other languages, see the
Supporting Different Devices class.
36
Add a Button
• Go back to the activity_main.xml file and add
a button after the <EditText>.
• Your file should look like this:
• [See the following overhead.]
37
• <LinearLayout
xmlns:android="http://schemas.android.com/apk/
res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText android:id="@+id/edit_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/edit_message" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_send" />
</LinearLayout>
38
• Note: This button doesn't need the android:id
attribute, because it won't be referenced from
the activity code.
• The layout is currently designed so that both
the EditText and Button widgets are only as
big as necessary to fit their content, as figure 2
shows.
• [See the following overhead.]
39
40
• This works fine for the button, but not as well
for the text field, because the user might type
something longer.
• It would be nice to fill the unused screen
width with the text field.
• You can do this inside a LinearLayout with the
weight property, which you can specify using
the android:layout_weight attribute.
41
• The weight value is a number that specifies
the amount of remaining space each view
should consume, relative to the amount
consumed by sibling views.
• This works kind of like the amount of
ingredients in a drink recipe:
• "2 parts soda, 1 part syrup" means two-thirds
of the drink is soda.
42
• For example, if you give one view a weight of
2 and another one a weight of 1, the sum is 3,
so the first view fills 2/3 of the remaining
space and the second view fills the rest.
• If you add a third view and give it a weight of
1, then the first view (with weight of 2) now
gets 1/2 the remaining space, while the
remaining two each get 1/4.
43
• The default weight for all views is 0, so if you
specify any weight value greater than 0 to only
one view, then that view fills whatever space
remains after all views are given the space
they require.
44
• In activity_main.xml, modify the <EditText> so
that the attributes look like this:
45
• <EditText android:id="@+id/edit_message"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/edit_message" />
46
• Setting the width to zero (0dp) improves
layout performance because using
"wrap_content" as the width requires the
system to calculate a width that is ultimately
irrelevant because the weight value requires
another width calculation to fill the remaining
space.
• [See the changed layout on the following
overhead.]
47
48
• Here’s how your complete
activity_main.xmllayout file should now look:
49
• <?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/
android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText android:id="@+id/edit_message"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/edit_message" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_send" />
</LinearLayout>
50
Run Your App
• This layout is applied by the default Activity
class that the SDK tools generated when you
created the project.
• To run the app and see the results, click Run
'app' in the toolbar.
• Continue to the next lesson to learn how to
respond to button presses, read content from
the text field, start another activity, and more.
51
4.2 R.java
52
• The first two overheads are the contents of
the sidebar on resources in the tutorial
• The sidebar refers to another part of the
tutorials
• Instead of going there, the rest of this section
is just a freelance discussion of R.java
53
Resource Objects
• A resource object is a unique integer name
that's associated with an app resource, such
as a bitmap, layout file, or string.
• Every resource has a corresponding resource
object defined in your project's gen/R.java file.
• You can use the object names in the R class to
refer to your resources, such as when you
need to specify a string value for the
android:hint attribute.
54
• You can also create arbitrary resource IDs that
you associate with a view using the android:id
attribute, which allows you to reference that
view from other code.
• The SDK tools generate the R.java file each
time you compile your app.
• You should never modify this file by hand.
• For more information, read the guide to
Providing Resources.
55
Commentary
• The remainder of this section is commentary
• There is no ideal order of presentation of the
material for any topic in computer science…
• The problem always is, to do X, you need Y,
and vice-versa, to do Y, you need X
• On the one hand, this section is a diversion in
the tutorial’s flow of making the new, echoing
application
56
• On the other hand, in the foregoing material the
gen/R.java file was mentioned
• The R.java file is so important, that it deserves
some attention early on
• Plus, it turns out that even finding the R. java file
is not intuitive
• In other words, this topic is related to the earlier
overhead files where the Android Studio
development environment was introduced
57
• Pursuing this now is not a complete diversion
for the following reasons:
• 1. When we look at the second half of the
application, that is where the code will make
reference to the variable for the input string
• In other words, part of the glue between the
first part of the app and the second half of the
app is the id which is stored in R.java
58
• 2. It was already pointed out that because
elements of an app are divided into different
files, errors will be generated until the files are
made consistent
• This means that some of the most critical
errors may end up being reflected as problems
with the system generated file, R.java
59
Finding R.java in the Android Studio
Interface
• The first thing to note about R.java is that it’s
system generated and should not be edited or
modified by the programmer
• For that reason, it is buried in the interface
• This makes a certain amount of sense
• But a programmer who wants to know what’s
really going on needs to be aware of it, and for
many people “being aware” means seeing it
with your own eyes
60
• Being able to see R.java goes back to the
Android Studio Interface
• A screenshot is given on the following
overhead
• The important thing to notice is that the
explorer window is set to “Android”
61
62
• You want to go to the drop down menu, as
shown on the following overhead:
63
64
• If you take the “Project” option, you can
follow the path shown in order to arrive at
R.java
• The R.java file that is shown on the following
overhead belongs to the original app, before
changing the interface and introducing an id
for the project
65
66
• If you add the id as directed in the lesson and
then build and run the project as it stands,
you can return to the R.java file
• If you scroll down through the many system
supplied components that are automatically
defined you will eventually reach the class
named id
67
• If you scroll down through the id class, you
will eventually find the line highlighted on the
following overhead
• This is the internal definition of the
edit_message id
• You will not refer to this element of your app
by its numeric value, but this shows you the
actual system supplied identifier that belongs
to the id that you declared in your code
68
•
•
•
•
public static final class id {
public static final int action0=0x7f0b0055;
public static final int action_bar=0x7f0b0045;
public static final int
action_bar_activity_content=0x7f0b0000;
public static final int action_bar_container=0x7f0b0044;
public static final int action_bar_root=0x7f0b0040;
…
public static final int customPanel=0x7f0b0039;
public static final int decor_content_parent=0x7f0b0043;
public static final int default_activity_button=0x7f0b002a;
public static final int disableHome=0x7f0b000c;
public static final int edit_message=0x7f0b0054;
…
69
• At this point it is sufficient to simply
understand R.java as Grand Central Station, or
alternatively, The Glue, that holds together
the various parts of an app that are declared
in different files belonging to the code
• With this simple explanation of R, it is possible
to go back to the code for the app, which was
shown earlier, and consider what it means
70
71
• Here the code is, without the distractions of
the development environment
72
•
package com.example.kascott.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
73
• You are capable of reading this, in outline
form
• MainActivity is the class containing the app
• It extends AppCompatActivity
• It is a subclass of AppCompatActivity and
inherits methods from it
74
• MainActivity contains a single method, onCreate()
• protected void onCreate(Bundle
savedInstanceState)
• For a programmer just graduating from beginning Java,
this is the moral equivalent of a main() method
• And just like main(), onCreate() receives a parameter
which is supplied at runtime, savedInstantState
• The meaning of Bundles will be taken up in a future set
of notes
75
• Now the fun begins:
• The first thing that happens in onCreate() is a call to
super.onCreate()
• super.onCreate(savedInstanceState);
• In doing onCreate() for a programmer defined app, you get
to rely on all of the groundwork laid by the system
programmers
• It is perfectly logical that the parameter that was passed in
to onCreate() should be passed up in the call to
super.onCreate()
76
• And now comes a the only other line of code:
• setContentView(R.layout.activity_
main);
• In practice, this says that the code so far simply
displays the contents defined in the app layout
• What is significant is that the parameter that is
passed as the contents to be viewed is something
that exists in R
77
• We have been talking about R.java, and
onCreate() does not refer to R.java directly
• This is what you can deduce from the code:
• Not only does the system create things like id’s in
R.java
• When the application is built and run, the layout
defined by the programmer in XML is converted
into a resource which can then be referred to in
the Java code of the app
• This resource is created in R
78
• I repeat, this discussion breaks the flow of
showing the new app under development in
the tutorials
• But it’s not too soon to start trying to see the
big picture
• There are shortcomings to the tutorial
approach to just leading you by the nose
79
4.3 Activities
80
• The last slide of information taken from the
tutorials, given above, contained a link to
Activity
• This is a link to the Android API
documentation
• It is necessary to understand what an activity
is in order to fully understand how apps work
81
• The next section will cover the changes
necessary in order for the second half of the
app to respond to a button click in the user
interface of the first half of the app
• By way of introduction, the beginning portion
of the API documentation of the Activity class
will be presented next
• The full documentation will be covered in the
next set of overheads
82
• Activity
• public class Activity
extends ContextThemeWrapper implements
LayoutInflater.Factory2, Window.Callback,
KeyEvent.Callback,
View.OnCreateContextMenuListener,
ComponentCallbacks2
83
java.lang.Object
↳
android.content.Context
↳
android.content.ContextWrapper
↳
android.view.ContextTheme
Wrapper
↳
android.app.
Activity
84
Known Indirect Subclasses ActionBarActivity, AppCompatActivity, LauncherActivity,
PreferenceActivity, TabActivity
Known Direct Subclasses AccountAuthenticatorActivity, ActivityGroup, AliasActivity,
ExpandableListActivity, FragmentActivity, ListActivity, NativeActivity
85
• An activity is a single, focused thing that the user
can do.
• Almost all activities interact with the user, so the
Activity class takes care of creating a window for
you in which you can place your UI with
setContentView(View).
• While activities are often presented to the user as
full-screen windows, they can also be used in
other ways: as floating windows (via a theme
with windowIsFloating set) or embedded inside
of another activity (using ActivityGroup).
86
• There are two methods almost all subclasses
of Activity will implement:
• onCreate(Bundle) is where you initialize your
activity.
• Most importantly, here you will usually call
setContentView(int) with a layout resource
defining your UI, and using findViewById(int)
to retrieve the widgets in that UI that you
need to interact with programmatically.
87
• onPause() is where you deal with the user
leaving your activity.
• Most importantly, any changes made by the
user should at this point be committed
(usually to the ContentProvider holding the
data).
• [Comment: The reality is, as seen from the
example already, that you may not explicitly
code for the onPause() case.]
88
• To be of use with Context.startActivity(), all
activity classes must have a corresponding
<activity> declaration in their package's
AndroidManifest.xml.
• [This is the end of the beginning part of the
API on the Activity class.]
89
Commentary
• The manifest file was noted in an earlier set of
overheads
• Until we start doing something fancy, we can
rely on default creation of the manifest file
• The following overhead shows the contents of
the manifest file so far
90
•
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.kascott.myapplication">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
91
• In the structure of the app as described in the
XML, you can see that the app contains a main
activity
• You will also notice that the keyword “intent”
appears, which will become significant
• At this point we don’t need a deeper
understanding
92
• We’re still getting used to the idea that a complete app
is specified in multiple files with multiple purposes
• An app may have multiple pieces of runnable Java code
• The pieces of an app, at a high level, are activities
• The manifest file specifies the activities
• Additionally, an app has resources like layouts and
strings
• And when the app is compiled, various components
that glue the app together are generated in the R.java
file
93
4.4 Creating an Activity that Responds
to a Button Click
94
Starting Another Activity
• After completing the previous lesson, you
have an app that shows an activity (a single
screen) with a text field and a button.
• In this lesson, you’ll add some code to
MainActivity that starts a new activity when
the user clicks the Send button.
95
Commentary
• Once again, the tutorials lead you by the nose,
when it might be helpful to have a quick
overview first
• The keyword sendMessage and a method
named sendMessage() will be used in order to
make the button in the app responsive to
clicks
96
• Responsiveness to clicks is inherent in a
button
• The system will call the sendMessage()
method when the button is clicked
• The body of the sendMessage() method
implements the functionality that is to be
executed when the button is clicked
• In this example, a new activity will be started
which displays the input string
97
• In the code you write to accomplish this, you
will make specific reference to the R.java file
• Referring to the R.java file and finding an
element of the code by id are critical aspects
of developing in Android (which deserve
emphasis)
98
Respond to the Send Button
• 1. In the file res/layout/activity_main.xml, add the android:onClick
attribute to the <Button> element as shown below:
• <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_send"
android:onClick="sendMessage" />
• This attribute tells the system to call the sendMessage() method in
your activity whenever a user clicks on the button.
99
• 2. In the file
java/com.example.myfirstapp/MainActivity.java, add
the sendMessage() method stub as shown below:
100
•
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/** Called when the user clicks the Send button */
•
public void sendMessage(View view) {
// Do something in response to button
}
}
101
• In order for the system to match this method to the
method name given to android:onClick, the signature
must be exactly as shown.
• Specifically, the method must:
– Be public
– Have a void return value
– Have a View as the only parameter (this will be the View
that was clicked)
• Commentary: Note the last statement well: A
reference to the button is automatically sent as a
parameter to the method that is called when the
button is clicked
102
• Next, you’ll fill in this method to read the
contents of the text field and deliver that text
to another activity.
103
Build an Intent
• An Intent is an object that provides runtime
binding between separate components (such as
two activities).
• The Intent represents an app’s "intent to do
something."
• You can use intents for a wide variety of tasks,
but in this lesson, your intent starts another
activity.
• In MainActivity.java, add the code shown below
to sendMessage():
104
•
public class MainActivity extends AppCompatActivity {
public final static String EXTRA_MESSAGE =
"com.example.myfirstapp.MESSAGE";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/** Called when the user clicks the Send button */
public void sendMessage(View view) {
Intent intent = new Intent(this, DisplayMessageActivity.class);
EditText editText = (EditText) findViewById(R.id.edit_message);
String message = editText.getText().toString();
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
}
}
105
• Note: Android Studio will display Cannot
resolve symbol errors because the code
references classes like Intent and EditText that
have not been imported.
• To import these classes, you can either 1) use
Android Studio's "import class" functionality
by pressing Alt + Enter (Option + Return on
Mac) or 2) manually add import statements at
the top of the file.
106
• Comment:
• To make the key combination work, highlight
the name of the missing class in the code file
and then press Alt + Enter
• A little pop-up menu will appear with the
option to import the class
• Comment Mode Off
107
• Comment:
• The tutorials mention this later, but it’s the
first bit of new code
• Don’t overlook it
•
public final static String EXTRA_MESSAGE =
"com.example.myfirstapp.MESSAGE";
• At the top of the method, you’re creating a
constant string for use in a call later on
108
• There’s a lot going on in sendMessage(), so let’s explain
what's going on.
• The Intent constructor takes two parameters:
• 1. A Context as its first parameter (this is used because
the Activity class is a subclass of Context)
• 2. The Class of the app component to which the
system should deliver the Intent (in this case, the
activity that should be started).
• Note: The reference to DisplayMessageActivity will
raise an error in Android Studio because the class
doesn’t exist yet.
• Ignore the error for now; you’ll create the class soon.
109
Commentary
• This is quite phenomenal
• The tutorials skip over these two lines of code
without explaining them
•
EditText editText = (EditText)
findViewById(R.id.edit_message);
String message = editText.getText().toString();
110
• The first line of these lines of code illustrates
what you have to do in order to get a Java
reference to the editable text field you
declared in your app code base
• Working from the inside out, you need to
know the form of the name it is given in R.java
• You need to call the method findViewById(),
passing the R.java name as a parameter
111
• And you need to know that the thing you’re
trying to get access to is an EditText object, so
that you can cast the returned View to that type
• The second line of code is conceptually simpler
• You call getText() on the reference and call
toString() on the result of that in order to acquire
the text string that is currently in the editText
view
• Comment Mode Off
112
• The putExtra() method adds the EditText's value
to the intent.
• An Intent can carry data types as key-value pairs
called extras.
• Your key is a public constant EXTRA_MESSAGE
because the next activity uses the key to retrieve
the text value.
• It's a good practice to define keys for intent extras
using your app's package name as a prefix.
• This ensures the keys are unique, in case your
app interacts with other apps.
113
• The startActivity() method starts an instance
of the DisplayMessageActivity specified by the
Intent.
• Now you need to create the class.
114
Commentary
• This is the summary of the foregoing:
• You acquired a reference to the edit text field
• You got the text string it contained
115
• In the following two lines of code, you create an intent
containing the text string
• You call startActivity() on “this”, passing the intent as
the parameter
•
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
• Activities and intents go together
• The new activity will find out what it needs to know by
checking the contents of the intent
• Comment Mode Off
116
Create the Second Activity
• 1. In the Project window, right-click the app
folder and select New > Activity > Empty
Activity.
• 2. In the Configure Activity window, enter
"DisplayMessageActivity" for Activity Name
and click Finish
117
Comment
• Throughout these overheads, what the tutorials
mean by “Project window” is what I’ve referred
to as the explorer
• In other words, if you click on “Project” in the left
hand margin, the “explorer” window is opened
on the left hand side of the screen
• This is the Project window, which shows you the
folders and files associated with the project
• See the following overhead
118
119
• Following this procedure for creating the new
activity is the analog to creating the new,
empty app at the very beginning
• Creating the new app created the main
activity
• Now you’re creating an additional activity
belonging to the app
• Comment Mode Off
120
• Android Studio automatically does three
things:
• Creates the class DisplayMessageActivity.java
with an implementation of the required
onCreate() method.
• Creates the corresponding layout file
activity_display_message.xml
• Adds the required <activity> element in
AndroidManifest.xml.
121
Comment
• When you do this, the system creates the java
file for the activity and the editor window
opens to that
• The various files appear in their respective
places in the explorer
• The editor window is shown on the following
overhead
• Then the tutorial material continues
• Comment Mode Off
122
123
• If you run the app and click the Send button
on the first activity, the second activity starts
but is empty.
• This is because the second activity uses the
default empty layout provided by the
template.
124
Comment
• It’s worth taking a moment to consider just how far we’ve
come
• The original layout has a button
• Clicking the button triggers sendMessage(), which creates
the new activity
• The app is runnable now—there are no missing files or
pieces—except for the logic
• The remaining element is making the second activity do
something
• The next two overheads show what the app does at this
point
• After that the tutorial material continues
125
The first activity runs fine. I can enter any message I want to in
the EditText area. Clicking the SEND button is functional
126
Clicking the SEND button causes the second activity to run. It is shown on the
device screen, replacing the interface for the main activity. But the second
activity does not yet contain any functionality. Nothing else happens
127
Display the Message
• Now you will modify the second activity to
display the message that was passed by the
first activity.
• 1. In DisplayMessageActivity.java, add the
following code to the onCreate() method:
128
•
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_message);
Intent intent = getIntent();
String message =
intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
TextView textView = new TextView(this);
textView.setTextSize(40);
textView.setText(message);
ViewGroup layout = (ViewGroup)
findViewById(R.id.activity_display_message);
layout.addView(textView);
}
129
• 2. Press Alt + Enter (option + return on Mac)
to import missing classes.
• Comment: Remember, highlight the missing
class name in the code, then press Alt + Enter
in order to get the pop-up menu with the
import option
130
• There’s a lot going on here, so let’s explain:
• 1. The call getIntent() grabs the intent that
started the activity.
• Every Activity is invoked by an Intent,
regardless of how the user navigated there.
• The call getStringExtra() retrieves the data
from the first activity.
131
• 2. You programmatically create a TextView
and set its size and message.
• 3. You add the TextView to the layout
identified by R.id.activity_display_message.
• You cast the layout to ViewGroup because it is
the superclass of all layouts and contains the
addView() method.
132
Commentary
• The tutorial’s description is OK as far as it goes
• But I think two elements of the code deserve
further emphasis
• They are the two places where the code refers
to R
133
• At the beginning of the onCreate() method for the new
activity, immediately after the call to super.onCreate(), you
have this call:
•
setContentView(R.layout.activity_display_message);
• You are making use of the name in R of the layout for the
activity in order to set the content view of the activity
• This is analogous to what happened with the main activity
• Note that you do this with a parameter that is simply a name
in R
134
• Then at the end of the onCreate() method for the
new activity, you do this:
•
ViewGroup layout = (ViewGroup)
findViewById(R.id.activity_display_message);
layout.addView(textView);
• This time you need to call findViewById() in order
to get a reference to the layout
• Then you can call add the newly created text view
to the layout for the new activity
• Comment Mode Off
135
• Note: The XML layout generated by previous
versions of Android Studio might not include the
android:id attribute.
• The call findViewById() will fail if the layout does
not have the android:id attribute.
• If this is the case, open
activity_display_message.xml and add the
attribute
android:id="@+id/activity_display_message" to
the layout element.
136
Comment
• The previous overhead contains vital
information—plus it seems muddled
• I installed the latest versions of everything on my
machine
• In spite of that, the id was not automatically
included in the XML file for
activity_display_message
• The moral of the story simply is, include the id
manually if necessary, regardless of what version
you’re using
137
• You can now run the app.
• When it opens, type a message in the text
field, and click Send.
• The second activity replaces the first one on
the screen, showing the message you entered
in the first activity.
• That's it, you've built your first Android app!
138
Comment
• With the id included, the build was clean and the
app was runnable
• The following two overheads show it in operation
• The first activity allows you to enter a message
• Clicking the button starts the second activity,
which displays the message which was sent to it
• After the screenshots, the tutorial material
continues
139
140
141
• “To learn more, follow the link below to the next
class.”
• Commentary: The next topic in this lesson is:
Supporting Different Devices
• Although support for different devices is one of
the great things about Android, this isn’t of
primary importance now
• For you homework and project, you can restrict
your attention to developing for a single device,
not many different devices
142
4.5 Code Review
143
• Although layouts are critical to an app, the
contents of the layouts we’ve seen so far are
not too complex, and won’t merit review here
• However, even though the code we’ve seen so
far has been relatively short, it already
exhibits a degree of complexity, so it merits
review
144
• The code is not computationally complex—it
doesn’t “do” anything
• It simply passes a message from one activity
to another and displays it
• The complexity arises from the need to
manage resources, like layouts, and obtain
and use id’s effectively
145
• What follows is the complete Java code for the
main activity and the display message activity,
with comments included
• This is intended to give a summary synopsis of
the main points of what was covered in this
set of overheads
146
MainActivity.java
147
Package and Imports
•
•
/* If you use the development environment it will
* automatically put your app into a package. */
•
package com.example.kascott.myapplication;
•
/*
•
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
Here are the general imports for the app.
*/
148
•
•
•
•
•
/* You need to import the intent class and the view classes
* in order to use them in your code. The view classes
* correspond to the views in the layout in
* activity_main.xml.
*/
•
import android.content.Intent;
import android.view.View;
import android.widget.EditText;
149
The App Class and the Standard
Provided Methods
•
•
/* This is the class of the app as provided by
* system. */
•
public class MainActivity extends AppCompatActivity {
•
/*
*/
•
public final static String EXTRA_MESSAGE =
"com.example.myfirstapp.MESSAGE";
This is simply a string constant which will be used later.
150
•
•
•
/* This method is the moral equivalent
* of a main() method. It’s provided
* by the system. */
•
•
•
•
•
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
151
• /* The sendMessage() method is called when the
•
* button in the layout which belongs to the app
•
* is clicked */
• /* This is very important: Remember that in
•
* layout terms, the button is a view.
•
* The view that comes in as a parameter to
•
* the method when the button is clicked
•
* is a reference to the button. */
• public void sendMessage(View view) {
152
•
/*
*/
•
•
•
•
•
•
•
•
•
•
/*
*
*
*
*
*
*
*
*
*
•
•
•
•
•
•
The body of the sendMessage() method will come next.
This is very important: In order to get handles
on the other views in the layout of the app so that
you can work with them in the app code, you have to
call methods to acquire them. You will see that the
calls are floating in space—they’re on the implicit
parameter. At this point we don’t really know what
the implicit parameter is. More explanations will
come later. For the time being, accept that the
calls can be made.
Notice these two critical elements of the calls:
* 1. You specify the view you want a handle on by
* sending its R.java id as a parameter.
* 2. You have to cast the return value to the specific
* kind of view you were expecting back.
*/
153
• /* Create an intent which goes from this, the
implicit parameter, the main activity, to what
will be the compiled class for the second
activity. */
• Intent intent = new Intent(this,
DisplayMessageActivity.class);
• /* Obtain a reference to the editText widget of
the main activity by passing in its identifier
from the R file. */
• EditText editText = (EditText)
findViewById(R.id.edit_message);
154
•
/* Using the reference, make a call to acquire the
contents of editText and convert it to a string. */
•
String message = editText.getText().toString();
•
/* Put the editText string into the intent, using the
EXTRA_MESSAGE string constant as the other parameter.
*/
•
intent.putExtra(EXTRA_MESSAGE, message);
•
/* Start the activity indicated by the intent. In
other words, run the code for the DisplayMessageActivity
class. */
•
startActivity(intent);
155
DisplayMessageActivity.java
•
/*
•
package com.example.kascott.myapplication;
•
import
import
import
import
import
Package and imports.
*/
android.support.v7.app.AppCompatActivity;
android.os.Bundle;
android.content.Intent;
android.view.ViewGroup;
android.widget.TextView;
156
•
/*
•
public class DisplayMessageActivity extends AppCompatActivity {
Class declaration and onCreate() method.
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_message);
157
•
/*
•
Intent intent = getIntent();
•
/*
•
String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
•
/* Create textView here in the program, not predefined in the layout file.
Put the string from the intent into textView. */
•
TextView textView = new TextView(this);
textView.setTextSize(40);
textView.setText(message);
Acquire a reference to the intent that started this activity.
Acquire the string that was sent to this activity.
*/
*/
/* Acquire a reference to the layout belonging to this activity and add
textView to the layout. */
•
ViewGroup layout = (ViewGroup) findViewById(R.id.activity_display_message);
layout.addView(textView);
158
Summary and Mission
• After 150+ overheads, your head can spin a
little
• What was this all about?
• In summary, it covered everything you needed
to know, every aspect of any file that you as a
programmer need to touch, in order to create
an echoing application.
159
• From a Java programmer’s point of view, the
code is not long
• Also, the functionality that’s implemented,
echoing a message, isn’t complex
• However, the code itself couldn’t be
characterized as simple by a person who is
first learning to do this
• There is a trade-off going on
160
• Each different activity has its own layout
• User interface design is isolated in the layouts,
not in the Java code
• Much of what you have to work with ends up
centralized in the R file
• The challenge is keeping track of all of the
different files in the project, what has to go
into them, and their relationships to each
other
161
• There is no one thing that’s most important
• Everything that is necessary to make this work
is important
• Activities are fundamental
• Intents are also fundamental
• From a programming point of view, maybe the
most important thing to get used to is
acquiring references to things using the R file
162
• What is your mission?
• You should be able to follow the steps given in
order to create the echoing app that was
described
163
The End
164