0% found this document useful (0 votes)
12 views

android-developerauto-recovered

The document is an internship report submitted by Sanapathi Nagasatish for the Android Developer Virtual Internship as part of his Bachelor of Technology in Electronics and Communication Engineering at Gayatri Vidya Parishad College of Engineering. It outlines the structure, objectives, and curriculum of the internship, emphasizing hands-on experience in Android app development using Kotlin. The report also includes acknowledgments, an abstract, and an introduction discussing the significance of the internship in preparing participants for careers in mobile app development.

Uploaded by

245122733153
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views

android-developerauto-recovered

The document is an internship report submitted by Sanapathi Nagasatish for the Android Developer Virtual Internship as part of his Bachelor of Technology in Electronics and Communication Engineering at Gayatri Vidya Parishad College of Engineering. It outlines the structure, objectives, and curriculum of the internship, emphasizing hands-on experience in Android app development using Kotlin. The report also includes acknowledgments, an abstract, and an introduction discussing the significance of the internship in preparing participants for careers in mobile app development.

Uploaded by

245122733153
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 85

lOMoARcPSD|51593599

android developerAuto Recovered)

Electronics and Communication engineering (Gayatri Vidya Parishad College of


Engineering)

Scan to open on Studocu

Studocu is not sponsored or endorsed by any college or university


Downloaded by asrith raj ([email protected])
lOMoARcPSD|51593599

ANDROID DEVELOPER VIRTUAL INTERNSHIP

Internship-II report submitted in partial fulfillment of the requirements for the


award of degree of

Bachelor of Technology

In

Electronics and Communication Engineering


By

SANAPATHI NAGASATISH
(22135A0429)

Department of Electronics and Communication Engineering


GAYATRI VIDYA PARISHAD COLLEGE OF
ENGINEERING
(AUTONOMOUS)

(Affiliated to J.N.T University, Kakinada, A.P)


VISAKHAPATNAM-530048

2024-2025
1

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

ELECTRONICS AND COMMUNICATION ENGINEERING DEPARTMENT

CERTIFICATE

This is to certify that the Intern-II titled ANDROID DEVELOPER VIRTUAL


INTERNSHIP a bonafide record of the work done by SANAPATHI NAGASATISH
(22135A0429) in partial fulfilment of the requirements for the award of the degree of
Bachelor of Technology in Electronics and Communication Engineering of the
Gayatri Vidya Parishad College of Engineering (Autonomous) affiliated to Jawaharlal
Nehru Technological University, Kakinada during the year 2024-2025.

Under the guidance of: Head of the Department:

Dr. Surya Prakasa Rao Reddi, Dr. N. Deepika Rani,


Assistant Professor, Professor & HOD,
Dept. of ECE, Dept. of ECE,
GVPCE(A). GVPCE(A).

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

CERTIFICATE:

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

ACKNOWLEDGEMENT

I would like to express my deep sense of gratitude to my esteemed institute


Gayatri Vidya Parishad College of Engineering - (A), which has provided us
with an opportunity to fulfil my cherished desire.
I express my sincere thanks to our Principal Dr. A.B. KOTESWARA RAO,
Gayatri Vidya Parishad College of Engineering - (A) for his encouragement to
me during this project, giving me a chance to explore and learn new technologies
in the form of a mini project.
I am highly indebted to Dr. N. Deepika Rani, Professor and Head of the
Department of Electronics and Communication Engineering, Gayatri Vidya
Parishad College of Engineering - (A), for allowing me to do the internship in
college.
My Course Coordinator, Dr. J. Bhaskar Rao, Associate Professor, Department
of Electronics and Communication Engineering and our internship mentor, Dr.
Surya Prakasa Rao Reddi, Assistant Professor, Department of Electronics and
Communication Engineering for the kind suggestions and guidance for the
successful completion of my internship.
I thank my Internship Coordinator Dr. Ch. Sita Kumari, Associate Professor,
Department of Computer Science and Engineering, for giving us an opportunity
to do the internship in college.
I express my sincere gratitude towards AICTE and Edu Skills Foundation for
providing me the opportunity to learn new technologies through the Virtual
Internship and I also thank Google who have supported AICTE by providing the
access to the courses to students helping them to gain knowledge in the Domain of
App Development
Finally, I am indebted to the teaching and non-teaching staff of the Electronics and
Communication Engineering Department for all their support in the completion of
my project.

SANAPATHI NAGASATISH

(22135A0429)

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

ABSTRACT

In today's dynamic tech landscape, hands-on experience is indispensable for aspiring


developers. The Google Android Developer Virtual Internship stands out as a pioneering
initiative aimed at equipping participants with practical skills in Android app development. This
abstract delves into the structure and objectives of the internship program, offering a
comprehensive overview of its curriculum and learning outcomes.

Android app development using Kotlin has witnessed remarkable growth and adoption since
Google endorsed it as an official language in 2017. Statistics reveal that over 80% of the top
1000 Android apps on the Google Play Store are leveraging Kotlin for development, indicating a
strong preference among developers. This surge in adoption is attributed to Kotlin's modern
language features, improved syntax, and enhanced productivity compared to Java. Developers
praise Kotlin for its concise syntax, null safety, extension functions, and support for coroutines,
which facilitate asynchronous programming. Moreover, Kotlin's seamless interoperability with
Java enables developers to gradually transition existing codebases to Kotlin, ensuring a smooth
migration process.

Performance-wise, Kotlin offers tangible benefits over Java, with reduced boilerplate code
and increased developer efficiency. Feedback from developers consistently highlights the
language's expressiveness, safety features, and ease of integration with existing Android tools
and libraries. The satisfaction level among developers using Kotlin for Android development
remains high, supported by its robust community and ongoing support from Google and
JetBrains, the language's creators.

Through a blend of guided tutorials, coding challenges, and real-world projects, interns engage in
the complete app development lifecycle, from conceptualization to deployment. The abstract
highlights the program's emphasis on fostering collaboration, innovation, and problem-solving
abilities within a virtual environment. Drawing on participant testimonials and performance
evaluations, it evaluates the effectiveness of the internship in enhancing technical proficiency
and preparing individuals for careers in mobile app development. Furthermore, it discusses the
scalability and potential impact of virtual internships in democratizing access to practical
learning opportunities. By shedding light on the Google Android Developer Virtual Internship,
this abstract contributes to the discourse on innovative approaches to skill development in the
digital age.

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

INTRODUCTION

The Google Android Development Virtual Internship stands as a testament to the


evolving landscape of technology education and workforce development. This innovative
program represents a collaborative effort between Google, a global leader in technology, and
aspiring developers worldwide seeking to gain practical experience in Android app
development. Through a blend of interactive learning modules, real-world projects, and
mentorship opportunities, the internship aims to equip participants with the skills and knowledge
necessary to thrive in the competitive field of mobile app development.

In this introduction, we delve into the structure, objectives, and significance of the
Google Android Development Virtual Internship, shedding light on its role in shaping the next
generation of Android developers. We explore how the program leverages Google's expertise in
Android development to provide participants with a comprehensive learning experience,
fostering collaboration, innovation, and professional growth within a virtual environment.

The introduction sets the stage for understanding the transformative impact of the Google
Android Development Virtual Internship, highlighting its contributions to skill development,
industry readiness, and the broader ecosystem of technology education. Through an exploration
of its key components and underlying principles, we aim to provide a comprehensive overview
of this ground-breaking initiative and its implications for the future of Android app
development.

Moreover, the Google Android Development Virtual Internship serves as a bridge


between theoretical knowledge and real-world application, offering participants the opportunity
to apply their skills in practical scenarios. By working on authentic projects that address industry
challenges and requirements, interns gain invaluable insights into the app development lifecycle,
including ideation, design, implementation, and deployment. This hands-on experience not only
enhances technical proficiency but also cultivates essential soft skills such as problem-solving,
teamwork, and communication, which are vital for success in the technology industry. Through
this immersive learning journey, participants emerge not only as proficient Android developers
but also as adaptable, creative problem solvers prepared to tackle the complexities of modern
software development.

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

INDEX
ANDROID DEVELOPMENT
MODULE 1. YOUR FIRST ANDROID APP (09 - 22)
1.1. Introduction to Kotlin
1.2. Set Up Android Studio
1.3. Build a Basic Layout

MODULE 2. BUILDING APP UI (23 - 34)


2.1. Kotlin fundamentals
2.2. Add a button to an app
2.3. Interacting with UI and State

MODULE 3. DISPLAY LISTS AND USE MATERIAL DESIGN (35 –46)


3.1. More Kotlin Fundamentals
3.2. Build a Scrollable List
3.3. Build beautiful Apps

MODULE 4. NAVIGATION AND APP ARCHTICTURE (47 - 52)


4.1. Architecture Components
4.2. Navigation in Jetpack Compose
4.3. Adapt For Different Screen Sizes

MODULE 5. CONNECT TO THE INTERNET (53 - 57)


5.1. Get Data From Internet
5.2. Load And Display Images From The Internet

MODULE 6. DATA PERSISTANCE (58 - 63)


6.1. Introduction to SQL
6.2. Use Room for data persistence
6.3. Store and access data using keys with DataStore

MODULE 7. WORK MANAGER (64 - 65)


7.1. Schedule tasks with Work Manager

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

MODULE 8. VIEWS AND COMPOSE (66 - 70)


8.1. Android Views
8.2. Views in Compose

9. CASE STUDY (71 - 74)

10. CONCLUSION (75)

11. REFERENCES (76)

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

ANDROID BASICS WITH COMPOSE


MODULE 1 - YOUR FIRST ANDROID APP

1.1 INTRODUCTION TO KOTLIN:


