Вы находитесь на странице: 1из 209



POUL KLAUSEN

JAVA 16: MOBIL PHONES


AND ANDROID
SOFTWARE DEVELOPMENT

2
Java 16: Mobil phones and Android: Software Development
1st edition
© 2018 Poul Klausen & bookboon.com
ISBN 978-87-403-2330-6
Peer review by Ove Thomsen, EA Dania

3
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Contents

CONTENTS
Foreword 7

1 Introduction 9
Exercise 1: Calculations 22

2 Widgets 24
2.1 A Zipcode app 27
Exercise 2: People 35

3 Layout 37
3.1 RelativeLayout 37
3.2 LinearLayout 47
3.3 TableLayout 51
3.4 GridLayout 51
3.5 A ConstraintLayout 57
3.6 Containers 60
Exercise 3: People1 73

Free eBook on
Learning & Development
By the Chief Learning Officer of McKinsey

Download Now

4
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Contents

4 User interaction 74
4.1 A context menu 76
4.2 A main menu 82
4.3 Define a menu in XML 87
Exercice 4: ImageApp 88
4.4 About activities 90
4.5 Multiple activities 94
Problem 1: LoanApp 96

5 Files 99
5.1 Reading resources 99
Exercise 5: Zipcodes 103
5.2 Ordinary files 103
5.3 Internal storage 104
Exercise 6: NameBook 117
Problem 2: PuzzleApp 119

6 SQLite 121
6.1 Creates a Database 124
6.2 SQL SELECT 128
6.3 SQL INSERT, UPDATE and DELETE 132
6.4 The other activities 137
Exercise 7: PhoneBook 137

7 Threads 141

8 Services 149
8.1 The class Intent 153
8.2 ServiceApp1 154
8.3 ServiceApp2 158
8.4 ServiceApp3 161
8.5 ServiceApp4 164
8.6 ServiceApp5 169
8.7 Ring the phone 172
8.8 A local service – ServiceApp 176
8.9 Services and SQLite 184

5
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Contents

9 A final example 196


9.1 Project start and MainActivity 196
9.2 The data access layer 198
9.3 Notes 199
9.4 Anniversaries 201
9.5 Appointments 202
9.6 The other tools 202
9.7 A project review 206

Appendix A, installing of Android Studio 207

6
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Foreword

FOREWORD
The current book is the sixteenth in this series of books on software development in Java,
and it is at the same time the first of two books that focus on developing applications for
Android, and especially for mobile phone applications. The books requires basic knowledge
of Java and system development in general, and the goal is that the reader, after reading
this book, is able to write simple applications to an Android phone. Important topics
are the most common widgets, layouts and basically about activities, but also use of files
and databases are processed. Mobile phone programming is in many ways different from
programming to a usual computer, for example because the phone is another machine
than a traditional computer, and the phone and, for that matter, other Android devices
like tablets have other features that are not available on a PC. However, these features are
dealt with in the following book.

As the title says this series of books deals with software development, and the goal is to
teach the reader how to develop applications in Java. It can be learned by reading about
the subject and by studying complete sample programs, but most importantly by yourself
to do it and write your own programs from scratch. Therefore, an important part of the
books is exercises and problems, where the reader has to write programs that correspond to
the substance being treated in the books. All books in the series is built around the same
skeleton and will consist of text and examples and exercises and problems that are placed
in the text where they naturally belongs. The difference between exercises and problems is
that the exercises largely deals with repetitions of the substance that is presented in the text,
and furthermore it is relatively accurately described what to do. Problems are in turn more
loosely described, and are typically a little bigger and there is rarely any clear best solution.
These are books to be read from start to finish, but the many code examples, including
exercises and problems plays a central role, and it is important that the reader predict in
detail studying the code to the many examples and also solves the exercises and problems
or possibly just studying the recommended solutions.

All books ends with one or two larger sample programs, which focus primarily is on process
and an explanation of how the program is written. On the other hand appears the code only
to a limited extent – if at all – and the reader should instead study the finished program
code perhaps while testing the program. In addition to show the development of programs
that are larger than the examples, which otherwise is presented, the aim of the concluding
examples also is to show program examples from varying fields of application.

Most books also ends with an appendix dealing with a subject that would not be treated
in the books. It may be issues on the installation of software or other topics in computer

7
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Foreword

technology, which are not about software development, but where it is necessary to have
an introductory knowledge. If the reader already is familiar with the subject, the current
appendix can be skipped.

The programming language is, as mentioned Java, and besides the books use the
following products:

1. etBeans as IDE for application development


2. MySQL to the extent there is a need for a database server (from the book Java 6
onwards)
3. GlassFish as a web server and application server (from the book Java 11 onwards)
4. Android Studio, that is a tool to development of apps to mobil phones

It is products that are free of charge and free to install, and there is even talk about products,
where the installation is progressing all by itself and without major efforts and challenges.
In addition, there are on the web detailed installation instructions for all the three products.
The products are available on Windows and Linux, and it therefore plays no special role if
you use Linux or Windows.

All sample programs are developed and tested on machines running Linux. In fact, it plays
no major role, as both Java and other products work in exactly the same way whether the
platform is one or the other. Some places will be in the books where you could see that
the platform is Linux, and this applies primarily commands that concerning the file system.
Otherwise it has no meaning to the reader that the programs are developed on a Linux
machine, and they can immediately also run under Windows unless a program refers to
the file system where it may be necessary to change the name of a file.

Finally a little about what the books are not. It is not “how to write” or for that matter
reference manuals in Java, but it is as the title says books on software development. It is
my hope that the reader when reading the books and through the many examples can find
inspiration for how to write good programs, but also can be used as a source collection
with a number of examples of solutions to concrete everyday programming problems that
you regularly face as a software developer.

8
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Introduction

1 INTRODUCTION
In short, this book is about programming mobile phones, and although it is in principle
not so different from writing programs to a regular PC, there are also significant differences.
Firstly, the programs are written in Java so that side of the case should be in place, but
what makes the programmming different are differences in the hardware.

Android is used as an operating system on a variety of devices such as mobile phones,


tablets, smart TV, and so on, and although the starting point for this book is a smart phone,
they are also widely different with different screen sizes and other options. Furthermore,
the development of the mobile phone market is so fast that writing programs for the latest
mobile phones you can not be sure they are supported by only a few phones. Thus, there
are a whole host of new factors to consider when writing applications for mobile phones.

As a development tool, for the rest of this book, I will use Android Studio, an IDE from
Google. Appendix A explains how to download and install the product and what it takes
to set up an Android application development environment. In the following, I would like
to assume that Android Studio is installed and in the rest of this section, I will show you
how to write a simple application that can convert kilometers to miles and the other way,
convert miles to kilometers, and it is so a little more than Hello World. I want to focus on
what you should do, but not so much about how it all works, which I want to postpone
for later.

I start by opening Android Studio. Is it the first time you opens the program you get the
following window:

9
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Introduction

Here I click on the top link Start a new Android Studio project, and the result is the following
window where I have to enter the project name (here KmMiles), and where in the file system
that the project should be created:

I have also entered a Company domain name, which is usually a web address, and the name
is included in the project’s package name. When you click Next, you get a window:

10
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Introduction

where to choose what it is for an application that you want to create and what version of
the operating system you want to support. I have chosen that the application should be

Phone and Tablet


and that it should support API 22 for Android 5.1. You should note that Android Studio
writes that I can expect my application to run on 62.6 percent of all devices. Instead, if I
had chosen the latest version, I would like to know that my application could run on less
than 1 percent of all devices.

In the next window, you must select the activity for the phone that corresponds to the
overall layout of the screen and what elements should be on it:

In this case, I have chosen Empty Activity, which is default. In the next window again, select
the name for that activity, which becomes a class name, and you must also choose the name
for the layout. There is no special reasons for choosing other names than what Android
Studio has done as default, so I keep the names. When you click Next, you get a window
where Android Studio builds the project and you then have to click Finish.

Is it the first time you run the program, Android Studio ask you to download more files,
what you should do, and after Android Studio opening the window with the program’s
code, you may also need to click on a few download links, but then the project has been
created and ready and you can start programming.

11
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Introduction

www.sylvania.com

We do not reinvent
the wheel we reinvent
light.
Fascinating lighting offers an infinite spectrum of
possibilities: Innovative technologies and new
markets provide both opportunities and challenges.
An environment in which your expertise is in high
demand. Enjoy the supportive working atmosphere
within our global group and benefit from international
career paths. Implement sustainable ideas in close
cooperation with other specialists and contribute to
influencing our future. Come and join us in reinventing
light every day.

Light is OSRAM

12
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Introduction

Below is a screenshot of Android Studio after the project has been created:

On the left side you have an overview of the project’s files, which I do not want to mention
further in this place. Otherwise, there are two tabs, where the first shows the application
layout, while the other shows a Java class that corresponds to a main class in a conventional
Java application.

The layout is called activity_main and is an XML document that defines the user interface.
You can work with the document both in design mode where you can place components
using the mouse, or you can work directly in the XML code. You can switch between the
two modes by clicking on the bottom tabs (Design and Text).

The project is actually a complete application that you can build and test. To test the program,
click the green arrow after app in the toolbar. When you do, you get the following window:

13
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Introduction

where to choose which device to test the program on. The first time the window is empty.
There is no device connected, but you can create a virtual device by clicking the bottom
button. Here you will first get an overview of which virtual devices are available. When
I created the project, I chose that the application has to support API 22, and so I must
choose a virtual device that does. I have chosen Nexus 4, and in the next window you will
need to download the current device. It requires some downloads, but when that happens,
you have a virtual device as shown in the above window.

When I then click OK, Android Studio will open the emulator (see below). It takes a while,
because you have to download the emulator itself, and it takes a long time to start, but with
a little hassle, you get a window that simulates a phone and with the current application
active. For the time being, the application is trivial as it does nothing but write a text in
the window. I will now expand the program from what Android Studio has auto generated
to an application that opens an emulator as shown below, that is, an application where
you can enter a number and then click on the Convert button, and depending on which
radio button are checked, the number entered is interpreted as miles or kilometers and the
number is converted to a value in the opposite unit. That’s a classic conversion program.
It is of course a very simple program that consists of

-- a text field
-- two radio buttons
-- and two push buttons

but it is nevertheless a program that performs a data processing and not just shows a text.

14
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Introduction

360°
thinking .

360°
thinking . 360°
thinking .
Discover the truth at www.deloitte.ca/careers D

© Deloitte & Touche LLP and affiliated entities.

Discover the truth at www.deloitte.ca/careers © Deloitte & Touche LLP and affiliated entities.

eloitte & Touche LLP and affiliated entities.

Discover the truth


15 at www.deloitte.ca/careers
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Introduction

To write the program I will start in the design window and drag components from the
toolbox to the design window’s Component Tree :

The design originally had a component that showed the text Hello World. I’ve deleted this
component, and then I added

-- a LinearLayout, there is some kind of layout manager


-- a EditText (a Plain Text), there is an input field
-- a RadioGroup, which is a container for components
-- two RadioButton components
-- a LinearLayout
-- two Button components

16
JAVA16:
JAVA 16: MOBILPHONES
PHONES ANDANDROID:
ANDROID:
JAVA 16:MOBIL
MOBIL PHONESAND
AND ANDROID:
SOFTWAREDEVELOPMENT
SOFTWARE DEVELOPMENT IntroduCtIon
Introduction
SOFTWARE DEVELOPMENT IntroduCtIon

You
You should
Youshould note
shouldnote that
notethat the
thatthe design
thedesign panel
designpanel shows
panelshows how
showshow the
howthe individual
theindividual components
individualcomponents
componentsare are nested
nestedinin
arenested in
a hierarchy.
aahierarchy. Also
hierarchy.Also note
Alsonote that
notethat if you
thatififyou select
youselect a component
selectaacomponent with
componentwith the
withthe mouse,
themouse,
mouse,youyou get
youget a panel
getaapanel
panelonon
on
the
the right
right side
side of
of the
the window,
window, where
where you
you can
can specify
specify properties
properties for
for that
that component.
component.
the right side of the window, where you can specify properties for that component.

IfIf you
Ifyou examine
youexamine
examinethethe project
theproject files,
projectfiles, see
files,see the
seethe
theappapp
app| ||res
res
res| ||values,
values, there
thereisis
values,there isaaafile
file called
filecalled strings.xml.
calledstrings.xml.
strings.xml.
It is an
ItItisisan XML
anXML document
XMLdocument
documentthat that defines
thatdefines strings
definesstrings
stringsandand other
andother resources
otherresources that
resourcesthat
thatthe the application
theapplication
applicationcan can
can
apply
apply and
and only
only one
one is
is defined,
defined, which
which is
is the
the program’s
program’s name.
name. I I have
have expanded
expanded
apply and only one is defined, which is the program’s name. I have expanded the file with the
the file
file with
with
55 new
5new definitions,
newdefinitions, the
definitions,the first
first44
thefirst being
4being texts
beingtexts for
textsfor radio
forradio buttons
radiobuttons
buttonsand and other
andother buttons,
otherbuttons, while
buttons,while
whilethe the last
thelast
last
is for
isisfor the
forthe background
thebackground
backgroundcolorcolor of
colorofofthethe window:
thewindow:
window:

<resources>
<resources>
<string name="app_name">KmMiles</string>
<string name="app_name">KmMiles</string>
<string name="km">Kilometers to miles</string>
<string name="km">Kilometers to miles</string>
<string name="ml">Miles to kilometers</string>
<string name="ml">Miles to kilometers</string>
<string name="ok">Convert</string>
<string name="ok">Convert</string>
<string name="cl">Clear</string>
<string name="cl">Clear</string>
<color name="bgColor">#F5F5DC</color>
<color name="bgColor">#F5F5DC</color>
</resources>
</resources>

I Iwill then display the finished XML for the user interface, which is essentially autogenerated
I will
will then
then display
display the
the finished
finished XML
XML for
for the
the user
user interface,
interface, which
which is
is essentially
essentially autogenerated
autogenerated
bybythe
the designer
designer window,
window, but
butwhere
whereI Imade
made some
some adjustments:
adjustments:
by the designer window, but where I made some adjustments:

<?xml version="1.0" encoding="utf-8"?>


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://
<android.support.constraint.ConstraintLayout xmlns:android="http://
schemas.android.com/apk/res/android"
schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="match_parent"
android:background="@color/bgColor"
android:background="@color/bgColor"
tools:context="dk.data.torus.kmmiles.MainActivity">
tools:context="dk.data.torus.kmmiles.MainActivity">
<LinearLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:orientation="vertical"
android:layout_marginTop="20dp"
android:layout_marginTop="20dp"
android:layout_marginStart="20dp">
android:layout_marginStart="20dp">
<EditText
<EditText
android:id="@+id/editText1"
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:ems="10"
android:inputType="numberSigned|numberDecimal"/>
android:inputType="numberSigned|numberDecimal"/>
<RadioGroup
<RadioGroup
android:id="@+id/radioGroup1"
android:id="@+id/radioGroup1"
android:layout_width="match_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent">

1717
17
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16:SOFTWARE
MOBIL PHONES AND ANDROID:
DEVELOPMENT Introduction
SOFTWARE DEVELOPMENT IntroduCtIon

<RadioButton
android:id="@+id/radioButton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/ml" />
<RadioButton
android:id="@+id/radioButton2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/km" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="@string/cl"
android:onClick="onClick"/>

We will turn your CV into


an opportunity of a lifetime

Do you like cars? Would you like to be a part of a successful brand? Send us your CV on
We will appreciate and reward both your enthusiasm and talent. www.employerforlife.com
Send us your CV. You will be surprised where it can take you.

18
18
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Introduction
SOFTWARE
JAVA DEVELOPMENT
16: MOBIL PHONES AND ANDROID: IntroduCtIon
SOFTWARE DEVELOPMENT IntroduCtIon
SOFTWARE DEVELOPMENT IntroduCtIon

<Button
<Button
android:id="@+id/button2"
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="@string/ok"
android:layout_marginTop="20dp"
android:text="@string/ok"
android:onClick="onClick"/>
android:text="@string/ok"
android:onClick="onClick"/>
</LinearLayout>
android:onClick="onClick"/>
</LinearLayout>
</RadioGroup>
</LinearLayout>
</RadioGroup>
</LinearLayout>
</RadioGroup>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
When
When you
When you see
you see the
see the code,
the code, you
code, you can
you can not
can not of
not of course
of course know
course know that
know that itit
that it should
should be
should be written
be written in
written in this
in this way,
this way,
way,
When
but you see the code, you can not of course know that it should be written in this way,
but you
but you can
you can easily
can easily understand
easily understand the
understand the code
the code and
code and the
and the meaning
the meaning of
meaning of the
of the individual
the individual lines.
individual lines. You
lines. You should
You should
should
but you can
especially easily understand theidentifier
code andforthe meaning of the individual lines. You should
especially note
especially note how
note how to
how to create
to create an
create an identifier
an identifier for
for aaa component
component (for
component (for aaa widget),
(for widget), such
widget), such as
such as
as
especially note how to create an identifier for a component (for a widget), such as
android:id="@+id/editText1"
android:id="@+id/editText1"
android:id="@+id/editText1"
You
You should
You should also
should also note
also note how
note how to
how to refer
to refer to
refer to resources
to resources (defined
resources (defined in
(defined in strings.xml ),
in strings.xml ), and
strings.xml ), and as
and as an
as an example:
an example:
example:
You should also note how to refer to resources (defined in strings.xml ), and as an example:
android:text="@string/km"
android:text="@string/km"
android:text="@string/km"
Finally,
Finally, note
note that
that an
an event
event handler
handler has
has been
been defined
defined for
for the
the two
two buttons.
buttons. Basically,
Basically, the
the
Finally,
Finally,
document note
note that
that an
an event
event handler
handler has
has been
been defined
defined for
for the
the two
two buttons.
buttons. Basically,
Basically, the
the
document defines
defines what
what components
components the the window
window should
should have
have and
and how
how itit should
should bebe laid
laid
document
document
out, defines
defines what
what components
components the
the window
window should
should have
have and
and how
how itit should
should bebe laid
laid
out, and
and in
in addition,
addition, for
for each
each widget,
widget, aa number
number of of attributes
attributes are
are defined
defined with
with values
values for
for
out,
out, and
and in
in addition,
corresponding addition, for each
for for
properties each widget,
widget,
the objectsaa that
number
number
the of
of attributes
attributes
finished are
are defined
program defined
must with
with values
consists values
of. for
for
corresponding properties for the objects that the finished program must consists of.
corresponding properties for the objects that the finished program must
corresponding properties for the objects that the finished program must consists of. consists of.
To
To perform
perform the
the conversion,
conversion, II have
have added
added aa class
class named
named Converter
Converter to
to the
the directory
directory (or
(or
To
To perform
perform
package in the
the
the conversion,
conversion,
project pane) II
apphave
have
| added
added
java | a
a class
class named
named Converter
Converter
dk.data.torus.kmmiles: to
to the
the directory
directory (or
(or
package in the project pane) app | java | dk.data.torus.kmmiles:
package
package in
in the
the project
project pane)
pane) app
app || java
java || dk.data.torus.kmmiles:
dk.data.torus.kmmiles:
package
package dk.data.torus.kmmiles;public
dk.data.torus.kmmiles;public class
class Converter
Converter
{
package
{ dk.data.torus.kmmiles;public class Converter
private static final double factor
private static final double factor =
{ = 1.609344;
1.609344;
public static double toKm(double
private static final double factor miles)
= 1.609344;
public static double toKm(double miles)
{
public
{ static double toKm(double miles)
{return
return miles
miles *
* factor;
factor;
}
} return miles * factor;
}
public
public static
static double
double toMl(double
toMl(double kilometers)
kilometers)
{
public
{ static double toMl(double kilometers)
{return kilometers /
return kilometers / factor;
factor;
}
} return kilometers / factor;
}
}}
}

19
19
19
19
JAVA
JAVA16:
16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
SOFTWARE
SOFTWAREDEVELOPMENT
DEVELOPMENT Introduction
IntroduCtIon

The
Theclass
classisisobviously
obviouslytrivial
trivialand
andisisincluded
includedsolely
solelytotoshow
showthat
thatan
anAndroid
Androidapplication
applicationcan
can
contain
containJava
Javaclasses
classesininthe
thesame
samewaywayasasother
otherJava
Javaapplications
applicationsand
andthat
thatititisisjust
justaausual
usual
Java
Javaclass.
class.

Back
Backthere
thereisisthe
themain
mainclass
classMainActivity:
MainActivity:

package dk.data.torus.kmmiles;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity


{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

public void onClick(View view)


{
EditText text = (EditText) findViewById(R.id.editText1);
if (view.getId() == R.id.button1)
{
text.setText("");
}
else if (view.getId() == R.id.button2)
{
RadioButton ml = (RadioButton) findViewById(R.id.radioButton1);
RadioButton km = (RadioButton) findViewById(R.id.radioButton2);
if (text.getText().length() == 0)
{
Toast.makeText(this, "Please enter a valid number",
Toast.LENGTH_LONG).show();
return;
}
double value = Double.parseDouble(text.getText().toString());
if (ml.isChecked()) text.setText(String.valueOf(Converter.toKm(value)));
else text.setText(String.valueOf(Converter.toMl(value)));
}
}
}

20
20
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Introduction
IntroduCtIon

As
As you
you can
can see,
see, this
this isis again
again aa regular
regular Java
Java class.
class. Here
Here isis onCreate()
onCreate() created
created by
by Android
Android
Studio,
Studio, while
while the
the event
event handler
handler should
should bebe written.
written. There
There isis not
not much
much toto explain
explain about
about the
the
code,
code, but
but you
you should
should notice
notice how
how toto refer
refer to
to the
the individual
individual components
components (widgets).
(widgets).

Then,
Then, in in principle,
principle, thethe program
program isis complete
complete and
and can
can be
be translated
translated and
and opened
opened in in the
the
emulator,
emulator, butbut inin practice,
practice, more
more needs
needs to to be
be done
done before
before the
the program
program can can bebe packed
packed and
and
placed
placed for
for download
download on on an
an app
app store.
store. II will
will postpone
postpone that
that for
for later,
later, but
but here
here aa few
few words
words
about
about what is needed. First, the program must be tested with different screen sizes, and
what is needed. First, the program must be tested with different screen sizes, and
that
that is,
is, with
with different
different emulators.
emulators. Next,
Next, thethe program
program must
must be
be tested
tested on
on aa physical
physical design,
design,
which
which isis actually
actually quite
quite simple.
simple. You
You can can connect
connect your
your device
device (phone)
(phone) viavia aa USB
USB cable.
cable. For
For
Android
Android Studio
Studio to to see
see the
the device,
device, itit must
must unlock
unlock the
the phone
phone asas aa Developer
Developer Device.
Device. You
You can
can
find out how
find out how on on

https://developer.android.com/studio/run/index.
html?utm_source=android-studio

and then
and then you
you can
can choose
choose the
the physical
physical device
device when
when you you run
run the
the program,
program, in
in the
the same
same way
way
as for
as for the
the emulator,
emulator, after
after which
which the
the program
program isis installed
installed and
and running
running on
on the
the phone.
phone.

21
21
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Introduction

EXERCISE 1: CALCULATIONS
You must write a program using the same procedure as shown above. When you opens
the program in the emulator, you should get a window as shown below that contains the
following widgets:

-- a LinearLayout
-- a TextView
-- an EditText
-- a ButtonGroup with two RadioButton widgets
-- a LinearLayout with two Button widgets
-- a TextView
-- an EditText
-- a TextView
-- an EditText
-- a TextView
-- an EditText

In the top entry field you must be able to enter a unit price, while in the next one must
be able to enter the number of units. When clicking on the OK button, the application
must calculate the total price without VAT (depending on which radio button is pressed),
the VAT and total price with VAT, and then the three lower entry fields must be updated.

22
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Introduction

If you press the Clear button, all input fields must be blanked.

When you solve the exercise, you should place texts in the file strings.xml in the same way
as in the introductory example.

The three bottom entry fields should in principle be read only. Try to find out how to do that.

AXA Global
Graduate Program
Find out more and apply

23
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Widgets
wIdgets

2 WIDGETS
2 WIDGETS
IfIf you
you consider
consider the
the introductory
introductory example,
example, itit contains
contains 55 controls:
controls:

--- aa entry
entry field
field –– aa EditText
EditText control
control
--- two
two radiobuttons
radiobuttons –– RadioButton
RadioButton controls
controls
--- two buttons – Button controls
two buttons – Button controls

In
In Android,
Android, these
these are
are called
called controls
controls for
for widgets,
widgets, butbut the
the above
above are
are the
the same
same as as you
you know
know
from
from Swing
Swing or
or JavaFX.
JavaFX. There
There areare many
many such
such widgets,
widgets, and and some
some of of the
the first
first to
to learn
learn to
to write
write
Android applications is of course learning which and how they are
Android applications is of course learning which and how they are used. I do not want used. I do not want
to
to systematically
systematically review
review the
the various
various components
components in in this
this book,
book, butbut illustrate
illustrate some
some of of them
them
through
through examples,
examples, but
but basically
basically they
they are
are used
used the
the same
same way
way you
you know
know itit fromfrom controls
controls inin
Java.
Java. Things
Things are
are of
of course
course called
called something
something else,
else, and
and there
there are
are other
other properties
properties thatthat you
you can
can
set, but the principles are the same. Widgets are arranged in an extensive
set, but the principles are the same. Widgets are arranged in an extensive class hierarchy, class hierarchy,
where
wherethetheoverall
overallbasic
basicclass
classisiscalled
calledView.
View.InInthis
thiscontext,
context,ititisisgood
goodto toknow
knowthe theweb
webaddress
address

https://developer.android.com/reference/classes.html

which
which isis the
the basic
basic reference
reference for
for Android’s
Android’s many
many features.
features.

As
As with
with Swing
Swing andand JavaFX,
JavaFX, thethe biggest
biggest challenges
challenges are
are getting
getting aa component
component placed
placed in
in the
the
window,
window, where
where youyou now
now exactly
exactly want
want them
them to to be,
be, but
but also
also that
that the
the window
window looks
looks nice
nice at
at
different
different sizes
sizes of
of the
the screen,
screen, but
but that
that isis the
the subject
subject of
of the
the next
next chapter.
chapter.

In
In general,
general, Android
Android has has the
the same
same widgets
widgets that
that you
you know
know as as controls
controls in
in Swing
Swing // JavaFX,
JavaFX, but
but
maybe
maybe they
they are
are called
called something
something else.
else. However,
However, there
there are
are also
also new
new ones
ones that
that are
are not
not found
found
in
in Java,
Java, and
and as
as an
an example,
example, II want
want to
to show
show an
an application
application with
with two
two widgets
widgets

--- aa Switch,
Switch, that
that isis an
an alternative
alternative to
to aa CheckBox
CheckBox
--- an
an AnalogClock,
AnalogClock, har har shows
shows aa clock
clock (the
(the widget
widget isis now
now deprecated)
deprecated)

The
The project
project isis called
called TheClock,
TheClock, and
and ifif you
you opens
opens the
the application
application in in the
the emulator,
emulator, the
the result
result
isis as shown below. The application shows an analogue clock that
as shown below. The application shows an analogue clock that counts in minutes. Overcounts in minutes. Over
the
the clock
clock there
there isis aa Switch
Switch (you
(you know
know the the widget
widget from
from your
your phone)
phone) that
that shows
shows aa text
text and
and isis
aa contact
contact that
that youyou can
can turn
turn on
on and
and off.
off. IfIf you
you run
run the
the application,
application, you
you can
can hide
hide the
the clock
clock
by
by clicking
clicking the
the Switch
Switch control,
control, and
and youyou cancan display
display itit again
again by
by clicking
clicking itit on.
on.

The
The project
project has
has been
been created
created in
in exactly
exactly the
the same
same way
way as
as the
the example
example inin the
the introductory
introductory
chapter,
chapter,where
whereIIhave
havefollowed
followedthe
thesame
samewizard,
wizard,and
andthe
theonly
onlydifference
differenceisisthat
thatIIhave
haveentered
entered
another
another project name. Then I deleted the TextView widget that Android Studio has added
project name. Then I deleted the TextView widget that Android Studio has added

24
24
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Widgets
wIdgets

and
and instead
instead added
added aa LinearLayout
LinearLayout and
and again
again aa Switch
Switch widget.
widget. AnalogClock
AnalogClock does
does not
not exist
exist in
in
the
the toolbox
toolbox (as
(as itit isis deprecated),
deprecated), so
so II have
have to
to add
add itit by
by entering
entering the
the XML
XML code.
code.

The code
The code isis very
very simple
simple and
and the
the most
most important
important isis main_activity.xml,
main_activity.xml, which
which defines
defines the
the
user interface:
user interface:

<?xml version="1.0" encoding="utf-8"?>


<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="dk.data.torus.theclock.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Switch
android:id="@+id/switch1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="30dp"
android:checked="true"
android:text="Set Clock on/off"
android:onClick="onClick"/>

25
25
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Widgets
SOFTWARE DEVELOPMENT wIdgets

<AnalogClock android:id="@+id/analog"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
/>
</LinearLayout>
</android.support.constraint.ConstraintLayout>

Again,
Again, it’s
it’s easy
easy enough
enough to to understand
understand the
the code
code when
when you
you see
see itit and
and remember
remember that
that Android
Android
Studio
Studio has created the most. The only thing that is difficult to understand is the width and
has created the most. The only thing that is difficult to understand is the width and
height
height attributes, but it is explained in the next chapter. Note that the Switch object has
attributes, but it is explained in the next chapter. Note that the Switch object has
an event handler that must be written in the Java code and the task is changed
an event handler that must be written in the Java code and the task is changed the clock’s the clock’s
visibility
visibility depending
depending on on the
the Switch
Switch contact’s
contact’s state:
state:

package dk.data.torus.theclock;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.*;
import android.widget.*;

�e Graduate Programme
I joined MITAS because for Engineers and Geoscientists
I wanted real responsibili� www.discovermitas.com
Maersk.com/Mitas �
I joined MITAS because for Eng
I wanted real responsibili� M

Month 16
I was a construction M
supervisor ina con
I was
the North Sea supe
advising and the N
Real work he
helping foremen adv
International
al opportunities
Internationa
�ree wo
work
or placements ssolve problems
Real work he
helping
International
Internationaal opportunities
�ree wo
work
or placements ssolve p

26
26
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Widgets
SOFTWARE DEVELOPMENT wIdgets

public class MainActivity extends AppCompatActivity


{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

public void onClick(View view)


{
Switch sw = (Switch) findViewById(R.id.switch1);
AnalogClock cl = (AnalogClock) findViewById(R.id.analog);
if (sw.isChecked()) cl.setVisibility(View.VISIBLE);
else cl.setVisibility(View.INVISIBLE);
}
}

2.1
2.1 A ZIPCODE APP
II want
want toto exit
exit this
this chapter
chapter about
about widgets
widgets with
with yet
yet another
another simple
simple example
example of of an
an app.
app. It
It
must
must bebe an
an application
application where
where youyou can
can search
search for
for Danish
Danish postal
postal codes
codes by
by entering
entering aa search
search
text
text for
for the
the postal
postal code
code and
and the
the city
city name,
name, respectively
respectively –– anan application
application that
that II have
have used
used
as
as an
an example
example until
until several
several times.
times. Compared
Compared withwith the
the above
above example,
example, the
the application
application is is
somewhat
somewhat larger
larger and
and thus
thus better
better reflects
reflects how
how aa typical
typical app
app for
for aa mobile
mobile phone
phone looks.
looks. If
If you
you
perform
perform thethe application
application in
in the
the emulator,
emulator, youyou get
get the
the following
following result
result where
where Sk
Sk is
is searched
searched
for
for city
city name.
name. TheThe result
result is
is all
all the
the zip
zip codes
codes where
where the
the city
city name
name contains
contains Sk.
Sk. Instead
Instead ifif
searching
searching for
for aa number,
number, you
you get
get the
the zip
zip codes
codes where
where the
the number
number starts
starts with
with the
the search
search text.
text.

This
This time
time the
the code
code fills
fills up
up aa little
little more
more and
and II want
want to
to start
start with
with the
the resource
resource file
file strings.xml:
strings.xml:

<resources>
<string name="app_name">Zipcodes</string>
<string name="codelabel">Code</string>
<string name="citylabel">City</string>
<string name="clrlabel">Clear</string>
<string name="seeklabel">Search</string>
<color name="bgColor">#F5F5BA</color>
</resources>

which
which defines
defines texts
texts for
for the
the user
user interface
interface as
as well
well as
as aa background
background color.
color. It
It is
is not
not aa requirement
requirement
that
that this is defined as resources, but it is recommended that you easily can change
this is defined as resources, but it is recommended that you easily can change the
the

27
27
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Widgets
wIdgets

program
program without
without having
having to
to go
go around
around the
the code,
code, and
and itit also
also opens
opens up
up to
to language
language versions
versions
of
of the
the application.
application.

The
The user
user interface
interface was
was built
built in
in the
the designer
designer window
window by by retrieving
retrieving components
components from
from the
the
toolbox,
toolbox, and
and then
then II have
have edited
edited the
the XML
XML code.
code. It’s
It’s filling
filling up
up aa bit:
bit:

<?xml version="1.0" encoding="utf-8"?>


<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"
android:background="@color/bgColor"
tools:context="dk.data.torus.zipcodes.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:orientation="vertical">
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

28
28
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL PHONES
SOFTWARE AND ANDROID:
DEVELOPMENT Widgets
SOFTWARE DEVELOPMENT wIdgets

<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:textSize="18dp"
android:text="@string/codelabel" />
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="4"
android:inputType="number" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

93%
OF MIM STUDENTS ARE
WORKING IN THEIR SECTOR 3 MONTHS
FOLLOWING GRADUATION

MASTER IN MANAGEMENT
• STUDY IN THE CENTER OF MADRID AND TAKE ADVANTAGE OF THE UNIQUE OPPORTUNITIES
Length: 1O MONTHS
THAT THE CAPITAL OF SPAIN OFFERS
Av. Experience: 1 YEAR
• PROPEL YOUR EDUCATION BY EARNING A DOUBLE DEGREE THAT BEST SUITS YOUR
Language: ENGLISH / SPANISH
PROFESSIONAL GOALS
Format: FULL-TIME
• STUDY A SEMESTER ABROAD AND BECOME A GLOBAL CITIZEN WITH THE BEYOND BORDERS
Intakes: SEPT / FEB
EXPERIENCE

5 Specializations #10 WORLDWIDE 55 Nationalities


MASTER IN MANAGEMENT
Personalize your program FINANCIAL TIMES
in class

www.ie.edu/master-management mim.admissions@ie.edu Follow us on IE MIM Experience

29
29
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Widgets
SOFTWARE DEVELOPMENT wIdgets

android:layout_marginRight="10dp"
android:textSize="18dp"
android:text="@string/citylabel" />
<EditText
android:id="@+id/editText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"/>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="10dp"
android:text="@string/clrlabel"
android:onClick="onClick"/>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="10dp"
android:text="@string/seeklabel"
android:onClick="onClick"/>
</LinearLayout>
</TableRow>
</TableLayout>
<ListView
android:id="@+id/listView1"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</LinearLayout>
</android.support.constraint.ConstraintLayout>

30
30
JAVA
JAVA16:
16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
SOFTWARE
SOFTWAREDEVELOPMENT
DEVELOPMENT Widgets
wIdgets

Again,
Again, the
the code
code isis easy
easy enough
enough to
to understand.
understand. Basic
Basic the
the layout
layout isis aa LinearLayout
LinearLayout with
with two
two
elements
elements laid
laid out
out vertically:
vertically:

--- aa TableLayout
TableLayout
--- aa ListView
ListView

You
You can
can think
think of of aa TableLayout
TableLayout asas aa HTML
HTML table, table, where
where elements
elements are
are organized
organized in in rows
rows
and
and columns. In this case, the component is used to create a form with the input fieldsand
columns. In this case, the component is used to create a form with the input fields and
buttons.
buttons. There
There areare three
three rows
rows where
where thethe first
first hashas aa label
label (a(a TextView
TextView widget)
widget) and
and anan input
input
field
field(a(aEditText
EditTextwidget).
widget).Note
Notewhich
whichattributes
attributesare aredefined,
defined,and andespecially
especiallyfor
forthe
thelatter,
latter,that
that
you
you can only enter integers. The next row is in principle identical, while the latter is a bit
can only enter integers. The next row is in principle identical, while the latter is a bit
different. Each row has two cells, and the first cell in the last row has
different. Each row has two cells, and the first cell in the last row has an empty label. The an empty label. The
second
second cell
cell has
has aa LinearLayout
LinearLayout withwith two
two buttons
buttons (Button
(Button widgets).
widgets). Note
Note that
that both
both buttons
buttons
have
havean anevent
eventhandler,
handler,which
whichmustmustbe bedefined
definedin inthe
theprogram
programcode code––the
theclass
classMainActivity.
MainActivity.
ListView
ListView is a widget that corresponds to a list box, and is temporarily empty asas itit should
is a widget that corresponds to a list box, and is temporarily empty should
be initialized in the
be initialized in the code.code.

As
As can
can bebe seen
seen from
from the
the above,
above, the
the XML
XML section
section forfor an
an activity
activity can
can quickly
quickly become
become
extensive,
extensive, but if you write applications for mobile phones, it is recommended (due to
but if you write applications for mobile phones, it is recommended (due to the
the
screen size) that a window may only contain few widgets, and if there is a
screen size) that a window may only contain few widgets, and if there is a need for many, need for many,
the
the application
application should
should in
in instead
instead use
use more
more activities,
activities, what
what II will
will later
later show
show examples
examples of.
of.

Back
Backthere
thereisisthe
theJava
Javacode,
code,where
wherethis
thistime
timeininaddition
additiontotoMainActivity
MainActivityare
aretwo
twoother
otherclasses,
classes,
which
which are usual model classes. The idea is to show that an Android application consists of
are usual model classes. The idea is to show that an Android application consists of
classes
classesininthe
thesame
sameway
wayasasother
otherapplications,
applications,andandagain,
again,ininprinciple,
principle,that
thatititisisnot
notso
somuch
much
different
different toto write
write mobile
mobile apps
apps than
than other
other PC
PC applications.
applications.

First,
First, II want
want the
the following
following simple
simple model
model class
class to
to be
be added
added to
to the
the project:
project:

package dk.data.torus.zipcodes;

public class Zipcode


