Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 184

Dr.

Amir Hammami

Learn Android in the University

Learn Android in the University


Shaqra University
1440-1439
Learn Android in the University

Learn Android in the University

Computer Science Department


Faculty of Business and Administration
Shaqra University
Afif Branch
Kingdom of Saudi Arabia

1
‫‪Learn Android in the University‬‬

‫بسم هللا الرحمن الرحيم‬


‫في إطار التدريس بقسم علوم الحاسب وبالتحديد في مقرر مواضيع مختارة في علوم الحاسب (‪ )I‬و (‪ )II‬الذي يعتني‬
‫بتعليم الطالب برمجة تطبيقات الجوال‪ ،‬تم تأليف هذا الكتاب بعنوان‪" :‬تعليم األندرويد في الجامعة"‪.‬‬
‫يحتوي الكتاب على تفاصيل املحاضرات التي تم تدريسها خالل الفصلين األول والثاني طبقا للخطة الدراسية مع بعض‬
‫التعديالت واإلضافات التي تهدف إلى االرتقاء بمستوى طالب الحاسب اآللي في اململكة العربية السعودية‪.‬‬
‫يمتاز الكتاب بسهولة العبارة وذلك لتيسير دراسته من قبل طالب اململكة وخاصة طالب جامعة شقراء ويمتاز كذلك‬
‫َََ ّ ّ‬
‫للتعلم‬ ‫بالتدرج في التعلم أي االنتقال من السهل اليسير إلى األكثر تعقيد حتى يتدرج الطالب وتصبح لديه ملكة‬
‫والبرمجة‪.‬‬
‫من مميزات الكتاب أيضا تفصيل املحاضرات والشروحات باالعتماد على الرسوم واألكواد الجاهزة التي تم برمجتها‬
‫ّ‬
‫خالل حصص العملي‪ .‬فما على الطالب إال التشمير عن ساعد الجد للتعلم والبرمجة واالستفادة من محتوى الكتاب‪.‬‬
‫الدكاترة واألساتذة املهتمين بهذا املقرر يجدون هنا مرجعا هاما ومادة دسمة لكتابة محاضراتهم بحيث يختزل لهم‬
‫الوقت والبحث‪.‬‬
‫إعتمدت على بعض املواقع والكتب املذكورة في آخر الكتاب‪.‬‬
‫وأخيرا نرحب بكل مالحظة ونقد بناء لتحسين هذا املنتوج العلمي والعمل الجامعي‪.‬‬
‫كما أني أتوجه بالشكر إلى معالي‹ مدير جامعة شقراء الدكتور عوض األسمري وإلى عميد كلية إدارة األعمال الدكتور‬
‫مطلق الروقي الذي إستقبلني في كليته ويسر لي العمل بفضل هللا في قسم علوم الحاسب اآللي وكذلك كامل أعضاء هيئة‬
‫التدريس‪.‬‬
‫د‪ .‬أمير محمد املنصف الحمامي‬

‫‪2‬‬
Learn Android in the University

About the Author


Dr. Amir Hammami received his Engineer degree (Computer Science) from INSAT,Tunisia in 2003, Majester diploma
from Paul Sabatier University Toulouse France in 2004 and Ph.D (Computer Science) from Paul Sabatier University
Toulouse France in 2007. He has more than 10 years of experience in teaching undergraduate as well as postgraduate
students of Computer Science, Information Technology and Computer Applications on ENIG Gabes University Tunisia.
He has authored more than 10 research papers on software engineering in leading international journals and conferences.
His current research interests are Internet of Things, Software Engineering (SE) such as Mobile Development, Database
and Web programming.

Email: amir.hammami@su.edu.sa

Mobile: 00966590320806 (WhatsApp)

3
Learn Android in the University

4
Learn Android in the University

Lesson 1. Android Layouts


1.1. Content
In this lesson we will discover Android Layouts.

- What is Layout?
- Android Layout Types
- LinearLayout
- RelativeLayout
- TableLayout
- GridLayout
- FrameLayout

1.2. What is Layout?


A layout defines the structure for a user interface in your application, such as in an activity.

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.

Figure 4-1. Illustration of a view hierarchy, which defines a UI layout

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

RelativeLayout is a view group that displays child views in relative positions.

TableLayout

TableLayout is a view that groups views into rows and columns.

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.

Sub-view in LinearLayout has an important attributes: android: layout_weight.

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

Distinguishing gravity and layout_gravity:


android:layout_gravity sets the gravity of the View or Layout in its parent.

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

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


<LinearLayout 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="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.

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


<LinearLayout 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="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

<?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=".RelativeActivity">

<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

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


<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".LinearLayoutActivity">
22 
Learn Android in the University

<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.

Sizes, Margins and Alignment/Gravity

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

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


<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".LinearLayoutActivity"
30 
Learn Android in the University
>

<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

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


<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"

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:

Design following interface with FrameLayout:

Prepare an image file:

bg.jpg

Copy and paste to drawable folder.

34 
Learn Android in the University

Drag and drop ImageView into the screen at left + top area.

Similarly drag and drop two TextView objects to screen:


35 
Learn Android in the University

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


<FrameLayout 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"
>

<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

Lesson 2. Event Handler


2.1. Content
This lesson explains event handling in Android with the help of example.

2.2. Event Handling


Event is an action. It occurs when a user interact with mobile application. Events in Android are in many different forms
like keystrokes, touch inputs and many others. Touch screen interaction falls in the category of touch events. Android
framework maintains all events in a queue which is First In First Out (FIFO). Event handler as the name suggests handles
events in Android. Event handler and event listener are related concepts.

2.3. Event Listener


It is an interface which contains a call back method. When user will trigger the view elements it will call these methods.
Here are few important call back methods:

 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.

2.4. Case 1: onClick() in Layout XML file


MainActivity.java

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;

public class MainActivity extends AppCompatActivity {


TextView welcome;
TextView java;
Button button;
int i=0;

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);

public void changeColor(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++;

}
}

activity_main.xml

<?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=".MainActivity">

<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;

public class InLineActivity extends AppCompatActivity {


TextView welcome;
TextView java;
Button button;
int i=0;

@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++;
}
});

}
}

<?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=".InLineActivity">

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;

public class ImplementActivity extends AppCompatActivity implements View.OnClickListener {


TextView welcome;
TextView java;
Button button;
int i=0;

@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++;
}
}
}

<?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=".ImplementActivity">

<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;

public class ClassActivity extends AppCompatActivity {


TextView welcome;
TextView java;
Button button;
int i=0;

@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));
}

public void changeColor() {


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) {
45 
Learn Android in the University
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++;
}
}

