[go: up one dir, main page]

0% found this document useful (0 votes)
32 views69 pages

Google Android Dev Final

The document details the Google Android Developer Virtual Internship undertaken by Saripalli Sanjana as part of her Bachelor of Technology in Electronics and Communication Engineering. It provides an overview of the internship program focused on Android app development using Jetpack Compose, emphasizing hands-on experience and practical skills. The document includes acknowledgments, an abstract, and a structured outline of the internship content, covering various aspects of Android development from Kotlin basics to app architecture.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
32 views69 pages

Google Android Dev Final

The document details the Google Android Developer Virtual Internship undertaken by Saripalli Sanjana as part of her Bachelor of Technology in Electronics and Communication Engineering. It provides an overview of the internship program focused on Android app development using Jetpack Compose, emphasizing hands-on experience and practical skills. The document includes acknowledgments, an abstract, and a structured outline of the internship content, covering various aspects of Android development from Kotlin basics to app architecture.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 69

GOOGLE ANDROID DEVELOPER VIRTUAL INTERNSHIP

Internship-I report submitted in partial fulfillment of


requirements for the award of a degree of

Bachelor of Technology
in
Electronics and Communication Engineering
by

SARIPALLI SANJANA (322103312188)

Department of Electronics and Communication Engineering


GAYATRI VIDYA PARISHAD COLLEGE OF ENGINEERING (A)
(Approved by AICTE & Affiliated to Andhra University, Visakhapatnam)

August 2025

I
Electronics and Communication Engineering Department

CERTIFICATE

This is to certify that the Intern-I titled GOOGLE ANDROID DEVELOPER VIRTUAL
INTERNSHIP bonafide record of the work done by SARIPALLI SANJANA (322103312188) in
partial fulfillment 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 Andhra University, Visakhapatnam during the year
2024-2025.

Under the guidance of: Head of the Department:


Mrs. A.M.CH JYOTHI Dr N. Deepika Rani
Assistant Professor, Professor & HoD,
Dept of ECE, Dept. of ECE,
GVPCE(A) GVPCE (A)

II
CERTIFICATE
322103312188

III
ACKNOWLEDGEMENT
We would like to express our deep sense of gratitude to our esteemed institute
Gayatri Vidya Parishad College of Engineering (Autonomous), which has provided
us an opportunity to fulfil our cherished desire.

We express our sincere thanks to our Principal Dr. A. B. Koteswara Rao,


Gayatri Vidya Parishad College of Engineering (Autonomous) for his encouragement
to us during this project, giving us a chance to explore and learn new technologies in the
form of mini projects.
We thank our Internship Mentor Mrs. A.M.CH JYOTHI, Assistant Professor,
Department of Electronics and Communication Engineering for the kind suggestions and
guidance for the successful completion of our internship.

We are highly indebted to Dr. N. Deepika Rani, Associate Professor and Head
of the Department of Electronics and Communication Engineering, Gayatri Vidya
Parishad College of Engineering (Autonomous), for giving us an opportunity to do the
internship in college.

We would also like to thank our Internship Coordinator Dr.Ch. Sitha Kumari,
Associate Professor and for the kind suggestions and guidance for the successful
completion of our internship.

We are grateful to AICTE EDUSKILLS and GOOGLE for providing us with this
learning opportunity. Finally, we are indebted to the teaching and non-teaching staff of the
Electronics and Communication Engineering Department for all their support in completing
our project.

SARIPALLI SANJANA
(322103312188)

IV
ABSTRACT

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


developers. The "Android Basics with Compose" internship equips participants with
essential skills in modern Android app development using Jetpack Compose. This
program provides a comprehensive overview of Jetpack Compose, Google's declarative
UI toolkit, known for its integration with Kotlin, reduced boilerplate code, and enhanced
developer productivity.
Through guided tutorials, coding challenges, and real-world projects, interns
engage in the full app development lifecycle, from conceptualization to deployment. The
internship emphasizes collaboration, innovation, and problem-solving in a virtual
environment, ensuring participants develop practical skills and technical proficiency.
Jetpack Compose's intuitive design, powerful state management, and seamless
integration with existing Android components make it a preferred choice among
developers. Feedback highlights its ease of use, flexibility, and robust feature set,
contributing to high satisfaction levels and widespread adoption.
By completing this internship, participants are well-prepared for careers in mobile
app development. The program's focus on practical, real-world applications enhances
technical skills and career readiness, demonstrating the effectiveness of virtual
internships in providing valuable learning opportunities.
Furthermore, it discusses the scalability and potential impact of virtual internships
in democratizing access to practical learning opportunities. By shedding light on the
"Android Basics with Compose" internship, this abstract contributes to the discourse on
innovative approaches to skill development in the digital age.