{
private String code;
private String city;

public Zipcode(String code, String city)


{
this.code = code;
this.city = city;
}

31
31
JAVA 16:
JAVA 16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
JAVA 16: MOBIL
SOFTWARE
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT
DEVELOPMENT wIdgets
Widgets
SOFTWARE DEVELOPMENT wIdgets

public String getCode()


public
{ String getCode()
{ return code;
}return code;
}

public String getCity()


public
{ String getCity()
{ return city;
}return city;
}

public String toString()


public
{ String toString()
{ return getCode() + " " + getCity();
}return getCode() + " " + getCity();
}
}
}
which represents
which represents aa zip
zip code.
code. Then
Then II have
have added
added aa class
class Zipcodes
Zipcodes where
where the
the zip
zip codes
codes are
are
which represents a zip code. Then I have added a class Zipcodes where the zip codes are
defined as
defined as constants,
constants, and
and where
where the
the class
class creates
creates aa custom
custom list
list with
with Zipcode
Zipcode objects:
objects:
defined as constants, and where the class creates a custom list with Zipcode objects:
package dk.data.torus.zipcodes;
package dk.data.torus.zipcodes;

import java.util.*;
import java.util.*;

32
32
32
JAVA16:
JAVA 16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
JAVA 16: MOBIL
SOFTWARE
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT
DEVELOPMENT wIdgets
Widgets
SOFTWARE DEVELOPMENT wIdgets

public class Zipcodes


public
{ class Zipcodes
{private List<Zipcode> list = new ArrayList();
private List<Zipcode> list = new ArrayList();

public Zipcodes()
public
{ Zipcodes()
{for (int i = 0; i < codes.length; ++i)
for (int i = 0;
list.add(new i < codes.length;
Zipcode(codes[i][0], ++i)
codes[i][1]));
} list.add(new Zipcode(codes[i][0], codes[i][1]));
}

public List<Zipcode> search(String code, String city)


public
{ List<Zipcode> search(String code, String city)
{city = city.toLowerCase();
city = city.toLowerCase();
List<Zipcode> lines = new ArrayList();
List<Zipcode>
for (Zipcode zlines = new ArrayList();
: list)
for
if (Zipcode z : list)
(z.getCode().startsWith(code) && z.getCity().
if (z.getCode().startsWith(code)
toLowerCase().contains(city)) && z.getCity().
toLowerCase().contains(city))
lines.add(z);
lines.add(z);
return lines;
}return lines;
}
private static String[][] codes =
private
{ static String[][] codes =
{{ "0800", "Høje Taastrup" },
{
{ "0800",
"0900", "Høje Taastrup"
"København C" },},
{
… "0900", "København C" },
}…
}
}
}

Here isis the


Here the important
important thethe method
method search()
search() that
that isis used
used to
to search
search for
for zip
zip codes.
codes. Here
Here you
you
Here is the important the method search() that is used to search for zip codes. Here you
should especially
should especially note
note that
that itit returns
returns aa List<Zipcode>,
List<Zipcode>, and and thus
thus aa list
list of
of the
the Zipcode
Zipcode objects
objects
should especially note that it returns a List<Zipcode>, and thus a list of the Zipcode objects
that match
that match the the search
search criteria.
criteria.
that match the search criteria.

Then there
Then there isis the
the MainActivity
MainActivity class:
class:
Then there is the MainActivity class:
package dk.data.torus.zipcodes;
package dk.data.torus.zipcodes;

import android.support.v7.app.AppCompatActivity;
import
import android.support.v7.app.AppCompatActivity;
android.os.Bundle;
import
import android.os.Bundle;
android.view.View;
import
import android.view.View;
android.widget.EditText;
import
import android.widget.EditText;
android.widget.ListView;
import
import android.widget.ListView;
java.util.*;
import
import java.util.*;
android.widget.ArrayAdapter;
import android.widget.ArrayAdapter;

public class MainActivity extends AppCompatActivity


public
{ class MainActivity extends AppCompatActivity
{private Zipcodes zipcodes = new Zipcodes();
private Zipcodes zipcodes = new Zipcodes();

33
33
33
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Widgets
SOFTWARE DEVELOPMENT wIdgets

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

public void onClick(View view)


{
EditText text1 = (EditText) findViewById(R.id.editText1);
EditText text2 = (EditText) findViewById(R.id.editText2);
if (view.getId() == R.id.button1)
{
text1.setText("");
text2.setText("");
}
else if (view.getId() == R.id.button2)
{
List<Zipcode> list = zipcodes.search(text1.getText().toString().trim(),
text2.getText().toString().trim());
ArrayAdapter<Zipcode> adapter =
new ArrayAdapter<Zipcode>(this, android.R.layout.
simple_list_item_1, list);
ListView lv = (ListView) findViewById(R.id.listView1);
lv.setAdapter(adapter);
}
}
}

The class
The class has
has an
an instance
instance of
of the
the class
class Zipcodes
Zipcodes and
and thus
thus has
has the
the zip
zip codes
codes available.
available. As
As for
for the
the
event handler,
event handler, only
only the
the code
code for
for the
the Search
Search button
button contains
contains something
something new.
new. ItIt you
you performs
performs
aa search
search the
the result
result must
must be
be used
used toto update
update the
the ListView
ListView component,
component, which
which occurs
occurs with
with an
an
ArrayAdapter for
ArrayAdapter for Zipcode
Zipcode objects.
objects. Here
Here the
the parameters
parameters areare not
not immediately
immediately obvious.
obvious. The
The
first is
first is aa reference
reference toto the
the current
current object
object and
and thus
thus the
the object
object that
that consists
consists of
of the
the ListView.
ListView.
The other
The other parameter
parameter looks
looks mysterious,
mysterious, butbut denotes
denotes aa constant,
constant, which
which isis defined
defined asas part
part
of Android
of Android andand indicates
indicates that
that it
it is
is an
an adapter
adapter for
for aa ListView.
ListView. Finally,
Finally, the
the last
last parameter
parameter
is the
is the objects
objects for
for which
which the
the ListView
ListView component
component is is initialized.
initialized. The
The adapter
adapter in in question
question is
is
subsequently used
subsequently used toto initialize
initialize the
the component.
component.

34
34
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Widgets

EXERCISE 2: PEOPLE
You must write a program similar to the example above which opens the window below.
At the top there are two entry fields and at the bottom there is a ListView. In the two top
fields you must be able to enter the name of a person and when you click OK, the name
must be inserted in the list view. In the example below, 4 names are entered.

In the past 5 years we have drilled around

95,000 km
—that’s more than twice around the world.

Who are we?


We are the world’s leading provider of reservoir characterization,
drilling, production, and processing technologies to the oil and
gas industry.

Who are we looking for?


We offer countless opportunities in the following domains:
n Operations
n Research, Engineering, and Manufacturing
n Geoscience and Petrotechnical
n Commercial and Business

We’re looking for high-energy, self-motivated graduates


with vision and integrity to join our team. What will you be?

careers.slb.com

35
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Widgets

You can solve the exercise as described below:

1. Create a new project in Android Studio, which you can call People.
2. Create all texts in string.xml.
3. Write the design, that is, add all widgets by dragging them from the toolbox and
dropping them into the Component Tree, and then adjust the XML code, but
without adding event handlers.
4. Test the program in the emulator and repeat until you think it all looks nice.
5. Add a simple model class Person representing a person by a first name and a last name.
6. Add a List<Person> to your MainActivity.
7. Add an adapter between your list and your ListView. Note that the adapter creates
a form of data binding between your list and the component.
8. Write the event handler to the Clear button.
9. Write the event handler to the OK button, which (if both a last name and first
name are entered) must create a Person object and add it to your list.

Then the program should be completed.

36
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Layout

3 LAYOUT
In this chapter I will look a little more on layouts, which have of course already been part
of the previous examples, but it is about how to place components in the window, thus
matching what you know from Swing as layout managers. With this background (and with
knowledge of panes in JavaFX) it is relatively simple to address how layouts works, what
the previous examples also shows. However, there are some syntax, and the following is not
a reference, but I will instead show through examples what is possible.

3.1 RELATIVELAYOUT
As example I will show an improved version of the program from chapter 1, which is
enhanced by conversion between fahrenheit and celsius:

In addition to that, the main difference is that another the layout manager that has been
used, which is called a RelativeLayout. The starting point is a new project, which I have
called Convert. After the project has been created, Android Studio has created the following
design for the user interface (that is main_activity.xml ):

37
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

<?xml version="1.0" encoding="utf-8"?>


<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="dk.data.torus.convert.MainActivity">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

The
The design
design contains
contains aa layout
layout manager,
manager, called
called ConstraintLayout,
ConstraintLayout, and
and as
as II return
return to
to later,
later, but
but
you may notice that two attributes are defined android:layout_width and android:layout_height,
you may notice that two attributes are defined android:layout_width and android:layout_height,
both
both of
of which
which have
have the
the value
value match_parent.
match_parent. This
This means
means that
that the
the layout
layout should
should apply
apply all
all

Excellent Economics and Business programmes at:

“The perfect start


of a successful,
international career.”

CLICK HERE
to discover why both socially
and academically the University
of Groningen is one of the best
places for a student to be
www.rug.nl/feb/education

38
38
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Layout
Layout

the
the space
space as
as the
the parent
parent –– and
and this
this will
will say
say the
the screen
screen –– makes
makes available,
available, and
and itit applies
applies to
to
both
both width
width and
and height.
height. In
In this
this layout,
layout, Android
Android Studio
Studio has
has inserted
inserted aa TextView
TextView widget
widget that
that
II want
want toto delete.
delete. II have
have then
then added
added aa RelativeLayout
RelativeLayout toto the
the layout
layout window,
window, andand from
from the
the
toolbox, I have draged the current widgets to the layout so that almost all widgets
toolbox, I have draged the current widgets to the layout so that almost all widgets are now are now
added
added toto the
the window
window in in the
the correct
correct hierarchy
hierarchy (where
(where II have
have changed
changed thethe names
names of of the
the
individual
individual widgets):
widgets):

The
The result
result isis that
that all
all widgets
widgets are
are in
in the
the top
top left
left corner
corner of
of the
the window,
window, and
and Android
Android Studio
Studio
has
has generated
generated the the following
following XML:
XML:

<?xml version="1.0" encoding="utf-8"?>


<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="dk.data.torus.convert.MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />

39
39
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA SOFTWARE
16: MOBIL PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<EditText
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Name" />
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RadioButton
android:id="@+id/radioButton4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="RadioButton" />
<RadioButton
android:id="@+id/radioButton3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="RadioButton" />
</RadioGroup>
<Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<Button
android:id="@+id/button6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />

40
40
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA SOFTWARE
16: MOBIL PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

<EditText
android:id="@+id/editText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Name" />
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RadioButton
android:id="@+id/radioButton6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="RadioButton" />
<RadioButton
android:id="@+id/radioButton5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="RadioButton" />
</RadioGroup>

American online
LIGS University
is currently enrolling in the
Interactive Online BBA, MBA, MSc,
DBA and PhD programs:

▶▶ enroll by September 30th, 2014 and


▶▶ save up to 16% on the tuition!
▶▶ pay in 10 installments / 2 years
▶▶ Interactive Online education
▶▶ visit www.ligsuniversity.com to
find out more!

Note: LIGS University is not accredited by any


nationally recognized accrediting agency listed
by the US Secretary of Education.
More info here.

41
41
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
SOFTWARE DEVELOPMENT
DEVELOPMENT Layout
Layout
SOFTWARE DEVELOPMENT Layout

<Button
<Button
android:id="@+id/button7"
android:id="@+id/button7"
android:layout_width="wrap_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:text="Button" />
/>
<Button
<Button
android:id="@+id/button8"
android:id="@+id/button8"
android:layout_width="wrap_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:text="Button" />
/>
</RelativeLayout>
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>

Here
Here you
you should
should especially
especially note
note what
what values
values Android
Android Studio
Studio has
has assigned
assigned forfor android:layout_
android:layout_
width
width and android:layout_height respectively. For the RelativeLayout, it is match_parent, which
and android:layout_height respectively. For the RelativeLayout, it is match_parent, which
means
means it should apply all the space that the parent component makes available, and here is
it should apply all the space that the parent component makes available, and here is
aa ConstraintLayout
ConstraintLayout that fills the entire window. For the other components, wrap_content is
that fills the entire window. For the other components, wrap_content is
used everywhere, which means that the component size is determined
used everywhere, which means that the component size is determined by the content, andby the content, and
if
if you
you take
take aa TextView
TextView asas an
an example,
example, itit is
is the
the component’s
component’s text.
text.

After
After I,
I, as
as described
described above,
above, have
have uncritically
uncritically filled
filled the
the widgets
widgets into
into the
the window,
window, it’s
it’s my
my job
job
to
to make them sit nicely, and this is where the layout manager enters the image, as here is
make them sit nicely, and this is where the layout manager enters the image, as here is
aa RelativeLayout. As the name says, it sets the individual widgets relative to
RelativeLayout. As the name says, it sets the individual widgets relative to each other by each other by
specifying
specifying attributes,
attributes, and
and so
so II have
have aa process
process back
back where
where II adjust
adjust the
the XML
XML code
code byby adding
adding
attributes
attributes until it’s all the way I want it. It’s also as part of this process that I name the
until it’s all the way I want it. It’s also as part of this process that I name the
individual widgets so they have slightly more pronounced names than what
individual widgets so they have slightly more pronounced names than what Android Studio Android Studio
has
has assigned.
assigned. Below
Below is is the
the completed
completed XML: XML:

<?xml version="1.0"
<?xml version="1.0" encoding="utf-8"?>
encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="match_parent"
android:background="#F5F5BA"
android:background="#F5F5BA"
tools:context="dk.data.torus.convert.MainActivity">
tools:context="dk.data.torus.convert.MainActivity">
<RelativeLayout
<RelativeLayout
android:layout_width="match_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp">
android:layout_margin="20dp">
<TextView
<TextView
android:id="@+id/lblHead1"
android:id="@+id/lblHead1"
android:layout_width="wrap_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_height="wrap_content"

42
42
42
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA SOFTWARE
16: MOBIL PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

android:layout_marginBottom="10dp"
android:text="Kilometers / miles"
android:textSize="24dp"/>
<TextView
android:id="@+id/lblDist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/lblHead1"
android:layout_alignBaseline="@id/txtDist"
android:text="Distance" />
<EditText
android:id="@+id/txtDist"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/lblDist"
android:layout_below="@id/lblHead1"
android:layout_marginLeft="10dp"
android:inputType="numberSigned|numberDecimal"/>
<RadioGroup
android:id="@+id/group1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/txtDist"
android:layout_marginTop="10dp">
<RadioButton
android:id="@+id/cmdMl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="true"
android:text="Miles to kilometers" />
<RadioButton
android:id="@+id/cmdKm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Kilometers to miles" />
</RadioGroup>
<Button
android:id="@+id/cmdClr1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/group1"
android:layout_marginTop="10dp"
android:text="Clear"
android:onClick="distClear"/>
<Button
android:id="@+id/cmdConv1"
android:layout_width="wrap_content"

43
43
JAVA 16: MOBIL PHONES AND ANDROID:
JAVASOFTWARE
16: MOBIL PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

android:layout_height="wrap_content"
android:layout_below="@id/group1"
android:layout_toEndOf="@id/cmdClr1"
android:layout_marginTop="10dp"
android:text="Convert"
android:onClick="distConvert"/>
<TextView
android:id="@+id/lblHead2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/cmdClr1"
android:layout_marginTop="20dp"
android:layout_marginBottom="10dp"
android:text="Fahrenheit / celsius"
android:textSize="24dp"/>
<TextView
android:id="@+id/lblTemp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/lblHead2"
android:layout_marginTop="20dp"
android:layout_alignBaseline="@id/txtTemp"
android:text="Temperature" />

44
44
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

<EditText
android:id="@+id/txtTemp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/lblHead2"
android:layout_toEndOf="@id/lblTemp"
android:layout_marginLeft="10dp"
android:inputType="numberSigned" />
<RadioGroup
android:id="@+id/group2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/txtTemp"
android:layout_marginTop="10dp">
<RadioButton
android:id="@+id/cmdFa"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="true"
android:text="Fahrenheit to celsius" />
<RadioButton
android:id="@+id/cmdCl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Celsius to fahrenheit" />
</RadioGroup>
<Button
android:id="@+id/cmdClr2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/group2"
android:layout_marginTop="10dp"
android:text="Clear"
android:onClick="tempClear"/>
<Button
android:id="@+id/cmdConv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/group2"
android:layout_toEndOf="@id/cmdClr2"
android:layout_marginTop="10dp"
android:text="Convert"
android:onClick="tempConvert"/>
</RelativeLayout>
</android.support.constraint.ConstraintLayout>

45
45
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Layout

In the following I will briefly mention what has happened. In the ConstraintLayout, I have
defined a background color, and in the RelativeLayout I have defined a margin of 20. It
does not matter where the individual widgets are placed, but are overall settings that are
even independent of the current layout manager.

For the first TextView widget, I changed the name to lblHead1, and then I have defined a
margin of 10 below the component. I have also changed the text (the text to be displayed
on the screen) and I have defined a font size.

The next TextView widget I have called the lblDist, and then I have with android:layout_below
defined that the component should be under lblHead1. This is where the relative layout
comes in. Then, with android:layout_alignBaseLine, I have defined the text to be displayed
on the same baseline as for the following component, which is the input field, and the goal
is to get the two widgets aligned vertically relative to each other. Here you should especially
note that in XML is allowed to refer to a widget (txtDist) that is not yet been defined. It is
the next widget that is defined and in addition to the name being changed to txtDist, note
that android:layout_width has been changed to fill_parent which means that the component
width should fill the rest of the space as the parent component (here a RelativeLayout) has
set aside, that is, it needs to use the rest of the window width. In addition, three attributes
are defined where with android:layout_toEndOf, the component should be located to the
right of the TextField component and with android:layout_below that it should sit under the
header text and finally with android:layout_marginLeft that there is some space between the
input field and the text in front.

The next widget is a RadioGroup. There is not much to explain here, but I have given it a
name and defined that it should be below the input field and that there must be a margin
of 10 to the input field. As for the two RadioButton widgets, there is also not much to
notice except that I have changed the names again and indicate that the first one must
be checked. Also note the attribute android:layout_weight. It is actually not necessary but
inserted by Android Studio and means that the entire height is to be used, but in other
contexts it is important.

Next, follows the two (top) buttons, and compared to what has already been explained,
there is nothing new, but you should note that for both buttons are defined event handlers.

The rest of the XML code is, in principle, just a repeat of the above, and the result of all
is that the individual widgets are laid out nicely adjusted to each other. The procedure may
sound a little bit comprehensive, and it is, but with a little practice it is actually a quite safe
and also relatively effective way to design a complex window. The actual window is actually
relative to mobile phones complex and should rarely be more complex.

46
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Layout

You should note that this time I have not defined texts as resources, but directly in the
XML code. There are no reasons, only for making it simple to write the code. Back there
is the Java code, and here the class Converter is expanded with two new static conversion
methods. The class MainActivity now has four event handlers for each of the four buttons.
They are all simple and I do not want to display the code here. Then the application is
complete and can be translated and tested in the emulator and can even be installed on a
phone as described in the introductory chapter.

3.2 LINEARLAYOUT
In the first examples of this book, I have used a LinearLayout, which is a layout manager
that composes components in a row or a column. It can instantly be compared to a VBox
and a HBox in JavaFX, and like JavaFX (and Swing) layout managers can be nested and
you can solve many layout challenges using a LinearLayout. The example shown below is
called ButtonApp and puts 6 buttons on the screen using two nested LinearLayout managers:

47
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Layout
Layout

The
The application
application does
does nothing
nothing butbut show
show the
the 66 buttons
buttons and
and they
they have
have no
no function
function so
so the
the
only
only code
code that
that isis to
to show
show isis main_activity.xml:
main_activity.xml:

<?xml version="1.0" encoding="utf-8"?>


<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="dk.data.torus.buttonapp.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:padding="20dp"
android:layout_weight="1"

48
48
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

android:textSize="24dp"
android:text="A" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:padding="10dp"
android:layout_weight="1"
android:textSize="24dp"
android:text="B" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="30dp"
android:padding="20dp"
android:layout_weight="1"
android:textSize="24dp"
android:text="C" />
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24dp"
android:layout_weight="2"
android:layout_gravity="center"
android:text="D" />
<Button
android:layout_width="50dip"
android:layout_height="wrap_content"
android:textSize="24dp"
android:layout_weight="1"
android:layout_gravity="right"
android:text="E" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24dp"
android:layout_weight="3"
android:text="F" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>

The layout
The layout starts
starts with
with aa LinearLayout
LinearLayout and
and itit has
has an
an attribute
attribute android:orientation
android:orientation that
that tells
tells that
that
the components
the components shouldshould toto be
be vertically
vertically positioned.
positioned. The The first
first element
element isis aa new
new LinearLayout
LinearLayout
and hence
and hence aa nested
nested layout,
layout, and
and its
its orientation
orientation is is instead
instead horizontal.
horizontal. Here
Here youyou should
should note
note
that itit sets
that sets android:layout_height
android:layout_height to to wrap_content
wrap_content so so itit does
does not
not take
take over
over the
the entire
entire window.
window.

49
49
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Layout

The inner LinearLayout contains three buttons with the texts A, B and C respectively, and
the result is that they are laid out horizontally. For each button, a margin is defined that
indicates how much space there should be outside of the button. A padding is also defined,
and it specifies how the distance should be from the text to the edges of the component (if
it is a component with a frame). For all three buttons, android:layout_weight are 1, which
indicates that they have to share the space equally and thus get the same width.

The outer LinearLayout has, in addition to the LinearLayout element above, three buttons,
which are then vertically laid out below the layout with the buttons A, B and C. The three
lower buttons D, E and F have the weights 2, 1 and 3. This means that they share the
vertical space in the ratios 2/6, 1/6 and 3/6. With respect to the width of the components,
note that for D, the width is determined of the content, while for E an absolute width is
given. For F, it is the width of the parent and thus the width of the window. You should
also note the attribute android:layout_gravity, which indicates alignment.

Previously, LinearLayout was a very used layout manager, and it still makes sense in situations
where a very simple layout is needed.

Join the best at Top master’s programmes


• 3
 3rd place Financial Times worldwide ranking: MSc
the Maastricht University International Business
• 1st place: MSc International Business
School of Business and • 1st place: MSc Financial Economics
• 2nd place: MSc Management of Learning

Economics! • 2nd place: MSc Economics


• 2nd place: MSc Econometrics and Operations Research
• 2nd place: MSc Global Supply Chain Management and
Change
Sources: Keuzegids Master ranking 2013; Elsevier ‘Beste Studies’ ranking 2012;
Financial Times Global Masters in Management ranking 2012

Maastricht
University is
the best specialist
university in the
Visit us and find out why we are the best! Netherlands
(Elsevier)
Master’s Open Day: 22 February 2014

www.mastersopenday.nl

50
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Layout

3.3 TABLELAYOUT
I used this layout manager in the previous chapter in the connection with the zip code
application, and I do not want to show another examples, but in fact there is a lot more to
explain. The best to do is to think of it as an HTML table, and it supports concepts like
colspan and placement of widgets in specific columns, but basically it’s a layout manager
that’s easy to use.

3.4 GRIDLAYOUT
There is also a layout manager called GridLayout and, in principle, it corresponds to a GridPane
in JavaFX. Basically, it is a layout manager that divides the screen into a number of cells, and
you can then load components into the manager, and if nothing else, it will put all widgets in
a large row, but you can specify a number of columns that so indicates how many columns
there should be. You can also define the number of rows and you can also define a span for
the individual cells. The IntCalc program is a simple calculator with the following layout:

The calculator works alone on integers, thus performing, for example, integer division. The
input field is read-only, and you can only enter numbers by clicking the buttons. Expressions
must be entered in postfix form, thus entering the operator after the arguments. For example,
if you want to calculate

23 + 19

51
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Layout
Layout

then
then you
you must
must enter
enter 23
23 and
and click
click on
on Enter,
Enter, which
which means
means that
that 23
23 will
will be
be saved
saved on
on aa stack.
stack.
Then
Then enter
enter 19,
19, and and then
then click
click on
on the
the plus
plus button
button and and the
the program
program calculates
calculates the
the sum
sum ofof
the
the content
content of
of thethe display
display and
and the
the number
number popped
popped from from the
the stack,
stack, after
after which
which the
the display
display isis
updated
updated with
with the
the result.
result. The
The commands
commands in in the
the bottom
bottom row row may
may not
not be
be quite
quite obvious,
obvious, but
but !!
determines
determines thethe factorial
factorial of
of the
the content
content ofof the
the display,
display, ^^ isis power
power raising
raising while
while __ changing
changing
the
the sign
sign of
of the
the content
content ofof the
the display.
display. Finally,
Finally, CC isis command
command that that deletes
deletes the
the content
content ofof the
the
display,
display, but
but itit simultaneously
simultaneously deletes
deletes the
the content
content of of the
the stack,
stack, although
although itit should
should probably
probably
be two commands.
be two commands.

The
The program
program isis made
made simple
simple and and consists
consists solely
solely of
of activity_main.xml
activity_main.xml and
and MainActivity.java.
MainActivity.java.
The
The XML
XML section
section fills
fills aa lot,
lot, and
and II have
have only
only shown
shown aa smaller
smaller part
part below,
below, as
as the
the rest
rest alone
alone
refers to more buttons, which, of course, are, in principle, identical:
refers to more buttons, which, of course, are, in principle, identical:

<?xml version="1.0" encoding="utf-8"?>


<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="dk.data.torus.intcalc.MainActivity">
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="5">
<EditText
android:id="@+id/txtDisplay"
android:layout_width="0dp"
android:layout_height="60dp"
android:layout_columnWeight="1"
android:layout_gravity="fill_horizontal"
android:textSize="24dp"
android:layout_columnSpan="5" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_columnWeight="1"
android:gravity="center"
android:layout_gravity="fill_horizontal"
android:textSize="24dp"
android:onClick="modClicked"
android:text="%" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_columnWeight="1"

52
52
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

android:gravity="center"
android:layout_gravity="fill_horizontal"
android:textSize="24dp"
android:onClick="divClicked"
android:text="/" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_columnWeight="1"
android:gravity="center"
android:layout_gravity="fill_horizontal"
android:textSize="24dp"
android:onClick="mulClicked"
android:text="*" />

</GridLayout>
</android.support.constraint.ConstraintLayout>

First,
First, note
note that
that aa GridLayout
GridLayout is
is defined
defined with
with 5
5 columns.
columns. Here
Here you can also
you can also specify
specify the
the number
number
of
of rows,
rows, but
but it
it is
is not
not necessary
necessary as
as the
the rows
rows are
are determined
determined from
from the
the XML
XML code.
code. The
The first
first

53
53
JAVA
JAVA16:
16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
SOFTWARE
SOFTWAREDEVELOPMENT
DEVELOPMENT Layout
Layout

widget
widgetisisananEditText
EditTextand
andyou youshould
shouldnote
notethat
thatitsitswidth
widthisisset
settoto0.0.This
Thisisisbecause
becausethe the
width
widthisisdetermined
determinedby bya aweight
weightattribute
attributeand
anda agraverty
gravertyattribute,
attribute,which
whichare arethe
theattributes
attributes
that
thata aGridLayout
GridLayoutuses
usestotodetermine
determinehow howmuch
muchcomponents
componentsshould shouldfill.
fill.Also
Alsonote
notethat
thata a
columnSpan
columnSpanofof55isisdefined
definedfor forthis
thiscomponent
componentasasthe themachine’s
machine’sdisplay
displayshould
shouldfill
fillthe
thefull
full
width
widthofofthe
thewindow.
window.Finally,
Finally,notenotethat
thatthe
thecomponent
componenthas hasananIDIDasasititshould
shouldbebereferred
referred
totoininthe
theJava
Javacode,
code,but
butititisisalso
alsothe
theonly
onlyone
oneofofthe
thelayout’s
layout’swidgets
widgetsthat
thathashasananID.ID.

All
Allthe
theremaining
remaining(20) (20)widgets
widgetsare
areButton
Buttoncomponents,
components,and andininfact
factthere
thereisisnot
notmuch
muchtoto
note
notebeyond
beyondwhich
whichattributes
attributesare
aredefined
definedfor
forthethesize.
size.Since
Sinceweight
weightanywhere
anywhereisis1,1,ititmeans
means
that
thatthey
theyallallget
getthe
thesame
samewidth
widthasasgravirty
gravirtyisisset
settotofill_horizontal.
fill_horizontal.

The
TheJava
Javacode
codealso
alsofills
fillsasasthere
thereare
are20
20event
eventhandlers,
handlers,and
andthe
thefollowing
followingisisonly
onlya apart
partofof
the
thecode:
code:

package dk.data.torus.intcalc;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.*;
import android.widget.*;
import java.util.*;

public class MainActivity extends AppCompatActivity


{
private Stack<Long> stack = new Stack();
private boolean newValue = false;

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText text = (EditText) findViewById(R.id.txtDisplay);
text.setKeyListener(null);
text.setEnabled(false);
}

public void oneClicked(View view)


{
insert(view, "1");
}

54
54
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

public void addClicked(View view)


{
calc2(view, '+');
}

private void insert(View view, String ch)


{
EditText text = (EditText) findViewById(R.id.txtDisplay);
try
{
if (newValue)
{
long value = Long.parseLong(text.getText().toString());
stack.push(value);
text.setText(ch);
newValue = false;
}
else text.setText(text.getText() + ch);
}
catch (Exception ex)
{
text.setText("Error");
}
}

private void calc2(View view, char opr)


{
EditText text = (EditText) findViewById(R.id.txtDisplay);
try
{
long value2 = Long.parseLong(text.getText().toString());
long value1 = stack.pop();
switch (opr)
{
case '+': value1 += value2; break;
case '-': value1 -= value2; break;
case '*': value1 *= value2; break;
case '/': value1 /= value2; break;
case '%': value1 %= value2; break;
case '^': value1 = (long)Math.pow(value1, value2);
}
text.setText("" + value1);
newValue = true;
}

55
55
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

catch (Exception ex)


{
text.setText("Error");
}
}

The class has two instance variables, where the first one is the stack, while the other is
The class has two instance variables, where the first one is the stack, while the other is
used to control whether the content of the display should be placed on the stack when
used to control whether the content of the display should be placed on the stack when
clicking on a digit. The constructor is expanded with two statements used to set the display
clicking on a digit. The constructor is expanded with two statements used to set the display
read-only so that you can not directly enter numbers. Note that this means that no virtual
read-only so that you can not directly enter numbers. Note that this means that no virtual
keyboard is displayed.
keyboard is displayed.

If you click on a button for a digit, the method insert() is performed. It tests the variable
If you click on a button for a digit, the method insert() is performed. It tests the variable
newValue, and if it is true, it means entering a new number and the method tries to parse
newValue, and if it is true, it means entering a new number and the method tries to parse
the content of the display into an integer and put it on the stack. Then the digit that is
the content of the display into an integer and put it on the stack. Then the digit that is
clicked on is inserted as the value of the display. If newValue is false, nothing else happens
clicked on is inserted as the value of the display. If newValue is false, nothing else happens
than the digit that is clicked is added to the content of the display.
than the digit that is clicked is added to the content of the display.

Need help with your


dissertation?
Get in-depth feedback & advice from experts in your
topic area. Find out what you can do to improve
the quality of your dissertation!

Get Help Now

Go to www.helpmyassignment.co.uk for more info

56
56
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Layout
Layout

Clicking
Clicking on on an
an operator
operator with with two
two arguments,
arguments, the
the event
event handler
handler calls
calls the
the method
method clac2().
clac2().
ItIt parses
parses the
the content
content of of the
the display
display andand pops
pops the
the stack
stack and
and execute
execute thethe actual
actual calculation,
calculation,
after
after which
which the
the display
display isis updated.
updated. Note
Note that
that newValue
newValue isis set
set to
to true
true as
as the
the result
result must
must be be
added
added to to the
the stack
stack next
next timetime aa button
button isis clicked.
clicked. Instead,
Instead, click
click onon an
an operator
operator with
with only
only
one
one argument
argument (and(and itit will
will say
say for
for the
the current
current machine
machine !! and
and _)_) the
the method
method calc1()
calc1() isis called
called
that
that changes
changes thethe value
value of of the
the display.
display.

3.5
3.5 AA CONSTRAINTLAYOUT
CONSTRAINTLAYOUT
As
As the
the last
last layout
layout manager,
manager, II would
would like
like to
to mention
mention aa ConstraintLayout,
ConstraintLayout, which which isis the
the layout
layout
manager
manager thatthat Android
Android Studio
Studio defines
defines asas default
default for
for an
an activity.
activity. In In principle,
principle, itit works
works aa bit
bit
like
like aa RelativeLayout,
RelativeLayout, but but itit isis more
more flexible
flexible and
and the
the goal
goal isis that
that you
you can
can design
design aa complex
complex
layout
layout solely
solely using
using the
the mouse
mouse and and inin the
the Android
Android Studio’s
Studio’s layout
layout editor.
editor. That
That is, is, you
you can
can
drag
drag widgets
widgets to to the
the window
window from from the
the toolbox
toolbox and
and drag
drag itit into
into the
the wanted
wanted places
places with with the
the
mouse.
mouse. YouYou cancan thus
thus create
create the the finished
finished design
design without
without having
having to to write
write XML
XML yourself.
yourself.

To
To define
define the
the position
position ofof aa view
view component,
component, itit must
must have
have at
at least
least one
one horizontal
horizontal and
and at
at
least
least one
one vertical
vertical constraint,
constraint, each
each constraint
constraint being
being an
an attachment
attachment or or an
an alignment
alignment to to another
another
view
view oror parent
parent layout.
layout. Each
Each constraint
constraint thus
thus defines
defines aa view
view position
position along
along either
either aa horizontal
horizontal
or
or vertical
vertical axis,
axis, but
but often
often there
there will
will be
be more
more constraints
constraints for
for each
each axis.
axis.

IfIf you
you drop
drop aa view
view in
in the
the layout
layout editor,
editor, itit has
has no
no constraints,
constraints, but
but sits
sits where
where itit isis dropped.
dropped.
There
There are
are probably
probably some
some attributes,
attributes, and
and an an example
example could
could be:
be:

<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
tools:layout_editor_absoluteX="148dp"
tools:layout_editor_absoluteY="167dp" />

where
where the
the last
last two
two attributes
attributes tells
tells you
you where
where the
the component
component isis in in the
the layout
layout editor,
editor, but
but ifif
you
you run
run the
the program,
program, youyou will
will find
find that
that the
the button
button isis located
located in
in the
the upper
upper left
left corner,
corner, and
and
the
the two
two attributes
attributes therefore
therefore dodo not
not matter
matter to
to the
the finished
finished program.
program.

Below
Below isis the
the XML
XML code
code after
after II have
have also
also added
added an
an EditText
EditText widget
widget and
and then
then II have
have drawn
drawn
both
both views
views to to those
those positions
positions where
where II think
think they
they should
should be:
be:

57
57
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
tools:layout_editor_absoluteX="148dp"
tools:layout_editor_absoluteY="168dp" />
<EditText
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
tools:layout_editor_absoluteX="85dp"
tools:layout_editor_absoluteY="83dp" />

IfIf you
you now
now select
select aa view
view (and
(and asas esample
esample thethe EditText
EditText component),
component), you you will
will see
see four
four
small
small circles.
circles. IfIf you
you point
point toto one
one ofof them,
them, you
you can
can drag
drag the
the component
component against
against another
another
component
componentor orlayout,
layout,that
thatthis
thiscomponent
componentshouldshouldbebeplaced
placedininrelation
relationto.
to.Below
Belowititisisthe
the
layout
layoutmanager
manageritself.
itself.Next,
Next,youyoucan
canadjust
adjustthe
thedistance
distanceunder
underProperties
Propertiestotothe
theright
rightofofthe
the
window,
window,and andininthe thetoolbar
toolbaryouyoucan
canspecify
specifyalignment.
alignment.

After
AfterI’ve
I’vedone
doneititfor
forboth
bothwidgets,
widgets,the
theXML
XMLcode
codeis:
is:

<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"

58
58
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

android:layout_marginTop="24dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editText" />
<EditText
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="46dp"
android:layout_marginStart="8dp"
android:layout_marginTop="32dp"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

Brain power By 2020, wind could provide one-tenth of our planet’s


electricity needs. Already today, SKF’s innovative know-
how is crucial to running a large proportion of the
world’s wind turbines.
Up to 25 % of the generating costs relate to mainte-
nance. These can be reduced dramatically thanks to our
systems for on-line condition monitoring and automatic
lubrication. We help make it more economical to create
cleaner, cheaper energy out of thin air.
By sharing our experience, expertise, and creativity,
industries can boost performance beyond expectations.
Therefore we need the best employees who can
meet this challenge!

The Power of Knowledge Engineering

Plug into The Power of Knowledge Engineering.


Visit us at www.skf.com/knowledge

59
59
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Layout

and Android Studio has converted all editor constraints into actual constraints, after which
the program can be translated and run, and the components are located corresponding to
the above XML.

Of course, it requires a little learning how to use the layout editor, but if you do not
write Android applications every day, it’s worth the effort, because you’re free to keep in
mind the XML syntax, which is not everywhere, easy to understand. With the help of a
ConstraintLayout, you can design a full-featured app without meeting the XML code. On the
other hand, if you often write mobile apps, it can actually pay to work directly in XML. By
learning how to use the different layout managers and how to determine the position and
alignment of widgets, you get a very stable and safe layout, and you get fast very efficiently
to works on complex activities. Here you should be aware that you can always switch to
design mode to see how it all looks.

3.6 CONTAINERS
Android also offers multiple components that can display a family of objects. There are
widgets called containers, and although layout managers are not directly containers, they have
something to do with layout. In fact, I have already shown an example in the application
Zipcodes, which used a ListView, which is a container that can display a number of objects.
If the container contains more objects than there is room for on the screen, you can scroll
the content, and you can also associate an event handler with the container that fires each
time you select an object. In principle, the different containers are used in the same way
and use a data source with the current objects, the container itself, such as a ListView and
then an adapter that has the task to update the container. I will start with a program that
shows an overview of Danish kings:

60
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Layout
Layout

where
where there
there above
above are
are clicked
clicked onon Svend
Svend Estridsen
Estridsen with
with the
the result
result that
that the
the government
government period
period
appears
appears in
in the
the top
top two
two fields.
fields. The
The design
design of
of the
the user
user interface
interface isis quite
quite simple
simple and
and contains
contains
in
in addition
addition toto two
two LinearLayout
LinearLayout three
three widgets:
widgets:

<?xml version="1.0" encoding="utf-8"?>


<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"
android:background="#E5E532"
tools:context="dk.data.torus.thekings.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="20dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/txtFrom"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"

61
61
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

android:textSize="24dp"
android:layout_marginRight="5dp"
android:padding="10dp"
android:textColor="#FFFFFF"
android:background="#FF0000"/>
<EditText
android:id="@+id/txtTo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="24dp"
android:layout_marginLeft="5dp"
android:padding="10dp"
android:textColor="#FFFFFF"
android:background="#FF0000"/>
</LinearLayout>
<ListView
android:id="@+id/lstKings"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"/>
</LinearLayout>
</android.support.constraint.ConstraintLayout>

62
62
JAVA
JAVA16:
16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
SOFTWARE
SOFTWAREDEVELOPMENT
DEVELOPMENT Layout
Layout

There
Thereare
aretwo
twoEditText
EditTextwidgets,
widgets,and andhere
hereisisnothing
nothingnewnewtotoexplain,
explain,but
butnote
notethe
thenames
namesand
and
which
whichattributes
attributesthat
thatare
aredefined.
defined.The
Thelatter
latterisisaaListView,
ListView,where
wherethere
thereisisnothing
nothingtotonotice
notice
besides
besidesthe
thename,
name,but
butititisisaacontainer
containerand
andthethewidget
widgettotobe
beinitialized
initializedwith
withdata,
data,and
andtoto
which
whichan anevent
eventhandler
handlerisistotobebeattached.
attached.ItIthappens
happensininthe
theJava
Javacode.
code.

First,
First,the
thedata
dataresource
resourceand
andthe
thestarting
startingpoint
pointisisthe
thefollowing
followingmodel
modelclass:
class:

package dk.data.torus.thekings;

public class King


{
private String name;
private int from;
private int to;

public King(String name, int from, int to)


{
this.name = name;
this.from = from;
this.to = to;
}

public String getName()


{
return name;
}

public int getFrom()


{
return from;
}

public int getTo()


{
return to;
}

public String toString()


{
return name;
}
}

ItItisisalso
alsoaavery
verysimple
simpleclass
classthat
thatdoes
doesnot
notcontain
containanything
anythingother
otherthan
thanwhat
whatthe
thecurrent
current
program needs, and here you should especially note the method toString() which returns
program needs, and here you should especially note the method toString() which returns

63
63
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA
JAVA16:
16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
SOFTWARE DEVELOPMENT Layout
SOFTWARE
SOFTWAREDEVELOPMENT
DEVELOPMENT Layout
Layout

the
the value
thevalue that
valuethat appears
thatappears for
appearsfor each
foreach object
objectinin
eachobject the
inthe ListView
theListView container.
container.AsAs
ListViewcontainer. the
Asthe second
thesecond part
partofof
secondpart the
ofthe
the
data
data resource,
dataresource, the
resource,the class
theclass Kings
classKings makes
Kingsmakes the
makesthe current
thecurrent King
currentKing objects
Kingobjects available:
objectsavailable:
available:

package dk.data.torus.thekings;
package dk.data.torus.thekings;

import java.util.*;
import java.util.*;

public class Kings


public class Kings
{
{
private List<King> list = new ArrayList();
private List<King> list = new ArrayList();

public Kings()
public Kings()
{
{
for (String[] arr : data)
for (String[] arr : data)
list.add(new King(arr[0], Integer.parseInt(arr[1]),
list.add(new King(arr[0], Integer.parseInt(arr[1]),
Integer.parseInt(arr[2])));
Integer.parseInt(arr[2])));
}
}

public List<King> getKings()


public List<King> getKings()
{
{
return list;
return list;
}
}

private static final String[][] data = {


private static final String[][] data = {
{ "Gorm den Gamle", "0", "958" },
{ "Gorm den Gamle", "0", "958" },
{ "Harald Blåtand", "958", "987" },
{ "Harald Blåtand", "958", "987" },


};
};
}
}

where
whereI IIhave
where haveonly
have onlyshown
only shownfew
shown fewdata.
few data.The
data. Theclass
The classisis
class isofof
ofcourse
coursepseudo
course pseudoasas
pseudo asallall
alldata
dataare
data arehard-coded
are hard-coded
hard-coded
and
and it is clear that this data should come from another source such as a file, databaseoror
andititisisclear
clearthat
that this
this data
datashould
should come
come from
from another
another source
source such
such asasa afile,
file,database
database or
equivalent,
equivalent, but
butsince
sinceI Ihave
havenot
notyet
yetshown
shown how,
how, ititmust
must wait
waitfor
forlater
later
equivalent, but since I have not yet shown how, it must wait for later , but it does not , ,but
but ititdoes
doesnot
not
change
changethe
change theprinciple.
the principle.
principle.

An
Anadapter
An adapterisis
adapter isactually
actuallya aabasic
actually basicconcept
basic conceptinin
concept inAndroid,
Android,and
Android, andthe
and thegoal
the goalisis
goal istoto
todisconnect
disconnectthe
disconnect thedata
the data
data
source
source from
from the
the presentation,
presentation, soso that
thatforforthe
the programmer
programmer itithappens
happens
source from the presentation, so that for the programmer it happens in the same way, in
in the
thesame
same way,
way,
regardless
regardlessofof
regardless ofwhich
whichdata
which datasource
data sourceitit
source itisis
isand
andregardless
and regardlessofof
regardless ofwhich
whichlist
which listwidget
list widgetisis
widget isused
usedtoto
used todisplay
display
display
the
thedata.
data. InInthis
thiscase, the
case, thecode
code ofofthe
theclass
class isisin
inthe
theclass
classMainActivity:
MainActivity:
the data. In this case, the code of the class is in the class MainActivity:

package dk.data.torus.thekings;
package dk.data.torus.thekings;

import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Bundle;
import android.view.*;
import android.view.*;

64
64
64
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

import android.widget.*;
import android.widget.AdapterView.*;
import java.util.*;

public class MainActivity extends AppCompatActivity


{
private List<King> kings = (new Kings()).getKings();
private EditText from;
private EditText to;

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
from = (EditText) findViewById(R.id.txtFrom);
to = (EditText) findViewById(R.id.txtTo);
disable(from);
disable(to);
ListView view = (ListView) findViewById(R.id.lstKings);
view.setAdapter(new ArrayAdapter<King>(this,
android.R.layout.simple_list_item_1, kings));

65
65
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

view.setOnItemClickListener(new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, final int position,
long id)
{
update(position);
}
});
}