Kotlin is a modern programming language that helps developers be more productive. For
example, Kotlin allows you to be more concise and write fewer lines of code for the same
functionality compared to other programming languages. Apps that are built with Kotlin are also
less likely to crash, resulting in a more stable and robust app for users. Essentially, with Kotlin,
you can write better Android apps in a shorter amount of time. As a result, Kotlin is gaining
momentum in the industry and is the language that the majority of professional Android
developers use.

1.1.1. Run Your First Program

Code in the Kotlin programming language is meant to be understood by humans, so that


people can more easily read, write, and collaborate on Kotlin programs. However, your
computer doesn't immediately understand this language.

We need something called the Kotlin compiler, which takes the Kotlin code you wrote, looks at
it line by line, and translates it into something that the computer can understand. This process is
called compiling the code.

If the code compiles successfully, your program will run (or execute). When the computer
executes your program, it performs each of your instructions.

Fig.1.1.1 Kotlin Playground


1.1.2. Parts Of Function
A function is a segment of a program that performs a specific task. Your program may have one
or more functions.

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Define versus call a function

In your code, you define a function first. That means you specify all the instructions needed to
perform that task.

Once the function is defined, then you can call that function, so the instructions within that
function can be performed or executed.

Define a function

These are the key parts needed to define a function:

• The function needs a name, so you can call it later.

• The function can also require some inputs, or information that needs to be provided
when the function is called. The function uses these inputs to accomplish its purpose.
Requiring inputs is optional, and some functions do not require inputs.

• The function also has a body which contains the instructions to perform the task.

Fig.1.1.2.1 Parts of Function


Function Keyword
To indicate that you're about to define a function in Kotlin, use the special word fun (short for
function) on a new line. You must type fun exactly as shown in all lowercase letters. You can't
use func, function, or some alternative spelling because the Kotlin compiler won't recognize
what you mean. These special words are called keywords in Kotlin and are reserved for a
specific purpose, such as creating a new function in Kotlin.

Function Name
Functions have names so they can be distinguished from each other, similar to how people have
names to identify themselves. The name of the function is found after the fun keyword.

Fig.1.1.2.2 Parts of Function


10

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

1.1.3. Kotlin Style Guide


Throughout this course, you'll learn about good coding practices to follow as an Android
developer. One such practice is to follow Google's Android coding standards for code written in
Kotlin. The complete guide is called a style guide and explains how code should be formatted in
terms of visual appearance and the conventions to follow when writing your code. For example,
the style guide includes recommendations on use of whitespace, indentation, naming, and more.

The purpose of following the style guide is to make your code easier to read and more
consistent with how other Android developers write their code. This consistency is important
when collaborating on large projects together, so that the style of code is the same throughout all
the files in the project.

Here are some of the relevant style guide recommendations for what you've learned in Kotlin so
far:

• Function names should be in camel case and should be verbs or verb phrases.

• Each statement should be on its own line.

• The opening curly brace should appear at the end of the line where the function begins.

• There should be a space before the opening curly brace.

Fig.1.1.3 Formatting rules for Function definition

11

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

1.2. SET UP ANDROID STUDIO


1.2.1. Download and Install Android Studio

Download Android Studio

1. Open any web browser and navigate to the Android Studio download page.

This is the Android Developers website, where you can download Android Studio. This page
automatically detects your operating system.

2. Click Download Android Studio. The Terms and Conditions page with the Android
Studio License Agreement opens.

3. Read the License Agreement.

4. At the bottom of the page, if you agree with the terms and conditions, select the I have
read and agree with the above terms and conditions checkbox.

5. Click Download Android Studio to start the download.

6. When prompted, save the file to a location where you can easily locate it, such as the
Downloads folder.

7. Wait for the download to complete. This may take a while and may be a good moment to
enjoy some tea!

]Install Android Studio on Windows


1. Open the folder where you downloaded and saved the Android Studio installation file.

2. Double-click the downloaded file.

3. If you see a User Account Control dialog about allowing the installation to make
changes to your computer, click Yes to confirm the installation.

Fig.1.2.1 Android Studio Installation Setup


12

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

4. Click Next to start the installation.

5. Accept the default installation settings for all steps.

6. Click Finish when the installation is done to launch Android Studio.

7. Choose your preference of light or dark theme when Android Studio first launches.
Screenshots in this course use the light theme, but choose whichever one you
prefer.

8. During the installation, the setup wizard downloads and installs additional components
and tools needed for Android app development. This may take some time depending on
your internet speed. During this time, you may see a User Account Control dialog for
Windows Command Processor. Click Yes to accept the dialog.

9. You may also receive a Windows Security Alert about adb.exe. Click Allow Access, if
needed, to continue the installation.

10. When the download and installation completes, click Finish.

The Welcome to Android Studio window displays and you're ready to start creating apps.

1.2.2. Create your First Android App


1.2.2.1. Create a project using the template
In this codelab, you create an Android app with the Empty Activity project template provided by
Android Studio.

To create a project in Android Studio:

1. Double-click the Android Studio icon to launch Android Studio.

2. In the Welcome to Android Studio dialog, click New Project.

The New Project window opens with a list of templates provided by Android Studio.

In Android Studio, a project template is an Android project that provides the blueprint for a
certain type of app. Templates create the structure of the project and the files needed for
Android Studio to build your project. The template that you choose provides a starter code to
get you going faster.
3. Make sure the Phone and Tablet tab is selected.

4. Click the Empty Activity template to select it as the template for your project. The

13

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Empty Activity template is the template to create a simple project that you can use to
build a Compose app. It has a single screen and displays the text "Hello Android!".

14

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

5. Click Next. The New Project dialog opens. This has some fields to configure your project.

6. Configure your project as follows:

7. The Name field is used to enter the name of your project, for this codelab type "Greeting
Card".

8. Leave the Package name field as is. This is how your files will be organized in the file
structure. In this case, the package name will be com.example.greetingcard.

9. Leave the Save location field as is. It contains the location where all the files related to
your project are saved. Take a note of where that is on your computer so that you can
find your files.

10. Select API 24: Android 7.0 (Nougat) from the menu in the Minimum SDK field.
Minimum SDK indicates the minimum version of Android that your app can run on.

11. Click Finish. This may take a while - this is a great time to get a cup of tea! While
Android Studio is setting up, a progress bar and message indicates whether Android
Studio is still setting up your project. It may look like this:

12. You may see a What's New pane which contains updates on new features in Android
Studio. Close it for now.

13. Click Split on the top right of Android Studio, this allows you to view both code and
design. You can also click Code to view code only or click Design to view design only.

14. After pressing Split you should see three areas:

The Project view (1) shows the files and folders of your project

The Code view (2) is where you edit code

The Design view (3) is where you preview what your app looks like

15. In the Design view, you will see a blank pane with this text:

16. Click Build & Refresh. It may take a while to build but when it is done the preview
shows a text box that says "Hello Android!". Empty Compose activity contains all the
code necessary to create this app.

15

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

1.2.2.2. Find project files


In this section you will continue to explore Android Studio by becoming familiar with the file
structure.

1. In Android Studio, take a look at the Project tab. The Project tab shows the files and
folders of your project. When you were setting up your project the package name was
com.example.greetingcard. You can see that package right here in the Project tab. A
package is basically a folder where code is located. Android Studio organizes the project
in a directory structure made up of set of packages.

2. If necessary, select Android from the drop-down menu in the Project tab.

3. Select Project Source Files from the drop-down menu. You can now browse the files in
the same way as in any file browser.

4. Select Android again to switch back to the previous view. You use the Android view for
this course. If your file structure ever looks strange, check to make sure you're still in
Android view.

1.2.3. Run your first App on Android Emulator


In this task, you'll use the Device Manager to create an Android Virtual Device (AVD).
An AVD is a software version, also called an emulator, of a mobile device that runs on your
computer and mimics the configuration of a particular type of Android device. This could be any
phone, tablet, TV, watch, or Android auto device. You'll use the AVD to run the Greeting Card
app.

1.2.3.1. Create an AVD


To run an Android app in an emulator on your computer, you first create a virtual device.

1. In Android Studio, select Tools > Device Manager.

2. Click Create virtual device.

3. Select Phone as the category.

4. Select a phone, such as the Pixel 5, and then click Next.

5. If there's a download link next to S, click Download > Accept > Next > Finish. The
presence of the download link indicates that the image isn't installed on your computer,
in which case you must install the image before you can configure the virtual device.
Expect the download to take some time to complete.

16

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

6. In the Recommended tab, choose S as the version of Android to run on the virtual device.

17

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

7. In the AVD Name field, enter a name for your AVD or use the default. Leave the rest of
the fields unchanged.

8. Click Finish.

Fig.1.2.2 Configuring Hardware part of Emulator


1.2.3.2. Run your app on the Android Emulator
1. Select the virtual device that you created from the dropdown menu at the top of the
Android Studio window.

Fig.1.2.3 Drop Menu specifying the installed Emulators

2. Click .

The virtual device starts just like a physical device. Expect this to take a while—potentially
several minutes—for the emulator to start for the first time. The virtual device should open
beside the code editor.

Fig.1.2.4 Emulator in Android Studio

18

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

When your app is ready, it opens on the virtual device.

Fig.1.2.5 Rendering Text in Basic Android App

1.2.4. How to connect your Android Device


1.2.4.1. Enable USB Debugging
To let Android Studio communicate with your Android device, you must enable USB
debugging in the Developer options settings of the device.

To show developer options and enable USB debugging:

1. On your Android device, tap Settings > About phone.

2. Tap Build number seven times.

3. If prompted, enter your device password or pin. You know you succeeded when
you see a You are now a developer! message.

Fig.1.2.6 Turning on Developer Mode in Emulator

4. Return to Settings and then tap System > Developer options.