class ListenerImplement implements OnClickListener {

private ClassActivity calledActivity;

public ListenerImplement(ClassActivity previousActivity) {


this.calledActivity = previousActivity;
}
@Override
public void onClick(View arg0) {
this.calledActivity.changeColor();
}

<?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=".ClassActivity">

<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>

Lesson 3. Drag and Drop


3.1. Using drag and drop in Android
As of Android 4.0 drag and drop of view onto other views or view groups is supported.

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

3.2. Defining drop target


The views which can be drop targets get an instance of OnDragListener assigned. In this drop listener you receive call
backs in case of predefined drag and drop related events. * DragEvent.ACTION_DRAG_STARTED *
DragEvent.ACTION_DRAG_ENTERED * DragEvent.ACTION_DRAG_EXITED * DragEvent.ACTION_DROP *
DragEvent.ACTION_DRAG_ENDED

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

3.3. Exercise: Drag and drop


In this exercise you create several view groups which allow to drag views between them.

Create project
Create a new Android project called com.vogella.android.draganddrop with an activity called DragActivity.

Create XML Drawables


In this exercise you are using XML drawables.

In this part you create several XML drawables in the res/drawable folder.

Create the following shape.xml file in this folder.

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


<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >

<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.

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


<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >

<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>

Activity and layout


Change the layout of your activity to the following code.

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


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".SimpleActivity">

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>

Change your activity class to the following code.

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;

public class SimpleActivity extends AppCompatActivity implements OnDragListener {


private Drawable enterShape;
private Drawable normalShape;

OnTouchListener dragListener = new OnTouchListener() {


@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
// start move on a touch event
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
ClipData data = ClipData.newPlainText("", "");
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag(data, shadowBuilder, view, 0);
view.setVisibility(View.INVISIBLE);
return true;
}
return false;

}
};

@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

Lesson 4. Android Drag and Drop


4.1. Content
In this lesson we will dosciver the Drag and Drop framework. This feature allow users to move a data from one view to
another using graphical drag and drop gesture.

- Drag and Drop Process


- Drag Event Listener and Call-back Method
- Android Drag Events
- Android Drag Shadow

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.

- Drag Event Class


- Drag Listeners
- Helper Methods and Classes

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.

4.3. Drag Event Listener and Call-back Method


In android, the View object receives a drag events either from a drag event listener that implements View.OnDragListener
or with its onDragEvent(DragEvent) call-back method. When the system calls a method or listener, it passes to a
DragEvent object.

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.

The combination of onDragEvent(DragEvent) method and View.OnDragListener is analogous to the combination of


onTouchEvent() and View.OnTouchListener used with touch events.

The official Android website details this Drag Event Listener


(https://developer.android.com/reference/android/view/View.OnDragListener)

We have to perform import library:

import android.view.View.OnDragListener;

Defined as:

public static interface View.OnDragListener

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.

It contains only one abstract method:

public abstract boolean onDrag (View v, DragEvent event)

Called when a drag event is dispatched to a view. This allows listeners to get a chance to override base View behavior.

Parameters

v View: The View that received the drag event.

event DragEvent: The DragEvent object for the drag event.

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.

4.4. Android Drag Events


57 
Learn Android in the University
Generally, the system sends a drag event object (DragEvent) to perform drag / drop process and the DragEvent object
contains an action type that tells the listener what is happening in the drag / drop process.

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.

4.5. Android Drag Shadow


In android, while performing a drag and drop operation, the system will display an image that the user drags and we can
call it as a drag shadow. During the data movement, images are used to represent that the data being dragged.

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.

Starting a Drag Event


In android, we can start a drag event by using a drag gesture, usually a long press on View object. In response, we need to
do the following things.

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.Item from the View object's tag


    ClipData.Item item = new ClipData.Item((CharSequence) v.getTag());

    // 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);

    // Instantiates the drag shadow builder.


59 
Learn Android in the University
    View.DragShadowBuilder dragshadow = new View.DragShadowBuilder(v);

    // Starts the drag


    v.startDrag(data       // data to be dragged
            , dragshadow  // drag shadow
            , v            // local data about the drag and drop operation
            , 0          // flags set to 0 because not using currently
    );
    return true;
}

This is how we can respond for a long press on View object by creating a ClipData object in android applications.

Responding to a Drag Start Event


During the drag operation, the system dispatches drag events to the drag event listeners of View objects in the current
layout. The listeners should react by calling getAction() to get the action type. At the start of a drag, this methods returns
ACTION_DRAG_STARTED.

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.

Handling an Events during the Drag


During the drag, listeners primarily use drag events such as ACTION_DRAG_ENTERED, ACTION_DRAG_LOCATION,
ACTION_DRAG_EXITED, etc. to decide whether to change the appearance of the View to indicate that it is about to
receive a drop.

Responding to a Drop Event


Whenever we release a drag shadow on the View that accept a content being dragged, the system dispatches a drag event
to that View with action type ACTION_DROP and the listener will do the following things.

- 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.

Responding to a Drag End


Whenever we release the drag shadow, the system will send a drag event to all the drag event listeners in our application,
with an action type of ACTION_DRAG_ENDED to indicate that the drag operation is over and the listener will do the
following things.

- 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:

            // Determines if this View can accept the dragged data


            if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
                // applies a blue color tint to the View to indicate that it can accept the 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 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;

        // An unknown action type was received.


        default:
            Log.e("DragDrop Example", "Unknown action type received by
OnDragListener.");
            break;
    }
    return false;
}

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

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


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">

<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;

public class MainActivity extends AppCompatActivity implements View.OnDragListener,


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

//Find all views and set Tag to all draggable views


TextView txtVw = (TextView) findViewById(R.id.lbl);
txtVw.setTag("DRAGGABLE TEXTVIEW");
txtVw.setOnLongClickListener(this);

ImageView imgVw = (ImageView) findViewById(R.id.ingvw);


imgVw.setTag("ANDROID ICON");
imgVw.setOnLongClickListener(this);

Button btn = (Button) findViewById(R.id.btnDrag);


btn.setTag("DRAGGABLE BUTTON");
btn.setOnLongClickListener(this);

//Set Drag Event Listeners for defined layouts


findViewById(R.id.layout1).setOnDragListener(this);
findViewById(R.id.layout2).setOnDragListener(this);
findViewById(R.id.layout3).setOnDragListener(this);
}
@Override
64 
Learn Android in the University
public boolean onLongClick(View v) {
// Create a new ClipData.Item from the ImageView object's tag
ClipData.Item item = new ClipData.Item((CharSequence) v.getTag());
// 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);
// Instantiates the drag shadow builder.
View.DragShadowBuilder dragshadow = new View.DragShadowBuilder(v);
// Starts the drag
v.startDrag(data // data to be dragged
, dragshadow // drag shadow builder
, v // local data about the drag and drop operation
, 0 // flags (not currently used, set to 0)
);
return true;
}

// 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();

View vw = (View) event.getLocalState();


ViewGroup owner = (ViewGroup) vw.getParent();
owner.removeView(vw); //remove the dragged view
//caste the view into LinearLayout as our drag acceptable layout is LinearLayout
LinearLayout container = (LinearLayout) v;
container.addView(vw);//Add the dragged view
vw.setVisibility(View.VISIBLE);//finally set Visibility to VISIBLE
// 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;
// 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

Lesson 5. Google Map and Geolocation


5.1. Content

5.2. Java Code


Create new project

And choose Google Maps Activity

68 
Learn Android in the University

Keep the project information

In order to use Google Map, we should obtain a KEY from:

69 
Learn Android in the University
5.3. Gradle configuration
Be sure that gradle are configured as followings:

File build.gradle (Project: MapApplication)

// 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'

// NOTE: Do not place your application dependencies here; they belong


// in the individual module build.gradle files
}
}

allprojects {
repositories {
mavenLocal()
google()
jcenter()
}
}

task clean(type: Delete) {


delete rootProject.buildDir
}
File build.gradle (Module: app)

apply plugin: 'com.android.application'


