The workshop deals with the design and implementation of applications for mobile devices using the Android operating system. Participants work at all stages of the development life-cycle from inception to deployment, whilst considering usability and device capabilities for a mobile application capable of meeting a functional specification. Participants are introduced to the programming environment for application development and have a hands-on approach to programming using the appropriate programming languages.
2. 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
4. 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
5. 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
6. 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
7. 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
8. 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
13. 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
14. 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
15. 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
17. 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
18. 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
19. 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
20. 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>
21. 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
22. 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.
23. 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
24. 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
25. 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
26. 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
27. 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
29. 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
30. 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” />
31. 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
32. 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" />
33. 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
34. 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" />
35. 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"/>
36. 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"/>
37. 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” />
38. 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();
39. 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
40. 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
42. 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
43. 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;
}
});
44. 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
45. 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
46. ANDROID - FROM ZERO TO HERO
COMMON LAYOUTS
46
Linear Layout Relative Layout
47. 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
48. 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>
50. 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
52. 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” />
53. ANDROID - FROM ZERO TO HERO
LAYOUT WEIGHT
53
<Button
…
android:layout_weight=“1” />
<Button
…
android:layout_weight=“1” />
<Button
…
android:layout_weight=“3” />
54. 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
55. 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
56. 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
57. 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
59. 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
60. 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
61. ANDROID - FROM ZERO TO HERO
COMMON ADAPTER LAYOUTS
61
List View Grid View
62. 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
63. 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);
64. 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
65. 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
}
}
);
66. 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();
68. 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
69. 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
70. 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
71. 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>
72. 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;
}
}
73. 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;
}
75. 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
77. 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
78. 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
79. 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
80. 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
81. 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";
82. 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
83. 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);
84. 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);
}
}
85. 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
86. 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);
}
87. 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
}
}
}
88. 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
}
}
91. 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
93. 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
94. 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
95. 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
96. 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
97. 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
98. 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
99. 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);
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 - 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
103. 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
104. 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);
}
105. 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);
106. 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();
107. 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
108. 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