Professional Documents
Culture Documents
Smart Phones
Internet access anywhere y Social networking
y
Introduction to Android
Open software platform for mobile development. A complete stack OS, Middleware, Applications. An Open Handset Alliance (OHA) project. Powered by Linux operating system. Fast application development in Java. Open source under the Apache license
3
Why Android
experience
OHA have developed Android , the first complete, open, and free mobile platform
Features
Application framework enabling reuse and replacement
of components Dalvik virtual machine optimized for mobile devices Integrated browser based on the open source WebKit engine Optimized graphics powered by a custom 2D graphics library; 3D graphics based on the OpenGL ES 1.0 specification (hardware acceleration optional) SQLite for structured data storage Media support for common audio, video, and still image formats (MPEG4, H.264, MP3, AAC, AMR, JPG, PNG, GIF)
7
Features (Contd .)
GSM Telephony (hardware dependent) Bluetooth, EDGE, 3G, and WiFi (hardware dependent) Camera, GPS, compass, and accelerometer (hardware
dependent) Rich development environment including a device emulator, tools for debugging, memory and performance profiling, and a plugin for the Eclipse IDE
Android Architecture
Linux Kernel
Android relies on Linux version 2.6 for core system services such as device drivers, security, memory management ,process management. The kernel also acts as an abstraction layer between the hardware and the rest of the software stack.
10
Includes a set of C/C++ libraries. Interface through Java. Surface manager Handling UI Windows. 2D and 3D graphics. Media codecs, SQLite, Browser engine.
11
Dalvik VM (translator between the application side and the operating system)
Dex files (.dex)format Compact and efficient than class files Limited memory and battery power Java 5 Std edition Collections, I/O etc
12
Core Libraries
Application Framework
Framework elements are: Intents , Content Providers , Views and managers This layer has been designed to facilitate the reuse of components in android Developers can build their applications to execute on android kernel and inter-operate among themselves and with existing applications
13
Applications
Android will ship with a set of core applications including an a)Email client, b)SMS program, c)Calendar, d)Contacts & others. All the applications are written using the Java programming language.
14
Linux OS
15
Android SDK
ADT: Android Development Tool, an Eclipe plugin Two debuggers
adb: Android Debug Bridge ddms: Dalvik Debug Monitor Server
16
17
18
No Not Supported
19
Contacts
Pick photo
GMail
Chat
Blogger Blogger
Client component makes a System picks best request for a specific use New components can component for that action action functionality existing
23
24
Project Properties
Project Name Package Name This is the name of the directory or folder on your computer that you want to contain the project. This is the package namespace (following the same rules as for packages in the Java programming language) that you want all your source code to reside under. This also sets the package name under which the stub Activity will be generated. The package name you use in your application must be unique across all packages installed on the system; for this reason, it's very important to use a standard domain-style package for your applications. In the example above, we used the package domain "com.chicagoandroids". This is the name for the class stub that will be generated by the plug-in. This will be a subclass of Android's Activity class. An Activity is simply a class that can run and do work. It can create a UI if it chooses, but it doesn't need to. This is the human-readable title for your application.
Activity Name
Application Name
25
Left: Manifest (* not that automatic) Right: R class and the android library (no need to touch) 26
Left: Source directories, where your classes go Right: Resources (this is what gets automatically build into the R class)
27
28
29
33
Activities (continue)
34
Activities (continue)
35
All activities in a task are arranged in a stack. If one activity starts another, the new activity is pushed on the stack and it becomes the running activity. When the user presses the BACK key, the current activity is popped from the stack and the previous one resumes.
37
Managing Tasks
Android manages tasks and the back stack by placing all activities started in succession in the same task and in a "last in, first out" stack. You might decide that you want to interrupt the normal behavior. Perhaps you want an activity in your application to begin a new task when it is started (instead of being placed within the current task). when you start an activity, you want to bring forward an existing instance of it (instead of creating a new instance on top of the back stack). you want your back stack to be cleared of all activities start an activity except for the root activity when the user leaves the task.
38
Managing Tasks
You can do these things and more, with attributes in the <activity> manifest element and with flags in the intent that you pass to startActivity(). <activity> attributes you can use are:
taskAffinity launchMode allowTaskReparenting clearTaskOnLaunch alwaysRetainTaskState finishOnTaskLaunch
39
There are four launch modes: standard (default) / singleTop / singleTask / singleInstance A launch mode can be set for each activity:
40
singleTask/singleInstance
41
Task B
Task A
Task B
A "standard" or "singleTop" activity can be instantiated many times. A "singleTask" or "singleInstance" activity is limited to just one instance.
42
43
The existing instance D is expected to handle the new intent (since it's at the top of the stack)
Original Task
If D is"standard"
If D is"singleTop"
44
Activity B
Original Task
If B is"singleInstance"
A "singleInstance" activity is always at the top of the stack, so it is always in position to handle the intent.
Activity B Activity A
Original Task
Activity A Activity B
An intent arrives for an activity of type B
If B is"singleTask"
Activity A Activity B
Activity B cannot handle the intent since it is not in position and the intent is dropped.
Original Task
If B is"singleTask"
47
An affinity means a preference for each activity to belong to a certain task. An individual affinity can be set for each activity:
By default, a new activity is launched into the task of the activity that called startActivity().
Some activity attributes that can be used to modify the default control: (Cont)
If finishOnTaskLaunch is set to an activity of a task
- The activity remains part of the task only for the current session.
- If the user leaves and then returns to the task, it no longer is present.
Another way to force activities to be removed from the stack (FLAG_ACTIVITY_CLEAR_TOP flag):
If an intent includes the FLAG_ACTIVITY_CLEAR_TOP flag and the target task already has an instance of the type of activity that should handle the intent in its stack, all activities above that instance are cleared away.
Process Basics
How does it all of this relate to the Unix roots of Android?
Android process == Linux process (w/ its own unique UID) By default, 1 process per APK By default, 1 thread per process Most components interleave events into the main thread
53
Creating an Activity
To create an activity, you must create a subclass of Activity . In your subclass, you need to implement callback methods that the system calls when the activity transitions between various states of its lifecycle. The two most important callback methods are:
onCreate() onPause().
54
There are several other attributes that you can include in this element, to define properties such as the label for the activity, an icon for the activity, or a theme to style the activity's UI
55
Using IntentFilters
An <activity> element can also specify various intent filters using the <intent-filter> element in order to declare how other application components may activate it. When you create a new application using the Android SDK tools, the stub activity that's created for you automatically includes an intent filter that declares the activity responds to the "main" action and should be placed in the "launcher" category. if you want your activity to respond to implicit intents that are delivered from other applications (and your own), then you must define additional intent filters for your activity 56
Starting an Activity
You can start another activity by calling startActivity(), passing it an Intent that describes the activity you want to start. The intent specifies either the exact activity you want to start or describes the type of action you want to perform. An intent can also carry small amounts of data to be used by the activity that is started
57
Starting an Activity
Intent Examples :
Intent intent = new Intent(this, SignInActivity.class); startActivity(intent); Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_EMAIL, recipientArray); startActivity(intent);
60
61
67
Home Process Home Mail Process Mail Map Process Browser Process Message
Browser
Map
Home Process Home Browser Process Map Process Mail Mail Message Map
Browser
71
72
73
75
76
77
78
Action Field
A string naming the action to be performed The Intent class defines a number of predefined action constants, including ACTION_CALL, ACTION_EDIT, ACTION_MAIN, ACTION_SYNC, ACTION_BATTERY_LOW, etc. You can also define your own action strings for activating the components in your application The action largely determines how the rest of the intent is structured - particularly the data and extras fields much as a method name determines a set of arguments and a return value.
79
Data Field
The URI of the data to be acted on and the MIME type of that data. Different actions are paired with different kinds of data specifications. If the action field is ACTION_EDIT, the data field would contain the URI of the document to be displayed for editing. If the action is ACTION_CALL, the data field would be a tel: URI with the number to call. If the action is ACTION_VIEW and the data field is an http: URI, the receiving activity would be called upon to download and display whatever data the URI refers to.
80
Data Field
Examples of Action/Data Pairs
ACTION_VIEW content://contacts/people/1 Display information about the person whose identifier is "1". ACTION_DIAL content://contacts/people/1 -- Display the phone dialer with the person filled in. ACTION_VIEW tel:123 -- Display the phone dialer with the given number filled in. ACTION_DIAL tel:123 -- Dial the phone dialer with the given number filled in. ACTION_EDIT content://contacts/people/1 Edit information about the person whose identifier is "1". ACTION_VIEW content://contacts/people/ -- Display a list of people, which the user can browse through. This example is a typical top-level entry into the Contacts application, showing you the list of people. 81
Category Field
A string containing additional information about the kind of component (activity, service, or broadcast receiver) that should handle the intent. Any number of category descriptions can be placed in an Intent object Android provides a set of predefined categories (We will see them in the following slide) You can define your own categories
82
Extras Field
Key-value pairs for additional information that should be delivered to the component handling the intent. Just as some actions are paired with particular kinds of data URIs, some are paired with particular extras. ACTION_TIMEZONE_CHANGED action has a "timezone extra that identifies the new time zone ACTION_HEADSET_PLUG action has a "state" extra indicating whether the headset is now plugged in or unplugged , as well as a "name" extra for the type of headset
84
Flags Field
Flags of various sorts. Many instruct the Android system how to launch an activity (for example, which task the activity should belong to) and how to treat it after it's launched (for example, whether it belongs in the list of recent activities).
85
Intent Resolution
86
87
Types of Intents
Explicit intents Designate the target component by its class (the component name field is set by the class name) Since component names (class name of the target activity, for example) would generally not be known to developers of other applications, explicit intents are typically used for application-internal messages such as an activity starting a subordinate service or launching a sister activity. Implicit intents Do not name a target (the component name field is blank). Implicit intents are often used to activate components in other applications.
88
91
Intent Filters
Intent Resolution
92
Intent Filters
Intent Resolution
As shown in the previous illustration. Activity3 has issue a generic request for help processing an incoming text-message. Assume the user has installed a Fancy SMS application to (perhaps) replace the standard HUMBLE SMS app originally included in Android. Upon the arrival of the implicit Intent, Android will (somehow) tell the user: You have got a new text-message. I have a FANCY and a HUMBLE SMS application which one you want me to execute? Make it a default?
93
Action Test
To pass this test, the action specified in the Intent object must match one of the actions listed in the filter. If the Intent object or the filter does not specify an action, the results are as follows:
If a filter does not specify any action, there is nothing for an intent to match, so all intents fail the test. No intents can get through the filter. On the other hand, an Intent object that doesn't specify an action automatically passes the test as long as the filter contains at least one action.
95
Category Test
For an intent to pass the category test, every category in the Intent object must match a category in the filter.
The filter can list additional categories, but it cannot omit any that are in the intent The categories of the filter should be the super-set of the categories of the Intent object
Special case
An Intent object with no categories should always pass this test, regardless of what's in the filter
96
97
Data Test
Example
<intent-filter . . . > <data android:mimeType="video/mpeg" android:scheme="http" . . . /> <data android:mimeType="audio/mpeg" android:scheme="http" . . . /> ... </intent-filter>
Each <data> element can specify a data type (MIME media type) and URI.
98
10 0
10 2
If they are to be represented in the application launcher, they also specify the "android.intent.category.LAUNCHER" category:
<intent-filter . . . > <action android:name="code android.intent.action.MAIN" /> <category android:name="code android.intent.category.LAUNCHER" /> </intent-filter>
10 3
10 5
View Hierarchy
All the views in a window are arranged in a tree you show the tree by calling setContentView(rootNode) in the activity
10 8
What is a Layout?
Your layout is the architecture for the user interface in an Activity. It defines the layout structure and holds all the elements that appear to the user.
10 9
Advantages of Option #1: Declaring UI in XML Separation of the presentation from the code that controls its behavior
You can modify UI without having to modify your source code and recompile For example, you can create XML layouts for different screen orientations, different device screen sizes, and different languages
11 3
11 4
11 5
11 6
Attributes
Every View and ViewGroup object supports their own variety of attributes. Some attributes are specific to a View object (for example, TextView supports the textSize attribute), but these attributes are also inherited by any View objects that may extend this class. Some are common to all View objects, because they are inherited from the root View class (like the id attribute). Other attributes are considered "layout parameters, which are attributes that describe certain layout orientations of the View object, as defined by that object's parent ViewGroup object. These attributes are typically in XML form
11 7
ID Attribute
Any View object may have an integer ID associated with it, to uniquely identify the View within the tree. When the application is compiled, this ID is referenced as an integer, but the ID is typically assigned in the layout XML file as a string, in the id attribute. Syntax
android:id="@+id/my_button"
11 8
With the android package namespace in place, we're now referencing an ID from the android.R resources class, rather than the local resources class.
11 9
Then you can make a reference to the view object via findViewById(R.id.<string-id>).
Button myButton = (Button) findViewById(R.id.my_button);
12 0
12 1
Parent view group defines layout parameters for each child view (including the child view group)
12 2
12 3
Linear Layout
fill_parent
Some Button...
fill_parent
wrap_content
fill_parent
Layout Types
All layout types are subclass of ViewGroup class Layout types
LinearLayout RelativeLayout TableLayout FrameLayout Tab layout
12 5
LinearLayout
Aligns all children in a single direction vertically or horizontally, depending on how you define the orientation attribute. All children are stacked one after the other, so a vertical list will only have one child per row, no matter how wide they are To configure a LinearLayout, you have five main areas of control besides the container's contents: Orientation fill model weight gravity padding
12 6
LinearLayout
Orientation : indicates whether the LinearLayout represents a row or a column. Add the android:orientation property to your LinearLayout element in your XML layout, setting the value to be horizontal for a row or vertical for a column. The orientation can be modified at runtime by invoking setOrientation()
12 7
LinearLayout
12 8
LinearLayout
Linear Layout: Fill Model Widgets have a "natural" size based on their accompanying text. When their combined sizes does not exactly match the width of the Android device's screen, we may have the issue of what to do with the remaining space
12 9
LinearLayout
Linear Layout: Fill Model All widgets inside a LinearLayout must supply dimensional attributes android:layout_width and android:layout_height to help address the issue of empty space. Values used in defining height and width are: Specific a particular dimension, such as 125px to indicate the widget should take up exactly 125 pixels. Provide wrap content which means the widget should fill up its natural space, unless that is too big, in which case Android can use word-wrap as needed to make it fit. Provide fill_parent, which means the widget should fill up all available space in its enclosing container, after all other widgets are taken care of.
13 0
LinearLayout
Linear Layout: Fill Model
13 1
LinearLayout
Linear Layout: Weight It is used to proportionally assign space to widgets in a view. You set android:layout_weight to a value (1, 2, 3, ) to indicates what proportion of the free space should go to that widget. Example Both the TextView and the Button widgets have been set as in the previous example. Both have the additional property android:layout_weight="1 whereas the EditText control has android:layout_weight="2
13 2
LinearLayout
Linear Layout: Gravity It is used to indicate how a control will align on the screen. By default, widgets are left- and top-aligned. You may use the XML property android:layout_gravity= to set other possible arrangements: left, center, right, top, bottom, etc.
13 3
LinearLayout
Linear Layout: Padding By default, widgets are tightly packed next to each other. If you want to increase the whitespace between widgets, you will want to use the android:padding property (or by calling setPadding() at runtime on the widget's Java object). The padding specifies how much space there is between the boundaries of the widget's "cell" and the actual widget contents. Note: Padding is analogous to the margins on a word processing document.
13 4
LinearLayout
Linear Layout: Padding Example: The EditText box has been changed to display 30px of padding all around
13 5
LinearLayout
LinearLayout vertical
RelativeLayout
RelativeLayout lets child views specify their position relative to the parent view or to each other (specified by ID)
You can align two elements by right border, or make one below another, centered in the screen, centered left, and so on
Elements are rendered in the order given, so if the first element is centered in the screen, other elements aligning themselves to that element will be aligned relative to screen center.
13 7
RelativeLayout
parentTop parentLeft 1 toRightOf 1
layout_below button1
parentBottom toRightOf 1
RelativeLayout : LayoutParams
@+id/red @+id/green
android:layout_above="@id/green" android:layout_below="@id/red"
android:layout_toLeftOf="@id/green"
@+id/red
@+id/green
android:layout_toRightOf="@id/red"
RelativeLayout : LayoutParams
android:layout_alignTop="@id/red"
@+id/green
@+id/green
@+id/red
RelativeLayout : LayoutParams
android:layout_alignParentTop="true" android:layout_alignParentLeft="true"
@+id/re d
parent
@+id/re d
android:layout_alignParentBottom="true" android:layout_alignParentRight="true"
RelativeLayout Example
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/blue" android:padding="10px" > <TextView android:id="@+id/label" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Type here:" /> <EditText android:id="@+id/entry" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@android:drawable/editbox_background" android:layout_below="@id/label" /> <Button android:id="@+id/ok" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/entry" android:layout_alignParentRight="true" android:layout_marginLeft="10px" android:text="OK" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@id/ok" android:layout_alignTop="@id/ok" android:text="Cancel" /> </RelativeLayout>
14 2
Table Layout
Android's TableLayout allows you to position your widgets in a grid made of identifiable rows and columns. Columns might shrink or stretch to accommodate their contents. TableLayout works in conjunction with TableRow. TableLayout containers do not display border lines for their rows, columns, or cells.
14 3
Table Layout
Rows are declared by you by putting widgets as children of a TableRow inside the overall TableLayout. The number of columns is determined by Android ( you control the number of columns in an indirect way). So if you have three rows one with two widgets one with three rows, widgets, widgets, and one with four widgets, there will be at least four columns.
14 4
Table Layout
However, a single widget can take up more than one column by including the android:layout_span property, indicating the number of columns the widget spans (this is similar to the colspan attribute one finds in table cells in HTML)
<TableRow> <TextView android:text="URL:" /> <EditText android:id="@+id/entry" android:layout_span="3" /> </TableRow>
14 5
Table Layout
Ordinarily, widgets are put into the first available column of each row. In the previous fragment, the label ( URL ) would go in the first column (column 0, as columns are counted starting from 0), and the TextField would go into a spanned set of three columns (columns 1 through 3).
14 6
14 7
Table Layout
By default, each column will be sized according to the "natural" size of the widest widget in that column. If your content is narrower than the available space, you can use the TableLayout property:
android:stretchColumns =
Its value should be a single column number (0-based) or a comma delimited list of column numbers. Those columns will be stretched to take up any available space yet on the row.
14 8
Table Layout
In our running example we stretch columns 2, 3, and 4 to fill the rest of the row.
14 9
Frame Layout
FrameLayout is designed to block out an area on the screen to display a single item. You can add multiple children to a FrameLayout and control their position within the FrameLayout using gravity. Children are drawn in a stack, with the most recently added child on top. The size of the frame layout is the size of its largest child (plus padding), visible or not (if the FrameLayout's parent permits).
15 0
15 1
ScrollView Layout
A ScrollView is a special type of FrameLayout in that it enables users to scroll through a list of views that occupy more space than the physical display When we have more data than what can be shown on a single screen you may use the ScrollView control. It provides a sliding or scrolling access to the data. This way the user can only see part of your layout at one time, but the rest is available via scrolling. The ScrollView can contain only one child view or ViewGroup, which normally is a LinearLayout. This is similar to browsing a large web page that forces the user to scroll up the page to see the bottom part of the form.
15 2
Example of ScrollView
15 3
Absolute Layout
Is based on the simple idea of placing each control at an absolute position. You specify the exact x and y coordinates on the screen for each control. This is not recommended for most UI development since absolutely positioning every element on the screen makes an inflexible UI that is much more difficult to maintain This class is deprecated. Use FrameLayout, RelativeLayout or a custom layout instead.
15 4
15 5
15 6
15 7
LANDSCAPE
PORTRAIT
15 8
16 4
android:id is the unique identifier of the element android:layout_width/layout_height are the size of the element. In the android:text attribute we set the text that its inside the Button.
16 5
The EditText widget is also a subclass of the TextView, but it has many other attributes that can be specified to alter the behavior of the field
16 8
17 0
17 1
Using android.widget.Button
To capture button clicks, we set up an event listener using the setOnClickListener method. E.g., we might use an (anonymous) inner class to capture button clicks, as is defined below:
Button button01=(Button)findViewById(R.id.button01); button01.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Log.d("PropertyApp", "button01 has just been pressed"); } });
17 2
Using android.widget.RadioButton To get the ID of a currently-checked radio button we use the getCheckedRadioButtonID method. E.g.:
RadioGroup myRadioGroup; myRadioGroup=(RadioGroup)findViewById(R.id.myRadioGroup); int checkedID = myRadioGroup.getCheckedRadioButtonId(); if (checkedID == -1) { Log.d(TAG, "No radio button was selected."); } else if (checkedID == R.id.radioButton01) { Log.d(TAG, "'radioButton01' was selected."); } else if (checkedID == R.id.radioButton02) { Log.d(TAG, "'radioButton02' was selected."); }
17 3
Creating Menus
Menus are an important part of an activity's user interface, which provide users a familiar way to perform actions. There are three types of application menus:
Options Menu :
The primary collection of menu items for an activity, which appears when the user touches the MENU button. When your application is running on Android 3.0 or later, you can provide quick access to select menu items by placing them directly in the Action Bar, as "action items."
17 4
Creating Menus
Types of application menus:
Context Menu
A floating list of menu items that appears when the user touches and holds a view that's registered to provide a context menu.
Submenu
A floating list of menu items that appears when the user touches a menu item that contains a nested menu.
17 5
Creating Menus
Create an application that supports options/sub/context menus
Automatically fill Hi! in the EditText Plus menu will also open a sub-menu
<option menu>
<sub-menu>
<context menu>
17 6
Menu Composition
Hi Hola Sub2 Home <sub-menu> Hello Long press in EditText
Sub1 Plus
Pre
17 7
<item>
Creates a MenuItem, which represents a single item in a menu. This element may contain a nested <menu> element in order to create a submenu.
<group>
An optional, invisible container for <item> elements. It allows you to categorize menu items so they share properties such as active state and visibility
17 9
The getMenuInflater() method returns a MenuInflater for the activity. With this object, you can call inflate(), which inflates a menu resource into a Menuobject
18 1
public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu, menu); return true; }
18 2
18 3
18 7
18 8
Creating Submenus
A submenu is a menu that the user can open by selecting an item in another menu. You can add a submenu to any menu (except a submenu). Submenus are useful when your application has a lot of functions that can be organized into topics, like items in a PC application's menu bar (File, Edit, View, etc.).
18 9
Creating Submenus
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/file" android:icon="@drawable/file" android:title="@string/file" > <!-- "file" submenu --> <menu> <item android:id="@+id/create_new" android:title="@string/create_new" /> <item android:id="@+id/open" android:title="@string/open" /> </menu> </item> </menu>
19 0
Creating Dialogs
A dialog is usually a small window that appears in front of the current Activity. The underlying Activity loses focus and the dialog accepts all user interaction. Dialogs are normally used for notifications that should interrupt the user and to perform short tasks that directly relate to the application in progress
19 1
Creating Dialogs
The Dialog class is the base class for creating dialogs. Typically you are going to use subclasses of Dialog class instead of using it directly. Example subclasses of Dialog class :
AlertDialog. ProgressDialog DatePickerDialog. TimePickerDialog
19 2
Showing a Dialog
A dialog is always created and displayed as a part of an Activity. You should normally create dialogs from within your Activity's onCreateDialog(int) callback method. When you use this callback, the Android system automatically manages the state of each dialog and hooks them to the Activity, effectively making it the "owner" of each dialog
19 3
Showing a Dialog
When you want to show a dialog, call showDialog(int) and pass it an integer that uniquely identifies the dialog that you want to display. When a dialog is requested for the first time, Android calls onCreateDialog(int) from your Activity, which is where you should instantiate the Dialog. Define onPrepareDialog(int, Dialog) method if you want to change any properties of the dialog each time it is opened
19 4
When it's time to show one of the dialogs,call showDialog(int) with the ID of a dialog:
showDialog(DIALOG_PAUSED_ID);
19 5
19 6
19 7
19 8
20 0
20 1
Creating a ProgressDialog
A ProgressDialog is an extension of the AlertDialog class. It displays a progress animation in the form of a spinning wheel, for a task with progress that's undefined, or a progress bar, for a task that has a defined progression. Opening a progress dialog can be as simple as calling ProgressDialog.show().
ProgressDialog dialog = ProgressDialog.show(MyActivity.this, "", "Loading. Please wait...", true);
20 2
Creating a ProgressDialog
The default style of a progress dialog is the spinning wheel. If you want to create a progress bar that shows the loading progress with granularity, some more code is required. To show the progression with an animated progress bar: Initialize the ProgressDialog with the class constructor, ProgressDialog(Context). Set the progress style to "STYLE_HORIZONTAL" with setProgressStyle(int) and set any other properties, such as the message. When you're ready to show the dialog, call show() or return the ProgressDialog from the onCreateDialog(int) callback. You can increment the amount of progress displayed in the bar by calling either setProgress(int) with a value for the total percentage completed so far or incrementProgressBy(int) with an incremental value to add to the total percentage completed so far. 20 3
20 6
20 7
20 8
20 9
21 0
21 1
LIST CONTROLS
21 2
Understanding Adapters
List controls are used to display collections of data. But instead of using a single type of control to manage both the display and the data, Android separates these two responsibilities into list controls and adapters. List controls are classes that extend android.widget.AdapterView and include ListView, GridView, Spinner, and Gallery
21 3
Understanding Adapters
21 4
What is an Adapter?
An Adapter object acts as a bridge between an AdapterView object and the underlying data for that view. The Adapter provides access to the data items. The Adapter is also responsible for making a View for each item in the data set. Types of Adatpers - they implements ListAdatper interface ArrayAdatper CursorAdatper There are a few more
21 6
21 7
AdapterView Responsibilities
Two main responsibilities of AdapterView
Filling the layout with data (it received through the help of an Adapter) Handling user selections - when a user selects an item, perform some action
21 8
21 9
22 0
22 1
AutoCompleteTextView
The AutoCompleteTextView control is a TextView with auto-complete functionality. In other words, as the user types in the TextView, the control can display suggestions for selection.
<AutoCompleteTextView android:id="@+id/actv" android:layout_width="fill_parent" android:layout_height="wrap_content" /> AutoCompleteTextView actv = (AutoCompleteTextView) this.findViewById(R.id.actv); ArrayAdapter<String> aa = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, new String[] {"English", "Hebrew", "Hindi", "Spanish", "German", "Greek" }); actv.setAdapter(aa);
22 5
MultiAutoCompleteTextView
If you have played with the AutoCompleteTextView control, you know that the control offers suggestions only for the entire text in the text view. In other words, if you type a sentence, you don t get suggestions for each word. That s where MultiAutoCompleteTextView comes in. You can use the MultiAutoCompleteTextView to provide suggestions as the user types
22 6
MultiAutoCompleteTextView
It requires that you give it a tokenizer that can parse the sentence and tell it whether to start suggesting again. <MultiAutoCompleteTextView android:id="@+id/mactv"
android:layout_width="fill_parent" android:layout_height="wrap_content" /> MultiAutoCompleteTextView mactv = (MultiAutoCompleteTextView) this .findViewById(R.id.mactv); ArrayAdapter<String> aa2 = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, new String[] {"English", "Hebrew", "Hindi", "Spanish", "German", "Greek" }); mactv.setAdapter(aa2); mactv.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
22 7
AutoCompleteTextViews
22 8
ListView Class
A child class of AdapterView class Shows items in a vertically scrolling list. The items come from the ListAdapter associated with this view
22 9
23 0
23 3
23 5
Spinner Class
A child class of AdapterView class Displays one child at a time and lets the user pick among them. The items in the Spinner come from the Adapter associated with this view There is NO special SpinnerActivity class, so you have to create Spinner object yourself
23 6
Example of Spinner
public class HelloSpinner extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Spinner spinner = (Spinner) findViewById(R.id.spinner); ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource( this, R.array.planets_array, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); spinner.setOnItemSelectedListener(new MyOnItemSelectedListener()); }
23 7
23 8
GridView Control
Android has a GridView control that can display data in the form of a grid. The contents of the grid can be text, images, and so on. The usage pattern for the GridView is :
Define the grid in the XML layout Bind the data to the grid.
23 9
Gallery Class
A child class of AdapterView class A view that shows items in a centerlocked, horizontally scrolling list
24 0
Example of Gallery
public class HelloGallery extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Gallery g = (Gallery) findViewById(R.id.gallery); g.setAdapter(new ImageAdapter(this)); g.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { Toast.makeText(HelloGallery.this, "" + position, Toast.LENGTH_SHORT).show(); } }); }
24 1
24 4
24 6
Don t
public View getView(int position, View convertView, ViewGroup parent) { View item = mInflater.inflate(R.layout.list_item_icon_text, null); ((TextView) item.findViewById(R.id.text)).setText(DATA[position]); ((ImageView) item.findViewById(R.id.icon)).setImageBitmap( (position & 1) == 1 ? mIcon1 : mIcon2); return item; }
24 7
Do
public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mInflater.inflate(R.layout.item, null); } ((TextView) convertView.findViewById(R.id.text)).setText(DATA[position]); ((ImageView) convertView.findViewById(R.id.icon)).setImageBitmap( (position & 1) == 1 ? mIcon1 : mIcon2); return convertView; }
24 8
Even better
static class ViewHolder { TextView text; ImageView icon; }
24 9
Even better
public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = mInflater.inflate(R.layout.list_item_icon_text, null); holder = new ViewHolder(); holder.text = (TextView) convertView.findViewById(R.id.text); holder.icon = (ImageView) convertView.findViewById(R.id.icon); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.text.setText(DATA[position]); holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2); return convertView; }
25 0
25 1
Defining Styles
To create a set of styles, save an XML file in the res/values/ directory of your project. The name of the XML file is arbitrary, but it must use the .xml extension and be saved in the res/values/ folder. The root node of the XML file must be <resources>. For each style you want to create, add a <style> element to the file with a name that uniquely identifies the style (this attribute is required). Then add an <item>element for each property of that style, with a name that declares the style property and a value to go with it (this attribute is required). The value for the <item> can be a keyword string, a hex color, a reference to another resource type, or other value depending on the style property
25 2
Example
<!-- normal sample !--> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <!-- style all the properties are moved to some resource file !--> <TextView style="@style/FillHorizontaly" android:text="@string/hello" /> <!-- definition of the style !--> <?xml version="1.0" encoding="utf-8"?> <resources> <style name="FillHorizontaly" parent="@android:style/TextAppearance.Medium"> <item name="android:layout_width">fill_parent</item> <item name="android:layout_height">wrap_content</item> </style> </resources>
25 3
25 5
Using Themes
One problem with styles is that you need to add an attribute specification of style="@style/..." to every view definition that you want it to apply to. If you have some style elements you want applied across an entire activity, or across the whole application, you should use a theme instead. A theme is really just a style applied broadly, but in terms of defining a theme, it's exactly like a style.
25 6
Using Themes
<resources> <style name=" MyTheme "> <item name=" ... "> ... </item> <item name=" ... "> ... </item> </style> </resources>
<?xml version="1.0" encoding="utf-8"?> <resources> <style name=" MyTheme "> <item name="panelForegroundColor"> #FFFFFFFF </item> <item name="panelBackgroundColor"> ?panelForegroundColor </item> <item name="panelTextSize"> 14 </item> <item name="menuItemTextColor"> ?panelTextColor </item> <item name="menuItemTextSize"> ?panelTextSize </item> </style> </resources>
25 7
Using Themes
Now that the theme is created, you can apply it to your application by editing the AndroidManifest.xml file of your application and adding the android:theme attribute to the application tag with its attribute as the theme's name you specified earlier. Example: <application android:theme="@style/MyTheme"> If you want to apply it to a single activity and not the whole application, edit the activity tag to add its attribute. <activity android:theme="@style/MyTheme">
25 8
Custom Attributes
Although it is nice to be able to override the default system properties in some cases, what we'd really like to do is define custom properties of our own in our application's layouts. Say we wanted the margins of all of our activities to be a certain dimension. Below is an example of a custom attribute added to our custom theme in themes.xml which we can use to define a property called pageMargin:
<item name="pageMargin">2sp</item>
25 9
Custom Attributes
If you simply copy the above text into your new file themes.xml, you will get a build error Error: No resource found that matches the given name: attr 'pageMargin'. This is because we have not defined what pageMargin is to the build system. Create a file called attrs.xml in res/values/. Here you will create your style attributes, which are any customizable attributes you would like for your theme to define.
<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="pageMargin" format="reference|dimension" /> </resources>
26 0
Custom Attributes
The format attribute indicates what type of values we can define for pageMargin; in this case, either a reference to another attribute, or a dimension such as 2sp or 4px. Other examples of possible formats are color,boolean, integer, and float. Now, I could set the margins in my views by referencing a single constant, instead of putting the same value piecemeal around the code:
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello" android:layout_margin="?pageMargin"/> 26 1
Handling UI Events
Events are actually system-generated messages that are sent to the View object whenever a UI element is accessed in some fashion by a user. Handling and handlers are two other terms used in conjunction with events in Java and Android. Once these events are triggered by a user s touch, keystroke, or navigation key, they must be handled within your application.
26 2
Listener
Callback
View.setOnKeyListener
onKey()
View.setOnTouchListener
onTouch()
View.setOnClickListener
onClick()
View.setOnLongClickListener
onLongClick()
View.setOnCreateContextMenuListener
onCreateContextMenu()
Long press on registered widget, usually ListView Focus shifts away from registered view
View.setOnFocusChanged
onFocusChanged()
26 5
Listener Implementations
Using a separate Listener class Using an anonymous inner class Using the main Activity
And having it implement the Listener interface
26 6
Approach
So, if event handler can be applied to different controls, it can be change independently from rest of app.
But, in most real situations, behavior is tightly coupled to app anyhow.
Disadvantages
If you want to call code in main Activity, you need reference Even then, that code in main Activity must be public 26 7
26 8
26 9
Advantages
Assuming that each class is applied to a single control only, it s a shorter approach. This approach is widely used in Swing, SWT, AWT, and GWT.
Disadvantages
If you applied the handler to more than one control, you would have to cut and paste the code for the handler. This approach should be applied for a single control only If the code for the handler is long, it makes the code harder to read by putting it inline. This approach is usually used only when handler code is short 27 0
27 1
Advantages
Assuming that the app has only a single control of that Listener type, this is the shortest and simplest of the approaches.
Disadvantages
Scales poorly to multiple controls unless they have completely identical behavior. This approach should be applied when your app has only a single control of that Listener type You cannot pass arguments to the Listener. So, again, works poorly for multiple controls 27 2
27 3
27 4
Services
A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication . For example, a service might handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.
27 5
Services
A service can essentially take two forms: Started :
A service is "started" when an application component (such as an activity) starts it by calling startService(). Once started, a service can run in the background indefinitely, even if the component that started it is destroyed. Usually, a started service performs a single operation and does not return a result to the caller. For example, it might download or upload a file over the network. When the operation is done, the service should stop itself. Bound A service is "bound" when an application component binds to it by calling bindService(). A bound service offers a client-server interface that allows components to interact with the service, send requests, get results. A bound service runs only as long as another application component is bound to it. Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed.
27 6
Services
To create a service, you must create a subclass of Service (or one of its existing subclasses). In your implementation, you need to override some callback methods. onStartCommand()
The system calls this method when another component, such as an activity, requests that the service be started, by calling startService(). Once this method executes, the service is started and can run in the background indefinitely. If you implement this, it is your responsibility to stop the service when its work is done, by calling stopSelf() or stopService()
27 7
Services
onBind()
The system calls this method when another component wants to bind with the service by calling bindService(). In your implementation of this method, you must provide an interface that clients use to communicate with the service, by returning an IBinder. You must always implement this method, but if you don't want to allow binding, then you should return null.
onCreate()
The system calls this method when the service is first created, to perform one-time setup procedures (before it calls either onStartCommand() or onBind()). If the service is already running, this method is not called.
onDestroy()
The system calls this method when the service is no longer used and is being destroyed. Your service should implement this to clean up any resources such as threads, registered listeners, receivers, etc. This is the last call the service receives.
27 8
28 1
Using IntentService
public class HelloIntentService extends IntentService { public HelloIntentService() { super("HelloIntentService"); } protected void onHandleIntent(Intent intent) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. long endTime = System.currentTimeMillis() + 5*1000; while (System.currentTimeMillis() < endTime) { synchronized (this) { try { wait(endTime - System.currentTimeMillis()); } catch (Exception e) { } } } } }
28 2
The service can be operated programmatically using an interface that it defines and exports.
Clients establish a connection to the Service object and use that connection to call into the service. established by calling Context.bindService() and closed by calling Context.unbindService()
Bound Services
Bound service is the server in a client-server interface. A bound service allows components (such as activities) to bind to the service, send requests, receive responses, and even perform interprocess communication (IPC). A bound service typically lives only while it serves another application component and does not run in the background indefinitely.
28 5
Bound Services(contd.)
A bound service is an implementation of the Service class that allows other applications to bind to it and interact with it. To provide binding for a service, you must implement the onBind() callback method. This method returns an IBinder object that defines the programming interface that clients can use to interact with the service
28 6
Bound Services(contd.)
A client can bind to the service by calling bindService(). It must provide an implementation of ServiceConnection, which monitors the connection with the service. When the Android system creates the connection between the client and service, it calls onServiceConnected() on the ServiceConnection, to deliver the IBinder that the client can use to communicate with the service
28 7
28 9
Return this instance of Binder from the onBind() callback method. In the client, receive the Binder from the onServiceConnected() callback method and make calls to the bound service using the methods provided.
29 0
An Intent-based publishsubscribe mechanism. Great for listening system events such as SMS messages.
29 1
Broadcast Receiver
A broadcast receiver is a component that does nothing but receive and react to broadcast announcements Your app can
Receive and react to system services (example: battery low) Receive and react to other apps broadcast announcements Initiate broadcasts to other apps
29 2
Registering
To register Broadcast Receiver, you can
Dynamically register with registerReceiver (in code) Using <register> tag in AndroidManifest.xml
29 3
1. Registering in Code
29 4
29 5
BroadcastReceiver
29 6
Sending Broadcast
Broadcast is sent using Intent and sendBroadcast or sendOrderedBroadcast methods Example:
Intent intent = new Intent( com.enlume.MSG_PRO"); sendBroadcast(intent);
29 7
Ordered Broadcasts
Sent with sendOrderedBroadcast. Each receiver executes in turn. Possible to propagate a result to next receiver. Order can be controlled using android:priority tag.
29 8
Receiver Lifecycle
Broadcast Receiver object is valid only for the duration of the onReceive(Context, Intent) method.
You cannot do anything asynchronous in here! Except you can start a service.. Which can start a thread
29 9
30 0
SQLite Database
Using SQLite
SQLite implements most of the SQL-92standard for SQL. It has partial support for triggers and allows most complex queries (exception made for outer joins). SQLITE does not implement referential integrity constraints through the foreign key constraint model. SQLite uses a relaxed data typing model. Instead of assigning a type to an entire column, types are assigned to individual values. Therefore it is possible to insert a string into numeric column and so on.
30 1
SQLite Database
A way of opening/creating a SQLITE database in your local Android s data space is given below SQLiteDatabasedb = this.openOrCreateDatabase("myfriendsDB", MODE_PRIVATE, null); where the assumed prefix for the database stored in the devices ram is: "/data/data/<CURRENT_namespace>/databases/". For instance if this app is created in a namespace called cis493.sql1 , the full name of the newly created database will be: /data/data/cis493.sql1/databases/myfriendsDB . This file could later be used by other activities in the app or exported out of the emulator (adbpush ) and given to a tool such as SQLITE_ADMINISTRATOR. MODEcould be: MODE_PRIVATE, MODE_WORLD_READABLE, and MODE_WORLD_WRITEABLE. Meaningful for apps consisting of multiples activities. 30 2
SQLite Database
Actionqueries and Retrievalqueries represent the most common operations against the database.
A retrieval query is typically a SQL-Select command in which a table holding a number of fields and rows is produced as an answer to a data request. An actionquery usually performs maintenance and administrative tasks such as manipulating tables, users, environment, etc.
30 4
Creating-Populating a Table
We will use the execSQL( )method to manipulate SQL action queries. The following example creates a new table called tblAmigo. The table has three fields: a numeric unique identifier called recID, and two string fields representing our friend s nameand phone. If a table with such a name exists it is first dropped and then created anew. Finally three rows are inserted in the table.
30 5
Creating-Populating a Table
Comments
The field recIDis defined as PRIMARY KEY of the table. The autoincrement feature guarantees that each new record will be given a unique serial number (0,1,2, ). The database data types are very simple, for instance we will use: text,varchar, integer, float, numeric, date, time, timestamp, blob, boolean, and so on. In general, any well-formed SQL action command (insert, delete, update, create, drop, alter, etc.) could be framed inside an execSQL( ) method. You should make the call to execSQLinside of a try-catch-finally block. Be aware of potential SQLiteExceptionsituations thrown by the method.
30 6
Using RawQuery(version 1)
Consider the following code fragmentCursor
c1 = db.rawQuery("select count(*) as Total from tblAMIGO",null);
The previous rawQuery contains a select-statement that counts the rows in the table tblAMIGO. The result of this count is held in a table having only one row and one column. The column is called Total . The cursor c1will be used to traverse the rows (one!) of the resulting table. Fetching a row using cursor c1requires advancing to the next record in the answer set. Later the (singleton) field total must be bound to a local Java variable.
30 8
Using ParametizedRawQuery(version 2)
Using arguments.Assume we want to count how many friends are there whose name is BBB and their recID> 1. We could use the following construction
String mySQL= "select count(*) as Total " + " from tblAmigo" + " where recID> ?" + " and name = ?"; String[] args= {"1", "BBB"}; Cursor c1 = db.rawQuery(mySQL, args);
30 9
Using RawQuery(version 3)
Using arguments : Assume we want to count how many friends are there whose name is BBB and their recID> 1. We could concatenate pieces of the string. Special care around (single) quoted strings.
String[] args= {"1", "BBB"}; String mySQL= " select count(*) as Total " + " from tblAmigo" + " where recID> " + args[0] + " and name = '" + args[1] + "'"; Cursor c1 = db.rawQuery(mySQL, null);
31 0
Simple Queries
Simple queries use a template implicitly representing a condensed version of a typical (non-joining) SQL select statement. No explicit SQL statement is made. Simple queries can only retrieve data from a single table. The method s signature has a fixed sequence of seven arguments representing:
the table name, the columns to be retrieved, the search condition (where-clause), arguments for the where-clause, the group-by clause, having-clause, and the order-by clause. 31 1
Simple Queries
The signature of the Android s simple query method is: query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
31 2
31 5
31 6
Updating a Row
Updating rows is also done with Content Values. Create a new ContentValues object, using the put methods to assign new values to each column you want to update. Call update on the database, passing in the table name, the updated Content Values object, and a where clause that specifies the row(s) to update
// Define the updated row content. ContentValues updatedValues = new ContentValues(); // Assign values for each row. newValues.put(COLUMN_NAME, newValue); [ ... Repeat for each column ... ] String where = KEY_ID + "=" + rowId; // Update the row with the specified index with the new values. myDatabase.update(DATABASE_TABLE, newValues, where, null);
31 7
Deleting Rows
To delete a row simply call delete on a database, specifying the table name and a where clause that returns the rows you want to delete.
myDatabase.delete(DATABASE_TABLE, KEY_ID + "=" + rowId, null);
31 8
Content Providers
Content providers store and retrieve data and make it accessible to all applications. They're the only way to share data across applications; there's no common storage area that all Android packages can access. Android ships with a number of content providers for common data types (audio, video, images, personal contact information, and so on). You can see some of them listed in the android.provider package.
32 0
Content Providers
If you want to make your own data public, you have two options:
You can create your own content provider you can add the data to an existing provider if there's one that controls the same type of data and you have permission to write to it.
Common interface for querying the data. Applications do not call these methods directly.
They use a ContentResolver object and call its methods instead.
ContentResolver cr = getContentResolver();
Content Providers
Content providers expose their data as a simple table on a database model, where each row is a record and each column is data of a particular type and meaning. A query returns a Cursor object that can move from record to record and column to column to read the contents of each field. Content provider exposes a public URI that uniquely identifies its data set
URIs begin with content:// Android Provides constants for native content providers, for example:
ContactsContract.Contacts.CONTENT_URI 32 2
Both methods take the same set of arguments, and both return a Cursor object. ManagedQuery() causes the activity to manage the life cycle of the Cursor. A managed Cursor handles all of the niceties, such as unloading itself when the activity pauses, and requerying itself when the activity restarts. To restrict a query to just one record, you can append the _ID value for that record to the URI that is, place a string matching the ID as the last segment of the path part of the URI.
For example, if the ID is 23, the URI would be: content://. . . ./23
There are some helper methods, particularly ContentUris.withAppendedId() and Uri.withAppendedPath(), that make it easy to append an ID to a URI 32 3
All data modification is accomplished using ContentResolver methods. If you don't have permission to write to a content provider, the ContentResolver methods will fail
32 6
Inserts
The Content Resolver offers two methods for inserting new records into your Content Provider
Insert bulkInsert.
Both methods accept the URI of the item type you re adding; where the former takes a single new ContentValues object, the latter takes an array. The simple insert method will return a URI to the newly added record BulkInsert returns the number of successfully added items
32 7
Inserts
// Create a new row of values to insert. ContentValues newValues = new ContentValues(); // Assign values for each row. newValues.put(COLUMN_NAME, newValue); [ ... Repeat for each column ... ] Uri myRowUri = getContentResolver().insert(MyProvider.CONTENT_URI, newValues); // Create a new row of values to insert. ContentValues[] valueArray = new ContentValues[5]; // TODO: Create an array of new rows int count = getContentResolver().bulkInsert(MyProvider.CONTENT_URI, valueArray);
32 8
Deletes
To delete a single record using the Content Resolver, call delete, passing in the URI of the row you want to remove. Alternatively, you can specify a where clause to remove multiple rows.
// Remove a specific row. getContentResolver().delete(myRowUri, null, null); // Remove the first five rows. String where = _id < 5 ; getContentResolver().delete(MyProvider.CONTENT_URI, where, null);
32 9
Updates
Updates to a Content Provider are handled using the update method on a Content Resolver. The update method takes the following :
URI of the target Content Provider ContentValues object that maps column names to updated values A where clause that specifi es which rows to update
33 0
Updates
// Create a new row of values to insert. ContentValues newValues = new ContentValues(); // Create a replacement map, specifying which columns you want to // update, and what values to assign to each of them. newValues.put(COLUMN_NAME, newValue); // Apply to the first 5 rows. String where = _id < 5 ; getContentResolver().update(MyProvider.CONTENT_URI, newValues, where, null);
33 1
33 2
Query
// Get a cursor over every contact. Cursor cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null); // Let the activity manage the cursor lifecycle. startManagingCursor(cursor); // Use the convenience properties to get the index of the columns int nameIdx = cursor.getColumnIndexOrThrow(People.NAME); int phoneIdx = cursor. getColumnIndexOrThrow(People.NUMBER); String[] result = new String[cursor.getCount()]; if (cursor.moveToFirst()) do { // Extract the name. String name = cursor.getString(nameIdx); // Extract the phone number. String phone = cursor.getString(phoneIdx); result[cursor.getPosition()] = name + ( + phone + ) ; } while(cursor.moveToNext());
33 4
33 5
33 6
Extend ContentProvider
public class MyContentProvider extends ContentProvider { public static final Uri CONTENT_URI = Uri.parse("content://fi.tamk.phonenumber"); @Override public int delete(Uri uri, String selection, String[] selectionArgs) {...} @Override public String getType(Uri uri) {...} @Override public Uri insert(Uri uri, ContentValues values) {...} @Override public boolean onCreate() {...} @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {...} @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {...} }
33 7
Manifest
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="fi.tamk" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".CallMe" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:name=".MyContentProvider" android:authorities="fi.tamk.phonenumber"></provider> </application> <uses-sdk android:minSdkVersion="8" /> </manifest>
33 8
My own provider
Cursor cur = managedQuery(MyContentProvider.CONTENT_URI, null, null, null, null);
33 9
Content Providers
A content provider makes a specific set of the application's data available to other applications.
The data can be stored in the file system, in an SQLite, or in any other manner that makes sense.
Application Activity Application Activity Content Resolver Activity Application Service
Content Resolver
Content Provider
Content Resolver
Data
SQLite
XML
Remote Store
Multi-Threading
Threads
A Thread is a concurrent unit of execution. Thread has its own call stack for methods being invoked, their arguments and local variables. Each virtual machine instance has at least one main Thread running when it is started; typically, there are several others for housekeeping. The application might decide to launch additional Threads for specific purposes.
34 1
Multi-Threading
Thread Threads in the same VM interact and synchronize by the use of shared objects and monitors associated with these objects. There are basically two main ways of having a Thread execute application code.
Create a new class that extends Thread and override its run() method. Create a new Thread instance passing to it a Runnable object. In both cases, the start() method must be called to actually execute the new Thread.
34 2
Multi-Threading
34 3
Advantages of MultiThreading
Threads share the process' resources but are able to execute independently. Applications responsibilities can be separated
main thread runs UI, and slow tasks are sent to background threads.
Threading provides an useful abstraction of concurrent execution. Particularly useful in the case of a single process that spawns multiple threads on top of a multiprocessor system. In this case real parallelism is achieved. Consequently, a multithreaded program operates faster on computer systems that have multiple CPUs.
34 4
Disadvantages of Multi-Threading
Code tends to be more complex Need to detect, avoid, resolve deadlocks
34 5
Multi-Threading
When an application is launched, the system creates a thread called "main" for the application. The main thread, also called the UI thread, is very important because it is in charge of dispatching the events to the appropriate widgets, including drawing events. It is also the thread where your application interacts with running components of the Android UI toolkit.
34 6
Multi-Threading
This single-thread model can yield poor performance unless your application is implemented properly. If everything is happening in a single thread, performing long operations on the UI thread will block the whole user interface. If the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with "application not responding" (ANR) dialog
34 7
Multi-Threading
Here's an example of a click listener downloading an image over the network and displaying it in an ImageView:
public void onClick(View v) { new Thread(new Runnable() { public void run() { Bitmap b = loadImageFromNetwork(); mImageView.setImageBitmap(b); } }).start(); }
The Android UI toolkit is not thread-safe and must always be manipulated on the UI thread. In this piece of code above, the ImageView is manipulated on a worker thread, which can cause really weird problems
34 8
Multi-Threading
Android offers several ways to access the UI thread from other threads
Handler objects Posting Runnable objects to the main view. Using AsyncTask class
34 9
Handler Class
When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the top-level application objects (activities, intent receivers, etc) and any windows they create. You can create your own secondary threads, and communicate back with the main application thread through a Handler. When you create a new Handler, it is bound to the message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
35 0
Threads and UI
Warning
Background threads are not allowed to interact with the UI. Only the main process can access the (main) activity s view. (Global) class variables can be seen and updated in the threads
35 1
Handler s MessageQueue
A secondary thread that wants to communicate with the main thread must request a message token using the obtainMessage() method. Once obtained, the background thread can fill data into the message token and attach it to the Handler s message queue using the sendMessage() method. The Handler uses the handleMessage() method to continuously attend new messages arriving to the main thread. A message extracted from the process queue can either return some data to the main process or request the execution of runnable objects through the post() method.
35 2
Multi-Threading
35 3
Multi-Threading
35 4
Messages
To send a Message to a Handler, the thread must first invoke obtainMessage() to get the Message object out of the pool. There are a few forms of obtainMessage(), allowing you to just create an empty Message object, or messages holding arguments Example
// thread 1 produces some local data String localData = Greeting from thread 1 ; // thread 1 requests a message & adds localData to it Message mgs = myHandler.obtainMessage (1, localData);
35 5
sendMessage Methods
You deliver the message using one of the sendMessage...() family of methods, such as
sendMessage() puts the message at the end of the queue immediately sendMessageAtFrontOfQueue() puts the message at the front of the queue immediately (versus the back, as is the default), so your message takes priority over all others sendMessageAtTime() puts the message on the queue at the stated time, expressed in the form of milliseconds based on system uptime (SystemClock.uptimeMillis()) sendMessageDelayed() puts the message on the queue after a delay, expressed in milliseconds
35 6
Processing Messages
To process messages sent by the background threads, your Handler needs to implement the listener handleMessage( . . . ) which will be called with each message that appears on the message queue. There, the handler can update the UI as needed. However, it should still do that work quickly, as other UI work is suspended until the Handler is done.
35 7
35 8
35 9
36 0
36 1
36 2
36 3
36 4
36 5
36 7