Professional Documents
Culture Documents
Learn Android in The University - Part2
Learn Android in The University - Part2
Amir Hammami
1
Learn Android in the University
2
Learn Android in the University
Email: amir.hammami@su.edu.sa
3
Learn Android in the University
4
Learn Android in the University
- What is Layout?
- Android Layout Types
- LinearLayout
- RelativeLayout
- TableLayout
- GridLayout
- FrameLayout
An Android layout is a class that handles arranging the way its children appear on the screen. Anything that is a View (or
inherits from View) can be a child of a layout.
All of the layouts inherit from ViewGroup (which inherits from View) so you can nest layouts. You could also create your
own custom layout by making a class that inherits from ViewGroup.
A View usually draws something the user can see and interact with. Whereas a ViewGroup is an invisible container that
defines the layout structure for View and other ViewGroup objects. The image below illustrates the inheritance hierarchy
between views in Android.
5
Learn Android in the University
1.3. The standard Layouts:
There are number of Layouts provided by Android which you will use in almost all the Android applications to provide
different view, look and feel.
Layout Description
LinearLayout
LinearLayout is a view group that aligns all children in a single direction, vertically or
(Horizontal)
horizontally.
(Vertical)
RelativeLayout
TableLayout
GridLayout
GridLayout uses a grid of infinitely-thin lines to separate its drawing area into: rows,
columns, and cells. It supports both row and column spanning, which together allow a
widget to occupy a rectangular range of cells that are next to each other.
FrameLayout
The FrameLayout is a placeholder on screen that you can use to display a single view.
AbsoluteLayout enables you to specify the exact location of its children. Arrange the
AbsoluteLayout
children views according coordinates x, y.
6
Learn Android in the University
1.4. LinearLayout
LinearLayout is a view group that aligns all children in a single direction, vertically or horizontally. You can specify the
layout direction with the android:orientation attribute.
Attributes:
Attribute Description
This specifies the direction of arrangement and you will use "horizontal" for a row,
android:orientation
"vertical" for a column. The default is horizontal.
android:layout_weight
This attribute assigns an "importance" value to a view in terms of how much space it should occupy on the screen. A larger
weight value allows it to expand to fill any remaining space in the parent view. Child views can specify a weight value, and
then any remaining space in the view group is assigned to children in the proportion of their declared weight. Default
weight is zero.
7
Learn Android in the University
The subcomponents that have weight will fill the remaining space of LinearLayout in proportion to its weight.
8
Learn Android in the University
With LinearLayout (Vertical), subcomponents that have android:layout_width=match_parent attribute will fill the
width of LinearLayout (Vertical).
Subcomponents can also be set a specific value for the width, height:
9
Learn Android in the University
android:gravity sets the gravity of the content of the View its used on (for example, Text).
10
Learn Android in the University
activity_linear_layout.xml
<Button
android:id="@+id/button"
android:layout_width="300dp"
android:layout_height="100dp"
android:layout_weight="0"
android:text="Button" />
<Button
android:id="@+id/button2"
android:layout_width="300dp"
android:layout_height="100dp"
android:layout_weight="0"
android:text="Button" />
<Button
android:id="@+id/button3"
android:layout_width="300dp"
android:layout_height="100dp"
android:layout_weight="0"
android:text="Button" />
11
Learn Android in the University
</LinearLayout>
1.5. Exercice
Complete the layout file to match the image below.
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_weight="0"
android:text="Go to Activity Two in the project" />
<Button
android:id="@+id/button2"
android:layout_width="250dp"
android:layout_height="100dp"
android:layout_weight="0"
android:text="Button"
android:layout_gravity="center"/>
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_weight="0"
12
Learn Android in the University
android:text="Button"
android:layout_gravity="right"
android:gravity="bottom"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
13
Learn Android in the University
1.6. RelativeLayout
RelativeLayout is a view group that displays child views in relative positions. The position of each view can be specified as
relative to sibling elements (such as to the left-of or below another view) or in positions relative to the parent
RelativeLayout area (such as aligned to the bottom, left or center).
A RelativeLayout is a very powerful utility for designing a user interface because it can eliminate nested view groups and
keep your layout hierarchy flat, which improves performance. If you find yourself using several nested LinearLayout
groups, you may be able to replace them with a single RelativeLayout.
activity_relative_layout.xml
14
Learn Android in the University
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LinearLayoutActivity"
android:orientation="vertical">
<Button
android:id="@+id/button"
android:layout_width="70dp"
android:layout_height="130dp"
android:layout_weight="0"
android:text="Button" />
<Button
android:id="@+id/button2"
android:layout_width="116dp"
android:layout_height="102dp"
android:layout_alignParentTop="true"
android:layout_marginStart="40dp"
android:layout_marginLeft="40dp"
android:layout_marginTop="174dp"
android:layout_toEndOf="@+id/button"
android:layout_toRightOf="@+id/button"
android:layout_weight="0"
android:text="Button" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="95dp"
android:layout_alignParentBottom="true"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginBottom="90dp"
android:layout_toEndOf="@+id/button2"
android:layout_toRightOf="@+id/button2"
android:layout_weight="0"
android:text="Button" />
</RelativeLayout>
1.7. Exercice
15
Learn Android in the University
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="141dp"
android:layout_marginStart="141dp"
android:layout_marginTop="89dp"
android:text="Sign In"
android:textColor="@android:color/black"
android:textColorLink="@android:color/black"
android:textSize="28sp" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:layout_alignStart="@+id/textView5"
android:layout_alignLeft="@+id/textView5"
android:layout_marginStart="30dp"
android:layout_marginLeft="30dp"
android:layout_marginTop="44dp"
android:text="ID"
android:textColor="@android:color/black"
android:textSize="18sp"
android:typeface="normal" />
<EditText
android:id="@+id/editText"
android:layout_width="272dp"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/textView2"
android:layout_alignStart="@+id/editText2"
16
Learn Android in the University
android:layout_alignLeft="@+id/editText2"
android:layout_alignBottom="@+id/textView2"
android:ems="10"
android:inputType="textPersonName"
android:text="Enter ID" />
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/editText2"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_marginStart="22dp"
android:layout_marginLeft="22dp"
android:layout_marginBottom="-2dp"
android:text="Password"
android:textColor="@android:color/black"
android:textSize="18sp" />
<EditText
android:id="@+id/editText2"
android:layout_width="272dp"
android:layout_height="wrap_content"
android:layout_below="@+id/editText"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginTop="0dp"
android:ems="10"
android:inputType="textPassword"
android:text="Password" />
<Button
android:id="@+id/S"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/editText2"
android:layout_marginTop="32dp"
android:text="SignIn" />
</RelativeLayout>
17
Learn Android in the University
1.8. TableLayout
TableLayout is a ViewGroup that displays child View elements in rows and columns.
TableLayout positions its children into rows and columns. TableLayout containers do not display border lines for their
rows, columns, or cells. The table will have as many columns as the row with the most cells. A table can leave cells empty,
but cells cannot span vertical, as they can in HTML.
TableRow
TableRow objects are the child views of a TableLayout (each TableRow defines a single row in the table). Each row has
zero or more cells, each of which is defined by any kind of other View. So, the cells of a row may be composed of a variety
of View objects, like ImageView or TextView objects. A cell may also be a ViewGroup object (for example, you can nest
another TableLayout as a cell).
18
Learn Android in the University
TableRow will be automaticcally created (if that row has not been existed) when you drag Subview to the table cell.
19
Learn Android in the University
Cells can span horizontally, but not vertically. There may be those cells do not contain any subView.
You can set a specific size for the View in cell, it will change the size of cell.
20
Learn Android in the University
You can set android:layout_gravity and android:gravity attributes for views in cell. I have described in detail in
LinearLayout.
21
Learn Android in the University
Example
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:layout_gravity="bottom"/>
<Button
android:id="@+id/button5"
android:layout_width="141dp"
android:layout_height="193dp"
android:gravity="top"
android:text="Button" />
<Button
android:id="@+id/button7"
android:layout_width="181dp"
android:layout_height="wrap_content"
android:text="Button"
android:layout_gravity="center"/>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/button8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<Button
android:id="@+id/button6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:layout_column="2"/>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button9"
android:layout_width="30dp"
android:layout_gravity="center"
android:layout_height="match_parent"
android:layout_column="1"
android:text="Button" />
</TableRow>
</TableLayout>
23
Learn Android in the University
1.9. GridLayout
GridLayout uses a grid of infinitely-thin lines to separate its drawing area into: rows, columns, and cells. It supports both
row and column spanning, this means it is possible to merge adjacent cells into a large cell (a rectangle) to contain a View.
In GridLayout, specifying sizes and margins is done just as with a LinearLayout. Alignment/gravity also works just like
gravity in LinearLayout and uses the same constants: left, top, right, bottom, center_horizontal, center_vertical, center,
fill_horizontal, fill_vertical and fill.
Flexibility
Unlike most grids in other toolkits, Android GridLayout does not associate data with rows or columns. Instead, everything
to do with alignment and flexibility is associated with the components themselves.
The flexibility of columns is inferred from the gravity of the components inside the column. If every component defines a
gravity, the column is taken as flexible, otherwise the column is considered inflexible
24
Learn Android in the University
Subcomponents determine its position in the grid according to the layout_row & layout_column attributes:
With GridLayout, if there is no object displaces grid column, the width of the grid at which is 0. Similarly, if row does not
be displaced by any objects, the height of the grid at which is 0.
layout_columnWeight
25
Learn Android in the University
In GridLayout, layout_columnWeight attribute is weight by column of the object in the cell, it may affect the occupancy by
column, the default value is 0.
26
Learn Android in the University
layout_rowSpan
27
Learn Android in the University
layout_rowWeight
In GridLayout, layout_rowWeight attribute is weight by row of the object in the cell, it may affect the occupancy by row,
the default value is 0.
28
Learn Android in the University
layout_columnSpan
29
Learn Android in the University
Example1: RowSpan
<Button
android:id="@+id/button10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1"
android:layout_row="0"
android:layout_column="0"
/>
<Button
android:id="@+id/button11"
android:layout_width="110dp"
android:layout_height="199dp"
android:layout_row="1"
android:layout_rowSpan="3"
android:layout_column="1"
android:text="Button2" />
<Button
android:id="@+id/button12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button3"
android:layout_row="3"
android:layout_column="3"/>
<Button
android:id="@+id/button13"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button3"
android:layout_row="4"
android:layout_column="2"/>
</GridLayout>
Example2: ColSpan
31
Learn Android in the University
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".LinearLayoutActivity"
>
<Button
android:id="@+id/button10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1"
android:layout_row="0"
android:layout_column="0"
/>
<Button
android:id="@+id/button11"
android:layout_width="110dp"
android:layout_height="251dp"
android:layout_row="1"
android:layout_rowSpan="3"
android:layout_column="1"
android:text="Button2" />
<Button
android:id="@+id/button12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button3"
android:layout_row="3"
android:layout_column="3"/>
<Button
android:id="@+id/button13"
android:layout_width="145dp"
android:layout_height="wrap_content"
android:layout_row="4"
android:layout_column="2"
android:layout_columnSpan="2"
android:text="Button3" />
</GridLayout>
32
Learn Android in the University
Exercise
Can you use GridLayout to design interface as shown below?
33
Learn Android in the University
1.10. FrameLayout
The FrameLayout is a placeholder on screen that you can use to display a single View.
Example:
bg.jpg
34
Learn Android in the University
Drag and drop ImageView into the screen at left + top area.
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="257dp"
android:layout_gravity="top"
app:srcCompat="@drawable/bg" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="15dp"
android:text=""مرحبا في عفيف
android:textColor="@color/colorPrimaryDark"
android:textSize="30sp"
android:layout_gravity="center_horizontal"/>
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""طقس جميل ومشمس
android:layout_gravity="top"
android:textColor="#000000"
36
Learn Android in the University
android:textSize="30dp"
android:paddingTop="150dp"
android:paddingLeft="100dp"/>
</FrameLayout>
37
Learn Android in the University
OnClickListener(): This event listener is called when a user clicks on any UI element like button, text or image.
OnClick() event handler is used to handle this listener.
OnLongClickListener(): This method is called when a user clicks on any UI element for a long time or hold a
UI element for few seconds. OnLongClick() event handler is used to handle this listener.
OnFocusChangeListener(): This method is called when a UI element or a widget losses its focus. Simply user
navigates forward. OnFocusChange() event handler is used to handle this listener.
OnKeyListener(): This method is called when a user presses a key on keyboard. OnKey() event handler is used
to handle this event.
OnTouchListener(): This method is called when a user touches any UI element on the screen like press or
release a button. OnTouch() event handler is used to handle this listener.
OnMenuItemClickListener(): This method is used when a user clicks or selects a menu
item.OnMenuItemClick() event handler is used to handle this listener.
OnCreateContextMenuListener(): OnCreateContextMenu() event handler is used to handle this listener.
package com.ksa.ah.eventhandler;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.graphics.Color;
38
Learn Android in the University
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
welcome = (TextView)findViewById(R.id.tv_welcome);
java = (TextView)findViewById(R.id.tv_java);
if(i==0) {
welcome.setTextColor(Color.BLACK);
java.setTextColor(Color.BLACK);
button.setBackgroundColor(Color.BLACK);
}
if(i==1) {
welcome.setTextColor(Color.GREEN);
java.setTextColor(Color.GREEN);
button.setBackgroundColor(Color.GREEN);
}
if(i==2) {
welcome.setTextColor(Color.BLUE);
java.setTextColor(Color.BLUE);
button.setBackgroundColor(Color.BLUE);
}
if(i==3) {
welcome.setTextColor(Color.MAGENTA);
java.setTextColor(Color.MAGENTA);
button.setBackgroundColor(Color.MAGENTA);
i=0;
}
if (i==4) {
i = 0;
}
i++;
}
}
activity_main.xml
<TextView
android:id="@+id/tv_welcome"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Welcome to "
android:textColor="@android:color/holo_red_dark"
android:textSize="40dp"
android:layout_centerVertical="true"
39
Learn Android in the University
android:layout_centerHorizontal="true" />
<TextView
android:id="@+id/tv_java"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/holo_red_dark"
android:textSize="40dp"
android:layout_marginTop="21dp"
android:text="KSA - Afif"
android:layout_below="@+id/tv_welcome"
android:layout_centerHorizontal="true" />
<Button
android:id="@+id/button"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:background="@android:color/holo_red_dark"
android:text="Change Color"
android:textColor="@android:color/background_light"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="70dp"
android:onClick="changeColor"/>
</RelativeLayout>
40
Learn Android in the University
When user will click on button the color of text will change. Initially color of text is red, on first click color will change
black, on second click color will change to green and so on
2.5. Case 2:
package com.ksa.ah.eventhandler;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
41
Learn Android in the University
import android.widget.TextView;
import android.graphics.Color;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_in_line);
welcome = (TextView)findViewById(R.id.tv_welcome);
java = (TextView)findViewById(R.id.tv_java);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(i==0) {
welcome.setTextColor(Color.BLACK);
java.setTextColor(Color.BLACK);
button.setBackgroundColor(Color.BLACK);
}
if(i==1) {
welcome.setTextColor(Color.GREEN);
java.setTextColor(Color.GREEN);
button.setBackgroundColor(Color.GREEN);
}
if(i==2) {
welcome.setTextColor(Color.BLUE);
java.setTextColor(Color.BLUE);
button.setBackgroundColor(Color.BLUE);
}
if(i==3) {
welcome.setTextColor(Color.MAGENTA);
java.setTextColor(Color.MAGENTA);
button.setBackgroundColor(Color.MAGENTA);
i=0;
}
if (i==4) {
i = 0;
}
i++;
}
});
}
}
42
Learn Android in the University
<TextView
android:id="@+id/tv_welcome"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Welcome to "
android:textColor="@android:color/holo_red_dark"
android:textSize="40dp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
<TextView
android:id="@+id/tv_java"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/holo_red_dark"
android:textSize="40dp"
android:layout_marginTop="21dp"
android:text="KSA - Afif"
android:layout_below="@+id/tv_welcome"
android:layout_centerHorizontal="true" />
<Button
android:id="@+id/button"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:background="@android:color/holo_red_dark"
android:text="Change Color"
android:textColor="@android:color/background_light"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="70dp"/>
</RelativeLayout>
2.6. Case 3:
package com.ksa.ah.eventhandler;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.graphics.Color;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_implement);
welcome = (TextView)findViewById(R.id.tv_welcome);
java = (TextView)findViewById(R.id.tv_java);
button = (Button) findViewById(R.id.button);
43
Learn Android in the University
button.setOnClickListener(this);
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.button) {
if (i == 0) {
welcome.setTextColor(Color.BLACK);
java.setTextColor(Color.BLACK);
button.setBackgroundColor(Color.BLACK);
}
if (i == 1) {
welcome.setTextColor(Color.GREEN);
java.setTextColor(Color.GREEN);
button.setBackgroundColor(Color.GREEN);
}
if (i == 2) {
welcome.setTextColor(Color.BLUE);
java.setTextColor(Color.BLUE);
button.setBackgroundColor(Color.BLUE);
}
if (i == 3) {
welcome.setTextColor(Color.MAGENTA);
java.setTextColor(Color.MAGENTA);
button.setBackgroundColor(Color.MAGENTA);
i = 0;
}
if (i == 4) {
i = 0;
}
i++;
}
}
}
<TextView
android:id="@+id/tv_welcome"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Welcome to "
android:textColor="@android:color/holo_red_dark"
android:textSize="40dp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
<TextView
android:id="@+id/tv_java"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
44
Learn Android in the University
android:textColor="@android:color/holo_red_dark"
android:textSize="40dp"
android:layout_marginTop="21dp"
android:text="KSA - Afif"
android:layout_below="@+id/tv_welcome"
android:layout_centerHorizontal="true" />
<Button
android:id="@+id/button"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:background="@android:color/holo_red_dark"
android:text="Change Color"
android:textColor="@android:color/background_light"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="70dp"/>
</RelativeLayout>
2.7. Case 4
package com.ksa.ah.eventhandler;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_class);
welcome = (TextView)findViewById(R.id.tv_welcome);
java = (TextView)findViewById(R.id.tv_java);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new ListenerImplement(this));
}
<TextView
android:id="@+id/tv_welcome"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Welcome to "
android:textColor="@android:color/holo_red_dark"
android:textSize="40dp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
<TextView
android:id="@+id/tv_java"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/holo_red_dark"
android:textSize="40dp"
android:layout_marginTop="21dp"
android:text="KSA - Afif"
android:layout_below="@+id/tv_welcome"
android:layout_centerHorizontal="true" />
46
Learn Android in the University
<Button
android:id="@+id/button"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:background="@android:color/holo_red_dark"
android:text="Change Color"
android:textColor="@android:color/background_light"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="70dp"/>
</RelativeLayout>
To use dragging a view you register a OnTouchListener or a LongClickListener on the view which can be dragged.
The startDrag method of the View start a drag operation. In this method you also specify the data which is passed to the
drop target via an instance of ClipData.
You also pass to the startDrag method an instance of DragShadowBuilder. This object specifies the picture used for the
drag operation. For example, you can pass in the view directly, that shows an image of the view during the drag operation.
The setup of this drag operation in a touch listener is demonstrated in the following example.
47
Learn Android in the University
A view with OnDragListener which are used as a drop zone, gets a OnDragListener assigned via the setOnDragListener.
48
Learn Android in the University
49
Learn Android in the University
Create project
Create a new Android project called com.vogella.android.draganddrop with an activity called DragActivity.
In this part you create several XML drawables in the res/drawable folder.
<stroke
android:width="2dp"
android:color="#FFFFFFFF" />
<gradient
android:angle="225"
android:endColor="#DD2ECCFA"
android:startColor="#DD000000" />
<corners
android:bottomLeftRadius="7dp"
android:bottomRightRadius="7dp"
android:topLeftRadius="7dp"
android:topRightRadius="7dp" />
</shape>
50
Learn Android in the University
Also create the following shape_droptarget.xml file.
<stroke
android:width="2dp"
android:color="#FFFF0000" />
<gradient
android:angle="225"
android:endColor="#DD2EFA61"
android:startColor="#00BCD4" />
<corners
android:bottomLeftRadius="7dp"
android:bottomRightRadius="7dp"
android:topLeftRadius="7dp"
android:topRightRadius="7dp" />
</shape>
51
Learn Android in the University
<LinearLayout
android:id="@+id/top"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="160dp"
android:layout_row="0"
android:background="@drawable/shape" >
<ImageView
android:id="@+id/myimage1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
</LinearLayout>
<LinearLayout
android:id="@+id/bottom"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="160dp"
android:background="@drawable/shape" >
<ImageView
android:id="@+id/myimage2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
</LinearLayout>
</LinearLayout>
package com.ksa.ah.draganddrop;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.content.ClipData;
import android.graphics.drawable.Drawable;
import android.view.DragEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnDragListener;
52
Learn Android in the University
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.LinearLayout;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
enterShape = getResources().getDrawable(R.drawable.shape_droptarget);
normalShape = getResources().getDrawable(R.drawable.shape);
findViewById(R.id.myimage1).setOnTouchListener(dragListener);
findViewById(R.id.myimage2).setOnTouchListener(dragListener);
findViewById(R.id.top).setOnDragListener(this);
findViewById(R.id.bottom).setOnDragListener(this);
@Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
// Do nothing
break;
case DragEvent.ACTION_DRAG_ENTERED:
v.setBackground(enterShape);
break;
case DragEvent.ACTION_DRAG_EXITED:
v.setBackground(normalShape);
break;
case DragEvent.ACTION_DROP:
// view dropped, reassign the view to the new ViewGroup
View view = (View) event.getLocalState();
ViewGroup owner = (ViewGroup) view.getParent();
owner.removeView(view);
LinearLayout container = (LinearLayout) v;
container.addView(view);
view.setVisibility(View.VISIBLE);
break;
case DragEvent.ACTION_DRAG_ENDED:
v.setBackground(normalShape);
default:
break;
53
Learn Android in the University
}
return true;
}
}
If you start this activity you should be able to drag the ImageViews to another container
3.4. Exercie
54
Learn Android in the University
55
Learn Android in the University
4.2. Drag and Drop Process
The Drag and Drop framework will include following functionalities to support the data movement in android
applications.
Generally, the Drag and Drop process starts when user making gestures recognized as a signal to start dragging data and
application tells the system that the drag is starting.
Once the drag is starting, the system call-back to our application to get the state of data being dragged and it sends drag
events to the drag event listeners or call-back methods of each View in the layout.
In android, the Drag and Drop process contains a 4 steps or states, those are:
Started
Continuing
Dropped
Ended
Started
This event will occur when we start dragging an item in layout and our application will call startDrag() method to tell the
system to start a drag. The startDrag() method arguments will provide a data to be dragged, metadata for this data and a
call-back for drawing the drag shadow.
The system will respond back to our application to get a drag shadow and it will display the drag shadow on the device.
After that, the system will send a drag event with action type ACTION_DRAG_STARTED to the drag event listeners for all
the View objects in the current layout. To receive drag events continuously, including a possible drop event, the drag event
listener must return true and it registers the listener with the system because only registered listeners continue to receive
drag events. At this point, listeners can also change the appearance of their View object to show that the listener can accept
a drop event.
In case if drag event listener returns false, then it won’t receive any drag events for the current operation until the system
sends a drag event with action type ACTION_DRAG_ENDED. By sending false, the listener tells the system that it is not
interested in the drag operation and does not want to accept the dragged data.
Continuing
When the user continues to drag, the drag shadow intersects with the bounding box of a View object and the system sends
one or more drag events to the View object's drag event listener (In case if it is registered to receive events).
In response to the event, the listener may choose to alter its View object’s appearance. For example, if the event indicates
that the drag shadow has entered the bounding box of the View (action type ACTION_DRAG_ENTERED), the listener can
react by highlighting its View.
Dropped
Whenever the user releases the drag shadow within the bounding box of a View that can accept the data. The system sends
the View object's listener a drag event with action type ACTION_DROP.
The drag event will contain the data that is passed to the system while starting the operation by using startDrag() method
and the listener will return true to the system in case if drop success.
56
Learn Android in the University
Ended
After completion of action type ACTION_DROP, the system sends out a drag event with action type
ACTION_DRAG_ENDED to indicate that the drag operation is over. This is done regardless of where the user released the
drag shadow.
We can use both listener and call-back method for View objects but in most cases listener is preferable. In case if we use
both method and listener, first system calls the listener and then defined call-back method as long as the listener returns
true.
import android.view.View.OnDragListener;
Defined as:
Interface definition for a callback to be invoked when a drag is being dispatched to this view. The callback will be invoked
before the hosting view's own onDrag(event) method. If the listener wants to fall back to the hosting view's onDrag(event)
behavior, it should return 'false' from this callback.
Called when a drag event is dispatched to a view. This allows listeners to get a chance to override base View behavior.
Parameters
Returns
boolean true if the drag event was handled successfully, or false if the drag event was not handled. Note
that false will trigger the View to call its onDragEvent() handler.
The listener calls getAction() method to get the action type from DragEvent object. Following are the different type of
action types available in DragEvent object.
Action Type Description
ACTION_DRAG_STARTED A View object's drag event listener receives this action type event just after the application
calls startDrag() and gets a drag shadow.
ACTION_DRAG_ENTERED A View object's drag event listener receives this action type when the drag shadow has
entered the bounding box of the View. This is the first action type event, the listener
receives when the drag shadow enters the bounding box.
ACTION_DRAG_LOCATIO A View object's drag event listener receives this action type event after it receives an
N ACTION_DRAG_ENTERED event while the drag shadow is still within the bounding box of
the View.
ACTION_DRAG_EXITED A View object's drag event listener receives this action type event after it receives an
ACTION_DRAG_ENTERED and at least one ACTION_DRAG_LOCATION event, and after the
user has moved the drag shadow outside the bounding box of the View.
ACTION_DROP A View object's drag event listener receives this action type event when the user releases
the drag shadow over the View object.
ACTION_DRAG_ENDED A View object's drag event listener receives this action type event when the system is
ending the drag operation.
The DragEvent object also contains the data that our application provided to the system in the call to startDrag(). Some of
the data is valid only for certain action types.
By using View.DragShadowBuilder object methods, we can display an image of View that the user drags and then pass it to
the system when we start a drag using startDrag() method. As part of its response to startDrag(), the system invokes the
methods that we defined in View.DragShadowBuilder to obtain a drag shadow
58
Learn Android in the University
4.6. Android Designing a Drag and Drop Operation
Following is the step-by-step how to start a drag event, how to respond to events during the drag, how respond to a drop
event, and how to end the drag and drop operation.
We need to create a ClipData and ClipData.item for the data that is being moved. As a part of the ClipData object, we need
to send a metadata that is stored in a ClipDescription object within the ClipData. For a drag and drop operation that does
not represent data movement, we may need to use null instead of an actual object.
After that, we need to use View.DragShadowBuilder(View) to create a drag shadow for the View objects that is being
moved. The View.DragShadowBuilder will create a default drag shadow that’s same size as the View argument passed to it.
In case, if we want to customize the drag shadow, then we need to extend the View.DragShadowBuilder functionality
based on our requirements.
For example, following is the code snippet which shows how to respond for a long press on View object by creating a
ClipData object that contains the tag or label of a View object.
@Override
public boolean onLongClick(View v) {
// Create a new ClipData using the tag as a label, the plain text MIME type, and
// the already-created item. This will create a new ClipDescription object within the
// ClipData, and set its MIME type entry to "text/plain"
String[] mimeTypes = {ClipDescription.MIMETYPE_TEXT_PLAIN};
ClipData data = new ClipData(v.getTag().toString(), mimeTypes, item);
This is how we can respond for a long press on View object by creating a ClipData object in android applications.
In response to an event with the action type ACTION_DRAG_STARTED, the listener will do the following things.
- The listener will call getClipDescription() to get the ClipDescription details and it uses a MIME type methods in
ClientDescription to decide whether to accept the data being dragged or not. In case if the drag and drop operation
does not represent any data movement, then it does not required.
- If the listener can accept a drop, it should return true. This tells the system to continue to send drag events to the
listener. If it can't accept a drop, it should return false, and the system will stop sending drag events until it sends
out ACTION_DRAG_ENDED.
- The listener will call getClipData() to get the ClipData object that was originally supplied in the call to startDrag()
and store it. If the drag and drop operation does not represent data movement, this may not be necessary.
- It will return either true or false to indicate that whether the drop was processed successfully or not and it return
the value from getResult() method in ACTION_DRAG_ENDED event.
- During the operation, in case if the listener changed its View object's appearance, it should reset the View to its
default appearance to indicate that the operation is over.
- The listener can optionally call getResult() to find out more about the operation.
60
Learn Android in the University
For example, following is the code snippet which shows how to respond for drag events in a listener.
// This is the method that the system calls when it dispatches a drag event to the listener.
@Override
public boolean onDrag(View v, DragEvent event) {
// Defines a variable to store the action type for the incoming event
int action = event.getAction();
// Handles each of the expected events
switch (action) {
case DragEvent.ACTION_DRAG_STARTED:
case DragEvent.ACTION_DRAG_ENTERED:
// Applies a YELLOW or any color tint to the View. Return true; the return value is ignored.
v.getBackground().setColorFilter(Color.YELLOW, PorterDuff.Mode.SRC_IN);
// Invalidate the view to force a redraw in the new tint
v.invalidate();
return true;
case DragEvent.ACTION_DRAG_LOCATION:
// Ignore the event
return true;
case DragEvent.ACTION_DRAG_EXITED:
// Re-sets the color tint to blue, if you had set the BLUE color or any color in ACTION_DRAG_STARTED.
Returns true; the return value is ignored.
v.getBackground().setColorFilter(Color.BLUE, PorterDuff.Mode.SRC_IN);
//If u had not provided any color in ACTION_DRAG_STARTED then clear color filter.
v.getBackground().clearColorFilter();
// Invalidate the view to force a redraw in the new tint
61
Learn Android in the University
v.invalidate();
return true;
case DragEvent.ACTION_DROP:
// Gets the item containing the dragged data
ClipData.Item item = event.getClipData().getItemAt(0);
// Gets the text data from the item.
String dragData = item.getText().toString();
// Displays a message containing the dragged data.
Toast.makeText(this, "Dragged data is " + dragData, Toast.LENGTH_SHORT).show();
// Turns off any color tints
v.getBackground().clearColorFilter();
// Invalidates the view to force a redraw
v.invalidate();
// Returns true. DragEvent.getResult() will return true.
return true;
case DragEvent.ACTION_DRAG_ENDED:
// Turns off any color tinting
v.getBackground().clearColorFilter();
// Invalidates the view to force a redraw
v.invalidate();
// Does a getResult(), and displays what happened.
if (event.getResult())
Toast.makeText(this, "The drop was handled.", Toast.LENGTH_SHORT).show();
else
Toast.makeText(this, "The drop didn't work.", Toast.LENGTH_SHORT).show();
// returns true; the value is ignored.
return true;
This is how we can implement the drag and drop operation in our applications
based on our requirements.
Now we will see how to drag and drop View objects such as button, imageview or
textview, etc. in android applications with example.
62
Learn Android in the University
4.7. Android Drag and Drop Example
Following is the example of defining a UI controls such as button, imageview and textview in LinearLayout to implement a
drag and drop functionality in android application.
Create a new android application using android studio and give names as DragDropExample. In case if you are not aware
of creating an app in android studio check this article Android Hello World App.
Now open an activity_main.xml file from \res\layout path and write the code like as shown below
File: activity_main.xml
<LinearLayout android:id="@+id/layout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#EE501B"
android:gravity="center"
android:orientation="vertical">
<TextView android:id="@+id/lbl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Draggable Text"
android:textSize="20sp" />
<ImageView android:id="@+id/ingvw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/drag2" />
<Button android:id="@+id/btnDrag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Draggable Button" />
</LinearLayout>
<LinearLayout android:id="@+id/layout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#00ADEF"
android:gravity="center"
android:orientation="vertical" />
<LinearLayout android:id="@+id/layout3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#80CC28"
android:gravity="center"
63
Learn Android in the University
android:orientation="vertical" />
</LinearLayout>
If you observe above code we created a multiple linear layouts with required UI controls to perform drag and drop
execution.
Once we are done with creation of layouts with required controls, we need to load the XML layout resource from our
activity onCreate() callback method, for that open main activity file MainActivity.java from
\java\com.tutlane.dragdropexample path and write the code like as shown below.
File: MainActivity.java
package com.ah.dragdropexample;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.ClipData;
import android.content.ClipDescription;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.util.Log;
import android.view.DragEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
// This is the method that the system calls when it dispatches a drag event to the listener.
@Override
public boolean onDrag(View v, DragEvent event) {
// Defines a variable to store the action type for the incoming event
int action = event.getAction();
// Handles each of the expected events
switch (action) {
case DragEvent.ACTION_DRAG_STARTED:
// Determines if this View can accept the dragged data
if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
// if you want to apply color when drag started to your view you can uncomment
below lines
// to give any color tint to the View to indicate that it can accept data.
// v.getBackground().setColorFilter(Color.BLUE, PorterDuff.Mode.SRC_IN);
// Invalidate the view to force a redraw in the new tint
// v.invalidate();
// returns true to indicate that the View can accept the dragged data.
return true;
}
// Returns false. During the current drag and drop operation, this View will
// not receive events again until ACTION_DRAG_ENDED is sent.
return false;
case DragEvent.ACTION_DRAG_ENTERED:
// Applies a GRAY or any color tint to the View. Return true; the return value is
ignored.
v.getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.SRC_IN);
// Invalidate the view to force a redraw in the new tint
v.invalidate();
return true;
case DragEvent.ACTION_DRAG_LOCATION:
// Ignore the event
return true;
case DragEvent.ACTION_DRAG_EXITED:
// Re-sets the color tint to blue. Returns true; the return value is ignored.
// view.getBackground().setColorFilter(Color.BLUE, PorterDuff.Mode.SRC_IN);
//It will clear a color filter .
v.getBackground().clearColorFilter();
// Invalidate the view to force a redraw in the new tint
v.invalidate();
return true;
case DragEvent.ACTION_DROP:
65
Learn Android in the University
// Gets the item containing the dragged data
ClipData.Item item = event.getClipData().getItemAt(0);
// Gets the text data from the item.
String dragData = item.getText().toString();
// Displays a message containing the dragged data.
Toast.makeText(this, "Dragged data is " + dragData, Toast.LENGTH_SHORT).show();
// Turns off any color tints
v.getBackground().clearColorFilter();
// Invalidates the view to force a redraw
v.invalidate();
case DragEvent.ACTION_DRAG_ENDED:
// Turns off any color tinting
v.getBackground().clearColorFilter();
// Invalidates the view to force a redraw
v.invalidate();
// Does a getResult(), and displays what happened.
if (event.getResult())
Toast.makeText(this, "The drop was handled.", Toast.LENGTH_SHORT).show();
else
Toast.makeText(this, "The drop didn't work.", Toast.LENGTH_SHORT).show();
// returns true; the value is ignored.
return true;
// An unknown action type was received.
default:
Log.e("DragDrop Example", "Unknown action type received by OnDragListener.");
break;
}
return false;
}
}
If you observe above code, we registered our View objects and implemented a required Drag and Long press events to
implement drag and drop functionality.
Generally, during the launch of our activity, onCreate() callback method will be called by android framework to get the
required layout for an activity.
When we run above example using android virtual device (AVD) we will get a result like as shown below.
66
Learn Android in the University
If you observe above result, we are able to drag and drop View’s such as Button, Imageview and Textview to different
layouts in our application.
This is how we can implement drag and drop functionality in our application to move data from one view to another based
on our requirements.
67
Learn Android in the University
68
Learn Android in the University
69
Learn Android in the University
5.3. Gradle configuration
Be sure that gradle are configured as followings:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
allprojects {
repositories {
mavenLocal()
google()
jcenter()
}
}
android {
compileSdkVersion 27
buildToolsVersion '28.0.2'
defaultConfig {
applicationId "com.example.mapdemo"
minSdkVersion 15
targetSdkVersion 27
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
implementation 'com.android.support:appcompat-v7:27.0.2'
implementation 'com.google.android.gms:play-services-maps:12.0.1'
implementation 'com.android.support:support-v4:27.0.2'
}
70
Learn Android in the University
5.4. Define a specific place on the map and add a marker
We can obtain the location of a place with this website: https://www.gps-coordinates.net/
- Latitude: 21.412276
- Longitude: 39.864044
package com.ah.mapapplication;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
@Override
public void onMapReady(GoogleMap googleMap) {
71
Learn Android in the University
mMap = googleMap;
OnMapReadyCallback
public interface OnMapReadyCallback
Once an instance of this interface is set on a MapFragment or MapView object, the onMapReady(GoogleMap) method is
triggered when the map is ready to be used and provides a non-null instance of GoogleMap.
If Google Play services is not installed on the device, the user will be prompted to install it, and the
onMapReady(GoogleMap) method will only be triggered when the user has installed it and returned to the app.
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
72
Learn Android in the University
1: World
5: Landmass/continent
10: City
15: Streets
20: Buildings
More details:
https://developers.google.com/maps/documentation/android-sdk/intro
Zoom 5: Landmass/continent
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
74
Learn Android in the University
75
Learn Android in the University
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
76
Learn Android in the University
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(Makka, 5f));
}
@Override
public void onMapReady(GoogleMap googleMap) {
77
Learn Android in the University
mMap = googleMap;
lines.add( Madina );
lines.add( Jeddah );
lines.add( Makka );
lines.add( Riyadh );
mMap.addPolyline( lines );
78
Learn Android in the University
5.7. Exercise
Make the following image using Google Map
5.8. dfgfdg
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
81
Learn Android in the University
6.2. Permission
Dfgdfg
82
Learn Android in the University
Manifest.xml
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!--
The API key for Google Maps-based APIs is defined as a string resource.
83
Learn Android in the University
(See the file "res/values/google_maps_api.xml").
Note that the API key is linked to the encryption key used to sign the APK.
You need a different API key for each encryption key, including the release key that
is used to
sign the APK for publishing.
You can define the keys for the debug and release targets in src/debug/ and
src/release/.
-->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
<activity
android:name=".MapsActivity"
android:label="@string/title_activity_maps">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</manifest>
MapsActivity.java
package com.ksa.ah.getlocation;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import android.os.Bundle;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
LocationManager locationManager;
LocationListener locationListener;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull
84
Learn Android in the University
int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
locationListener);
}
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
@Override
public void onProviderEnabled(String s) {
@Override
public void onProviderDisabled(String s) {
}
};
85
Learn Android in the University
mMap.clear();
LatLng userLocation = new LatLng(lastKnownLocation.getLatitude(),
lastKnownLocation.getLongitude());
mMap.addMarker(new MarkerOptions().position(userLocation).title("Your Location"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(userLocation));
}
}
}
}
86
Learn Android in the University
package com.example.zappycode.mapandlocationdemo;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.widget.ListView;
import android.widget.Toast;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
LocationManager locationManager;
LocationListener locationListener;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull
int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
locationListener);
}
}
}
}
87
Learn Android in the University
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
try {
List<Address> listAddresses =
geocoder.getFromLocation(location.getLatitude(),location.getLongitude(),1);
if (listAddresses.get(0).getThoroughfare() != null) {
address += listAddresses.get(0).getThoroughfare() + " ";
}
if (listAddresses.get(0).getLocality() != null) {
address += listAddresses.get(0).getLocality() + " ";
}
if (listAddresses.get(0).getPostalCode() != null) {
address += listAddresses.get(0).getPostalCode() + " ";
}
if (listAddresses.get(0).getAdminArea() != null) {
address += listAddresses.get(0).getAdminArea();
}
88
Learn Android in the University
} catch (Exception e) {
e.printStackTrace();
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
@Override
public void onProviderEnabled(String s) {
@Override
public void onProviderDisabled(String s) {
}
};
mMap.clear();
LatLng userLocation = new LatLng(lastKnownLocation.getLatitude(),
lastKnownLocation.getLongitude());
mMap.addMarker(new MarkerOptions().position(userLocation).title("Your Location"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(userLocation));
}
}
}
}
89
Learn Android in the University
7.3. Exercice
The purpose of this exercice is to display information details about the current location:
- Latitude
- Longitude
- Altitude
- Accuracy
- Address.
90
Learn Android in the University
The Layout file contains 5 TextViews:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/background"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:id="@+id/imageView"
android:scaleType="fitXY" />
<TextView
android:text="Hiker's Watch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="21dp"
android:id="@+id/textView"
android:textSize="24sp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:textColor="@android:color/background_dark" />
<TextView
android:text="Latitude:"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:layout_alignParentStart="true"
android:layout_marginStart="24dp"
android:layout_marginTop="72dp"
android:id="@+id/latTextView"
android:textColor="@android:color/background_light"
android:textSize="@dimen/activity_horizontal_margin" />
<TextView
android:text="Longitude:"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/latTextView"
android:layout_alignParentStart="true"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:id="@+id/lonTextView"
android:textColor="@android:color/background_light"
android:textSize="@dimen/activity_horizontal_margin" />
<TextView
android:text="Accuracy:"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/lonTextView"
91
Learn Android in the University
android:layout_alignParentStart="true"
android:layout_marginStart="24dp"
android:layout_marginTop="12dp"
android:id="@+id/accTextView"
android:textColor="@android:color/background_light"
android:textSize="@dimen/activity_horizontal_margin" />
<TextView
android:text="Altitude:"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/accTextView"
android:layout_alignParentStart="true"
android:layout_marginStart="24dp"
android:layout_marginTop="12dp"
android:id="@+id/altTextView"
android:textColor="@android:color/background_light"
android:textSize="@dimen/activity_horizontal_margin" />
<TextView
android:text="Address:"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/altTextView"
android:layout_alignParentStart="true"
android:layout_marginStart="24dp"
android:layout_marginTop="12dp"
android:id="@+id/addressTextView"
android:textColor="@android:color/background_light"
android:textSize="@dimen/activity_horizontal_margin" />
</RelativeLayout>
AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.NoActionBar" >
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</manifest>
MainActivity.xml
92
Learn Android in the University
package com.robpercival.hikerswatch;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import org.w3c.dom.Text;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
LocationManager locationManager;
LocationListener locationListener;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull
int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
startListening();
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED) {
Log.i("LocationInfo", location.toString());
93
Learn Android in the University
TextView accTextView = (TextView) findViewById(R.id.accTextView);
try {
Log.i("PlaceInfo", listAddresses.get(0).toString());
if (listAddresses.get(0).getSubThoroughfare() != null) {
if (listAddresses.get(0).getThoroughfare() != null) {
if (listAddresses.get(0).getLocality() != null) {
if (listAddresses.get(0).getPostalCode() != null) {
if (listAddresses.get(0).getCountryName() != null) {
addressTextView.setText(address);
} catch (IOException e) {
e.printStackTrace();
94
Learn Android in the University
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
updateLocationInfo(location);
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
@Override
public void onProviderEnabled(String s) {
@Override
public void onProviderDisabled(String s) {
}
};
startListening();
} else {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED) {
} else {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
locationListener);
Location location =
locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
updateLocationInfo(location);
95
Learn Android in the University
}
}
96
Learn Android in the University
8.2. MainActivity
activity_main.xml
<ListView
android:id="@+id/listView"
android:layout_width="368dp"
android:layout_height="495dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
MainActivity.java
package com.example.zappycode.memorableplaces;
import android.content.Intent;
import android.location.Location;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import com.google.android.gms.maps.model.LatLng;
import java.util.ArrayList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView.setAdapter(arrayAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(getApplicationContext(), MapsActivity.class);
intent.putExtra("placeNumber",i);
startActivity(intent);
}
98
Learn Android in the University
});
}
}
8.3. MapsActivity
package com.example.zappycode.memorableplaces;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
99
Learn Android in the University
import android.location.LocationListener;
import android.location.LocationManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.widget.Toast;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
LocationManager locationManager;
LocationListener locationListener;
private GoogleMap mMap;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull
int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
Location lastKnownLocation =
locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
centerMapOnLocation(lastKnownLocation, "Your Location");
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
100
Learn Android in the University
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setOnMapLongClickListener(this);
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
@Override
public void onProviderEnabled(String s) {
@Override
public void onProviderDisabled(String s) {
}
};
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
Location lastKnownLocation =
locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
centerMapOnLocation(lastKnownLocation, "Your Location");
} else {
ActivityCompat.requestPermissions(this,new String[]
{Manifest.permission.ACCESS_FINE_LOCATION},1);
}
} else {
Location placeLocation = new Location(LocationManager.GPS_PROVIDER);
placeLocation.setLatitude(MainActivity.locations.get(intent.getIntExtra("placeNumber",0)).latitude);
placeLocation.setLongitude(MainActivity.locations.get(intent.getIntExtra("placeNumber",0)).longitude
);
centerMapOnLocation(placeLocation,
MainActivity.places.get(intent.getIntExtra("placeNumber",0)));
}
}
@Override
public void onMapLongClick(LatLng latLng) {
try {
List<Address> listAdddresses =
101
Learn Android in the University
geocoder.getFromLocation(latLng.latitude,latLng.longitude,1);
} catch (Exception e) {
e.printStackTrace();
}
if (address.equals("")) {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm yyyy-MM-dd");
address += sdf.format(new Date());
}
mMap.addMarker(new MarkerOptions().position(latLng).title(address));
MainActivity.places.add(address);
MainActivity.locations.add(latLng);
MainActivity.arrayAdapter.notifyDataSetChanged();
Toast.makeText(this,"Location Saved!",Toast.LENGTH_SHORT).show();
}
}
102
Learn Android in the University
8.4. AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.zappycode.memorableplaces">
<!--
The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
Google Maps Android API v2, but you must specify either coarse or fine
location permissions for the 'MyLocation' functionality.
-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<activity
android:name=".MapsActivity"
android:label="@string/title_activity_maps"></activity>
</application>
</manifest>
104
Learn Android in the University
package com.example.zappycode.sharedprefrences;
import android.content.Context;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.io.IOException;
import java.util.ArrayList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences sharedPreferences =
this.getSharedPreferences("com.example.zappycode.sharedprefrences", Context.MODE_PRIVATE);
sharedPreferences.edit().putString("username","nick").apply();
}
}
ObjectSerializer.java
package com.example.zappycode.sharedprefrences;
import android.util.Log;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
105
Learn Android in the University
public static String serialize(Serializable obj) throws IOException {
if (obj == null) return "";
try {
ByteArrayOutputStream serialObj = new ByteArrayOutputStream();
ObjectOutputStream objStream = new ObjectOutputStream(serialObj);
objStream.writeObject(obj);
objStream.close();
return encodeBytes(serialObj.toByteArray());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return strBuf.toString();
}
package com.example.zappycode.sharedprefrences;
import android.content.Context;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.io.IOException;
import java.util.ArrayList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
106
Learn Android in the University
setContentView(R.layout.activity_main);
SharedPreferences sharedPreferences =
this.getSharedPreferences("com.example.zappycode.sharedprefrences", Context.MODE_PRIVATE);
friends.add("Saleh");
friends.add("Ali");
friends.add("Sami");
try {
sharedPreferences.edit().putString("friends",ObjectSerializer.serialize(friends)).apply();
Log.i("friends",ObjectSerializer.serialize(friends));
} catch (Exception e) {
e.printStackTrace();
}
try {
newFriends = (ArrayList<String>)
ObjectSerializer.deserialize(sharedPreferences.getString("friends", ObjectSerializer.serialize(new
ArrayList<String>())));
} catch (Exception e) {
e.printStackTrace();
}
Log.i("new Friends",newFriends.toString());
}
}
107
Learn Android in the University
- Creating Database,
- Creating Tables,
- Creating Records,
- Reading Records,
- Updating Records and,
- Deleting Records in Android SQLite Database.
After going through these lessons you will be having a complete idea about using SQLite database for your Android
Application
Now we have only a single table, but in real-world scenarios, you will have multiple tables with some complex
relationships. Also, remember one thing whenever you create a table create a column named id with int as PRIMARY KEY
SQL Queries
Now let’s see how we can create the above table in our SQLite database.
and AUTOINCREMENT. (If you are confused don’t worry we will see now how do we create tables in database using SQL).
Note: * means selecting all the columns, if you want a specific column or multiple columns but not all you can write names
of the columns like SELECT name, department.
Updating a Record
UPDATE employees
SET
name = 'Belal Haque',
department = 'Research and Development',
salary = '100000'
WHERE id = 1;
Deleting a Record
These are just some simple basics operations, but we can perform many tasks in our database. For this, you need to learn
SQL in detail.
109
Learn Android in the University
Creating Record
As you can see we have EditText, Button, Spinner and some TextViews. To create the above interface, you can use the
following XML code. You need to paste the following code inside activity_main.xml which is generated by default in any
project because this will be the first screen for our application.
File: activity_main.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:text="Add a new Employee"
android:textAlignment="center"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Large" />
110
Learn Android in the University
<EditText
android:id="@+id/editTextName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter Employee Name" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:paddingLeft="6dp"
android:text="Select Department" />
<Spinner
android:id="@+id/spinnerDepartment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/departments" />
<EditText
android:id="@+id/editTextSalary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:digits="0123456789"
android:hint="Enter Employee Salary"
android:inputType="number" />
<Button
android:id="@+id/buttonAddEmployee"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add Employee" />
<TextView
android:id="@+id/textViewViewEmployees"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="View Employees"
android:textAlignment="center"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
android:textStyle="bold" />
</LinearLayout>
</RelativeLayout>
For the spinner that we used in the above screen, we need to define an Array as the entries for the spinner. So go inside
values->strings.xml and modify it as below.
File: strings.xml
<resources>
<string name="app_name">SQLiteCRUDExample</string>
<array name="departments">
<item>Technical</item>
<item>Support</item>
<item>Research and Development</item>
<item>Marketing</item>
<item>Human Resource</item>
</array>
</resources>
111
Learn Android in the University
Adding an Employee
We will perform this operation inside MainActivity.java so inside this file write the following code.
package net.ah.sqlitecrudexample;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import java.text.SimpleDateFormat;
import java.util.Calendar;
TextView textViewViewEmployees;
EditText editTextName, editTextSalary;
Spinner spinnerDepartment;
SQLiteDatabase mDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.buttonAddEmployee).setOnClickListener(this);
textViewViewEmployees.setOnClickListener(this);
/*
Button btn = (Button) findViewById(R.id.buttonAddEmployee);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addEmployee();
}
});
textViewViewEmployees.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(MainActivity.this, EmployeeActivity.class));
}
});
*/
//creating a database
mDatabase = openOrCreateDatabase(DATABASE_NAME, MODE_PRIVATE, null);
}
112
Learn Android in the University
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.buttonAddEmployee:
addEmployee();
break;
case R.id.textViewViewEmployees:
break;
}
}
}
- First parameter is the database name as String, that we need to open. Lets assume we passed some name “xyz” as
the first parameter then if there exist a database named “xyz” it will open it, if no database found with the
specified name it will create a new database named “xyz” and will open it.
- Second Parameter is the open mode as int. We have some predefined values for it, right now we are using
MODE_PRIVATE and it simply means that only this application can access this database.
Now we will create a method to create the Employee table. So create a method named createEmployeeTable().
Now just call this method just after calling the openOrCreateDatabase() method.
//creating a database
mDatabase = openOrCreateDatabase(DATABASE_NAME, MODE_PRIVATE, null);
createEmployeeTable();
}
In the above method we are just calling the method execSQL() to create our database table. The execSQL() method takes
String as a parameter and the String is actually the SQL query that we need to execute.
Remember we use execSQL() method only for creating table, inserting or updating records. We cannot use it to retrieve
values.
Till now we have the database, the table now we need to insert the employee in the table and we need to do this inside
addEmployee() method.
Now you can test your application for the Create Operation.
114
Learn Android in the University
Now lets move towards fetching the stored employees which we call the Read Operation.
So, to create a new EmptyActivity in your project named EmployeeActivity. It will create a java file named
EmployeeActivity.java and a layout file called activity_employee.xml
115
Learn Android in the University
This screen contains a only a ListView. The xml for the above screen is below.
<ListView
android:id="@+id/listViewEmployees"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
But here we will not use a simple ListView as we need to display multiple items in the List we will be using a Custom
ListView. And for the ListView item we need one more layout as well, so create one more layout file named
list_layout_employee.xml and write the following xml code
116
Learn Android in the University
Employee Model
Create a simple java class named Employee.java and write the following code.
package net.ah.sqlitecrudexample;
public Employee(int id, String name, String dept, String joiningDate, double salary) {
this.id = id;
this.name = name;
this.dept = dept;
this.joiningDate = joiningDate;
this.salary = salary;
}
117
Learn Android in the University
Create a java class named EmployeeAdapter and write the following code.
package net.ah.sqlitecrudexample;
import android.content.Context;
import android.content.DialogInterface;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
Context mCtx;
int listLayoutRes;
List<Employee> employeeList;
SQLiteDatabase mDatabase;
this.mCtx = mCtx;
this.listLayoutRes = listLayoutRes;
this.employeeList = employeeList;
this.mDatabase = mDatabase;
}
118
Learn Android in the University
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(mCtx);
View view = inflater.inflate(listLayoutRes, null);
textViewName.setText(employee.getName());
textViewDept.setText(employee.getDept());
textViewSalary.setText(String.valueOf(employee.getSalary()));
textViewJoiningDate.setText(employee.getJoiningDate());
return view;
}
}
package net.ah.sqlitecrudexample;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;
List<Employee> employeeList;
SQLiteDatabase mDatabase;
ListView listViewEmployees;
EmployeeAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_employee);
120
Learn Android in the University
We modify the listview by adding two buttons in list_layout_employee.xml: update and delete.
<LinearLayout
android:layout_width="230dp"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
121
Learn Android in the University
android:id="@+id/textViewName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="10dp"
android:text="Saleh Mahmoud"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Large" />
<TextView
android:id="@+id/textViewDepartment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Technical"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" />
<TextView
android:id="@+id/textViewSalary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="25000"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" />
<TextView
android:id="@+id/textViewJoiningDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="2019-09-30 10:00:00" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/buttonEditEmployee"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="@color/colorPrimary"
android:text="Edit" />
<Button
android:id="@+id/buttonDeleteEmployee"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="@color/colorAccent"
android:text="Delete" />
</LinearLayout>
</LinearLayout>
122
Learn Android in the University
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:text="Edit Employee"
android:textAlignment="center"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Large" />
<EditText
android:id="@+id/editTextName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter Employee Name" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:paddingLeft="6dp"
android:text="Select Department" />
123
Learn Android in the University
<Spinner
android:id="@+id/spinnerDepartment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/departments" />
<EditText
android:id="@+id/editTextSalary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:digits="0123456789"
android:hint="Enter Employee Salary"
android:inputType="number" />
<Button
android:id="@+id/buttonUpdateEmployee"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Update" />
</LinearLayout>
For the Update operation we need two new methods inside the EmployeeAdapter.java. One is to update the employee and
the second one is to reload the employee from database to show updated information.
124
Learn Android in the University
So inside the class you need to make below given two methods named updateEmployee() and
reloadEmployeesFromDatabase() method.
editTextName.setText(employee.getName());
editTextSalary.setText(String.valueOf(employee.getSalary()));
view.findViewById(R.id.buttonUpdateEmployee).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String name = editTextName.getText().toString().trim();
String salary = editTextSalary.getText().toString().trim();
String dept = spinnerDepartment.getSelectedItem().toString();
if (name.isEmpty()) {
editTextName.setError("Name can't be blank");
editTextName.requestFocus();
return;
}
if (salary.isEmpty()) {
editTextSalary.setError("Salary can't be blank");
editTextSalary.requestFocus();
return;
}
dialog.dismiss();
}
});
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(mCtx);
View view = inflater.inflate(listLayoutRes, null);
textViewName.setText(employee.getName());
textViewDept.setText(employee.getDept());
textViewSalary.setText(String.valueOf(employee.getSalary()));
textViewJoiningDate.setText(employee.getJoiningDate());
return view;
}
126
Learn Android in the University
127
Learn Android in the University
We will do the deletion also in the EmployeeAdapter class. The operation is same we just need to change the SQL String to
perform delete operation the rest part is exactly the same.
So to make the delete operation again modify the getView() of EmployeeAdapter as below.
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(mCtx);
View view = inflater.inflate(listLayoutRes, null);
128
Learn Android in the University
textViewName.setText(employee.getName());
textViewDept.setText(employee.getDept());
textViewSalary.setText(String.valueOf(employee.getSalary()));
textViewJoiningDate.setText(employee.getJoiningDate());
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
});
return view;
}
So the operation is complete and now you can test all the operation in your application and you should see something like
this.
129
Learn Android in the University
130
Learn Android in the University
- What is Firebase?
- F
131
Learn Android in the University
- Now wait for your project, once it is fully loaded we can start working.
- But before we need a app in Firebase Console as well. So switch to your browser from Android Studio.
132
Learn Android in the University
133
Learn Android in the University
Now you will see the Firebase Panel. You need to click on Android Icon here.
134
Learn Android in the University
Now you will see a panel here you need to put the package name of your project. You can get the package name from
AndroidManifest.xml file. Copy the package name and paste it here and then click on Add App.
135
Learn Android in the University
When you click Add App, a file named google-services.json will be downloaded. You need to paste this file inside app
directory of your project. See the below image for explanation.
136
Learn Android in the University
Now come inside your project level build.gradle file and modify it as follows.
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.0'
classpath 'com.google.gms:google-services:4.0.1'
allprojects {
repositories {
google()
137
Learn Android in the University
jcenter()
}
}
android {
compileSdkVersion 28
defaultConfig {
applicationId "ah.net.firebaseapp"
minSdkVersion 24
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.google.firebase:firebase-core:16.0.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
apply plugin: 'com.google.gms.google-services'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.google.firebase:firebase-core:16.0.1'
//add this line
implementation 'com.google.firebase:firebase-auth:16.0.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
138
Learn Android in the University
https://firebase.google.com/support/release-notes/android
On the left side menu you will see Authentication, click on it.
139
Learn Android in the University
140
Learn Android in the University
Creating User Signup Form
Now we will need to create a form in our activity from where user can Sign Up to our app.
Come inside your Android Studio Project, and in activity_main.xml write the following code.
<LinearLayout
android:layout_centerVertical="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:id="@+id/editTextEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:hint="Enter email"
android:inputType="textEmailAddress" />
<EditText
android:id="@+id/editTextPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:hint="Enter password"
android:inputType="textPassword" />
<Button
android:id="@+id/buttonSignup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:text="Signup" />
</LinearLayout>
</RelativeLayout>
141
Learn Android in the University
Step #1
First we will define a FirebaseAuth object. Then inside method onCreate() we will initialize this object. See the following
code snippet.
package ah.net.firebaseapp;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.google.firebase.auth.FirebaseAuth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
142
Learn Android in the University
Step #2
Now we will call the method createUserWithEmailAndPassword() from the FirebaseAuth object. This method take two
String parameters for email and password. And we attach a OnCompleteListener on it to check the task is completed or
not.
//checking if success
if(task.isSuccessful()){
//display some message here
}else{
//display some message here
}
}
});
package ah.net.firebaseapp;
import android.app.ProgressDialog;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
@Override
protected void onCreate(Bundle savedInstanceState) {
143
Learn Android in the University
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initializing views
editTextEmail = (EditText) findViewById(R.id.editTextEmail);
editTextPassword = (EditText) findViewById(R.id.editTextPassword);
if(TextUtils.isEmpty(password)){
Toast.makeText(this,"Please enter password",Toast.LENGTH_LONG).show();
return;
}
}
@Override
public void onClick(View view) {
//calling register method on click
registerUser();
144
Learn Android in the University
}
}
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</manifest>
145
Learn Android in the University
Click on Signup and if you got the success message. Check your firebase console.
146
Learn Android in the University
In the next lessons we will see about user login and other options like Password Reset, Email Change, Delete Account etc.
https://www.simplifiedcoding.net/android-firebase-tutorial-1/
147
Learn Android in the University
Lesson 12. Firebase- User Authentication: Login using Email and
Password
https://www.simplifiedcoding.net/firebase-user-authentication-tutorial/
12.1. Content
In this lesson we will learn about Firebase User Authentication or Signin. In the last lesson we covered the User
Registration part using Firebase. In this Firebase User Authentication lesson we will create a login option in our app using
Email and Password.
Go inside activity_main.xml and change the layout as follows. We are adding a TextView where user can click to go to the
login activity directly.
<LinearLayout
android:layout_centerVertical="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="User Registration"
android:id="@+id/textView"
android:layout_gravity="center_horizontal" />
<EditText
android:id="@+id/editTextEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:hint="Enter email"
android:inputType="textEmailAddress" />
<EditText
android:id="@+id/editTextPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:hint="Enter password"
android:inputType="textPassword" />
<Button
android:id="@+id/buttonSignup"
android:layout_width="match_parent"
148
Learn Android in the University
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:text="Signup" />
<TextView
android:text="Already Registered? Signin Here"
android:id="@+id/textViewSignin"
android:textAlignment="center"
android:layout_margin="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</RelativeLayout>
package ah.net.firebaseapp;
import android.app.ProgressDialog;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
149
Learn Android in the University
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initializing views
editTextEmail = (EditText) findViewById(R.id.editTextEmail);
editTextPassword = (EditText) findViewById(R.id.editTextPassword);
textViewSignin = (TextView) findViewById(R.id.textViewSignin);
if(TextUtils.isEmpty(password)){
150
Learn Android in the University
Toast.makeText(this,"Please enter password",Toast.LENGTH_LONG).show();
return;
}
@Override
public void onClick(View view) {
if(view == buttonSignup){
registerUser();
}
if(view == textViewSignin){
//open login activity when user taps on the already registered textview
startActivity(new Intent(this, LoginActivity.class));
}
}
}
151
Learn Android in the University
Inside the layout file of this activity write the following xml code. (In my case it is activity_profile.xml)
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
152
Learn Android in the University
android:text="Large Text"
android:id="@+id/textViewUserEmail"
android:layout_gravity="center_horizontal" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Logout"
android:id="@+id/buttonLogout"
android:layout_gravity="center_horizontal" />
</LinearLayout>
</RelativeLayout>
We haven’t done much on this activity as it contains a TextView and a Button only. In TextView we will show the logged in
user email and the button will be used for logout.
The above XML code will show you the following layout.
153
Learn Android in the University
Again right click on package and new -> activity -> empty activity, and create a new Activity. Name it LoginActivity.
Inside the layout file of this activity activity_login.xml write the following xml code.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
154
Learn Android in the University
android:text="User Login"
android:id="@+id/textView"
android:layout_gravity="center_horizontal" />
<EditText
android:id="@+id/editTextEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:hint="Enter email"
android:inputType="textEmailAddress" />
<EditText
android:id="@+id/editTextPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:hint="Enter password"
android:inputType="textPassword" />
<Button
android:id="@+id/buttonSignin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:text="Signin" />
<TextView
android:text="Not have an account? Signup Here"
android:id="@+id/textViewSignUp"
android:textAlignment="center"
android:layout_margin="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</RelativeLayout>
155
Learn Android in the University
Now lets code this activity, so come inside LoginActivity.java and write the following code.
package ah.net.firebaseapp;
import android.app.ProgressDialog;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
156
Learn Android in the University
//progress dialog
private ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
//initializing views
editTextEmail = (EditText) findViewById(R.id.editTextEmail);
editTextPassword = (EditText) findViewById(R.id.editTextPassword);
buttonSignIn = (Button) findViewById(R.id.buttonSignin);
textViewSignup = (TextView) findViewById(R.id.textViewSignUp);
if(TextUtils.isEmpty(password)){
Toast.makeText(this,"Please enter password",Toast.LENGTH_LONG).show();
return;
}
157
Learn Android in the University
//start the profile activity
finish();
startActivity(new Intent(getApplicationContext(),
ProfileActivity.class));
}
}
});
@Override
public void onClick(View view) {
if(view == buttonSignIn){
userLogin();
}
if(view == textViewSignup){
finish();
startActivity(new Intent(this, MainActivity.class));
}
}
}
Thats it now just run your app go to login and try logging in.
158
Learn Android in the University
13.1. Content
In this lesson we will learn about Firebase Phone Authentication. Firebase is usefull, and it provides almost the features
that you need for the backend of your application. So in this lesson, we will learn about Firebase Phone Authentication,
and I am pretty sure that you have already seen this thing in many apps. You enter your phone number, receives an OTP,
and then you use that OTP to authenticate.
Preventing Fake Users: When you use phone authentication, the user can’t be able to register for multiple
accounts, as for each account a unique phone number is needed.
Increase User Value: When you have all the users verified by a phone number the value of your user base
increases.
Increased Security and User Experience:Nowadays more people using apps and remembering passwords are a
headache for many users, so they end up using weak passwords. Using phone authentication increases security
and user experience, as the user does not need to create and remember passwords, they will enter their number
and then they can receive a temporary authentication code by SMS.
Once the project is completely loaded, we will add firebase authentication into it.
159
Learn Android in the University
Before moving into designing I would like to tell you that, for Sign In we will have two activities, in the first activity the
user will enter his phone number and in the next we will verify the code sent by SMS.
160
Learn Android in the University
For designing the above screen come inside activity_main.xml and write the following xml code
<RelativeLayout
android:id="@+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@color/colorPrimary">
<ImageView
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="@drawable/ic_logo" />
</RelativeLayout>
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="120dp"
161
Learn Android in the University
android:layout_below="@id/relativeLayout"
android:layout_marginTop="-50dp"
android:background="@drawable/waves" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/imageView"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:text="May I ask you phone number?"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Large"
android:textColor="@color/colorPrimary" />
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/textView"
android:orientation="horizontal"
android:padding="15dp">
<ImageView
android:id="@+id/imageView2"
android:layout_width="50dp"
android:layout_height="50dp"
app:srcCompat="@drawable/ic_phone" />
<Spinner
android:id="@+id/spinnerCountries"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1" />
<EditText
android:id="@+id/editTextPhone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:digits="0123456789"
android:hint="enter your number"
android:layout_gravity="center"
android:maxLength="10"
/>
</LinearLayout>
<Button
android:id="@+id/buttonContinue"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_below="@id/linearLayout"
android:layout_centerHorizontal="true"
android:background="@color/colorPrimary"
android:text="Continue"
android:textAllCaps="false"
android:textColor="#ffffff" />
</RelativeLayout>
First create a new Activity in the project, and I have created an activity named VerifyPhoneActivity.
For the above design for your VerifyPhoneActivity, open the activity_verify_phone.xml and write the following xml
code.
<RelativeLayout
android:id="@+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@color/colorPrimary">
<ImageView
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="@drawable/ic_logo" />
</RelativeLayout>
163
Learn Android in the University
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_below="@id/relativeLayout"
android:layout_marginTop="-50dp"
android:background="@drawable/waves" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/imageView"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:text="Wait for the code I sent you..."
android:textAppearance="@style/Base.TextAppearance.AppCompat.Large"
android:textColor="@color/colorPrimaryDark" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/textView"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="5dp"
android:text="I sent you a code, it will be detected automatically but if it is not detected
you can put it below manually as well"
android:textAlignment="center"
android:textColor="@color/colorPrimary" />
<EditText
android:id="@+id/editTextCode"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_below="@id/textView1"
android:layout_centerHorizontal="true"
android:digits="0123456789"
android:hint="enter code"
android:maxLength="6" />
<Button
android:id="@+id/buttonSignIn"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_below="@id/editTextCode"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:background="@color/colorPrimary"
android:text="Sign In"
android:textAllCaps="false"
android:textColor="#ffffff" />
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/buttonSignIn"
android:layout_centerHorizontal="true"
android:visibility="gone" />
</RelativeLayout>
164
Learn Android in the University
Now we will create one more activity named ProfileActivity.
Creating ProfileActivity
Create a new EmptyActivity named ProfileActivity and this activity will open after the successful login.
In this screen we have nothing but only a TextView with a welcome message, as you can see below.
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Welcome to Your Profile"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Large"
android:textColor="@color/colorPrimary" />
<Button
android:id="@+id/buttonLogout"
165
Learn Android in the University
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_below="@id/textView"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:background="@color/colorPrimary"
android:text="Logout"
android:textAllCaps="false"
android:textColor="#ffffff" />
</RelativeLayout>
package net.simplifiedcoding.firebasephoneauth;
package ah.net.firebaseapp;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import com.google.firebase.auth.FirebaseAuth;
public class MainPhoneActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
spinner = findViewById(R.id.spinnerCountries);
spinner.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_dropdown_item, CountryData.countryNames));
editText = findViewById(R.id.editTextPhone);
findViewById(R.id.buttonContinue).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String code = CountryData.countryAreaCodes[spinner.getSelectedItemPosition()];
166
Learn Android in the University
}
});
}
@Override
protected void onStart() {
super.onStart();
if (FirebaseAuth.getInstance().getCurrentUser() != null) {
Intent intent = new Intent(this, ProfileActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
}
}
The above code is very straightforward. We are just taking the mobile number from EditText and sending it to
VerifyPhoneActivity.class with intent.
private PhoneAuthProvider.OnVerificationStateChangedCallbacks
mCallBack = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
@Override
public void onCodeSent(String s, PhoneAuthProvider.ForceResendingToken forceResendingToken) {
super.onCodeSent(s, forceResendingToken);
verificationId = s;
}
167
Learn Android in the University
@Override
public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {
String code = phoneAuthCredential.getSmsCode();
if (code != null) {
editText.setText(code);
verifyCode(code);
}
}
@Override
public void onVerificationFailed(FirebaseException e) {
Toast.makeText(VerifyPhoneActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
};
sendVerificationCode(): This method will send the verification code. You can also see that I am concatenating +91
with the mobile number which is the country code for India. But in real scenario you might have users from different
countries. So if that is the case, you need to let the user select their country as well so that you know the code, and you can
also tell the user to input the number with country code.
mCallbacks: This is our callback that will help us to know the code is sent or not. It has three methods.
onCodeSent(): This is called when the code is sent successfully. The first parameter here is our verification id
that is sent. So we are storing it in our mVerificationId object.
onVerificationFailed(): This method is called when the verification is failed for some reasons, so here we are
only displaying a simple toast.
onVerificationCompleted(): This method is called when the verification is completed. Here we have the
PhoneAuthCredential Object which will give us the code if it is automatically detected.
To verify verification code we will use this method. If the verification is successful we will let the user sign in into the
application.
startActivity(intent);
} else {
Toast.makeText(VerifyPhoneActivity.this, task.getException().getMessage(),
Toast.LENGTH_LONG).show();
}
}
});
}
168
Learn Android in the University
VerifyPhoneActivity Code
package ah.net.firebaseapp;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.TaskExecutors;
import com.google.firebase.FirebaseException;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthProvider;
import java.util.concurrent.TimeUnit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_verify_phone);
//initializing objects
mAuth = FirebaseAuth.getInstance();
progressBar = findViewById(R.id.progressbar);
editText = findViewById(R.id.editTextCode);
//if the automatic sms detection did not work, user can also enter the code manually
//so adding a click listener to the button
findViewById(R.id.buttonSignIn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
editText.setError("Enter code...");
editText.requestFocus();
return;
169
Learn Android in the University
}
//verifying the code entered manually
verifyCode(code);
}
});
startActivity(intent);
} else {
//verification unsuccessful.. display an error message
Toast.makeText(VerifyPhoneActivity.this,
task.getException().getMessage(), Toast.LENGTH_LONG).show();
}
}
});
}
@Override
public void onCodeSent(String s, PhoneAuthProvider.ForceResendingToken forceResendingToken)
{
super.onCodeSent(s, forceResendingToken);
//storing the verification id that is sent to the user
verificationId = s;
}
170
Learn Android in the University
@Override
public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {
//Getting the code sent by SMS
String code = phoneAuthCredential.getSmsCode();
//sometime the code is not detected automatically
//in this case the code will be null
//so user has to manually enter the code
if (code != null) {
editText.setText(code);
//verifying the code
verifyCode(code);
}
}
@Override
public void onVerificationFailed(FirebaseException e) {
Toast.makeText(VerifyPhoneActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
};
}
171
Learn Android in the University
172
Learn Android in the University
In this lesson we will learn modeling SQL tables to NoSQL Firebase Database. And then we will also learn the basic CRUD
operation on the database (Create, Read, Update and Delete).
But firebase is not an SQL database and it does not store data in tabular format. It uses JSON tree structure. So for
firebase realtime database the structure for above database will be.
173
Learn Android in the University
14.3. Firebase Realtime Database Basics
You have the database structure now you need to know the basic operations. So let's understand the steps of handling
firebase database.
FirebaseFirestore db = FirebaseFirestore.getInstance();
CollectionReference notesCollectionRef = db
.collection("notes");
The data is stored in the JSON Tree form so you need to get the reference of a specified path. Like in the above database
we can get all the Notes by passing “notes”. If you want to access everything don’t pass anything and it will create a
reference of the root of the tree.
Write Operation
Suppose we have to store a Note to our reference then we will create a model class as below.
package ah.net.firebaseapp.database.models;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.firebase.firestore.IgnoreExtraProperties;
import com.google.firebase.firestore.ServerTimestamp;
import java.util.Date;
@IgnoreExtraProperties
public class Note implements Parcelable{
public Note(String title, String content, Date timestamp, String note_id, String user_id) {
this.title = title;
this.content = content;
this.timestamp = timestamp;
this.note_id = note_id;
this.user_id = user_id;
}
public Note() {
@Override
public Note[] newArray(int size) {
return new Note[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(title);
parcel.writeString(content);
parcel.writeString(note_id);
parcel.writeString(user_id);
}
}
175
Learn Android in the University
Write Operation
set() – This method will take a model java class object that will hold all the variables to be stored in the reference. The
same method will be used to update the values at it overwrites the data of the specified reference.
@Override
public void createNewNote(String title, String content) {
FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference newNoteRef = db
.collection("notes")
.document();
newNoteRef.set(note).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if(task.isSuccessful()){
makeSnackBarMessage("Created new note");
getNotes();
}
else{
makeSnackBarMessage("Failed. Check log.");
}
}
});
}
Read Operation
We will attache a ValueEventListener to the reference to read the data.
FirebaseFirestore db = FirebaseFirestore.getInstance();
CollectionReference notesCollectionRef = db
.collection("notes");
176
Learn Android in the University
.orderBy("timestamp", Query.Direction.ASCENDING);
}
notesQuery.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if(task.isSuccessful()){
if(task.getResult().size() != 0){
mLastQueriedDocument = task.getResult().getDocuments()
.get(task.getResult().size() -1);
}
mNoteRecyclerViewAdapter.notifyDataSetChanged();
}
else{
makeSnackBarMessage("Query Failed. Check Logs.");
}
}
});
}
Whenever you will change something in the Database the method onDataChange() will be executed. It contains all the
data inside the specified path in the reference. We can use the DataSnapshot object to read all the data inside the
reference. If some error occurres onCancelled() method will be called.
onDataChange() method will also called once after the app launch and hence you can read the data at starting as well.
Delete Operation
removeValue() can be used to delete the data.
177
Learn Android in the University
178
Learn Android in the University
Open Android Studio and create a new project. In my case I have created FirebaseDatabaseExample.
Now once your project is loaded completely, add Firebase Database in it.
179
Learn Android in the University
Library
Now add your app level build.gradle file as follows.
//Firebase database
implementation 'com.google.firebase:firebase-database:16.0.1'
180
Learn Android in the University
In this android login and registration lesson we will create a very simple application that will contain 3 screens. The User
Registration Screen, User Login Screen and the User Profile Screen.
For the server side part we will be using PHP and MySQL with Laragon (you can use wamp or lamp as well) server.
Our application cannot access our server directly. We need some medium between server and the application so that our
application can access the database residing in our web server. For this we use Web Services often called APIs, ore more
specifically a RESTful API. We will use the basic php only.
Creating Database
We need to following database table.
181
Learn Android in the University
https://www.simplifiedcoding.net/firebase-realtime-database-crud/
https://www.simplifiedcoding.net/firebase-storage-tutorial-android/
https://www.simplifiedcoding.net/firebase-storage-uploading-pdf/
182
Learn Android in the University
Sdfg
References
Books
- Android 5 Programming by Example – Kyle Mew – 2015 Packt Publishing
Websites
- Official Android Website: https://developers.google.com/training/android/
- https://codingwithmitch.com
- https://www.simplifiedcoding.net
- https://www.tutorialspoint.com/android/
- https://www.tutlane.com/tutorial/android
183