public void update(int position)


{
int a = kings.get(position).getFrom();
int b = kings.get(position).getTo();
from.setText(a == 0 ? "" : "" + a);
to.setText(b == 9999 ? "" : "" + b);
}

private void disable(EditText view)


{
view.setKeyListener(null);
view.setEnabled(false);
}
}

Initially, a list of objects of the type King is created, which is then the program’s data
source. In addition, variables are defined for the two EditText components, and they are
both initialized in onCreate(). In addition, for both objects, the method disable() is called,
which disables both input fields so that you can not enter text. Next, a reference to the
ListViev component is defined and initialized with an adapter:

new ArrayAdapter<King>(this, android.R.layout.simple_list_item_1, kings)

The type is ArrayAdapter which is an adapter used for a data source that is an array or
a list and thus a data source where the individual objects are indentified by an index. In
addition, a parameter (for the generic type) tells that the adapter represents King objects.
The constructor has three parameters, where the first is the object (here the current object)
to which the container has to initialize is a member, while the last parameter is the data
resource. Then there is the middle parameter that tells how the objects should be presented
by the container, and here it is a constant whose meaning is not easy to understand, but
it tells that an object should be presented as a string and thus that it is the value of the
object’s toString() method to de displayed.

66
66
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Layout

As the last, an event handler is attached to the ListView component, and it happens with the
method setOnItemClickListener(), where the parameter is an OnItemClickListener, which is an
interface that defines the event handler. It has four parameters, where the most important
is position, which indicates the index of the object that is clicked (tabbed with the finger).
In this case, it performs the method update(), which updates the two top input fields with
the king’s government period.

I want to show a variation of the above application, which I have called SelectKings. The
program opens the following phone, which again shows the Danish kings, but this time
there are two ListView components, where the top shows the kings selected in the bottom.
At the bottom you can this time select objects using checkboxes and you can select multiple
and select more objects. In the example, there are selected two, and if you uncheck the
checkboxes, the names disappear from the top ListView.

Again, the program consists of an XML file for defintion of the user interface, as well as
the class MainActivity (and the model classes King and Kings), and the program primarily
shows how to dynamically update the user interface using an adapter.

67
JAVA 16:
JAVA 16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE DEVELOPMENT
SOFTWARE DEVELOPMENT Layout
Layout

The
The layout
layout in
in the
the XML
XML file
file isis this
this time
time the
the following:
following:

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="20dp">
<ListView
android:id="@+id/lstKings1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginBottom="20dp"/>
<ListView
android:id="@+id/lstKings2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:choiceMode="multipleChoice"
android:drawSelectorOnTop="false" />
</LinearLayout>

Challenge the way we run

EXPERIENCE THE POWER OF


FULL ENGAGEMENT…

RUN FASTER.
RUN LONGER.. READ MORE & PRE-ORDER TODAY
RUN EASIER… WWW.GAITEYE.COM

1349906_A6_4+0.indd 1 22-08-2014 12:56:57


68
68
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Layout
Layout

There
There isis not
not much
much to to note,
note, but
but you
you should
should notice
notice how
how toto indicate
indicate in
in the
the bottom
bottom that
that
select
select multiple
multiple should
should bebe possible.
possible. In
In addition,
addition, note
note how
how in
in the
the design
design with
with layout_weight
layout_weight
to
to define
define that
that the
the two
two components
components should
should share
share the
the space
space equally.
equally. The
The most
most important
important
thing
thing happens
happens in in the
the Java
Java part,
part, and
and here
here the
the classes
classes King
King and
and Kings
Kings are
are unchanged
unchanged while
while
MainActivity
MainActivity isis changed:
changed:

package dk.data.torus.selectkings;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.*;
import android.widget.*;
import android.widget.AdapterView.*;
import java.util.*;

public class MainActivity extends AppCompatActivity


{
private List<King> kings = (new Kings()).getKings();
private List<String> lines = new ArrayList();
private ListView view;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view = (ListView) findViewById(R.id.lstKings1);
ListView view2 = (ListView) findViewById(R.id.lstKings2);
view2.setAdapter(new ArrayAdapter<King>(this,
android.R.layout.simple_list_item_multiple_choice, kings));
view2.setOnItemClickListener(new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, final int position,
long id)
{
update(kings.get(position));
}
});
}

private void update(King king)


{
String line = toString(king);
if (!lines.remove(line)) lines.add(line);
view.setAdapter(new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_1, lines));
}

69
69
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Layout
SOFTWARE DEVELOPMENT Layout

private String toString(King king)


{
if (king.getFrom() != 0 && king.getTo() != 9999)
return String.format("%s: %d – %d", king.
getName(), king.getFrom(), king.getTo());
if (king.getFrom() != 0)
return String.format("%s: %d -", king.getName(), king.getFrom());
if (king.getTo() != 9999)
return String.format("%s: – %d", king.getName(), king.getTo());
return king.getName();
}
}

Same as in the previous example, a List of King objects is created that is used as data source
for the bottom ListView. In addition, another list is created for strings that is used as data
source for the top ListView, and a reference to the top ListView is also defined. The reason
is that you do not have to find the reference each time you clicks on the bottom ListView.
This reference is initialized in onCreate(). Here, the bottom ListView is also initialized, in
principle similar to the previous example, but this time another parameter for the second
parameter to the adapter is used:

android.R.layout.simple_list_item_multiple_choice

It says that the King objects this time not only should be displayed as strings but with a
subsequent checkbox and that it should be possible to select multiple. Instead, if you had
only been able to select single, you would instead have written:

android.R.layout.simple_list_item_single_choice

The bottom ListView has in the same way as in the previous example attached an event
The bottom
handler, but itListView
performshassomething
in the same way now.
different as in The
the method
previousupdate()
exampleconverts
attachedtheancurrent
event
handler, but into
King object it performs
a string,something
and if thisdifferent
string isnow. The method
already update()
in data source converts
lines, the current
it is deleted and
King objectadded.
otherwise into aAnstring, andisif then
adapter this string
used tois update
already the
in data source lines, it is deleted and
top ListView.
otherwise added. An adapter is then used to update the top ListView.

70
70
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Layout

As the last example of kings, the program SpinKings opens the following window:

This e-book
is made with SETASIGN
SetaPDF

PDF components for PHP developers

www.setasign.com

71
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Layout
Layout

The
The program
program isis almost
almost identical
identical to
to the
the program
program TheKings,
TheKings, and
and there
there isis only
only one
one difference
difference
that
that instead
instead ofof aa ListView,
ListView, aa Spinner
Spinner isis used,
used, which
which corresponds
corresponds toto aa ComboBox,
ComboBox, as as you
you
know
know itit from
from Swing
Swing or or JavaFX.
JavaFX. The
The code
code isis essentially
essentially the
the same
same as
as well,
well, and
and for
for the
the XML
XML
part,
part, there is only one difference in which the ListView element has been replaced with aa
there is only one difference in which the ListView element has been replaced with
Spinner
Spinner element:
element:

<Spinner
android:id="@+id/lstKings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawSelectorOnTop="true"
android:layout_marginTop="20dp"/>

Regarding
Regarding the
the Java
Java code,
code, the
the two
two model
model classes
classes King
King and
and Kings
Kings are
are unchanged,
unchanged, but
but the
the class
class
MainActivity is changed, and it is only the method onCreate():
MainActivity is changed, and it is only the method onCreate():

protected void onCreate(Bundle savedInstanceState)


{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
from = (EditText) findViewById(R.id.txtFrom);
to = (EditText) findViewById(R.id.txtTo);
disable(from);
disable(to);
Spinner view = (Spinner) findViewById(R.id.lstKings);
view.setAdapter(new ArrayAdapter<King>(this,
android.R.layout.simple_spinner_item, kings));
view.setOnItemSelectedListener(new OnItemSelectedListener()
{
@Override
public void onItemSelected(AdapterView<?> parent,
View view, int position,long id)
{
update(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent)
{
from.setText("");
to.setText("");
}
});
}

Here
Here isis the
the most
most important
important of
of course
course the
the event
event handler,
handler, that
that this
this time
time has
has another
another listener,
listener,
which
which isis an
an interface
interface that
that defines
defines two
two methods.
methods.

72
72
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Layout

EXERCISE 3: PEOPLE1
Start by creating a copy of the project from exercise 2. You can call the copy for People1. You
must add a few changes. The user interface must be almost the same. The only difference is
that a new button must be added (see below). Once you have entered one or more persons
and they have been inserted into the ListView container, you must be able to click on a
person, and the name of the person must then be inserted into the two top input fields so
the names can be edited. When you click OK, no new person should be added, but the list
should be updated with the changed name. If you have clicked on a name and it is inserted
in the input fields, you must also be able to delete the name by clicking the new button.

Note that the new button from the start is disabled, and it must be enabled only if a name
has been clicked in the list.

73
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT User interaction

4 USER INTERACTION
In this chapter I will look a little more on the basic user interaction, including how to use
menus and dialogs. However, I want to start with the virtual keyboard.

An Android device may well have a hardware keyboard, but most devices, including
smartphones, have a virtual keyboard that pops up when you click in an input field. An
input field is an EditText widget, but if you look at the design editor under the Text palette,
you will see that there are many options, and each option tells you how to display the
content, but primarily which virtual keyboard to use:

Free eBook on
Learning & Development
By the Chief Learning Officer of McKinsey

Download Now

74
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT User interaction

Each line will insert an EditText view, and the different options indicate the value of the
attribute InputType. As you can see, there are many options, and in particular, you should
note that there are attributes to typical tasks like entering text, email addresses, numbers,
and so on. It is important to note that the attribute InputType primarily tells how the
virtual keyboard should look and thus which keys there are. For example, if you have
chosen Number, you will get a keyboard that only has keys to digits, sign on and thus a
very limited keyboard:

Note that you can not switch to a keyboard with letters. The program EnterText can be
used to experiment and show the meaning of the virtual keyboards. The program opens a
window that contains 5 TextView widgets and 5 EditText widgets. I do not want to show
activity_main.xml here because the only thing to note is the value of the attribute InputText,
but you should note the following:

-- The top one is blank, which means you can enter anything.
-- The next has the value textPassword, which means that what you enter appears as dots.
-- The third has the value number and means that you can enter integers.
-- The fourth has the value numberDecimal so you can enter decimal numbers.
-- The latter has the value textMultiline and means that you can enter more lines, and
then as what you know as a TextArea.

75
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT User
user interaction
InteraCtIon

As
As mentioned
mentioned above,
above, II willwill not
not show
show the
the XML
XML code
code as
as itit fills
fills aa lot
lot without
without adding
adding so
so
much
much new.
new. Basically,
Basically, itit is
is aa TableLayout
TableLayout with
with TextView
TextView and
and EditText
EditText widgets,
widgets, but
but the
the layout
layout
manager
manager is
is placed
placed in
in aa ScrollView:
ScrollView:

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp">

</TableLayout>
</ScrollView>

This
This means
means that
that the
the user
user can
can scroll
scroll the
the content
content vertically.
vertically. If
If you
you want
want to
to scroll
scroll horizontally,
horizontally,
use
use aa HorizontalScrollView
HorizontalScrollView instead.
instead.

4.1
4.1 AA CONTEXT
CONTEXT MENU
MENU
Menus
Menus are
are frequently
frequently used
used in
in mobile
mobile phone
phone apps,
apps, and
and in
in this
this section
section II will
will show
show you
you how
how to
to
attach a context menu to a control. As example, I will use the program TheKings,
attach a context menu to a control. As example, I will use the program TheKings, as I have as I have
shown
shown above,
above, where
where II want
want toto attach
attach aa context
context menu
menu forfor the
the single
single kings
kings in
in the
the ListView
ListView

76
76
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT User
user interaction
InteraCtIon

component.
component. II have
have started
started with
with aa copy
copy of
of the
the project,
project, which
which II have
have called
called AboutKings.
AboutKings. The
The
user
user interface
interface is
is exactly
exactly the
the same,
same, soso the
the changes
changes concern
concern only
only the
the Java
Java section.
section. Therefore,
Therefore,
II do
do not
not want
want toto show
show the
the XML
XML codecode for
for the
the user
user interface
interface again.
again.

The
The class
class Kings
Kings contains
contains aa static
static array,
array, where
where data
data for
for Danish
Danish kings
kings are
are defined
defined as
as constants.
constants.
For
For each
each king
king there
there are
are three
three values,
values, but
but the
the array
array is
is expanded
expanded with
with aa fourth
fourth value,
value, which
which
is
is aa brief
brief description
description of
of the
the current
current king.
king. The
The information
information isis obtained
obtained from
from

http://kongehuset.dk/monarkiet-i-danmark/kongerakken

but
but regarding
regarding the
the program,
program, the
the information
information is is not
not critical
critical (it’s
(it’s just
just aa text)
text) and
and the
the text
text is
is
not
not translated
translated into
into English.
English. Similar
Similar to
to this
this extension,
extension, the
the class
class King
King isis also
also expanded
expanded with
with
an
an additional
additional attribute
attribute that
that returns
returns that
that description,
description, and
and the
the class
class is
is expanded
expanded by by aa method
method
getKing(),
getKing(), which
which returns
returns aa string
string that
that is
is the
the king’s
king’s name
name and
and government
government period.
period.

www.sylvania.com

We do not reinvent
the wheel we reinvent
light.
Fascinating lighting offers an infinite spectrum of
possibilities: Innovative technologies and new
markets provide both opportunities and challenges.
An environment in which your expertise is in high
demand. Enjoy the supportive working atmosphere
within our global group and benefit from international
career paths. Implement sustainable ideas in close
cooperation with other specialists and contribute to
influencing our future. Come and join us in reinventing
light every day.

Light is OSRAM

77
77
JAVA
JAVA16:
16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
SOFTWARE
SOFTWAREDEVELOPMENT
DEVELOPMENT User
userinteraction
InteraCtIon

Then
Thenthere’s
there’sthe
theclass
classMainActivity,
MainActivity,which
whichisisexpanded
expandedaalot:
lot:

public class MainActivity extends AppCompatActivity


{
public static final int MENU_NAME = Menu.FIRST + 1;
public static final int MENU_TEXT = Menu.FIRST + 2 ;
private List<King> kings = (new Kings()).getKings();
private EditText from;
private EditText to;

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
from = (EditText) findViewById(R.id.txtFrom);
to = (EditText) findViewById(R.id.txtTo);
disable(from);
disable(to);
ArrayAdapter<King> adapter =
new ArrayAdapter<King>(this, android.R.layout.
simple_list_item_1, kings);
ListView view = (ListView) findViewById(R.id.lstKings);
view.setAdapter(adapter);
view.setOnItemClickListener(new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view,
final int position, long id) {
update(position);
}
});
registerForContextMenu(view);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo)
{
menu.add(Menu.NONE, MENU_NAME, Menu.NONE, "King");
menu.add(Menu.NONE, MENU_TEXT, Menu.NONE, "Description");
}

@Override
public boolean onContextItemSelected(MenuItem item)
{
AdapterView.AdapterContextMenuInfo menuInfo =
(AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
King king = kings.get(menuInfo.position);

78
78
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT User interaction
SOFTWARE DEVELOPMENT user InteraCtIon

switch (item.getItemId()) {
case MENU_NAME:
Toast.makeText(this, king.getKing(), Toast.LENGTH_LONG).show();
return (true);
case MENU_TEXT:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(king.getName());
builder.setMessage(king.getText());
builder.setPositiveButton("Close", new
DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
builder.show();
return (true);
}
return (super.onContextItemSelected(item));
}

public void update(int position)


{
int a = kings.get(position).getFrom();
int b = kings.get(position).getTo();
from.setText(a == 0 ? "" : "" + a);
to.setText(b == 9999 ? "" : "" + b);
}

private void disable(EditText view)


{
view.setKeyListener(null);
view.setEnabled(false);
}
}

First,
First, two
two constants
constants are
are defined
defined that
that define
define two
two menu
menu items
items in
in aa context
context menu.
menu. Actually,
Actually,
they
they must
must just
just be
be unique
unique integers,
integers, but
but the
the documentation
documentation recommends
recommends doing
doing it it as
as shown
shown
in
in this
this example,
example, asas Android
Android creates
creates other
other menu
menu items
items in
in other
other contexts,
contexts, and
and they
they must
must
have
have a unique identifier within the same activity. The last statement in onCreate() says that
a unique identifier within the same activity. The last statement in onCreate() says that
aa context menu must be registered for the program’s ListView component.
context menu must be registered for the program’s ListView component. If there were If there were
other
other widgets
widgets that
that should
should have
have aa context
context menu,
menu, they
they should
should bebe registered
registered in
in the
the same
same way.
way.

Then
Then there
there is
is the
the method
method onCreateContextMenu()
onCreateContextMenu() thatthat creates
creates the
the menu.
menu. InIn this
this case,
case, it
it is
is
simple with two menu items, but of course there could be more. Finally, there is
simple with two menu items, but of course there could be more. Finally, there is the event the event
handler,
handler, which
which inin this
this case
case is
is performed
performed every
every time
time aa menu
menu item
item is
is selected
selected in
in the
the context
context
menu.
menu. The
The parameter
parameter is is the
the menu
menu item
item that
that is
is selected.
selected. First
First of
of all,
all, which
which line
line is
is clicked
clicked

79
79
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT User interaction

and the corresponding King object is determined. If it is the first menu item, nothing
happens except a simple Toast with a text that is the king’s name and government period.
There it is a message that is shown over the window and automatically disappears after a
short period of time determined by the devic. All you can control is that a parameter can
indicate whether it takes a long time (few seconds = 3.5) or less time (= 2 seconds). Below
is the window in which the context menu is activated:

360°
thinking .

360°
thinking . 360°
thinking .
Discover the truth at www.deloitte.ca/careers D

© Deloitte & Touche LLP and affiliated entities.

Discover the truth at www.deloitte.ca/careers © Deloitte & Touche LLP and affiliated entities.

eloitte & Touche LLP and affiliated entities.

Discover the truth


80 at www.deloitte.ca/careers
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT User interaction

How to activate a context menu depends on the Android version (there are no mouse that
you can right-click), but in the newer Android versions it happens when you hold your
finger on the component until the menu pops up.

The second menu item opens an alert, which is a simple message box. You create an alert
with a sophisticated builder, which, as a parameter, that indicates the activity that should
be the owner. The builder then defines what should be in the title line and the message
itself. You must then define which buttons there should be. There may be two buttons that
you defines with the methods setPositiveButton() and setNegativeButton(), and in this case
there is only one. When you click on a button, the dialog closes no matter what button
it is, but an event handler is assigned for the button. In this case it is empty, but in other
situations an action could be performed when clicking the button.

As an example, below is shown how an alert looks after clicking on a name. What the text
tells is not important, but the text has been chosen so much that the entire text can not
be displayed, but you automatically get a scrollbar.

81
JAVA
JAVA16:
16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
SOFTWARE
SOFTWAREDEVELOPMENT
DEVELOPMENT User
userinteraction
InteraCtIon

4.2
4.2 AA MAIN
MAIN MENU
MENU
II will
will then
then show
show how
how toto define
define aa main
main menu,
menu, which
which isis called
called onon an
an option
option menu
menu in in Android.
Android.
As
As example,
example, II would
would like
like to
to use
use aa modified
modified version
version ofof the
the application
application SelectKings,
SelectKings, which
which II
have
have called
called MoreKings.
MoreKings. IfIf you
you open
open thethe program,
program, you you get
get aa window
window as as shown
shown below,
below, where
where
there
there isis aa ListView
ListView that
that shows
shows thethe kings
kings with
with aa checkbox,
checkbox, but but in
in the
the title
title bar,
bar, called
called the
the
ActionBar
ActionBarwindow,
window,there
thereare
arenow
nowthree
threevertical
verticaldots
dotsshowing
showingthat thatthere
thereisisaamenu.
menu.The Themenu
menu
has
has two
two menu
menu items,
items, where
where one
one menu
menu item
item deletes
deletes all
all the
the kings
kings with
with aa checkmark
checkmark in in the
the
checkboxes,
checkboxes, whilewhile the
the other
other menu
menu item
item performs
performs aa reset
reset and
and thus
thus reinsertes
reinsertes allall the
the kings.
kings.
The
The program
program still
still has
has the
the same
same context
context menu
menu as as in
in the
the previous
previous example.
example.

Due
Due to to the
the latter,
latter, the
the classes
classes King
King and
and Kings
Kings are
are replaced
replaced by
by the
the corresponding
corresponding classes
classes from
from
the
the previous
previous example.
example. activity_main.xml
activity_main.xml isis almost
almost identical
identical to
to the
the corresponding
corresponding filefile from
from
SelectKings
SelectKings withwith the
the one
one difference
difference that
that the
the one
one ListView
ListView component
component isis deleted,
deleted, so
so the
the XML
XML
part
part isis now
now quite
quite simple.
simple. The
The new
new things
things to
to note
note therefore
therefore only
only concerns
concerns MainActivity.java:
MainActivity.java:

package dk.data.torus.selectkings;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.*;
import android.widget.*;

82
82
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT User interaction
SOFTWARE DEVELOPMENT user InteraCtIon

import android.util.*;
import android.app.AlertDialog;
import android.content.*;
import java.util.*;

public class MainActivity extends AppCompatActivity


{
public static final int MENU_NAME = Menu.FIRST + 1;
public static final int MENU_TEXT = Menu.FIRST + 2 ;
public static final int MENU_REMOVE = Menu.FIRST + 3;
public static final int MENU_RESET = Menu.FIRST + 4;
private List<King> kings;
private ListView view;
private ArrayAdapter<King> adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view = (ListView) findViewById(R.id.lstKings2);
reset();
registerForContextMenu(view);
}

We will turn your CV into


an opportunity of a lifetime

Do you like cars? Would you like to be a part of a successful brand? Send us your CV on
We will appreciate and reward both your enthusiasm and talent. www.employerforlife.com
Send us your CV. You will be surprised where it can take you.

83
83
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT User interaction
SOFTWARE DEVELOPMENT user InteraCtIon

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo)
{
menu.add(Menu.NONE, MENU_NAME, Menu.NONE, "King");
menu.add(Menu.NONE, MENU_TEXT, Menu.NONE, "Description");
}

@Override
public boolean onContextItemSelected(MenuItem item)
{
AdapterView.AdapterContextMenuInfo menuInfo =
(AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
King king = kings.get(menuInfo.position);
switch (item.getItemId()) {
case MENU_NAME:
Toast.makeText(this, king.getKing(), Toast.LENGTH_LONG).show();
return (true);
case MENU_TEXT:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(king.getName());
builder.setMessage(king.getText());
builder.setPositiveButton("Close", new
DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
builder.show();
return (true);
}
return (super.onContextItemSelected(item));
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(Menu.NONE, MENU_RESET, Menu.NONE, "Reset");
menu.add(Menu.NONE, MENU_REMOVE, Menu.NONE, "Remove");
return(super.onCreateOptionsMenu(menu));
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_RESET:
reset();
return(true);
case MENU_REMOVE:
remove();

84
84
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT User interaction
SOFTWARE DEVELOPMENT user InteraCtIon

return(true);
}
return(super.onOptionsItemSelected(item));
}

private void reset()


{
kings = (new Kings()).getKings();
view.setAdapter(adapter = new ArrayAdapter<King>(this,
android.R.layout.simple_list_item_multiple_choice, kings));
}

private void remove() {


SparseBooleanArray checkedItems = view.getCheckedItemPositions();
if (checkedItems != null) {
for (int i = checkedItems.size() – 1; i >= 0; --i) {
if (checkedItems.valueAt(i)) {
King king = kings.get(checkedItems.keyAt(i));
adapter.remove(king);
}
}
for (int i = 0; i < view.getCount(); ++i) view.setItemChecked(i,false);
}
}
}

When you see the code, there is not so much mystery in it, although it has been changed a
When you see the code, there is not so much mystery in it, although it has been changed a
lot compared to SelectKings. First, note that the four constants that will identify the menu
lot compared to SelectKings. First, note that the four constants that will identify the menu
items. In addition, there are three instance variables that refer to the program’s data, the
items. In addition, there are three instance variables that refer to the program’s data, the
ListView component, as well as an adapter. The ListView component is initialized in the
ListView component, as well as an adapter. The ListView component is initialized in the
method reset(), called from onCreate(). The reason is that the method must also be performed
method reset(), called from onCreate(). The reason is that the method must also be performed
when selecting Reset in the menu. The two following methods are the methods from the
when selecting Reset in the menu. The two following methods are the methods from the
previous example and are used to create the context menu and to the event handler.
previous example and are used to create the context menu and to the event handler.

The method onCreateOptionsMenu() creates the main menu. There is not much to explain
The method onCreateOptionsMenu() creates the main menu. There is not much to explain
except for the parameters and the value Menu.NONE. As the name says, of course, it means
except for the parameters and the value Menu.NONE. As the name says, of course, it means
that you do not have a value for a parameter. In this case, it is a question that menu items
that you do not have a value for a parameter. In this case, it is a question that menu items
can be divided into groups, which is not used here.
can be divided into groups, which is not used here.

The method onOptionsItemSelected() is the associated event handler, which is also simple, but
The method onOptionsItemSelected() is the associated event handler, which is also simple, but
it calls the method remove() to delete all items selected in the ListView component. Here
it calls the method remove() to delete all items selected in the ListView component. Here
you should especially note how to determine the indexes (positions) of the items that are
you should especially note how to determine the indexes (positions) of the items that are
selected and that the result is a SparseBooleanArray, which you can think of as an arrays of
selected and that the result is a SparseBooleanArray, which you can think of as an arrays of
indexes on items that are selected. You must also note the last statement that is required
indexes on items that are selected. You must also note the last statement that is required
to remove checkmarks in the ListView component.
to remove checkmarks in the ListView component.

85
85
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT User interaction

The result, along with the previous program, is that it is simple enough to associate menus
with an app.

86
JAVA 16:
JAVA 16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE DEVELOPMENT
SOFTWARE DEVELOPMENT user interaction
User InteraCtIon

4.3
4.3 DEFINE
DEFINE A
A MENU
MENU IN
IN XML
XML
In
In the
the above
above examples,
examples, thethe menus
menus are
are defined
defined in in Java,
Java, and
and there
there isis nothing
nothing wrong
wrong with
with that,
that,
but
but you
you can
can also
also do
do itit as
as aa resource
resource in
in XML,
XML, and and in
in fact,
fact, itit isis recommended
recommended that
that you
you do
do
so,
so, partly
partly to
to separate
separate the
the code
code and
and the
the definition
definition of of user
user interface,
interface, and and partly
partly to
to facilitate
facilitate
language versions
language versions of
of an
an app.
app. InIn addition,
addition, itit isis very
very simple.
simple.

The
The project
project LastKings
LastKings isis aa copy
copy of
of the
the above
above project,
project, but
but during
during the
the directory
directory res
res II have
have
created
created aa new
new subdirectory
subdirectory withwith the
the name
name menu,
menu, that
that includes
includes two
two xml
xml documents:
documents:

The
The content
content of
of the
the first
first document
document are:
are:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/king_menu"
android:title="Respond" />
<item android:id="@+id/text_menu"
android:title="Description" />
</menu>

and the
and the other
other isis in
in principle
principle identical:
identical:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/remove_menu"
android:title="Remove" />
<item android:id="@+id/reset_menu"
android:title="Reset" />
</menu>

In
In the
the Java
Java code,
code, the
the methods
methods onCreateContextMenu()
onCreateContextMenu() and
and onCreateOptionsMenu()
onCreateOptionsMenu() should
should
be
be changed
changed

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo)

87
87
JAVA
JAVA 16:
JAVA 16: MOBIL
16: MOBIL PHONES
MOBIL PHONES AND
PHONES AND ANDROID:
AND ANDROID:
ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
SOFTWARE DEVELOPMENT
SOFTWARE DEVELOPMENT
DEVELOPMENT User
user interaction
user InteraCtIon
InteraCtIon
SOFTWARE DEVELOPMENT user InteraCtIon

{
{
{
new MenuInflater(this).inflate(R.menu.context_menu,
new MenuInflater(this).inflate(R.menu.context_menu, menu);
menu);
new MenuInflater(this).inflate(R.menu.context_menu, menu);
}
}
}

@Override
@Override
@Override
public
public boolean
boolean onCreateOptionsMenu(Menu
onCreateOptionsMenu(Menu menu)
menu) {
{
public boolean onCreateOptionsMenu(Menu menu) {
new MenuInflater(this).inflate(R.menu.main_menu, menu);
new MenuInflater(this).inflate(R.menu.main_menu, menu);
new MenuInflater(this).inflate(R.menu.main_menu, menu);
return(super.onCreateOptionsMenu(menu));
return(super.onCreateOptionsMenu(menu));
return(super.onCreateOptionsMenu(menu));
}
}
}

and the
and the 4 constants for
for the menu
menu items can can be deleted.
deleted. The event
event handlers must
must also be
be
and the 44 constants
constants for the
the menu items
items can be
be deleted. The
The event handlers
handlers must also
also be
changed so
changed so that they
they do not
not use the
the constants but
but instead the
the identifiers from
from the XML
XML
changed so that
that they do
do not use
use the constants
constants but instead
instead the identifiers
identifiers from the
the XML
documents. As
documents. As an example,
example, below isis shown
shown one of
of the two
two event handlers:
handlers:
documents. As anan example, below
below is shown oneone of the
the two event
event handlers:
@Override
@Override
@Override
public
public boolean
boolean onOptionsItemSelected(MenuItem
onOptionsItemSelected(MenuItem item)
item) {
{
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId())
switch (item.getItemId()) {
{
switch (item.getItemId()) {
case
case R.id.reset_menu:
R.id.reset_menu:
case R.id.reset_menu:
reset();
reset();
reset();
return(true);
return(true);
return(true);
case R.id.remove_menu:
case R.id.remove_menu:
case R.id.remove_menu:
remove();
remove();
remove();
return(true);
return(true);
return(true);
}
}
}
return(super.onOptionsItemSelected(item));
return(super.onOptionsItemSelected(item));
return(super.onOptionsItemSelected(item));
}
}
}

and
and then
then everything
everything works
works again.
again.
and then everything works again.

EXERCICE
EXERCICE 4:
4: IMAGEAPP
IMAGEAPP
EXERCICE 4: IMAGEAPP
Create
Create aa new
new project
project that
that you
you can
can call
call ImageApp.
ImageApp. The
The book’s
book’s source
source code
code has
has aa folder
folder called
called
Create a new project
images containing four that you can call ImageApp. The book’s source code has a folder called
images containing four images.
images. Copy
Copy these
these images
images to
to your
your project:
project:
images containing four images. Copy these images to your project:
ImageApp/app/src/main/res/drawable
ImageApp/app/src/main/res/drawable
ImageApp/app/src/main/res/drawable

The images are img1.jpg, img2.jpg, img3.jpg and img4.jpg, and after copying the images,
The images
The images are
are img1.jpg,
img1.jpg, img2.jpg,
img2.jpg, img3.jpg
img3.jpg and
and img4.jpg,
img4.jpg, and
and after
after copying
copying the
the images,
images,
they are added as resources to your project. The project must (in the emulator) open the
they are
they are added
added as
as resources
resources to
to your
your project.
project. The
The project
project must
must (in(in the
the emulator)
emulator) open
open the
the
following window, which has two components in the form of a TextView and an ImageView:
following window,
following window, which
which has
has two
two components
components in in the
the form
form of
of aa TextView
TextView and
and an
an ImageView:
ImageView:

88
88
88
88
JAVA
JAVA16:
16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
SOFTWARE
SOFTWAREDEVELOPMENT
DEVELOPMENT User
userinteraction
InteraCtIon

In
In the
the file
file strings.xml,
strings.xml, you
you must
must define
define 44 strings,
strings, which
which are
are the
the names
names of
of the
the birds
birds that
that the
the
images
images shows:
shows:

<resources>
<string name="app_name">ImageApp</string>
<string name="lbl_img1">Great Tit</string>
<string name="lbl_img2">Starling</string>
<string name="lbl_img3">Jackdaw</string>
<string name="lbl_img4">Robin Redbreast</string>
</resources>

AXA Global
Graduate Program
Find out more and apply

89
89
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT User interaction

To the TextView component, a context menu has to be defined with four menu items (se
below). The menu must be defined in XML, and if you select a menu item, the program must
display the corresponding image and update the TextView component with the correct name.

Once you have tested the program, you can optionally replace the pictures with your own
pictures and maybe have 6 images instead of 4.

4.4 ABOUT ACTIVITIES


I want to conclude this chapter by looking a little closer to the class Activity, and as shown
in the previous examples, each mobile app has an Activity object. One might think of an
Activity as an object that represents the program’s window and implements the logic that
the application uses, and a program may therefore have more activities. An activity can be
in four modes

1. Launched, when an activity comes in to existence, usually as the result of a user


performing some action to starts the application.
2. Running at which the users actually sees your activity, after all of the various setup
steps are performed.
3. Killed, that is a state in which the Android OS has determined to terminate
the appplication.
4. Shut down at which all persistent state information is deleted.