apply plugin: 'project-report'

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/

For example Makka coordinates are:

- Latitude: 21.412276
- Longitude: 39.864044

The layout activity_maps.xml contains:

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


<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MapsActivity" />

The Java class for the activity contains:

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;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

private GoogleMap mMap;

@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;

// Add a marker in Sydney and move the camera


LatLng Makka = new LatLng(21.412276, 39.864044);
mMap.addMarker(new MarkerOptions().position(Makka).title("Marker in Makka"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(Makka));
}
}

OnMapReadyCallback
public interface OnMapReadyCallback

Callback interface for when the map is ready to be used.

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.

Public Method Summary

abstract void onMapReady(GoogleMap googleMap)


Called when the map is ready to be used.

Called when the map is ready to be used.

In our case we display a marker on Makka city.

@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;

// Add a marker in Sydney and move the camera


LatLng Makka = new LatLng(21.412276, 39.864044);
mMap.addMarker(new MarkerOptions().position(Makka).title("Marker in Makka"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(Makka));
}

We run the application on the Emulator:

72 
Learn Android in the University

Here are the approximate zoom levels and what they do :

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;

// Add a marker in Sydney and move the camera


LatLng Makka = new LatLng(21.412276, 39.864044);
mMap.addMarker(new MarkerOptions().position(Makka).title("Marker in Makka"));
73 
Learn Android in the University
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(Makka, 10f));
}

Zoom 10: City


@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;

// Add a marker in Sydney and move the camera


LatLng Makka = new LatLng(21.412276, 39.864044);
mMap.addMarker(new MarkerOptions().position(Makka).title("Marker in Makka"));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(Makka, 10f));
}

74 
Learn Android in the University

Zoom 15: Streets


@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;

// Add a marker in Sydney and move the camera


LatLng Makka = new LatLng(21.412276, 39.864044);
mMap.addMarker(new MarkerOptions().position(Makka).title("Marker in Makka"));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(Makka, 15f));
}

75 
Learn Android in the University

5.5. Define many places with markers

Place Latitude Longitude


Makka 21.412275 39.88054
Madina 24.527245 39.583909
Jeddah 21.47833 39.161379
Riyadh 24.671686 46.665041

@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;

// Add a marker in Sydney and move the camera


LatLng Makka = new LatLng(21.412276, 39.864044);
mMap.addMarker(new MarkerOptions().position(Makka).title("Marker in Makka"));

LatLng Madina = new LatLng(24.527245, 39.583909);


mMap.addMarker(new MarkerOptions().position(Madina).title("Marker in Madina"));

LatLng Jeddah = new LatLng(21.47833, 39.161379);


mMap.addMarker(new MarkerOptions().position(Jeddah).title("Marker in Jeddah"));

76 
Learn Android in the University

LatLng Riyadh = new LatLng(24.671686, 46.665041);


mMap.addMarker(new MarkerOptions().position(Riyadh).title("Marker in Riyadh"));

mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(Makka, 5f));
}

5.6. Draw a line between many points


In order to draw lines in Maps V2, we would add a Polyline to our GoogleMap.

Notice: GeoPoint is only used for Maps V1.

@Override
public void onMapReady(GoogleMap googleMap) {

77 
Learn Android in the University
mMap = googleMap;

// Add a marker in Sydney and move the camera


LatLng Makka = new LatLng(21.412276, 39.864044);
mMap.addMarker(new MarkerOptions().position(Makka).title("Marker in Makka"));

LatLng Madina = new LatLng(24.527245, 39.583909);


mMap.addMarker(new MarkerOptions().position(Madina).title("Marker in Madina"));

LatLng Jeddah = new LatLng(21.47833, 39.161379);


mMap.addMarker(new MarkerOptions().position(Jeddah).title("Marker in Jeddah"));

LatLng Riyadh = new LatLng(24.671686, 46.665041);


mMap.addMarker(new MarkerOptions().position(Riyadh).title("Marker in Riyadh"));

PolylineOptions lines = new PolylineOptions();

lines.color( Color.parseColor( "#CC0000FF" ) );


lines.width( 5 );
lines.visible( true );

lines.add( Madina );
lines.add( Jeddah );
lines.add( Makka );
lines.add( Riyadh );

mMap.addPolyline( lines );

LatLng Afif = new LatLng(23.93074, 42.940675);


mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(Afif, 5.5f));
}

78 
Learn Android in the University

5.7. Exercise
Make the following image using Google Map

Place Latitude Longitude


‫مكة‬ 21.422703 39.827025
79 
Learn Android in the University
)‫ذو الحذيفة (آبار علي‬ 24.413742 39.542992
‫ميقات الجحفة‬ 22.704939 39.14669
)‫ذات عرق (الخريبات‬ 21.929909 40.425482
)‫قرن المنازل (السيل الكبير‬ 21.633176 40.427456
)‫يلمم (السعدية‬ 20.707047 39.910412

5.8. dfgfdg
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;

mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);

// Add a marker in Sydney and move the camera


80 
Learn Android in the University
LatLng everest = new LatLng(28.0249447, 86.8869557);
mMap.addMarker(new MarkerOptions().position(everest).title("Biggest in the
World!").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_YELLOW)));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(everest,10));
}

5.9. GPS Track: Get current real-time location

81 
Learn Android in the University

Lesson 6. Get User Location


6.1. Content
Smartphones have GPS ship that can tell exactly where you are in the world.

6.2. Permission

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

6.3. Showing User Location on a Map

Dfgdfg

82 
Learn Android in the University

Manifest.xml

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


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.zappycode.mapandlocationdemo">
<!--
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">
<!--
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" />

<category android:name="android.intent.category.LAUNCHER" />


</intent-filter>
</activity>
</application>

</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;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

private GoogleMap mMap;

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;

locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);


locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
mMap.clear();
LatLng userLocation = new LatLng(location.getLatitude(), location.getLongitude());
mMap.addMarker(new MarkerOptions().position(userLocation).title("Your Location"));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 15f));
}

@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

if (Build.VERSION.SDK_INT < 23) {


if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// Activity#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for Activity#requestPermissions for more details.
return;
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
locationListener);
} else {
if (ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.ACCESS_FINE_LOCATION},1);
} else {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
locationListener);
Location lastKnownLocation =
locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

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

Lesson 7. Get Information about Location


7.1. Content

7.2. Obtain Address

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;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

private GoogleMap mMap;

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;

locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);


locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
mMap.clear();
LatLng userLocation = new LatLng(location.getLatitude(), location.getLongitude());
mMap.addMarker(new MarkerOptions().position(userLocation).title("Your Location"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(userLocation));

Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());

try {
List<Address> listAddresses =
geocoder.getFromLocation(location.getLatitude(),location.getLongitude(),1);

if (listAddresses != null && listAddresses.size() > 0) {


String address = "";

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();
}

Toast.makeText(MapsActivity.this, address, Toast.LENGTH_SHORT).show();


Log.i("Address", address);
}

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) {

}
};

if (Build.VERSION.SDK_INT < 23) {


locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
locationListener);
} else {
if (ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.ACCESS_FINE_LOCATION},1);
} else {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
locationListener);
Location lastKnownLocation =
locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

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:

<?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:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
tools:context="com.robpercival.hikerswatch.MainActivity">

