ANDROID - FROM ZERO TO
HERO
IVO NESKOVIC
ANDROID - FROM ZERO TO HERO
WHO AM I?
▸ An alumnus of CITY College (BSc, MSc)
▸ One of the earliest adopters of Android, working with Android
professionally since day 1
▸ Teaching Mobile Development with Android at CITY College
▸ Building MVPs for Silicon Valley startups for the past couple of
years
▸ Mobile Game Developer in various Game Engines
▸ Gamer =)
2
INTRODUCTION
TO ANDROID
PART #1
3
ANDROID - FROM ZERO TO HERO
OUTLINE
▸ Challenges of Mobile Development
▸ History and versioning of Android
▸ Android Permission System and Mobile Ethics
▸ Introduction to the Android development environment
▸ Fundamental App components
▸ Basic UI Widgets
▸ Laying out UI components
4
ANDROID - FROM ZERO TO HERO
TRADITIONAL VS MOBILE DEVELOPMENT
▸ Consider context and user interaction
▸ Recognise the importance of user experience
▸ Understand the limitations of a touch-based interface
▸ Stick with platform best practices
▸ Pay attention to perceived speed
▸ Break away from long product release-cycles
▸ Bridge the gap between security and accessibility
5
ANDROID - FROM ZERO TO HERO
KEY MOBILE CHALLENGES
▸ Smartphone == small computer from the 90’s
▸ Low processing power
▸ Limited RAM
▸ Intermittent, low bandwidth, high latency data connections
▸ Impact on battery life
6
ANDROID - FROM ZERO TO HERO
WHAT IS ANDROID?
▸ Mobile operating system maintained by Google
▸ Originally purchased from Android, Inc. in 2005
▸ Runs on phones, tablets, watches, TVs, cars, cameras…
▸ Based on Java and Linux
▸ The #1 mobile OS worldwide, but also the #1 OS
worldwide
▸ Code is released periodically as open source
7
ANDROID - FROM ZERO TO HERO
ANDROID VERSION HISTORY
8
Code Name Version Number Release Date
Cupcake 1.5 April 27, 2009
Donut 1.6 September 15, 2009
Eclair 2.0 - 2.1 October 26, 2009
Froyo 2.2 - 2.2.3 May 20, 2010
Gingerbread 2.3 - 2.3.7 December 6, 2010
Honeycomb 3.0 - 3.2.6 February 22, 2011
Ice Cream Sandwich 4.0 - 4.0.4 October 18, 2011
Jelly Bean 4.1 - 4.3.1 July 9, 2012
Kit Kat 4.4 - 4.4.4 October 31, 2013
Lollipop 5.0 - 5.1.1 November 12, 2014
Marshmallow 6.0 - 6.0.1 October 5, 2015
9
ANDROID - FROM ZERO TO HERO
ANDROID VERSION DISTRIBUTION
10
LET’S TALK
ARCHITECTURE
11
12
ANDROID - FROM ZERO TO HERO
THE PERMISSION SYSTEM AND MOBILE ETHICS
▸ Android is a privilege-separated
operating system, in which each
application runs with a distinct
system identity
▸ Additional finer-grained security
features are provided through a
"permission" mechanism that
enforces restrictions on the specific
operations that a particular process
can perform
13
ANDROID - FROM ZERO TO HERO
ANDROID STUDIO
▸ The official IDE for Android application development
▸ replaces previous Eclipse-based environment
▸ based on IntelliJ IDEA
▸ free to download and use
14
ANDROID - FROM ZERO TO HERO
ANDROID VIRTUAL DEVICE (AVD)
▸ Allows to run apps in an emulator
▸ a software simulation of the entire Android tablet, phone,
watch…
▸ Must set up a virtual device first in Android Studio
▸ Alternative: install the app on an actual Android device!
▸ pro: app will run faster, better test of real execution
▸ con: requires an Android device to be plugged into the
development PC
15
16
ANDROID - FROM ZERO TO HERO
APP FUNDAMENTALS
▸ Every Android app is composed of exactly 3 parts
▸ Core framework components that define the app
▸ A manifest file in which components and required
device features are declared
▸ Resources that are separate from the code and allow the
app to gracefully handle different device configurations
17
ANDROID - FROM ZERO TO HERO
CORE FRAMEWORK COMPONENTS
▸ Activities - representing a single screen with a user
interface
▸ Services - run in the background to perform long-running
operations or perform work for remote processes
▸ Content Providers - manage a shared set of data
▸ Broadcast Receivers - respond to system-wide broadcast
announcements
18
ANDROID - FROM ZERO TO HERO
THE MANIFEST FILE
▸ Apps must declare all of their components in this file
▸ Identify any user permissions the app requires, such as Internet
access or read-access to the user's contacts
▸ Declare the minimum API Level required by the app, based on
which APIs the app uses
▸ Declare hardware and software features used or required by the
app, such as a camera, bluetooth services, or a multitouch screen
▸ API libraries the app needs to be linked against (other than the
Android framework APIs), such as the Google Maps library
19
ANDROID - FROM ZERO TO HERO
THE MANIFEST FILE - DECLARING ACTIVITIES
20
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:icon="@drawable/app_icon.png" ... >
<activity android:name="com.example.project.ExampleActivity"
android:label="@string/example_label" ... >
</activity>
...
</application>
</manifest>
ANDROID - FROM ZERO TO HERO
RESOURCES
▸ A good engineer will always
externalise application resources from
code as to increase maintainability
▸ An excellent engineer will also
provide different resources for
different device configurations
▸ Lucky for us Google is filled with
excellent engineers =)
21
ANDROID - FROM ZERO TO HERO
IMPORTANT RESOURCE FOLDERS (SO FAR)
22
Directory Resource Type
drawable/
Bitmap files (.png, .9.png, .jpg, .gif) or XML
files that are compiled into the available drawable
resource subtypes
layout/ XML files that define a user interface layout
menu/
XML files that define application menus, such as an
Options Menu, Context Menu, or Sub Menu
raw/ Arbitrary files to save in their raw form (sound)
values/
XML files that contain simple values, such as strings,
integers, and colors.
ANDROID - FROM ZERO TO HERO
ACCESSING RESOURCES
▸ In xml:
▸ @resource_type/id
▸ examples: @string/hello_word, @drawable/cat
▸ In code:
▸ Using the mysterious R.java class
▸ A static generated class which contains all the id’s of your resources
▸ R.resource_type.id
▸ examples: R.string.hello_world, R.drawable.cat
23
ANDROID - FROM ZERO TO HERO
BYE BYE PIXELS
▸ Your program will be run on a HUGE array of devices with
different hardware specifications including screen size
▸ Screens have densities (ranging from small amounts of
pixels to huge amounts of pixels)
▸ Using pixels will produce a different look depending on
the screen size of the device
24
ANDROID - FROM ZERO TO HERO
WELCOME DENSITY INDEPENDENT PIXELS
▸ DP is an abstract unit that is based on the physical density
of the screen rather than the actual pixels
▸ Scales to uniform dimensions on any screens
▸ When defining font sizes, scaled pixels (sp) are used
instead which also take the user’s font size preference into
consideration (think accessibility)
25
ANDROID - FROM ZERO TO HERO
ACTIVITY
▸ Each activity is given a window in which to draw its user
interface
▸ An application usually consists of multiple activities that
are loosely bound to each other
▸ There must be a “main” activity, the entry point of the app
▸ Each time a new activity starts, the previous activity is
stopped, but the system preserves the activity in a stack
(the "back stack")
26
ANDROID - FROM ZERO TO HERO
UI OVERVIEW
▸ All user interface elements in an Android app are built
using View and ViewGroup objects
▸ View - an object that draws something on the screen that
the user can interact with
▸ ViewGroup - an object that holds other View (and
ViewGroup) objects in order to define the layout of the
interface
▸ Can be declared either in XML layout resources or in code
27
ANDROID - FROM ZERO TO HERO
UI OVERVIEW - VISUALIZED
28
ANDROID - FROM ZERO TO HERO
WRITING UI
▸ Declare UI elements in XML
▸ Better separation of presentation from the code that
controls its behaviour
▸ Instantiate UI elements from code at runtime
▸ Useful for when the UI is dynamic and not know before
hand
29
ANDROID - FROM ZERO TO HERO
TEXT VIEW
▸ An extremely simple view component which displays text
to the user
▸ Notable attribute “android:text”: defines the text to be
shown in the TextView
30
<TextView
android:id=“@+id/tv_hello_world”
android:layout_width=“match_parent"
android:layout_height="wrap_content"
android:text=“@string/hello_world” />
ANDROID - FROM ZERO TO HERO
EDIT TEXT
▸ Allows the user to type text into the app
▸ It can be either single line or multi-line
▸ Touching a text field places the cursor and automatically
displays the keyboard
▸ Allows for a variety of other activities, such as text
selection (cut, copy, paste) and data look-up via auto-
completion
31
ANDROID - FROM ZERO TO HERO
EDIT TEXT
32
<EditText
android:id="@+id/email_address"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="@string/email_hint"
android:inputType="textEmailAddress" />
ANDROID - FROM ZERO TO HERO
EDIT TEXT
▸ Notable attributes:
▸ android:hint - defines a text to be shown when the
user has still not written any text as to hint the text fields
purpose
▸ android:inputType - defines the type of data being
placed in the text field
▸ text, textEmailAddress, textUri, number, phone
▸ textCapSentences, textCapWords, textPassword
33
ANDROID - FROM ZERO TO HERO
IMAGE VIEW
▸ Displays an arbitrary image such as an icon
▸ Notable attribute “android:src”: defines the image
resource to be shown in the ImageView
34
<ImageView
android:id=“@+id/img_splash"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/android" />
ANDROID - FROM ZERO TO HERO
BUTTON
▸ A view consisting of text or an icon (or both text and an
icon) that communicates what action occurs when the user
touches it
▸ Notable attribute “android:text”: defines the text to be
shown in the Button
35
<Button android:id=“@+id/btn_set_alarm”
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/alarm"/>
ANDROID - FROM ZERO TO HERO
BUTTON
▸ Notable attribute “android:src”: defines the image
resource to be shown in the ImageButton
36
<ImageButton android:id=“@+id/btn_set_alarm”
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/clock"/>
ANDROID - FROM ZERO TO HERO
BUTTON
▸ Notable attribute “android:drawableLeft”: defines the
image resource to be shown at the left edge of the
Button
37
<Button android:id=“@+id/btn_set_alarm”
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=“@string/alarm"
android:drawableLeft=“@drawable/clock” />
ANDROID - FROM ZERO TO HERO
TOAST
▸ Provides simple feedback about an operation in a small
popup which disappears over time
▸ Should note be relied upon extensively for important info
▸ time - either Toast.LENGTH_SHORT or
Toast.LENGTH_LONG
38
Toast.makeText(context, “text”, time).show();
Toast.makeText(context, R.string.text, time).show();
ANDROID - FROM ZERO TO HERO
SETTING SCREEN LAYOUT AND RETRIEVING COMPONENTS
▸ Every activity must set its view hierarchy to render on the
screen
▸ setContentView(R.layout.welcome_screen);
▸ Every activity can retrieve any view from its view hierarchy
▸ findViewById(R.id.btn_alarm);
39
ANDROID - FROM ZERO TO HERO
EVENTS
▸ Event - an external stimulus that a program responds to
▸ Common kinds include:
▸ Mouse motion / screen tap, key press
▸ Timer expiring, network data available
▸ Event-driven programming - overall execution of a
program is largely dictated by user events
▸ GUI heavy programs are almost always event-driven
40
ANDROID - FROM ZERO TO HERO
EVENT LOOP
41
ANDROID - FROM ZERO TO HERO
BASIC EVENT LISTENERS
▸ An event listener is an interface in the View class that
contains a single callback method
▸ Called by the Android framework when the View to which
the listener has been registered is triggered by user
interaction (a classic example of an observer pattern)
▸ onClick(View) - called when the user touches the item
▸ onLongClick(View) - called when the user touches and
holds the item
42
ANDROID - FROM ZERO TO HERO
BUTTON CLICK LISTENERS
43
Button alarmButton = (Button) findViewById(R.id.btn_alarm);
alarmButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// I have been clicked;
}
});
alarmButton.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View v) {
// I have been long clicked
return true;
}
});
ANDROID - FROM ZERO TO HERO
HOW DOES ONE SPECIFY WHERE COMPONENTS GO ON THE SCREEN
▸ Absolute positioning (C++, C#, others):
▸ Exactly specifying the position of the component on the screen
using pixels
▸ button.setPosition(75, 0);
▸ Layout Managers (Java, Android, others):
▸ Objects which decide the exact pixels of where a component
should be placed based on some rules
▸ More flexible and general, works well with different device
configurations
44
ANDROID - FROM ZERO TO HERO
LAYOUTS
▸ A layout (ViewGroup) defines the visual structure for a
user interface by providing placement rules for its children
(other ViewGroups or Views)
▸ Each layout file must contain exactly one root element,
which must be a View or ViewGroup object
▸ Add additional layout objects or widgets as child elements
to gradually build a View hierarchy
45
ANDROID - FROM ZERO TO HERO
COMMON LAYOUTS
46
Linear Layout Relative Layout
ANDROID - FROM ZERO TO HERO
LINEAR LAYOUT
▸ A view group that aligns all children in a single direction,
vertically or horizontally
▸ All children of a LinearLayout are stacked one after the
other, vertical orientation positions one child per row and
horizontal orientation positions all children in a single row
▸ Items do not wrap if they reach the end of the screen
▸ Supports complex layouts by using attributes called
gravity and weight
47
ANDROID - FROM ZERO TO HERO
LINEAR LAYOUT
▸ Notable attribute “android:orientation”: defines the
orientation in which the layout should position its children
▸ Possible values “vertical” or “horizontal” (default)
48
<LinearLayout
android:layout_width=“match_parent"
android:layout_height="wrap_content"
android:orientation=“vertical”>
.....
</LinearLayout>
ANDROID - FROM ZERO TO HERO
LINEAR LAYOUT
49
ANDROID - FROM ZERO TO HERO
LET’S TALK ABOUT GRAVITY
▸ Alignment direction that widgets are pulled in
▸ top, bottom, left, right, center,
center_vertical, center_horizontal
▸ Combine gravity with the pipe operator |
▸ Set gravity on the layout to adjust all widgets
▸ Set layout_gravity on an individual widget
50
ANDROID - FROM ZERO TO HERO
GRAVITY
51
ANDROID - FROM ZERO TO HERO
LAYOUT WEIGHT
▸ Gives elements relative sizes by using integers
▸ Widget with weight W gets W/total fraction of total size
▸ Cooking analogy
▸ 2 parts flour, 1 part sugar
52
<Button android:id=“@+id/btn_set_alarm”
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=“@string/alarm"
android:layout_weight=“1” />
ANDROID - FROM ZERO TO HERO
LAYOUT WEIGHT
53
<Button
…
android:layout_weight=“1” />
<Button
…
android:layout_weight=“1” />
<Button
…
android:layout_weight=“3” />
ANDROID - FROM ZERO TO HERO
SIZING AN INDIVIDUAL VIEW
▸ width and height of a view can be:
▸ wrap_content - exactly large enough to fit the view’s
content
▸ match_parent - as wide or tall as 100% of the layout it
resides in
▸ a specific fixed value - example 64dp (not usually
recommended)
54
ANDROID - FROM ZERO TO HERO
NESTED LAYOUTS
▸ To produce a more complicated appearance, layouts can
be nested
▸ Layout inside a layout
▸ Possible because all ViewGroups are also Views
55
ANDROID - FROM ZERO TO HERO
RELATIVE LAYOUT
▸ A view group that displays child views in relative positions,
either specified as relative to sibling elements or in
positions relative to the parent RelativeLayout area
▸ It eliminates nested view groups and keeps the layout
hierarchy flat which improves performance
▸ One RelativeLayout can replace using several nested
LinearLayout groups
56
ANDROID - FROM ZERO TO HERO
RELATIVE ANCHOR POINTS
▸ Properties for x and y relative to another view (provide
view id):
▸ layout_below, above, toLeftOf, toRightOf
▸ Properties for x and y relative to the parent container
(boolean values)
▸ layout_alignParentTop, Bottom, Left, Right
▸ layout_centerHorizontal, Vertical, InParent
57
ADVANCED
ANDROID TOPICS
PART #2
58
HTTPS://GITHUB.COM/TRUMPETS/MC-ADVANCEDANDROIDTOPICS
ANDROID - FROM ZERO TO HERO
OUTLINE
▸ Adapter Layouts
▸ Adapter
▸ Handling Adapter Events
▸ Multi-screen Apps
▸ Intent
▸ Building Intents
▸ Keeping apps responsive
▸ Android process model
▸ Background operations with AsyncTasks
59
ANDROID - FROM ZERO TO HERO
BUILDING LAYOUTS WITH AN ADAPTER
▸ When the content of the layout is dynamic or not pre-
determined, one can use AdapterView to populate the
layout with views at runtime
▸ Using an Adapter to bind the data to the layout
▸ ListView - a view group that displays a list of scrollable
items
▸ GridView - a ViewGroup that displays items in a two-
dimensional, scrollable grid
60
ANDROID - FROM ZERO TO HERO
COMMON ADAPTER LAYOUTS
61
List View Grid View
ANDROID - FROM ZERO TO HERO
ADAPTER
▸ Behaves as a middleman between the data source and the
AdapterView layout (a classic example of an adapter
pattern)
▸ Provides access to the data items
▸ Responsible for making a View for each item in the data
set
▸ Also used by some UI components to provide their data
(eg. Spinner)
62
ANDROID - FROM ZERO TO HERO
COMMON ADAPTERS
▸ ArrayAdapter - backed by an array of arbitrary objects
▸ CursorAdapter - exposes data from a database Cursor
▸ SimpleCursorAdapter - an easy adapter to map
columns from a cursor to TextViews or ImageViews
63
ArrayAdapter<String> adapter = new
ArrayAdapter<String>(activity, layout, array);
listView.setAdapter(adapter);
ANDROID - FROM ZERO TO HERO
ADAPTER VIEW EVENTS
▸ setOnItemClickListener(AdapterView.OnItemClickList
ener)
▸ Called when an item has been clicked
▸ setOnItemLongClickListener(AdapterView.OnItemLongC
lickListener)
▸ Called when an item has been clicked and held
▸ setOnItemSelectedListener(AdapterView.OnItemSelect
edListener)
▸ Called when an item in the list has been selected
64
ANDROID - FROM ZERO TO HERO
ON ITEM CLICKED LISTENER
65
ListView listView = (ListView) findViewById(R.id.list);
listView.setOnItemClickedListener(
new AdapterView.OnItemClickedListener() {
@Override
public void onItemClick(AdapterView<?> list,
View row,
int index,
long rowId) {
// Code to run when the item is clicked
}
}
);
ANDROID - FROM ZERO TO HERO
CHANGES TO ADAPTER DATA
▸ If the data in the collection backing the adapter changes,
the adapter must be notified
66
ArrayList<String> items = …;
ArrayAdapter<String> adapter = …;
listView.setAdapter(adapter);
// change data
items.remove(0);
// notify the adapter
adapter.notifyDataSetChanged();
ANDROID - FROM ZERO TO HERO
CUSTOM ADAPTER LAYOUTS
67
ANDROID - FROM ZERO TO HERO
CUSTOM ADAPTER LAYOUTS
▸ Provide the item layout in XML just like Activity layouts
▸ Either
▸ 1) Instruct the ArrayAdapter how to supply the item
text to each item
▸ 2) Build a custom adapter by extending BaseAdapter
68
ANDROID - FROM ZERO TO HERO
CUSTOM ARRAY ADAPTER
69
<LinearLayout android:orientation=“horizontal” …>
<ImageView … />
<TextView android:id=“@+id/tv_label” … />
</LinearLayout>
ArrayAdapter<String> adapter =
new ArrayAdapter<String>(
activity,
R.layout.item_layout,
R.id.tv_label,
data
);
item_layout.xml
ANDROID - FROM ZERO TO HERO
EXTENDING BASE ADAPTER
▸ Must implement four important methods of every adapter
▸ getCount() - return how many items are in total in the data set
▸ getItem(position) - return the item from the data set at the
specified position
▸ getItemId(position) - get the row id associated with the
specified position in the list
▸ getView(position, convertView, parent) - get a view
that displays the data at the specified position in the data set
70
ANDROID - FROM ZERO TO HERO
EXAMPLE BASE ADAPTER
71
public class Item {
public String name;
public int quantity;
}
<LinearLayout android:orientation=“horizontal” …>
<TextView android:id=“@+id/tv_name” … />
<TextView android:id=“@+id/tv_quantity” … />
</LinearLayout>
ANDROID - FROM ZERO TO HERO
EXAMPLE BASE ADAPTER
72
public class ItemAdapter extends BaseAdapter<Item> {
private List<Item> items = …;
@Override
public int getCount() {
return items.size();
}
@Override
public Object getItem(int position) {
return items.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
}
ANDROID - FROM ZERO TO HERO
EXAMPLE BASE ADAPTER - THE HEAVY LIFTING
73
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(context);
convertView = inflater.inflate(
R.layout.item_layout, parent, false);
}
Item item = (Item) this.getItem(position);
TextView nameTextView = (TextView)
convertView.findViewById(R.id.tv_name);
TextView quantityTextView = (TextView)
convertView.findViewById(R.id.tv_quantity);
nameTextView.setText(item.name);
quantityTextView(String.valueOf(item.quantity);
return convertView;
}
MULTI-SCREEN
APPS
74
ANDROID - FROM ZERO TO HERO
MULTI-SCREEN APPS
▸ Many apps have multiple screens (activities)
▸ An activity A can launch another activity B in response to
an event
▸ Activity A can pass data to activity B
▸ Activity B can return data back to activity A
▸ Each activity has a Java class and an XML layout
▸ Remember: AndroidManifest should list all activities
75
ANDROID - FROM ZERO TO HERO
MULTI-SCREEN APPS
76
ANDROID - FROM ZERO TO HERO
INTENT
▸ An object representing a desired action
▸ Used to request an action from another app component
▸ Three fundamental use cases
▸ Start an Activity - startActivity()
▸ Start a Service - startService()
▸ Deliver a broadcast - sendBroadcast()
77
ANDROID - FROM ZERO TO HERO
INTENT
▸ The component can be in the same app or another app
installed on the same device
▸ Can store extra data to pass to the component
78
ANDROID - FROM ZERO TO HERO
INTENT TYPES
▸ Explicit Intent
▸ Specifies the component to start explicitly by referring to
its fully-qualified class name
▸ Typically used for starting components which are part of the
same app
▸ When the system receives an explicit Intent it immediately
starts the app component specified in the Intent
▸ We will be using explicits Intents today!
79
ANDROID - FROM ZERO TO HERO
INTENT TYPES
▸ Implicit Intent
▸ Declare a general action to perform which allows all the
components on the device to handle it
▸ Typically used for communicating with components which offer
commonly present functionality in mobile devices (eg. Maps, Browser)
▸ When the system receives an implicit intent it consults with all the
declared IntentFilters in all the AndroidManifests on the device
▸ This is not important for this course but it is included here as a starting
point for further research!
80
ANDROID - FROM ZERO TO HERO
BUILDING AN INTENT
▸ Component name - mandatory for explicit intents, meaning that the
intent should be delivered only to the app component defined by it
▸ Action - mandatory for implicit intents, specifying the action to
perform (eg. view, pick, send…)
▸ Broadcast intents report the action which took place
▸ You can specify your custom actions for your own components
▸ Common actions include ACTION_VIEW / ACTION_SEND
▸ Custom actions should include the package name
81
final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
ANDROID - FROM ZERO TO HERO
BUILDING AN INTENT
▸ Data - the URI that references the data to be acted upon (eg. open THIS
image) or the MIME type of that data
▸ Category - a string containing additional info about the kind of
component to launch (eg. CATEGORY_BROWSABLE)
▸ Extras - key-value pairs that carry additional information required to
accomplish the requested action
▸ Components should define their own extras including the package
name
▸ Flags - metadata in the Intent which instruct the system on how to
launch an activity
82
ANDROID - FROM ZERO TO HERO
INTENT EXAMPLES
83
// Executed in an Activity, so 'this' is the Context
Intent intent = new Intent(this, GreetingActivity.class);
intent.putExtra(GreetingActivity.EXTRA_NAME, “Ivo”);
startActivity(intent);
ANDROID - FROM ZERO TO HERO
EXTRACTING INTENT INFO
84
public class GreetingActivity extends Activity {
...
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(...);
Intent intent = getIntent();
String name = intent.getStringExtra(EXTRA_NAME);
}
}
ANDROID - FROM ZERO TO HERO
GETTING RESULT FROM AN ACTIVITY
▸ Calling activity wants to get an answer from the called activity
▸ Use startActivityForResult(int requestCode)
instead of startActivity()
▸ The method returns immediately but later on when the called
activity finishes onActivityResult() will be called with
the answer from the called activity
▸ The called activity must set the answer before finishing
▸ Example: Starting the People app to select a contact
85
ANDROID - FROM ZERO TO HERO
STARTING AN ACTIVITY FOR A RESULT
86
static final int PICK_CONTACT_REQUEST = 1; // The request code
...
private void pickContact() {
Intent pickContactIntent = new Intent(Intent.ACTION_PICK,
Uri.parse(“content://contacts”));
// Show user only contacts w/ phone numbers
pickContactIntent.setType(Phone.CONTENT_TYPE);
startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);
}
ANDROID - FROM ZERO TO HERO
WAITING FOR A RESULT
87
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
// Check which request it is that we're responding to
if (requestCode == PICK_CONTACT_REQUEST) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// Get the URI that points to the selected contact
Uri contactUri = data.getData();
String stringExtra = data.getStringExtra(KEY);
// do something with the returned data...
// activities can return data in different format
// make sure you know what that format is
}
}
}
ANDROID - FROM ZERO TO HERO
SENDING BACK A RESULT
88
public class NameChooserActivity extends Activity {
...
public void onClick(View view) {
Intent intent = new Intent();
intent.putExtra(EXTRA_NAME);
setResult(RESULT_OK, intent);
finish(); // calls onDestroy
}
}
ANDROID - FROM ZERO TO HERO
ACTIVITY STACK
89
BUILDING
RESPONSIVE APPS
90
ANDROID - FROM ZERO TO HERO
KEEPING APPS RESPONSIVE
▸ Slow and sluggish performance is the #1 reason why your users
will uninstall your app
▸ The Android system has a built-in guard which protects the users
from non-responsive applications
▸ After an app is not responsive for a considerable amount of time
(a couple of secs) the system displays the dreadful Application
Not Responding (ANR) dialog
▸ No response to input in 5 secs
▸ A BroadcastReceiver taking more than 10 secs
91
ANDROID - FROM ZERO TO HERO
ANR == UNINSTALL
92
ANDROID - FROM ZERO TO HERO
PERCEIVED SPEED RESEARCH
▸ 100 to 200ms is the threshold beyond which users will perceive
slowness in an app
▸ If an app is performing background work as a response to user
input, always show a progress dialog (ProgressBar)
▸ If an app has a time consuming start-up process (setting up initial
data, server communication etc) either:
▸ Show a splash screen with a progress indicator
▸ Render the main UI as fast as possible with a progress indicator
and filling in the new data asynchronously as it arrives
93
ANDROID - FROM ZERO TO HERO
KEEPING APPS RESPONSIVE
▸ All data persistence operations take time
▸ All network operations take time
▸ All graphic manipulation operations take time
▸ Need to delve deeper in the Android process model
94
ANDROID - FROM ZERO TO HERO
ANDROID PROCESS MODEL
▸ Android apps are single threaded apps
▸ UI thread is their main thread
▸ drawing UI elements, dispatching events
▸ Android’s single-threaded model has two rules
▸ 1) Do not block the UI thread
▸ 2) Do not access the Android toolkit from outside the UI
thread
95
ANDROID - FROM ZERO TO HERO
ANDROID PROCESS MODEL
96
public class ExampleActivity extends Activity {
...
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
Bitmap b = loadImageFromNetwork("http://example.com/image.png");
mImageView.setImageBitmap(b);
}
}).start();
}
}
public class ExampleActivity extends Activity {
...
public void onClick(View v) {
Bitmap b = loadImageFromNetwork("http://example.com/image.png");
mImageView.setImageBitmap(b);
}
}
BAD - RUNNING A LONG OPERATION ON THE UI THREAD
BAD - ACCESSING THE ANDROID UI TOOLKIT FROM AN OUTSIDE THREAD
ANDROID - FROM ZERO TO HERO
ANDROID PROCESS MODEL
97
public class ExampleActivity extends Activity {
...
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap b = loadImageFromNetwork("http://example.com/image.png");
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(bitmap);
}
});
}
}).start();
}
}
GOOD
ANDROID - FROM ZERO TO HERO
ASYNC TASK
▸ We need worker threads that are allowed to interact with the Android
UI Toolkit
▸ AsyncTask enables proper and easy use of the UI thread
▸ A utility that supports running operations in the background in a
worker thread and delivering the results on the UI thread without
having to manipulate threads and and handlers
▸ Useful for long running operations but one that span at most a minute
or max two
▸ All AsyncTasks in the system are executed sequentially on a single
worker thread (no parallelism)
98
ANDROID - FROM ZERO TO HERO 99
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
// Do the long-running work in here
// !!! Executed in background
protected Long doInBackground(URL... urls) {
long totalSize = 0;
for (int i = 0; i < urls.length; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
}
return totalSize;
}
// This is called each time you call publishProgress()
// !!! Executed on UI thread
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
// This is called when doInBackground() is finished
// !!! Executed on UI thread
protected void onPostExecute(Long result) {
showNotification("Downloaded " + result + " bytes");
}
}
new DownloadFilesTask().execute(url1, url2, url3);
NETWORK
COMMUNICATION
100
101URL url = new URL(CREATE_STUDENTS_URL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.addRequestProperty("Content-Type", "application/json");
Student student = new Student();
student.setFirstName(firstName);
student.setLastName(lastName);
student.setAge(age);
String studentJson = new Gson().toJson(student);
BufferedWriter writer = new BufferedWriter(new
OutputStreamWriter(conn.getOutputStream(), "UTF-8"));
writer.write(studentJson);
writer.flush();
writer.close();
conn.getOutputStream().close();
// Starts the post
conn.connect();
int response = conn.getResponseCode();
ANDROID - FROM ZERO TO HERO
RETROFIT
▸ Retrofit turns our HTTP API into a Java interface
▸ Use annotations to describe the HTTP request:
▸ URL parameter replacement and query parameter
support
▸ Object conversion to request body (e.g., JSON)
▸ Calls can be executed either synchronously or
asynchronously
102
ANDROID - FROM ZERO TO HERO
ADDING RETROFIT TO A PROJECT
103
dependencies {
...
compile "com.squareup.retrofit2:retrofit:2.0.1"
compile "com.squareup.retrofit2:converter-gson:2.0.1"
...
}
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
app/build.gradle
proguard-rules.pro
<uses-permission android:name="android.permission.INTERNET" />
AndroidManifest.xml
ANDROID - FROM ZERO TO HERO
DEFINE YOUR API IN CODE
104
public interface StudentsApi {
static final String BASE_URL = "http://students-sdmdcity.rhcloud.com/rest/";
static final String STUDENTS_URL = "students";
@GET(STUDENTS_URL)
Call<List<Student>> getAllStudents();
@POST(STUDENTS_URL)
Call<Void> createStudent(@Body Student student);
}
ANDROID - FROM ZERO TO HERO
CREATE YOU API INSTANCE
105
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(StudentsApi.BASE_URL)
// automatic JSON conversion using Googles Gson [so cool!]
.addConverterFactory(GsonConverterFactory.create())
.build();
StudentsApi studentsApi = retrofit.create(StudentsApi.class);
ANDROID - FROM ZERO TO HERO
FINALLY, EXECUTE THE CALL
106
// If using enqueue() - this is asynchronously executed on a background
// thread
studentsApi.createStudent(student).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
int responseCode = response.code();

Void returnData = response.body();
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
}
});
// If using execute() - this is synchronously executed on the calling
// thread
Response<Void> response = studentsApi.createStudent(student).execute();
ANDROID - FROM ZERO TO HERO
CONSUMING REST WEB SERVICES - GENERAL RULES
▸ HTTP defines methods (sometimes referred to as verbs) to
indicate the desired action to be performed on the
identified resource
▸ POST - most-often utilised to create new resources
▸ GET - used to read (or retrieve) a representation of a
resource
▸ PUT - most-often utilised for updating existing resources
▸ DELETE - used to delete a resource identified by a URI
107
ANDROID - FROM ZERO TO HERO
CONSUMING WEB SERVICES - HTTP STATUS CODES
▸ 200 OK - everything was fine with the request
▸ 204 No Content - everything was fine with the request, but the
server returned no content
▸ 400 Bad Request - the request to the server contains a syntax error
and was not understood by the server
▸ 403 Forbidden - the resource you are trying to access if forbidden
for the current authorised user
▸ 404 Not Found - the resource you are trying to access does not
exist on the server
108