Changes are made on the basis of callback methods, where onCreate() is an example, but
there are some others, and it’s all methods that you can override. In the following, I will
mention the main callback methods.

90
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT User interaction

onCreate() is executed when an activity starts its life cycle, typically because a user has
requested the activity or the activity is restarted due to changes in the environment, for
example due to a rotation of the devic. It is for restart that onCreate() has a parameter of
the type Bundle, that can contain information about the state of the activity. Basically,
onCreate() is used for:

1. Load the layouts that the activity uses so the components in the user interface can
be constructed in the method onStart().
2. Initialize the activitiy’s instance variables.

There are some tasks that relate to onCreate() and primarily concerns restart of the activity,
including keeping track of existing global resources from the last time the activity was active.
For example, if you programmatically change the layout depending on an user interaction
of the application.

onStart(), that is executed after onCreate() has created the required objects from the layout
definitions and performed other initialization work, it is onStart() which is tasked with
presenting the current UI elements for the user. There is seldom the need to override this
method. And if you do, it is important to call super.onStart().

onResume() is executed immediately before the user interface becomes visible and the method
performs almost the same as onStart(), but is performed in conjunction with another state
switch as you can se in the following state diagram:

91
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT User interaction

onPause() is executed after an application is switched to the background state after Android
has suspended the application. Viewed from the programmer, the method can be used to
ensure data is saved when the application is suspended.

onStop() sends the activity in background, and you can think of the method as the opposite
of onStart() and the activity is no longer visible to the user, while the view and properties
still exist and are transferred to onResume() and onStart() if they are performed. Note that
onStop() is not necessarily performed, if the Android decides to terminate the application,
and it is therefore rare to override this method.

onRestart() is executed at a state shift from stopped to start, then allowing to some extend
to decide how to restart the activity.

onDestroy() is performed when an activity is closed, but note that it concerns an activity
and not the entire application. The method can only be used for a cleanup that relates to
the current activity.

92
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT User interaction

The above state diagram should show where and when the different callback methods are
performed in connection with state shift. In the above examples I have only used onCreate(),
but as the examples use more of the phone’s facilities, more of the above callback methods
are also interesting.

There are several methods that relates to change of state for an activity and can be overwritten,
and as example I would like to mention two:

1. onRestoreInstanceState() that is executed when a user leaves an activity by clicking


the back button or performing other logic that is part of the application and the
method can be used in situations where there is a need to save user data.
2. onSaveInstanceState() which is responsible for storing an activity’s state information,
primarily associated with onDestroy().

�e Graduate Programme
I joined MITAS because for Engineers and Geoscientists
I wanted real responsibili� www.discovermitas.com
Maersk.com/Mitas �
I joined MITAS because for Eng
I wanted real responsibili� M

Month 16
I was a construction M
supervisor ina con
I was
the North Sea supe
advising and the N
Real work he
helping foremen adv
International
al opportunities
Internationa
�ree wo
work
or placements ssolve problems
Real work he
helping
International
Internationaal opportunities
�ree wo
work
or placements ssolve p

93
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT User interaction
SOFTWARE DEVELOPMENT user InteraCtIon

4.5
4.5 MULTIPLE
MULTIPLEACTIVITIES
ACTIVITIES
As
Asthe
thelast
lastininthis
thischapter,
chapter,I Iwill
willshow
showananexample
exampleofofananapp appthat
thathas
hastwo
twoactivities.
activities.The
The
application is trivial and should only show how to add more activities to
application is trivial and should only show how to add more activities to an application.an application.
You
Youmust
mustnote
notethat
thatananapplication
applicationcancanhave
haveallallthe
theactivities
activitiesthat
thatare
areneeded.
needed.

I Ihave
havestarted
startedwith
witha aproject
projectcalled
calledMoreActivities,
MoreActivities,and
andafter
afterI Ihave
havecreated
createdthe
theproject,
project,there
there
isisone activity called MainActivity, where the layout is called activity_main.xml. Next,
one activity called MainActivity, where the layout is called activity_main.xml. Next, I haveI have
under
underproject
projectfiles
filesright-click
right-clickon
onappappand
andselected
selected

New
New| |Activity
Activity| |Empty
EmptyActivity
Activity

and
andininthe
thenext
nextwindow
windowI Ihave
havefor
forthe
thenames
namesselected
selectedSecondActivity
SecondActivityand
andactivity_second.
activity_second.
xml. As a result, my project now contains two activities.
xml. As a result, my project now contains two activities.

For
Forthe
thefirst
first(that
(thatisisMainActivity)
MainActivity)I Ihave
haveadded
addedananevent
eventhandler:
handler:

package dk.data.torus.moreactivities;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.view.*;

public class MainActivity extends AppCompatActivity


{

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

public void openActivity(View view)


{
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
}
}

94
94
JAVA
JAVA16:
JAVA 16:MOBIL
16: MOBILPHONES
MOBIL PHONESAND
PHONES ANDANDROID:
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWAREDEVELOPMENT
SOFTWARE DEVELOPMENT
DEVELOPMENT User
userinteraction
user InteraCtIon
InteraCtIon

There
Thereisis
There isnot
notmuch
not muchtoto
much toexplain
explainbesides
explain besidestaking
besides takingnote
taking notethat
note thatthe
that thehandler
the handleropens
handler opensanother
opens anotheractivity,
another activity,
activity,
and
and the result is that the phone’s screen changes content and shows the other activity.The
andthe
theresult
resultis
is that
that the
thephone’s
phone’sscreen
screenchanges
changescontent
content and
andshows
shows the
theother
otheractivity.
activity. The
The
XML
XML code
code and
and thus
thus the
thelayout
layoutare
areas
as
XML code and thus the layout are as follows: follows:
follows:

<?xml version="1.0"
<?xml version="1.0" encoding="utf-8"?>
encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp"
android:layout_margin="20dp"
tools:context="dk.data.torus.moreactivities.MainActivity">
tools:context="dk.data.torus.moreactivities.MainActivity">
<TextView
<TextView
android:id="@+id/lbl_main"
android:id="@+id/lbl_main"
android:layout_width="wrap_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerHorizontal="true"
android:text="Go to
android:text="Go to the
the second
second activity"
activity" />
/>
<Button
<Button
android:layout_width="wrap_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_height="wrap_content"
android:text="Open Activity"
android:text="Open Activity"
android:layout_below="@id/lbl_main"
android:layout_below="@id/lbl_main"
android:layout_marginTop="50dp"
android:layout_marginTop="50dp"
android:layout_centerHorizontal="true"
android:layout_centerHorizontal="true"
android:onClick="openActivity" />
android:onClick="openActivity" />
</RelativeLayout>
</RelativeLayout>

which
which isan
whichisis anextremely
an extremelysimple
extremely simplelayout
simple layoutwith
layout withaaatext
with textand
text andaaabutton.
and button.
button.

For
For the
Forthe other
theother activity,
otheractivity, almost
activity,almost the
almostthe same
thesame thing
samething must
thingmust happen.
musthappen. The
happen.The XML
TheXML code
codeisis
XMLcode isinin principle
inprinciple
principle
identical.
identical. Just
identical.Just another
Justanother text
anothertext appears
textappears and
appearsand the
andthe button
thebutton has
buttonhas another
hasanother event
anotherevent handler:
eventhandler:
handler:

public
public class
class SecondActivity
SecondActivity extends
extends AppCompatActivity
AppCompatActivity
{
{
@Override
@Override
protected void
protected void onCreate(Bundle
onCreate(Bundle savedInstanceState)
savedInstanceState)
{
{
super.onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
setContentView(R.layout.activity_second);
}
}

95
95
95
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT User interaction
SOFTWARE DEVELOPMENT user InteraCtIon

public void closeActivity(View view)


{
finish();
}
}

That’s all, and then the application can be translated and tested, and the result is an
application with two activities.

PROBLEM 1: LOANAPP
In the book Java 3 (and also elsewhere) I have shown an application that implements a loan
calculator where the user can calculate the payment on a loan. This time the loan every
time is an annuity loan and the program must open the following window:

93%
OF MIM STUDENTS ARE
WORKING IN THEIR SECTOR 3 MONTHS
FOLLOWING GRADUATION

MASTER IN MANAGEMENT
• STUDY IN THE CENTER OF MADRID AND TAKE ADVANTAGE OF THE UNIQUE OPPORTUNITIES
Length: 1O MONTHS
THAT THE CAPITAL OF SPAIN OFFERS
Av. Experience: 1 YEAR
• PROPEL YOUR EDUCATION BY EARNING A DOUBLE DEGREE THAT BEST SUITS YOUR
Language: ENGLISH / SPANISH
PROFESSIONAL GOALS
Format: FULL-TIME
• STUDY A SEMESTER ABROAD AND BECOME A GLOBAL CITIZEN WITH THE BEYOND BORDERS
Intakes: SEPT / FEB
EXPERIENCE

5 Specializations #10 WORLDWIDE 55 Nationalities


MASTER IN MANAGEMENT
Personalize your program FINANCIAL TIMES
in class

www.ie.edu/master-management mim.admissions@ie.edu Follow us on IE MIM Experience

96
96
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT User interaction

which contains only labels, entry fields and buttons. In the two top fields one must be able
to enter the borrowing costs and the loan principal respectively, while you in the next two
fields you must be able to enter the number of years for the repayment of the loan and
the number of terms per year. In the last field you must be able to enter the interest rate,
which is entered as the interest rate in percent per year. When you click the CALCULATE
button, the program must calculate the term payment and show it in the field after the
text Payment, which is a read-only EditText.

Before calculating (when clicked on the CALCULATE button), the program must validate data:

1. The cost must not be negative


2. The loan must be positive
3. The number of years must be an integer between 1 and 60 (both inclusive)
4. The number of terms per year must be an integer between 1 and 12 (both inclusive)
5. The interest rate must be positive and less than 50

In the case of an error, the program must display an error message in the form of a simple
Toast. Below is shown the window after a loan calculation has been made:

97
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT User interaction

If you click on the AMORTIZATION button, the program must open another activity that
shows an amortization plan:

Here you should especially note that the window’s Action Bar has a back button. It’s part
of the task to find out how to add this button – it’s quite simple and you can try to search
the Internet. The actual table is shown with a GridView. It’s also part of the task to find
out how to use a GridView, but it’s almost the same as a TextView.

98
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Files

5 FILES
In view of the above examples, the subjects shown can now be a good move in developing
mobile phone apps, but the phone provides a range of other services beyond what is
applicable to ordinary computers, where I can mention SMS and phone, GPS, camera and
more. These are facilities that I will first treat in the following book, but it is also possible
to save data in files and databases, which is necessary for many apps, and in this and the
following chapter I will focus on how to do that. This chapter will look at files, including
how to manipulate the file system just like on a regular PC, but I want to start somewhere
else, namely files that you only can read. If there are files that only have interest in the
current application, the files can be saved as resource files within the application. Examples
could be text, images, audio and more.

5.1 READING RESOURCES


If you create a project in Andoid Studio, under project files there will be two directories
java and res, where the latter contains resource files. It are files that are packed with the

99
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA16:
JAVA 16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
SOFTWARE DEVELOPMENT FILes
SOFTWAREDEVELOPMENT
SOFTWARE DEVELOPMENT FILes
Files

program
program code
program code in
code in the
in the apk
the apk file.
apk file. Here
file. Here you
Here you will
you will find,
will find, among
find, among other
among other things,
things, aaa subdirectory
other things, subdirectory layout
subdirectory layout
layout
that contains
that contains
that activity_main.xml
contains activity_main.xml
activity_main.xml that that defines
that defines the
defines the application’s
the application’s user
application’s user interface
user interface and
interface and at the
and atat the same
the same
same
location will
location will
location be
will be other
be other xml
other xml documents
xml documents
documents forfor layout
for layout
layout ofof other
of other activities.
other activities. You
activities. You have
You have also
have also met
also met the
met the
the
file strings.xml
file strings.xml
file under
strings.xml under
under thethe subdirectory
the subdirectory values.
subdirectory values. Making
values. Making
Making datadata available
data available to
available to the
to the program
the program
program in in this
in this
this
way
way has
way has several
has several advantages,
several advantages,
advantages, suchsuch as:
such as:
as:

----ItIt
It isis easy
is easy to
easy to define
to define data,
define data, that
that isis
data, that always
is always available
always available for
available for the
for the program.
the program.
program.
---- It ensures
ItIt ensures a separation
ensures aa separation
separation ofof code
of code
code and and data.
and data.
data.
---- It allows
ItIt allows
allows toto place
to place resources
place resources
resources in in a library
in aa library
library so so that
so that they
that they can
they can be
can be used
be used by
used by multiple
by multiple
multiple
applications.
applications.
applications.
- Simple
--- Simple
Simple data data can
data can be
can be made
be made available
made available
available in in
in aaa standard
standard format
standard format such
such asas
format such XML.
as XML.
XML.

There are
There are
There also
are also disadvantages,
also disadvantages, among
disadvantages, among other
among other things,
other things, to
things, to mention:
to mention:
mention:

---- Data
Data
Data isis fundamentally
is fundamentally read-only,
fundamentally read-only, although
read-only, although
although inin principle
principle itit
in principle it isis possible
is possible to
possible to modify
to modify the
modify the
the
content
content of
content of a resource.
of aa resource.
resource.
- It can
--- ItIt can be
can be problematic/cumbersome
be problematic/cumbersome
problematic/cumbersome to to ensure
to ensure data
data isis
ensure data up
is up to
up to date.
to date.
date.

To
To show
To show
show anan example
an example
example ofof how
of how to
how to
to do,do,
do, III will
will return
will return to
return to the
to the example
the example with
example with the
with the Danish
the Danish kings,
Danish kings,
kings,
which represent
whichrepresent
which data
representdata that
datathat rarely
thatrarely changes.
rarelychanges. It is therefore
changes.ItItisistherefore data
thereforedata that
datathat can
thatcan be
canbe conveniently
beconveniently placed
convenientlyplaced
placed
as a resource,
asas aa resource, but
resource, but also
but also because
also because it is data
because itit isis data that
data that does
that does not
does not fill
not fill up
fill up much.
up much. The
much. The data
The data in
data in question
in question
question
is stored
isis stored in
stored in an
in an XML
an XML document
XML document named
document named regents.xml
named regents.xml and
regents.xml and has
and has the
has the following
the following content:
following content:
content:

<regents>
<regents>
<regent
<regent name="Gorm
name="Gorm den
den Gamle"
Gamle" to="958"/>
to="958"/>
<regent
<regent name="Harald Blåtand" from="958" to="987"/>
name="Harald Blåtand" from="958" to="987"/>
<regent
<regent name="Svend
name="Svend Tveskæg"
Tveskæg" from="987"
from="987" to="1014"/>
to="1014"/>
<regent
<regent name="Harald
name="Harald 2."
2." from="1014"
from="1014" to="1018"/>
to="1018"/>


<regent
<regent name="Frederik
name="Frederik 9."
9." from="1947"
from="1947" to="1972"/>
to="1972"/>
<regent
<regent name="Margrethe
name="Margrethe 2."
2." from="1972"/>
from="1972"/>
</regents>
</regents>

II have then created a project, which I have called DanishRegents. The layout defines only
I have
have then
then created
created aa project,
project, which
which II have
have called
called DanishRegents.
DanishRegents. The
The layout
layout defines
defines only
only
aa single
single component:
component:
a single component:

<ListView
<ListView
android:id="@+id/lstReg"
android:id="@+id/lstReg"
android:layout_width="match_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="match_parent" />
/>

100
100
100
JAVA
JAVA16:
16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
SOFTWARE
SOFTWAREDEVELOPMENT
DEVELOPMENT Files
FILes

and
andthe
theonly
onlything
thingtotododoisistotofill
fillthis
thisListView
ListViewwith
withthe
thenames
namesof ofthetheDanish
Danishkings.
kings.InInorder
order
to
tomake
makedata
dataavailable,
available,IIhave
havecreated
createdaasubdirectory
subdirectorynamed
namedraw rawand andcopied
copiedfile
fileregents.xml
regents.xml
to
tothis
thissubdirectory.
subdirectory.ThenThenthe thedocument
documentisisaaresource
resourceforforthe
theapplication.
application.IIhave havethen
thenadded
added
aa model
model class
class Regent,
Regent, which
which can can represent
represent aa regent,
regent, and
and apart
apart from
from the
the name,
name, the
the class
class isis
identical
identical to
to the
the class
class King
King that
that II used
used previously.
previously. Back
Back there
there isis only
only the
the class
class MainActivity:
MainActivity:

package dk.data.torus.danishregents;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.*;
import android.view.*;
import java.util.*;
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import android.widget.AdapterView.*;

public class MainActivity extends AppCompatActivity


{
List<Regent> regents = new ArrayList();

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try
{
InputStream stream = getResources().openRawResource(R.raw.regents);
DocumentBuilder builder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(stream, null);
NodeList nodes = doc.getElementsByTagName("regent");
for (int i = 0; i < nodes.getLength(); ++i)
{
Element elem = (Element)nodes.item(i);
String attr = elem.getAttribute("from");
int from = attr == null || attr.length() == 0 ?
Integer.MIN_VALUE : Integer.parseInt(attr);
attr = elem.getAttribute("to");
int to = attr == null || attr.length() == 0 ?
Integer.MAX_VALUE : Integer.parseInt(attr);
regents.add(new Regent(elem.getAttribute("name"), from, to));
}
stream.close();
}

101
101
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Files
SOFTWARE DEVELOPMENT FILes

catch (Exception e) {
}
ListView view = (ListView)findViewById(R.id.lstReg);
view.setAdapter(new ArrayAdapter<Regent>(this,
android.R.layout.simple_list_item_1, regents));
view.setOnItemClickListener(new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view,
final int position, long id)
{
Regent regent = regents.get(position);
Toast.makeText(MainActivity.this, regent.getRegent(),
Toast.LENGTH_LONG).show();
}
});
}
}

First, note that there are a number of new import statement, among other things because the
First, note that there are a number of new import statement, among other things because the
program should read and parse a XML document. The class has a single instance variable,
program should read and parse a XML document. The class has a single instance variable,
which is a List for Regent objects, and thus to the objects that the ListView component
which is a List for Regent objects, and thus to the objects that the ListView component
should display. Otherwise, the class only has an onCreate(). It starts by loading the resource.
should display. Otherwise, the class only has an onCreate(). It starts by loading the resource.

In the past 5 years we have drilled around

95,000 km
—that’s more than twice around the world.

Who are we?


We are the world’s leading provider of reservoir characterization,
drilling, production, and processing technologies to the oil and
gas industry.

Who are we looking for?


We offer countless opportunities in the following domains:
n Operations
n Research, Engineering, and Manufacturing
n Geoscience and Petrotechnical
n Commercial and Business

We’re looking for high-energy, self-motivated graduates


with vision and integrity to join our team. What will you be?

careers.slb.com

102
102
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Files

Here you should note how to refer to a program’s resources using the method getResources()
and how to load a raw file using the method openRawResource() and that the result is a
regular InputStream. With this stream available, a DocumentBuilder can read the document
and parse it as XML, after which you can create the current Regent objects and initialize the
list. After the data is loaded and the list is initialized, an adapter is added to the ListView
component. Additionally, an event handler has been added so that the program shows a
Toast if you click on a name in the ListView component.

EXERCISE 5: ZIPCODES
In section 2.1 I shows an application Zipcodes, where you can search for Danish zip codes.
Start by creating a copy of the project Zipcodes. Under the directory res you must create a
subdirectory named raw. The book’s source code contains a file zipcodes.txt, which contains
the Danish zip codes as a comma-separated file. Copy this file to the new directory raw.
In the class Zipcodes, all zip codes are defined in a static array. You must now delete this
array and change the class so that the Zipcode objects are created by instead reading the
content of your resource zipcodes.txt. You can do the following:

1. Delete the static array


2. Add a parameter of the type InputStream to the class’ constructor
3. The constructor must then initialize the list of zip codes by reading the content of
the stream represented by the parameter

A single change must be added to the class MainActivity. In onCreate() you must create a
reference to your resource and send it as a parameter to the constructor in the class Zipcodes.
Then everything should work again.

5.2 ORDINARY FILES


You can also use common files, as you know it from PC, and not enough, it goes a long
way in the same way as described in the book Java 5 about IO. The main difference is that
files can be stored in two places, either internally where they are stored together with the
program in internal storage or external where they can be stored on an external SD card.
I only want to show the first option because the ability to save files remotely to a SD card
is a security problem with Android, and that’s why Google has tightened the requirements
for external files significantly and they have probably not found the final solution yet. It’s
actually possible to open up a device so that you can easily create files on a SD card, but
it is not recommended, so I’m looking only at the internal files, but with respect to the
code, the difference is not big.

103
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Files

When files are created internally, they are stored in the phone’s memory which in this
context is called internal storage. It has its pros and cons where I can mention:

-- Internal storage is something that always are there and is part of any Android
device, but it’s limited in size and significantly less than what, an SD card makes
available and there’s a not insignificant risk that if applications often saves files in
internal storage, so that it will be filled up.
-- Basically, files stored in internal storage are associated with an application and can
only be used immediately by this application. Should the file be used by other
applications, special efforts are required, and in fact, it is not at all the intention
to share information between applications using internal files.
-- Files stored in internal storage are perceived as part of the application they are
associated with, and if you delete the application, you also deletes its internal files.

Internal files are thus primarily suitable for storing smaller amounts of data that must be
available for a program the next time it starts up, but there is also a need for that in many
examples, so the conclusion is not to avoid using internal files, but just think about what
they are used for.

As mentioned, internal files are associated with an application, and the application generally
has unlimited access to a file and can thus both read and write the file – the application
simply owns the file.

When you open a file, you can specify the following modes:

-- MODE_PRIVATE, that is default and only the application that creates the file is
allowed to access the file
-- MODE_APPEND

In the following, I will look at an example that shows how to use a file.

5.3 INTERNAL STORAGE


The program is a simple contact program, where you can enter a name, a phone number,
an email address and a text for a person:

104
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Files

Excellent Economics and Business programmes at:

“The perfect start


of a successful,
international career.”

CLICK HERE
to discover why both socially
and academically the University
of Groningen is one of the best
places for a student to be
www.rug.nl/feb/education

105
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Files

Once you have entered a contact (the name must be entered) you can save the contact
by saving it to a file in internal storage. If you click the SHOW button, you will see the
window below that shows an overview of the contacts that were entered. If you hold your
finger on a contact, you will get a context menu with two functions, where you can delete
a contact (and then delete in the file) and choose to see the details for the contact (see the
window below). It is therefore an application with three activities.

I do not want to look at the XML code for the three layouts, as here is nothing new, so
the following mainly concerns the Java code. Here are two things that you should notice:

1. how to write to a file, which is the primary purpose of the example


2. how to transfer a parameter from one activity to another

The program uses the following model class where I have not shown get and set methods:

106
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Files
FILes

public class Person implements Serializable


{
private String name;
private String phone;
private String mail;
private String text;

public Person(String name, String phone, String mail, String text)


{
this.name = name;
this.phone = phone;
this.mail = mail;
this.text = text;
}

public Person(String line) throws Exception


{
String[] elems = line.split("\f");
if (elems.length != 4) throw new Exception("Illegal text for person");
name = elems[0];
phone = elems[1].trim();
mail = elems[2].trim();
text = elems[3].trim();
}

107
107
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Files
SOFTWARE DEVELOPMENT FILes

public String getPerson()


{
StringBuilder builder = new StringBuilder(name);
builder.append("\f");
builder.append(phone.length() == 0 ? "\t" : phone);
builder.append("\f");
builder.append(mail.length() == 0 ? "\t" : mail);
builder.append("\f");
builder.append(text.length() == 0 ? "\t" : text);
return builder.toString();
}

@Override
public String toString()
{
return name;
}
public boolean equals(Object obj)
{

}
}

American online
LIGS University
is currently enrolling in the
Interactive Online BBA, MBA, MSc,
DBA and PhD programs:

▶▶ enroll by September 30th, 2014 and


▶▶ save up to 16% on the tuition!
▶▶ pay in 10 installments / 2 years
▶▶ Interactive Online education
▶▶ visit www.ligsuniversity.com to
find out more!

Note: LIGS University is not accredited by any


nationally recognized accrediting agency listed
by the US Secretary of Education.
More info here.

108
108
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Files
FILes

The
The class
class represents
represents aa person person with
with thethe four
four desired
desired properties.
properties. It It isis the
the idea
idea that
that contacts
contacts
should
should bebe saved
saved as as text
text lines
lines in
in aa file,
file, and
and itit isis therefore
therefore necessary
necessary to to separate
separate the
the fields
fields so
so
you
you can
can read
read in in the
the file
file again.
again. A A seperation
seperation markmark must must be be used,
used, which
which isis just
just aa character
character
that
that does
does not
not appear
appear in in the
the text
text fields,
fields, and
and here
here II use
use aa form
form feed feed (page
(page shift).
shift). The
The method
method
getPerson()
getPerson() thus
thus returns
returns aa string
string with
with thethe person’s
person’s fields
fields separated
separated by by form
form feeds.
feeds. You
You should
should
note
note that
that ifif aa field
field isis empty
empty (what
(what the the fields
fields may
may be be ifif itit isis not
not the
the name),
name), aa tab
tab will
will be
be
saved.
saved. That’s
That’s what
what youyou can can call
call aa “work
“work around”,
around”, and and thethe reason
reason isis the
the split()
split() method
method in in
the
the String
String class
class ignores
ignores blank
blank fields.
fields.

The
The class
class has
has two
two constructors,
constructors, and
and here
here you
you should
should first
first notice
notice thethe last
last one
one that
that has
has aa
String
String as
as aa parameter
parameter andand assumes
assumes that
that the
the String
String consists
consists of of 44 fields
fields separated
separated by by form
form
feeds.
feeds. The
The fields
fields are
are determined
determined by by separating
separating strings
strings into
into fields
fields using
using the
the split()
split() method,
method,
and
and note
note that
that for
for the
the last
last three
three fields
fields aa trim()
trim() isis performed,
performed, and and the
the purpose
purpose isis to
to remove
remove
any
any tab
tab inserted
inserted byby the
the above
above method.
method.

Finally,
Finally, you
you must
must note
note that
that the
the class
class isis defined
defined Serializable.
Serializable. The
The reason
reason isis that
that itit should
should be
be
possible
possible to
to transfer
transfer aa Person
Person object
object as
as parameter
parameter from
from one
one activity
activity to
to another.
another.

This
This class
class isis aa major
major part
part of
of the
the work
work of
of saving
saving person
person objects
objects in
in aa file.
file. Reading
Reading and
and writing
writing
to
to aa file
file takes
takes place
place in
in the
the class
class Persons,
Persons, which
which represents
represents all
all contacts:
contacts:

public class Persons implements Serializable


{
private static final String filename = "papersons";
private List<Person> persons = new ArrayList();
private transient Context context;

public Persons(Context context) throws Exception


{
this.context = context;
FileInputStream stream = null;
try {
stream = context.openFileInput(filename);
}
catch (Exception ex)
{
return;
}
BufferedReader reader = new BufferedReader(new
InputStreamReader(stream));
for (String line = reader.readLine(); line
!= null; line = reader.readLine())
try
{

109
109
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Files
SOFTWARE DEVELOPMENT FILes

persons.add(new Person(line));
}
catch (Exception ex)
{
}
reader.close();
}

public Person getPerson(int n)


{
return persons.get(n);
}

public List<Person> getPersons()


{
return persons;
}

public void save(Person person) throws Exception


{
FileOutputStream stream =
context.openFileOutput(filename, Context.MODE_APPEND);
BufferedWriter writer = new BufferedWriter(new
OutputStreamWriter(stream));
writer.write(person.getPerson());
writer.newLine();
writer.close();
persons.add(person);
}

public void remove(Context context, Person person) throws Exception


{
if (persons.remove(person))
{
FileOutputStream stream =
context.openFileOutput(filename, Context.MODE_PRIVATE);
BufferedWriter writer = new BufferedWriter(new
OutputStreamWriter(stream));
for (Person p : persons)
{
writer.write(p.getPerson());
writer.newLine();
}
writer.close();
}
else throw new Exception("Person could not be removed");
}
}

110
110
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Files
FILes

As
As youyou study
study thethe code,
code, you
you should
should first
first notice
notice that
that all
all ofof the
the basics
basics areare the
the same
same asas you
you know
know
itit from
from IO IO in in Java,
Java, and
and that
that even
even the
the same
same classes
classes are
are used.
used. The
The class
class is
is defined
defined Serializable
Serializable
as
as itit should
should be be transferred
transferred asas parameter
parameter to to an
an activity.
activity. TheThe class
class has
has three
three variables,
variables, where
where
the first is the filename, the other an ArrayList to Person objects, and
the first is the filename, the other an ArrayList to Person objects, and the latter is a Contextthe latter is a Context
that
that represents
represents an an activity.
activity. It
It is
is used
used when
when creating
creating aa file
file as
as itit is
is associated
associated with
with anan activity.
activity.
Note
Note that that itit is
is defined
defined transient.
transient. The
The reason
reason is
is that
that itit should
should not not be
be serialized
serialized when
when aa Person
Person
object
object is is transferred
transferred to to another
another activity.
activity.

The
The class’
class’ constructor
constructor loads
loads the
the file’s
file’s lines
lines and
and parses
parses them
them to
to Person
Person objects.
objects. Basically,
Basically, itit is
is
similar
similar to
to the
the same
same classes
classes that
that you
you generally
generally use
use to read a text file in Java. There is only
one
one place
place where
where there
there is
is something
something new new and
and that’s
that’s where
where the
the file
file opens:
opens:

stream = context.openFileInput(filename)

This happens
This happens with
with the
the method
method openFileInput(),
openFileInput(), which
which is
is aa method
method in
in the
the context
context object
object
that opens
that opens aa file
file in
in internal
internal storage
storage and
and returns
returns an
an InputFileStream
InputFileStream object.
object. Then
Then itit all
all goes
goes
as with
as with other
other text
text files
files in
in Java.
Java.

111
111
JAVA
JAVA 16:
JAVA 16: MOBIL
16: MOBIL PHONES
MOBIL PHONES AND
PHONES AND ANDROID:
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT
DEVELOPMENT
JAVA 16: MOBIL PHONES AND ANDROID: Files
FILes
FILes
SOFTWARE DEVELOPMENT FILes

When
When saving
When saving an
saving an entered
an entered contact,
entered contact, you
contact, you call
you call the
call the method
the method save()
method save() with
save() with aaa Person
with Person object
Person object as
object as parameter.
as parameter.
parameter.
When
Here’s
Here’s saving
Here’s not
not an
not much
much entered
much new,
new, contact,
new, and
and the
and you
the only
the call
only is
only is how
is the
how to
how method
to open
to save()
open the
open the file:
the with
file:
file: a Person object as parameter.
Here’s not much new, and the only is how to open the file:
context.openFileOutput(filename, Context.MODE_APPEND)
context.openFileOutput(filename, Context.MODE_APPEND)
context.openFileOutput(filename, Context.MODE_APPEND)
which opens
which opens anan output
output filefile in
in internal
internal storage
storage and and again
again itit isis with
with aa method
method inin the
the context
context
which The
object.
object. opens an output
The method
method file ain
returns
returns internal storage and
a FileOutputStream
FileOutputStream again
object.
object. The
The it is filewith
file a method
opens
opens in the
in append
in append mode
modecontext
to
to
object.
add
add to Thefile
to the
the method
file and ifif returns
and the file adoes
the file FileOutputStream
does not exist,
not object.
exist, itit will
will The file opens
be automatically
be automatically in append mode to
created.
created.
add to the file and if the file does not exist, it will be automatically created.
Finally, there
Finally, there isis the
the method
method remove()
remove() to
to delete
delete aa Person
Person in
in the
the file.
file. The
The file
file isis this
this time
time
Finally,as
opened
opened asthere is the method remove() to delete a Person in the file. The file is this time
opened as
context.openFileOutput(filename, Context.MODE_PRIVATE)
context.openFileOutput(filename, Context.MODE_PRIVATE)
context.openFileOutput(filename, Context.MODE_PRIVATE)
which means
which means that
that anan existing
existing content
content isis overwritten.
overwritten. The
The method
method works
works by by writing
writing the
the
which
which means
means
entire content
entire content of that
that
of the an
an
the list existing
existing
list persons content
content
persons back
back into is
is
into theoverwritten.
overwritten.
the file
file (but The
The
(but not method
method
not the
the object works
works
object that
that isbyby writing
writing
is deleted). the
the
deleted). This
This
isentire
entire
is content
content
necessary
necessary ofofthe
because
because theit list
itlist
is aapersons
is persons backfile,
back
sequential
sequential intoand
into
file, thefile
the
and file(but
(butnot
something
something not theobject
the
similar
similar object
would
would that
that isisdeleted).
apply
apply deleted).
ifif you This
This
you could
could
isisnecessary
necessary
change
change becauseititisisfor
because
the information
the information aasequential
for sequential file,and
contact.file,
aa contact. andsomething
somethingsimilar
similarwould
wouldapply
applyififyou youcould
could
changethe
change theinformation
informationfor foraacontact.
contact.
Then there
Then there is
is the
the class
class MainActivity:
MainActivity:
Thenthere
Then thereisisthe
theclass
classMainActivity:
MainActivity:
public class
public class MainActivity
MainActivity extends
extends AppCompatActivity
AppCompatActivity {{
private
public Persons
class persons;
MainActivity
private Persons persons; extends AppCompatActivity {
private EditText
private EditText
private txtName;
Persons persons;
txtName;
private
private EditText
EditText txtPhone;
txtName;
private EditText txtPhone;
private EditText
private EditText
private txtMail;
EditText txtMail;
txtPhone;
private
private EditText
EditText txtText;
txtMail;
private EditText txtText;
private EditText txtText;
@Override
@Override
protected void onCreate(Bundle
@Override void
protected onCreate(Bundle savedInstanceState)
savedInstanceState) {{
super.onCreate(savedInstanceState);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadPersons();
setContentView(R.layout.activity_main);
loadPersons();
txtName = (EditText)findViewById(R.id.txtName);
loadPersons();
txtName = (EditText)findViewById(R.id.txtName);
txtPhone = (EditText)findViewById(R.id.txtPhone);
txtName = (EditText)findViewById(R.id.txtName);
txtPhone = (EditText)findViewById(R.id.txtPhone);
txtMail = (EditText)findViewById(R.id.txtMail);
txtMail = (EditText)findViewById(R.id.txtMail);
txtPhone = (EditText)findViewById(R.id.txtPhone);
txtText = (EditText)findViewById(R.id.txtText);
txtMail = (EditText)findViewById(R.id.txtMail);
txtText = (EditText)findViewById(R.id.txtText);
}
} txtText = (EditText)findViewById(R.id.txtText);
}
public void
public void onClear(View
onClear(View view)
view)
{{public void onClear(View view)
clear();
{clear();
}} clear();
}

112
112
112
112
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Files
SOFTWARE DEVELOPMENT FILes

public void onSave(View view)


{
String name = txtName.getText().toString().trim();
String phone = txtPhone.getText().toString().trim();
String mail = txtMail.getText().toString().trim();
String text = txtText.getText().toString().trim();
if (name.length() > 0)
{
try
{
persons.save(new Person(name, phone, mail, text));
Toast.makeText(this, getResources().getString(R.string.msg_save),
Toast.LENGTH_LONG).show();
clear();
}
catch (Exception ex)
{
Toast.makeText(this, getResources().getString(R.string.err_save),
Toast.LENGTH_LONG).show();
}
}
}

public void onShow(View view)


{
Intent intent = new Intent(this, ShowActivity.class);
intent.putExtra("persons", persons);
startActivity(intent);
}

private void clear()


{
txtName.setText("");
txtPhone.setText("");
txtMail.setText("");
txtText.setText("");
txtName.requestFocus();
}

private void loadPersons()


{
try
{
persons = new Persons(this);
}
catch (Exception ex)
{
Intent home = new Intent(Intent.ACTION_MAIN);

113
113
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Files
SOFTWARE DEVELOPMENT FILes

home.addCategory(Intent.CATEGORY_HOME);
home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(home);
}
}
}

In onCreate() not much else happens than the method instantiates variables to the 4 input
In onCreate() not much else happens than the method instantiates variables to the 4 input
fields, but the method calls loadPersons(), which initializes the variable persons by creating
fields, but the method calls loadPersons(), which initializes the variable persons by creating
a new Persons object, thus reading all contacts in the file. Note the parameter, which is the
a new Persons object, thus reading all contacts in the file. Note the parameter, which is the
Context object. The constructor in the class Persons can raise an exception if the file for
Context object. The constructor in the class Persons can raise an exception if the file for
one reason or another can not be read correctly. If so, there is nothing more to do than
one reason or another can not be read correctly. If so, there is nothing more to do than
stop the application, and the method can be perceived as a standard way to stop an app.
stop the application, and the method can be perceived as a standard way to stop an app.

In addition to the method onCreate(), the class primarily has three event handlers for the
In addition to the method onCreate(), the class primarily has three event handlers for the
three buttons. Here, onSave() is the most comprehensive, as it must create a Person object
three buttons. Here, onSave() is the most comprehensive, as it must create a Person object
corresponding to what the user has entered. Otherwise, the method does not do much else
corresponding to what the user has entered. Otherwise, the method does not do much else
than to call the method save() in the class Persons, and finally the method shows a Toast
than to call the method save() in the class Persons, and finally the method shows a Toast
that tells whether the contact was saved or not.
that tells whether the contact was saved or not.

114
114
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT FILes
Files
SOFTWARE DEVELOPMENT FILes

The event handler onShow() must open another activity, and it happens the same way as
The event handler onShow() must open another activity, and it happens the same way as
shown earlier with one difference:
shown earlier with one difference:
intent.putExtra("persons", persons);
intent.putExtra("persons", persons);

It indicates that the object persons must be sent as a parameter and identified by the key
It
It indicates
indicates that
that the
the object
object persons
persons must
must bebe sent
sent as
as aa parameter
parameter and and identified
identified by
by the
the key
key
persons. The class Intent has many overrides of puExtra(), including overrides for all the
persons. The class Intent has many overrides of puExtra(), including overrides
persons. The class Intent has many overrides of puExtra(), including overrides for all the for all the
simple types and strings, but there is also an override for a serializable object, which is why
simple
simple types
types and
and strings,
strings, but
but there
there isis also
also an
an override
override for
for aa serializable
serializable object,
object, which
which isis why
why
the classes Person and Persons are defined Serializable.
the
the classes
classes Person
Person and
and Persons
Persons are
are defined
defined Serializable.
Serializable.
Then there is the class ShowActivity, which is the window that shows an overview of
Then
Then there
there isis the
the class
class ShowActivity,
ShowActivity, which
which isis the
the window
window that
that shows
shows an
an overview
overview of
of
all contacts:
all
all contacts:
contacts:
public class ShowActivity extends AppCompatActivity {
public
privateclass ShowActivity
Persons persons; extends AppCompatActivity {
private ListView
private Persons persons;
view;
private ListView view;
private ArrayAdapter<Person> adapter;
private ArrayAdapter<Person> adapter;

@Override
@Override void onCreate(Bundle savedInstanceState) {
protected
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show);
setContentView(R.layout.activity_show);
Intent intent = getIntent();
persons intent
Intent = getIntent();
= (Persons)intent.getSerializableExtra("persons");
persons = (Persons)intent.getSerializableExtra("persons");
view = (ListView) findViewById(R.id.lstView);
reset();
view = (ListView) findViewById(R.id.lstView);
reset();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
registerForContextMenu(view);
} registerForContextMenu(view);
}

@Override
@Override
public boolean onSupportNavigateUp(){
public boolean onSupportNavigateUp(){
finish();
return
finish();
true;
} return true;
}

@Override
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
public void onCreateContextMenu(ContextMenu
ContextMenu.ContextMenuInfo menuInfo) menu, View v,
{ ContextMenu.ContextMenuInfo menuInfo)
{new MenuInflater(this).inflate(R.menu.context_menu, menu);
} new MenuInflater(this).inflate(R.menu.context_menu, menu);
}