<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

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


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.robpercival.hikerswatch" >

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<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" />

<category android:name="android.intent.category.LAUNCHER" />


</intent-filter>
</activity>
</application>

</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;

public class MainActivity extends AppCompatActivity {

LocationManager locationManager;

LocationListener locationListener;

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull
int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);

if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

startListening();

public void startListening() {

if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED) {

locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

public void updateLocationInfo(Location location) {

Log.i("LocationInfo", location.toString());

TextView latTextView = (TextView) findViewById(R.id.latTextView);

TextView lonTextView = (TextView) findViewById(R.id.lonTextView);

TextView altTextView = (TextView) findViewById(R.id.altTextView);

93 
Learn Android in the University
TextView accTextView = (TextView) findViewById(R.id.accTextView);

latTextView.setText("Latitude: " + location.getLatitude());

lonTextView.setText("Longitude: " + location.getLongitude());

altTextView.setText("Altitude: " + location.getAltitude());

accTextView.setText("Accuracy: " + location.getAccuracy());

Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());

try {

String address = "Could not find address";

List<Address> listAddresses = geocoder.getFromLocation(location.getLatitude(),


location.getLongitude(), 1);

if (listAddresses != null && listAddresses.size() > 0 ) {

Log.i("PlaceInfo", listAddresses.get(0).toString());

address = "Address: \n";

if (listAddresses.get(0).getSubThoroughfare() != null) {

address += listAddresses.get(0).getSubThoroughfare() + " ";

if (listAddresses.get(0).getThoroughfare() != null) {

address += listAddresses.get(0).getThoroughfare() + "\n";

if (listAddresses.get(0).getLocality() != null) {

address += listAddresses.get(0).getLocality() + "\n";

if (listAddresses.get(0).getPostalCode() != null) {

address += listAddresses.get(0).getPostalCode() + "\n";

if (listAddresses.get(0).getCountryName() != null) {

address += listAddresses.get(0).getCountryName() + "\n";

TextView addressTextView = (TextView) findViewById(R.id.addressTextView);

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);

locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

locationListener = new LocationListener() {


@Override
public void onLocationChanged(Location location) {

updateLocationInfo(location);

@Override
public void onStatusChanged(String s, int i, Bundle bundle) {

@Override
public void onProviderEnabled(String s) {

@Override
public void onProviderDisabled(String s) {

}
};

if (Build.VERSION.SDK_INT < 23) {

startListening();

} else {

if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED) {

ActivityCompat.requestPermissions(this, new String[]


{Manifest.permission.ACCESS_FINE_LOCATION}, 1);

} 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

Lesson 8. Memorable Places App


8.1. Content

8.2. MainActivity

activity_main.xml

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


<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
97 
Learn Android in the University
tools:context="com.example.zappycode.memorableplaces.MainActivity">

<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;

public class MainActivity extends AppCompatActivity {

static ArrayList<String> places = new ArrayList<String>();


static ArrayList<LatLng> locations = new ArrayList<LatLng>();
static ArrayAdapter arrayAdapter;

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

ListView listView = findViewById(R.id.listView);


places.add("Add a new place...");
locations.add(new LatLng(0,0));

arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, places);

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;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,


GoogleMap.OnMapLongClickListener {

LocationManager locationManager;
LocationListener locationListener;
private GoogleMap mMap;

public void centerMapOnLocation(Location location, String title) {


if (location != null) {
LatLng userLocation = new LatLng(location.getLatitude(), location.getLongitude());
mMap.clear();
mMap.addMarker(new MarkerOptions().position(userLocation).title(title));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 12));
}
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull
int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);

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);
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);

Intent intent = getIntent();


if (intent.getIntExtra("placeNumber",0) == 0) {
// Zoom in on user location
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
centerMapOnLocation(location, "Your Location");
}

@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) {

Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());

String address = "";

try {

List<Address> listAdddresses =
101 
Learn Android in the University
geocoder.getFromLocation(latLng.latitude,latLng.longitude,1);

if (listAdddresses != null && listAdddresses.size() > 0) {


if (listAdddresses.get(0).getThoroughfare() != null) {
if (listAdddresses.get(0).getSubThoroughfare() != null) {
address += listAdddresses.get(0).getSubThoroughfare() + " ";
}
address += listAdddresses.get(0).getThoroughfare();
}
}

} 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();
}
}

After a long click on a place

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" />

<category android:name="android.intent.category.LAUNCHER" />


</intent-filter>
</activity>
<!--
103 
Learn Android in the University
The API key for Google Maps-based APIs is defined as a string resource.
(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"></activity>
</application>

</manifest>

104 
Learn Android in the University

Lesson 9. Permanent Data Storage using SharedPreferences


9.1. Content

9.2. Store Text like username

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;

public class MainActivity extends AppCompatActivity {

@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();

String username = sharedPreferences.getString("username","");

Log.i("This is the username",username);

}
}

9.3. Store an Array

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;

public class ObjectSerializer {

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);
}
}

public static Object deserialize(String str) throws IOException {


if (str == null || str.length() == 0) return null;
try {
ByteArrayInputStream serialObj = new ByteArrayInputStream(decodeBytes(str));
ObjectInputStream objStream = new ObjectInputStream(serialObj);
return objStream.readObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public static String encodeBytes(byte[] bytes) {


StringBuffer strBuf = new StringBuffer();

for (int i = 0; i < bytes.length; i++) {


strBuf.append((char) (((bytes[i] >> 4) & 0xF) + ((int) 'a')));
strBuf.append((char) (((bytes[i]) & 0xF) + ((int) 'a')));
}

return strBuf.toString();
}

public static byte[] decodeBytes(String str) {


byte[] bytes = new byte[str.length() / 2];
for (int i = 0; i < str.length(); i+=2) {
char c = str.charAt(i);
bytes[i/2] = (byte) ((c - 'a') << 4);
c = str.charAt(i+1);
bytes[i/2] += (c - 'a');
}
return bytes;
}

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;

public class MainActivity extends AppCompatActivity {

@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);

ArrayList<String> friends = new ArrayList<>();

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();
}

ArrayList<String> newFriends = new ArrayList<>();

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

Lesson 10. Android SQLite Database


10.1. Content
You may already know that we have SQLite database in android that we can use as a local SQL Database for our android
application.

This Android SQLite Database series will cover:

- 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

10.2. The Database Structure


The first thing needed is the database structure. We create database structure according to the system. But here we are not
building an application, and it is only an example demonstrating the use of SQLite Database. So for this, I will use the
following table structure.

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).

Creating the Table

CREATE TABLE employees (


    id INTEGER NOT NULL CONSTRAINT employees_pk PRIMARY KEY AUTOINCREMENT,
    name varchar(200) NOT NULL,
    department varchar(200) NOT NULL,
108 
Learn Android in the University
    joiningdate datetime NOT NULL,
    salary double NOT NULL
);

Creating a new Record

INSERT INTO employees


(name, department, joiningdate, salary)
VALUES
('Belal Khan', 'Technical', '2017-09-30 10:00:00', '40000');

Reading All Existing Records

SELECT * FROM employees;

Reading Specific Record

SELECT * FROM employees WHERE id = 1;

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

DELETE FROM employees WHERE id = 1;

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.

Note: SQL Queries are not case sensitive.

10.3. Adding a new Employee


The first thing is adding a new record to our database, and for this, we can use the following screen.

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

<?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="net.simplifiedlearning.sqlitecrudexample.MainActivity">

<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;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

public static final String DATABASE_NAME = "myemployeedatabase";

TextView textViewViewEmployees;
EditText editTextName, editTextSalary;
Spinner spinnerDepartment;

SQLiteDatabase mDatabase;

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

textViewViewEmployees = (TextView) findViewById(R.id.textViewViewEmployees);


editTextName = (EditText) findViewById(R.id.editTextName);
editTextSalary = (EditText) findViewById(R.id.editTextSalary);
spinnerDepartment = (Spinner) findViewById(R.id.spinnerDepartment);

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

//this method will validate the name and salary


//dept does not need validation as it is a spinner and it cannot be empty
private boolean inputsAreCorrect(String name, String salary) {
if (name.isEmpty()) {
editTextName.setError("Please enter a name");
editTextName.requestFocus();
return false;
}

if (salary.isEmpty() || Integer.parseInt(salary) <= 0) {


editTextSalary.setError("Please enter salary");
editTextSalary.requestFocus();
return false;
}
return true;
}

//In this method we will do the create operation


private void addEmployee() { }

@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.buttonAddEmployee:

addEmployee();

break;
case R.id.textViewViewEmployees:

startActivity(new Intent(this, EmployeeActivity.class));

break;
}
}
}