5. If you don't see Developer options, tap Advanced options.

19

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.1.2.7 Steps to be followed to turn-on dev-mode

6. Tap Developer options and then tap the USB debugging toggle
to turn it on.

1.4.2.2. Run your app on the Android device with a cable


There are two ways to connect your device to Android Studio, through a cable or through Wi-Fi.
You can choose whichever you like more.

To run your app from Android Studio on your Android device:

1. Connect your Android device to your computer with a USB cable. A dialog should
appear on your device, which asks you to allow USB debugging.

2. Select the Always allow from this computer checkbox and then tap OK.

3. In Android Studio on your computer, make sure your device is selected in the dropdown.

Click .

4. Select your device and then click OK. Android Studio installs the app on your device and
runs it.

5. If your device runs an Android platform that isn't installed in Android Studio and you see
a message that asks whether you want to install the needed platform, click Install >
Continue > Finish. Android Studio installs the app on your device and runs it.

Note: For Android Studio 3.6 and higher, the physical device is automatically selected when
the device is connected with debugging turned on.

20

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.1.2.8 Allowing Physical Devices into Android Studio through USB

Fig.1.2.9 Drop Menu specifying the installed


Emulators
1.3. BUILD A BASIC LAYOUT
1.3.1. Build a simple app with text composables

Create an Empty Activity project

1. In the Welcome to Android Studio dialog, select New Project.

2. In the New Project dialog, select Empty Activity and then click Next.

3. In the Name field enter Happy Birthday and then select a minimum API level of 24
(Nougat) in the Minimum SDK field and click Finish.

4. Wait for Android Studio to create the project files and build the project.

5. Click Run ‘app'.

The app should look like this screenshot:

21

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.1.3.1 Rendering Hello World in Basic App


Jetpack Compose
Jetpack Compose is a modern toolkit for building Android UIs. Compose simplifies
and accelerates UI development on Android with less code, powerful tools, and
intuitive Kotlin capabilities. With Compose, you can build your UI by defining a set
of functions, called composable functions, that take in data and describe UI
elements.

Composable functions
Composable functions are the basic building block of a UI in Compose. A composable function:

• Describes some part of your UI.

• Doesn't return anything.

• Takes some input and generates what's shown on the screen.

Annotations
Annotations are means of attaching extra information to code. This information
helps tools like the Jetpack Compose compiler, and other developers understand the
app's code.

An annotation is applied by prefixing its name (the annotation) with the @ character
at the beginning of the declaration you are annotating. Different code elements,
including properties, functions, and classes, can be annotated. Later on in the
course, you'll learn about classes.
22

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.1.3.2 Using Annotations


Composable function names
The compose function that returns nothing and bears the @Composable annotation MUST be
named using Pascal case. Pascal case refers to a naming convention in which the first letter of
each word in a compound word is capitalized. The difference between Pascal case and camel
case is that all words in Pascal case are capitalized. In camel case, the first word can be in
either case.

The Compose function:

• MUST be a noun: DoneButton()


• NOT a verb or verb phrase: DrawTextField()
• NOT a nouned preposition: TextFieldWithLink()
• NOT an adjective: Bright()
• NOT an adverb: Outside()
• Nouns MAY be prefixed by descriptive adjectives: RoundIcon()

1.3.2. Add images to your Android App


1. In Android Studio, click View > Tool Windows > Resource Manager or click the
Resource Manager tab next to the Project window.

2. Click + (Add resources to the module) > Import Drawables.

3. In the file browser, select the image file that you downloaded and then click Open.
Android Studio shows you a preview of the image. Select Density from the QUALIFIER
TYPE drop-down list. You'll learn why you're doing this, in a later section.

4. This action opens the Import drawables dialog.

5. Android Studio shows you a preview of the image. Select Density from the QUALIFIER
TYPE drop-down list. You'll learn why you're doing this, in a later section.

23

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

6. Select No Density from the VALUE list.

7. Click Next. 8. Android Studio shows you the folder structure in which your image will
be placed.
Notice the drawable-nodpi folder.

9. Click Import(C).

10. Switch back to the project view, click View > Tool Windows > Project or click the
Project tab on the far left.

Click app > res > drawable to confirm that the image is in the drawable folder.

Add a composable function to add an image

1. In the MainActivity.kt file, add a GreetingImage() composable


function after the GreetingText() function

24

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

MODULE 2
BUILDING APP
UI

2.1. KOTLIN FUNDAMENTALS


2.1.1. Write conditionals in Kotlin

Use if/else statements to express conditions:

Decision-making is also a fundamental concept in programming. You write


instructions about how a program should behave in a given situation so that it can act or
react accordingly when the situation occurs. In Kotlin, when you want your program to
perform different actions based on a condition, you can use an if/else statement. In the
next section, you write an if statement.

Write if conditions with boolean expressions

Imagine that you build a program that tells drivers what they should do when they're at a
traffic light. Focus on the first condition: a red traffic light. What do you do at a red traffic
light? Stop!

In Kotlin, you can express this condition with an if statement. Take a look at the anatomy
of an if statement:

Fig.2.1.1 Conditional Statement Structure

To use if statements, you need to use the if keyword followed by the condition that you
want to evaluate. You need to express the condition with a boolean expression.
Expressions combine values, variables, and operators that return a value. Boolean
expressions return a boolean value.

The if statement can also contain the if branch and else if branches without any else branch:

25

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.2.1.2 Else-If Conditional Statement Structure

Use a When statement for multiple branches:


In Kotlin, when you deal with multiple branches, you can use the when statement
instead of the if/else statement because it improves readability, which refers to how
easy it is for human readers, typically developers, to read the code. It's very
important to consider readability when you write your code because it's likely that
other developers need to review and modify your code throughout its lifetime. Good
readability ensures that developers can correctly understand your code and don't
inadvertently introduce bugs into it. when statements are preferred when there are
more than two branches to consider.

Fig.2.1.3 Switch Statement Structure

Use if/else and when as expressions:

You can also use conditionals as expressions to return different values for each
branch of condition. When the body of each branch appears similar, you can use
conditional expressions to improve code readability compared to conditional
statements

26

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.2.1.4 Storing Conditional Statement result in a


variable

The syntax for conditionals as expressions is similar to statements, but the last line of bodies in
each branch need to return a value or an expression, and the conditionals are assigned to a
variable. If the bodies only contain a return value or expression, you can remove the curly
braces to make the code more concise.

Fig.2.1.5 Storing Conditional Statement result in a


variable

2.1.2. Use classes and objects in Kotlin


A class definition starts with the class keyword, followed by a name and a set of curly braces.
The part of the syntax before the opening curly brace is also referred to as the class header. In
the curly braces, you can specify properties and functions for the class. You learn about
properties and functions soon. You can see the syntax of a class definition in this diagram:

Fig.2.1.6 Class Structure

A class consists of three major parts:

• Properties. Variables that specify the attributes of the class's objects.

• Methods. Functions that contain the class's behaviors and actions.

27

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

• Constructors. A special member function that creates instances of the class throughout
the program in which it's defined.

Creating an instance of class

The Kotlin runtime uses the class, or blueprint, to create an object of that particular type.
With the SmartDevice class, you have a blueprint of what a smart device is. To have an actual
smart device in your program, you need to create a SmartDevice object instance. The
instantiation syntax starts with the class name followed by a set of parentheses as you can see in
this diagram:

Fig.2.1.7 Rules followed while defining a


ClassName

To use an object, you create the object and assign it to a variable, similar to how you define a
variable. You use the val keyword to create an immutable variable and the var keyword for a
mutable variable. The val or var keyword is followed by the name of the variable, then an =
assignment operator, then the instantiation of the class object.

You can see the syntax in this diagram:

Fig.2.1.8 Creating an Object of class

Defining class properties:


While methods define the actions that a class can perform, the properties define the class's
characteristics or data attributes. For example, a smart device has these properties:

• Name. Name of the device.

• Category. Type of smart device, such as entertainment, utility, or cooking.

• Device status. Whether the device is on, off, online, or offline. The device is considered
online when it's connected to the internet. Otherwise, it's considered offline.

Properties are basically variables that are defined in the class body instead of the function body.
This means that the syntax to define properties and variables are identical. You define an

28

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

immutable property with the val keyword and a mutable property with the var keyword.

29

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Defining a Constructor:
Constructors initialize an object and make the object ready for use. You did this when you
instantiated the object. The code inside the constructor executes when the object of the class is
instantiated. You can define a constructor with or without parameters.

Default constructor
A default constructor is a constructor without parameters.

Defining a Parameterized Constructor:


In the SmartDevice class, the name and category properties are immutable. You need to ensure
that all the instances of the SmartDevice class initialize the name and category properties. With
the current implementation, the values for the name and category properties are hardcoded. This
means that all the smart devices are named with the "Android TV" string and categorized with
the "Entertainment" string.

The constructor now accepts parameters to set up its properties, so the way to instantiate an
object for such a class also changes.

You can see the full syntax to instantiate an object in this diagram:

Fig.2.1.9 Arguments Passed to the class through


the Command Line at Runtime

There are two main types of constructors in Kotlin:

• Primary constructor. A class can have only one primary constructor, which is defined as
part of the class header. A primary constructor can be a default or parameterized
constructor. The primary constructor doesn't have a body. That means that it can't
contain any code.

• Secondary constructor. A class can have multiple secondary constructors. You can
define the secondary constructor with or without parameters. The secondary constructor
can initialize the class and has a body, which can contain initialization logic. If the class
has a primary constructor, each secondary constructor needs to initialize the primary
constructor.

You can use the primary constructor to initialize properties in the class header. The arguments
passed to the constructor are assigned to the properties. The syntax to define a primary
constructor
30

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