V
INTRODUCTION ON GOOGLE ANDROID DEVELOPMENT

In the fast-paced world of technology, practical experience is crucial for aspiring


developers. The "Android Basics with Compose" internship is designed to equip
participants with a comprehensive understanding of Android app development using
Jetpack Compose, Google's innovative toolkit for building native Android UIs. This
program aims to provide interns with the skills necessary to create intuitive, responsive,
and efficient Android applications, leveraging the latest advancements in UI
development.
Jetpack Compose, introduced by Google, marks a significant shift in UI
development for Android. Its declarative approach simplifies the process, making it more
intuitive and flexible compared to traditional XML-based methods. By integrating
seamlessly with Kotlin, Compose allows developers to reduce boilerplate code and create
more expressive and maintainable applications. Kotlin's features, such as concise syntax,
null safety, and coroutine support, further enhance the development experience.
The "Android Basics with Compose" internship offers a structured blend of
theoretical knowledge and hands-on practice. Participants will engage in guided tutorials,
coding challenges, and real-world projects, covering the entire app development lifecycle
from design to deployment. This immersive approach ensures a deep and practical
understanding of Android development, fostering collaboration, innovation, and
problem- solving skills.
Through this internship, participants will gain firsthand experience in creating
dynamic and adaptive user interfaces, managing application state efficiently, and
implementing best practices for performance and maintainability. By the end of the
program, interns will have developed a portfolio of projects demonstrating their ability to
build modern Android applications using Jetpack Compose.
The "Android Basics with Compose" internship not only aims to enhance technical
proficiency but also to prepare participants for successful careers in mobile app
development. By focusing on practical, real-world applications, the program ensures that
participants are well-equipped to meet the demands of the rapidly evolving tech industry.

VI
CONTENTS

Page No.

Certificate III

Acknowledgment IV

Abstract V

Introduction VI

Contents VII-VIII

List of figures IX-X

1. Your first Android app 1- 13


1.1. Introduction to Kotlin
1.2. Set Up Android Studio

1.3. Build a Basic Layout

2. Building app UI 14- 23


2.1. Koltin fundamentals
2.2. Add a button to an app

2.3. Interacting with UI and State

3. Display Lists and use material Design 24- 32


3.1. More Kotlin Fundamentals
3.2. Build a Scrollable List

3.3. Build beautiful Apps

4. Navigation and App Architecture 33 - 37

4.1. Architecture Components


4.2. Navigation in JetPack Compose
4.3. Adapt for different screen sizes

VII
Connect
5. to the internet 38 - 41
5.1. Get data from the internet
5.2. Load and display images from the Internet

Data
6. Persistence 42- 46
6.1. Introduction to SQL
6.2. Use Room for data persistence

6.3. Store and access data using keys with DataStore

Work
7. Manager 47 - 48
7.1. Schedule tasks with Work Manager

Views
8. and Compose 49 - 52
8.1. Android Views
8.2. Views in Compose

Case
9. Study 53 - 55

Conclusion 56

References 57
List of Figures
Figure No Caption (Name of the figure)

1.1 Execution of hello world

1.2 Defining a function Function


1.2.1 name

1.3 Kotlin style guide

1.4 Setting up android studio

1.5 Creating an AVD

1.6 – 1.8 Running apps on android emulator

1.9 Running app on android device with a cable

1.10 Basic layout

2.1-2.2 Kotlin fundamentals

2.3-2.5 Using different statements

2.6-2.10 Creating an instance of class and defining class properties

2.11 Adding a button

2.12 Vertical layout

3.1-3.3 Generics ,objects& extentions

3.4 Collections

3.5 Lists

3.6-3.9 Map collections

3.10-3.13 Building a scrollable list

4.1 Architecture components

4.2 Layers

IX

1
4.3 Adaptive to different screen sizes

5.1 – 5.3 Getting Data from internet

6.1 - 6.3 Reading data with select statement

6.4 Using select statements

6.5 – 6.6 Filtering queries

6.7 Using room for data peristance

6.8 Storing and accessing data

8.1 – 8.2 Android views and compose in views

9.1 – 9.3 Images related to weather forecast

X
2
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 Execution of hello world

1
Parts of function
A function is a segment of a program that performs a specific task. Your program may have one
or more functions.
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.2.1- defining a 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.

2
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.3- Kotlin styl

3
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.4- setting up android studio

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