In the above code you see we used a method openOrCreateDatabase().

This method takes 3 parameters.

- 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().

//this method will create the table


//as we are going to call this method everytime we will launch the application
//I have added IF NOT EXISTS to the SQL
//so it will only create the table when the table is not already created
private void createEmployeeTable() {
mDatabase.execSQL(
"CREATE TABLE IF NOT EXISTS employees (\n" +
" id INTEGER NOT NULL CONSTRAINT employees_pk PRIMARY KEY AUTOINCREMENT,\n" +
" name varchar(200) NOT NULL,\n" +
" department varchar(200) NOT NULL,\n" +
" joiningdate datetime NOT NULL,\n" +
113 
Learn Android in the University
" salary double NOT NULL\n" +
");"
);
}

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.

//In this method we will do the create operation


private void addEmployee() {

String name = editTextName.getText().toString().trim();


String salary = editTextSalary.getText().toString().trim();
String dept = spinnerDepartment.getSelectedItem().toString();

//getting the current time for joining date


Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss");
String joiningDate = sdf.format(cal.getTime());

//validating the inptus


if (inputsAreCorrect(name, salary)) {

String insertSQL = "INSERT INTO employees \n" +


"(name, department, joiningdate, salary)\n" +
"VALUES \n" +
"(?, ?, ?, ?);";

//using the same method execsql for inserting values


//this time it has two parameters
//first is the sql string and second is the parameters that is to be binded with the query
mDatabase.execSQL(insertSQL, new String[]{name, dept, joiningDate, salary});

Toast.makeText(this, "Employee Added Successfully", Toast.LENGTH_SHORT).show();


}
}

Now you can test your application for the Create Operation.

114 
Learn Android in the University

Android SQLite Database Example – Create Operation

Now lets move towards fetching the stored employees which we call the Read Operation.

10.4. Fetching All the Employees


Now after storing employee to the database, we also need to see all the stored employee from the database. For this, we
can use a ListView.

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.

<?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="net.simplifiedlearning.sqlitecrudexample.EmployeeActivity">

<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

Retrieving All Employees


We will do this operation inside EmployeeActivity.java. But before fetching the employees, we need two more java classes
to display employees in the list. The first class is a regular java class to store the employee as an object and a
CustomAdapter class for the ListView.

Employee Model

Create a simple java class named Employee.java and write the following code.

package net.ah.sqlitecrudexample;

public class Employee {


int id;
String name, dept, joiningDate;
double salary;

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;
}

public int getId() {


return id;
}

117 
Learn Android in the University

public String getName() {


return name;
}

public String getDept() {


return dept;
}

public String getJoiningDate() {


return joiningDate;
}

public double getSalary() {


return salary;
}
}

Now we will create a custom adapter class for our ListView.

Custom ListView Adapter

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;

public class EmployeeAdapter extends ArrayAdapter<Employee> {

Context mCtx;
int listLayoutRes;
List<Employee> employeeList;
SQLiteDatabase mDatabase;

public EmployeeAdapter(Context mCtx, int listLayoutRes, List<Employee> employeeList,


SQLiteDatabase mDatabase) {
super(mCtx, listLayoutRes, employeeList);

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);

final Employee employee = employeeList.get(position);

TextView textViewName = view.findViewById(R.id.textViewName);


TextView textViewDept = view.findViewById(R.id.textViewDepartment);
TextView textViewSalary = view.findViewById(R.id.textViewSalary);
TextView textViewJoiningDate = view.findViewById(R.id.textViewJoiningDate);

textViewName.setText(employee.getName());
textViewDept.setText(employee.getDept());
textViewSalary.setText(String.valueOf(employee.getSalary()));
textViewJoiningDate.setText(employee.getJoiningDate());

return view;
}
}

Now we can fetch the employees to display them in the ListView.

Retrieving and Displaying in ListView

Come inside EmployeeActivity.java and write the following code.

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;

public class EmployeeActivity extends AppCompatActivity {

List<Employee> employeeList;
SQLiteDatabase mDatabase;
ListView listViewEmployees;
EmployeeAdapter adapter;

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

listViewEmployees = (ListView) findViewById(R.id.listViewEmployees);


employeeList = new ArrayList<>();

//opening the database


mDatabase = openOrCreateDatabase(MainActivity.DATABASE_NAME, MODE_PRIVATE, null);

//this method will display the employees in the list


showEmployeesFromDatabase();
}
119 
Learn Android in the University

private void showEmployeesFromDatabase() {


//we used rawQuery(sql, selectionargs) for fetching all the employees
Cursor cursorEmployees = mDatabase.rawQuery("SELECT * FROM employees", null);

//if the cursor has some data


if (cursorEmployees.moveToFirst()) {
//looping through all the records
do {
//pushing each record in the employee list
employeeList.add(new Employee(
cursorEmployees.getInt(0),
cursorEmployees.getString(1),
cursorEmployees.getString(2),
cursorEmployees.getString(3),
cursorEmployees.getDouble(4)
));
} while (cursorEmployees.moveToNext());
}
//closing the cursor
cursorEmployees.close();

//creating the adapter object


adapter = new EmployeeAdapter(this, R.layout.list_layout_employee, employeeList, mDatabase);

//adding the adapter to listview


listViewEmployees.setAdapter(adapter);
}

Now try running the application to see the Read Operation.

120 
Learn Android in the University

Android SQLite Database Example – Read Operation

10.5. Updating an Employee


We have done with Create and Read, now lets do the Update Operation.

We modify the listview by adding two buttons in list_layout_employee.xml: update and delete.

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


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:padding="8dp">

<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>

The above xml code will generate the following layout.

122 
Learn Android in the University

We edit employee in a dialog: dialog_update_employee.xml

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


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">

<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>

We will perform the update inside the EmployeeAdapter class.

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.