starts with the class name followed by the constructor keyword and a set of parentheses. The
parentheses contain the parameters for the primary constructor. If there's more than one
parameter, commas separate the parameter definitions. You can see the full syntax to define a
primary constructor in this diagram:

Fig.2.1.10 Structure of Contructor

The secondary constructor is enclosed in the body of the class and its syntax includes three parts:

• Secondary constructor declaration. The secondary constructor definition starts with the
constructor keyword followed by parentheses. If applicable, the parentheses contain the
parameters required by the secondary constructor.

• Primary constructor initialization. The initialization starts with a colon followed by the
this keyword and a set of parentheses. If applicable, the parentheses contain the
parameters required by the primary constructor.

• Secondary constructor body. Initialization of the primary constructor is followed by a set


of curly braces, which contain the secondary constructor's body.

You can see the syntax in this diagram:

Fig.2.1.11 Primary and Secondary Constructor


together
31

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

2.2. ADD A BUTTON TO AN APP

2.2.1. Creating an interactive Dice Roller App[2]


1. In Android Studio, click File > New > New Project.

2. In the New Project dialog, select Empty Activity and then click Next.

Fig.2.2.1 Selecting Pre-defined UI

3. In the Name field, enter Dice Roller.

4. In the Minimum SDK field, select a minimum API level of 24 (Nougat) from the menu
and then click Finish.

To restructure the sample code:

1. Remove the GreetingPreview() function.

2. Create a DiceWithButtonAndImage() function with the @Composable annotation.

This composable function represents the UI components of the layout and also holds the
buttonclick and image-display logic.

3. Remove the Greeting(name: String, modifier: Modifier = Modifier) function.

4. Create a DiceRollerApp() function with the @Preview and @Composable annotations.

Because this app only consists of a button and an image, think of this composable function as
the app itself. That's why it's called the DiceRollerApp() function.

5. Delete all of the code inside the setContent{} lambda found in the onCreate() method.

32

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

6. In the setContent{} lambda body, call the DiceRollerTheme{} lambda and then inside
the DiceRollerTheme{} lambda, call the DiceRollerApp() function.

7. In the DiceRollerApp() function, call the DiceWithButtonAndImage() function.

Add a modifier

Compose uses a Modifier object, which is a collection of elements that decorate or modify the
behavior of Compose UI elements. You use this to style the UI components of the Dice Roller
app's components.

Create a vertical layout:

In Compose, vertical layouts are created with the Column() function.

The Column() function is a composable layout that places its children in a vertical sequence. In
the expected app design, you can see that the dice image displays vertically above the roll
button:

Fig.2.2.2 Dice App

To create a vertical layout:

1. In the DiceWithButtonAndImage() function, add a Column() function.

Note: The import statement for the Column composable is import


androidx.compose.foundation.layout.Column.

2. Pass the modifier argument from the DiceWithButtonAndImage() method signature to


the Column()'s modifier argument.

33

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

The modifier argument ensures that the composables in the Column() function adhere to the
constraints called on the modifier instance.

3. Pass a horizontalAlignment argument to the Column() function and then set it to a value
of Alignment.CenterHorizontally.

This ensures that the children within the column are centered on the device screen with respect
to the width.

Add a Button:

1. In the strings.xml file, add a string and set it to a Roll value.

res/values/strings.xml

<string name="roll">Roll</string>

2. In the Column()'s lambda body, add a Button() function.

Note: The import statement for the Button composable is import


androidx.compose.material3.Button.

3. In the MainActivity.kt file, add a Text() function to the Button() in the lambda body of
the function.

4. Pass the string resource ID of the roll string to the stringResource() function and pass the
result to the Text composable.

Build the Dice roll logic:

Now that all the necessary composables are present, you modify the app so that a tap of the
button rolls the dice.

Make the button interactive

1. In the DiceWithButtonAndImage() function before the Column() function, create a


result variable and set it equal to a 1 value.

2. Take a look at the Button composable. You will notice that it is being passed an onClick
parameter which is set to a pair of curly braces with the comment /*TODO*/ inside the
braces. The braces, in this case, represent what is known as a lambda, the area inside of
the braces being the lambda body. When a function is passed as an argument, it can also
be referred to as a " callback".

34

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

3. In the Button() function, remove the /*TODO*/ comment from the value of the lambda
body of the onClick parameter.
4. A dice roll is random. To reflect that in code, you need to use the correct syntax to
generate a random number. In Kotlin, you can use the random() method on a number
range. In the onClick lambda body, set the result variable to a range between 1 to 6 and
then call the random() method on that range. Remember that, in Kotlin, ranges are
designated by two periods between the first number in the range and the last number in
the range.

2.3. INTERACT WITH UI AND STATE

2.3.1. Intro to state in Compose


State in an app is any value that can change over time. In this app, the state is the bill amount.

Add a variable to store state:

1. At the beginning of the EditNumberField() function, use the val keyword to add an
amountInput variable set it to "0" value:

val amountInput = "0"

2. Set the value named parameter to an amountInput valueheck the preview. The text box
displays the value set to the state variable as you can see in this image:

Fig.2.2.3 Text Box

3. Run the app in the emulator, try to enter a different value. The hardcoded state
remains unchanged because the TextField composable doesn't update itself. It updates
when its value parameter changes, which is set to the amountInput property.

The amountInput variable represents the state of the text box. Having a hardcoded state isn't
useful because it can't be modified and it doesn't reflect user input. You need to update the state
of the app when the user updates the bill amount.

35

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

2.3.2. Writing Automated Tests


Testing, for software, is a structured method of checking your software to make sure that
it works as expected. Automated testing is code that checks to ensure that another piece of code
that you wrote works correctly.

Testing is an important part of the app development process. By running tests against your app
consistently, you can verify your app's correctness, functional behavior, and usability before you
release it publicly.

Testing also provides a way to continuously check the existing code as changes are

introduced. Why automated tests are important

To grow your codebase, you need to test existing functionality as you add new pieces,
which is only possible if you have existing tests. As your app grows, manual testing
takes much more effort than automated testing. Furthermore, once you start
working on apps in production, testing becomes critical when you have a large user
base. For example, you must account for many different types of devices running
many different versions of Android.

Eventually, you reach a point where automated tests can account for the majority of usage
scenarios significantly faster than manual tests. When you run tests before you release new
code, you can make changes to the existing code so that you avoid the release of an app with
unexpected behaviors.

Remember that automated tests are tests executed through software, as opposed to manual tests,
which are carried out by a person who directly interacts with a device. Automated testing and
manual testing play a critical role in ensuring that users of your product have a pleasant
experience. However, automated tests can be more precise and they optimize your team's
productivity because a person isn't required to run them and they can be executed much faster
than a manual test. Type of automated tests

Local tests

Local tests are a type of automated test that directly test a small piece of code to ensure that it
functions properly. With local tests, you can test functions, classes, and properties. Local tests
are executed on your workstation, which means they run in a development environment without
the need for a device or emulator. This is a fancy way to say that local tests run on your
computer. They also have very low overhead for computer resources, so they can run fast even
with limited resources. Android Studio comes ready to run local tests automatically.

36

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Instrumentation tests

For Android development, an instrumentation test is a UI test. Instrumentation tests let you test
parts of an app that depend on the Android API, and its platform APIs and services.

Unlike local tests, UI tests launch an app or part of an app, simulate user interactions, and check
whether the app reacted appropriately. Throughout this course, UI tests are run on a physical
device or emulator.

When you run an instrumentation test on Android, the test code is actually built into its own
Android Application Package (APK) like a regular Android app. An APK is a compressed file
that contains all the code and necessary files to run the app on a device or emulator. The test
APK is installed on the device or emulator along with the regular app APK.

37

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

MODULE 3
DISPLAY LISTS AND USE MATERIAL DESIGN

3.1. MORE KOTLIN FUNDAMENTALS


3.1.1. Generics, objects, and extentions
Generic types, or generics for short, allow a data type, such as a class, to specify an unknown
placeholder data type that can be used with its properties and methods.

A generic data type is provided when instantiating a class, so it needs to be defined as part of the
class signature. After the class name comes a left-facing angle bracket (<), followed by a
placeholder name for the data type, followed by a right-facing angle bracket (>).

The placeholder name can then be used wherever you use a real data type within the class, such
as for a property.

Fig.3.1.1 Structure of a Generic Class

This is identical to any other property declaration, except the placeholder name is used instead
of the data type. Enum_Class:
An enum class is used to create types with a limited set of possible values. In the real world, for
example, the four cardinal directions—north, south, east, and west—could be represented by an
enum class. There's no need, and the code shouldn't allow, for the use of any additional
directions.
The syntax for an enum class is shown below.

38

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.3.1.2 Structure of an Enum

39

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Each possible value of an enum is called an enum constant. Enum constants are placed inside
the curly braces separated by commas. The convention is to capitalize every letter in the
constant name.

You refer to enum constants using the dot operator.

Fig.3.1.3 Accessing of Enum Variables

3.1.2. Use collections in Kotlin


Arrays:
An array is the simplest way to group an arbitrary number of values in your programs.

Like a grouping of solar panels is called a solar array, or how learning Kotlin opens up an array
of possibilities for your programming career, an Array represents more than one value.
Specifically, an array is a sequence of values that all have the same data type.

Fig.3.1.4 Collections in Kotlin

• An array contains multiple values called elements, or sometimes, items.

• The elements in an array are ordered and are accessed with an index.

What's an index? An index is a whole number that corresponds to an element in the array. An
index tells the distance of an item from the starting element in an array. This is called zero-
indexing. The first element of the array is at index 0, the second element is at index 1, because
it's one place from the first element, and so on.

40

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.3.1.5 Representing an Array