5
3. 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:
4. You may see a What's New pane which contains updates on new features in Android
Studio. Close it for now.
5. 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.
6. 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
7. In the Design view, you will see a blank pane with this text:
8. 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.

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.

6
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.
6. In the Recommended tab, choose S as the version of Android to run on the virtual device.
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.5- creating an AVD


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.

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

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

Fig: Running apps on android emulator

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

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


5. If you don't see Developer options, tap Advanced options.
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 Play.
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.

10
Fig1.9- Running app on android device with a cable

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:

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

1.10- Basic layout

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

12
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.
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.
11. Click app > res > drawable to confirm that the image is in the drawable folder.

Add a composable function to add an image


In the MainActivity.kt file, add a GreetingImage() composable function after the GreetingText()
function.[1]

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

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:

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

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.

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.

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

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.
 Constructors. Aspecial member function that creates instances of the class
throughout theprogram 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:

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:

16
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 ofline. The device is considered
online when it's connected to the internet. Otherwise, it's considered ofline.
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
immutable property with the val keyword and a mutable property with the var keyword.
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:

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.

17
 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 primaryconstructor, 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 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:

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:

18
2.2. Add a button to an App
2.2.1. Creating an interactive Dice Roller App
1. In Android Studio, click File > New > New Project.
2. In the New Project dialog, select Empty Activity and then click Next.

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

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

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

20
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: To import the Button composable, use the following statement: 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 theresult 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 asa 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".

A lambda is a function literal, which is a function like any other, but instead of being declared
separately with the fun keyword, it is written inline and passed as an expression. The
Button composable is expecting a function to be passed as the onClick parameter. This is
theperfect place to use a lambda, and you will be writing the lambda body in this section.

3. In the Button() function, remove the /*TODO*/ comment from the value of the
lambdabody of the onClick parameter.
4. A dice roll is random. To reflect that in code, you need to use the correct syntax to
generatea random number. In Kotlin,you can use the random() method on a number

21
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 boxdisplays the value set to the state variable as you can see in this image:

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

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.

22
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.
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. The test APK then
runs its tests against the app APK.[2]

23
MODULE 3 - DISPLAYLISTS AND USE MATERIAL DESIGN

3.1 More Kotlin Fundamentals


3.1.1. Generics, objects, and extensions
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.

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.

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

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.

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

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

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

25
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
orderedcollection 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
array- based 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.
Sets:
A set is a collection that does not have a specific order and does not allow duplicate values.

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.

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

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.

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.

27
3.2 Build a Scrollable List

3.2.1Add 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 thatonly contain properties, they can provide some utility methods to work with those
properties.
1. Create a new package under com.example.affirmations.

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.

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

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

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

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

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

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.

31
3.2.2. Testing for Accessibility
Use woof with Talk Back

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:

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.

32
MODULE 4 – NAVIGATION AND APP ARCHITECTURE

4.1 Architecture Components

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.

4.1.1. 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
app. They're 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

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

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

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.

34
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 through user
interactions such as button clicks or gestures. Jetpack Compose provides a type-safe API
for defining navigation actions.
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
35
navigation within Android applications, empowering developers to create intuitive and seamless

36
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
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.[1]

37
38
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 issynchronous 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

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.

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

1.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.[4]

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.

40
1.2. Load and display images from the internet

1.2.1 Add repository and Manual dependency

Injection Repository Pattern:

 The repository pattern serves as an intermediary between the data source (e.g.,
localdatabase, 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.
 Constructor injection involves passing dependencies to a class through its constructor,
while method injection involves providing dependencies through setter methods or
custominitialization 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.
[2]
Coil basically needs two things:
 The URL of the image you want to load and display.
 An AsyncImage composable to actually display that image.

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

42
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 SQLitedata 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.1 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 (.

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

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

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.2. 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.
Instead of a column name, you can call an aggregate function and pass in a column name as an
argument between the parentheses.

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

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

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:

45
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 datastored 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 datain the database.
 Room Database class is the database class that provides your app with instances
of theDAOs 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.

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

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


representa DataStore object instance with a Preferences type.

3. Create a companion object inside the UserPreferencesRepository class.


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.[3]

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

48
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.[1]

Type WorkManager Method Description

Get work getWorkInfoByIdLiveData() This function returns a


using id single LiveData<WorkInfo> for a
specific WorkRequest by its ID.

Get work getWorkInfosForUniqueWorkLiveData() This function


using unique returns LiveData<List<WorkInfo>>
chain name forall work in a unique chain of
WorkRequests.

Get work getWorkInfosByTagLiveData() This function returns


using a tag the LiveData<List<WorkInfo>> for atag.

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

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

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

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

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

a) Jetpack Compose facilitates the integration of Composables with Views and


ViewGroups through interoperability APIs.
b) Developers can embed Composables within existing layouts defined using XML-
based Viewsand ViewGroups, enabling incremental adoption of Compose in legacy
Android projects.
2. ComposeView:

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