private void updateEmployee(final Employee employee) {


final AlertDialog.Builder builder = new AlertDialog.Builder(mCtx);

LayoutInflater inflater = LayoutInflater.from(mCtx);


View view = inflater.inflate(R.layout.dialog_update_employee, null);
builder.setView(view);

final EditText editTextName = view.findViewById(R.id.editTextName);


final EditText editTextSalary = view.findViewById(R.id.editTextSalary);
final Spinner spinnerDepartment = view.findViewById(R.id.spinnerDepartment);

editTextName.setText(employee.getName());
editTextSalary.setText(String.valueOf(employee.getSalary()));

final AlertDialog dialog = builder.create();


dialog.show();

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;
}

String sql = "UPDATE employees \n" +


"SET name = ?, \n" +
"department = ?, \n" +
"salary = ? \n" +
"WHERE id = ?;\n";

mDatabase.execSQL(sql, new String[]{name, dept, salary,


String.valueOf(employee.getId())});
Toast.makeText(mCtx, "Employee Updated", Toast.LENGTH_SHORT).show();
reloadEmployeesFromDatabase();

dialog.dismiss();
}
});
}

private void reloadEmployeesFromDatabase() {


Cursor cursorEmployees = mDatabase.rawQuery("SELECT * FROM employees", null);
if (cursorEmployees.moveToFirst()) {
employeeList.clear();
do {
employeeList.add(new Employee(
cursorEmployees.getInt(0),
cursorEmployees.getString(1),
125 
Learn Android in the University
cursorEmployees.getString(2),
cursorEmployees.getString(3),
cursorEmployees.getDouble(4)
));
} while (cursorEmployees.moveToNext());
}
cursorEmployees.close();
notifyDataSetChanged();
}
The update operation is same as the insert operation, we changed the query only to update from insert. If you are having
any confusion understanding the codes please comment and I will help you.

Now we need to modify the getView() method 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);

final Employee employee = employeeList.get(position);

TextView textViewName = view.findViewById(R.id.textViewName);


TextView textViewDept = view.findViewById(R.id.textViewDepartment);
TextView textViewSalary = view.findViewById(R.id.textViewSalary);
TextView textViewJoiningDate = view.findViewById(R.id.textViewJoiningDate);

textViewName.setText(employee.getName());
textViewDept.setText(employee.getDept());
textViewSalary.setText(String.valueOf(employee.getSalary()));
textViewJoiningDate.setText(employee.getJoiningDate());

Button buttonDelete = view.findViewById(R.id.buttonDeleteEmployee);


Button buttonEdit = view.findViewById(R.id.buttonEditEmployee);

//adding a clicklistener to button


buttonEdit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
updateEmployee(employee);
}
});

return view;
}

Now you can test the Update Operation.

126 
Learn Android in the University

127 
Learn Android in the University

Android SQLite Database Example – Update Operation

10.6. Deleting an Employee


We have done with Create, Read and Update. Now the last operation is the Delete Operation. So lets do this to complete
the CRUD for this tutorial.

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);

final Employee employee = employeeList.get(position);

128 
Learn Android in the University

TextView textViewName = view.findViewById(R.id.textViewName);


TextView textViewDept = view.findViewById(R.id.textViewDepartment);
TextView textViewSalary = view.findViewById(R.id.textViewSalary);
TextView textViewJoiningDate = view.findViewById(R.id.textViewJoiningDate);

textViewName.setText(employee.getName());
textViewDept.setText(employee.getDept());
textViewSalary.setText(String.valueOf(employee.getSalary()));
textViewJoiningDate.setText(employee.getJoiningDate());

Button buttonDelete = view.findViewById(R.id.buttonDeleteEmployee);


Button buttonEdit = view.findViewById(R.id.buttonEditEmployee);

//adding a clicklistener to button


buttonEdit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
updateEmployee(employee);
}
});

//the delete operation


buttonDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(mCtx);
builder.setTitle("Are you sure?");
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String sql = "DELETE FROM employees WHERE id = ?";
mDatabase.execSQL(sql, new Integer[]{employee.getId()});
reloadEmployeesFromDatabase();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {

}
});
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

Android SQLite Database Example – Delete Operation

130 
Learn Android in the University

Lesson 11. Firebase - User Registration with Authentication


11.1. Content
We start a series of Firebase lessons. Here we will see how we can make User Registration in Android by using Firebase as
our App’s backend.

- What is Firebase?
- F

11.2. What is Firebase?


Firebase is a cloud service provider. It is now under google and this service can replace your whole server side part of your
application. In many applications we can use MySQL and PHP for our database. But if we will use Firebase we do not need
any server side code or configuration. We can directly use firebase. Firebase comes with a bundle of many features.

Creating Android Studio Project


We will start from creating a new project.

- Open Android Studio and Create a New Project. I created FirebaseAuthApplication

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.

Adding Firebase to our Project


Go to firebase.google.com.

Click on Get Started.

132 
Learn Android in the University

Now click on create a new project.

Give your app a name and click on create project.

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'

// NOTE: Do not place your application dependencies here; they belong


// in the individual module build.gradle files
}
}

allprojects {
repositories {
google()
137 
Learn Android in the University
jcenter()
}
}

task clean(type: Delete) {


delete rootProject.buildDir
}

Now modify your app level build.gradle file as follows.

apply plugin: 'com.android.application'

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'

Now sync your project with Gradle.

Adding Firebase Authentication


As in this Android Firebase Tutorial, we are building a user registration application, we need to use Firebase
Authentication. So we need to add Firebase Authentication to our project. For this go inside app level build.gradle file and
inside dependencies block add the following line.

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

Again sync your project.

The latest SDK versions are available in this website:

https://firebase.google.com/support/release-notes/android

Enabling Email/Password Authentication


Again go to your firebase panel.

On the left side menu you will see Authentication, click on it.

Now click on Set Up Sign In Method.

139 
Learn Android in the University

Now click on Email/Password, enable it and press save.

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.

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


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">

<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>

The above code will generate the following UI.

141 
Learn Android in the University

Understanding Firebase Signup


This is the main part of this Android Firebase Tutorial. First I will tell you about the methods. As we will be using Firebase
Authentication for the user Signup we need these steps to get it done.

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;

public class MainActivity extends AppCompatActivity {


//defining firebaseauth object
private FirebaseAuth firebaseAuth;

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

//initializing firebase auth object


firebaseAuth = FirebaseAuth.getInstance();
}
}

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.

private void registerUser(){

//creating a new user


firebaseAuth.createUserWithEmailAndPassword("user email here", "user password here")
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {

//checking if success
if(task.isSuccessful()){
//display some message here
}else{
//display some message here
}

}
});

Implementing Firebase Signup