In the device's memory, elements in the array are stored next to each other. While the
underlying details are beyond the scope of this codelab, this has two important implications:

• Accessing an array element by its index is fast. You can access any random element of
an array by its index and expect it to take about the same amount of time to access any
other random element. This is why it's said that arrays have random access.

An array has a fixed size. This means that you can't add elements to an array beyond this size.
Trying to access the element at index 100 in a 100 element array will throw an exception
because the highest index is 99 (remember that the first index is 0, not 1). You can, however,
modify the values at indexes in the array.

Lists:

A list is an ordered, resizable collection, typically implemented as a resizable array. When the
array is filled to capacity and you try to insert a new element, the array is copied to a new bigger
array.

Fig.3.1.6 Lists in Kotlin

With a list, you can also insert new elements between other elements at a specific index.

41

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.3.1.7 Operations on Lists

This is how lists are able to add and remove elements. In most cases, it takes the same amount of
time to add any element to a list, regardless of how many elements are in the list. Every once in
a while, if adding a new element would put the array above its defined size, the array elements
might have to move to make room for new elements. Lists do all of this for you, but behind the
scenes, it's just an array that gets swapped out for a new array when needed.

List and MutableList

The collection types you'll encounter in Kotlin implement one or more interfaces. As you
learned in the Generics, objects, and extensions codelab earlier in this unit, interfaces provide a
standard set of properties and methods for a class to implement. A class that implements the List
interface provides implementations for all the properties and methods of the List interface. The
same is true for MutableList.

So what do List and MutableList do?

• List is an interface that defines properties and methods related to a read-only ordered
collection of items.

• MutableList extends the List interface by defining methods to modify a list, such as
adding and removing elements.

These interfaces only specify the properties and methods of a List and/or MutableList. It's up to
the class that extends them to determine how each property and method is implemented. The
arraybased implementation described above is what you'll use most, if not all of the time, but
Kotlin allows other classes to extend List and MutableList.

42

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Sets:
A set is a collection that does not have a specific order and does not allow duplicate values.

Fig.3.1.8 Set in Kotlin

Map Collection:

A Map is a collection consisting of keys and values. It's called a map because unique keys are
mapped to other values. A key and its accompanying value are often called a key-value pair.

Fig.3.1.9 Maps in Kotlin

A map's keys are unique. A map's values, however, are not. Two different keys could map to the
same value. For example, "Mercury" has 0 moons, and "Venus" has 0 moons.

Accessing a value from a map by its key is generally faster than searching through a large list,
such as with indexOf().

Maps can be declared using the mapOf() or mutableMapOf() function. Maps require two generic
types separated by a comma—one for the keys and another for the values.

Fig.3.1.10 Defining Mutable Maps in kotlin

43

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

A map can also use type inference if it has initial values. To populate a map with initial values,
each key value pair consists of the key, followed by the to operator, followed by the value. Each
pair is separated by a comma.

Fig.3.1.11 Defining Maps with some initial values

These collection types allow you to group and organize values in your code. Arrays and lists
provide fast access to elements by their index, while sets and maps use hash codes to make it
easier to find elements in the collection.

3.2. BUILD A SCROLLABLE LIST

3.2.1. Add a Scrollable List


Create a data class for an Affirmation

In Android apps, lists are made up of list items. For single pieces of data, this could be
something simple like a string or an integer. For list items that have multiple pieces of data, like
an image and text, you will need a class that contains all of these properties. Data classes are a
type of class that only contain properties, they can provide some utility methods to work with
those properties.

1. Create a new package under com.example.affirmations.

44

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.3.2.1 Defining Packages in kotlin

Name the new package model. The model package will contain the data model that will be
represented by a data class. The data class will be comprised of properties that represent the
information relevant to what will be an "Affirmation," which will consist of a string resource
and an image resource. Packages are directories that contain classes and even other directories.

Fig.3.2.2 Defining Packages in kotlin

2. Create a new class in the com.example.affirmations.model package.

45

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.3.2.3 Adding Files within a Package

Name the new class Affirmation and make it a Data class.

Fig.3.2.4 Defining Class Which Represents Data in kotlin

3. Each Affirmation consists of one image and one string. Create two val properties in the
Affirmation data class. One should be called stringResourceId and the other
imageResourceId. They should both be integers.

4. Annotate the stringResourceId property with the @StringRes annotation and annotate
the imageResourceId with the @DrawableRes annotation.

46

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

The stringResourceId represents an ID for the affirmation text stored in a string resource.
The imageResourceId represents an ID for the affirmation image stored in a drawable
resource.

5. In the com.example.affirmations.data package, open the Datasource.kt file and

uncomment the two import statements and the contents of the class.

3.3. BUILD BEAUTIFUL APPS

3.3.1. Material Theming with Jetpack Compose

Explore the starter code

1. Open the starter code in Android Studio.

2. Open com.example.woof > data > Dog.kt. This contains the Dog data class that will be
used to represent the dog's photo, name, age, and hobbies. It also contains a list of dogs
and the information that you will use as the data in your app.

3. Open res > drawable. This contains all the image assets that you need for this project,
including the app icon, dog images, and icons.

4. Open res > values > strings.xml. This contains the strings you use in this app, including
the app name, dog names, their descriptions, and more.

5. Open MainActivity.kt. This contains the code to create a simple list that displays a photo
of a dog, the dog's name, and the dog's age.

6. WoofApp() contains a LazyColumn that displays the DogItems.

7. DogItem() contains a Row that displays a photo of the dog and information about it.

8. DogIcon() displays a photo of the dog.

9. DogInformation() displays the dog's name and age.

10. WoofPreview() allows you to see a preview of the app in the Design pane.

Ensure your emulator/device is in light theme

In this codelab, you will be working with both light and dark themes, however, most of the
codelab is in light theme. Before you get started, ensure that your device/emulator is in light

47

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

theme.

48

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

In order to view your app in light theme, on your emulator or physical device:

1. Go to the Settings app on the device.

2. Search for Dark theme and click into it.

3. If Dark theme is on, switch it off.

Run the starter code to see what you're starting with; it's a list that displays dogs with their
photos, names, and ages. It is functional, but it doesn't look great, so we are going to fix that.

Fig.3.3.1 Rendering List of Values on UI

Add Color:

A color scheme is the combination of colors that your app uses. Different color combinations
evoke different moods, which influences how people feel when they use your app.