@Override
@Override
public boolean onContextItemSelected(MenuItem item) {
public boolean onContextItemSelected(MenuItem item) {

115
115
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Files
SOFTWARE DEVELOPMENT FILes

AdapterView.AdapterContextMenuInfo menuInfo =
(AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
Person person = persons.getPerson(menuInfo.position);
switch (item.getItemId()) {
case R.id.details_menu:
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra("person", person);
startActivity(intent);
return(true);
case R.id.remove_menu:
try
{
persons.remove(this, person);
reset();
Toast.makeText(this, getResources().getString(R.string.msg_rem),
Toast.LENGTH_LONG).show();
}
catch (Exception ex)
{
Toast.makeText(this, getResources().getString(R.string.err_rem),
Toast.LENGTH_LONG).show();
}
return(true);
}
return (super.onContextItemSelected(item));
}

private void reset()


{
view.setAdapter(adapter = new ArrayAdapter<Person>(this,
android.R.layout.simple_list_item_1, persons.getPersons()));
}
}

The
The code
code fills
fills aa part,
part, but
but itit is
is primarily
primarily the
the event
event hander
hander for
for the
the window’s
window’s context
context menu
menu
that
that fills.
fills. Note
Note howhow the
the method
method onCreate()
onCreate() determines
determines the
the parameter
parameter transferred
transferred from
from
MainActivity:
MainActivity:

Intent intent = getIntent();


persons = (Persons)intent.getSerializableExtra("persons");

where itit is
where is important
important toto use
use the
the same
same key
key and
and the
the correct
correct type
type of
of cast.
cast. Also
Also note
note that
that
onCreate() defines
onCreate() defines that
that the
the Action
Action Bar
Bar for
for the
the window
window should
should have
have aa back
back button:
button:

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

116
116
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Files

and corresponding override the method onSupportNavigationUp(). The context menu is defined
as a resource, and the class must implement onConextItemSelected(). The method fills a lot,
but it does not contain anything new. You should note that this time you transfer a Person
object to the activity DetailActivity. I do not want to show the code for DetailActivity, as
there is nothing new.

EXERCISE 6: NAMEBOOK
You shoul expand the NameBook example, such that you can also change the information
about a contact. Start with a copy of the project NameBook. You must add a new activity to
the project that can be used to edit a contact. Note that this activity should have a layout
similar to MainActivity, except that you can not edit the name and there should only be
a single button. The new activity should be opened by expanding the context menu with
a new menu item in ShowActivity. In addition, the class Persons must be expanded with a
new method so you can update the changes. It should be done in the same way as deletion,
where all activates are saved.

Join the best at Top master’s programmes


• 3
 3rd place Financial Times worldwide ranking: MSc
the Maastricht University International Business
• 1st place: MSc International Business
School of Business and • 1st place: MSc Financial Economics
• 2nd place: MSc Management of Learning

Economics! • 2nd place: MSc Economics


• 2nd place: MSc Econometrics and Operations Research
• 2nd place: MSc Global Supply Chain Management and
Change
Sources: Keuzegids Master ranking 2013; Elsevier ‘Beste Studies’ ranking 2012;
Financial Times Global Masters in Management ranking 2012

Maastricht
University is
the best specialist
university in the
Visit us and find out why we are the best! Netherlands
(Elsevier)
Master’s Open Day: 22 February 2014

www.mastersopenday.nl

117
JAVA
JAVA
JAVA 16:
16: MOBIL
16: MOBIL PHONES
MOBIL PHONES AND
PHONES AND ANDROID:
AND ANDROID:
ANDROID:
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT
DEVELOPMENT Files
FILes
FILes
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT FILes
FILes

There
There isis aa single challenge, namely when to save the changes. The easiest thing is to do
There is a single
single challenge,
challenge, namely
namely when
when toto save
save the
the changes.
changes. The
The easiest
easiest thing
thing is
is to
to do
do
that
that in
in ShowActivity,
ShowActivity, but
but itit requires
requires that
that the
the new
new activity
activity can
can return
return aa value
value when
when you
you click
click
that in ShowActivity, but it requires that the new activity can return a value when you click
Save
Save andand the
the window
window isis closed.
closed. You
You should
should solve
solve the
the problem
problem thatthat way,
way, especially
especially because
because
Save and the window is closed. You should solve the problem that way, especially because
itit may
may be
be useful
useful in
in other
other contexts.
contexts. To
To solve
solve the
the problem,
problem, follow
follow these
these steps:
steps:
it may be useful in other contexts. To solve the problem, follow these steps:

In
In ShowActivity you must add aa constant (the value is not important):
In ShowActivity
ShowActivity you
you must
must add
add a constant
constant (the
(the value
value is
is not
not important):
important):

private static final int PERSON_UPDATED =


private static final int PERSON_UPDATED 1;
private static final int PERSON_UPDATED =
= 1;
1;

You must then add the following method:


You must then
You must then add
add the
the following
following method:
method:

public void
public void onActivityResult(int requestCode,
requestCode, int resultCode,
resultCode, Intent data) {
public void onActivityResult(int
onActivityResult(int requestCode, int
int resultCode, Intent
Intent data)
data) {
{
if (requestCode == PERSON_UPDATED)
if (requestCode == PERSON_UPDATED)
if (requestCode == PERSON_UPDATED)
{
{
{
if
if (resultCode == RESULT_OK) {
if (resultCode
(resultCode == RESULT_OK) {
== RESULT_OK) {
// here you can save the changes to the file
// here you can save the changes to the file
// here you can save the changes to the file
Person
Person person = (Person)data.getSerializableExtra("person");
Person person
person =
= (Person)data.getSerializableExtra("person");
(Person)data.getSerializableExtra("person");



}
}
}
}
}
}
}
}
}
}
}
}

The method
The method onActivityResult() isis now
now a method thatthat can bebe called from
from your new
new activity
The method onActivityResult()
onActivityResult() is now aa method
method that can
can be called
called from your
your new activity
activity
when
when it ends and wishes to send a value back. It requires the new activity to be opened as:
when it
it ends
ends and
and wishes
wishes to
to send
send a
a value
value back.
back. It
It requires
requires the
the new
new activity
activity to
to be
be opened
opened as:
as:

startActivityForResult(intent,
startActivityForResult(intent, PERSON_UPDATED);
startActivityForResult(intent, PERSON_UPDATED);
PERSON_UPDATED);

In
In your
In your new
your new activity,
new activity, you
activity, you can
you can then
can then write
then write the
write the event
the event handler
event handler for
handler for the
for the Save
the Save button
Save button as
button as follows:
as follows:
follows:

public void
public void onSave(View view)
view)
public void onSave(View
onSave(View view)
{
{
{
person.setPhone(txtPhone.getText().toString().trim());
person.setPhone(txtPhone.getText().toString().trim());
person.setPhone(txtPhone.getText().toString().trim());
person.setMail(txtMail.getText().toString().trim());
person.setMail(txtMail.getText().toString().trim());
person.setMail(txtMail.getText().toString().trim());
person.setText(txtText.getText().toString().trim());
person.setText(txtText.getText().toString().trim());
person.setText(txtText.getText().toString().trim());
Intent
Intent data = new Intent();
Intent data
data =
= new
new Intent();
Intent();
data.putExtra("person", person);
data.putExtra("person", person);
data.putExtra("person", person);
setResult(RESULT_OK,
setResult(RESULT_OK, data);
setResult(RESULT_OK, data);
data);
finish();
finish();
finish();
}
}
}

118
118
118
118
118
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Files

PROBLEM 2: PUZZLEAPP
As the final example in the book Java 4, I have shown a program that simulates a simple game,
which consists of a square of 5 × 5 pieces arranged in random order. One of the pieces is empty,
and you can move a piece by moving a neighbor to the empty piece. In the case below (the
square on the left) you can then move the pieces H, E, L and J (you can not move diagonally).
The game is solved when the pieces are arranged as shown in the example to the right.

The square is basically a 5 × 5 square, but it must in the same way as in Java 4 be possible
to configure the program so that you can also play with a 3 × 3 square, a 7 × 7 square and
a 9 × 9 square. Also the program must have a high score list where to save the five best
results. A result consists of the number of movements, used to solve the square, and it is
therefore to solve the square by moving as few pieces as possible.

The program should work in the same way as in Java 4, but must be written to a mobile
phone this time and the user interface could be something like the following:

119
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Files

You can reuse much of the code from Java 4 – if not directly, then using smaller adjustments.
Of course, the two challenges are the user interface, which needs to be written in a different
way, and to save the high score list that must be saved in local file.

120
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT SQLite

6 SQLITE
You can also write apps for mobile phones that use databases, because Android is born
with a very simple database called SQLite. The database is also widely used in many other
places than on Android devices. It’s a simple database (what exactly is also the goal) and
it has far from all the facilitators that other database products (like MySQL, Oracle, etc.)
make available, but it’s a complete SQL database where you can create local databases
and performs the usual database operations – almost as you know it from MySQL. In this
chapter, I will show you how to use SQLite through an example.

As example, I will write an app called PhoneBook and it corresponds to the Contact app
with which the phone is born, but it is not intended as an alternative to that application,
but only to show the use of a database, and it should also be a example of a slightly larger
app and thus a slightly more realistic app than what the previous examples have shown.
The application’s data must be stored in a database with two tables:

where one table is a table with Danish zip codes, while the other contains contact information
about persons. The column code in table addresses is a foreign key to the table zipcodes.
When you open the application, you get a window that shows an overview of zip codes
(see below). At the top there are a two input fields and two buttons that act as a filter for
zip codes. In general, contacts are organized by zip codes and in order to find a contact,
hold your finger on a zip code, after which you get a context menu, where you can either
view the contacts organized under that zip code or add a new contact. If you choose to
view existing contacts, there are three options:

1. There are no contacts, and you just get a simple Toast that tells you.
2. There is a single contact and the program opens a window that displays the
informations (see below). In this window you can also edit the contact and delete it.
3. You will get a window that shows all contacts organized under the current zip code.
I have not shown the window here, but it is nothing but a ListView with the names
of those contacts. If you here click on a name, you will come to the window with
all the contact informations.

121
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT SQLite

As the last concerning the user interface, MainActivity has an option menu with a single
menu item. Clicking on it opens an activity where you can enter search criteria (first name,
last name, address and title), and the program will find the contacts that match the search
criteria. The result has the same three options as described above.

122
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT SQLite

It was the program’s functionality, and then how the program is written. There are no less
than 4 activities, but none of them contain anything new, so I do not want to display the
XML code for the layout, and the following only concerns the Java code and here primarily
how to

1. creates a database
2. performs a SQL INSERT
3. performs a SQL UPDATE
4. performs a SQL DELETE
5. performs a SQL SELECT

and the following will be centered on these 5 topics.

The program must be initialized with the Danish zip codes, and to make it easy, I have
added a resource:

raw/zipcodes.txt

which is a comma-separated file with the Danish zip codes.

Need help with your


dissertation?
Get in-depth feedback & advice from experts in your
topic area. Find out what you can do to improve
the quality of your dissertation!

Get Help Now

Go to www.helpmyassignment.co.uk for more info

123
JAVA
JAVA16:
16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
SOFTWARE
SOFTWAREDEVELOPMENT
DEVELOPMENT SQLite
sQLIte

6.1
6.1 CREATES
CREATES AA DATABASE
DATABASE
You
You cancan create
create aa database
database inin two
two ways.
ways. You
You can
can dodo itit extern
extern on
on thethe developer
developer machine,
machine, andand
then
then copy
copy the
the database
database to to the
the application
application asas aa resource,
resource, butbut itit can
can easily
easily lead
lead to
to difficulties
difficulties
ifif the
the database
database hashas toto be
be updated
updated later.
later. For
For that
that reason,
reason, there
there isis aa helper
helper class
class that
that makes
makes
itit easy
easy to
to create
create the
the database
database in in the
the code
code and
and ensures
ensures that
that thethe database
database isis automatically
automatically
created
created thethe first
first time
time the
the application
application isis used,
used, but
but also
also ensures
ensures that
that the
the database
database isis updated
updated
ifif you
you change
change itit later
later –– assuming
assuming that
that you
you have
have added
added the the required
required code.
code. InIn the
the present
present
case,
case, II have
have added
added thethe following
following class:
class:

package dk.data.torus.phonebook;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.io.*;

public class DbHelper extends SQLiteOpenHelper


{
public static final java.util.Random rand = new java.util.Random();
public static final String ZTABLE_NAME="zipcodes";
public static final int ZCOLNO_CODE = 0;
public static final int ZCOLNO_CITY = 1;
public static final String[] ZTABLE_COLUMNS = new String[]{ "code", "city" };
public static final String ATABLE_NAME="addresses";
public static final int ACOLNO_ID = 0;
public static final int ACOLNO_FIRRSTNAME = 1;
public static final int ACOLNO_LASTNAME = 2;
public static final int ACOLNO_ADDRESS = 3;
public static final int ACOLNO_CODE = 4;
public static final int ACOLNO_PHONE = 5;
public static final int ACOLNO_MAIL = 6;
public static final int ACOLNO_DATE = 7;
public static final int ACOLNO_TITLE = 8;
public static final String[] ATABLE_COLUMNS =
new String[]{ "id", "firstname", "lastname", "address", "code", "phone",
"mail", "date", "title" };
private static final String DBFILENAME="phonebook.db";
private static final int DBVERSION = 1;
private static final String ZINITIAL_SCHEMA =
"create table zipcodes (code char(4) primary
key, city varchar(30) not null)";
private static final String AINITIAL_SCHEMA =
"create table addresses (" +
"id integer primary key autoincrement," +
"firstname varchar(50) not null," +
"lastname varchar(30)," +

124
124
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT SQLite
SOFTWARE DEVELOPMENT sQLIte

"address varchar(50)," +
"code char(4) not null," +
"phone varchar(20)," +
"mail varchar(50)," +
"date varchar(10)," +
"title varchar(50),"+
"foreign key (code) references zipcodes (code))";
private Context context;

public DbHelper(Context context) {


super(context, DBFILENAME, null, DBVERSION);
// super(context, DBFILENAME, null, rand.nextInt(20) + 1);
this.context = context;
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(ZINITIAL_SCHEMA);
db.execSQL(AINITIAL_SCHEMA);
db.execSQL(insertZipcodes());
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// db.execSQL("DROP TABLE IF EXISTS zipcodes");
// db.execSQL("DROP TABLE IF EXISTS addresses");
// db.execSQL(ZINITIAL_SCHEMA);
// db.execSQL(AINITIAL_SCHEMA);
// db.execSQL(insertZipcodes());
}

@Override
public void onDowngrade(SQLiteDatabase db,
int oldVersion, int newVersion) {
// db.execSQL("DROP TABLE IF EXISTS zipcodes");
// db.execSQL("DROP TABLE IF EXISTS addresses");
// db.execSQL(ZINITIAL_SCHEMA);
// db.execSQL(AINITIAL_SCHEMA);
// db.execSQL(insertZipcodes());
}

private String insertZipcodes()


{
InputStream stream = context.getResources().
openRawResource(R.raw.zipcodes);
StringBuilder builder =
new StringBuilder("insert into zipcodes (code, city) values ");
try (BufferedReader reader = new BufferedReader(new

125
125
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT SQLite
SOFTWARE DEVELOPMENT sQLIte

InputStreamReader(stream)))
{
addRow(builder, reader.readLine());
for (String line = reader.readLine(); line
!= null; line = reader.readLine())
{
if (line.length() > 0)
{
builder.append(",");
addRow(builder, line);
}
}
}
catch (Exception e) {
}
return builder.toString();
}

private void addRow(StringBuilder builder, String line)


{
String[] elems = line.split(",");
builder.append("('");
builder.append(elems[0]);

Brain power By 2020, wind could provide one-tenth of our planet’s


electricity needs. Already today, SKF’s innovative know-
how is crucial to running a large proportion of the
world’s wind turbines.
Up to 25 % of the generating costs relate to mainte-
nance. These can be reduced dramatically thanks to our
systems for on-line condition monitoring and automatic
lubrication. We help make it more economical to create
cleaner, cheaper energy out of thin air.
By sharing our experience, expertise, and creativity,
industries can boost performance beyond expectations.
Therefore we need the best employees who can
meet this challenge!

The Power of Knowledge Engineering

Plug into The Power of Knowledge Engineering.


Visit us at www.skf.com/knowledge

126
126
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT SQLite
SOFTWARE DEVELOPMENT sQLIte

builder.append("','");
builder.append(elems[1]);
builder.append("')");
}
}

Initially,
Initially,a arandom
randomgenerator
generatorhashasbeenbeendefined
definedand andititshould
shouldnot notbebepart
partofofa athe
thefinished
finished
application,
application, but I will explain the stetement in a while. Otherwise, the class defines alarge
but I will explain the stetement in a while. Otherwise, the class defines a large
number of constants that defines the database. These constants are not
number of constants that defines the database. These constants are not absolutely necessary, absolutely necessary,
but
butthey
theycancanmake
makethe thefollowing
followingcode codeeasier
easiertotoread
readand andunderstand,
understand,and andthey
theycan
canmake
make
the
themaintenance
maintenanceofofthe thecode
codesignificantly
significantlyeasier.
easier.ItItisistherefore
thereforeadvisable
advisabletotointroduce
introducethese
these
constants, and in this case there are two sets of constants for each of the two
constants, and in this case there are two sets of constants for each of the two database tables. database tables.
When
Whenyou youseeseethe
theconstants,
constants,it’s
it’seasy
easyenough
enoughtotounderstand
understandthe themeaning.
meaning.Note Notethat
thatthere
thereisisa a
constant
constantfor forthe
thedatabase
databasenamenameitself,
itself,and
andnote
notethat
thatthere
thereisisa aconstant
constantfor forthe
theversion
versionnumber.
number.
Also
Alsonote
notethat
thatthere
thereareareconstants
constantsfor forthe
thetwo
twoSQL
SQLexpressions
expressionsthat thatcreate
createthe
thedatabase
databasetables.
tables.

The
Theclass
classinherits
inheritsSQLiteOpenHelper,
SQLiteOpenHelper,and andthetheconstructor
constructorininthe
thebase
baseclass
classchecks,
checks,ififthere
there
isisa adatabase with that name. If not, it will perform onCreate(). If the database
database with that name. If not, it will perform onCreate(). If the database is found, is found,
the
theversion
versionnumber
numberisistested
testedand
andititisislarger
largerthan
thanthe
thedatabase
databaseversion
versionnumber
numberthe themethod
method
onUpgrade() is performed. Is the version number smaller than the database
onUpgrade() is performed. Is the version number smaller than the database version number version number
the
themethod
methodonDowngrade()
onDowngrade()isisperformed.
performed.AASQLiteOpenHelper
SQLiteOpenHelperclass
classshould
shouldtherefore
thereforeoverride
override
these three methods – however, in many cases you do not override the last one
these three methods – however, in many cases you do not override the last one (the version (the version
number
numberwill willalways
alwaysbebehigher).
higher).

InInthis
thiscase,
case,onCreate()
onCreate()creates
createsthethetwo
twotables.
tables.Note
Notethat
thatititisisthe
theconstructor
constructorininthe thebase
base
class that creates the database, while onCreate() creates the tables. onCreate() calls
class that creates the database, while onCreate() creates the tables. onCreate() calls the method the method
insertZipcodes().
insertZipcodes().ItItuses
usesa aStringBuilder
StringBuildertotodynamically
dynamicallycreate
createa aSQL
SQLINSERT
INSERTusingusingthetheresource
resource
with the zip codes, and the method returns the result as a string. onCreate()
with the zip codes, and the method returns the result as a string. onCreate() has a parameterhas a parameter
ofofthe
thetype
typeSQLiteDatabase
SQLiteDatabaseand anditithas
hasmethods,
methods,such suchasasheader
headerexecSQL(),
execSQL(),which
whichperforms
performs
a aSQL
SQL statement. The method is used to create the two tables and can generally beused
statement. The method is used to create the two tables and can generally be usedtoto
execute
executea aSQLSQLstatement
statementrepresented
representedasasa astring
stringand
andthus
thusalso
alsothe
theresult
resultofofinsertZipcodes().
insertZipcodes().

The
Theprogram
programalso alsooverrides
overridesthetheother
othertwo twomethods
methodsfromfromthe thebase
baseclass:
class:onUpgrade()
onUpgrade()and and
onDowngrade().
onDowngrade(). Both are trivial as all the code has been commented out, but the meaningisis
Both are trivial as all the code has been commented out, but the meaning
that
thatyou
youhave
havetotoinsert
insertthe
thecode
codetotobebeused
usedififthe
theversion
versionnumber
numberisisincreased
increased(until
(untilyou
youdefine
define
the final version). When you develop a program, you will typically be interested
the final version). When you develop a program, you will typically be interested in creating in creating
the
thedatabase
databaseeach
eachtimetimeyou
yourun
runthetheprogram.
program.This Thiscan
canbebeenforced
enforcedbybyincreasing
increasingthetheversion
version
number,
number, and then adding the code to onUpgrade(), which deletes the existing tables andre-
and then adding the code to onUpgrade(), which deletes the existing tables and re-
creates
createsthem.
them.That
Thatisisthethegoal
goalofofmy
myrandom
randomgenerator
generatorthat
thatevery
everytime
timethetheprogram
programruns,runs,itit
gets
getsa arandom
randomversion
versionnumber
number(see (seethe
theconstructor)
constructor)and andthetheresult
resultisisthat
thateither
eitheronUpgarde()
onUpgarde()
ororonDownload()
onDownload() is performed. You may, of course, remember to remove this actionbefore
is performed. You may, of course, remember to remove this action before
applying the application, otherwise you delete the database every time the application
applying the application, otherwise you delete the database every time the application is running. is running.

127
127
JAVA
JAVA16:
16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
SOFTWARE
SOFTWAREDEVELOPMENT
DEVELOPMENT SQLite
sQLIte

6.2
6.2 SQL
SQLSELECT
SELECT
To
To the
the project
project has
has been
been added
added two
two model
model classes
classes Zipcode
Zipcode and
and Person,
Person, which
which represent
represent aa
zip
zipcode
codeand
andaacontact,
contact,respectively.
respectively.Both
Bothclasses
classesare
aresimple
simpleand
andconsist
consistonly
onlyofofget
getand
andset
set
methods,
methods,butbutyou
youshould
shouldnote
notethat
thatboth
bothclasses
classesare
aredefined
definedSerializable,
Serializable,sosothat
thatobjects
objectsofof
the
theclasses
classescan
canbebetransferred
transferredasasparameters
parameterstotoother
otheractivities.
activities.

There
Thereisisalso
alsoaaclass
classcalled
calledZipcodes,
Zipcodes,which
whichrepresents
representsall
allzip
zipcodes:
codes:

package dk.data.torus.phonebook;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.util.ArrayList;
import java.util.List;

public class Zipcodes implements java.io.Serializable


{
private List<Zipcode> zipcodes = new ArrayList();

public Zipcodes(SQLiteDatabase db)


{
try {
Cursor cursor = db.query(DbHelper.ZTABLE_NAME, DbHelper.ZTABLE_COLUMNS,
null, null, null, null, null);
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
String code = cursor.getString(DbHelper.ZCOLNO_CODE);
String city = cursor.getString(DbHelper.ZCOLNO_CITY);
zipcodes.add(new Zipcode(code, city));
}
cursor.close();
}
catch (Exception ex)
{
zipcodes.clear();
}
}

public List<Zipcode> getZipcodes()


{
return zipcodes;
}
}

The
The class
class has
has aa single
single instance
instance variable,
variable, which
which isis used
used for
for the
the Zipcode
Zipcode objects.
objects. The
The list
list isis
initialized
initializedininthe
theconstructor,
constructor,whose
whoseparameter
parameterisisan anopen
opendatabase.
database.The
Theconstructor
constructorstarts
starts

128
128
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT SQLite
sQLIte

by
by creating
creating aa Cursor,
Cursor, which
which isis an
an object
object that
that represents
represents aa SQL
SQL SELECT
SELECT and
and can
can be
be used
used
to
to traverse
traverse the
the result.
result. In
In this
this case,
case, aa SELECT
SELECT statement
statement isis performed
performed using
using the
the method
method
query(),
query(), which
which is
is quite
quite aa complex
complex method
method

query(String table,
String columns[],
String selection,
String selectionArgs,
String groupBy,
String having,
String orderBy,
String limit)

The
The method
method has
has aa parameter
parameter for for each
each of
of the
the elements
elements thatthat can
can be
be included
included inin aa SELECT
SELECT
statement,
statement, and
and above,
above, II have
have only
only set
set values
values for
for the
the first
first two
two parameters,
parameters, since
since the
the statement
statement
should
should retrieve all zip codes in the database. You should note how the table name and
retrieve all zip codes in the database. You should note how the table name and
column
column names
names are
are defined
defined using
using the
the constants
constants in
in the
the class
class DbHelper.
DbHelper. After
After the
the statement
statement has
has
been
been completed,
completed, youyou can
can traverse
traverse the
the rows
rows using
using the
the Cursor
Cursor object,
object, an
an object
object that
that basically
basically
works
works in
in the
the same
same wayway asas aa ResultSet.
ResultSet.

129
129
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT SQLite
sQLIte

There
There isis also
also aa class
class called
called Persons
Persons that,
that, in
in principle,
principle, works
works in
in the
the same
same way,
way, but
but where
where the
the
constructor
constructor instead
instead determines
determines aa list
list of
of Person
Person objects:
objects:

package dk.data.torus.phonebook;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.util.ArrayList;
import java.util.List;

public class Persons implements java.io.Serializable


{
private List<Person> persons = new ArrayList();

public Persons(SQLiteDatabase db, Zipcode zipcode)


{
try {
String[] params = new String[]{zipcode.getCode()};
Cursor cursor =
db.rawQuery("select * from addresses where code = ?", params);
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
int id = cursor.getInt(DbHelper.ACOLNO_ID);
String fname = cursor.getString(DbHelper.ACOLNO_FIRRSTNAME);
String lname = cursor.getString(DbHelper.ACOLNO_LASTNAME);
String addr = cursor.getString(DbHelper.ACOLNO_ADDRESS);
String phone = cursor.getString(DbHelper.ACOLNO_PHONE);
String mail = cursor.getString(DbHelper.ACOLNO_MAIL);
String date = cursor.getString(DbHelper.ACOLNO_DATE);
String title = cursor.getString(DbHelper.ACOLNO_TITLE);
persons.add(new Person(id, fname, lname, addr, zipcode, phone,
mail, date, title));
}
cursor.close();
}
catch (Exception ex)
{
persons.clear();
}
}

public Persons(SQLiteDatabase db, String firstname, String lastname,


String address, String persontitle)
{
try {
Cursor cursor = db.query(DbHelper.ATABLE_NAME, DbHelper.ATABLE_COLUMNS,
"firstname like ? and lastname like ? and
address like ? and title like ?",

130
130
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT SQLite
SOFTWARE DEVELOPMENT sQLIte

new String[] { firstname + "%", lastname + "%", "%" + address + "%",


"%" + persontitle + "%" }, null, null, null);
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext())
{
int id = cursor.getInt(DbHelper.ACOLNO_ID);
String fname = cursor.getString(DbHelper.ACOLNO_FIRRSTNAME);

persons.add(new Person(id, fname, lname, addr, getZipcode(db, code),
phone, mail, date, title));
}
cursor.close();
}
catch (Exception ex)
{
persons.clear();
}
}
public List<Person> getPersons()
{
return persons;
}

private Zipcode getZipcode(SQLiteDatabase db, String code)


{
Cursor cursor = db.query(DbHelper.ZTABLE_NAME, DbHelper.ZTABLE_COLUMNS,
"code = ?", new String[] { code }, null, null, null);
cursor.moveToFirst();
return new Zipcode(cursor.getString(DbHelper.ZCOLNO_CODE),
cursor.getString(DbHelper.ZCOLNO_CITY));
}
}

Here
Here is
is the
the most
most important
important thing
thing the
the two
two constructors
constructors which
which based
based on
on search
search criteria
criteria
determines
determines a number of contacts in the database. The difference is how they define the
a number of contacts in the database. The difference is how they define the
SQL SELECT statement.
SQL SELECT statement.

The
The first
first finds
finds all
all contacts
contacts that
that have
have aa specific
specific zip
zip code,
code, but
but this
this time
time the
the Cursor
Cursor object
object is
is
created using a method rawQuery(). It has two parameters, the first being
created using a method rawQuery(). It has two parameters, the first being a regular SELECT a regular SELECT
statement
statement written
written as
as aa string.
string. In
In the
the same
same way
way asas you
you have
have seen
seen before,
before, the
the SQL
SQL statement
statement
may
may have
have parameters
parameters as as indicated
indicated byby ?? and
and the
the last
last parameter
parameter for for the
the method
method rawQuery()
rawQuery()
should
should be be an
an array
array of
of values
values toto be
be substituted
substituted forfor the
the ?? placeholders.
placeholders. After
After the
the statement
statement
is
is completed, the Cursor uses the object in the same way as above, but this time, Person
completed, the Cursor uses the object in the same way as above, but this time, Person
objects
objects are created. Note how the individual columns are referenced with constants from
are created. Note how the individual columns are referenced with constants from
the
the class
class DbHelper.
DbHelper.

131
131
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT SQLite

The other constructor has in addition to a reference to an open database four parameters, all
of which are strings. The constructor must find all contacts where the first name starts with
a certain value, where the last name starts with a certain value, where the address contains
a certain value and the title contains a particular value. The Cursor object is created this
time using the method query(), but the first four parameters are used to define a WHERE
part. The actual WHERE part is a string (an expression), and the following parameter is
an array of strings to the expression’s placeholders. Otherwise, the two constructors seems
to work identically, but note that in the last case it is necessary to determine the zip code
by reading the database.

6.3 SQL INSERT, UPDATE AND DELETE


The application has an activity called PersonActivity, which is used to display contact details
(see the window above), but also used to create new contacts, edit existing contacts, and
delete contacts. The code is therefore similarly comprehensive:

132
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT SQLite
SOFTWARE DEVELOPMENT sQLIte

package dk.data.torus.phonebook;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.widget.*;
import android.view.*;
import android.database.sqlite.SQLiteDatabase;
import android.content.ContentValues;
import java.util.*;

public class PersonActivity extends AppCompatActivity {


private Zipcode zipcode = null;
private Person person = null;
private EditText txtZip;
private EditText txtFname;
private EditText txtLname;
private EditText txtAddr;
private EditText txtPhone;
private EditText txtMail;
private EditText txtDate;
private EditText txtTitle;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_person);
Intent intent = getIntent();
txtFname = (EditText) findViewById(R.id.txtFname);
txtLname = (EditText) findViewById(R.id.txtLname);
txtAddr = (EditText) findViewById(R.id.txtAddr);
txtPhone = (EditText) findViewById(R.id.txtPhone);
txtMail = (EditText) findViewById(R.id.txtMail);
txtDate = (EditText) findViewById(R.id.txtDate);
txtTitle = (EditText) findViewById(R.id.txtTitle);
txtZip = (EditText) findViewById(R.id.txtZip);
Object obj = intent.getSerializableExtra("zipcode");
if (obj != null) {
zipcode = (Zipcode) obj;
Calendar cal = Calendar.getInstance();
txtDate.setText(String.format("%02d-%02d-
%d", cal.get(Calendar.DAY_OF_MONTH),
cal.get(Calendar.MONTH) + 1, cal.get(Calendar.YEAR)));
}
else
{
person = (Person)intent.getSerializableExtra("person");
txtFname.setText(person.getFirstname());

133
133
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT SQLite
SOFTWARE DEVELOPMENT sQLIte

txtLname.setText(person.getLastname());
txtAddr.setText(person.getAddress());
txtPhone.setText(person.getPhone());
txtMail.setText(person.getMail());
txtDate.setText(person.getDate());
txtTitle.setText(person.getTitle());
zipcode = person.getZipcode();
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
txtZip.setText(zipcode.toString());
disable(txtDate);
disable(txtZip);
}

@Override
public boolean onSupportNavigateUp(){
finish();
return true;
}

public void onOk(View view)


{
String fname = txtFname.getText().toString().trim();
if (fname.length() > 0)
{
String lname = txtLname.getText().toString().trim();
String addr = txtAddr.getText().toString().trim();
String phone = txtPhone.getText().toString().trim();
String mail = txtMail.getText().toString().trim();
String date = txtDate.getText().toString().trim();
String title = txtTitle.getText().toString().trim();
DbHelper dbHelper = new DbHelper(this);
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues(8);
values.put(DbHelper.ATABLE_COLUMNS[DbHelper.ACOLNO_FIRRSTNAME], fname);
values.put(DbHelper.ATABLE_COLUMNS[DbHelper.ACOLNO_LASTNAME], lname);
values.put(DbHelper.ATABLE_COLUMNS[DbHelper.ACOLNO_ADDRESS], addr);
values.put(DbHelper.ATABLE_COLUMNS[DbHelper.
ACOLNO_CODE], zipcode.getCode());
values.put(DbHelper.ATABLE_COLUMNS[DbHelper.ACOLNO_PHONE], phone);
values.put(DbHelper.ATABLE_COLUMNS[DbHelper.ACOLNO_MAIL], mail);
values.put(DbHelper.ATABLE_COLUMNS[DbHelper.ACOLNO_TITLE], title);
if (person == null)
{
values.put(DbHelper.ATABLE_COLUMNS[DbHelper.ACOLNO_DATE], date);
db.insert(DbHelper.ATABLE_NAME, null, values);
}
else
{

134
134
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT SQLite
SOFTWARE DEVELOPMENT sQLIte

Calendar cal = Calendar.getInstance();


values.put(DbHelper.ATABLE_COLUMNS[DbHelper.ACOLNO_DATE],
String.format("%02d-%02d-%d", cal.get(Calendar.DAY_OF_MONTH),
cal.get(Calendar.MONTH) + 1, cal.get(Calendar.YEAR)));
String[] args = { "" + person.getId() };
db.update(DbHelper.ATABLE_NAME, values, "id = ?", args);
}
db.close();
onSupportNavigateUp();
}
}

public void onRem(View view)


{
if (person != null)
{
DbHelper dbHelper = new DbHelper(this);
SQLiteDatabase db = dbHelper.getWritableDatabase();
String[] args = { "" + person.getId() };
db.delete(DbHelper.ATABLE_NAME, "id = ?", args);
db.close();
onSupportNavigateUp();
}
}

Challenge the way we run

EXPERIENCE THE POWER OF


FULL ENGAGEMENT…

RUN FASTER.
RUN LONGER.. READ MORE & PRE-ORDER TODAY
RUN EASIER… WWW.GAITEYE.COM

135
1349906_A6_4+0.indd 1 22-08-2014 12:56:57
135
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT SQLite
SOFTWARE DEVELOPMENT sQLIte

private void disable(EditText view)


{
view.setKeyListener(null);
view.setEnabled(false);
}
}

The class defines several variables, but for the sake of the code, the most important are
The class defines several variables, but for the sake of the code, the most important are
the first two, which define a Zipcode and a Person object, respectively. The other variables
the first two, which define a Zipcode and a Person object, respectively. The other variables
are components in the user interface and are initialized in onCreate(). When the relevant
are components in the user interface and are initialized in onCreate(). When the relevant
activity is opened, a parameter is transferred, either a Zipcode object (if you want to create
activity is opened, a parameter is transferred, either a Zipcode object (if you want to create
a new contact) or a Person object (if you want to view or edit a contact). onCreate() starts
a new contact) or a Person object (if you want to view or edit a contact). onCreate() starts
by referencing a Zipcode object, and if this reference is not null, it is a Zipcode object that
by referencing a Zipcode object, and if this reference is not null, it is a Zipcode object that
has been transferred and the variable zipcode is initialized (while the variable person is still
has been transferred and the variable zipcode is initialized (while the variable person is still
null). Next, the field txtDate is set to date, as this field must contain the date of last change
null). Next, the field txtDate is set to date, as this field must contain the date of last change
of the contact. If obj is zero, it is because the transferred parameter is a Person object, and
of the contact. If obj is zero, it is because the transferred parameter is a Person object, and
the variable person is then initialized with this object. It is the object to be displayed in the
the variable person is then initialized with this object. It is the object to be displayed in the
user interface, and all fields are initialized with the object’s values. Finally, note that the
user interface, and all fields are initialized with the object’s values. Finally, note that the
txtDate and txtZip fields are read-only as these fields can not be changed.
txtDate and txtZip fields are read-only as these fields can not be changed.

The class defines two event handlers onOk() and onRem(), where the first one is used when
The class defines two event handlers onOk() and onRem(), where the first one is used when
the OK button is clicked while the last one is used when clicking on the button REMOVE.
the OK button is clicked while the last one is used when clicking on the button REMOVE.
onOk() tests whether a first name has been entered (it is assumed that a contact must have
onOk() tests whether a first name has been entered (it is assumed that a contact must have
a first name). If so, the handler determines the other values entered in the user interface,
a first name). If so, the handler determines the other values entered in the user interface,
and then create an object that represents the database. Here you must note the syntax as
and then create an object that represents the database. Here you must note the syntax as
well as the database is opend writeable. Next, a ContentValue object is created containing
well as the database is opend writeable. Next, a ContentValue object is created containing
the values to be written to the database, whether it is because a new row must be created
the values to be written to the database, whether it is because a new row must be created
or it is an existing row to be updated. Note again the syntax and note how to refer to the
or it is an existing row to be updated. Note again the syntax and note how to refer to the
individual columns using the constants defined in the class DbHelper. Next, the variable
individual columns using the constants defined in the class DbHelper. Next, the variable
person is tested, and if it is null, it is an INSERT and otherwise it should be an UPDATE.
person is tested, and if it is null, it is an INSERT and otherwise it should be an UPDATE.
Basically, it happens the same way, in the one case, you use the method insert() method,
Basically, it happens the same way, in the one case, you use the method insert() method,
while in the second case, you use the method update(), except that in the latter case you
while in the second case, you use the method update(), except that in the latter case you
should specify a WHERE part.
should specify a WHERE part.