We understood the code. Now lets implement it to make registration work in the activity. Write the following code in your
MainActivity.java

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;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {


//defining view objects
private EditText editTextEmail;
private EditText editTextPassword;
private Button buttonSignup;
private ProgressDialog progressDialog;

//defining firebaseauth object


private FirebaseAuth firebaseAuth;

@Override
protected void onCreate(Bundle savedInstanceState) {

143 
Learn Android in the University
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//initializing firebase auth object


firebaseAuth = FirebaseAuth.getInstance();

//initializing views
editTextEmail = (EditText) findViewById(R.id.editTextEmail);
editTextPassword = (EditText) findViewById(R.id.editTextPassword);

buttonSignup = (Button) findViewById(R.id.buttonSignup);

progressDialog = new ProgressDialog(this);

//attaching listener to button


buttonSignup.setOnClickListener(this);
}

private void registerUser(){


//getting email and password from edit texts
String email = editTextEmail.getText().toString().trim();
String password = editTextPassword.getText().toString().trim();

//checking if email and passwords are empty


if(TextUtils.isEmpty(email)){
Toast.makeText(this,"Please enter email",Toast.LENGTH_LONG).show();
return;
}

if(TextUtils.isEmpty(password)){
Toast.makeText(this,"Please enter password",Toast.LENGTH_LONG).show();
return;
}

//if the email and password are not empty


//displaying a progress dialog

progressDialog.setMessage("Registering Please Wait...");


progressDialog.show();

//creating a new user


firebaseAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
//checking if success
if(task.isSuccessful()){
//display some message here
Toast.makeText(MainActivity.this,"Successfully
registered",Toast.LENGTH_LONG).show();
}else{
//display some message here
Toast.makeText(MainActivity.this,"Registration
Error",Toast.LENGTH_LONG).show();
}
progressDialog.dismiss();
}
});

}
@Override
public void onClick(View view) {
//calling register method on click
registerUser();

144 
Learn Android in the University
}
}

Now lastly add internet permission to your AndroidManifest.xml file

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


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ah.net.firebaseapp">

<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" />

<category android:name="android.intent.category.LAUNCHER" />


</intent-filter>
</activity>
</application>

</manifest>

Now run your application.

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

The registration is working fine.

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.

12.2. Firebase User Authentication


Modifying the User Registration Screen
First open the last project we created.

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.

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


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">

<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>

Now your Activity will look as follow in the preview.

Now come inside MainActivity.java and modify your code as follows.

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;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {


//defining view objects
private EditText editTextEmail;
private EditText editTextPassword;
private Button buttonSignup;

private TextView textViewSignin;

private ProgressDialog progressDialog;

//defining firebaseauth object


private FirebaseAuth firebaseAuth;

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

//initializing firebase auth object


firebaseAuth = FirebaseAuth.getInstance();

//if getCurrentUser does not returns null


if(firebaseAuth.getCurrentUser() != null){
//that means user is already logged in
//so close this activity
finish();

//and open profile activity


startActivity(new Intent(getApplicationContext(), ProfileActivity.class));
}

//initializing views
editTextEmail = (EditText) findViewById(R.id.editTextEmail);
editTextPassword = (EditText) findViewById(R.id.editTextPassword);
textViewSignin = (TextView) findViewById(R.id.textViewSignin);

buttonSignup = (Button) findViewById(R.id.buttonSignup);

progressDialog = new ProgressDialog(this);

//attaching listener to button


buttonSignup.setOnClickListener(this);
textViewSignin.setOnClickListener(this);
}
private void registerUser(){

//getting email and password from edit texts


String email = editTextEmail.getText().toString().trim();
String password = editTextPassword.getText().toString().trim();

//checking if email and passwords are empty


if(TextUtils.isEmpty(email)){
Toast.makeText(this,"Please enter email",Toast.LENGTH_LONG).show();
return;
}

if(TextUtils.isEmpty(password)){

150 
Learn Android in the University
Toast.makeText(this,"Please enter password",Toast.LENGTH_LONG).show();
return;
}

//if the email and password are not empty


//displaying a progress dialog

progressDialog.setMessage("Registering Please Wait...");


progressDialog.show();

//creating a new user


firebaseAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
//checking if success
if(task.isSuccessful()){
finish();
startActivity(new Intent(getApplicationContext(),
ProfileActivity.class));
}else{
//display some message here
Toast.makeText(MainActivity.this,"Registration
Error",Toast.LENGTH_LONG).show();
}
progressDialog.dismiss();
}
});

@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));
}

}
}

Now we will create the Profile Activity.

Adding Profile Activity to Project


Right click on package and create new activity named ProfileActivity.

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)

<?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=".ProfileActivity">

<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.

Now come inside ProfileActivity.java and write the following code:

Now we will add Login Activity to our project.

Adding Login Activity to Project

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.

<?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=".LoginActivity">
<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"

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>

You will see the following layout in preview.

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;

public class LoginActivity extends AppCompatActivity implements View.OnClickListener {


//defining views
private Button buttonSignIn;
private EditText editTextEmail;
private EditText editTextPassword;
private TextView textViewSignup;

//firebase auth object


private FirebaseAuth 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);

//getting firebase auth object


firebaseAuth = FirebaseAuth.getInstance();

//if the objects getcurrentuser method is not null


//means user is already logged in
if(firebaseAuth.getCurrentUser() != null){
//close this activity
finish();
//opening profile activity
startActivity(new Intent(getApplicationContext(), ProfileActivity.class));
}

//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);

progressDialog = new ProgressDialog(this);

//attaching click listener


buttonSignIn.setOnClickListener(this);
textViewSignup.setOnClickListener(this);
}

//method for user login


private void userLogin(){
String email = editTextEmail.getText().toString().trim();
String password = editTextPassword.getText().toString().trim();

//checking if email and passwords are empty


if(TextUtils.isEmpty(email)){
Toast.makeText(this,"Please enter email",Toast.LENGTH_LONG).show();
return;
}

if(TextUtils.isEmpty(password)){
Toast.makeText(this,"Please enter password",Toast.LENGTH_LONG).show();
return;
}

//if the email and password are not empty


//displaying a progress dialog

progressDialog.setMessage("Signin Please Wait...");


progressDialog.show();

//logging in the user


firebaseAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
progressDialog.dismiss();
//if the task is successfull
if(task.isSuccessful()){

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

Lesson 13. Firebase Phone Authentication Android


https://www.simplifiedcoding.net/firebase-phone-authentication-android-tutorial/

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.

Benefits of using Phone Authentication


When you use phone number authentication, you have many benefits like

 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.

Why Firebase Phone Authentication?


For implementing phone authentication you need to pay for SMS service, but with firebase, you can do it for FREE.The
free plan of firebase has Ten Thousand Verification per month. If you exceed this limit, you need to pay.

13.2. Firebase Phone Authentication


Creating a new Android Studio Project
Again we will do it in a new project, so create a new Android Studio project. In my case I have created a project named
FirebasePhoneAuthentication.

Once the project is completely loaded, we will add firebase authentication into it.

Enable Firebase Phone Authentication


To do this go to Firebase Console and open the project that you are using.

Then go to Sign In Method and enable Phone Authentication.

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.

Enter Phone Number Screen


We have created this design for this Screen:

160 
Learn Android in the University

For designing the above screen come inside activity_main.xml and write the following xml code

<?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=".MainActivity">

<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>

Verify Phone Number Screen


162 
Learn Android in the University
Now we will create the next activity where we will very the phone number. In this screen as well we need an EditText
where user will input the code. But we will detect the SMS automatically so user do not need to enter manually.

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.

<?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=".VerifyPhoneActivity">

<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.

<?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=".ProfPhoneActivity">

<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>

Display Country Code


CountryCode.java

package net.simplifiedcoding.firebasephoneauth;

public class CountryData {


public static final String[] countryNames = {"Afghanistan", "Albania",
"Algeria", … "Zimbabwe"};

public static final String[] countryAreaCodes = {"93", "355", … "263"};


}

Getting the Mobile Number


We will get the mobile number of the user in MainActivity. So come inside MainActivity.java and write the following code.

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 {

private Spinner spinner;


private EditText editText;

@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

String number = editText.getText().toString().trim();

if (number.isEmpty() || number.length() < 10) {


editText.setError("Valid number is required");
editText.requestFocus();
return;
}

String phoneNumber = "+" + code + number;

Intent intent = new Intent(MainActivity.this, VerifyPhoneActivity.class);


intent.putExtra("phonenumber", phoneNumber);
startActivity(intent);

}
});
}