traditional Android Views.
b) Developers can include a ComposeView within their layout XML files and inflate
Composablesdynamically at runtime, allowing for seamless integration of Compose-based
UI elements with Views-based layouts.
3. Hosting Composables in Views:

a) 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 layouthierarchy.
b) 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:

a) View interoperability in Jetpack Compose enables bi-directional communication between


Composables and Views.
b) Developers can pass data and events between Composables and Views using interfaces,
callbacks, or LiveData, enabling seamless interaction between the two paradigms within
the sameapplication.
5. Gradual Migration:

a. View interoperability empowers developers to adopt Jetpack Compose gradually,


allowing them to refactor and replace existing Views with Composables
incrementally.

52
b. This approach enables teams to leverage the benefits of Compose, such as
declarative UI designand state management, while maintaining compatibility with
legacy Views during the transition period.
6. Performance Considerations:

a) While view interoperability provides flexibility, developers should consider performance


implications when mixing Views and Composables.
b) 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:

a) When incorporating view interoperability, developers should follow best practices for
managing state, handling layout transitions, and optimizing rendering performance.
b) Clear documentation and code organization are essential to ensure maintainability and
readability, especially in projects with a mix of Composables and traditional Android
Views.

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.[1]

53
9. Case Study

Developing a Weather Forecast Android Application


Scenario:
Weather Forecast is envisioned as a comprehensive weather forecasting app that caters to users diverse
needs while ensuring accuracy and ease of use. The app's development process focuses on key features
that enhance the overall user experience, providing real-time updates and detailed weather information in
an intuitive interface.

Problem Statement:
Many people rely on accurate weather forecasts to plan their daily activities, travel plans, and outdoor
events. However, finding a reliable, user-friendly weather forecasting app that provides realtime updates
and detailed information can be challenging. Users often face issues such as inaccurate forecasts,
complex user interfaces, and limited customization options. This case study focuses on developing a
user-friendly Android application called Weather Forecast that addresses these challenges and provides
an enhanced weather forecasting experience for users.

Solution:
Weather Forecast's solution entails utilizing multiple reliable data sources for accurate forecasts, creating
a minimalist and intuitive interface, implementing push notifications for real-time updates, and
integrating GPS for location-based forecasts. Customization options, including units, themes, and
notification settings, enhance user experience. Continuous updates and user feedback integration ensure
Weather Forecast remains a reliable and user-friendly weather forecasting
app.

Working Process:
1. User Research: The development team conducts extensive user research to understand user
preferences, motivations, and pain points. Insights from user surveys, interviews, and app analytics guide
the design of gamification features.
2. Gamification Design: Based on user feedback and industry best practices, the team identifies key
gamification elements to integrate into the app. These include achievement badges, progress tracking,
challenges, social sharing, and rewards.
3. Android Development: Using Android Studio and Kotlin programming language, the team redesigns
the app's user interface to accommodate gamification features seamlessly. They leverage Android
Jetpack components to implement functionality such as leaderboards, notifications, and in-app
messaging.
4. Integration of Firebase Services: Firebase Authentication, Realtime Database, and Cloud Messaging
services are integrated into the app architecture to enable real-time data synchronization and cloud-based
storage. This facilitates seamless user experiences across multiple devices and platforms.
54
5. Testing and Iteration: The development team conducts rigorous testing, including functional testing,
usability testing, and A/B testing of gamification features. User feedback and performance metrics guide
iterative refinements to optimize user experience and engagement.
Conclusion:
Weather Forecast exemplifies a user-centric approach to developing an Android weather forecasting
application, addressing the challenges users face with existing apps. By prioritizing accuracy, user-
friendliness, customization, and real-time updates, Weather Forecast aims to provide a seamless and
enhanced weather forecasting experience, empowering users to make informed decisions and plan their
activities with confidence.

55
56
10. 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.

57
11.REFERENCES

1. Android Basics with Compose - https://developer.android.com/courses/android-


basics- compose/course

2. Research and Development of Mobile Application for Android Platform


-
https://www.researchgate.net/publication/273903911_Research_and_Develo
p ment_of_Mobile_Application_for_Android_Platform

3. Research on Development of Android


Applications
-
https://ieeexplore.ieee.org/document/61
04696

4. Research on Android Architecture and Application


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

You might also like