Finally, there is the last event handler used to delete a contact and thus perform a SQL
Finally, there is the last event handler used to delete a contact and thus perform a SQL
DELETE. It’s basically done just in the same way as above, but where you must use the
DELETE. It’s basically done just in the same way as above, but where you must use the
method delete().
method delete().

136
136
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT SQLite
sQLIte

6.4
6.4 THE
THE OTHER
OTHER ACTIVITIES
ACTIVITIES
The
The aplicationen
aplicationen has has three
three additional
additional activities.
activities. PersonsActivity
PersonsActivity displays
displays aa list
list of
of contacts
contacts
found
found in
in the
the database,
database, and and it’s
it’s aa simple
simple activity
activity with
with aa ListVew,
ListVew, and and clicking
clicking onon aa contact
contact
PersonActivity
PersonActivity isis shown.
shown. The The Java
Java code
code contains
contains nothing
nothing regarding
regarding databases.
databases. TheThe activity
activity
SearchActivity
SearchActivity is also simple and is used to enter search criteria, and the code is executed aa
is also simple and is used to enter search criteria, and the code is executed
SQL
SQL SELECT,
SELECT, but but using
using thethe class
class Persons.
Persons. Finally,
Finally, there
there isis MainActivity,
MainActivity, which
which binds
binds itit all
all
together
together and
and fills
fills aa lot.
lot. II do
do not
not want
want toto display
display the
the code
code for for these
these three
three activities,
activities, as
as they
they
do
do not
not contain
contain anything
anything new new regarding
regarding databases,
databases, and
and by
by thethe way,
way, nothing
nothing new.
new.

EXERCISE
EXERCISE 7:
7: PHONEBOOK
PHONEBOOK
In
In this
this exercise
exercise youyou will
will need
need toto make
make some
some changes
changes to
to the
the above
above program
program PhoneBook,
PhoneBook, and
and
the
the goal
goal isis to
to add
add some
some small
small improvements,
improvements, but
but primarily
primarily to
to work
work aa bit
bit more
more with
with database
database
programming and SQLite. Start by creating a copy of
programming and SQLite. Start by creating a copy of the project.the project.

As
As the
the first
first change,
change, expand
expand the
the table
table addresses
addresses with
with an
an additional
additional column,
column, whichwhich you
you can
can
call
call text
text and
and whose
whose type
type should
should be
be VARCHAR(1000).
VARCHAR(1000). The The idea
idea isis that
that itit should
should be
be possible
possible
to
to associate a short description with a contact. You must start changing the DbHelper class:
associate a short description with a contact. You must start changing the DbHelper class:

1.
1. delete
delete the
the variable
variable rand
rand atat the
the start
start of
of the
the class
class
2.
2. delete
delete the
the line
line with
with the
the comment
comment in in the
the constructor
constructor
3. delete the method onDowngrade()
3. delete the method onDowngrade()
4.
4. add
add an
an int
int constant
constant with
with the
the name
name ACOLNO_TEXT
ACOLNO_TEXT and and the
the value
value 99 to
to the
the class
class
5.
5. add
add aa String
String “text”
“text” to
to the
the array
array ATABLE_COLUMNS
ATABLE_COLUMNS
6.
6. update
update the
the SQL
SQL expression
expression (the(the String
String AINITIAL_SCEMA)
AINITIAL_SCEMA) such such that
that itit creates
creates aa
column
column with
with the
the name
name text
text and
and the
the type
type varchar(1000).
varchar(1000).

Next,
Next, you
you must
must change
change the
the method
method onUpgrade()
onUpgrade() to
to the
the following:
following:

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {


if (newVersion > oldVersion) {
try {
db.execSQL("ALTER TABLE addresses ADD COLUMN
text VARCHAR(1000) DEFAULT ''");
}
catch (Exception ex)
{
}
}
}

137
137
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT SQLite

Test the program. The result should now be that the database table addresses have a new
column, but it still contains the old contacts.

You must then expand the program such that you can also enter a text, which means that
the window for entering and editing contacts must be expanded with an input field:

This e-book
is made with SETASIGN
SetaPDF

PDF components for PHP developers

www.setasign.com

138
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT SQLite

You can do the following:

1. Expand the class Person with an additional String property that you can call text.
It is also necessary to expand the two constructors with an extra parameter for the
new property.
2. The class Persons must be changed so it now takes into consideration that the
database table has a new column and the class Person a new property.
3. The activity_person.xml layout should be expanded with the new field (and a label),
which should be a multiline EditText.
4. PersonActivity must be updated so that the value of the new field is stored in
the database.

Test application to make sure the text is saved. Remember to test both creating new contacts
and editing existing contacts.

As the program is written right now, all texts are hard-coded, ie texts for labels, texts for
buttons, toast messages and menu items. Replace these texts with constants in string.xml,
while defining other texts for the 4 activity title lines, so you can see where in the application
you are working.

139
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT SQLite

Currently, you can not change the zip code. It’s probably a little too restrictive. Solve this
problem when the field of the zip code always must contain a legal zip code.

The application has another problem that you may not discover before installing the
application on a physical device. The problem is that the activity PersonActivity has so many
fields that they are covered by the virtual keyboard. You can solve this problem by placing
the window layout in a ScrollView.

Free eBook on
Learning & Development
By the Chief Learning Officer of McKinsey

Download Now

140
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Threads

7 THREADS
Android is a multi-threaded operating system, so you can use threads almost the same way
you know it from PC. Once an Android application is started, the runtime system will create
a primary thread, and all the application’s components will as defaulted be running in this
thread. The primary thread’s main task is to handle the user interface, including processing
events, but the thread can of course perform any other operation, whichever is the default.
Like what you know from PC, the primary thread can start a secondary thread, and there
may be many good reasons for which are the same as you know from earlier, but there are
also the same challenges that if a secondary thread directly updates the user interface, so
the program will stop with an exception. If you use threads, you need a little more, and
the purpose of this chapter is to show what is needed.

I will use an example that I have used earlier, which is an application that opens the
following window:

In the two input fields, you can enter two positive integers, and click on CALCULATE,
the program will determine all prime numbers between the two entered numbers and
insert them into a ListView under the buttons. The idea to use the prime numbers is that
for large numbers it takes a long time to determine whether a number is prime and if you

141
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Threads

have entered as large numbers as above, the result is that the program intermittently adds
a prime to the ListView component. To limit the memory consumption, the two entered
numbers must only differ by 1000, but you can of course change if you want to.

Under the input fields there are three radio buttons. If you perform the calculation and
the top radio button is pressed, the calculations are performed in the primary thread and
the meaning is that you will find that the application is not responding and if the numbers
are sufficiently large, you will receive a warning as shown below where you can interrupt
the program:

If the program is allowed to perform the calculations, then after all the prime numbers are
found, it will definitely update the ListView component with all the numbers found.

If, on the other hand, you perform the program while the middle radio button is pressed,
the calculations are performed in second thread, which updates the ListView component
whenever a prime is found. Since nothing special has been done to update the component,
the result is that the program stops with an exception. On the other hand, if you performs
the program while the lower radio button is pressed, runs everything as it should. The
program updates the ListView component and the program is alive, but this time without
causing problems, as it happens with a Handler object.

142
JAVA 16:
JAVA 16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE DEVELOPMENT
SOFTWARE DEVELOPMENT threads
Threads

The user
The user interface
interface consists
consists of
of 10
10 components
components that that are
are placed
placed using
using aa RelativeLayout,
RelativeLayout, and and
the design
the design does
does notnot contain
contain anything
anything new new soso II do
do not
not want
want to
to display
display the
the XML
XML code code here,
here,
so where
so where there
there isis something
something newnew isis in
in the
the class
class MainActivity.
MainActivity. The
The full
full code
code isis as
as follows:
follows:

package dk.data.torus.primesapp;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.*;
import android.widget.*;
import android.os.*;
import android.content.*;
import java.util.*;

public class MainActivity extends AppCompatActivity


{
private EditText txtFrom;
private EditText txtTo;
private RadioButton cmdPrim;
private RadioButton cmdSec1;
private RadioButton cmdSec2;
private ListView lstPrimes;

www.sylvania.com

We do not reinvent
the wheel we reinvent
light.
Fascinating lighting offers an infinite spectrum of
possibilities: Innovative technologies and new
markets provide both opportunities and challenges.
An environment in which your expertise is in high
demand. Enjoy the supportive working atmosphere
within our global group and benefit from international
career paths. Implement sustainable ideas in close
cooperation with other specialists and contribute to
influencing our future. Come and join us in reinventing
light every day.

Light is OSRAM

143
143
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Threads
SOFTWARE DEVELOPMENT threads

private ArrayAdapter<Long> adapter;


private List<Long> primes = new ArrayList();
private Handler messageHandler;
private Handler primeHandler;

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtFrom = (EditText) findViewById(R.id.txtFrom);
txtTo = (EditText) findViewById(R.id.txtTo);
cmdPrim = (RadioButton) findViewById(R.id.cmdPrim);
cmdSec1 = (RadioButton) findViewById(R.id.cmdSec1);
cmdSec2 = (RadioButton) findViewById(R.id.cmdSec2);
lstPrimes = (ListView) findViewById(R.id.lstPrimes);
lstPrimes.setAdapter(adapter = new ArrayAdapter<Long>(this,
android.R.layout.simple_list_item_1, primes));
messageHandler = new MessageHandler(this);
primeHandler = new PrimeHandler(this, adapter);
}

public void onClear(View view)


{
adapter.clear();
}

public void onCalculate(View view)


{
try {
long from = Long.parseLong(txtFrom.getText().toString());
long to = Long.parseLong(txtTo.getText().toString());
if (from > 0 && to > from && to – from <= 1000)
{
if (cmdPrim.isChecked()) calc1(from, to);
else if (cmdSec1.isChecked()) calc2(from, to);
else calc3(from, to);
return;
}
}
catch (Exception ex)
{
}
Toast.makeText(this, "Illegal values", Toast.LENGTH_LONG).show();
}

private void calc1(long a, long b)


{
for (long t = a; t <= b; ++t) if (isPrime(t))
{

144
144
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Threads
SOFTWARE DEVELOPMENT threads

adapter.add(t);
}
}

private void calc2(long from, long to)


{
final long a = from;
final long b = to;
Runnable runnable = new Runnable() {
public void run() {
for (long t = a; t <= b; ++t) if (isPrime(t))
{
adapter.add(t);
}
}
};
(new Thread(runnable)).start();
}

private void calc3(long from, long to)


{
final long a = from;
final long b = to;
Runnable runnable = new Runnable() {
public void run() {
for (long t = a; t <= b; ++t) if (isPrime(t))
{
Message msg = primeHandler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putLong("prime", t);
msg.setData(bundle);
primeHandler.sendMessage(msg);
}
messageHandler.sendEmptyMessage(0);
}
};
(new Thread(runnable)).start();
}

private boolean isPrime(long n)


{
if (n == 2 || n == 3 || n == 5 || n == 7) return true;
if (n < 11 || n % 2 == 0) return false;
for (long t = 3, m = (long)Math.sqrt(n) + 1; t <= m; t += 2)
if (n % t == 0) return false;
return true;
}
}

145
145
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Threads

The class ends with an method isPrime() that tests whether a number is a prime and is a
well-known method that I have used many times. The class defines no less than 10 instance
variables. The first are references to components in the user interface and the names tells
what they are use for. Then there is a List<Long> for the content of the ListView component
and an associated adapter, and finally there are two variables of the type Handler that I
returns to in a little while. In onCreate(), there is also nothing new, except for the last two
statements that create objects for the two Handler variables (explained below).

The program has two event handlers for the buttons, the first one is trivial and does nothing
but delete the content of the ListView component. The other is the event handler for the
button CALCULATE, and even if the code fills, the handler is simple enough. It must
determine the values of the two numbers entered in the user interface and test if they are
legal. If this is not the case, a simple Toast will appear with an error message. Are the values

360°
legal the event handler calls one of the methods

.
1. calc1()
2. calc2()
3. calc3() thinking

360°
thinking . 360°
thinking .
Discover the truth at www.deloitte.ca/careers D

© Deloitte & Touche LLP and affiliated entities.

Discover the truth at www.deloitte.ca/careers © Deloitte & Touche LLP and affiliated entities.

eloitte & Touche LLP and affiliated entities.

Discover the truth


146 at www.deloitte.ca/careers
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Threads
threads

depending on which radio button is pressed. Is it the top radio button the method calc1() is
called with the two numbers as parameters and the method consists of a loop that updated
the ListView component with the primes determined within the current range:

for (long t = a; t <= b; ++t) if (isPrime(t))


{
adapter.add(t);
}

Since
Since calc1()
calc1() is
is aa common
common method,
method, it
it is
is executed
executed by
by the
the primary
primary thread,
thread, which
which inin principle
principle
is fine enough, but the method can take a long time to perform (for large input parameters)
is fine enough, but the method can take a long time to perform (for large input parameters)
and
and during
during that
that time
time the
the program
program does
does not
not respond
respond and
and you
you may
may receive
receive aa warning
warning as
as
shown above.
shown above.

If
If instead
instead calc2()
calc2() is
is executed,
executed, the
the same
same happens,
happens, but
but this
this time
time in
in aa secondary
secondary thread,
thread, in
in
which the thread performs the above loop. Once a prime has been found, the method
which the thread performs the above loop. Once a prime has been found, the method add() add()
of
of the
the adapter
adapter is
is called,
called, which
which due
due to
to the
the data
data binding
binding will
will update
update the
the user
user interface,
interface, and
and
as it happens from another thread, the program will fail and stop with an exception.
as it happens from another thread, the program will fail and stop with an exception.

This
This problem
problem isis solved
solved in
in calc3()
calc3() which
which updates
updates the
the user
user interface
interface using
using aa Handler
Handler object,
object,
which is an object performed in the primary thread. At the end of the file MainActivity.
which is an object performed in the primary thread. At the end of the file MainActivity.
java
java is
is defined
defined two
two classes:
classes:

class MessageHandler extends Handler


{
private Context context;

public MessageHandler(Context context)


{
this.context = context;
}

@Override
public void handleMessage(Message msg) {
Toast.makeText(context, "Primes generated", Toast.LENGTH_LONG).show();
}
}

class PrimeHandler extends Handler


{
private Context context;
private ArrayAdapter<Long> adapter;
public PrimeHandler(Context context, ArrayAdapter<Long> adapter)
{

147
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Threads
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT threads
SOFTWARE DEVELOPMENT threads

this.context
this.context =
= context;
context;
this.adapter
this.adapter =
= adapter;
adapter;
}
}

@Override
@Override
public
public void
void handleMessage(Message
handleMessage(Message msg)
msg) {
{
Bundle bundle = msg.getData();
Bundle bundle = msg.getData();
Long
Long prime
prime == bundle.getLong("prime");
bundle.getLong("prime");
adapter.add(prime);
adapter.add(prime);
}
}
}
}

Both
Both classes
classes override
override the
the method
method handleMessage(),
handleMessage(), which
which is
is aa callback
callback method
method performed
performed
by
by the
the primary
primary thread,
thread, and
and the
the difference
difference between
between thethe two
two classes
classes is,
is, among
among other
other things,
things,
which
which parameters are transmitted. In the first class, handleMessage() is trivial as it simply
parameters are transmitted. In the first class, handleMessage() is trivial as it simply
performs
performs a Toast, but in the second class, a parameter must be transferred. It happens with
a Toast, but in the second class, a parameter must be transferred. It happens with
aa Bundle
Bundle object, and in this case it must be a Long, which is the prime to be added to the
object, and in this case it must be a Long, which is the prime to be added to the
ListView
ListView component.
component. Note,
Note, inin particular,
particular, that
that the
the parameter
parameter hashas the
the type
type Message,
Message, and
and also
also
note the syntax for referring to the transferred
note the syntax for referring to the transferred value. value.

With
With these
these two
two Handler
Handler types
types available,
available, the
the program
program can
can create
create instance
instance variables
variables of
of the
the
types in question, what happens in onCreate().
types in question, what happens in onCreate().

Then
Then there
there is
is the
the method
method calc3(),
calc3(), which
which is
is in
in principle
principle identical
identical to
to calc2()
calc2() and
and performs
performs
the
the task
task of
of determining
determining the
the prime
prime numbers
numbers inin aa secondary
secondary thread,
thread, but
but the
the method
method run()
run()
is
is changed
changed aa bit:
bit:
public
public void
void run()
run() {
{
for
for (long t = a; t
(long t = a; t <=
<= b;
b; ++t)
++t) if
if (isPrime(t))
(isPrime(t))
{
{
Message
Message msg
msg == primeHandler.obtainMessage();
primeHandler.obtainMessage();
Bundle
Bundle bundle =
bundle = new
new Bundle();
Bundle();
bundle.putLong("prime",
bundle.putLong("prime", t);
t);
msg.setData(bundle);
msg.setData(bundle);
primeHandler.sendMessage(msg);
primeHandler.sendMessage(msg);
}
}
messageHandler.sendEmptyMessage(0);
messageHandler.sendEmptyMessage(0);
}
}

In
In the
the for
for loop,
loop, the
the object
object primeHandler
primeHandler is is used
used to
to create
create aa Message
Message object.
object. In
In addition,
addition, aa
In the for loop, the object primeHandler is used to create a Message object. In addition, a
Bundle
Bundle object
object is
is initialized
initialized with
with thethe current
current prime
prime and
and this
this Bundle
Bundle object
object is
is linked
linked to
to the
the
Bundle object is initialized with the current prime and this Bundle object is linked to the
Message
Message object.
object. Hereafter
Hereafter thethe primeHandler
primeHandler object’s
object’s sendMessage()
sendMessage() method
method isis called.
called. When
When
Message object. Hereafter the primeHandler object’s sendMessage() method is called. When
the
the loop is completed, the second handler object is used to send a message, but here the
loop is completed, the second handler object is used to send a message, but here the
the loop is completed, the second handler object is used to send a message, but here the
method sendEmptyMessage() is
method sendEmptyMessage() is called. called.
method sendEmptyMessage() is called.

148
148
148
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Services

8 SERVICES
A service is a component that is performed in the background without direct interaction with
the user, and a service has no user interface. Services are used to perform special operations
and often operations that take a long time. For example, it could be downloading a file from
the Internet, testing for new data, and more. A service is performed with higher priority than
activities, and there is therefore less chance that a service will be interrupted by Android if
there is insufficient resources available. However, it is possible to provide a service with the
same priority as foreground activities, and if so, it is necessary to have a visible indication
that tells that the service is active, something that is used by video and music players.

There are two main types of services:

1. A service is be started when an application (an activity) starts it by calling the method
startService(). Once started, a service can run in the background indefinitely, even
if the application that started the service is destroyed. Usually, a started service
performs a single operation (as download or upload a file over the network) and
does not return a result to the caller. When the operation is done, the service
should stop itself.

We will turn your CV into


an opportunity of a lifetime

Do you like cars? Would you like to be a part of a successful brand? Send us your CV on
We will appreciate and reward both your enthusiasm and talent. www.employerforlife.com
Send us your CV. You will be surprised where it can take you.

149
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Services

2. A service is bounded when an application component binds to it by calling the


method bindService(). A bound service offers a client-server interface that allows
components to interact with the service, send requests, get results, and also across
processes. A bound service runs only as long as another application component is
bound to it. Multiple components can bind to the service at once, but when all
of them unbind, the service is destroyed.

By default, a service is performed in the same process as an application’s primary thread,


but if it is a service that is started by an application, that service will usually perform its
work in a secondary thread, and the service will then be terminated with the end of the
secondary thread.

Android performs a number of predefined services that any application may apply if it is
allowed. Use of these services usually occurs with a special Manager class using a method
getSystemService(), and the Context class defines more constants for these services. An
application may, in addition to these system services, define and apply new services that
behave in the same way as system services. Custom services can generally be started from
other Android components, that is, activities, broadcast receivers and other services.

The entire lifetime of a service happens between the call of a method onCreate() and the
call of the method onDestroy() where onCreate() is used to all initial setup, while the release
of resources is done in onDestroy(). The methods are called for all services, whether they’re
created by startService() or bindService(). A service begins its work with a call to either
onStartCommand() or onBind(). Each method is handed an Intent object passed to either
startService() or bindService(), respectively. If the service is started, it ends its work when
onStartCommand() returns, and if the service is bound, it ends when onUnbind() returns.

A service must be defined in AndroidManifest.xml and written as a class that inherits the
class Service or one of its subclasses. As an example, an Android component (and so far, to
say an activity) can start a service with the method startService(), and as alternative it can
use bindService() that allows for direct communication with the service.

A started service starts its life with the method startService() and if the service is not already
running, a service object is created in the service’s onCreate() method. Once running, a
service can notify the user of events using Toast notifications or Status Bar notifications,
but the service can not directly call the user.

150
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Services

The method onStartCommand() returns an int that indicates how services should be restarted
if it is terminated by Android and there are the following options:

1. Service.START_STICKY, which means that the service is restarted, but such that
the Intent object is null and used if the service maintains its own state and does
not depend on the Intent object.
2. Service.START_NOT_STICKY, which indicates that the service will not be
automatically restarted.
3. Service.START_REDELIVER_INTENT, which means the same as the first option,
but with the difference that the original Intent object is sent to onStartCommand().

One can end a service with the method stopService() and a service can end itself with stopSelf().

To create a bound service, you must implement the method onBind() that returns an IBinder
that defines the interface for communication with the service. Other applications can then
call bindService() to retrieve the interface and begin calling methods on the service. The
service is only alive as long there are applications that is bound to it, and when there are
no components bound to the service, the system destroys it, and you do not need to stop
a bound service in the way you must when the service is started with onStartCommand().
There are two ways you can define the IBinder interface:

1. Extending the Binder class. If your service is private to your own application and
runs in the same process as the application, which is often the case, you should
create your interface by extending the Binder class and returning an instance of it
from onBind(). Then the client receives the Binder object and can use it to directly
access public methods available in either the Binder implementation or the Service.
When the service is merely a background worker for the application it is the way
to create the Binder, and the only reason not to create the interface this way is
because the service has to be used by other applications or across separate processes.
2. Using a Messenger. If you your interface must work across different processes, you
can create an interface for the service with a Messenger. In this manner, the service
defines a Handler that responds to different types of Message objects. This Handler is
the basis for a Messenger that can share an IBinder with the client, allowing the client
to send commands to the service using Message objects. Also the client can define
its own Messenger so the service can send messages back. This is the simplest way
to perform interprocess communication, because the Messenger queues all requests
into a single thread so that you don’t have to design your service to be thread-safe.

Application components can bind to a service by calling bindService(), and Android then
calls the service’s onBind() method, which returns an IBinder object for interacting with

151
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Services

the service. It happens asynchronous and bindService() returns immediately and does not
return the IBinder object. To receive the object, the client must create an instance of
ServiceConnection and pass it to bindService(). ServiceConnection is an interface and defines
a method onServiceConnected() that the system calls to get the IBinder object. The interface
also defines a method onServiceDisconnected() that Android calls when the connection to the
service is lost because the service has crashed or has been killed. The method is not called
when the application unbinds. To disconnect from a service, you must call the method
unbindService(). When the application is destroyed, it will automatical unbind from the
service, but you should always unbind when you’re done so that the service can shutdown
while it is not longer being used.

A service can also be a foreground service, which is a service associated to something that
the user is aware of and thus not a candidate for the system to kill when low on memory. A
foreground service must provide a notification in the status bar, which is a notification that
cannot be dismissed unless the service is either stopped or removed from the foreground.
To start a service in the foreground you use the method startForeground(), that takes
two parameters, where the first is an int that uniquely identifies the notification and the
notification for the status bar.

152
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Services

In the simple case, there is no need for any communication between activity and service. The
service receives an Intent object from the activity component, and the service then performs
its work, but in other contexts there is a need for direct communication between an activity
and a service, and here you can use a receiver. An activity can detect a broadcast receiver
for an event and the service can send notifications for this event and typically responds that
the service will signal the activity object that it has completed its work:

A broadcast receiver is a class which extends BroadcastReceiver and which is registered as a


receiver in an application other in AndroidManifest.xml or in code. The receiver will be able to
receive intents generated with the method Context.sendBroadcast(). The class BroadcastReceiver
defines the method onReceive() that the application can use to get the received object.

It was briefly a little about the theory, and in the following I will show what exactly to be
written to use services, at least the start of simple services and the use of local services, but
the subject is actually relatively complex, and I will return to it in the next book. Among
other things, BroadcastReceiver objects are not featured in this book.

First, however, I would like to attach a few comments to the class Intent.

8.1 THE CLASS INTENT


The class Intent has not alone to do with services, and I have already used the class many
times without mentioning what it is for a class. As the class plays a crucial role in services,
I will briefly mention it here.

The class primarily applies to activities, services and broadcast receivers. These components
are created using messages called intents, which are a form of late binding of components,
so it always happens in the same way. An Intent object is a data structure that contains an
abstract description of an operation to be performed or a description of something that
has happened and has to be advertised. There are several mechanisms to send intents to
different types of components:

1. An Intent object can be passed to Context.startActivity() or Activity.startActivityForResult()


to launch an activity or get an existing activity to do something new. It can also be
passed to Activity.setResult() to return information from the activity that has been
performed with startActivityForResult().

153
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Services

2. An Intent object can be passed to Context.startService() to initiate a service or deliver


new instructions to a running service. Similarly, an intent can be passed to Context.
bindService() to establish a connection between the calling activity and a service. It
can also be used to initiate the service if it’s not already running.
3. Intent objects can be passed to broadcast methods (see the next book) such as Context.
sendBroadcast(), Context.sendOrderedBroadcast(), or Context.sendStickyBroadcast() and
are delivered to all interested broadcast receivers.

Intents are really useful with services to exchange information and notification between the
calling object and the service. You are encouraged to examine the documentation for the
Intent class.

8.2 SERVICEAPP1
A service is written as a class inheriting the class Service or IntentService, where the last is
derived from the first. The goal of an IntentService is to simplify the start of a service as
much as possible. The service carries out requests asynchronously in their own thread, and
it can take as long as necessary and does not block the application. The individual request
is added to a queue and executed one at a time. An IntentService is a background service
that is started by an activity, and then there is no direct communication between the service
and the activity. A typical application is the start of an action that takes a long time, such
as downloading a file.

The example ServiceApp1 opens the following window:

154
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Services

AXA Global
Graduate Program
Find out more and apply

155
JAVA
JAVA16:
16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
SOFTWARE
SOFTWAREDEVELOPMENT
DEVELOPMENT Services
servICes

IfIfyou
youclick
clickon
onthe
thetop
topbutton,
button,the thewindow
windowgets
getsaarandom
randomcolor
colorand
andclicking
clickingononthe
thebottom
bottom
button
buttonstarts
startsaaservice
servicethat
thatisisan
anIntentService.
IntentService.The
Theservice
serviceisiswritten
writtenasasthe
thefollowing
followingclass:
class:

import android.app.IntentService;

import android.content.Intent;
import android.net.Uri;
import android.media.RingtoneManager;
import android.media.Ringtone;

public class TheService extends IntentService


{
public TheService() {
super("TheService");
}

@Override
protected void onHandleIntent(Intent intent)
{
long n = intent.getLongExtra("todo", 0);
for (long i = 0; i < n; ++i) Math.sin(Math.sqrt(i));
Uri notification =
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r =
RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
}
}

The
Theclass
classshould
shouldonly
onlyhave
haveaadefault
defaultconstructor
constructorwhowhoperforms
performsthethebase
baseclass’
class’constructor
constructorwith
with
the service name as parameter and furthermore it must override the method onHandleIntent(),
the service name as parameter and furthermore it must override the method onHandleIntent(),
which
whichisisthethemethod
methodthat
thatperforms
performsthe thedesired
desiredaction.
action.InInthis
thiscase,
case,the
themethod
methodperforms
performs
aalong
long(meaningless)
(meaningless)action,
action,after
afterwhich
whichititactivates
activatesaaringtone.
ringtone.With
Withregard
regardtotothe
theaction,
action,
the
the goal is to show how you with an Intent can transfer values to a service and thatthe
goal is to show how you with an Intent can transfer values to a service and that the
service is doing something for a while, before you because of the sound observes
service is doing something for a while, before you because of the sound observes that the that the
service
servicehas
hasperformed
performeditsitswork.
work.

When
Whenan
anapplication
applicationuses
usesaaservice,
service,ititmust
mustbe
bedefined
definedininthe
theprogram’s
program’smanifest
manifest

<application

</activity>
<service android:name=".TheService" />
</application>

AAdetail
detailthat
thatisisimportant
importanttotoremember.
remember.

156
156
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Services
servICes

With
With regard
regard to
to the
the program
program (MainActivity),
(MainActivity), the
the goal
goal of
of the
the top
top button
button isis to
to show
show that
that the
the
application
application isis not
not blocked
blocked while
while the
the service
service performs
performs its
its work
work –– and
and also
also aa little
little to
to show
show
how
how toto change
change the
the background
background color
color of
of the
the window.
window. When
When you you try
try out
out the
the program,
program, note
note
that
that you
you can
can start
start multiple
multiple services
services and
and how
how they
they are
are queued.
queued. The
The code
code for
for MainActivity
MainActivity
is
is as
as follows:
follows:

package serviceapp1.dk.data.torus.serviceapp1;

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.*;
import android.content.*;
import java.util.Random;

public class MainActivity extends AppCompatActivity {


private static Random rand = new Random();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

public void onClick(View view)


{
getWindow().getDecorView().setBackgroundColor(getColor());
}

public void onStart(View view)


{
Intent intent = new Intent(this, TheService.class);
intent.putExtra("todo", 100000000L);
startService(intent);
}

private int getColor()


{
return Color.rgb(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
}
}

Here
Here the
the most
most important
important is
is the
the event
event handler
handler onStart(),
onStart(), that
that starts
starts aa service.
service. First,
First, an
an Intent
Intent
object is created for the service and the service is started with the method startService().
object is created for the service and the service is started with the method startService().

157
157
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Services

8.3 SERVICEAPP2
Often, an IntentService does not provide enough options, for example, if you want to stop
a running service, and you will then have to write a service that directly inherits the class
Service. The program ServiceApp2 shows how. The program’s window is almost identical to
the above, just there is a third button:

�e Graduate Programme
I joined MITAS because for Engineers and Geoscientists
I wanted real responsibili� www.discovermitas.com
Maersk.com/Mitas �
I joined MITAS because for Eng
I wanted real responsibili� M

Month 16
I was a construction M
supervisor ina con
I was
the North Sea supe
advising and the N
Real work he
helping foremen adv
International
al opportunities
Internationa
�ree wo
work
or placements ssolve problems
Real work he
helping
International
Internationaal opportunities
�ree wo
work
or placements ssolve p

158
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Services
servICes

which
which isis used
used to
to stop
stop aa running
running service.
service. The
The service
service isis this
this time
time written
written as:
as:

package serviceapp2.dk.data.torus.serviceapp2;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;

public class TheService extends Service {

@Override
public void onCreate() {
Toast.makeText(this, "Service created", Toast.LENGTH_LONG).show();
}

@Override
public IBinder onBind(Intent arg0) {
return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
long timeout = System.currentTimeMillis() + 30000;

159
159
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16:
JAVA 16: MOBIL
SOFTWARE MOBIL PHONES AND
PHONES
DEVELOPMENTAND ANDROID:
ANDROID: Services
SOFTWARE DEVELOPMENT
SOFTWARE DEVELOPMENT servICes
servICes

while (System.currentTimeMillis()
while (System.currentTimeMillis() << timeout)
timeout) {{
synchronized (this)
synchronized (this) {{
Toast.makeText(this, "Service
Toast.makeText(this, "Service "" ++ startId
startId ++ "" is
is working",
working",
Toast.LENGTH_LONG).show();
Toast.LENGTH_LONG).show();
try {{
try
wait(5000);
wait(5000);
}}
catch (Exception
catch (Exception e)
e) {{
}}
}}
}}
return Service.START_STICKY;
return Service.START_STICKY;
}}

@Override
@Override
public void
public void onDestroy()
onDestroy() {{
Toast.makeText(this, "Service
Toast.makeText(this, "Service destroyed",
destroyed", Toast.LENGTH_LONG).show();
Toast.LENGTH_LONG).show();
}}
}}

A
A background
A background
background service service (which
service (which
(which doesdoes not
does not have
have aaa user
not have user interface)
user interface) can
interface) can communicate
can communicate
communicate with with the
with the
the
environment
environment in
environment in two
in two ways,
two ways, and
ways, and the
and the one
the one with
one with a simple
with aa simple Toast,
simple Toast, which
Toast, which is just
which isis just a simple
just aa simple message
simple message
message
that appears
that appears
that appears brieflybriefly on
briefly on the
on the screen.
the screen. The
screen. The class
The class inherits
class inherits
inherits this this time
this time the
time the class
the class Service
class Service
Service andand
and aaa service
service
service
has an
has an
has onCreate()
an onCreate()
onCreate() method method where
method where
where youyou can
you can initialize
can initialize
initialize the the service.
the service. In
service. In this
In this case,
this case, nothing
case, nothing happens
nothing happens
happens
other than
other than
other than the the service
the service shows
service shows a Toast
shows aa Toast that
Toast that says
that says it was
says itit was created.
was created. There
created. There is also
There isis also a method
also aa method called
method called
called
onBind()
onBind() and
onBind() and is inserted
and isis inserted by
inserted by Android
by Android Studio,
Android Studio,
Studio, but but it is only
but itit isis only used
only used for
used for a bounded
for aa bounded service.
bounded service. Then
service. Then
Then
there isis the
there is
there the last
the last method
last method onDestroy()
method onDestroy() that
onDestroy() that isis performed
that is performed
performed when when the
when the service
the service
service is isis stopped,
stopped,
stopped, andand in
and inin
this case
this case
this case it itit also
also shows
also shows just
just aaa simple
shows just simple Toast.
simple Toast.
Toast.

Finally, there
Finally, there
Finally, isis onStartCommand(),
there is onStartCommand(), which
onStartCommand(), which
which isisis the
the method
the method that
method that isis performed
that is performed
performed when when the
when the service
the service
service
isis started,
is started, thus
started, thus
thus whenwhen the
when the starting
the starting activity
starting activity performs
activity performs startService().
performs startService().
startService(). In In this
In this case,
case, aaa loop
this case, loop isis
loop is
running
running for
running for approximate
for approximate
approximate 30 30 seconds.
30 seconds. For
seconds. For each
For each iteration,
iteration, aaa Toast
each iteration, Toast
Toast isisis performed,
performed, after
performed, after which
after which
which
service is waiting
service isis waiting
service 5 seconds.
waiting 55 seconds.
seconds.

The class
The class
The MainActivity
class MainActivity
MainActivity is isis almost
almost identical
almost identical to
identical to the
to the previous
the previous example,
previous example, just
example, just the
just the event
the event handler
event handler for
handler for
for
the Start
the Start
the button
Start button isis aaa bit
button is bit simpler
bit simpler (no
simpler (no parameter
(no parameter
parameter mustmust be
must be transferred),
be transferred), and
transferred), and an
and an event
an event handler
event handler
handler
is added
isis added
added toto the
to the Stop
the Stop button:
Stop button:
button:

public void
public void onStart(View
onStart(View view)
view)
{{
Intent intent
Intent intent == new
new Intent(this,
Intent(this, TheService.class);
TheService.class);
startService(intent);
startService(intent);
}}

160
160
160
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

public void onStop(View view)


{
Intent intent = new Intent(this, TheService.class);
stopService(intent);
}

If you try the program and click the start button, you will find that the other buttons do
If you try the program and click the start button, you will find that the other buttons do
not seem to work and you will not see Toasts either – at least not before the service has
not seem to work and you will not see Toasts either – at least not before the service has
finished its work, after which the background changes color (if you have clicked the button).
finished its work, after which the background changes color (if you have clicked the button).
If you have not clicked the Stop button and do it now, you will see a Toast, telling that the
If you have not clicked the Stop button and do it now, you will see a Toast, telling that the
service is stopped. The reason is that the service and the program itself are executed in the
service is stopped. The reason is that the service and the program itself are executed in the
same thread, and as the service temporarily suspends the thread, the program will appear
same thread, and as the service temporarily suspends the thread, the program will appear
to be unresponsive – and you may also get a message from Android, that it is the case.
to be unresponsive – and you may also get a message from Android, that it is the case.

8.4 SERVICEAPP3
8.4 SERVICEAPP3
This example is exactly the same as the previous example, just showing the solution to the
This example is exactly the same as the previous example, just showing the solution to the
above problem. That is, the layout and MainActivity (and the manifest) are completely
above problem. That is, the layout and MainActivity (and the manifest) are completely
unchanged. The solution is, of course, that the service must do its work in a second thread,
unchanged. The solution is, of course, that the service must do its work in a second thread,

93%
OF MIM STUDENTS ARE
WORKING IN THEIR SECTOR 3 MONTHS
FOLLOWING GRADUATION

MASTER IN MANAGEMENT
• STUDY IN THE CENTER OF MADRID AND TAKE ADVANTAGE OF THE UNIQUE OPPORTUNITIES
Length: 1O MONTHS
THAT THE CAPITAL OF SPAIN OFFERS
Av. Experience: 1 YEAR
• PROPEL YOUR EDUCATION BY EARNING A DOUBLE DEGREE THAT BEST SUITS YOUR
Language: ENGLISH / SPANISH
PROFESSIONAL GOALS
Format: FULL-TIME
• STUDY A SEMESTER ABROAD AND BECOME A GLOBAL CITIZEN WITH THE BEYOND BORDERS
Intakes: SEPT / FEB
EXPERIENCE

5 Specializations #10 WORLDWIDE 55 Nationalities


MASTER IN MANAGEMENT
Personalize your program FINANCIAL TIMES
in class

www.ie.edu/master-management mim.admissions@ie.edu Follow us on IE MIM Experience

161
161
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Services
servICes

which
which in in principle
principle isis quite
quite simple,
simple, but
but there
there are
are still
still aa few
few things
things to
to be
be aware
aware of.
of. The
The code
code
isis as
as follows:
follows:

package serviceapp3.dk.data.torus.serviceapp3;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
import android.os.*;