@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.

Verifying Mobile Number


Sending Verification Code

For sending verification code we will use the following code.

private void sendVerificationCode(String number) {


progressBar.setVisibility(View.VISIBLE);
PhoneAuthProvider.getInstance().verifyPhoneNumber(
number,
60,
TimeUnit.SECONDS,
TaskExecutors.MAIN_THREAD,
mCallBack
);

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.

Verifying Code and Sign In

To verify verification code we will use this method. If the verification is successful we will let the user sign in into the
application.

private void verifyCode(String code) {


PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
signInWithCredential(credential);
}

private void signInWithCredential(PhoneAuthCredential credential) {


mAuth.signInWithCredential(credential)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {

Intent intent = new Intent(VerifyPhoneActivity.this, ProfileActivity.class);


intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TASK);

startActivity(intent);

} else {
Toast.makeText(VerifyPhoneActivity.this, task.getException().getMessage(),
Toast.LENGTH_LONG).show();

}
}
});
}

168 
Learn Android in the University
VerifyPhoneActivity Code

Here is the full code of VerifyPhoneActivity.java

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;

public class VerifyPhoneActivity extends AppCompatActivity {


//It is the verification id that will be sent to the user
private String verificationId;
//firebase auth object
private FirebaseAuth mAuth;
private ProgressBar progressBar;
//The edittext to input the code
private EditText editText;

@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);

//getting mobile number from the previous activity


//and sending the verification code to the number
Intent intent = getIntent();
String phonenumber = intent.getStringExtra("phonenumber");
sendVerificationCode(phonenumber);

//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) {

String code = editText.getText().toString().trim();

if (code.isEmpty() || code.length() < 6) {

editText.setError("Enter code...");
editText.requestFocus();
return;
169 
Learn Android in the University
}
//verifying the code entered manually
verifyCode(code);
}
});

private void verifyCode(String code) {


//creating the credential
PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
//signing the user
signInWithCredential(credential);
}

private void signInWithCredential(PhoneAuthCredential credential) {


mAuth.signInWithCredential(credential)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
//verification successful we will start the profile activity
Intent intent = new Intent(VerifyPhoneActivity.this,
ProfileActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TASK);

startActivity(intent);

} else {
//verification unsuccessful.. display an error message
Toast.makeText(VerifyPhoneActivity.this,
task.getException().getMessage(), Toast.LENGTH_LONG).show();

}
}
});
}

//the method is sending verification code


//the country id is concatenated
//you can take the country id as user input as well
private void sendVerificationCode(String number) {
progressBar.setVisibility(View.VISIBLE);
PhoneAuthProvider.getInstance().verifyPhoneNumber(
number,
60,
TimeUnit.SECONDS,
TaskExecutors.MAIN_THREAD,
mCallBack
);

//the callback to detect the verification status


private PhoneAuthProvider.OnVerificationStateChangedCallbacks
mCallBack = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

@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

Lesson 14. Firebase Realtime Database CRUD Operation for Android


14.1. Content
Now days NoSQL databases are gaining popularity and Firebase Realtime Database is one of the NoSQL database.

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).

14.2. Designing Database


For this example, we have the following table.

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.

Getting Database Reference


First we need to get the Firebase Database Reference. You can use DatabaseReference to get the reference.

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{

private String title;


private String content;
private @ServerTimestamp Date timestamp;
private String note_id;
private String user_id;

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() {

protected Note(Parcel in) {


title = in.readString();
content = in.readString();
note_id = in.readString();
user_id = in.readString();
}

public static final Creator<Note> CREATOR = new Creator<Note>() {


174 
Learn Android in the University
@Override
public Note createFromParcel(Parcel in) {
return new Note(in);
}

@Override
public Note[] newArray(int size) {
return new Note[size];
}
};

public String getUser_id() {


return user_id;
}

public void setUser_id(String user_id) {


this.user_id = user_id;
}

public String getTitle() {


return title;
}

public void setTitle(String title) {


this.title = title;
}

public String getContent() {


return content;
}

public void setContent(String content) {


this.content = content;
}

public Date getTimestamp() {


return timestamp;
}

public void setTimestamp(Date timestamp) {


this.timestamp = timestamp;
}

public String getNote_id() {


return note_id;
}

public void setNote_id(String note_id) {


this.note_id = note_id;
}

@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.

Now to save the note we will use set() method.

@Override
public void createNewNote(String title, String content) {

FirebaseFirestore db = FirebaseFirestore.getInstance();

String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();

DocumentReference newNoteRef = db
.collection("notes")
.document();

Note note = new Note();


note.setTitle(title);
note.setContent(content);
note.setNote_id(newNoteRef.getId());
note.setUser_id(userId);

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.");
}
}
});
}

The update operation will also be done in the same way.

Read Operation
We will attache a ValueEventListener to the reference to read the data.

private void getNotes(){

FirebaseFirestore db = FirebaseFirestore.getInstance();

CollectionReference notesCollectionRef = db
.collection("notes");

Query notesQuery = null;


if(mLastQueriedDocument != null){
notesQuery = notesCollectionRef
.whereEqualTo("user_id", FirebaseAuth.getInstance().getCurrentUser().getUid())
.orderBy("timestamp", Query.Direction.ASCENDING)
.startAfter(mLastQueriedDocument);
}
else{
notesQuery = notesCollectionRef
.whereEqualTo("user_id", FirebaseAuth.getInstance().getCurrentUser().getUid())

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()){

for(QueryDocumentSnapshot document: task.getResult()){


Note note = document.toObject(Note.class);
mNotes.add(note);
}

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.

Now lets understand the operations in an Android Project.

177 
Learn Android in the University

14.4. Firebase Realtime Database Project


Creating Android Studio Project

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.

Adding Firebase Database


Go to tools -> Firebase, it will open an assistant. Now from the assistant go to Realtime Database.

Connect to your Firebase Project and Setup the dependencies.

179 
Learn Android in the University

Now you are ready to use Firebase Database in your project.

Library
Now add your app level build.gradle file as follows.

//Firebase database
implementation 'com.google.firebase:firebase-database:16.0.1'

Creating Activity Layouts

180 
Learn Android in the University

Lesson 15. Android Login and Registration with PHP MySQL


15.1. Content
The next step after using Firebase concerns using MySQL database with a remote server.

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.

15.2. Creating Web Services


The first phase of this tutorial covers creating web services for User Signup and Login.

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/

Lesson 16. Upload Files in Firebase Storage


16.1. Content
In this tutorial we are going to learn how you can upload images to firebase storage. Infact not only images you can use
this firebase storage android tutorial to upload any kind of file to firebase storage.

https://www.simplifiedcoding.net/firebase-storage-tutorial-android/

Lesson 17. Uploading and Downloading PDF Files

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

- Android App Development – AbhiAndroid (http://abhiandroid.com )

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 

You might also like