Color, in the Android system, is represented by a hexadecimal (hex) color value. A hex color
code starts with a pound (#) character, and is followed by six letters and/or numbers that
represent the red, green, and blue (RGB) components of that color. The first two letters/numbers
refer to red, the next two refer to green, and the last two refer to blue.

Fig.3.3.2 RGB coloring in kotlin

49

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

A color can also include an alpha value—letters and/or numbers—which represents the
transparency of the color (#00 is 0% opacity (fully transparent), #FF is 100% opacity (fully
opaque)). When included, the alpha value is the first two characters of the hex color code after
the pound (#)character. If an alpha value is not included, it is assumed to be #FF, which is 100%
opacity (fully opaque).

Add Shape:

Applying a shape can change so much about the look and feel of a composable. Shapes direct
attention, identify components, communicate state, and express brand. The Shape.kt file is
used to define shapes of components in Compose. There are three types of components: small,
medium, and large. In this section, you will modify the Card component, which is defined as
medium size.
Components are grouped into shape categories based on their size.

3.3.2. Testing for Accessibility


Use woof with TalkBack

TalkBack is a Google screen reader that provides spoken feedback so users can navigate their
device without looking at the screen. This is especially helpful for people with impaired vision.
Once TalkBack is enabled, users can navigate their device through spoken feedback and
gestures— such as swipes and taps. Navigating with TalkBack is a great way for you to test for
areas of improvement in your app.

Use woof with switch Access

Switch Access lets you interact with your Android device using one or more switches instead
of the touchscreen. This alternative to using the touchscreen for users is especially helpful to
users with limited dexterity. Switch Access scans the items on your screen, highlighting each
item in turn, until you make a selection.

To use Switch Access, you'll first need one or more switches. There are several kinds of
switches, when Switch Access is enabled, there is a Menu tab at the top of the device's screen.
When selected, the tab opens a global menu with navigation options, such as Back and Home,
which are equivalent to the gestures on the device screen. Some options customize Switch
Access behavior.

Improving UI Accessibility
50

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

There are a number of UI design choices to consider when trying to create a more
accessible app. In addition to attributes and behaviors that allow for effective usage of
TalkBack and Switch Access, below are some UI optimizations you can make to improve the
accessibility of your app. Content description

Users of accessibility services, such as screen readers (like TalkBack), rely on content
descriptions to understand the meaning of elements in an interface. In some cases, such as
when information is conveyed graphically within an element, content descriptions can provide
a text description of the meaning or action associated with the element.

In Compose, you can describe visual elements using the contentDescription attribute. For
strictly decorative visual elements, it's okay to set the contentDescription to null.

Touch target size:

Any on-screen element that someone can interact with must be large enough for reliable
interaction. The minimum touch target size for something clickable is 48dp high x 48dp wide.
There are a number of Material Design components for which Compose automatically assigns
the correct minimum target size. Keep in mind that the minimum touch target size refers to
clickable components smaller than 48dp. Components larger than 48dp will have a touch target
that is at least the size of the component.

51

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

MODULE 4

NAVIGATION AND APP ARCHITECTURE

4.1.
ARCHITECTURE COMPONENTS[4]
4.1.1. Stages of Activity Life cycle
The activity lifecycle consists of the different states that an activity can go through, from
when the activity first initializes to its destruction, at which time the operating system (OS)
reclaims its memory. Typically, the entry point of a program is the main() method. Android
activities, however, begin with the onCreate() method; this method would be the equivalent of
the egg stage in the above example. You have used activities already, many times throughout
this course, and you might recognize the onCreate() method. As the user starts your app,
navigates between activities, navigates inside and outside of your app, the activity changes state.

Fig.4.1.1 Activity LifeCycle

4.1.2. View Model and State in Compose:


App Architecture:

An app's architecture provides guidelines to help you allocate the app responsibilities between
the classes. A well-designed app architecture helps you scale your app and extend it with
additional features. Architecture can also simplify team collaboration.

Separation of concerns

The separation of concerns design principle states that the app is divided into classes of
functions, each with separate responsibilities.

Drive UI from a model

The drive UI from a model principle states that you should drive your UI from a model,
preferably a persistent model. Models are components responsible for handling the data for an
52

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

app. They're

53

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

independent from the UI elements and app components in your app, so they're unaffected by the
app's lifecycle and associated concerns.

Recommended app architecture

Considering the common architectural principles mentioned in the previous section, each app
should have at least two layers:

• UI layer: a layer that displays the app data on the screen but is independent of the data.

• Data layer: a layer that stores, retrieves, and exposes the app data.

Fig.4.1.2 3 Layer Architecture in kotlin

UI layer

The role of the UI layer, or presentation layer, is to display the application data on the screen.
Whenever the data changes due to a user interaction, such as pressing a button, the UI should
update to reflect the changes.

The UI layer is made up of the following components:

• UI elements: components that render the data on the screen. You build these elements
using Jetpack Compose.

• State holders: components that hold the data, expose it to the UI, and handle the app
logic. An example state holder is ViewModel.

ViewModel

The ViewModel component holds and exposes the state the UI consumes. The UI state is
application data transformed by ViewModel. ViewModel lets your app follow the architecture
principle of driving the UI from the model.
54

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

ViewModel stores the app-related data that isn't destroyed when the activity is destroyed and
recreated by the Android framework. Unlike the activity instance, ViewModel objects are not
destroyed. The app automatically retains ViewModel objects during configuration changes so
that the data they hold is immediately available after the recomposition.

To implement ViewModel in your app, extend the ViewModel class, which comes from the
architecture components library and stores app data within that class.

Fig.4.1.3 UI

4.2 NAVIGATION IN JETPACK COMPOSE

Navigation in Jetpack Compose simplifies the process of implementing navigation within


Android applications, offering a declarative and type-safe approach to handle navigation
between composables. By integrating with the Navigation component of the Android Jetpack
library, Jetpack Compose provides developers with powerful tools to manage navigation flows
efficiently.

1. Navigation Graph: Jetpack Compose utilizes a navigation graph to define the various
destinations and navigation paths within an application. The navigation graph is defined
using a composable function, specifying the navigation routes and associated
destinations. This declarative approach allows developers to visualize and manage the
app's navigation structure effectively.

2. NavHost Composable: The NavHost composable serves as the container for displaying
different destinations within the application. It is responsible for managing the
navigation stack and rendering the appropriate destination based on the current
navigation state. Developers can define a NavHost within their composables hierarchy to
enable navigation functionality.

3. Navigation Actions: Navigation actions define the transitions between destinations


within the navigation graph. Actions can be triggered programmatically or
55

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

through user

56

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

interactions such as button clicks or gestures. Jetpack Compose provides a type-safe API
for defining navigation actions, ensuring compile-time safety and preventing runtime
errors.

4. Navigation Composables: Jetpack Compose offers a set of navigation-related composables


to facilitate navigation within the application. These include functions for navigating to
specific destinations, popping destinations off the navigation stack, and accessing
navigation arguments passed between composables.

5. Safe Args: Jetpack Compose integrates seamlessly with Safe Args, a feature of the
Navigation component that generates type-safe accessors for navigation arguments. This
allows developers to pass data between composables safely and efficiently, reducing the
likelihood of runtime errors caused by type mismatches or missing arguments.

6. Deep Linking: Jetpack Compose supports deep linking, allowing developers to define
custom URL patterns that navigate to specific destinations within the application. Deep
linking enables seamless integration with external sources such as web links or
notifications, enhancing the overall user experience.

7. ViewModel Integration: Navigation in Jetpack Compose can be combined with


ViewModels to manage the navigation state and business logic of the application. By
separating concerns and adhering to the MVVM (Model-View-ViewModel) architecture,
developers can create robust and maintainable navigation flows within their applications.

Overall, navigation in Jetpack Compose offers a modern and efficient approach to handling
navigation within Android applications, empowering developers to create intuitive and seamless
user experiences. With its declarative syntax, type-safe API, and seamless integration with other
Jetpack libraries, Jetpack Compose simplifies the navigation process while providing flexibility
and scalability for building complex navigation flows.

4.3. ADAPT FOR DIFFERENT SCREEN SIZES

Adapting for different screen sizes in Android development using Kotlin is crucial for creating
apps that provide a consistent and user-friendly experience across various devices, ranging from
smartphones to tablets and beyond. Here's some content on this topic:

1. Layouts and Views:

Kotlin allows developers to create flexible layouts using ConstraintLayout, LinearLayout,


FrameLayout, and RelativeLayout among others. These layouts can dynamically adjust their size

57

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

and position based on available screen space, ensuring optimal rendering on devices with
different screen sizes.

2. Resource Qualifiers:

Android's resource system supports qualifiers such as layout, drawable, values, and more,
allowing developers to provide alternative resources for different screen sizes. By creating
layout files, drawables, and dimensions specific to screen sizes (e.g., layout-large, drawable-
xhdpi, values-sw600dp), developers can tailor the app's UI elements to fit various screen
configurations.

3. Responsive Design Patterns:

Kotlin enables developers to implement responsive design patterns, such as flexible layouts,
scalable fonts, and adjustable margins/padding, to accommodate varying screen sizes.
Techniques like using ConstraintLayout guidelines, percent-based dimensions, and dynamic
resource loading help create UIs that adapt seamlessly to different screen dimensions.

4. ConstraintLayout Guidelines:

Kotlin's ConstraintLayout offers guidelines that enable developers to define flexible


constraints for UI elements, ensuring consistent spacing and alignment across different screen
sizes. By anchoring UI elements to guidelines and constraints, developers can create layouts that
adapt fluidly to varying screen dimensions without sacrificing design integrity.

5. Testing and Validation:

Kotlin supports testing frameworks like Espresso and UI Automator for validating app
behavior across different screen sizes and orientations. By conducting comprehensive testing on
various devices and screen configurations, developers can identify and address layout issues,
ensuring a seamless user experience across the board.

In conclusion, adapting for different screen sizes in Android development using Kotlin involves
leveraging responsive design techniques, resource qualifiers, modular UI components, and
testing methodologies to create apps that deliver a consistent and intuitive user experience
across diverse devices.

58

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.4.3.1 Different Screen Sizes Offered by Emulators

59

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

MODULE 5
CONNECT TO THE INTERNET

5.1. GET DATA FROM INTERNET


5.1.1. Introduction to Coroutines in Kotlin Playground Synchronous
Code:
In synchronous code, only one conceptual task is in progress at a time. You can think of it as a
sequential linear path. One task must finish completely before the next one is started. Below is
an example of synchronous code.

1. Open up Kotlin Playground.

2. Replace the code with the following code for a program that shows a weather forecast of
sunny weather. In the main() function, first we print out the text: Weather forecast. Then
we print out: Sunny.

3. println() is a synchronous call because the task of printing the text to the output is
completed before execution can move to the next line of code. Because each function
call in main() is synchronous, the entire main() function is synchronous. Whether a
function is synchronous or asynchronous is determined by the parts that it's composed of.

4. A synchronous function returns only when its task is fully complete. So after the last
print statement in main() is executed, all work is done. The main() function returns and
the program ends.

Add a delay delay() is actually a special suspending function provided by the Kotlin coroutines
library. Execution of the main() function will suspend (or pause) at this point, and then resume
once the specified duration of the delay is over (one second in this case).

If you try to run your program at this point, there will be a compile error: Suspend function
'delay' should be called only from a coroutine or another suspend function.

For the purposes of learning coroutines within the Kotlin Playground, you can wrap your
existing code with a call to the runBlocking() function from the coroutines library.
runBlocking() runs an event loop, which can handle multiple tasks at once by continuing each
task where it left off when it's ready to be resumed. Suspending functions

60

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

A suspending function is like a regular function, but it can be suspended and resumed again
later. To do this, suspend functions can only be called from other suspend functions that make
this capability available.

A suspending function may contain zero or more suspension points. A suspension point is the
place within the function where execution of the function can suspend. Once execution resumes,
it picks up where it last left off in the code and proceeds with the rest of the function.

5.1.2. Introduction to Web services


Create a layer for the network service that communicates with the backend server and fetches
the required data. You use a third-party library, called Retrofit, to implement this task. You
learn more about this later. The ViewModel communicates with the data layer, and the rest of
the app is transparent to this implementation.

Fig.5.1.1 Interaction between UI and Service Layer

5.1.3. Connecting to the Internet


You use the Retrofit library to talk to the Mars web service and display the raw JSON response
as a String. The placeholder Text either displays the returned JSON response string or a message
indicating a connection error.

Retrofit creates a network API for the app based on the content from the web service. It fetches
data from the web service and routes it through a separate converter library that knows how to
decode the data and return it in the form of objects, like String. Retrofit includes built-in support
for popular data formats, such as XML and JSON. Retrofit ultimately creates the code to call
and consume this service for you, including critical details, such as running the requests on
background threads.

61

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.5.1.2 Retrofit

ViewModelScope

A viewModelScope is the built-in coroutine scope defined for each ViewModel in your app. Any
coroutine launched in this scope is automatically canceled if the ViewModel is cleared.

5.2 LOAD AND DISPLAY IMAGES FROM INTERNET

5.2.1. Add repository and Manual dependency Injection Repository pattern


Pattern:
• The repository pattern serves as an intermediary between the data source (e.g., local
database, network) and the rest of the application.

• In Kotlin, you can define a repository class that encapsulates the logic for fetching and
manipulating data. This class abstracts away the details of data retrieval and provides a
clean interface for interacting with data sources.

• For example, a UserRepository class might contain methods for fetching user data from
a local database or a remote server.

Manual Dependency Injection:

• Manual dependency injection involves explicitly providing dependencies to classes


rather than relying on a framework like Dagger or Hilt.

• In Kotlin, you can achieve manual dependency injection using constructor injection or
method injection.

62

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

• Constructor injection involves passing dependencies to a class through its constructor,


while method injection involves providing dependencies through setter methods or
custom initialization methods.

Display a downloaded image:

Displaying a photo from a web URL might sound straightforward, but there is quite a
bit of engineering to make it work well. The image has to be downloaded, internally
stored(cached), and decoded from its compressed format to an image that Android can use.

You can cache the image to an in-memory cache, a storage-based cache, or both. All
this has to happen in low-priority background threads so the UI remains responsive. Also, for
the best network and CPU performance, you might want to fetch and decode more than one
image at once.

Fortunately, you can use a community-developed library called Coil to download, buffer,
decode, and cache your images. Without the use of Coil, you would have much more work to
do.

Coil basically needs two things:

• The URL of the image you want to load and display.

• An AsyncImage composable to actually display that image.

Fig.5.2.1 Displaying the Data fetched from internet


63

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Add Coil dependency

1. Open the Mars Photos solution app from the Add repository and Manual DI codelab.

2. Run the app to confirm that it shows the count of Mars photos retrieved.

3. Open build.gradle.kts (Module :app).

4. In the dependencies section, add this line for the Coil library: // Coil
implementation("io.coil-kt:coil-compose:2.4.0")

5. Click Sync Now to rebuild the project with the new dependency.

64

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

MODULE 6
DATA
PERSISTENCE

6.1. INTRODUCTION TO SQL


6.1.1. Use SQL to read and write to a database:
SQL Lite: SQLite is a commonly used relational database. Specifically, SQLite refers to a
lightweight C library for relational database management with Structured Query Language,
known as SQL and sometimes pronounced as "sequel" for short.

Representing data with SQLite

In Kotlin, you're familiar with data types like Int and Boolean. SQLite databases use data types
too! Data table columns must have a specific data type. The following table maps common
Kotlin data types to their SQLite equivalents.

Kotlin data type SQLite data type

Int INTEGER

String VARCHAR or TEXT

Boolean BOOLEAN

Float, Double REAL

The tables in a database and the columns in each table are collectively known as the schema. In
the next section, you download the starter data set and learn more about its schema.

6.1.2. Read data with a SELECT Statement


A SQL statement—sometimes called a query—is used to read or manipulate a database.

You read data from a SQLite database with a SELECT statement. A simple SELECT statement
consists of the SELECT keyword, followed by the column name, followed by the FROM
keyword, followed by the table name. Every SQL statement ends with a semicolon (.

65

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.6.1.1 Select Statement in SQL

66

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

A SELECT statement can also return data from multiple columns. You must separate column
names with a comma.

Fig.6.1.2 Select Statement in SQL

If you want to select every column from the table, you use the wildcard character (*) in place of
the column names.

Fig.6.1.3 Select Statement in SQL

In either case, a simple SELECT statement like this returns every row in the table. You just need
to specify the column names you want it to return.

6.1.3. Use SELECT statements with aggregate functions and distinct values
Reduce columns with aggregate functions

SQL statements aren't limited to returning rows. SQL offers a variety of functions that can
perform an operation or calculation on a specific column, such as finding the maximum value,
or counting the number of unique possible values for a particular column. These functions are
called aggregate functions. Instead of returning all the data of a specific column, you can return
a single value from a specific column.

Examples of SQL aggregate functions include the following:

• COUNT(): Returns the total number of rows that match the query.

• SUM(): Returns the sum of the values for all rows in the selected column.

• AVG(): Returns the mean value—average—of all the values in the selected column.

• MIN(): Returns the smallest value in the selected column.

• MAX(): Returns the largest value in the selected column.

67

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Instead of a column name, you can call an aggregate function and pass in a column name as an
argument between the parentheses.

Fig.6.1.4 Select Statement with Aggregations

Instead of returning that column's value for every row in the table, a single value is returned
from calling the aggregate function.

Aggregate functions can be an efficient way to perform calculations on a value when you don't
need to read all the data in a database. For example, you might want to find the average of the
values in a column without loading your entire database into a List and doing it manually.

6.1.4. Filter Queries with a WHERE clause


Many email apps offer the feature to filter the messages shown based on certain criteria, such as
data, search term, folder, sender, etc. For these types of use cases, you can add a WHERE clause
to your SELECT query.

After the table name, on a new line, you can add the WHERE keyword followed by an
expression. When writing more complex SQL queries, it's common to put each clause on a new
line for readability.

Fig.6.1.5 Filtering Data using WHERE clause

This query performs a boolean check for each selected row; if the check returns true, it includes
the row in the result of the query. Rows for which the query returns false are not included in
the result.

SELECT Statement syntax:

68

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.6.1.6 ORDER of Clauses in SELECT statement

6.2. USE ROOM FOR DATA PERSISTENCE

Kotlin provides an easy way to work with data through data classes. While it is easy to work
with in-memory data using data classes, when it comes to persisting data, you need to convert
this data into a format compatible with database storage. To do so, you need tables to store the
data and queries to access and modify the data.

The following three components of Room make these workflows seamless.

• Room entities represent tables in your app's database. You use them to update the data
stored in rows in tables and to create new rows for insertion.

• Room DAOs provide methods that your app uses to retrieve, update, insert, and delete
data in the database.

• Room Database class is the database class that provides your app with instances of the
DAOs associated with that database.

You implement and learn more about these components later in the codelab. The
following diagram demonstrates how the components of Room work together to
interact with the database.

69

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.6.2.1 Interaction Between REST API and Database

6.3. STORE AND ACCESS DATA USING KEYS WITH DATASTORE

6.3.1. Implement the user preferences repository

1. In the data package, create a new class called UserPreferencesRepository.

Fig.6.3.1 Define Classes which represents the


Data

2. In the UserPreferencesRepository constructor, define a private value property to


represent a DataStore object instance with a Preferences type.

3. Create a companion object inside the UserPreferencesRepository class.

70

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

4. Use the booleanPreferencesKey() function to define a key and pass it the name
is_linear_layout. Similar to SQL table names, the key needs to use an underscore format.
This key is used to access a boolean value indicating whether the linear layout should be
shown.

Exception handling

Any time you interact with the file system on a device, it's possible that something can
fail. For example, a file might not exist, or the disk could be full or unmounted. As DataStore
reads and writes data from files, IOExceptions can occur when accessing the DataStore. You use
the catch{} operator to catch exceptions and handle these failures.

1. In the companion object, implement an immutable TAG string property to use for logging.

2. Preferences DataStore throws an IOException when an error is encountered while


reading data. In the isLinearLayout initialization block, before map(), use the
catch{}operator to catch the IOException.
3. Preferences DataStore throws an IOException when an error is encountered while
reading data. In the isLinearLayout initialization block, before map(), use the
catch{}operator to catch the IOException.

71

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

MODULE 7
WORK MANAGER

7.1. SCHEDULE TASKS WITH WORK MANAGER

Work Manager:

WorkManager is part of Android Jetpack and an Architecture Component for background work
that needs a combination of opportunistic and guaranteed execution. Opportunistic execution
means that WorkManager does your background work as soon as it can. Guaranteed execution
means that WorkManager takes care of the logic to start your work under a variety of situations,
even if you navigate away from your app.

WorkManager is an incredibly flexible library that has many additional benefits. Some of these
benefits include:

• Support for both asynchronous one-off and periodic tasks.

• Support for constraints, such as network conditions, storage space, and charging status.

• Chaining of complex work requests, such as running work in parallel.

• Output from one work request used as input for the next.

• Handling API-level compatibility back to API level 14 (see note).

• Working with or without Google Play services.

• Following system health best practices.

• Support to easily display state of work requests in the app's UI.


When to use Work Manager:

The WorkManager library is a good choice for tasks that you need to complete. The running
of these tasks is not dependent on the app continuing to run after the work is enqueued. The
tasks run even if the app is closed or the user returns to the home screen.

Some examples of tasks that are a good use of WorkManager:

• Periodically querying for latest news stories.

72

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

• Applying filters to an image and then saving the image.

• Periodically syncing local data with the network.

WorkManager is one option for running a task off of the main thread but it is not a catch-all for
running every type of task off of the main thread.

Work Manager Basics:

There are a few WorkManager classes:

• Worker / CoroutineWorker: Worker is a class that performs work synchronously on a


background thread. As we are interested in asynchronous work, we can use
CoroutineWorker, which has interoperability with Kotlin Coroutines. In this app, you
extend from the CoroutineWorker class and override the doWork() method. This method
is where you put the code for the actual work you want to perform in the background.

• WorkRequest: This class represents a request to do some work. A WorkRequest is where


you define if the worker needs to be run once or periodically. Constraints can also be
placed on the WorkRequest that require certain conditions are met before the work runs.
One example is that the device is charging before starting the requested work. You pass
in your CoroutineWorker as part of creating your WorkRequest.

• WorkManager: This class actually schedules your WorkRequest and makes it run. It
schedules a WorkRequest in a way that spreads out the load on system resources, while
honoring the constraints you specify.

A WorkInfo object contains details about the current state of a WorkRequest, including:

• Whether the work is BLOCKED, CANCELLED, ENQUEUED, FAILED,


RUNNING, or SUCCEEDED.

• If the WorkRequest is finished and any output data from the work.

These methods return LiveData. LiveData is a lifecycle aware observable data holder. We
convert it into a Flow of WorkInfo objects by calling .asFlow().

73

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

MODULE 8
COMPOSE WITH VIEWS

8.1. ANDROID VIEWS AND COMPOSE IN VIEWS


Build an Android App with Views:

Creating Layout

When building an app with Views, you construct the UI inside of a Layout. Layouts
are typically declared using XML. These XML layout files are located in the
resources directory under res > layout. Layouts contain the components that make
up the UI; these components are known as Views.

XML syntax consists of tags, elements, and attributes. For more details on XML syntax,
reference the Create XML layouts for Android codelab.

In this section, you build an XML layout for the "Type of juice" entry dialog
pictured.

Fig.8.1.1 Working with Views

74

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

1. Create a new Layout Resource File in the main > res > layout directory called
fragment_entry_dialog.

Fig.8.1.2 Creating a new Resource file

Fig.8.1.3 Naming a new Resource file

75

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

The fragment_entry_dialog.xml layout contains the UI components that the app displays to the
user.

Notice that the Root element is a ConstraintLayout. This type of layout is a ViewGroup that lets
you position and size Views in a flexible way using the constraints. A ViewGroup is a type of
View that contains other Views, called children or child Views. The following steps cover this
topic in more detail, but you can learn more about ConstraintLayout in Build a Responsive UI
with ConstraintLayout.

8.2. VIEWS IN COMPOSE

View interoperability in Jetpack Compose refers to the seamless integration and coexistence of
Compose-based UI components with existing Android Views and ViewGroups. This capability
allows developers to gradually adopt Jetpack Compose within their Android projects while
leveraging the rich ecosystem of traditional Android Views when needed. Here's some content
on view interoperability in Jetpack Compose:

1. Coexistence of Views and Composables:

- Jetpack Compose facilitates the integration of Composables with Views and


ViewGroups through interoperability APIs.

- Developers can embed Composables within existing layouts defined using XML-based
Views and ViewGroups, enabling incremental adoption of Compose in legacy Android projects.

2. ComposeView:

- The ComposeView class serves as a bridge between Compose-based UI components and


traditional Android Views.

- Developers can include a ComposeView within their layout XML files and inflate
Composables dynamically at runtime, allowing for seamless integration of Compose-based UI
elements with Views-based layouts.

3. Hosting Composables in Views:

76

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

- Jetpack Compose provides APIs for hosting Composables within Views, enabling the
composition of UI elements using both Compose and traditional Android Views in the same
layout hierarchy.

- Developers can create custom Views that act as containers for Composables, facilitating
the reuse of existing View-based components alongside Compose-based UI elements.

4. Bi-directional Communication:

- View interoperability in Jetpack Compose enables bi-directional communication


between Composables and Views.

- Developers can pass data and events between Composables and Views using interfaces,
callbacks, or LiveData, enabling seamless interaction between the two paradigms within the
same application.

5. Gradual Migration:

- View interoperability empowers developers to adopt Jetpack Compose gradually, allowing


them to refactor and replace existing Views with Composables incrementally.

- This approach enables teams to leverage the benefits of Compose, such as declarative UI
design and state management, while maintaining compatibility with legacy Views during the
transition period.

6. Performance Considerations:

- While view interoperability provides flexibility, developers should consider performance


implications when mixing Views and Composables.

- Excessive nesting of Composables within Views or vice versa may impact rendering
performance and hinder the benefits of using Jetpack Compose's optimized rendering pipeline.

7. Best Practices:

- When incorporating view interoperability, developers should follow best practices for
managing state, handling layout transitions, and optimizing rendering performance.

- Clear documentation and code organization are essential to ensure maintainability and
readability, especially in projects with a mix of Composables and traditional Android Views.

77

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

In summary, view interoperability in Jetpack Compose offers developers the flexibility to


combine Composables with existing Views and ViewGroups, enabling gradual adoption of the
Compose framework within Android projects. By leveraging interoperability APIs and best
practices, developers can seamlessly integrate Compose-based UI components with traditional
Android Views, facilitating a smooth transition to modern UI development paradigms.

78

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

9.Case Study

Bus Tracking Android Application

Scenario:
The transportation system for schools in cities has become complex, especially in ensuring the
safety and convenience of students. Parents and guardians are often worried about knowing the
exact location of school buses in real time. Traditional methods of communication can
sometimes fail, leading to stress and delays in tracking buses. Therefore, there is a need for a
reliable mobile application that provides real-time tracking of school buses.

Problem Statement:
Parents and school authorities face challenges in tracking the precise location of school buses in
real time. Current systems are either inaccurate, lack real-time updates, or require significant
manual effort. The absence of a dynamic and user-friendly solution increases stress and delays,
especially during emergencies or when a bus is running late.

Solution:

To address this problem, a mobile application was developed that enables real-time tracking of
school buses using GPS. The app has two components:

Host app: Installed on the driver’s device to send the real-time location to a Firebase
database.
Client app: Used by parents or guardians to track the bus location, view the predefined
bus route, and monitor the bus's progress in real time. The integration of Google Maps
and Firebase ensures accurate location tracking and real-time updates, helping parents
stay informed.

Design

The app’s design focused on providing a simple and intuitive interface. The user-friendly
interface ensures that both the driver (using the host app) and parents (using the client app) can
easily interact with the app without technical difficulties. The main features are the map, which
shows the current location of the bus, the path already covered, and the remaining route.

79

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Fig.9.1 SignInActivity & HostActivity & ClientActivity

Fig. 9.1.2 AndroidManifest.xml

Android Development

Two Android apps were developed using Kotlin:

80

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

• Host App: Captures the GPS location of the bus and sends it to Firebase in real time.
• Client App: Fetches location data from Firebase, draws the predefined route, and shows
the current location of the bus on Google Maps. It also calculates the distance covered and
highlights the remaining route.

Both apps use Android’s FusedLocationProviderClient to handle location services, and Google
Maps API to display routes and the bus's current location.

Integration of Firebase Services

Fig.9.1.3 Firebase Integration for Database & Authentication

Firebase services were integrated for real-time data storage and syncing:

• Firebase Realtime Database: Stores the location data provided by the bus.
• Firebase Authentication: Provides secure sign-in and sign-out functionality for users.
The data in Firebase is continuously updated and fetched in real time to ensure that the client app
shows the most recent location of the bus.

Testing and Iteration

The app went through several stages of testing:

• Unit Testing: Individual features like location updates, Google Maps integration, and
Firebase data syncing were tested.
• User Acceptance Testing (UAT): A small group of parents and bus drivers tested the
app to ensure it met real-world requirements.
• Iterative Improvements: Based on feedback from UAT, changes
were made to the app's UI, performance optimization, and bug fixing.

81

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Deployment and Monitoring

The final version of the app was deployed for users on the Indus App Store for parents, school
authorities, and bus drivers. Firebase Realtime Database is continuously monitored to ensure that
location data is uploaded and fetched without delays.

Conclusion

This project successfully addressed the issue of real-time school bus tracking by creating a robust
mobile solution. Through a combination of Google Maps integration and Firebase services, the app
ensures that parents can view the bus's exact location and progress on a predefined route. This
solution improves safety, reduces stress, and provides peace of mind to parents and school
authorities alike.

82

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

Conclusion

The Google Android Development internship provided a comprehensive learning experience


in building Android applications, covering essential aspects from creating the first app to
incorporating advanced features like data persistence and background processing. Throughout the
internship, I gained proficiency in developing user interfaces following Material Design principles,
enabling me to create visually appealing and intuitive apps. Additionally, the emphasis on
displaying lists efficiently enhanced my ability to present data effectively within applications.
Starting with the creation of their first Android app, interns progressed through building intuitive
user interfaces, implementing Material Design principles, structuring app navigation and
architecture, integrating internet connectivity, managing data persistence, and mastering
background task processing.

The internship provided a structured curriculum that equipped interns with essential skills
and knowledge, ensuring they emerged proficient in developing professional-grade Android
applications. From foundational concepts to advanced topics, interns gained valuable hands-on
experience and emerged ready to embark on successful careers as Android developers.

Additionally, the internship fostered a collaborative learning environment where participants


engaged in practical exercises, code reviews, and projects, allowing them to apply theoretical
knowledge to real-world scenarios. Through mentorship and peer interaction, interns not only
honed their technical skills but also developed critical problem-solving abilities and effective
communication within a team setting. Furthermore, the internship encouraged continuous learning
and adaptation to the ever-evolving landscape of Android development, instilling in interns the
mindset of lifelong learners equipped to tackle new challenges and innovations in the field.

In conclusion, the Google Android Development internship provided a well-rounded


education in Android app development, covering fundamental concepts as well as advanced
techniques. The hands-on experience gained throughout the program has equipped me with the
skills necessary to create impactful and feature-rich Android applications.

83

Downloaded by asrith raj ([email protected])


lOMoARcPSD|51593599

References

1. Android Basics with Compose –


https://developer.android.com/courses/android-basics-compose/

2. Research and Development of Mobile Application for Android Platform –


https://www.researchgate.net/publication/273903911_Research_and_Development_of
_M obile_Application_for_Android_Platform

3. Research on Development of Android Applications


– https://ieeexplore.ieee.org/document/6104696

4. Research on Android Architecture and Application Development –


https://iopscience.iop.org/article/10.1088/1742-6596/1992/2/022168/pdf

5. Modular App building:


https://ai2.appinventor.mit.edu/

84

Downloaded by asrith raj ([email protected])

You might also like