public class TheService extends Service {


private boolean running = false;

@Override
public void onCreate() {
Toast.makeText(this, "Service created", Toast.LENGTH_LONG).show();
}

@Override
public IBinder onBind(Intent arg0) {
return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (running) Toast.makeText(this, "Service already running",
Toast.LENGTH_LONG).show();
else {
final int currentId = startId;
Runnable r = new Runnable() {
public void run() {
long timeout = System.currentTimeMillis() + 30000;
running = true;
while (running && System.currentTimeMillis() < timeout) {
synchronized (this) {
sendMessage(currentId);
try {
wait(5000);
} catch (Exception e) {
}
}
}
stopSelf();
}
};

162
162
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

Thread t = new Thread(r);


t.start();
}
return Service.START_STICKY;
}

@Override
public void onDestroy()
{
running = false;
Toast.makeText(this, "Service destroyed", Toast.LENGTH_LONG).show();
}

private void sendMessage(int id)


{
final int currentId = id;
Handler handler = new Handler(TheService.this.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),
"Service " + currentId + " is working", Toast.LENGTH_LONG).show();
}
});
}
}

Note that
Note that atat the
the start
start of
of the
the class,
class, an
an instance
instance variable
variable isis defined.
defined. ItIt must
must be be used
used to
to ensure
ensure
that the
that the service
service can
can only
only start
start one
one thread.
thread. ItIt is
is not
not necessary,
necessary, butbut itit is
is included
included to to show
show
how to
how to stop
stop aa thread
thread started
started byby aa service.
service. Note,
Note, in in particular,
particular, that
that the
the variable
variable isis set
set to
to false
false
in the
in the method
method onDestroy(),
onDestroy(), and and itit is
is executed
executed either
either because
because the
the thread
thread stops
stops oror because
because
onDestroy() is
onDestroy() is called
called from
from anan activity.
activity. The
The method
method onStartCommand()
onStartCommand() starts starts testing
testing this
this variable,
variable,
and if
and if it
it is
is true,
true, nothing
nothing elseelse happens
happens thanthan the
the method
method performs
performs aa Toast.
Toast. Otherwise,
Otherwise, the the
method creates
method creates aa thread
thread that
that performs
performs the the same
same as as in
in the
the previous
previous example,
example, in in which
which in in an
an
iteration it
iteration it performs
performs aa Toast
Toast followed
followed by by aa wait().
wait(). However,
However, there
there isis aa small
small problem.
problem. The The
message is
message is now
now sent
sent from
from aa secondary
secondary thread,
thread, and
and although
although it it is
is only
only aa Toast,
Toast, the
the thread
thread
must still
must still update
update the the user
user interface.
interface. ItIt requires
requires aa Handler
Handler and
and isis performed
performed in in the
the method
method
sendMessage(). A
sendMessage(). A Handler
Handler is is linked
linked toto aa message
message loop,
loop, and
and since
since aa thread
thread doesdoes not
not have
have aa
message loop,
message loop, thethe method
method getMainLooper()
getMainLooper() is is used.
used. The
The Handler
Handler object
object will
will then
then use
use thet
thet
method post()
method post() toto insert
insert aa Runnable
Runnable object
object that
that performs
performs the the desired
desired Toast.
Toast.

163
163
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Services

8.5 SERVICEAPP4
In this section I will show an example of local service and thus a service that the application
can bind to and communicate with. That it is a local service means that it is a service
performed in the same process as the application and that it is automatically terminated
when the application close. The program opens the following window with a TextView and
3 Button components:

164
JAVA
JAVA16:
16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
SOFTWARE
SOFTWAREDEVELOPMENT
DEVELOPMENT Services
servICes

After
After the
the program
program hashas started,
started, the
the text
text shows
shows Disconnected,
Disconnected, and and clicking
clicking onon the
the two
two top top
buttons
buttons nothing
nothing happens
happens because
because thethe program
program isis not not yet
yet connected
connected to to the
the service.
service. IfIf you
you
click
click on
on the
the bottom
bottom button,
button, the
the text
text changes
changes to to Connected,
Connected, as as the
the program
program isis now
now bounded
bounded
to
to the
the service,
service, and
and when
when youyou click
click onon the
the two
two top top buttons,
buttons, the the text
text displays
displays the
the current
current
date
date and
and time,
time, respectively.
respectively. These
These values
values are
are determined
determined by by the
the program
program (the(the buttons
buttons event
event
handlers)
handlers) by by calling
calling aa service
service method,
method, and and itit isis the
the service
service that
that reads
reads the
the clock.
clock.

The
The user
user interface
interface isis trivial
trivial and
and should
should not
not be
be displayed
displayed here,
here, and
and the
the manifest
manifest has
has been
been
changed
changed in in the
the same
same wayway asas in
in the
the previous
previous examples
examples inin this
this chapter.
chapter. The
The code
code for
for the
the
service
service isis as
as follows:
follows:

package dk.data.torus.serviceapp4;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import java.util.Calendar;

public class TheService extends Service {


private final IBinder binder = new TheBinder();

165
165
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes
SOFTWARE DEVELOPMENT servICes

@Override
@Override
public IBinder
IBinder onBind(Intent
onBind(Intent intent)
intent) {{
public
return binder;
return binder;
}}

public String
String getCurrentDate()
getCurrentDate() {{
public
Calendar cal == Calendar.getInstance();
Calendar cal Calendar.getInstance();
return String.format("%04d-%02d-%02d",
String.format("%04d-%02d-%02d", cal.get(Calendar.YEAR),
cal.get(Calendar.YEAR),
return
cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH));
cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH));
}
}

public String
String getCurrentTime()
getCurrentTime() {{
public
Calendar cal
cal == Calendar.getInstance();
Calendar.getInstance();
Calendar
return String.format("%02d:%02d:%02d:%03d", cal.get(Calendar.HOUR_OF_DAY),
return String.format("%02d:%02d:%02d:%03d", cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND),
cal.get(Calendar.SECOND),
cal.get(Calendar.MINUTE),
cal.get(Calendar.MILLISECOND));
cal.get(Calendar.MILLISECOND));
}}

public class TheBinder extends Binder {


public class TheBinder extends Binder {
TheService getService() {
TheService getService() {
return TheService.this;
return TheService.this;
}
}
}
}
}
}

First note
First note
First that
note that the
that the class
the class inherits
class inherits the
inherits the class
the class Service,
class Service, but
Service, but this
but this time
time III have
this time have not
have not overridden
not overridden
overridden the the
the
methods onStartCommand()
methods onStartCommand()
methods onStartCommand() and and onDestroy().
and onDestroy(). Instead,
onDestroy(). Instead, the
Instead, the method
the method onBind()
method onBind()
onBind() is isis implemented,
implemented,
implemented,
so itit returns
so it
so returns
returns aaa Binder
Binder object.
Binder object. This
object. This object
This object isis created
object is created at
created at the
at the beginning
the beginning
beginning of of the
of the class
the class as
class as an
as an object
an object
object
of an
of an
of inner
an inner class.
inner class. ItIt is
class. It isis aaa class
class inheriting
class inheriting
inheriting thethe class
the class Binder
class Binder (which
Binder (which implements
(which implements
implements an an interface
an interface
interface
IBinder),
IBinder), and
IBinder), and itit implements
and it implements
implements aaa single single method
single method getService(),
method getService(), which
getService(), which returns
returns aaa reference
which returns reference
reference to to the
to the
the
current service.
current service.
current service. In In addition,
In addition,
addition, the the class
the class TheService
class TheService implements
TheService implements
implements the the two
the two service
two service methods,
service methods,
methods, bothboth
both
of which
of which
of which are are simple.
are simple.
simple.

Then there
Then there
Then isis the
there is the class
the class MainActivity,
class MainActivity, which
MainActivity, which isis responsible
which is responsible for
responsible for starting
for starting the
starting the service
the service in
service in question
in question
question
by binding
by binding
by binding toto it:
to it:
it:

package dk.data.torus.serviceapp4;
dk.data.torus.serviceapp4;
package

import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Bundle;
import android.view.*;
import android.view.*;
import android.widget.*;
import android.widget.*;
import android.os.*;
import android.os.*;
import android.content.*;
import android.content.*;

166
166
166
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

public class MainActivity extends AppCompatActivity


implements ServiceConnection {
private TheService theService;
private boolean isBound = false;
private TextView txtResult;

@Override
public void onServiceConnected(ComponentName className, IBinder service) {
TheService.TheBinder binder = (TheService.TheBinder) service;
theService = binder.getService();
isBound = true;
txtResult.setText("Connected");
}

@Override
public void onServiceDisconnected(ComponentName className) {
isBound = false;
theService = null;
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

In the past 5 years we have drilled around

95,000 km
—that’s more than twice around the world.

Who are we?


We are the world’s leading provider of reservoir characterization,
drilling, production, and processing technologies to the oil and
gas industry.

Who are we looking for?


We offer countless opportunities in the following domains:
n Operations
n Research, Engineering, and Manufacturing
n Geoscience and Petrotechnical
n Commercial and Business

We’re looking for high-energy, self-motivated graduates


with vision and integrity to join our team. What will you be?

careers.slb.com

167
167
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

setContentView(R.layout.activity_main);
txtResult = findViewById(R.id.txtResult);
}

public void onDate(View view)


{
if (isBound) txtResult.setText(theService.getCurrentDate());
}

public void onTime(View view)


{
if (isBound) txtResult.setText(theService.getCurrentTime());
}

public void onConnect(View view)


{
if (!isBound) {
Intent intent = new Intent(this, TheService.class);
bindService(intent, this, Context.BIND_AUTO_CREATE);
}
}
}

Here you should first notice that the class implements the interface ServiceConnection. This
Here you should first notice that the class implements the interface ServiceConnection. This
interface defines two methods, the first being called onServiceConnected() and is executed after
interface defines two methods, the first being called onServiceConnected() and is executed after
the program has connected to the service. The other is called onServiceDisconnected() and
the program has connected to the service. The other is called onServiceDisconnected() and
executed if the program has been disconnected from the service. In this case, the program
executed if the program has been disconnected from the service. In this case, the program
binds to the service in the event handler onConnect(), and if the program is not already
binds to the service in the event handler onConnect(), and if the program is not already
bound, an Intent object is created for the current class (program) and service class. Then,
bound, an Intent object is created for the current class (program) and service class. Then,
the program binds using the method bindService(), and note the last parameter telling that
the program binds using the method bindService(), and note the last parameter telling that
the service should be created if it is not already. After bindService() is performed, Android
the service should be created if it is not already. After bindService() is performed, Android
calls the method onServiceConnected(), and its last parameter has the type IBinder and is a
calls the method onServiceConnected(), and its last parameter has the type IBinder and is a
reference to the service and is the return value of the service’s onBind() method. This value
reference to the service and is the return value of the service’s onBind() method. This value
is used to reference the service’s getService() method, so the program has a reference to
is used to reference the service’s getService() method, so the program has a reference to
service’s methods, which can then be used in the two event handlers for the top buttons.
service’s methods, which can then be used in the two event handlers for the top buttons.

You should note that a local service such as the above can be perceived as part of the sole
You should note that a local service such as the above can be perceived as part of the sole
program and the current service is not typical as both service methods are trivial. Typically,
program and the current service is not typical as both service methods are trivial. Typically,
a program needs to have performed a work that takes time, and the program then starts a
a program needs to have performed a work that takes time, and the program then starts a
service that performs the work in a secondary thread.
service that performs the work in a secondary thread.

168
168
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Services
servICes

8.6 SERVICEAPP5
8.6 SERVICEAPP5
The next
The next example
example shows
shows aa remote
remote service,
service, and
and it’s
it’s just
just aa simple
simple example,
example, but but more more in in the
the
next book.
next book. The
The application
application opens
opens aa window
window withwith two
two buttons.
buttons. Clicking
Clicking onon the
the top top button,
button,
the background
the background color
color of
of the
the window
window isis changed
changed andand clicking
clicking onon the
the bottom
bottom buttonbutton sendssends
aa message
message (the
(the current
current date
date and
and time)
time) to
to aa remote
remote service,
service, which
which after
after 55 seconds
seconds shows shows aa
Toast with
Toast with the
the message.
message. The
The mening
mening with
with the
the 5-second
5-second delay
delay and
and the
the color
color change
change button
button
are that
are that you
you should
should find
find that
that the
the service
service does
does not
not block
block the
the application
application as as itit isis performed
performed
in another
in another process,
process, than
than the
the application.
application. The
The service
service isis quite
quite simple:
simple:

package dk.data.torus.serviceapp5;

import android.app.Service;
import android.content.Intent;
import android.os.*;
import android.widget.Toast;

public class TheService extends Service {


private final Messenger theMessenger = new Messenger(new TheHandler());

class TheHandler extends Handler {


@Override
public void handleMessage(Message msg) {
Bundle data = msg.getData();
synchronized (this) {
try {
wait(5000);
}
catch (Exception e) {
}
Toast.makeText(getApplicationContext(), data.getString("message"),
Toast.LENGTH_LONG).show();
}
}
}

@Override
public IBinder onBind(Intent intent) {
return theMessenger.getBinder();
}
}

The
The class
class inherits
inherits Service
Service as
as the
the other
other examples.
examples. It It defines
defines an an inner
inner class
class that
that inherits
inherits
Handler,
Handler, and it overrides the method handleMessage(). The method’s parameter has the type
and it overrides the method handleMessage(). The method’s parameter has the type
Message
Message and
and represents
represents the
the message
message that
that aa client
client sends.
sends. It
It isis wrapped
wrapped in
in aa Bundle
Bundle object.
object.

169
169
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Services
servICes

The
The method
method starts
starts blocking
blocking the
the current
current thread
thread for
for 55 seconds,
seconds, after
after which
which itit displays
displays aa Toast
Toast
message
message with
with the
the message
message sent.
sent.

TheService
TheService class
class has
has aa single
single instance
instance variable,
variable, whichwhich isis aa Messenger
Messenger object
object that
that isis created
created
with
with an
an object
object of
of the
the above
above inner
inner class
class (it
(it isis aa Handler)
Handler) asas aa parameter.
parameter. AA Messenger
Messenger object
object
has
has aa Binder,
Binder, and
and the
the method
method onBind()
onBind() returns
returns thisthis Binder.
Binder.

In
In order
order for
for the
the service
service to
to be
be created
created in
in aa process
process other
other than
than the
the program,
program, enter
enter itit in
in the
the
manifest:
manifest:

<service android:name=".TheService"
android:process=":app5_process" >
</service>

Finally,
Finally, there
there isis the
the class
class MainActivity:
MainActivity:

package dk.data.torus.serviceapp5;

import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.os.*;

Excellent Economics and Business programmes at:

“The perfect start


of a successful,
international career.”

CLICK HERE
to discover why both socially
and academically the University
of Groningen is one of the best
places for a student to be
www.rug.nl/feb/education

170
170
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

import android.content.*;
import android.graphics.Color;
import java.util.Calendar;
import java.util.Random;

public class MainActivity extends AppCompatActivity {


private static final Random rand = new Random();
private Messenger theService = null;
private boolean isBound;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService(new Intent(this, TheService.class), theConnection,
Context.BIND_AUTO_CREATE);
}

private ServiceConnection theConnection = new ServiceConnection() {


public void onServiceConnected(ComponentName className, IBinder service) {
theService = new Messenger(service);
isBound = true;
}
public void onServiceDisconnected(ComponentName className) {
theService = null;
isBound = false;
}
};

public void sendMessage(View view)


{
if (!isBound) return;
Message msg = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("message", getMessage());
msg.setData(bundle);
try {
theService.send(msg);
}
catch (RemoteException e) {
e.printStackTrace();
}
}

public void onClick(View view)


{
getWindow().getDecorView().setBackgroundColor(getColor());
}

171
171
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA
JAVA 16:
16: MOBIL
SOFTWARE MOBIL PHONES
PHONES AND
DEVELOPMENTAND ANDROID:
ANDROID: Services
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT servICes
servICes

private
private int
int getColor()
getColor()
{{
return
return Color.rgb(rand.nextInt(256),
Color.rgb(rand.nextInt(256), rand.nextInt(256),
rand.nextInt(256), rand.nextInt(256));
rand.nextInt(256));
}}

private
private String
String getMessage()
getMessage() {{
//
// returns
returns the
the mesage
mesage
}}
}}

When
When you you see
see the
the code,
code, itit isis simple
simple and
and as
as in
in the
the previous
previous example,
example, thethe method
method should
should use
use aa
ServiceConnection
ServiceConnectionobject.
object.Instead
Insteadof ofinheriting
inheritingthe theinterface
interfaceServiceConnection,
ServiceConnection,thetheclass
classcreates
creates
an
an anonymous
anonymous object.
object. There
There isis no no particular
particular reason
reason for
for that
that in
in addition
addition to
to showing
showing that
that itit
isis possible.
possible. The
The binding
binding to to thethe service
service isis done
done in in onCreate()
onCreate() and
and occurs
occurs in
in the
the same
same way
way as
as
in the previous example. Otherwise, you should primarily note the
in the previous example. Otherwise, you should primarily note the method sendMessage() method sendMessage()
that
that isis event
event handler
handler the
the button
button SendSend and
and thethe method
method that
that sends
sends aa message
message toto the
the service.
service.

8.7
8.7 RING
8.7 RING THE
THE PHONE
PHONE
The
The following
following example
example opens
opens aa simple
simple window
window asas shown
shown below.
below. IfIf you
you click
click on on the
the toptop
button,
button, the
the phone
phone rings
rings and
and continue
continue until
until you
you click
click thethe bottom
bottom button.
button. Note
Note that
that ifif you
you
click
click on
on the
the top
top button
button and
and then
then close
close the
the program,
program, the the phone
phone will
will continue
continue to to ring.
ring. This
This
isis because
because the
the program
program starts
starts aa service,
service, and
and since
since itit isis not
not aa local
local service,
service, itit will
will still
still be
be
active after the application is closed.
active after the application is closed.

After
After the
the phone
phone has
has ringed
ringed for
for 10
10 seconds,
seconds, the
the phone
phone will
will open
open thethe window
window below
below (allowing
(allowing
you
you to
to stop
stop ringing),
ringing), regardless
regardless of
of whether
whether the
the application
application isis closed
closed or
or not.
not.

II do
do not
not want
want to
to show
show the
the layout
layout for
for the
the user
user interface,
interface, and
and MainActivity
MainActivity isis also
also simple:
simple:

public
public class
class MainActivity
MainActivity extends
extends AppCompatActivity
AppCompatActivity {{
@Override
@Override
protected
protected void
void onCreate(Bundle
onCreate(Bundle savedInstanceState)
savedInstanceState) {{
super.onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setContentView(R.layout.activity_main);
((Button) findViewById(R.id.cmdStart)).setOnClickListener(
((Button) findViewById(R.id.cmdStart)).setOnClickListener(
new
new View.OnClickListener()
View.OnClickListener() {{
public
public void
void onClick(View
onClick(View view)
view) {{
startService(new
startService(new Intent(MainActivity.this, SimpleService.class));
Intent(MainActivity.this, SimpleService.class));
}}
});
});

172
172
172
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

((Button) findViewById(R.id.cmdStop)).setOnClickListener(
new View.OnClickListener() {
public void onClick(View view) {
stopService(new Intent(MainActivity.this, SimpleService.class));
}
});
}
}

American online
LIGS University
is currently enrolling in the
Interactive Online BBA, MBA, MSc,
DBA and PhD programs:

▶▶ enroll by September 30th, 2014 and


▶▶ save up to 16% on the tuition!
▶▶ pay in 10 installments / 2 years
▶▶ Interactive Online education
▶▶ visit www.ligsuniversity.com to
find out more!

Note: LIGS University is not accredited by any


nationally recognized accrediting agency listed
by the US Secretary of Education.
More info here.

173
173
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Services
servICes

There is only an onCreate() and there is not much about services. An event handler to
a button is an object of a class that implements the interface View.OnClickListener. This
interface defines a single method called onClick() and has a View object as parameter. The
method associates event handlers with the two buttons by creating objects of anonymous
classes. The event handler for the button cmdStart has a single statement, which calls the
method startService(), where the parameter is an Intent object for the current class and also
the class RingService, which is the service class. With regard to the method startService(),
it is a method in the Context class as an Activity inheritance, and the method starts a
RingService service – if it is not already running. The event handler for the second button
is implemented accordingly, but instead calls the method stopService().

The services itselves are written as follows:

public class RingService extends Service {


private MediaPlayer player = null;

@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}

174
174
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (player == null) {
Runnable r = new Runnable() {
public void run() {
synchronized (this) {
try {
wait(10000);
} catch (Exception e) {
}
}
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName cn = new ComponentName(RingService.this,
dk.data.torus.ringthephone.MainActivity.class);
intent.setComponent(cn);
startActivity(intent);
}
};
player = MediaPlayer.create(RingService.this,
Settings.System.DEFAULT_RINGTONE_URI);
player.setLooping(true);
player.start();
Thread t = new Thread(r);
t.start();
}
return START_STICKY;
}

@Override
public void onDestroy() {
super.onDestroy();
if (player != null) player.stop();
}
}

The class has a variable of the type MediaPlayer that is used to ring the phone, but otherwise,
The class has a variable of the type MediaPlayer that is used to ring the phone, but otherwise,
the class overrides two methods from the class Service. The first is called from the event
the class overrides two methods from the class Service. The first is called from the event
handler for the first button when it calls startService() and it creates a MediaPlayer object
handler for the first button when it calls startService() and it creates a MediaPlayer object
(if it is not already created) and says it should continue to ring. Then, the method starts
(if it is not already created) and says it should continue to ring. Then, the method starts
a thread that waits for 10 seconds, and then opens the window MainActivity, even if the
a thread that waits for 10 seconds, and then opens the window MainActivity, even if the
application is closed. The syntax is not simple and by no means obvious and there is not
application is closed. The syntax is not simple and by no means obvious and there is not
much more than to take it into account. The second method is called equivalent from the
much more than to take it into account. The second method is called equivalent from the
event handler to the bottom button when it performs the method stopService().
event handler to the bottom button when it performs the method stopService().

175
175
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Services

8.8 A LOCAL SERVICE – SERVICEAPP


I will then show an application that uses a local service. The application opens the following
window:

176
JAVA
JAVA16:
16:MOBIL
MOBILPHONES
PHONESAND
ANDANDROID:
ANDROID:
SOFTWARE
SOFTWAREDEVELOPMENT
DEVELOPMENT Services
servICes

The
The program
program usesuses aa service
service that
that always
always finds
finds the
the next
next prime
prime number.
number. In In the
the beginning,
beginning, it’sit’s
fast,
fast, but
but ifif the
the program
program has has runrun for
for aa long
long time,
time, itit starts
starts to
to take
take time
time toto determine
determine the the
next
next prime.
prime. The The window
window has has 44 buttons
buttons and and aa ListView.
ListView. IfIf you
you click
click on
on the
the button
button PRIME,
PRIME,
the
the prime
prime forfor which
which thethe service
service isis reached
reached isis added
added to to the
the ListView,
ListView, partly
partly as
as the
the number’s
number’s
index
index in
in the
the sequence
sequence of of primes
primes and and partly
partly as
as the
the actual
actual prime
prime number.
number. Clicking
Clicking thethe button
button
CLEAR
CLEAR willwill delete
delete the
the content
content of of the
the ListView.
ListView. IfIf you
you click
click on
on the
the button
button WAIT,
WAIT, the the service
service
stops
stops its
its work,
work, butbut itit can
can be
be restarted
restarted (meaning
(meaning itit continues)
continues) by by clicking
clicking GO.
GO. Above,
Above, after
after
the
the program
program has has been
been running
running for for aa while,
while, there
there are
are clicked
clicked

--- PRIME
PRIME
--- PRIME
PRIME
--- WAIT
WAIT
--- PRIME
PRIME
--- PRIME
PRIME
--- GO
GO
--- PRIME
PRIME
--- and
and after
after aa while
while PRIME
PRIME

The
The layout
layout isis simple
simple and
and contains
contains only
only 55 components:
components:

<?xml version="1.0" encoding="utf-8"?>


<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="dk.data.torus.serviceapp.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<Button
android:id="@+id/cmdRestart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onGo"
android:text="Go" />

177
177
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

<Button
android:id="@+id/cmdPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onWait"
android:text="Wait" />
<Button
android:id="@+id/cmdClear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onClear"
android:text="Clear" />
<Button
android:id="@+id/cmdCalc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onService"
android:text="Prime" />
</LinearLayout>
<ListView
android:id="@+id/lstView"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
</android.support.constraint.ConstraintLayout>

and
and the
the only
only thing
thing to
to note
note is
is the
the names
names that
that II have
have given
given the
the buttons
buttons and
and the
the ListView,
ListView, as
as
well
well asas the
the names
names ofof the
the event
event handlers
handlers that
that the
the buttons
buttons calls.
calls. The
The code
code for
for MainActivity
MainActivity
is as follows:
is as follows:

package dk.data.torus.serviceapp;

import android.support.v7.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.*;
import android.os.*;
import android.view.*;
import android.widget.*;
import java.util.*;

public class MainActivity extends AppCompatActivity


implements ServiceConnection {
private ListView lstView;

178
178
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

private ArrayAdapter<String> adapter;


private List<String> primesList = new ArrayList();
private LocalService service;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lstView = (ListView)findViewById(R.id.lstView);
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, primesList);
lstView.setAdapter(adapter);
}

@Override
protected void onResume() {
super.onResume();
Intent intent= new Intent(this, LocalService.class);
bindService(intent, this, Context.BIND_AUTO_CREATE);
}

@Override
protected void onPause() {

179
179
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

super.onPause();
unbindService(this);
}

public void onGo(View view) {


service.start();
}

public void onWait(View view) {


service.pause();
}

public void onService(View view) {


adapter.add(String.format("%d: %d", service.
getIndex(), service.getPrime()));
Toast.makeText(this, "List is updated", Toast.LENGTH_SHORT).show();
}

public void onClear(View view) {


adapter.clear();
}

@Override
public void onServiceConnected(ComponentName name, IBinder binder)
{
if (service == null)
service = ((LocalService.PrimesBinder) binder).getService();
Toast.makeText(MainActivity.this, "Service connected",
Toast.LENGTH_SHORT).show();
}

@Override
public void onServiceDisconnected(ComponentName name)
{
service = null;
Toast.makeText(MainActivity.this, "Service disconnected",
Toast.LENGTH_SHORT).show();
}
}

The
The first
first thing
thing to
to note
note is
is that
that the
the class
class implements
implements an an interface
interface ServiceConnection.
ServiceConnection. ThisThis
interface defines two methods to be overridden. The first is called onServiceConnected(),
interface defines two methods to be overridden. The first is called onServiceConnected(),
and
and itit is
is executed
executed when
when the
the application
application starts
starts and
and binds
binds to to the
the service.
service. ItIt initializes
initializes aa
variable
variable service,
service, which
which then
then refers
refers to
to the
the service
service in
in question.
question. InIn addition,
addition, aa simple
simple Toast
Toast is
is
performed,
performed, so so you
you can
can see
see that
that the
the program
program isis bound
bound to
to the
the service.
service. The
The second
second method
method is is
called onServiceDisconnected() and is executed if the application disconnects from
called onServiceDisconnected() and is executed if the application disconnects from the service,the service,
typically
typically because
because Android
Android can
can terminate
terminate the
the service.
service.

180
180
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Services
servICes

In
In addition
addition to
to the
the variable
variable service,
service, there
there isis nothing
nothing to
to note
note about
about the
the class’
class’ variables,
variables, and
and
the
the same
same applies
applies to
to onCreate(),
onCreate(), where
where there
there isis nothing
nothing new.
new. On
On the
the other
other hand,
hand, the
the class
class
overrides
overrides both
both the
the method
method onResume()
onResume() and and onPause(),
onPause(), and
and these
these methods
methods bind
bind oror unbinds
unbinds
the application to the service, thus resulting in the above two methods being
the application to the service, thus resulting in the above two methods being performed. performed.

Finally,
Finally, there
there are
are the
the 44 event
event handlers
handlers for
for the
the buttons,
buttons, which
which are
are generally
generally trivial,
trivial, but
but three
three
of
of them
them use
use methods
methods at at the
the service
service to
to pause,
pause, restart,
restart, and
and read
read its
its value.
value.

The
The service
service isis also
also aa class
class and
and isis written
written as
as follows:
follows:

package dk.data.torus.serviceapp;

import android.app.Service;
import android.content.Intent;
import android.os.*;

public class LocalService extends Service {


private final IBinder binder = new PrimesBinder();
private long prime = 2;
private int index = 0;
private boolean running = false;

@Override
public IBinder onBind(Intent intent)
{
start();
return binder;
}

@Override
public void onRebind(Intent intent) {
start();
}

@Override
public boolean onUnbind(Intent intent) {
running = false;
return true;
}

public int getIndex()


{
return index;
}

181
181
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

public long getPrime()


{
return prime;
}

public void start()


{
if (!running) {
running = true;
Thread th = new Thread(new Generator());
th.start();
}
}

public void pause()


{
running = false;
}

public class PrimesBinder extends Binder {


LocalService getService() {
return LocalService.this;
}
}

Join the best at Top master’s programmes


• 3
 3rd place Financial Times worldwide ranking: MSc
the Maastricht University International Business
• 1st place: MSc International Business
School of Business and • 1st place: MSc Financial Economics
• 2nd place: MSc Management of Learning

Economics! • 2nd place: MSc Economics


• 2nd place: MSc Econometrics and Operations Research
• 2nd place: MSc Global Supply Chain Management and
Change
Sources: Keuzegids Master ranking 2013; Elsevier ‘Beste Studies’ ranking 2012;
Financial Times Global Masters in Management ranking 2012

Maastricht
University is
the best specialist
university in the
Visit us and find out why we are the best! Netherlands
(Elsevier)
Master’s Open Day: 22 February 2014

www.mastersopenday.nl

182
182
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

private class Generator implements Runnable


{
public void run()
{
long t = index == 0 ? 3 : prime + 2;
for ( ; running ; t += 2)
if (isPrime(t))
{
++index;
prime = t;
}
}

private boolean isPrime(long n)


{
if (n == 2 || n == 3 || n == 5 || n == 7) return true;
if (n < 11 || n % 2 == 0) return false;
for (long t = 3, m = (long)Math.sqrt(n) + 1; t <= m; t += 2)
if (n % t == 0) return false;
return true;
}
}
}

First, note that the class inherits the class Service, which is what makes it to a service.
Then note the class’ variables, where the first has the type IBinder, which is an interface
that defines how components can communicate with the service. The variable refers to a
PrimesBinder object, which is a public inner class inheriting the class Binder, and the class
does nothing but implement a method that returns a reference to the current service. The
following variables are for the current prime number, while the last indicates whether the
service is paused.

The class overrides three methods from the class Service, which is performed when a
component binds or rebinds the service, and a method if a component unbinds. Here is
the last trivial, in which it just sets running to false, while the others call the method start().
It is the method that starts the work of the service by starting a thread that runs until the
variable running becomes false. When the thread terminates (running becomes false) the
thread stops and the variables index and prime are not updated, but their value are retained.
This means that if the method start() is executed again, it will start a new thread, which
will then continue from where the previous one stopped.

The thread itself is implemented by an inner class Generator, but here is nothing new and
the method isPrime(), is as you have seen it many times.

183
183
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA
JAVA 16:
JAVA 16: MOBIL
16: MOBIL
MOBIL PHONES
PHONES AND
PHONES AND ANDROID:
AND ANDROID:
ANDROID:
SOFTWARE DEVELOPMENT servICes
SOFTWARE
SOFTWARE DEVELOPMENT
SOFTWARE DEVELOPMENT
DEVELOPMENT Services
servICes
servICes

Back
Back there
there isis
Back there only
is only one
only one thing,
one thing, that
thing, that the
that the manifest
the manifest must
manifest must be
must be updated:
be updated:
updated:

<?xml version="1.0" encoding="utf-8"?>


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dk.data.torus.serviceapp">
package="dk.data.torus.serviceapp">
<application
<application


</activity>
</activity>
<service
<service
android:name=".LocalService"
android:name=".LocalService"
android:label="A local service" >
android:label="A local service" >
</service>
</service>
</application>
</application>
</manifest>
</manifest>

8.9
8.9 SERVICES
8.9 SERVICES AND
SERVICES AND SQLITE
AND SQLITE
SQLITE
As
As the
As the last
the last example
last example
example ofof
of aaa service,
service,
service, III will
will show
show aaa program
will show program that
program that starts
starts aaa service
that starts service that
service that updates
updates aaa
that updates
database
database every
database every 20
every 20 seconds.
20 seconds.
seconds. The The example
The example also
example also includes
also includes another
includes another program
another program
program (a (a client)
(a client) that
client) that can
that can
can
read
read the
read the content
the content of
content of the
of the database
the database
database andand the
and the goal
the goal is to
goal isis to show
to show
show

1.
1. how
1. how an
how an application
an application and
and aaa service
application and service can
service can write
can write to
to aaa database
write to database
database
2.
2. how
2. how another
how another application
another application can
application can read
can read the
read the same
the same database
same database
database

However,
However, III will
However, will start
will start with
with aaa database
start with database adapter
database adapter
adapter thatthat
that isis not
is not necessary
not necessary for
necessary for the
for the purpose
the purpose of
purpose of this
of this
this
task,
task, but
task, but a very
but aa very used
very used pattern.
used pattern.
pattern. InIn fact,
In fact, it is nothing
fact, itit isis nothing
nothing but but a class
but aa class that
class that encapsulates
that encapsulates the
encapsulates the class
the class
class
SQLiteOpenHelper
SQLiteOpenHelper
SQLiteOpenHelper and and the
and the database
the database operations.
database operations.
operations. In In this
In this case,
this case, the
case, the database
the database must
database must have
must have only
have only
only
one
one table
one table that
table that has
that has three
has three columns:
three columns:
columns:

create table posts (


create table posts (
id integer primary key autoincrement,
id integer primary key autoincrement,
time varchar(19) not null,
time varchar(19) not null,
post varchar(100) not null)
post varchar(100) not null)

where
where the column time contains a clock time of the form YYYY-MM-DD HH:MM:SS, while
where the
the column
column time
time contains
contains aa clock
clock time
time of
of the
the form
form YYYY-MM-DD
YYYY-MM-DD HH:MM:SS,
HH:MM:SS, while
while
the
the last
last column
column isis just
just aa text.
text. The
The adapter
adapter can
can then
then be
be written
written as
as follows:
follows:
the last column is just a text. The adapter can then be written as follows:

package dk.data.torus.launchposts;
package dk.data.torus.launchposts;

import android.content.ContentValues;
import android.content.ContentValues;
import android.content.Context;
import android.content.Context;
import android.database.Cursor;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteOpenHelper;

184
184
184
184
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

public class DbAdapter {


public static final String TABLE_NAME="posts";
public static final int COLNO_ID = 0;
public static final int COLNO_TIME = 1;
public static final int COLNO_POST = 2;
public static final String[] TABLE_COLUMNS =
new String[]{ "id", "time", "post" };
private static final String DBFILENAME="posts.db";
private static final int DBVERSION = 1;
private static final String INITIAL_SCHEMA =
"create table posts (id integer primary key autoincrement, " +
"time varchar(19) not null, " +
"post varchar(100) not null)";
private final Context context;
private DatabaseHelper dbHelper;
private SQLiteDatabase db;

public DbAdapter(Context context) {


this.context = context;
dbHelper = new DatabaseHelper(context);
}

185
185
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

public DbAdapter open() {


db = dbHelper.getWritableDatabase();
return this;
}

public void close() {


dbHelper.close();
}

public long insert(String time, String post) {


ContentValues values = new ContentValues();
values.put(TABLE_COLUMNS[COLNO_TIME], time);
values.put(TABLE_COLUMNS[COLNO_POST], post);
return db.insert(TABLE_NAME, null, values);
}

public boolean update(String time, String post) {


ContentValues values = new ContentValues();
values.put(TABLE_COLUMNS[COLNO_TIME], time);
values.put(TABLE_COLUMNS[COLNO_POST], post);
return db.update(TABLE_NAME, values, "id = 1", null) != 0;
}

public boolean delete(int id) {


return db.delete(TABLE_NAME, "id = ?", new String[] {"" + id}) != 0;
}

public void delete() {


db.delete(TABLE_NAME, null, null);
}

public Cursor getRows() {


Cursor cursor =
db.query(TABLE_NAME, TABLE_COLUMNS, null, null, null, null, null);
return cursor;
}

public Cursor getRow(int id) {


Cursor cursor = db.query(TABLE_NAME, TABLE_COLUMNS, "id = ?",
new String[] {"" + id}, null, null, null, null);
return cursor;
}

public Cursor getRows(String date) {


Cursor cursor = db.query(TABLE_NAME, TABLE_COLUMNS, "time like ?",
new String[] { date + "%"}, null, null, null, null);
return cursor;
}

186
186
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA
JAVA16:
16:MOBIL
SOFTWARE MOBIL PHONES
PHONESAND
DEVELOPMENTANDANDROID:
ANDROID: Services
SOFTWARE
SOFTWAREDEVELOPMENT
DEVELOPMENT servICes
servICes

private
private static
static class
class DatabaseHelper
DatabaseHelper extends
extends SQLiteOpenHelper
SQLiteOpenHelper
{{
DatabaseHelper(Context
DatabaseHelper(Context context)
context) {{
super(context, DBFILENAME, null,
super(context, DBFILENAME, null, DBVERSION);
DBVERSION);
}}

@Override
@Override
public
public void
void onCreate(SQLiteDatabase
onCreate(SQLiteDatabase db)
db) {{
db.execSQL(INITIAL_SCHEMA);
db.execSQL(INITIAL_SCHEMA);
}}

@Override
@Override
public
public void
void onUpgrade(SQLiteDatabase
onUpgrade(SQLiteDatabase db,
db, int
int oldVersion,
oldVersion, int
int newVersion)
newVersion)
{{
db.execSQL("DROP
db.execSQL("DROP TABLE
TABLE IF
IF EXISTS
EXISTS "" ++ TABLE_NAME);
TABLE_NAME);
onCreate(db);
onCreate(db);
}}

@Override
@Override
public
public void
void onDowngrade(SQLiteDatabase
onDowngrade(SQLiteDatabase db,
db, int
int oldVersion,
oldVersion, int
int newVersion)
newVersion)
{{
db.execSQL("DROP
db.execSQL("DROP TABLE
TABLE IF
IF EXISTS
EXISTS "" ++ TABLE_NAME);
TABLE_NAME);
onCreate(db);
onCreate(db);
}}
}}
}}