Android - From Zero to Hero @ DEVit 2017

  • 1.
    ANDROID - FROMZERO TO HERO IVO NESKOVIC
  • 2.
    ANDROID - FROMZERO TO HERO WHO AM I? ▸ An alumnus of CITY College (BSc, MSc) ▸ One of the earliest adopters of Android, working with Android professionally since day 1 ▸ Teaching Mobile Development with Android at CITY College ▸ Building MVPs for Silicon Valley startups for the past couple of years ▸ Mobile Game Developer in various Game Engines ▸ Gamer =) 2
  • 3.
  • 4.
    ANDROID - FROMZERO TO HERO OUTLINE ▸ Challenges of Mobile Development ▸ History and versioning of Android ▸ Android Permission System and Mobile Ethics ▸ Introduction to the Android development environment ▸ Fundamental App components ▸ Basic UI Widgets ▸ Laying out UI components 4
  • 5.
    ANDROID - FROMZERO TO HERO TRADITIONAL VS MOBILE DEVELOPMENT ▸ Consider context and user interaction ▸ Recognise the importance of user experience ▸ Understand the limitations of a touch-based interface ▸ Stick with platform best practices ▸ Pay attention to perceived speed ▸ Break away from long product release-cycles ▸ Bridge the gap between security and accessibility 5
  • 6.
    ANDROID - FROMZERO TO HERO KEY MOBILE CHALLENGES ▸ Smartphone == small computer from the 90’s ▸ Low processing power ▸ Limited RAM ▸ Intermittent, low bandwidth, high latency data connections ▸ Impact on battery life 6
  • 7.
    ANDROID - FROMZERO TO HERO WHAT IS ANDROID? ▸ Mobile operating system maintained by Google ▸ Originally purchased from Android, Inc. in 2005 ▸ Runs on phones, tablets, watches, TVs, cars, cameras… ▸ Based on Java and Linux ▸ The #1 mobile OS worldwide, but also the #1 OS worldwide ▸ Code is released periodically as open source 7
  • 8.
    ANDROID - FROMZERO TO HERO ANDROID VERSION HISTORY 8 Code Name Version Number Release Date Cupcake 1.5 April 27, 2009 Donut 1.6 September 15, 2009 Eclair 2.0 - 2.1 October 26, 2009 Froyo 2.2 - 2.2.3 May 20, 2010 Gingerbread 2.3 - 2.3.7 December 6, 2010 Honeycomb 3.0 - 3.2.6 February 22, 2011 Ice Cream Sandwich 4.0 - 4.0.4 October 18, 2011 Jelly Bean 4.1 - 4.3.1 July 9, 2012 Kit Kat 4.4 - 4.4.4 October 31, 2013 Lollipop 5.0 - 5.1.1 November 12, 2014 Marshmallow 6.0 - 6.0.1 October 5, 2015
  • 9.
  • 10.
    ANDROID - FROMZERO TO HERO ANDROID VERSION DISTRIBUTION 10
  • 11.
  • 12.
  • 13.
    ANDROID - FROMZERO TO HERO THE PERMISSION SYSTEM AND MOBILE ETHICS ▸ Android is a privilege-separated operating system, in which each application runs with a distinct system identity ▸ Additional finer-grained security features are provided through a "permission" mechanism that enforces restrictions on the specific operations that a particular process can perform 13
  • 14.
    ANDROID - FROMZERO TO HERO ANDROID STUDIO ▸ The official IDE for Android application development ▸ replaces previous Eclipse-based environment ▸ based on IntelliJ IDEA ▸ free to download and use 14
  • 15.
    ANDROID - FROMZERO TO HERO ANDROID VIRTUAL DEVICE (AVD) ▸ Allows to run apps in an emulator ▸ a software simulation of the entire Android tablet, phone, watch… ▸ Must set up a virtual device first in Android Studio ▸ Alternative: install the app on an actual Android device! ▸ pro: app will run faster, better test of real execution ▸ con: requires an Android device to be plugged into the development PC 15
  • 16.
  • 17.
    ANDROID - FROMZERO TO HERO APP FUNDAMENTALS ▸ Every Android app is composed of exactly 3 parts ▸ Core framework components that define the app ▸ A manifest file in which components and required device features are declared ▸ Resources that are separate from the code and allow the app to gracefully handle different device configurations 17
  • 18.
    ANDROID - FROMZERO TO HERO CORE FRAMEWORK COMPONENTS ▸ Activities - representing a single screen with a user interface ▸ Services - run in the background to perform long-running operations or perform work for remote processes ▸ Content Providers - manage a shared set of data ▸ Broadcast Receivers - respond to system-wide broadcast announcements 18
  • 19.
    ANDROID - FROMZERO TO HERO THE MANIFEST FILE ▸ Apps must declare all of their components in this file ▸ Identify any user permissions the app requires, such as Internet access or read-access to the user's contacts ▸ Declare the minimum API Level required by the app, based on which APIs the app uses ▸ Declare hardware and software features used or required by the app, such as a camera, bluetooth services, or a multitouch screen ▸ API libraries the app needs to be linked against (other than the Android framework APIs), such as the Google Maps library 19
  • 20.
    ANDROID - FROMZERO TO HERO THE MANIFEST FILE - DECLARING ACTIVITIES 20 <?xml version="1.0" encoding="utf-8"?> <manifest ... > <application android:icon="@drawable/app_icon.png" ... > <activity android:name="com.example.project.ExampleActivity" android:label="@string/example_label" ... > </activity> ... </application> </manifest>
  • 21.
    ANDROID - FROMZERO TO HERO RESOURCES ▸ A good engineer will always externalise application resources from code as to increase maintainability ▸ An excellent engineer will also provide different resources for different device configurations ▸ Lucky for us Google is filled with excellent engineers =) 21
  • 22.
    ANDROID - FROMZERO TO HERO IMPORTANT RESOURCE FOLDERS (SO FAR) 22 Directory Resource Type drawable/ Bitmap files (.png, .9.png, .jpg, .gif) or XML files that are compiled into the available drawable resource subtypes layout/ XML files that define a user interface layout menu/ XML files that define application menus, such as an Options Menu, Context Menu, or Sub Menu raw/ Arbitrary files to save in their raw form (sound) values/ XML files that contain simple values, such as strings, integers, and colors.
  • 23.
    ANDROID - FROMZERO TO HERO ACCESSING RESOURCES ▸ In xml: ▸ @resource_type/id ▸ examples: @string/hello_word, @drawable/cat ▸ In code: ▸ Using the mysterious R.java class ▸ A static generated class which contains all the id’s of your resources ▸ R.resource_type.id ▸ examples: R.string.hello_world, R.drawable.cat 23
  • 24.
    ANDROID - FROMZERO TO HERO BYE BYE PIXELS ▸ Your program will be run on a HUGE array of devices with different hardware specifications including screen size ▸ Screens have densities (ranging from small amounts of pixels to huge amounts of pixels) ▸ Using pixels will produce a different look depending on the screen size of the device 24
  • 25.
    ANDROID - FROMZERO TO HERO WELCOME DENSITY INDEPENDENT PIXELS ▸ DP is an abstract unit that is based on the physical density of the screen rather than the actual pixels ▸ Scales to uniform dimensions on any screens ▸ When defining font sizes, scaled pixels (sp) are used instead which also take the user’s font size preference into consideration (think accessibility) 25
  • 26.
    ANDROID - FROMZERO TO HERO ACTIVITY ▸ Each activity is given a window in which to draw its user interface ▸ An application usually consists of multiple activities that are loosely bound to each other ▸ There must be a “main” activity, the entry point of the app ▸ Each time a new activity starts, the previous activity is stopped, but the system preserves the activity in a stack (the "back stack") 26
  • 27.
    ANDROID - FROMZERO TO HERO UI OVERVIEW ▸ All user interface elements in an Android app are built using View and ViewGroup objects ▸ View - an object that draws something on the screen that the user can interact with ▸ ViewGroup - an object that holds other View (and ViewGroup) objects in order to define the layout of the interface ▸ Can be declared either in XML layout resources or in code 27
  • 28.
    ANDROID - FROMZERO TO HERO UI OVERVIEW - VISUALIZED 28
  • 29.
    ANDROID - FROMZERO TO HERO WRITING UI ▸ Declare UI elements in XML ▸ Better separation of presentation from the code that controls its behaviour ▸ Instantiate UI elements from code at runtime ▸ Useful for when the UI is dynamic and not know before hand 29
  • 30.
    ANDROID - FROMZERO TO HERO TEXT VIEW ▸ An extremely simple view component which displays text to the user ▸ Notable attribute “android:text”: defines the text to be shown in the TextView 30 <TextView android:id=“@+id/tv_hello_world” android:layout_width=“match_parent" android:layout_height="wrap_content" android:text=“@string/hello_world” />
  • 31.
    ANDROID - FROMZERO TO HERO EDIT TEXT ▸ Allows the user to type text into the app ▸ It can be either single line or multi-line ▸ Touching a text field places the cursor and automatically displays the keyboard ▸ Allows for a variety of other activities, such as text selection (cut, copy, paste) and data look-up via auto- completion 31
  • 32.
    ANDROID - FROMZERO TO HERO EDIT TEXT 32 <EditText android:id="@+id/email_address" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/email_hint" android:inputType="textEmailAddress" />
  • 33.
    ANDROID - FROMZERO TO HERO EDIT TEXT ▸ Notable attributes: ▸ android:hint - defines a text to be shown when the user has still not written any text as to hint the text fields purpose ▸ android:inputType - defines the type of data being placed in the text field ▸ text, textEmailAddress, textUri, number, phone ▸ textCapSentences, textCapWords, textPassword 33
  • 34.
    ANDROID - FROMZERO TO HERO IMAGE VIEW ▸ Displays an arbitrary image such as an icon ▸ Notable attribute “android:src”: defines the image resource to be shown in the ImageView 34 <ImageView android:id=“@+id/img_splash" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android" />
  • 35.
    ANDROID - FROMZERO TO HERO BUTTON ▸ A view consisting of text or an icon (or both text and an icon) that communicates what action occurs when the user touches it ▸ Notable attribute “android:text”: defines the text to be shown in the Button 35 <Button android:id=“@+id/btn_set_alarm” android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/alarm"/>
  • 36.
    ANDROID - FROMZERO TO HERO BUTTON ▸ Notable attribute “android:src”: defines the image resource to be shown in the ImageButton 36 <ImageButton android:id=“@+id/btn_set_alarm” android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/clock"/>
  • 37.
    ANDROID - FROMZERO TO HERO BUTTON ▸ Notable attribute “android:drawableLeft”: defines the image resource to be shown at the left edge of the Button 37 <Button android:id=“@+id/btn_set_alarm” android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=“@string/alarm" android:drawableLeft=“@drawable/clock” />
  • 38.
    ANDROID - FROMZERO TO HERO TOAST ▸ Provides simple feedback about an operation in a small popup which disappears over time ▸ Should note be relied upon extensively for important info ▸ time - either Toast.LENGTH_SHORT or Toast.LENGTH_LONG 38 Toast.makeText(context, “text”, time).show(); Toast.makeText(context, R.string.text, time).show();
  • 39.
    ANDROID - FROMZERO TO HERO SETTING SCREEN LAYOUT AND RETRIEVING COMPONENTS ▸ Every activity must set its view hierarchy to render on the screen ▸ setContentView(R.layout.welcome_screen); ▸ Every activity can retrieve any view from its view hierarchy ▸ findViewById(R.id.btn_alarm); 39
  • 40.
    ANDROID - FROMZERO TO HERO EVENTS ▸ Event - an external stimulus that a program responds to ▸ Common kinds include: ▸ Mouse motion / screen tap, key press ▸ Timer expiring, network data available ▸ Event-driven programming - overall execution of a program is largely dictated by user events ▸ GUI heavy programs are almost always event-driven 40
  • 41.
    ANDROID - FROMZERO TO HERO EVENT LOOP 41
  • 42.
    ANDROID - FROMZERO TO HERO BASIC EVENT LISTENERS ▸ An event listener is an interface in the View class that contains a single callback method ▸ Called by the Android framework when the View to which the listener has been registered is triggered by user interaction (a classic example of an observer pattern) ▸ onClick(View) - called when the user touches the item ▸ onLongClick(View) - called when the user touches and holds the item 42
  • 43.
    ANDROID - FROMZERO TO HERO BUTTON CLICK LISTENERS 43 Button alarmButton = (Button) findViewById(R.id.btn_alarm); alarmButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // I have been clicked; } }); alarmButton.setOnLongClickListener(new View.OnLongClickListener() { public boolean onLongClick(View v) { // I have been long clicked return true; } });
  • 44.
    ANDROID - FROMZERO TO HERO HOW DOES ONE SPECIFY WHERE COMPONENTS GO ON THE SCREEN ▸ Absolute positioning (C++, C#, others): ▸ Exactly specifying the position of the component on the screen using pixels ▸ button.setPosition(75, 0); ▸ Layout Managers (Java, Android, others): ▸ Objects which decide the exact pixels of where a component should be placed based on some rules ▸ More flexible and general, works well with different device configurations 44
  • 45.
    ANDROID - FROMZERO TO HERO LAYOUTS ▸ A layout (ViewGroup) defines the visual structure for a user interface by providing placement rules for its children (other ViewGroups or Views) ▸ Each layout file must contain exactly one root element, which must be a View or ViewGroup object ▸ Add additional layout objects or widgets as child elements to gradually build a View hierarchy 45
  • 46.
    ANDROID - FROMZERO TO HERO COMMON LAYOUTS 46 Linear Layout Relative Layout
  • 47.
    ANDROID - FROMZERO TO HERO LINEAR LAYOUT ▸ A view group that aligns all children in a single direction, vertically or horizontally ▸ All children of a LinearLayout are stacked one after the other, vertical orientation positions one child per row and horizontal orientation positions all children in a single row ▸ Items do not wrap if they reach the end of the screen ▸ Supports complex layouts by using attributes called gravity and weight 47
  • 48.
    ANDROID - FROMZERO TO HERO LINEAR LAYOUT ▸ Notable attribute “android:orientation”: defines the orientation in which the layout should position its children ▸ Possible values “vertical” or “horizontal” (default) 48 <LinearLayout android:layout_width=“match_parent" android:layout_height="wrap_content" android:orientation=“vertical”> ..... </LinearLayout>
  • 49.
    ANDROID - FROMZERO TO HERO LINEAR LAYOUT 49
  • 50.
    ANDROID - FROMZERO TO HERO LET’S TALK ABOUT GRAVITY ▸ Alignment direction that widgets are pulled in ▸ top, bottom, left, right, center, center_vertical, center_horizontal ▸ Combine gravity with the pipe operator | ▸ Set gravity on the layout to adjust all widgets ▸ Set layout_gravity on an individual widget 50
  • 51.
    ANDROID - FROMZERO TO HERO GRAVITY 51
  • 52.
    ANDROID - FROMZERO TO HERO LAYOUT WEIGHT ▸ Gives elements relative sizes by using integers ▸ Widget with weight W gets W/total fraction of total size ▸ Cooking analogy ▸ 2 parts flour, 1 part sugar 52 <Button android:id=“@+id/btn_set_alarm” android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=“@string/alarm" android:layout_weight=“1” />
  • 53.
    ANDROID - FROMZERO TO HERO LAYOUT WEIGHT 53 <Button … android:layout_weight=“1” /> <Button … android:layout_weight=“1” /> <Button … android:layout_weight=“3” />
  • 54.
    ANDROID - FROMZERO TO HERO SIZING AN INDIVIDUAL VIEW ▸ width and height of a view can be: ▸ wrap_content - exactly large enough to fit the view’s content ▸ match_parent - as wide or tall as 100% of the layout it resides in ▸ a specific fixed value - example 64dp (not usually recommended) 54
  • 55.
    ANDROID - FROMZERO TO HERO NESTED LAYOUTS ▸ To produce a more complicated appearance, layouts can be nested ▸ Layout inside a layout ▸ Possible because all ViewGroups are also Views 55
  • 56.
    ANDROID - FROMZERO TO HERO RELATIVE LAYOUT ▸ A view group that displays child views in relative positions, either specified as relative to sibling elements or in positions relative to the parent RelativeLayout area ▸ It eliminates nested view groups and keeps the layout hierarchy flat which improves performance ▸ One RelativeLayout can replace using several nested LinearLayout groups 56
  • 57.
    ANDROID - FROMZERO TO HERO RELATIVE ANCHOR POINTS ▸ Properties for x and y relative to another view (provide view id): ▸ layout_below, above, toLeftOf, toRightOf ▸ Properties for x and y relative to the parent container (boolean values) ▸ layout_alignParentTop, Bottom, Left, Right ▸ layout_centerHorizontal, Vertical, InParent 57
  • 58.
  • 59.
    ANDROID - FROMZERO TO HERO OUTLINE ▸ Adapter Layouts ▸ Adapter ▸ Handling Adapter Events ▸ Multi-screen Apps ▸ Intent ▸ Building Intents ▸ Keeping apps responsive ▸ Android process model ▸ Background operations with AsyncTasks 59
  • 60.
    ANDROID - FROMZERO TO HERO BUILDING LAYOUTS WITH AN ADAPTER ▸ When the content of the layout is dynamic or not pre- determined, one can use AdapterView to populate the layout with views at runtime ▸ Using an Adapter to bind the data to the layout ▸ ListView - a view group that displays a list of scrollable items ▸ GridView - a ViewGroup that displays items in a two- dimensional, scrollable grid 60
  • 61.
    ANDROID - FROMZERO TO HERO COMMON ADAPTER LAYOUTS 61 List View Grid View
  • 62.
    ANDROID - FROMZERO TO HERO ADAPTER ▸ Behaves as a middleman between the data source and the AdapterView layout (a classic example of an adapter pattern) ▸ Provides access to the data items ▸ Responsible for making a View for each item in the data set ▸ Also used by some UI components to provide their data (eg. Spinner) 62
  • 63.
    ANDROID - FROMZERO TO HERO COMMON ADAPTERS ▸ ArrayAdapter - backed by an array of arbitrary objects ▸ CursorAdapter - exposes data from a database Cursor ▸ SimpleCursorAdapter - an easy adapter to map columns from a cursor to TextViews or ImageViews 63 ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity, layout, array); listView.setAdapter(adapter);
  • 64.
    ANDROID - FROMZERO TO HERO ADAPTER VIEW EVENTS ▸ setOnItemClickListener(AdapterView.OnItemClickList ener) ▸ Called when an item has been clicked ▸ setOnItemLongClickListener(AdapterView.OnItemLongC lickListener) ▸ Called when an item has been clicked and held ▸ setOnItemSelectedListener(AdapterView.OnItemSelect edListener) ▸ Called when an item in the list has been selected 64
  • 65.
    ANDROID - FROMZERO TO HERO ON ITEM CLICKED LISTENER 65 ListView listView = (ListView) findViewById(R.id.list); listView.setOnItemClickedListener( new AdapterView.OnItemClickedListener() { @Override public void onItemClick(AdapterView<?> list, View row, int index, long rowId) { // Code to run when the item is clicked } } );
  • 66.
    ANDROID - FROMZERO TO HERO CHANGES TO ADAPTER DATA ▸ If the data in the collection backing the adapter changes, the adapter must be notified 66 ArrayList<String> items = …; ArrayAdapter<String> adapter = …; listView.setAdapter(adapter); // change data items.remove(0); // notify the adapter adapter.notifyDataSetChanged();
  • 67.
    ANDROID - FROMZERO TO HERO CUSTOM ADAPTER LAYOUTS 67
  • 68.
    ANDROID - FROMZERO TO HERO CUSTOM ADAPTER LAYOUTS ▸ Provide the item layout in XML just like Activity layouts ▸ Either ▸ 1) Instruct the ArrayAdapter how to supply the item text to each item ▸ 2) Build a custom adapter by extending BaseAdapter 68
  • 69.
    ANDROID - FROMZERO TO HERO CUSTOM ARRAY ADAPTER 69 <LinearLayout android:orientation=“horizontal” …> <ImageView … /> <TextView android:id=“@+id/tv_label” … /> </LinearLayout> ArrayAdapter<String> adapter = new ArrayAdapter<String>( activity, R.layout.item_layout, R.id.tv_label, data ); item_layout.xml
  • 70.
    ANDROID - FROMZERO TO HERO EXTENDING BASE ADAPTER ▸ Must implement four important methods of every adapter ▸ getCount() - return how many items are in total in the data set ▸ getItem(position) - return the item from the data set at the specified position ▸ getItemId(position) - get the row id associated with the specified position in the list ▸ getView(position, convertView, parent) - get a view that displays the data at the specified position in the data set 70
  • 71.
    ANDROID - FROMZERO TO HERO EXAMPLE BASE ADAPTER 71 public class Item { public String name; public int quantity; } <LinearLayout android:orientation=“horizontal” …> <TextView android:id=“@+id/tv_name” … /> <TextView android:id=“@+id/tv_quantity” … /> </LinearLayout>
  • 72.
    ANDROID - FROMZERO TO HERO EXAMPLE BASE ADAPTER 72 public class ItemAdapter extends BaseAdapter<Item> { private List<Item> items = …; @Override public int getCount() { return items.size(); } @Override public Object getItem(int position) { return items.get(position); } @Override public long getItemId(int position) { return position; } }
  • 73.
    ANDROID - FROMZERO TO HERO EXAMPLE BASE ADAPTER - THE HEAVY LIFTING 73 @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { LayoutInflater inflater = LayoutInflater.from(context); convertView = inflater.inflate( R.layout.item_layout, parent, false); } Item item = (Item) this.getItem(position); TextView nameTextView = (TextView) convertView.findViewById(R.id.tv_name); TextView quantityTextView = (TextView) convertView.findViewById(R.id.tv_quantity); nameTextView.setText(item.name); quantityTextView(String.valueOf(item.quantity); return convertView; }
  • 74.
  • 75.
    ANDROID - FROMZERO TO HERO MULTI-SCREEN APPS ▸ Many apps have multiple screens (activities) ▸ An activity A can launch another activity B in response to an event ▸ Activity A can pass data to activity B ▸ Activity B can return data back to activity A ▸ Each activity has a Java class and an XML layout ▸ Remember: AndroidManifest should list all activities 75
  • 76.
    ANDROID - FROMZERO TO HERO MULTI-SCREEN APPS 76
  • 77.
    ANDROID - FROMZERO TO HERO INTENT ▸ An object representing a desired action ▸ Used to request an action from another app component ▸ Three fundamental use cases ▸ Start an Activity - startActivity() ▸ Start a Service - startService() ▸ Deliver a broadcast - sendBroadcast() 77
  • 78.
    ANDROID - FROMZERO TO HERO INTENT ▸ The component can be in the same app or another app installed on the same device ▸ Can store extra data to pass to the component 78
  • 79.
    ANDROID - FROMZERO TO HERO INTENT TYPES ▸ Explicit Intent ▸ Specifies the component to start explicitly by referring to its fully-qualified class name ▸ Typically used for starting components which are part of the same app ▸ When the system receives an explicit Intent it immediately starts the app component specified in the Intent ▸ We will be using explicits Intents today! 79
  • 80.
    ANDROID - FROMZERO TO HERO INTENT TYPES ▸ Implicit Intent ▸ Declare a general action to perform which allows all the components on the device to handle it ▸ Typically used for communicating with components which offer commonly present functionality in mobile devices (eg. Maps, Browser) ▸ When the system receives an implicit intent it consults with all the declared IntentFilters in all the AndroidManifests on the device ▸ This is not important for this course but it is included here as a starting point for further research! 80
  • 81.
    ANDROID - FROMZERO TO HERO BUILDING AN INTENT ▸ Component name - mandatory for explicit intents, meaning that the intent should be delivered only to the app component defined by it ▸ Action - mandatory for implicit intents, specifying the action to perform (eg. view, pick, send…) ▸ Broadcast intents report the action which took place ▸ You can specify your custom actions for your own components ▸ Common actions include ACTION_VIEW / ACTION_SEND ▸ Custom actions should include the package name 81 final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
  • 82.
    ANDROID - FROMZERO TO HERO BUILDING AN INTENT ▸ Data - the URI that references the data to be acted upon (eg. open THIS image) or the MIME type of that data ▸ Category - a string containing additional info about the kind of component to launch (eg. CATEGORY_BROWSABLE) ▸ Extras - key-value pairs that carry additional information required to accomplish the requested action ▸ Components should define their own extras including the package name ▸ Flags - metadata in the Intent which instruct the system on how to launch an activity 82
  • 83.
    ANDROID - FROMZERO TO HERO INTENT EXAMPLES 83 // Executed in an Activity, so 'this' is the Context Intent intent = new Intent(this, GreetingActivity.class); intent.putExtra(GreetingActivity.EXTRA_NAME, “Ivo”); startActivity(intent);
  • 84.
    ANDROID - FROMZERO TO HERO EXTRACTING INTENT INFO 84 public class GreetingActivity extends Activity { ... public void onCreate(Bundle savedState) { super.onCreate(savedState); setContentView(...); Intent intent = getIntent(); String name = intent.getStringExtra(EXTRA_NAME); } }
  • 85.
    ANDROID - FROMZERO TO HERO GETTING RESULT FROM AN ACTIVITY ▸ Calling activity wants to get an answer from the called activity ▸ Use startActivityForResult(int requestCode) instead of startActivity() ▸ The method returns immediately but later on when the called activity finishes onActivityResult() will be called with the answer from the called activity ▸ The called activity must set the answer before finishing ▸ Example: Starting the People app to select a contact 85
  • 86.
    ANDROID - FROMZERO TO HERO STARTING AN ACTIVITY FOR A RESULT 86 static final int PICK_CONTACT_REQUEST = 1; // The request code ... private void pickContact() { Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse(“content://contacts”)); // Show user only contacts w/ phone numbers pickContactIntent.setType(Phone.CONTENT_TYPE); startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST); }
  • 87.
    ANDROID - FROMZERO TO HERO WAITING FOR A RESULT 87 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // Check which request it is that we're responding to if (requestCode == PICK_CONTACT_REQUEST) { // Make sure the request was successful if (resultCode == RESULT_OK) { // Get the URI that points to the selected contact Uri contactUri = data.getData(); String stringExtra = data.getStringExtra(KEY); // do something with the returned data... // activities can return data in different format // make sure you know what that format is } } }
  • 88.
    ANDROID - FROMZERO TO HERO SENDING BACK A RESULT 88 public class NameChooserActivity extends Activity { ... public void onClick(View view) { Intent intent = new Intent(); intent.putExtra(EXTRA_NAME); setResult(RESULT_OK, intent); finish(); // calls onDestroy } }
  • 89.
    ANDROID - FROMZERO TO HERO ACTIVITY STACK 89
  • 90.
  • 91.
    ANDROID - FROMZERO TO HERO KEEPING APPS RESPONSIVE ▸ Slow and sluggish performance is the #1 reason why your users will uninstall your app ▸ The Android system has a built-in guard which protects the users from non-responsive applications ▸ After an app is not responsive for a considerable amount of time (a couple of secs) the system displays the dreadful Application Not Responding (ANR) dialog ▸ No response to input in 5 secs ▸ A BroadcastReceiver taking more than 10 secs 91
  • 92.
    ANDROID - FROMZERO TO HERO ANR == UNINSTALL 92
  • 93.
    ANDROID - FROMZERO TO HERO PERCEIVED SPEED RESEARCH ▸ 100 to 200ms is the threshold beyond which users will perceive slowness in an app ▸ If an app is performing background work as a response to user input, always show a progress dialog (ProgressBar) ▸ If an app has a time consuming start-up process (setting up initial data, server communication etc) either: ▸ Show a splash screen with a progress indicator ▸ Render the main UI as fast as possible with a progress indicator and filling in the new data asynchronously as it arrives 93
  • 94.
    ANDROID - FROMZERO TO HERO KEEPING APPS RESPONSIVE ▸ All data persistence operations take time ▸ All network operations take time ▸ All graphic manipulation operations take time ▸ Need to delve deeper in the Android process model 94
  • 95.
    ANDROID - FROMZERO TO HERO ANDROID PROCESS MODEL ▸ Android apps are single threaded apps ▸ UI thread is their main thread ▸ drawing UI elements, dispatching events ▸ Android’s single-threaded model has two rules ▸ 1) Do not block the UI thread ▸ 2) Do not access the Android toolkit from outside the UI thread 95
  • 96.
    ANDROID - FROMZERO TO HERO ANDROID PROCESS MODEL 96 public class ExampleActivity extends Activity { ... public void onClick(View v) { new Thread(new Runnable() { public void run() { Bitmap b = loadImageFromNetwork("http://example.com/image.png"); mImageView.setImageBitmap(b); } }).start(); } } public class ExampleActivity extends Activity { ... public void onClick(View v) { Bitmap b = loadImageFromNetwork("http://example.com/image.png"); mImageView.setImageBitmap(b); } } BAD - RUNNING A LONG OPERATION ON THE UI THREAD BAD - ACCESSING THE ANDROID UI TOOLKIT FROM AN OUTSIDE THREAD
  • 97.
    ANDROID - FROMZERO TO HERO ANDROID PROCESS MODEL 97 public class ExampleActivity extends Activity { ... public void onClick(View v) { new Thread(new Runnable() { public void run() { final Bitmap b = loadImageFromNetwork("http://example.com/image.png"); mImageView.post(new Runnable() { public void run() { mImageView.setImageBitmap(bitmap); } }); } }).start(); } } GOOD
  • 98.
    ANDROID - FROMZERO TO HERO ASYNC TASK ▸ We need worker threads that are allowed to interact with the Android UI Toolkit ▸ AsyncTask enables proper and easy use of the UI thread ▸ A utility that supports running operations in the background in a worker thread and delivering the results on the UI thread without having to manipulate threads and and handlers ▸ Useful for long running operations but one that span at most a minute or max two ▸ All AsyncTasks in the system are executed sequentially on a single worker thread (no parallelism) 98
  • 99.
    ANDROID - FROMZERO TO HERO 99 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { // Do the long-running work in here // !!! Executed in background protected Long doInBackground(URL... urls) { long totalSize = 0; for (int i = 0; i < urls.length; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); } return totalSize; } // This is called each time you call publishProgress() // !!! Executed on UI thread protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } // This is called when doInBackground() is finished // !!! Executed on UI thread protected void onPostExecute(Long result) { showNotification("Downloaded " + result + " bytes"); } } new DownloadFilesTask().execute(url1, url2, url3);
  • 100.
  • 101.
    101URL url =new URL(CREATE_STUDENTS_URL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(10000 /* milliseconds */); conn.setConnectTimeout(15000 /* milliseconds */); conn.setRequestMethod("POST"); conn.setDoInput(true); conn.setDoOutput(true); conn.addRequestProperty("Content-Type", "application/json"); Student student = new Student(); student.setFirstName(firstName); student.setLastName(lastName); student.setAge(age); String studentJson = new Gson().toJson(student); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8")); writer.write(studentJson); writer.flush(); writer.close(); conn.getOutputStream().close(); // Starts the post conn.connect(); int response = conn.getResponseCode();
  • 102.
    ANDROID - FROMZERO TO HERO RETROFIT ▸ Retrofit turns our HTTP API into a Java interface ▸ Use annotations to describe the HTTP request: ▸ URL parameter replacement and query parameter support ▸ Object conversion to request body (e.g., JSON) ▸ Calls can be executed either synchronously or asynchronously 102
  • 103.
    ANDROID - FROMZERO TO HERO ADDING RETROFIT TO A PROJECT 103 dependencies { ... compile "com.squareup.retrofit2:retrofit:2.0.1" compile "com.squareup.retrofit2:converter-gson:2.0.1" ... } -dontwarn retrofit2.** -keep class retrofit2.** { *; } -keepattributes Signature -keepattributes Exceptions app/build.gradle proguard-rules.pro <uses-permission android:name="android.permission.INTERNET" /> AndroidManifest.xml
  • 104.
    ANDROID - FROMZERO TO HERO DEFINE YOUR API IN CODE 104 public interface StudentsApi { static final String BASE_URL = "http://students-sdmdcity.rhcloud.com/rest/"; static final String STUDENTS_URL = "students"; @GET(STUDENTS_URL) Call<List<Student>> getAllStudents(); @POST(STUDENTS_URL) Call<Void> createStudent(@Body Student student); }
  • 105.
    ANDROID - FROMZERO TO HERO CREATE YOU API INSTANCE 105 Retrofit retrofit = new Retrofit.Builder() .baseUrl(StudentsApi.BASE_URL) // automatic JSON conversion using Googles Gson [so cool!] .addConverterFactory(GsonConverterFactory.create()) .build(); StudentsApi studentsApi = retrofit.create(StudentsApi.class);
  • 106.
    ANDROID - FROMZERO TO HERO FINALLY, EXECUTE THE CALL 106 // If using enqueue() - this is asynchronously executed on a background // thread studentsApi.createStudent(student).enqueue(new Callback<Void>() { @Override public void onResponse(Call<Void> call, Response<Void> response) { int responseCode = response.code();
 Void returnData = response.body(); } @Override public void onFailure(Call<Void> call, Throwable t) { } }); // If using execute() - this is synchronously executed on the calling // thread Response<Void> response = studentsApi.createStudent(student).execute();
  • 107.
    ANDROID - FROMZERO TO HERO CONSUMING REST WEB SERVICES - GENERAL RULES ▸ HTTP defines methods (sometimes referred to as verbs) to indicate the desired action to be performed on the identified resource ▸ POST - most-often utilised to create new resources ▸ GET - used to read (or retrieve) a representation of a resource ▸ PUT - most-often utilised for updating existing resources ▸ DELETE - used to delete a resource identified by a URI 107
  • 108.
    ANDROID - FROMZERO TO HERO CONSUMING WEB SERVICES - HTTP STATUS CODES ▸ 200 OK - everything was fine with the request ▸ 204 No Content - everything was fine with the request, but the server returned no content ▸ 400 Bad Request - the request to the server contains a syntax error and was not understood by the server ▸ 403 Forbidden - the resource you are trying to access if forbidden for the current authorised user ▸ 404 Not Found - the resource you are trying to access does not exist on the server 108