Google Android Developer Summer Internship Report
Google Android Developer Summer Internship Report
ON
AT
BY
1
DECLARATION
This is to certify that the Summer Internship entitled “Android Developer Virtual
Internship” is a record of Bonafide work done by us as part of internship in the AICTE
Virtual Internship. The report is based on the project work done entirely by us and not
copied from any other source.
2451-22-750-306
2
CERTIFICATE
3
ACKNOWLEDGEMENT
I would like to express my gratitude to all the people behind the screen who helped me to transform an idea
I would like to thank my Project coordinator K. Padma, Asst Professor, D. Krishna, Associate Professor
for their technical guidance, constant encouragement and support in carrying out my project at college.
I profoundly thank J. Prasanna Kumar, Head of the Department of Computer Science and Engineering,
who has been an excellent guide and a great source of inspiration in my work.
I would like to express my heart-felt gratitude to my parents without whom I would not have been privileged
to achieve and fulfil my dreams. I am grateful to our principal, who most ably runs the institution and has
The satisfaction and euphoria that accompany the successful completion of the task would be great but
incomplete without the mention of the people who made it possible with their constant guidance and
encouragement crowns all the efforts with success. In this context, I would like to thank all the other staff
members, both teaching and non-teaching, who have extended their timely help and eased my task.
4
VISION AND MISSION
VISION
To impart technical education of the highest standards, producing competent and confident
engineers with an ability to use computer science knowledge to solve societal problems.
MISSION
The bachelor’s program in Computer Science and Engineering is aimed at preparing graduates who will:
PEO-1: Achieve recognition through demonstration of technical competence for successful execution of
PEO-2: Practice life-long learning by pursuing professional certifications, higher education or research in
the emerging areas of information processing and intelligent systems at a global level.
PEO-3: Contribute to society by understanding the impact of computing using a multidisciplinary and
ethical approach.
5
Program Outcomes (PO’s)
3.Design and Development of Solutions: Design and develop software solutions and
systems to meet specified needs, considering public health, safety, and environmental
concerns.
complex problems, design experiments, and interpret data to reach valid conclusions.
5.Modern Tool Usage: Select and apply modern tools, techniques, and resources for
6.The Engineer and Society: Assess societal, legal, health, safety, and cultural issues
6
through reports, documentation, and presentations.
11.Project Management and Finance: Demonstrate knowledge of project management and financial
12.Lifelong Learning: Recognize the need for lifelong learning and the ability to adapt
7
Course Objectives:
1.To give experience to the students in solving real life practical problems with all its constraints.
2. To give an opportunity to integrate different aspects of learning with reference to real life problems.
3.To enhance the confidence of the students while communicating with industry engineers
Course Outcomes:
2. Able to complete the task or realize a pre-specified target, with limited scope, rather than taking up a
3. Able to learn to find alternate viable solutions for a given problem and evaluate these alternatives with
8
Abstract
The AICTE Android Developer Virtual Internship, designed in collaboration with Google for
Developers, offers a dynamic platform for students to gain practical experience in Android application
development. The program emphasizes a hands-on approach to mastering Android tools, frameworks, and
Through this internship, participants are introduced to fundamental and advanced concepts of
Android development. The curriculum covers essential topics such as activities, fragments, services, and
layout design, enabling learners to create responsive and user-friendly applications. It also delves into
critical areas like database management, API integration, and cloud storage, equipping participants with
A strong focus is placed on problem-solving and debugging techniques, ensuring participants can
identify and resolve issues efficiently. The program further enhances teamwork and collaboration by
encouraging group projects and peer interactions. With an emphasis on real-world applications,
participants gain insights into optimizing apps for various devices and configurations, ensuring high
The internship not only builds technical proficiency but also fosters lifelong learning and
recognized certificates from AICTE and Edu Skills, validating their expertise and increasing their
employability in the competitive tech landscape. This internship serves as a stepping stone for students
9
Table of Contents
DECLARATION ...........................................................................................................................................2
CERTIFICATE ..............................................................................................................................................3
ACKNOWLEDGEMENT .............................................................................................................................4
Abstract ..........................................................................................................................................................9
MODULE 2 .................................................................................................................................................34
MODULE 3 .................................................................................................................................................49
10
DISPLAY LISTS AND USE MATERIAL DESIGN .................................................................................49
MODULE 4 .................................................................................................................................................65
MODULE 5 .................................................................................................................................................74
MODULE 6 .................................................................................................................................................81
6.3. STORE AND ACCESS DATA USING KEYS WITH DATASTORE ...........................................86
MODULE 7 .................................................................................................................................................89
MODULE 8 .................................................................................................................................................92
11
8.2. VIEWS IN COMPOSE.....................................................................................................................94
Conclusion ...................................................................................................................................................98
References ....................................................................................................................................................99
List Of Figures
Fig 1.2.9 Allowing Physical Devices into Android Studio through USB ...................................................28
Variable........................................................................................................................................................37
ClassName ...................................................................................................................................................38
13
Fig.4.1.2 3 Layer Architecture in Kotlin .....................................................................................................67
Fig.4.1.3 UI ..................................................................................................................................................68
Fig.5.1.2 Retrofit..........................................................................................................................................77
14
ANDROID BASICS WITH COMPOSE
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
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
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
15
Fig.1.1.1 Kotlin Playground
A function is a segment of a program that performs a specific task. Your program may have one or more
functions.
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
Define a function
• The function can also require some inputs, or information that needs to be provided
16
when the function is called. The function uses these inputs to accomplish its purpose.
• The function also has a body which contains the instructions to perform the task.
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
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
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.
17
1.1.3. Kotlin Style Guide
Throughout this course, you'll learn about good coding practices to follow as an Android
developer. One such practice is to follow Google's Android coding standards for code written in Kotlin.
The complete guide is called a style guide and explains how code should be formatted in terms of visual
appearance and the conventions to follow when writing your code. For example, the style guide includes
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.
• The opening curly brace should appear at the end of the line where the function begins.
18
1.2 SET UP 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
2. Click Download Android Studio. The Terms and Conditions page with the Android
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.
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
19
Install Android Studio on Windows
1. Open the folder where you downloaded and saved the Android Studio installation file.
3. If you see a User Account Control dialog about allowing the installation to make
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
20
your internet speed. During this time, you may see a User Account Control dialog for
9. You may also receive a Windows Security Alert about adb.exe. Click Allow Access, if
The Welcome to Android Studio window displays and you're ready to start creating apps.
In this codelab, you create an Android app with the Empty Activity project template provided by Android
Studio.
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
4. Click the Empty Activity template to select it as the template for your project. The Empty Activity
template is the template to create a simple project that you can use to
21
build a Compose app. It has a single screen and displays the text "Hello Android!".
5. Click Next. The New Project dialog opens. This has some fields to configure your project.
7. The Name field is used to enter the name of your project, for this codelab type "Greeting
Card".
8. Leave the Package name field as is. This is how your files will be organized in the file
9. Leave the Save location field as is. It contains the location where all the files related to
your project are saved. Take a note of where that is on your computer so that you can
10. Select API 24: Android 7.0 (Nougat) from the menu in the Minimum SDK field.
Minimum SDK indicates the minimum version of Android that your app can run on.
11. Click Finish. This may take a while - this is a great time to get a cup of tea! While
Android Studio is setting up, a progress bar and message indicates whether Android
12. You may see a What's New pane which contains updates on new features in Android
22
13. Click Split on the top right of Android Studio, this allows you to view both code and
design. You can also click Code to view code only or click Design to view design only.
The Project view (1) shows the files and folders of your project
The Design view (3) is where you preview what your app looks like
15. In the Design view, you will see a blank pane with this text:
16. Click Build & Refresh. It may take a while to build but when it is done the preview
shows a text box that says, "Hello Android!". Empty Compose activity contains all the
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
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
23
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.
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.
To run an Android app in an emulator on your computer, you first create a virtual device.
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.
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
24
the fields unchanged.
8. Click Finish.
1. Select the virtual device that you created from the dropdown menu at the top of the
2. Click Run.
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
25
Fig 1.2.6 Rendering Text in Basic Android App
To let Android Studio communicate with your Android device, you must enable USB
3. If prompted, enter your device password or pin. You know you succeeded when
26
Fig 1.2.7 Turning on Developer Mode in Emulator
6. Tap Developer options and then tap the USB debugging toggle
to turn it on.
27
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.
1. Connect your Android device to your computer with a USB cable. A dialog should
2. Select the Always allow from this computer checkbox and then tap OK.
3. In Android Studio on your computer, make sure your device is selected in the dropdown.
Click.
4. Select your device and then click OK. Android Studio installs the app on your device and
runs it.
5. If your device runs an Android platform that isn't installed in Android Studio and you see
a message that asks whether you want to install the needed platform, click Install >
Continue > Finish. Android Studio installs the app on your device and runs it.
Note: For Android Studio 3.6 and higher, the physical device is automatically selected when
Fig 1.2.9 Allowing Physical Devices into Android Studio through USB
28
1.3. BUILD A BASIC LAYOUT
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
4. Wait for Android Studio to create the project files and build the project.
29
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
elements.
Composable functions
Composable functions are the basic building block of a UI in Compose. A composable function:
Annotations
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,
30
Fig.1.3.2 Using Annotations
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.
1. In Android Studio, click View > Tool Windows > Resource Manager or click the
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.
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.
7. Click Next. 8. Android Studio shows you the folder structure in which your image will
be placed.
9. Click Import(C).
10. Switch back to the project view, click View > Tool Windows > Project or click the
Click app > res > drawable to confirm that the image is in the drawable folder.
32
Fig 1.3.3 Add Image to App
33
MODULE 2
BUILDING APP UI
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
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:
34
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
The if statement can also contain the if branch and else if branches without any else branch:
In Kotlin, when you deal with multiple branches, you can use the when statement
instead of the if/else statement because it improves readability, which refers to how
easy it is for human readers, typically developers, to read the code. It's very
important to consider readability when you write your code because it's likely that
other developers need to review and modify your code throughout its lifetime. Good
readability ensures that developers can correctly understand your code and don't
inadvertently introduce bugs into it. when statements are preferred when there are
35
Fig.2.1.3 Switch Statement Structure
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
statements
Variable
The syntax for conditionals as expressions is similar to statements, but the last line of bodies in each
branch need to return a value or an expression, and the conditionals are assigned to a
36
variable. If the bodies only contain a return value or expression, you can remove the curly
Variable
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:
• Constructors. A special member function that creates instances of the class throughout
37
Creating an instance of class
The Kotlin runtime uses the class, or blueprint, to create an object of that type.
With the Smart Device 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 Smart Device object instance. The
instantiation syntax starts with the class name followed by a set of parentheses as you can see in this
diagram:
ClassName
To use an object, you create the object and assign it to a variable, similar to how you define a
variable. You use the val keyword to create an immutable variable and the var keyword for a
mutable variable. The val or var keyword is followed by the name of the variable, then an =
While methods define the actions that a class can perform, the properties define the class's
38
characteristics or data attributes. For example, a smart device has these properties:
• Device status. Whether the device is on, off, online, or offline. The device is considered
online when it's connected to the internet. Otherwise, it's considered offline.
Properties are basically variables that are defined in the class body instead of the function body.
This means that the syntax to define properties and variables are identical. You define an
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
Default 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
39
object for such a class also changes.
You can see the full syntax to instantiate an object in this diagram:
• Primary constructor. A class can have only one primary constructor, which is defined as part of
the class header. A primary constructor can be a default or parameterized constructor. The primary
constructor doesn't have a body. That means that it can't contain any code.
• Secondary constructor. A class can have multiple secondary constructors. You can
define the secondary constructor with or without parameters. The secondary constructor can
initialize the class and has a body, which can contain initialization logic. If the class has a primary
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:
40
Fig.2.1.10 Structure of Contructor
The secondary constructor is enclosed in the body of the class and its syntax includes three parts:
• Secondary constructor declaration. The secondary constructor definition starts with the
• Primary constructor initialization. The initialization starts with a colon followed by the this
41
2.2. ADD A BUTTON TO AN APP
1. In the New Project dialog, select Empty Activity and then click Next.
4. In the Minimum SDK field, select a minimum API level of 24 (Nougat) from the menu
This composable function represents the UI components of the layout and also holds the
42
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
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.
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:
43
To create a vertical layout:
androidx.compose.foundation.layout.Column.
The modifier argument ensures that the composables in the Column() function adhere to the
3. Pass a horizontalAlignment argument to the Column() function and then set it to a value
of Alignment.CenterHorizontally.
This ensures that the children within the column are centered on the device screen with respect to the
width.
Add a Button:
Note: The import statement for the Button composable is import androidx.compose.material3.Button.
3. In the MainActivity.kt file, add a Text() function to the Button() in the lambda body of
the function.
4. Pass the string resource ID of the roll string to the stringResource() function and pass the
44
Build the Dice roll logic:
Now that all the necessary composables are present, you modify the app so that a tap of the
2. Take a look at the Button composable. You will notice that it is being passed an onClick
parameter which is set to a pair of curly braces with the comment /*TODO*/ inside the
braces. The braces, in this case, represent what is known as a lambda, the area inside of
the braces being the lambda body. When a function is passed as an argument, it can also
4. A dice roll is random. To reflect that in code, you need to use the correct syntax to
generate a random number. In Kotlin, you can use the random() method on a number
range. In the onClick lambda body, set the result variable to a range between 1 to 6 and
then call the random() method on that range. Remember that, in Kotlin, ranges are
designated by two periods between the first number in the range and the last number in
the range.
45
2.3. INTERACT WITH UI AND STATE
State in an app is any value that can change over time. In this app, the state is the bill amount.
1. At the beginning of the EditNumberField() function, use the val keyword to add an
2. Set the value named parameter to an amountInput valueheck the preview. The text box
displays the value set to the state variable as you can see in this image:
3. Run the app in the emulator, try to enter a different value. The hardcoded state
remains unchanged because the TextField composable doesn't update itself. It updates
when its value parameter changes, which is set to the amount Input property.
The amount Input 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
46
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
Testing is an important part of the app development process. By running tests against your app
consistently, you can verify your app's correctness, functional behavior, and usability before you release it
publicly.
Testing also provides a way to continuously check the existing code as changes are
introduced. Why automated tests are important To grow your codebase, you need to test existing
functionality as you add new pieces, which is only possible if you have existing tests. As your app grows,
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
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.
47
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
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
48
MODULE 3
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.
49
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.
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.
50
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.
• 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
51
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,
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.
52
Fig.3.1.7 Operations on Lists
This is how lists are able to add and remove elements. In most cases, it takes the same amount of time to
add any element to a list, regardless of how many elements are in the list. Every once in a while, if adding
a new element would put the array above its defined size, the array elements might have to move to make
room for new elements. Lists do all of this for you, but behind the scenes, it's just an array that gets
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.
• List is an interface that defines properties and methods related to a read-only ordered
collection of items.
53
• MutableList extends the List interface by defining methods to modify a list, such as
These interfaces only specify the properties and methods of a List and/or MutableList. It's up to the class
that extends them to determine how each property and method is implemented. The arraybased
implementation described above is what you'll use most, if not all of the time, but Kotlin allows other
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.
54
Fig.3.1.9 Maps in Kotlin
A map's keys are unique. A map's values, however, are not. Two different keys could map to the same
value. For example, "Mercury" has 0 moons, and "Venus" has 0 moons.
Accessing a value from a map by its key is generally faster than searching through a large list, such as
with indexOf().
Maps can be declared using the mapOf() or mutableMapOf() function. Maps require two generic types
separated by a comma—one for the keys and another for the values.
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.
55
Fig.3.1.11 Defining Maps with some initial values
These collection types allow you to group and organize values in your code. Arrays and lists
provide fast access to elements by their index, while sets and maps use hash codes to make it
In Android apps, lists are made up of list items. For single pieces of data, this could be
56
something simple like a string or an integer. For list items that have multiple pieces of data, like an image
and text, you will need a class that contains all of these properties. Data classes are a type of class that
only contain properties, they can provide some utility methods to work with those properties.
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
and an image resource. Packages are directories that contain classes and even other directories.
57
Fig.3.2.3 Adding Files within a Package
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
58
imageResourceId. They should both be integers.
4. Annotate the stringResourceId property with the @StringRes annotation and annotate
The stringResourceId represents an ID for the affirmation text stored in a string resource.
resource.
uncomment the two import statements and the contents of the class.
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,
59
4. Open res > values > strings.xml. This contains the strings you use in this app, including
5. Open MainActivity.kt. This contains the code to create a simple list that displays a photo
7. DogItem() contains a Row that displays a photo of the dog and information about it.
10. WoofPreview() allows you to see a preview of the app in the Design pane.
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:
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.
60
Fig.3.3.1 Rendering List of Values on UI
Add Color:
A color scheme is the combination of colors that your app uses. Different color combinations
evoke different moods, which influences how people feel when they use your app.
Color, in the Android system, is represented by a hexadecimal (hex) color value. A hex color
code starts with a pound (#) character, and is followed by six letters and/or numbers that
represent the red, green, and blue (RGB) components of that color. The first two letters/numbers refer to
red, the next two refer to green, and the last two refer to blue.
61
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.
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
Switch Access lets you interact with your Android device using one or more switches instead
62
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
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
Users of accessibility services, such as screen readers (like TalkBack), rely on content
when information is conveyed graphically within an element, content descriptions can provide a text
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.
63
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.
64
MODULE 4
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.
App Architecture:
65
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.
Separation of concerns
The separation of concerns design principle states that the app is divided into classes of
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
Considering the common architectural principles mentioned in the previous section, each app
• 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.
66
Fig.4.1.2 3 Layer Architecture in Kotlin
UI layer
The role of the UI layer, or presentation layer, is to display the application data on the screen.
Whenever the data changes due to a user interaction, such as pressing a button, the UI should
• UI elements: components that render the data on the screen. You build these elements
• State holders: components that hold the data, expose it to the UI, and handle the app
ViewModel
The ViewModel component holds and exposes the state the UI consumes. The UI state is
67
application data transformed by ViewModel. ViewModel lets your app follow the architecture principle
View mode stores the app-related data that isn't destroyed when the activity is destroyed and
recreated by the Android framework. Unlike the activity instance, ViewModel objects are not
destroyed. The app automatically retains ViewModel objects during configuration changes so
that the data they hold is immediately available after the recomposition.
To implement ViewModel in your app, extend the ViewModel class, which comes from the
architecture components library and stores app data within that class.
Fig.4.1.3 UI
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
68
destinations and navigation paths within an application. The navigation graph is defined
destinations. This declarative approach allows developers to visualize and manage the
2. NavHost Composable: The NavHost composable serves as the container for displaying
navigation stack and rendering the appropriate destination based on the current
navigation state. Developers can define a NavHost within their composables hierarchy to
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, ensuring compile-time safety and preventing runtime
errors.
to facilitate navigation within the application. These include functions for navigating to
specific destinations, popping destinations off the navigation stack, and accessing
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
69
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
View Models to manage the navigation state and business logic of the application. By
developers can create robust and maintainable navigation flows within their applications.
Overall, navigation in Jetpack Compose offers a modern and efficient approach to handling
navigation within Android applications, empowering developers to create intuitive and seamless user
experiences. With its declarative syntax, type-safe API, and seamless integration with other Jetpack
libraries, Jetpack Compose simplifies the navigation process while providing flexibility and scalability for
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
70
1. Layouts and Views:
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
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, drawablexhdpi, values-
sw600dp), developers can tailor the app's UI elements to fit various screen configurations.
Kotlin enables developers to implement responsive design patterns, such as flexible layouts,
resource loading help create UIs that adapt seamlessly to different screen dimensions.
4. ConstraintLayout Guidelines:
constraints for UI elements, ensuring consistent spacing and alignment across different screen
71
sizes. By anchoring UI elements to guidelines and constraints, developers can create layouts that adapt
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
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.
72
Fig.4.3.1 Different Screen Sizes Offered by Emulators
73
MODULE 5
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.
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
3. 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
function is synchronous or asynchronous is determined by the parts that it's composed of.
4. A synchronous function returns only when its task is fully complete. So after the last
print statement in main() is executed, all work is done. The main() function returns and
74
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
If you try to run your program at this point, there will be a compile error: 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
later. To do this, suspend functions can only be called from other suspend functions that make this
capability available.
A suspending function may contain zero or more suspension points. A suspension point is the
place within the function where execution of the function can suspend. Once execution resumes, it picks
up where it last left off in the code and proceeds with the rest of the function.
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
75
Fig.5.1.1 Interaction between UI and Service Layer
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,
76
Fig.5.1.2 Retrofit
ViewModelScope
A viewModelScope is the built-in coroutine scope defined for each ViewModel in your app.
Any coroutine launched in this scope is automatically canceled if the ViewModel is cleared.
Pattern:
• The repository pattern serves as an intermediary between the data source (e.g., local
• 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
77
• For example, a UserRepository class might contain methods for fetching user data from
• In Kotlin, you can achieve manual dependency injection using constructor injection or
method injection.
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.
78
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.
1. Open the Mars Photos solution app from the Add repository and Manual DI codelab.
79
2. Run the app to confirm that it shows the count of Mars photos retrieved.
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.
80
MODULE 6
DATA PERSISTENCE
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,
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
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.
81
6.1.2. Read data with a SELECT Statement
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
A SELECT statement can also return data from multiple columns. You must separate column
If you want to select every column from the table, you use the wildcard character (*) in place of the
column names.
82
In either case, a simple SELECT statement like this returns every row in the table. You just need to
6.1.3. Use SELECT statements with aggregate functions and distinct values
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
• 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.
Instead of a column name, you can call an aggregate function and pass in a column name as an argument
83
Instead of returning that column's value for every row in the table, a single value is returned
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.
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.
84
Fig.6.1.6 ORDER of Clauses in SELECT statement
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
• Room entities represent tables in your app's database. You use them to update the data
• Room DAOs provide methods that your app uses to retrieve, update, insert, and delete
• Room Database class is the database class that provides your app with instances of the
85
You implement and learn more about these components later in the codelab. The
86
Fig.6.3.1 Define Classes which represents the Data
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
1. In the companion object, implement an immutable TAG string property to use for logging.
reading data. In the isLinearLayout initialization block, before map(), use the
87
3. Preferences DataStore throws an IOException when an error is encountered while
reading data. In the isLinearLayout initialization block, before map(), use the
88
MODULE 7
WORK MANAGER
Work Manager:
Work Manager 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
WorkManager is an incredibly flexible library that has many additional benefits. Some of these benefits
include:
• Support for constraints, such as network conditions, storage space, and charging status.
• Output from one work request used as input for the next.
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.
WorkManager is one option for running a task off of the main thread but it is not a catch-all for running
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.
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.
90
One example is that the device is charging before starting the requested work. You pass
• 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
A WorkInfo object contains details about the current state of a WorkRequest, including:
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
91
MODULE 8
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
XML syntax consists of tags, elements, and attributes. For more details on XML syntax,
In this section, you build an XML layout for the “Type of juice” entry dialog
pictured.
92
Fig.8.1.1 Working with Views
1. Create a new Layout Resource File in the main > res > layout directory called
fragment_entry_dialog.
93
Fig.8.1.3 Naming a new Resource file
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.
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
94
gradually adopt Jetpack Compose within their Android projects while leveraging the rich ecosystem of
- Developers can embed Composables within existing layouts defined using XML-based
Views and ViewGroups, enabling incremental adoption of Compose in legacy Android projects.
2. ComposeView:
- Developers can include a ComposeView within their layout XML files and inflate
- Jetpack Compose provides APIs for hosting Composables within Views, enabling the
composition of UI elements using both Compose and traditional Android Views in the same
layout hierarchy.
- Developers can create custom Views that act as containers for Composables, facilitating
95
the reuse of existing View-based components alongside Compose-based UI elements.
4. Bi-directional Communication:
- Developers can pass data and events between Composables and Views using interfaces,
callbacks, or LiveData, enabling seamless interaction between the two paradigms within the
same application.
5. Gradual Migration:
- This approach enables teams to leverage the benefits of Compose, such as declarative UI
design and state management, while maintaining compatibility with legacy Views during the
transition period.
6. Performance Considerations:
- 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.
96
7. Best Practices:
- When incorporating view interoperability, developers should follow best practices for
- Clear documentation and code organization are essential to ensure maintainability and
readability, especially in projects with a mix of Composables and traditional Android Views.
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
97
Conclusion
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
The internship provided a structured curriculum that equipped interns with essential skills and
From foundational concepts to advanced topics, interns gained valuable hands-on experience and
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
techniques. The hands-on experience gained throughout the program has equipped me with the skills
98
References
99