In
In fact,
fact, the
the class
class isis easy
easy enough
enough to to understand
understand and and contains,
contains, amongamong other
other things,
things, what
what II
have
have previously
previously shown
shown as as aa DbHelper
DbHelper class.
class. In
In addition,
addition, there
there are
are the
the database
database operations
operations
and
and which
which will
will depend
depend on on the
the specific
specific database
database andand how
how itit will
will be
be used.
used. In
In this
this case,
case, there
there
are
are more
more than
than the
the applications
applications uses,
uses, just
just to
to give
give an
an impression
impression of of which
which operations
operations youyou
typically
typically want.
want. The
The mostmost important
important reason
reason forfor the
the class
class isis that
that itit makes
makes itit easy
easy to
to use
use the
the
same
same database
database from
from multiple
multiple programs.
programs.

The
The project
project that
that creates
creates the
the database
database and and the
the service
service isis called
called LaunchPosts,
LaunchPosts, andand itit will
will thus
thus
be
be the
the application
application to to which
which thatthat database
database isis aa belongs.
belongs. The The project
project uses
uses two
two classes,
classes, which
which II
have
haveused
usedin
inprevious
previousexamples
examplesand andititare
arethe
theclass
classKing,
King,whichwhichrepresents
representsaaDanish
Danishkingkingandand
the
the class
class Kings,
Kings, which
which isis aa list
list of
of King
King objects
objects andand has
has aa method
method that
that returns
returns aa List<King>.
List<King>.
The
The service
service isis as
as follows:
follows:

package
package dk.data.torus.launchposts;
dk.data.torus.launchposts;

import
import android.app.Service;
android.app.Service;
import
import android.content.Context;
android.content.Context;
import
import android.content.Intent;
android.content.Intent;
import
import android.database.Cursor;
android.database.Cursor;

187
187
187
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

import android.os.IBinder;
import android.support.annotation.Nullable;
import java.util.*;

public class PostService extends Service {


private static final Random rand = new Random();
private Kings kings = new Kings();
private Timer timer;
private TimerTask timerTask;

public PostService() {
}

public PostService(Context applicationContext) {


super();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
startTimer();
return START_STICKY;
}

Need help with your


dissertation?
Get in-depth feedback & advice from experts in your
topic area. Find out what you can do to improve
the quality of your dissertation!

Get Help Now

Go to www.helpmyassignment.co.uk for more info

188
188
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

@Override
public void onDestroy() {
super.onDestroy();
stoptimertask();
}

public void startTimer() {


timer = new Timer();
initializeTimerTask();
timer.schedule(timerTask, 20000, 20000);
}

public void initializeTimerTask() {


timerTask = new TimerTask() {
public void run() {
writePost(getPost());
}
};
}

public void stoptimertask() {


if (timer != null) {
timer.cancel();
timer = null;
}
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}

private void writePost(String post)


{
Calendar cal = Calendar.getInstance();
String time = String.format("%04d-%02d-%02d %02d:%02d:%02d",
cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1,
cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
Context context = getApplicationContext();
DbAdapter db = new DbAdapter(getApplicationContext());
db.open();
Cursor cursor = db.getRows();
cursor.moveToFirst();
if (cursor.isAfterLast()) db.insert(time, post); else db.update(time, post);
cursor.close();
db.close();
}

189
189
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

private String getPost()


{
King king = kings.getKings().get(rand.nextInt(kings.getKings().size()));
if (king.getFrom() > 0 && king.getTo() < 9999)
return String.format("Kind regards: %s, %d – %d", king.getName(),
king.getFrom(), king.getTo());
if (king.getFrom() > 0) return String.format("Kind regards: %s, %d -",
king.getName(), king.getFrom());
if (king.getTo() < 9999) return String.format("Kind regards: %s, – %d",
king.getName(), king.getTo());
return "Kind regards: " + king.getName();
}
}

Please note that it is a normal service, and since onBind() is trivial, it is not a service that
Please note that it is a normal service, and since onBind() is trivial, it is not a service that
clients can connect to, but a service that starts and runs until it’s done, and in this case it’s
clients can connect to, but a service that starts and runs until it’s done, and in this case it’s
until onDestroy() is performed. onStartCommand() is simple, but it starts a timer ticking
until onDestroy() is performed. onStartCommand() is simple, but it starts a timer ticking
every 20 seconds, and every time it ticks, it creates with the last method a greeting from a
every 20 seconds, and every time it ticks, it creates with the last method a greeting from a
Danish king, which is sent to the method writePost(). This method uses the database adapter
Danish king, which is sent to the method writePost(). This method uses the database adapter
to update the database with the current greeting. Here you should note that the method
to update the database with the current greeting. Here you should note that the method
updates the same row every time (the database table has only 1 row) and the reason is that
updates the same row every time (the database table has only 1 row) and the reason is that
the database should not grow beyond all limits. The goal is only to show that a service can
the database should not grow beyond all limits. The goal is only to show that a service can
write to a database.
write to a database.

Running the LaunchPosts application opens the following window:


Running the LaunchPosts application opens the following window:

190
190
JAVA 16:
JAVA 16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE DEVELOPMENT
SOFTWARE DEVELOPMENT servICes
Services

The window
The window has has 66 components.
components. The The top
top two
two are
are TextView components and are updated
ifif you
you click
click the
the buttons.
buttons. If
If you
you click
click on
on the
the top
top button,
button, the
the program
program reads
reads thethe database
database
and the
and the fields
fields are
are updated
updated with
with the
the record
record that
that is
is read.
read. The
The next
next tests
tests where
where thethe service
service is
is
running and
running and updates
updates the
the top
top TextView
TextView component.
component. The The Button
Button Start
Start starts
starts the
the service,
service, while
while
the last
the last stops
stops the
the service.
service. The
The user
user interface
interface is
is of
of course
course simple,
simple, but
but the
the class
class MainActivity
MainActivity
contains some
contains some code:
code:

package dk.data.torus.launchposts;

import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {


private TextView txtDate;
private TextView txtPost;
private PostService service;

Brain power By 2020, wind could provide one-tenth of our planet’s


electricity needs. Already today, SKF’s innovative know-
how is crucial to running a large proportion of the
world’s wind turbines.
Up to 25 % of the generating costs relate to mainte-
nance. These can be reduced dramatically thanks to our
systems for on-line condition monitoring and automatic
lubrication. We help make it more economical to create
cleaner, cheaper energy out of thin air.
By sharing our experience, expertise, and creativity,
industries can boost performance beyond expectations.
Therefore we need the best employees who can
meet this challenge!

The Power of Knowledge Engineering

Plug into The Power of Knowledge Engineering.


Visit us at www.skf.com/knowledge

191
191
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtDate = (TextView) findViewById(R.id.txtDate);
txtPost = (TextView) findViewById(R.id.txtPost);
service = new PostService(this);
}

public void onCheck(View view) {


checkState(service.getClass());
}

public void onStart(View view) {


if (!isRunning(service.getClass()))
{
startService(new Intent(this, service.getClass()));
if (isRunning(service.getClass())) txtDate.setText("Post service started");
else txtDate.setText("Service could not be started");
}
else txtDate.setText("Service is already started");
}

public void onStop(View view) {


stopService(new Intent(MainActivity.this, PostService.class));
if (isRunning(service.getClass()))
txtDate.setText("Service could not be stopped");
else txtDate.setText("Post service stopped");
}

public void onRead(View view)


{
try {
DbAdapter db = new DbAdapter(getApplicationContext());
db.open();
Cursor cursor = db.getRows();
cursor.moveToFirst();
if (!cursor.isAfterLast())
{
txtDate.setText(cursor.getString(DbAdapter.COLNO_TIME));
txtPost.setText(cursor.getString(DbAdapter.COLNO_POST));
}
else txtDate.setText("Database is empty");
cursor.close();
db.close();
}
catch (Exception ex)
{

192
192
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
SOFTWARE DEVELOPMENT servICes

txtDate.setText(ex.getMessage());
}
}

private boolean isRunning(Class<?> serviceClass) {


ActivityManager manager =
(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service :
manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}

private void checkState(Class<?> serviceClass)


{
ActivityManager manager =
(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service :
manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
txtDate.setText("Post service: Running");
return;
}
}
txtDate.setText("Post service: Not started");
}
}

In particular, note the two last methods. Here’s the first the test where the servise identified
In particular, note the two last methods. Here’s the first the test where the servise identified
by a Class is running. There is not much to explain in addition to noting that, but shortly,
by a Class is running. There is not much to explain in addition to noting that, but shortly,
you use the method getSystemService() to determine which services are running and the
you use the method getSystemService() to determine which services are running and the
result is an ActivityManager object. This object has a collection of running services, and you
result is an ActivityManager object. This object has a collection of running services, and you
can traverse this collection to determine if that service is running. The last method works
can traverse this collection to determine if that service is running. The last method works
in the same way, but it updates the TextView component. The two methods are used from
in the same way, but it updates the TextView component. The two methods are used from
the event handlers, and here you should especially note how to indicates the Class object.
the event handlers, and here you should especially note how to indicates the Class object.

The event handlers onStart() and onStop() in principle do not contain anything new besides
The event handlers onStart() and onStop() in principle do not contain anything new besides
using the above methods, and the same applies to onCheck(). Finally, there is the event
using the above methods, and the same applies to onCheck(). Finally, there is the event
handler onRead(), which reads in the database, and it happens with the adapter. Note that
handler onRead(), which reads in the database, and it happens with the adapter. Note that
the adapter’s get methods returns a Cursor object, and you could make a nicer wrapper by
the adapter’s get methods returns a Cursor object, and you could make a nicer wrapper by
returning a King object or a list of King objects instead.
returning a King object or a list of King objects instead.

193
193
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Services
servICes

If
If you
you look
look at
at the
the class
class MainActivity
MainActivity (and
(and also
also the
the class
class PostService),
PostService), there
there is
is nothing
nothing about
about
that
that the
the database
database should
should bebe able
able to
to be
be used
used from
from another
another program.
program. Nor
Nor should
should much
much
happen,
happen, but only that the other program should use the same database adapter and then
but only that the other program should use the same database adapter and then
add an addition to the manifest:
add an addition to the manifest:

<?xml version="1.0" encoding="utf-8"?>


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:sharedUserId="dk.data.torus.app"
package="dk.data.torus.launchposts">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
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>

194
194
JAVA 16: MOBIL PHONES AND ANDROID:
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT Services
JAVA 16: MOBIL
SOFTWARE PHONES AND ANDROID:
DEVELOPMENT servICes
SOFTWARE DEVELOPMENT servICes

<service
<service
android:name="dk.data.torus.launchposts.PostService"
android:name="dk.data.torus.launchposts.PostService"
android:enabled="true" >
android:enabled="true" >
</service>
</service>
</application>
</application>
</manifest>
</manifest>

Then to the second program, called ReadPosts. Firstly, the manifest of this program must be
Then
Then toto the
the second
second program,
program, called
called ReadPosts.
ReadPosts. Firstly,
Firstly, the
the manifest
manifest ofof this
this program
program must
must be
be
updated in the same way as shown above, so it has the same sharedUserId. The program’s
updated
updated in in the
the same
same way
way as
as shown
shown above,
above, so
so itit has
has the
the same
same sharedUserId.
sharedUserId. TheThe program’s
program’s
user interface is almost identical to the above, just missing the three bottom buttons. Then
user
user interface
interface isis almost
almost identical
identical to
to the
the above,
above, just
just missing
missing the
the three
three bottom
bottom buttons.
buttons. Then
Then
a copy of the class DbAdapter has been added, and finally there are MainActivity:
aa copy
copy of
of the
the class
class DbAdapter
DbAdapter has has been
been added,
added, andand finally
finally there
there are
are MainActivity:
MainActivity:
public class MainActivity extends AppCompatActivity {
public class MainActivity extends AppCompatActivity {
private TextView txtDate;
private TextView txtDate;
private TextView txtPost;
private TextView txtPost;
private Context sharedContext = null;
private Context sharedContext = null;

@Override
@Override
protected void onCreate(Bundle savedInstanceState) {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setContentView(R.layout.activity_main);
txtDate = (TextView)findViewById(R.id.txtDate);
txtDate = (TextView)findViewById(R.id.txtDate);
txtPost = (TextView)findViewById(R.id.txtPost);
txtPost = (TextView)findViewById(R.id.txtPost);
try {
try {
sharedContext = this.createPackageContext("dk.data.torus.launchposts",
sharedContext = this.createPackageContext("dk.data.torus.launchposts",
Context.CONTEXT_INCLUDE_CODE);
Context.CONTEXT_INCLUDE_CODE);
} catch (Exception e) {
} catch (Exception e) {
sharedContext = this;
sharedContext = this;
}
}
}
}

public void onRead(View view)


public void onRead(View view)
{
{


}
}
}
}

Here the
Here the event handler
handler onRead() isis the
the same and
and all you
you need to
to note isis that
that the same
same
Here the event
event handler onRead()
onRead() is the same
same and all
all you need
need to note
note is that thethe same
Contextshould
Context should beused
used forthe
the databaseand
and howtoto determinethis
this withcontext.getResources().
context.getResources().
Context shouldbe
be usedfor
for thedatabase
database andhow
how todetermine
determine thiswith
with context.getResources().

After that,
After that, both programs
programs can be be installed on
on the phone
phone and itit allall should work.
work. If you
After that, both
both programs can can be installed
installed on the
the phone and and it all should
should work. IfIf you
you
install the
install the programs
programs on
on aa physical
physical device,
device, be
be sure
sure to
to stop
stop the
the service
service after
after you
you have
have tested
tested
install the programs on a physical device, be sure to stop the service after you have tested
the programs
the programs as itit will
will continue and
and update thethe database every
every 20 seconds.
seconds.
the programs as as it will continue
continue and update
update the database
database every 20 20 seconds.

195
195
195
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT A final example

9 A FINAL EXAMPLE
As the final example of this book, I will write the same program, which was the final example
of the book Java 8, and thus a calendar program where you can navigate the calendar and
enter notes and appointments. The program should basically have the same features as in
Java 8, and it is a goal to reuse as much of the design and code as possible. One can thus
think of the task as a project, where you have to migrate a PC application to a mobile phone.

The purpose of the example is to show a slightly larger program and partly to apply many
of the elements for developing mobile phone apps mentioned in this book. Regarding the
requirements of the program, please refer to the Java 8 book, and the following will only
focus on how I developed the program, what I have reused from the previous version, and
what has been implemented differently, including primarily in relation to Android and mobile
phones. The program is developed through a series of small iterations or sprints, and the
following is a brief presentation of these sprints and including the most important decisions.

9.1 PROJECT START AND MAINACTIVITY

196
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT A final example

The overall design of the window is shown here, where the icons (buttons) in the toolbar
are used for:

-- to navigate the calendar a year back


-- to navigate the calendar a month back
-- to navigate the calendar a month onwards
-- to navigate the calendar a year onwards
-- to navigate the calendar for a particular month a certain year
-- set a stopwatch
-- set a count down
-- set an alarm

The calendar’s other functions are located in the main menu of the program and as a context
menu for the calendar itself. The function export to XML is not included in this mobil
phone version. Initially, only the first four buttons in the toolbar are implemented, so you
can navigate the calendar one month back or forth and one year back or forth.

From the previous version of the program I have copied the two classes Date and MainModel.
Both these classes are placed in a sub package called models. The class Date is completely

197
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT A final example

unchanged from the fact that the package name has been changed. In principle, this also
applies to the class MainModel, but something here has no meaning yet and is therefore
commented out.

The user interface is defined entirely in XML. It’s extensive (fills a lot), but the user interface
is simple to design using copy/paste, and in the code is defined references to individual
components, and the result is a user interface that is simple and stable to update. As a
result, the class MainActivity until this place is simple to write.

When reviewing the code, you should first notice how to create an ImageButton in XML,
which is a button with an image. The individual images are added as resources to res.
drawable. In the Java code, you should notice how to refer to the individual widgets using
their name and not their ID. You should also note how the event handlers are linked to
the four buttons in the code.

9.2 THE DATA ACCESS LAYER


The program should be able to maintain data regarding notes, appointments and anniversaries.
In the original PC application, I used object serialization, but in the current version I would
instead use a SQLite database. The goal of this iteration is to clarify the model to persist
data. The result is as follows:

1. The classes Note, Appointment and Anniversery are copied from the Java 8 project.
These model classes have not been changed.
2. The interface Repository is copied and it is also unchanged.
3. The class Time is copied. It is expanded with an additional constructor that parses
a string on the form HH:MM to a Time object.
4. Similarly, the class Date is expanded with a constructor that parses a string on the
form YYYY-MM-DD to a Date object.

The reason for the last two changes is that SQLite does not have types for Date and
Time columns.

A package dal has been added to the project, and here a I have created a DbHelper class
for three tables notes, appointments and anniversaries.

The class IORpository is copied from the original project. The class has the same interface
(Repository), but otherwise the class has been completely modified so it now persists data
in a SQLite database. The class has not been tested in addition to it has an error-free

198
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT A final example

translation, and the test is associated with the implementation of the individual calendar
functions. One must therefore expect that there will be changes to the class during the
following three sprints.

9.3 NOTES
This sprint is about implementing maintenance of notes and in principle includes 3 features

1. To create and maintain a note (CRUD)


2. To show an overview of all notes
3. To delete all notes within an interval of two dates

The two lower functions are selected from the program’s options menu, while the first one
is selected either from the context menu or from the list of notes. The result is that three
new activities have been added to the project, but there are also significant changes to the
class MainActivity.

Since all database operations are implemented in the previous iteration, it should be in
place and there are no changes to these operations. However, the class IORepository and
thus the interface Repository are expanded with a new method used to search notes by title.

The first of the above activities is called NoteActivity and is used for CRUD operations. It
opens from the program’s context menu, or from the activity NotesActivity. It is a simple
activity and can be called with two parameters, which can be a Date object and is used
if the activity is opened from the context menu, and it may be a Note object and used if
opened from NotesActivity. In the latter case, you will see all the note’s data, you can edit
the note (not the date that specifies when the note is created) and you can delete it.

The other activity is called NotesActivity and shows an overview of all notes. If it has no
parameter, it shows all notes, but you can search for a title that works like a filter. If the
activity is called without parameter, it is from the program’s options menu. If a note has been
created for a specific day in the calendar, the context menu is expanded with an additional
menu item called Show notes, and selecting this menu item opens NotesActivity again, but
this time with the date as parameter, and the window only shows notes for the current day.

The last activity is called RemoveActivity and is very simple. It’s only a matter of being able
to enter two dates and then call a database operation that deletes all notes within that range.
The function is performed from the program’s options menu. Since it basic is the same

199
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT A
a final
FInaL example
exampLe

function
function that
that will
will be
be used
used for
for appointments
appointments and
and anniversaries,
anniversaries, the
the activity
activity has
has aa parameter
parameter
indicating what the function is to be used for.
indicating what the function is to be used for.

Then
Then there
there is
is MainActivity
MainActivity where
where there
there are
are changes.
changes. There
There are
are of
of course
course changes
changes to
to open
open
the
the above
above activities,
activities, but
but the
the biggest
biggest change
change concerns
concerns the
the context
context menu.
menu. First,
First, each
each date
date field
field
should be able to open its own context menu, which corresponds
should be able to open its own context menu, which corresponds to that to that

registerForContextMenu()

must
must bebe performed
performed for for all
all TextView
TextView widgets
widgets that
that represent
represent aa date.
date. In
In order
order toto read
read the
the date,
date,
one
one should also be able to determine which TextView one has held his finger on, and you can
should also be able to determine which TextView one has held his finger on, and you can
not
not do
do that
that immediately.
immediately. One One solution
solution isis that
that when
when you
you touch
touch aa View
View object,
object, anan onTouch()
onTouch()
method is performed, which is an event handler defined in the interface
method is performed, which is an event handler defined in the interface OnTouchListener. OnTouchListener.
If
If you
you associate
associate this
this event
event with
with all
all TextView
TextView components
components for for dates,
dates, you
you can
can initialize
initialize an
an
instance variable with the reference of the last viewed View, and when the event
instance variable with the reference of the last viewed View, and when the event handler for handler for
the
the context
context menu
menu isis executed,
executed, you
you can
can determine
determine which
which View
View relates
relates to
to the
the event.
event. It
It requires
requires
that
that you also know its coordinates (row and column), but it can be done by attaching aa
you also know its coordinates (row and column), but it can be done by attaching
tag
tag object
object toto the
the component.
component. It It sounds
sounds aa bitbit complex
complex and
and can
can be
be called
called for
for aa work
work around.
around.

Challenge the way we run

EXPERIENCE THE POWER OF


FULL ENGAGEMENT…

RUN FASTER.
RUN LONGER.. READ MORE & PRE-ORDER TODAY
RUN EASIER… WWW.GAITEYE.COM

1349906_A6_4+0.indd 1 22-08-2014 12:56:57


200
200
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT A
a final
FInaL example
exampLe

Another
Another problem
problem to to be
be solved
solved isis that
that the
the context
context menu
menu should
should bebe dynamic.
dynamic. InIn addition
addition to
to
the
the three
three fixed
fixed menu
menu items,
items, there
there must
must be be anan additional
additional menu
menu item
item for
for each
each of
of the
the three,
three,
ifif aa note,
note, appointment or anniversary has been created for that date. Finally, there must
appointment or anniversary has been created for that date. Finally, there must
be
be an additional menu item if the date is a public holiday. For these reasons, the menu isis
an additional menu item if the date is a public holiday. For these reasons, the menu
now
now defined
defined inin the
the code
code (and
(and the
the file
file context_menu.xml
context_menu.xml isis removed).
removed).

Finally,
Finally, itit should
should be
be possible
possible in
in the
the user
user interface
interface to
to see
see (with
(with aa red
red color)
color) and
and for
for aa given
given
date if there are extensions to the context menu. It requires a change in model
date if there are extensions to the context menu. It requires a change in model (the three (the three
static
static methods
methods previously
previously commented
commented out out should
should bebe activated
activated and
and changed
changed slightly).
slightly).

9.4 ANNIVERSARIES
9.4 ANNIVERSARIES
In
In the
the next
next sprint,
sprint, II will
will implement
implement maintenance
maintenance of of anniversaries.
anniversaries. In In principle,
principle, they
they must
must
be
be done
done inin the
the same
same wayway as
as maintenance
maintenance of of notes,
notes, but
but itit isis simpler
simpler as
as most
most challenges
challenges
are
are solved,
solved, and
and since
since the
the function
function can
can be
be implemented
implemented to to aa large
large extent
extent using
using copy/paste.
copy/paste.
Basically, two activities must be added:
Basically, two activities must be added:

1.
1. AnniversaryActivitiy
AnniversaryActivitiy to
to CRUD
CRUD functions
functions
2.
2. AnniversariesActivity
AnniversariesActivity to
to overview
overview of
of anniversaries
anniversaries

Both
Both activities
activities can
can bebe implemented
implemented byby copying
copying the the corresponding
corresponding activities
activities for
for notes.
notes. In
In
the
the same
same way
way asas for
for the
the maintenance
maintenance of
of notes,
notes, itit has
has been
been necessary
necessary to
to add
add anan additional
additional
search
search method
method to to IORepository
IORepository regarding
regarding anniversaries.
anniversaries.

Finally,
Finally, there
there isis removing
removing anniversaries,
anniversaries, but
but itit isis already
already implemented
implemented in
in RemoveActivity.
RemoveActivity.
However,
However, itit has
has been
been necessary
necessary to
to change
change the
the method
method

public boolean deleteAnniversaries(SQLiteDatabase db, Date from, Date to)

in
in the
the class
class IORepository.
IORepository.

As
As part
part of
of this
this iteration,
iteration, MainActivity
MainActivity has
has also
also been
been updated,
updated, but
but it’s
it’s only
only aa matter
matter of
of
updating
updating the
the menus
menus event
event handlers.
handlers.

At
At the
the end
end of
of the
the iteration,
iteration, the
the following
following changes
changes have
have been
been made:
made:

1.
1. II have
have deleted
deleted the
the interface
interface Repository.
Repository.
2.
2. II have
have changed
changed the
the name
name of
of IORepository
IORepository to
to the
the Repository
Repository and
and at
at the
the same
same time
time
changed the class to a singleton.
changed the class to a singleton.

201
201
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT A final example

The reason for this changes is primarily that it provides a slightly simpler code, which does
not always require instances of the class IORepository. Another reason is that the Repository
class contains several methods that are not used, but they are there because of the interface
and as part of the conversion of the class IORepository to the current project. I want to
remove these methods as part of the next sprint.

9.5 APPOINTMENTS
This sprint is essentially identical to the previous one, but it is less about copy/paste. The
CRUD window is more complex as it also has to show an overview of other appointments
for the same day, and also the program must validate that an appointment does not
consolidate with an already created appointment. The code for that is taken from the PC
version of the program.

After this sprint, all functions relating to the database are completed and all menu item
functions are in place (except the clock menu item). Finally, the class Repository is updated
where the unused methods are removed.

9.6 THE OTHER TOOLS


The task of this iteration is to implement the last functions, that is, the four tools in the
toolbar and to turn the clock on and off.

The tool: Select a month


It’s a simple feature. Choosing this tool in the toolbar opens an activity GotoActivity, where
you can enter a year and select a month. If you click OK, you will return to MainActity,
and the calendar will show the selected month. In addition to adding the GotoActivity class,
a class Month has been added that is used to return the selected month.

The tool: Stopwatch


The stopwatch appears under the calendar as a button and a read-only EditText component,
which displays the clock. By default, these two components are invisible. Clicking on the
button in the toolbar displays the components and the clock starts. If you click on the button

202
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT A final example

again, the components disappear, and the button in the toolbar is thus an on/off button. If
the stopwatch is visible and running, and you click the button below the calendar, it will
stop the clock and you can start it again by clicking the button.

To implement the stopwatch, the following types are added to the project’s model:

-- Stopwatch
-- StopEvent
-- StopListener

These types are taken from the PC version and are largely unchanged. Stopwatch is in principle
an enclosure of a timer ticking every second and every time the timer is ticking, a notification
is sent as a StopEvent to a StopListener. It is an interface that MainActivity implements.

The tool: Count Down


The counter is displayed below the stopwatch as a button and a read-only EditText component,
which displays the clock. By default, these two components are invisible. If you click on
the button in the toolbar, you switch to an activity WatchActivity, where you have to set

This e-book
is made with SETASIGN
SetaPDF

PDF components for PHP developers

www.setasign.com

203
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT A final example

the clock (the clock counts down to 0). Clicking on OK displays the components and the
clock starts. If you click on the button again, nothing happens (it’s not an on/off button),
but clicking on the button below the calendar stops the counter and the two components
become invisible again.

When starting a counter, the program simultaneously starts a service that runs to just before
the counter is 0. When it occurs, the phone rings for 10 seconds and the MainActivity
window opens, which it is not already. The service class is called CounterService.

In order to implement the counter, the following types are also added to the project model:

-- Watch, som er basisklasse til Counter


-- TimeEvent
-- TimeListener
-- Counter

These types are taken from the PC version and are largely unchanged. Counter is in principle
an enclosure of a timer ticking every second and every time the timer is ticking, a notification
is sent as a TimeEvent to a TimeListener. It is an interface that MainActivity implements.
Notifications are also sent when the counter starts and stops.

The tool: Alarm


This tool is in principle identical to the above counter and appears in the window under the
counter. The difference is that an alarm selects an alarm clock (with the activity WatchActivity)
and the alarm occurs when the clock reaches this time. The following types have been added:

-- Alarm
-- AlarmService

The tool: Clock


It’s a simple feature. In the menu you can choose to turn a watch on and off. The function
consists only of starting a timer that ticks every second and the following types have been
added to the model:

-- Clock
-- ClockEvent
-- ClockListener

204
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT A final example

The AppointmentService
In fact, another feature still lacks, that must warning the user if it is time for an appointment.
The function is implemented as a service that starts when the program is started (if it is
not already running). The service tests for appointments every second minute:

1. If an appointment occurs within 5 minutes, the service sends a Toast.


2. If an appointment occurs within 15 minutes, the service sends a Toast.
3. If an appointment occurs within 1 hour, the service sends a Toast.

If the time for an appointment has passed, the following occurs:

1. The service in question is deleted in the database.


2. The phone rings for 2 seconds.
3. The service opens the Calendar’s MainActivity (if it is not already).
4. The service will insert a notification in the window’s action bar.

Appointments have a property Save, which indicates that an appointment should not to
be deleted (a feature inherited from the PC version of the program). This feature does not
really make sense, and as it complicates the current service, the option is removed. The
database has not been changed, and the only thing that has happened is that in the acitivity
AppointmentActivity, a CheckBox has been removed.

For the purpose of notifications from the service, the program’s options menu is expanded
with a function so that you can delete all notifications in the action bar.

The service starts when the application starts, if it is not already running.

Then there is the implementation of the service itself, which is not quite simple, and which
uses to send notifications to the client, something that I have not mentioned. The service
starts a thread that performs the work, and the code for this thread (at least the algorithm)
is retrieved from the PC program. What complicates the service is that the thread must
communicate with the program either in the form of Toast messages or notifications to
the status bar. It is therefore necessary to create Handler objects for the communication.
Finally, there is the code that sends notifications, which is quite complex and difficult to
figure out. If you not only want to take it as it is, studying the online documentation best
describes the meaning of it all.

205
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT A final example

9.7 A PROJECT REVIEW


The last iteration includes review of the code, further testing, and rectification of deficiencies
and inconveniences.

Regarding the latter, two things have changed:

When maintaining notes, appointments and anniversaries, the user interface must be updated
to see that a change has occurred for a date in the current month. Predictable, it applies
only to changes from the options menu. The change consists primarily of switching activity
using the method startActivityForResult() instead of startActivity().

With regard to the service AppointmentService, it may not be desirable for this service to run
all the time, at least not if it is a demo program. The option menu is therefore expanded
with two new menu items for starting and stopping this service. You must therefore manually
start the service, but then it should also run until the device is booted. One might consider
instead starting the sevice at the start of the program (as it is now) and retaining the menu
items and thus having the opportunity to stop the service.

Otherwise, only minor color adjustments, a new icon, and changes have been introduced
so that you use the correct virtual keyboard.

The largest part of this iteration has been used on the test, and some errors are corrected.

If you look at the final result, there should be things that should be different, and for
example, some of the application’s activities should be replaced by dialogs, but here I lack
the foundation so it has to wait for later. The biggest problem, however, is that the program
does not work at all – at least not as desired. As long as the phone is switched on, it all
works well in principle, but if the phone has gone to sleep, the three services can not wake
the application, and so the idea goes a little to the ground. Thus there is another pendant
to the next book.

206
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT Appendix A, installing of Android Studio

APPENDIX A, INSTALLING
OF ANDROID STUDIO
The following is a brief introduction to how to set up a development environment for
Android. There are several options, and you can add a plugin to NetBeans, thus using your
well-known development tool. However, most people use either Eclipse or Android Studio,
and as I apply the latter, it is the product as the following reviews. An Android developer
tool requires two things:

1. A common IDE, where you can enter and edit the code.
2. An emulator, which is a program running a virtual Android machine on your PC,
simulating a mobile phone, for example, to test the programs you write before they
are installed on a physical device such as a phone.

In fact, the integration between the two products is the challenge, as it seems from the
developer must be easy and effective without big problems. That’s why there are not so
many who uses NetBeans as a platform for software development for Android.

Free eBook on
Learning & Development
By the Chief Learning Officer of McKinsey

Download Now

207
JAVA
JAVA 16:
16: MOBIL
MOBIL PHONES
PHONES AND
AND ANDROID:
ANDROID:
SOFTWARE
SOFTWARE DEVELOPMENT
DEVELOPMENT Appendix
appendIx A,
a, installing
InstaLLIng of
oF Android
androId Studio
studIo

To
To write
write Android
Android applications
applications you
you need
need two
two things:
things:

1.
1. Android
Android SDK
SDK that
that best
best can
can be
be characterized
characterized as
as aa number
number of
of libraries
libraries that
that contains
contains
all the components that an Android application
all the components that an Android application may need.may need.
2.
2. Android
Android Tools,
Tools, which
which areare aa number
number ofof tools
tools used
used in
in the
the development
development of of apps,
apps,
including
including the
the emulator
emulator and
and more.
more.

When
When AndroidAndroid came
came on
on thethe market,
market, the the most
most widely
widely used
used development
development environment
environment was was
Eclipse
Eclipse combined
combined with
with the
the above
above two
two products,
products, and and itit has
has since
since been
been aa stable
stable and
and efficient
efficient
development
development platform.
platform. When
When II mention
mention EclipseEclipse here,
here, it’s
it’s also
also because
because thethe product
product isis worth
worth
acquainting
acquainting for completely other reasons, as it is generally an effective tool for developing aa
for completely other reasons, as it is generally an effective tool for developing
Java
Java application,
application, andand it’s
it’s in
in every
every way
way an an alternative
alternative toto NetBeans,
NetBeans, and and many
many prefer
prefer Eclipse
Eclipse
rather
rather thanthan NetBeans.
NetBeans. There
There maymay bebe aa long
long discussions
discussions about
about –– andand will
will be
be –– which
which of of the
the
two
two products
products isis the
the best
best and
and inin fact
fact itit isis probably
probably the the product
product thatthat for
for the
the user
user isis the
the best
best
known and has the most experience with. In these books I have
known and has the most experience with. In these books I have used NetBeans everywhere, used NetBeans everywhere,
but
but itit isis good
good to
to know
know that
that there
there isis something
something called called Eclipse
Eclipse andand you
you can
can easily
easily end
end upup in
in
aa development
development organization
organization using
using this
this tool,
tool, especially
especially ifif the
the tasks
tasks relate
relate to
to the
the development
development
of
of apps
apps for for mobile
mobile phones
phones or or other
other mobile
mobile devices.
devices.

The
The two
two products
products Android
Android SDK
SDK and
and Android
Android Tools
Tools come
come from
from Google,
Google, as as isis the
the company
company
behind
behind Android’s
Android’s development.
development. Together
Together with
with these
these products,
products, Google
Google hashas also
also developed
developed an
an
IDE
IDE for
for the
the development
development of of Android
Android applications.
applications. It
It has
has been
been quite
quite aa long
long time
time underway,
underway,
but
but today it has reached a stage where it is quite user-friendly and efficient tool. That’s
today it has reached a stage where it is quite user-friendly and efficient tool. That’s the
the
reason why I’ll use this tool everywhere, a tool which Google calls Android
reason why I’ll use this tool everywhere, a tool which Google calls Android Studio. Studio.

In
In principle,
principle, itit isis quite
quite simple
simple to to install
install Android
Android Studio,
Studio, asas itit isis all
all packed
packed into
into aa single
single
package that can be downloaded and installed instantly, and it is quite
package that can be downloaded and installed instantly, and it is quite easy under Windows, easy under Windows,
whereas
whereas Linux
Linux requires
requires aa little
little more.
more. In In the
the following,
following, II will
will outline
outline what what II have
have done
done to
to
set
set up
up aa development
development environment
environment on on aa Fedora
Fedora machine,
machine, and and it’s
it’s actually
actually not
not easy
easy to
to write
write
aa precise
precise guide,
guide, partly
partly because
because updates
updates and and changes
changes areare constantly
constantly being being added
added andand partly
partly
because
because the commands depend a little of the current Linux distribution. Fortunately, there
the commands depend a little of the current Linux distribution. Fortunately, there
are many guides online, and the best thing to do is follow these instructions,
are many guides online, and the best thing to do is follow these instructions, if it is manuals if it is manuals
of
of recent
recent date.
date. The
The following
following are are therefore
therefore primarily
primarily references
references to to good
good guidelines.
guidelines.

In
In order
order for
for you
you to
to develop
develop Android
Android applications
applications in
in practice,
practice, you
you need
need to
to have
have installed
installed
virtualization
virtualization software, supported by a hardware accelerator, as the emulator otherwise runs
software, supported by a hardware accelerator, as the emulator otherwise runs
intolerably
intolerablyslow.
slow.You
Youcan
cansee
seehow
howat
atthe
thefollowing
followingaddresses
addresses(for
(forFedora
FedoraandandUbuntu,
Ubuntu,respectively):
respectively):

https://fedoraproject.org/wiki/Getting_started_with_virtualization

208
208
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT
JAVA 16: MOBIL PHONES AND ANDROID: Appendix A, installing of Android Studio
JAVA 16: MOBIL PHONES AND ANDROID:
SOFTWARE DEVELOPMENT appendIx a, InstaLLIng oF androId studIo
SOFTWARE DEVELOPMENT appendIx a, InstaLLIng oF androId studIo

https://software.intel.com/en-us/blogs/2012/03/12/how-to-
https://software.intel.com/en-us/blogs/2012/03/12/how-to-
start-intel-hardware-assisted-virtualization-hypervisor-
start-intel-hardware-assisted-virtualization-hypervisor-
on-linux-to-speed-up-intel-android-x86-emulator
on-linux-to-speed-up-intel-android-x86-emulator

The
The emulator
The emulator itself
emulator itself isis
itself is 32
32 bit
32 bit software,
bit software, and
software, and ifif
and if you
you have
you have aaa 64
have 64 bit
64 bit machine
bit machine (whatever
machine (whatever you
(whatever you
you
have),
have), you
have), you should
you should also
should also install
also install a special
install aa special library
special library called
library called ia32-libs.
called ia32-libs. For
ia32-libs. For Fedora
For Fedora you
Fedora you can
you can see
can see how
see how
how
at
at the
the following
following address:
address:
at the following address:

https://ask.fedoraproject.org/en/question/9556/how-do-
https://ask.fedoraproject.org/en/question/9556/how-do-
i-install-32bit-libraries-on-a-64-bit-fedora/
i-install-32bit-libraries-on-a-64-bit-fedora/

and
and for
and for Ubuntu,
for Ubuntu, the
Ubuntu, the following
the following document
following document explains
document explains how,
explains how, and
how, and also
and also how
also how to
how to download
to download and
download and
and
install
install Android
Android Studio:
Studio:
install Android Studio:

http://www.vogella.com/tutorials/Android/article.html
http://www.vogella.com/tutorials/Android/article.html

The
The document
document isis
The document also
also aaa brief
is also brief introduction
brief introduction to
introduction to what
to what Android
what Android is,
Android is, and
is, and also
and also shows
also shows how
shows how to
how to write
to write
write
the
the first
first application.
application.
the first application.

With
With the
With the above
the above referrals
above referrals (or
referrals (or alternatives),
(or alternatives), setting
alternatives), setting up
setting up your
up your development
your development environment
development environment should
environment should
should
run
run without the big challenges, but keep in mind that Android is a dynamic world that
run without
without the
the big
big challenges,
challenges, but
but keep
keep in
in mind
mind that
that Android
Android is
is a
a dynamic
dynamic world
world that isis
that is
constantly
constantly changing.
changing.
constantly changing.

209
209
209

Вам также может понравиться