MOBILE APPLICATION DEVELOPMENT
UNIT - I: INTRODUCTION AND MOBILE USER
INTERFACE DESIGN
Topics Covered:
Mobile Web Presence and Applications
User Interface Design: Effective use of screen space,
understanding mobile application users, information design, and
platform-specific tools.
Mobile Platforms and Tools: Overview of Android versions,
features, architecture, and essential tools for application
launching.
Introduction
The mobile web encompasses accessing the World Wide Web (WWW)
through portable devices such as smartphones and tablets. Unlike
traditional desktop-based web browsing via fixed-line networks,
mobile web services are designed for convenience and portability.
Today, the demand for content accessible on multiple platforms and
devices has surged.
Key Benefits of Mobile Web Usage
Faster Connectivity: Advanced wireless technologies enable
seamless browsing.
Portability: Compact and easy to carry devices.
Feature-Rich Experience: Enhanced functionality for diverse
needs.
Wide Range of Applications: Availability of various mobile apps.
1
Devices and Platforms Usage Statistics
Device/ Sign-Up Platform Viewing Platform
Platform Users (%) Users (%)
Android TV 0.4% –
Tv OS 1.87% –
Roku 2.82% 2.43%
Android 5.69% 19.87%
iOS 13.81% –
Web 75.4% 41.21%
Apple TV – 1.21%
iPad – 3.31%
iPhone – 31.88%
These statistics highlight the growing reliance on mobile devices,
primarily due to their portability, speed, and feature-rich nature.
Developing a Mobile Web Presence
1. Planning
Effective planning lays the foundation for a successful mobile
web presence:
Design and Layout: Determine the overall structure of the site,
including colour schemes, menu navigation, and the flow of user
interaction.
Content Strategy: Focus on the key information users will search
for or read on your website.
Visual Assets: Prepare and organize images, icons, and other
graphics to streamline development and enhance user
experience.
2
2. Building
This phase involves transforming plans into a functional mobile
website:
Responsive Design: Create layouts that adapt seamlessly to
different devices, including smartphones and tablets.
Functional Features: Add essential elements such as forms,
interactive calendars, or notification systems to improve
usability.
Pre-Launch Testing: Check for errors, ensure functionality, and
make necessary edits before the site goes live.
3. Sharing and Marketing
To attract visitors, promote your website through various
channels:
Social media: Share updates and links on platforms like
Instagram, LinkedIn, Facebook, and Twitter to drive traffic.
Search Engine Indexing: Optimize your site for search engines
to ensure it appears in search results.
Networking: Share your web presence with professional
connections and within relevant community groups.
4. Growing
A growing website attracts more visitors and sustains long-term
engagement:
Content Updates: Regularly publish blogs, articles, or updates to
keep your site relevant and engaging.
Search Engine Optimization (SEO): Use targeted keywords and
maintain high-quality content to improve visibility in search
results.
3
5. Maintenance
Consistent maintenance ensures your site remains secure,
functional, and relevant.
Security Updates: Protect your site from vulnerabilities and
potential hacking attempts by updating software and plugins.
Content Refresh: Update text, images, and design elements to
keep the site visually appealing and informative.
Performance Monitoring: Use tools like Google Analytics to track
user behaviour and identify areas for improvement.
Password Management: Update passwords regularly to enhance
site security.
FAQ1: What is Mobile Application development?
Mobile application development is the set of processes and
procedures involved in writing software for small, wireless computing
devices, such as smartphones and other hand-held devices.
MOBILE APPLICATIONS (APPS)-TYPES
Native Apps
Native applications are specifically developed for a particular mobile
platform, such as Android or iOS. For example, native iOS apps are
created using programming languages like Swift or Objective-C, while
Android native apps are developed using Kotlin or Java. By being
tailored to a specific platform, native apps can fully leverage the
device’s hardware and software features, providing high performance
and a seamless user experience.
Key Advantage: The primary benefit of native apps is their
ability to deliver an optimized user experience. Since they are
designed specifically for a particular platform, they perform
4
efficiently and have an intuitive interface that aligns with the
platform's standards.
Examples: Some popular native apps include Instagram
(Android), VLC media player (Android), WordPress (iOS), and the
2048 game (iOS).
Languages for Native Development:
1. Swift or Objective-C for iOS apps
2. Java or Kotlin for Android apps
3. C# or VB.NET for Windows apps
Hybrid Apps
Hybrid applications merge the features of both native and web apps.
These apps are developed using web technologies like HTML, CSS,
and JavaScript and are then encapsulated within a native wrapper
using frameworks such as Apache Cordova or Ionic. This approach
allows a single codebase to work across multiple platforms, reducing
both development time and costs. However, hybrid apps may not offer
the same level of performance as native apps due to their dependency
on web-based technologies.
Examples: Popular hybrid apps include MarketWatch, Untappd,
Fan React, and TripCase.
5
Frameworks for Hybrid Development:
Ionic Framework
Flutter Framework
Progressive Web Apps (PWAs)
Progressive Web Applications (PWAs) offer a native-like experience on
mobile devices while being developed using standard web
technologies such as HTML, CSS, and JavaScript. These apps are
designed to work offline, send push notifications, and can even be
added to the home screen, offering functionalities similar to native
apps. Unlike native applications, PWAs are accessible directly via web
browsers and do not require distribution through app stores. This
makes them a flexible and cost-effective solution for developers
aiming to reach a broad audience.
User Interface Design in Android
Android is a versatile platform with a wide range of devices and fewer
restrictions compared to other systems. This flexibility, guided by
Google and supported by a global user base, has made Android a
strong competitor in the mobile market. However, designing for
Android requires understanding its unique conventions, such as
placing view-control tabs at the top of the screen, using the main
application icon for navigation instead of a "back" button, and
avoiding the reuse of interface elements from other platforms.
Incorporating features like parallax scrolling and home-screen
widgets can further enhance the user experience.
Key Points:
Tabs are conventionally placed at the top of the screen.
6
The main application icon is used for hierarchical navigation.
Avoid replicating design elements or icons from other platforms.
Features like parallax scrolling and home-screen widgets add
functionality.
Effective Use of Screen Real Estate
Designing for small mobile interfaces requires understanding user
contexts, needs, and behaviour. Developers should embrace
minimalism by limiting features and ensuring all screen elements
serve a purpose. Maintaining a clear visual hierarchy, with prominent
features highlighted using size, colour, and contrast, helps reduce
cognitive load. A focused approach keeps file sizes smaller, improving
load times and user experience by avoiding overwhelming users with
unnecessary content or excessive navigation steps.
1. Embrace Minimalism-A minimalist approach to mobile
application design involves limiting the number of features
displayed on each screen to prevent clutter and enhance usability.
Every design component, such as banners, graphics, and bars,
must have a specific and valuable purpose. Designers should
carefully evaluate each element to ensure it contributes to the
overall functionality of the application, avoiding unnecessary
content unless it adds clear value.
2. Use a Visual Hierarchy-Implementing a well-structured visual
hierarchy helps users navigate the application effortlessly by
prioritizing important information. Key elements should stand out
through the use of larger sizes, bold or vibrant colours, and visual
markers like arrows or bullets, guiding the user’s attention.
Conversely, secondary content can be displayed in lighter shades,
smaller sizes, or with minimal emphasis. Maintaining consistency in
7
the visual hierarchy through careful use of position, shape, size,
and contrast ensures an intuitive and user-friendly experience.
3. Stay Focused-Focus is critical during the development process to
create efficient and streamlined applications. Keeping the file size
small not only speeds up loading times but also improves usability
by reducing unnecessary features and images. By minimizing
complex navigation paths and avoiding text-heavy pages,
developers can keep users engaged. Understanding user
expectations and prioritizing essential features ensures the
application meets their needs without overwhelming them,
delivering a purposeful and enjoyable experience.
Key Points:
Embrace minimalism—limit features and ensure purposeful
design.
Use visual hierarchy to draw attention with size, colour, and
contrast.
Focused design reduces load times and enhances usability.
Avoid text-heavy pages to maintain user engagement.
Understanding Mobile Application Users
Mobile users engage with applications in short bursts during daily
activities. To create intuitive designs, developers can use real-world
metaphors like a recycle bin for deleted files while adhering to
industry standards. Drawing from established principles like the
Gestalt theories of visual perception ensures simplicity and usability.
These principles, including proximity, closure, continuity, figure-
8
ground relationships, and similarity, help designers create visually
cohesive and user-friendly interfaces.
Key Points:
Mobile usage is context-driven and time-sensitive.
Use real-world metaphors and adhere to industry standards.
Apply Gestalt principles (proximity, closure, continuity, figure-
ground, similarity) for intuitive designs.
Simplicity is key to user satisfaction.
Mobile Information Design
The way information is visually displayed on mobile devices is crucial
for effective interaction and communication. Whether it's checking on
the status of a car's gas tank or navigating through an unfamiliar
area, mobile screens serve as the medium for real-time data that users
rely on. Designing for mobile offers an exciting opportunity to tailor
content for small, personalized, and context-driven screens. However,
it's essential to keep the user's goals in mind, as mobile devices are
typically used for quick, task-oriented interactions rather than
complex searches or extended browsing. Designers must prioritize
clarity, brevity, and functionality to provide an optimal user experience
in this constrained space.
Tools for Mobile Interface Design
1.Sketch-Sketch is a widely used design tool for macOS, primarily
focused on UI and UX design for mobile and web applications. It is
commonly employed for creating wireframes, prototypes, and custom
icons. Its standout features include responsive grid guides for
alignment, reusable symbols for consistency across designs, and rapid
9
iteration capabilities. While Sketch excels in macOS environments, it
has limited real-time preview functionality on Android or Windows
devices. Despite these limitations, companies like Apple, Facebook,
and Google use Sketch for its precision and efficiency in design
workflows.
2.Figma-Figma is a collaborative, cloud-based vector graphics editor
and prototyping tool that allows real-time teamwork. It is designed
specifically for UI/UX projects, enabling users to create interactive
prototypes and scalable designs for different screen sizes. Figma
stands out for its real-time collaboration feature, which allows
multiple designers to work on the same project simultaneously,
making it ideal for team-based projects. Large organizations like
Microsoft, Uber, and Slack rely on Figma due to its versatility,
seamless collaboration features, and ability to ensure design
consistency across platforms.
3. Mockplus-Mockplus is a fast, easy-to-use prototyping tool for
designing mobile applications on both Android and iOS. It includes a
comprehensive library of interface components and icons, helping
designers quickly build prototypes for testing and iteration. Its user-
friendly interface makes it suitable for both beginners and
professionals, while its emphasis on simplicity helps developers focus
on creating functional and efficient designs. Mockplus is perfect for
designers looking to quickly transform ideas into tangible prototypes
without a steep learning curve.
4.AdobeXD-Adobe XD is a comprehensive design tool available on
both macOS and Windows, aimed at helping designers create
wireframes, high-fidelity prototypes, and interactive designs. Its key
features include responsive resizing to adapt designs for multiple
screen sizes, repeat grids for consistent replication of design
elements, and easy integration with other Adobe Creative Cloud tools.
Adobe XD is widely respected for its flexibility and powerful features,
10
making it a go-to option for designers already using Adobe's
ecosystem of tools.
5.Proto.io-Proto.io is a web-based tool designed to simplify the
process of creating interactive, animated prototypes for mobile
applications. Its intuitive drag-and-drop interface makes it easy to
design and test prototypes without coding. Proto.io supports a wide
range of animation, transition, and gesture effects, which help
simulate the experience of using a final app. It also includes
collaboration features, allowing teams to work together seamlessly on
design projects. Proto.io is ideal for designers seeking a
straightforward tool for prototyping with dynamic, interactive
features.
ANDROID VERSIONS
Version Release Date API Key Features
Level
Android 1.0 September 1 Initial release; basic
functionality including a
23, 2008
Alpha web browser, camera,
Gmail synchronisation,
and the Android Market.
Android 1.1 February 9, 2 Minor updates and bug
fixes; improvements to
2009
Beta the Android Market app.
Android 1.5 April 27, 2009 3 Introduction of on-screen
keyboard, widgets, video
Cupcake
recording, and upload to
YouTube.
Android 1.6 September 4 Enhanced user interface,
improved search
Donut 15, 2009
functionality, support for
WVGA screen resolutions,
and Quick Search Box.
Android October 26, 5/7 Improved user interface,
new browser interface,
11
2.0/2.1 Eclair 2009 Microsoft Exchange
support, and Bluetooth
2.1.
Android 2.2 May 20, 2010 8 Speed improvements,
support for Adobe Flash,
Froyo
USB tethering, and Wi-Fi
hotspot functionality.
Android 2.3 December 6, 9/10 Improved UI design,
enhanced copy-paste
Gingerbread 2010
functionality, support for
extra-large screen sizes
and NFC.
Android February 22, 11/12/ Specifically designed for
tablets, refined
3.0/3.1/3.2 2011 13
multitasking, holographic
Honeycomb user interface, and
support for multi-core
processors.
Android 4.0 October 18, 14/15 Unified user interface for
smartphones and tablets,
Ice Cream 2011
face unlock, data usage
Sandwich analysis, and improved
copy-paste.
Android July 9, 2012 16/17/ Project Butter for
smoother performance,
4.1/4.2/4.3 18
Google Now, expandable
Jelly Bean notifications, and multiple
user accounts for tablets.
Android 4.4 October 31, 19/20 Optimized for low-end
devices, immersive mode,
KitKat 2013
improved memory
management, and
support for wireless
printing.
Android November 12, 21/22 Material Design,
improved notifications,
5.0/5.1 2014
battery saver feature, and
Lollipop support for 64-bit CPUs.
Android 6.0 October 5, 23 Google Now on Tap, Doze
mode for battery saving,
12
Marshmallow 2015 granular app permissions,
and native support for
fingerprint recognition.
Android August 22, 24/25 Split-screen mode, quick
app switching, bundled
7.0/7.1 2016
notifications, and
Nougat improved Doze mode.
Android August 21, 26/27 Picture-in-picture mode,
notification dots, autofill
8.0/8.1 Oreo 2017
API, and Android Instant
Apps.
Android 9.0 August 6, 28 Adaptive Battery and
Brightness, gesture
2018
Pie navigation, Digital
Wellbeing, and App
Actions.
Android 10 September 3, 29 Dark mode, Smart Reply
in notifications, enhanced
2019
Q privacy controls, and
support for foldable
phones.
Android 11 September 8, 30 Conversation bubbles,
one-time permissions,
2020
R built-in screen recording,
and improved support for
5G.
Android 12 October 4, 31 Material You design,
improved privacy
2021
S dashboard, microphone
and camera indicators,
and enhanced auto-
rotate.
Android 13 August 15, 33 Enhanced customization
options, improved privacy
2022
Tiramisu settings, Bluetooth LE
audio support, and spatial
audio.
Android 14 April 12, 2023 34 Enhanced security and
privacy, satellite
(Developer
connectivity support,
13
Upside Down Preview); predictive back gestures,
and improved battery life.
Cake August 21,
2023 (Stable
Release)
Android 15 October 3, 35 Anticipated features
include further
2024
Vennila enhancement of user
customization, improved
Icecream
performance, and
advanced AI capabilities
for personalized user
experiences.
FEATURES OF ANDROID
1. Multi-Window Support on Android enhances multitasking by
enabling users to work with multiple apps simultaneously. One of
the key features is Split-Screen Mode, which allows two
applications to run side by side, improving productivity. Another
feature, Picture-in-Picture (PiP), lets users continue watching
videos or using navigation apps in a small window while performing
other tasks, offering a seamless multitasking experience.
Additionally, Freeform Mode (experimental) enables users to
resize and move app windows, much like desktop environments,
adding more flexibility to how users interact with apps.
2. Notification Channels provide a more organized and
customizable way to manage alerts. Notifications are grouped into
different categories, such as messages or calls, making it easier for
users to identify their importance. Users also have control over
how these notifications appear, including settings for sound,
vibration, and visual interruptions. The importance levels of
notifications can be customized, from urgent alerts with sound to
low-priority notifications with no visual disruption, offering a
tailored experience based on user preferences.
14
3. Biometric Authentication on Android includes several methods
to ensure secure access to devices and apps. Fingerprint
Authentication offers fast and reliable unlocking, as well as app
authentication using the user’s fingerprint. Face Recognition
leverages the front camera to scan and verify the user’s face,
providing an alternative method for unlocking. Iris Scanning
offers an even more secure biometric method by scanning the
user’s iris. Android’s Biometric API simplifies the integration of
these authentication methods into apps, enabling developers to add
secure login functionality effortlessly.
4. In addition to security features, Android also includes Adaptive
Battery and Brightness, which uses machine learning to optimize
the device’s battery consumption based on usage patterns. This
feature ensures that battery power is used efficiently, extending the
device's lifespan. The Dark Mode feature provides a system-wide
theme that reduces eye strain, especially on OLED screens, and
also helps save battery. Gesture Navigation replaces traditional
navigation buttons with swipe gestures, offering a more immersive
and fluid user experience that allows users to make better use of
screen real estate.
5. Digital Wellbeing is a suite of tools designed to help users
manage their screen time and promote healthier digital habits.
Features such as app usage timers and a dashboard that tracks
screen time enable users to monitor and adjust their app usage for
a more balanced lifestyle. Finally, Enhanced Privacy Controls
give users greater control over their data and permissions.
Features like one-time permissions for apps and a privacy
dashboard that displays how apps access data ensure users can
make informed decisions about their privacy. These features
together contribute to a more secure, user-friendly, and efficient
Android experience.
15
MOBILE APPLICATION ARCHITECTURE
What is Mobile App Architecture?
Application architecture is a set of technologies and models for the
development of fully-structured mobile programs based on industry
and vendor specific standards.
Presentation Layer
The presentation layer is the interface between the user and the
application, focusing on how the app is visually and interactively
presented. In this layer, developers must consider the type of client
app they are building, ensuring it is compatible with the intended
infrastructure, including web, mobile, or desktop platforms. It is
crucial to keep deployment restrictions in mind to ensure that the app
functions well across different devices and environments.
Furthermore, the presentation layer is responsible for selecting the
correct data format for smooth interaction with the user, ensuring
consistency in data representation. Powerful data validation
techniques are applied to protect the app from receiving invalid or
16
corrupted data inputs, maintaining the integrity and reliability of the
application.
Business Layer
The business layer is responsible for processing the core functionality
of the app. This layer deals with operations like caching, logging,
authentication, exception management, and security—each of which
plays a vital role in the app's overall performance and user
experience. To manage the complexity of this layer, developers should
divide tasks into distinct categories, making it easier to implement
and maintain. For example, caching may involve managing data
storage to reduce retrieval times, while logging can be used to track
the app’s activities for debugging and audit purposes. Authentication
and exception management ensure secure access and error handling.
When handling complex business rules, app policies, data
transformations, and validation, it is essential to define a clear set of
demands for each category to ensure that all requirements are met
efficiently.
Data Access Layer
The data access layer is designed to handle all interactions with the
app’s data storage systems, ensuring secure transactions between the
app and its underlying data repositories. This layer is critical for
maintaining the security and integrity of the data, ensuring that the
right data is fetched or updated as required by the application.
Moreover, it must be flexible enough to scale as business needs evolve
over time. For example, as the business grows or the app’s
functionalities expand, this layer must adapt to handle increased data
loads or new data formats while maintaining performance and
security standards. A well-designed data access layer ensures that the
application can continue to perform reliably under varying data
demands and conditions.
17
ARCHITECTURE PATTERN FOR MOBILE APPLICATION
DEVELOPMENT
1. MVVM (Model View ViewModel)
Model-View-ViewModel (MVVM) is a software architectural pattern
that is widely adopted to overcome the limitations of older patterns
like MVC (Model-View-Controller) and MVP (Model-View-Presenter).
MVVM effectively separates the concerns of data presentation from
the core business logic of an application, enhancing maintainability,
testability, and flexibility.
Here’s an overview of the core layers in MVVM:
1. Model: The Model layer is responsible for the abstraction of data
sources. It handles the retrieval and storage of data, often
interacting with databases, APIs, or other services. The Model
doesn't contain any business logic related to the UI; instead, it
focuses on the data itself. It works closely with the ViewModel to
ensure that data is retrieved and persisted appropriately.
2. View: The View layer is the user interface (UI) of the application.
Its role is to display data to the user and capture user input.
However, it doesn't contain any business logic. Instead, it simply
18
observes the ViewModel for changes, reacting to updates, and
notifying the ViewModel of user actions (e.g., button clicks, form
submissions). It’s designed to be passive, meaning it does not
directly handle the logic behind the data it displays.
3. ViewModel: The ViewModel acts as a bridge between the Model
and the View. It holds the logic for preparing the data that the View
requires, exposing relevant data streams to the View. The
ViewModel is also responsible for reacting to user input, altering
the Model if necessary, and updating the View with the latest data.
It provides a separation of concerns by keeping the business logic
out of the View, ensuring that the UI is not tightly coupled to the
underlying data processing and handling logic.
2. MVC (Model View Controller)
The Model-View-Controller (MVC) pattern is a widely used software
architecture design that splits an application into three
interconnected components, helping to separate the internal
representations of information from the ways that information is
presented and accepted by the user.
1. Model: The Model component is responsible for managing the data
of the application. It holds the core business logic, performs
operations on the data, and is responsible for retrieving and storing
data from databases or other external data sources. The Model
does not have any knowledge of the user interface, making it
19
independent of the view. Its main job is to reflect the real-world
business rules and logic.
2. View: The View is the User Interface (UI) of the application, where
the user interacts with the app. It is responsible for displaying data
from the Model to the user and providing elements for user
interaction, such as buttons and text fields. The View’s role is to
visualize data from the Model in a way that is easy to understand
and interact with. It does not directly modify the data but can
display any changes made by the Controller.
3. Controller: The Controller acts as an intermediary between the
View and the Model. It listens to user inputs (such as button clicks
or text input) and processes these inputs by updating the Model or
making changes to the View. The Controller manages the flow of
the application, receiving input from the user, processing it (often
via the Model), and determining how the UI (View) should be
updated. It essentially handles the application's core logic.
ARCHITECTURE OF ANDROID
The Android architecture is organized in a layered structure designed
to efficiently manage the app development and execution
environment. Here's a detailed breakdown of its components:
20
1. Applications Layer
The topmost layer of Android architecture is dedicated to the
applications. This includes both pre-installed apps, such as home,
contacts, camera, and gallery, and third-party apps downloaded from
the Google Play Store, such as messaging and gaming apps. All
applications run within the Android runtime, utilizing services and
classes provided by the application framework to function effectively.
2. Application Framework Layer
The Application Framework layer provides essential components and
services for building Android applications. It abstracts hardware
access, manages the user interface, and allows developers to access
various services for application creation. Key services include the
21
Activity Manager, Notification Manager, View System, and Package
Manager, all of which help streamline the application development
process by providing predefined components and structures.
3. Platform Libraries
The Platform Libraries layer contains a set of core libraries written in
C/C++ and Java. These libraries provide the fundamental building
blocks needed for Android app development, such as:
Media Library: Enables audio and video playback and recording.
Surface Manager: Manages display subsystem access.
OpenGL: Supports 2D and 3D graphics.
SQLite: Offers database management support.
WebKit: Powers web content display and page loading.
SSL: Ensures secure communication between devices and web
servers through encryption.
4. Application Runtime Layer
The Android Runtime (ART) is a crucial part of the Android
architecture. It includes core libraries and the Dalvik Virtual Machine
(DVM), which powers Android applications. The Dalvik VM is a
register-based virtual machine optimized for mobile devices, ensuring
efficient performance, battery life, and memory usage. ART helps apps
run seamlessly by converting Java class files into optimized bytecode.
The Dalvik VM uses a specific .dex (Dalvik Executable) format for its
execution. ART, along with the core libraries, allows developers to
implement Android apps using Java or Kotlin.
22
5. Linux Kernel
The Linux Kernel is the foundation of the Android system, providing
essential services such as memory management, device drivers, and
process management. It serves as an abstraction layer between the
hardware and higher-level components of the Android architecture. Its
key functions include:
Security: Ensures secure interactions between applications and
system resources.
Memory Management: Optimizes memory allocation for efficient
app execution.
Process Management: Allocates system resources to running
processes as needed.
Network Stack: Handles network communication.
Driver Model: Manages hardware drivers to ensure proper device
function during runtime.
10 Best Android Development Tools
23
1. Android Studio: As the official IDE for Android development,
Android Studio is equipped with a rich layout editor, debugging
tools, and code completion features. It is optimized for building
Android apps with support for Kotlin, Java, and C++, and
integrates seamlessly with other tools like Firebase to enhance the
development process.
2. Firebase: Firebase is a robust suite of backend services designed
to simplify mobile app development. Offering real-time databases,
crash reporting, authentication, cloud storage, and A/B testing,
Firebase is an essential tool for streamlining backend services in
Android apps.
3. GitHub: GitHub is the leading platform for version control,
allowing developers to track changes, collaborate on projects, and
manage repositories effectively. It’s vital for maintaining a
collaborative environment and managing project versions across
teams.
4. Unity 3D: Unity 3D is an ideal tool for game developers working on
Android, supporting both 2D and 3D game development. It is
known for its high-quality graphics and cross-platform capabilities,
making it a go-to solution for interactive game development.
5. Gradle: Gradle is an automation tool that simplifies the process of
building Android apps. It helps developers manage dependencies,
generate optimized APK files, and streamline the build process,
integrating well with Android Studio.
6. Retrofit: Retrofit is an efficient HTTP client for making API calls
and network requests. It simplifies JSON parsing, supporting both
synchronous and asynchronous operations, and reduces boilerplate
code for handling HTTP responses in Android apps.
7. LeakCanary: LeakCanary is a tool designed to detect memory
leaks in Android apps, helping developers identify and fix issues
that may affect performance and stability. It’s a valuable tool for
maintaining smooth, crash-free user experiences.
24
8. Realm: Realm is a mobile database that simplifies data
management for Android apps. With its real-time synchronization
capabilities and object-oriented data model, it is well-suited for
modern mobile environments.
9. Stetho: Stetho is a debugging tool developed by Facebook that
integrates with Chrome Developer Tools. It allows developers to
inspect network requests, shared preferences, and SQLite
databases in real-time, offering a smoother debugging experience.
10. Lottie: Lottie is a tool that allows developers to add high-quality
animations to their Android apps. By using JSON files exported
from After Effects, Lottie delivers smooth and interactive
animations without compromising app performance.
LAUNCHING THE APPLICATION
Step1: After Installing Android Studio Open New Project
25
Step 2: In Phone and Tablet Template, Select Empty Activity
Step 3: Give the name for your application, and choose the minimum
SDK level
26
Step 4: After the build is completed, create your Virtual Device from
the Device Manager which is located at Right pane by just clicking the
plus Button
27
Step 5: Select the Phone with the appropriate screen size you want.
Step 6: After creating your own virtual device, Start the
virtual device and click the run button, you can see the result
in the Emulator.
28
UNIT - II: ACTIVITIES, INTENTS, AND ANDROID USER
INTERFACE
Topics Covered
Activities
Linking Activities Using Intents
Calling Built-in Applications Using Intents
Displaying Notifications
Components of a Screen
Adapting to Display Orientation
Managing Changes to Screen Orientation
Utilizing the Action Bar
Listening for UI Notifications
Introduction to Activities in Android
In Android development, an Activity is essentially a screen where
user interaction happens. Android applications can have multiple
activities, but usually, each activity serves a specific function or
displays a part of the user interface (UI). The main objective of an
activity is to handle user interaction through different UI components.
An understanding of the Activity Lifecycle is crucial in Android
development as it outlines the stages an activity goes through from
creation to destruction. These stages allow developers to manage
resources and ensure smooth transitions between activities. When the
activity is created, it undergoes a series of life cycle events that
dictate how it behaves as it interacts with the user.
Activity Lifecycle Methods
29
1. onCreate(): This method is called when the activity is first
created. It's used to initialize the activity, set up the UI, and load
any essential data.
2. onStart(): Triggered when the activity becomes visible to the
user but is not yet interactive.
3. onResume(): Called when the activity is in the foreground and
is ready to interact with the user.
4. onPause(): This method is invoked when the activity is being
partially obscured (e.g., by another activity) and gives
developers a chance to pause tasks.
5. onStop(): Triggered when the activity is no longer visible. At
this point, it's essential to release any resources that are not
needed.
6. onDestroy(): This method is called when the activity is about to
be destroyed, providing a chance to clean up any resources
before the activity is completely removed.
7. onRestart(): This is called when an activity that was previously
stopped is about to become active again.
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding:ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
binding=ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
super.onCreate(savedInstanceState)
}
}
30
Note: When the Configuration Changes, the Activity will get
Destroyed(i.e.onDestroy()) is called and Killed and Again the Activity
Start form the Beginning (i.e. onCreate())
INTENTS IN ANDROID
In Android, an Intent acts as a mechanism for facilitating
communication between different components of an app, such as
activities, services, or broadcast receivers. Intents enable the transfer
of data, allowing activities from different applications to work
together seamlessly. They function as a "glue" between various app
components and are used to start activities, services, or broadcast
messages.
31
Linking Activities Using Intents
When an Android application contains multiple activities, navigation
between them is achieved using Intents. Here’s how different types
of intents can be used to facilitate communication between activities:
1. Starting a New Activity/ Explicit Intent
To start a new activity from an existing one, an Explicit Intent is
used.
val intent = Intent(this, TargetActivity::class.java)
startActivity(intent)
2. Passing Data Between Activities
We can pass data by using putExtra() with the intent.
val intent = Intent(this, TargetActivity::class.java)
intent.putExtra("key_name", "value")
startActivity(intent)
In the TargetActivity, retrieve the data like
val value = intent.getStringExtra("key_name")
3. Receiving Data Back
First, we need to register for an activity result launcher in your
Activity
MainActivity.kt
class MainActivity : AppCompatActivity() {
// Register the ActivityResultLauncher
private val startForResult =
registerForActivityResult(ActivityResultContracts.StartActivityForR
esult()) { result: ActivityResult ->
if (result.resultCode == Activity.RESULT_OK) {
// Retrieve data from the intent
val data = result.data
val returnedData = data?.getStringExtra("result_key")
// Handle the result (for example, display the returned data)
32
println("Result received: $returnedData")
}
}
// Start TargetActivity when a button is clicked or any other event
val intent = Intent(this, TargetActivity::class.java)
startForResult.launch(intent)
}
}
TargetActivity.kt
class TargetActivity : AppCompatActivity() {
// Create the result intent with data
val resultIntent = Intent()
resultIntent.putExtra("result_key", "This is the result from
TargetActivity")
// Set the result and finish the activity
setResult(Activity.RESULT_OK, resultIntent)
finish() // Close the activity and return to the calling activity
}
}
Key points:
ActivityResultContracts.StartActivityForResult(): Replaces
the deprecated startActivityForResult().
Lambda-based result handling: The result is processed
directly in the callback, improving readability and reducing
boilerplate code.
This method aligns with modern Android practices and is
recommended for handling activity results as it avoids using
onActivityResult() and simplifies activity result management.
4. Using Implicit Intents
Implicit Intents allow us to request an action without specifying which
component will handle it.
For example, opening a webpage
33
val intent = Intent(Intent.ACTION_VIEW,
Uri.parse("http://www.example.com"))
startActivity(intent)
5.Sending a Broadcast Intent
To send a broadcast in Kotlin, you create an Intent with a specific
action, then send it using sendBroadcast().
val intent = Intent("com.example.broadcast.MY_NOTIFICATION")
intent.putExtra("data_key", "data_value")
sendBroadcast(intent)
Receiving a Broadcast Intent
To receive a broadcast, we need to create a BroadcastReceiver. This
receiver listens for specific broadcast intents, reacts to them, and
processes any data that is attached to the broadcast.
class MyBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val data = intent.getStringExtra("data_key")
// Handle the broadcast (e.g., log the data or update the UI)
Log.d("BroadcastReceiver", "Received data: $data")
}
}
Registering the Receiver:
There are two ways to register a BroadcastReceiver:
1. In the Manifest (for global broadcasts or when using static
broadcasts):
Add the receiver to your AndroidManifest.xml file
Manifest.xml
34
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action
android:name="com.example.broadcast.MY_NOTIFICATION"/
>
</intent-filter>
</receiver>
2. Dynamically at Runtime (for local broadcasts):
In the activity or service, register the receiver dynamically:
val intentFilter =
IntentFilter("com.example.broadcast.MY_NOTIFICATION")
val receiver = MyBroadcastReceiver()
registerReceiver(receiver, intentFilter)
Note: We should unregister the receiver when no longer needed, for
example, in the onDestroy() method.
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(receiver)
}
Calling Built-In Applications Using Intents in Android
One of the key features of Android programming is the ability to
interact with built-in applications using intents. This allows your
application to leverage existing functionalities, such as maps, phone
calls, contact management, and web browsing, without the need to
implement these features from scratch. For example, if your
application requires displaying a web page, you can use an Intent to
invoke the built-in web browser instead of creating your own.
35
Components of an Intent
1. Action: Specifies the task to be performed, such as viewing or
editing an item.
2. Data: Defines the target of the action, often represented as a
Uniform Resource Identifier (URI).
The combination of an action and data describes the operation to be
executed.
Common Actions and Data Examples
Below are some examples of commonly used actions and their
corresponding data:
Action Data Example Purpose
ACTION_VIE geo:37.827500,-
Open a location on a map.
W 122.481670
ACTION_DIA Open the phone dialer with a
tel: +91 6598521456
L phone number.
ACTION_PIC Pick a contact from the contact
content://contacts
K list.
ACTION_VIE
www.google.com Display a webpage in a browser.
W
Examples of Using Intents in Android
Below are examples of how to use intents to call built-in applications
1. Dialing a Phone Number
To open the phone dialer with a pre-filled phone number
val dialIntent = Intent(Intent.ACTION_DIAL).apply {
data = Uri.parse("tel:+1234567890")
36
}
startActivity(dialIntent)
2. Opening a Web Page
To launch the web browser and open a specified webpage
val webIntent = Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse("https://mbu.com")
}
startActivity(webIntent)
3. Displaying a List of Contacts
To display the contacts stored on the device
val contactsIntent = Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse("content://contacts/people")
}
startActivity(contactsIntent)
4. Selecting a Contact
To allow the user to pick a contact from their contact list
val pickContactIntent = Intent(Intent.ACTION_PICK).apply {
data = Uri.parse("content://contacts")
}
pickContactLauncher.launch(pickContactIntent)
Note: For using this method, we have to Register the Activity Result
Launcher
5. Opening a Location in Maps
To open a specific location in a map application using coordinates
37
val locationIntent = Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse("geo:37.7749,-122.4194")
}
startActivity(locationIntent)
Displaying Notifications in Android
Notifications are a key feature in Android that allow applications to
send persistent messages to the user. Unlike Toast messages, which
are temporary and disappear after a few seconds, notifications remain
in the status bar (also called the notification bar) until the user
interacts with them or clears them. Notifications are typically used to
provide important or time-sensitive information.
For displaying the notification there are four important concepts that
we have to know.
1. NOTIFICATION CHANNEL
2. NOTIFICATION BUILDER
3. NOTIFICATION MANAGER
4. PENDING INTENT
Steps to Display a Notification
1. Creating an Intent
An Intent is used to specify the target activity that will launch when
the user clicks on the notification. For example, this could navigate
the user to a specific screen in your application.
val intent = Intent(this, NotificationViewActivity::class.java)
2. Creating a PendingIntent
38
Since notifications might need to interact with the app even if it's not
running, you need a PendingIntent. A PendingIntent acts as a wrapper
for the Intent and allows it to be executed at a later time on behalf of
your application. Use the getActivity() method to create a
PendingIntent for launching an activity
val pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_IMMUTABLE)
3. Building the Notification
To create the notification, use the NotificationCompat.Builder
class, which provides an easy way to construct notifications.
val notification = NotificationCompat.Builder(this,
NOTIFICATION_CHANNEL_ID)
.setContentTitle("MBU Id Registered Successfully")
.setContentText("Click here to explore")
.setSmallIcon(R.drawable.notification_foreground)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build()
4. Displaying Notification with Notification Manager
Obtain an instance of the NotificationManager class and use the
notify() method to display the notification.
val notificationManager = NotificationManagerCompat.from(this)
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
notificationManager.notify(NOTIFICATION_ID, notification)
}
val manager =
getSystemService(Context.NOTIFICATION_SERVICE) as
39
NotificationManager
manager.createNotificationChannel(channel)
5. Configuring Vibration or Sound
We can add vibration or sound to the notification using the
setVibrate() and setSound() methods
val vibrationPattern = longArrayOf(0, 500, 1000)
notification.vibrate = vibrationPattern
Key Points
1. PendingIntent: Allows the notification to perform an action
later, even if the app is not active.
2. NotificationCompat.Builder: Simplifies the creation of
notifications.
3. Notification Channels: Mandatory for devices running Android
8.0 (API level 26) and above.
4. Vibration and Sound: You can enhance notifications by adding
vibration patterns or custom sounds.
Understanding the Components of a Screen in Android
The fundamental unit of an Android application is an Activity. It
serves as the entry point for interacting with the user and typically
displays the user interface (UI). The UI consists of various
40
components like widgets (buttons, text boxes, labels, etc.) organized
within layouts.
Views and ViewGroups
An Activity manages UI components through Views and
ViewGroups:
View: Represents an individual UI element that has a visible
appearance on the screen. Examples include buttons, text views,
and image views.
ViewGroup: Acts as a container for multiple views and
organizes them into a specific layout. Examples of ViewGroups
are LinearLayout and RelativeLayout.
Common ViewGroups in Android
1. LinearLayout
Organizes child views in either horizontally or vertically.
Controlled using the orientation attribute.
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
2. RelativeLayout
Positions child views relative to one another or the parent
container.
Examples: Positioning view A to the right of view B.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
</RelativeLayout>
41
3. ConstraintLayout
Similar to RelativeLayout but more powerful with constraints.
Allows complex layouts without nesting.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout>
4. FrameLayout
Stacks child views on top of each other, displaying only one
view at a time.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
</FrameLayout>
5. TableLayout
Organizes child views into rows and columns.
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- Rows and Cells -->
</TableLayout>
Common Attributes for Views and ViewGroups
Attribute Description
layout_width Defines the width of a View or ViewGroup.
layout_height Defines the height of a View or ViewGroup.
layout_marginTop Adds extra space above the View or ViewGroup.
layout_marginBott
Adds extra space below the View or ViewGroup.
om
42
Attribute Description
Adds extra space to the left of the View or
layout_marginLeft
ViewGroup.
layout_marginRigh Adds extra space to the right of the View or
t ViewGroup.
Specifies how child views are aligned within the
layout_gravity
parent ViewGroup.
Determines the proportion of extra space a View
layout_weight
takes in a layout.
Specifies the X-coordinate of the View or
layout_x
ViewGroup.
Specifies the Y-coordinate of the View or
layout_y
ViewGroup.
Screen Densities in Android
Android devices vary in screen size and resolution, which impacts
pixel density (measured in dots per inch or DPI). The platform
classifies screen densities into four categories.
Density Description DPI
120
Low density Small screens
dpi
Medium 160
Standard screens
density dpi
240
High density Larger screens
dpi
Extra high High-resolution 320
43
Density Description DPI
density screens dpi
Using density-independent pixels (dp) ensures consistent UI
dimensions across different screen densities.
Units of Measurement in Android
1. dp (Density-independent Pixel)
A virtual pixel unit recommended for defining UI dimensions.
Scales automatically across different screen densities.
2. sp (Scale-independent Pixel)
Similar to dp but scales based on the user's preferred text size.
Recommended for defining font sizes.
3. pt (Point)
Based on physical screen size, where 1 pt equals 1/72 inch.
4. px (Pixel)
Corresponds to actual screen pixels.
Avoid using as it may result in inconsistent layouts on different
devices.
Adapting to Display Orientation in Android
Modern smartphones provide users with the flexibility to switch
screen orientation between portrait and landscape modes. Android
natively supports this functionality, and developers need to ensure
their applications adapt seamlessly to these changes for an optimal
user experience.
44
Default Behaviour of Orientation Changes
By default, when the device orientation changes:
The activity is destroyed and recreated.
The system redraws the layout to fit the new screen dimensions.
While this ensures that the UI adjusts to the new orientation, it
may lead to performance overhead and loss of temporary data if
not handled properly.
Techniques for Handling Orientation Changes
1. Anchoring Views to Screen Edges
This is the simplest way to handle orientation changes.
Views are aligned to the four edges of the screen using
layout attributes such as
android:layout_alignParentLeft,android:layout_alignPare
ntRight, android:layout_alignParentTop,
android:layout_alignParentBottom.
Advantages
Minimal effort is required for implementation.
The layout adapts naturally to the new orientation.
Use Cases
Static layouts where the placement of elements does not
require complex adjustments.
2. Resizing and Repositioning Views
Resizing and repositioning is a more advanced technique that
adjusts the size and position of every view dynamically based on
the orientation.
Steps to Implement
45
Create separate layout files for portrait and landscape
orientations.
Use the res/layout folder for portrait layouts and res/layout-
land folder for landscape layouts.
Each layout file can define the size, position, and alignment
of views differently based on the orientation.
Advantages
Provides maximum control over the layout.
Allows the use of additional screen space in landscape
mode.
Use Cases
Applications where layout changes significantly in
landscape mode, such as media players, gaming apps, or
apps requiring multi-column designs.
Handling Orientation Without Activity Recreation
By default, the system destroys and recreates the activity during an
orientation change. To avoid this, developers can:
1. Use the android:configChanges attribute in the
AndroidManifest.xml
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize" />
46
This prevents the activity from being recreated. Instead, the
onConfigurationChanged() method is called, where you can manually
handle the changes.
2. Override onConfigurationChanged()
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
if (newConfig.orientation ==
Configuration.ORIENTATION_LANDSCAPE) {
// Handle landscape-specific changes
} else if (newConfig.orientation ==
Configuration.ORIENTATION_PORTRAIT) {
// Handle portrait-specific changes
}
}
Utilizing the Action Bar in Android
The Action Bar serves as a key component in Android apps, providing
a consistent user interface for performing various operations. It
enhances user experience by integrating branding, navigation, and
frequently used actions in a central location.
Key Features of the Action Bar
1. Navigation: The Action Bar can include navigation options such as
tabs or drop-down menus, allowing users to move between
different sections of the app easily.
2. Branding: The Action Bar provides a space where you can place
the app's logo or title, helping reinforce the app's brand identity
and making it easily recognizable to users.
47
3. User Actions: It provides quick access to essential user actions
such as search or settings, allowing users to perform these tasks
quickly without navigating through the app.
4. Overflow Menu: When there are more actions than can fit on the
Action Bar, they are placed in an overflow menu, accessible by
tapping the three-dot icon (⋮), which helps keep the interface
organized and free from clutter.
Customizing the Action Bar
The Action Bar can be customized programmatically to suit the app's
requirements.
// Get a reference to the Action Bar
val actionBar = supportActionBar
if (actionBar != null) {
// Set a custom title
actionBar.title = "My Custom Title"
// Enable the 'Up' button for navigation
actionBar.setDisplayHomeAsUpEnabled(true)
// Optionally, set a custom logo
actionBar.setLogo(R.drawable.ic_logo)
actionBar.setDisplayUseLogoEnabled(true)
}
Key Points
title: Sets a custom title for the Action Bar.
setDisplayHomeAsUpEnabled(true): Adds a back button for
easier navigation.
setLogo(): Sets a logo to be displayed alongside the title.
setDisplayUseLogoEnabled(true): Ensures the logo is shown.
Listening for UI Notifications
48
In Android, we can listen for various UI notifications to respond to
user interactions. These notifications are typically triggered by user
actions such as clicks, touches, or changes in UI elements. Below are
some examples demonstrating how to handle these UI notifications.
Example 1: Handling a Button Click
To handle a button click, an OnClickListener is used to detect the
event when a user taps the button.
val myButton = findViewById<Button>(R.id.myButton)
myButton.setOnClickListener {
Toast.makeText(
applicationContext,
"Button clicked!",
Toast.LENGTH_SHORT
).show()
}
Example 2: Listening for Text Input Changes
Android also allows us to listen for changes in text input. The
TextWatcher interface provides methods to track text changes in an
EditText field.
val editText = findViewById<EditText>(R.id.editText)
editText.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence, start: Int, before:
Int, count: Int) {
}
override fun beforeTextChanged(s: CharSequence, start: Int,
count: Int, after: Int) {
}
override fun afterTextChanged(s: Editable) {
}
})
49
UNIT III: ADVANCED USER INTERFACE AND DATA
PERSISTENCE
Introduction
This unit focuses on creating enriched user interfaces and managing
data storage effectively in Android applications. It emphasizes the use
of Basic Views (e.g., TextView, EditText, Button) and interactive
elements like Picker Views (DatePicker, TimePicker) and ListView
for displaying dynamic data. It also introduces ImageView for media
content and WebView for integrating web content within the app. On
the data persistence side, it covers saving user settings with
SharedPreferences, persisting data to files, and managing databases
for long-term data storage. The aim is to ensure intuitive user
interfaces and reliable data handling techniques for seamless app
functionality.
Basic Views in Android
Basic Views are fundamental components for building Android user
interfaces. They enable interaction and display content effectively.
Below are some essential views with examples:
TextView in Android
50
TextView is used to display static text. It is often paired with other
views like EditText or CheckBox for labelling purposes in forms or
layouts.
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, World!"
android:textSize="18sp"/>
EditText in Android
EditText is an editable version of TextView. It is ideal for user input
fields and supports both single-line and multi-line text input.
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter your name"/>
RadioButton and CheckBox in Android
RadioButton: Used for single selection from multiple options.
CheckBox: Allows multiple selections among a set of options.
<CheckBox
android:id="@+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Agree to terms"/>
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RadioButton
android:id="@+id/radioButton1"
android:layout_width="wrap_content"
51
android:layout_height="wrap_content"
android:text="Option 1"/>
<RadioButton
android:id="@+id/radioButton2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Option 2"/>
</RadioGroup>
Button in Android
Button triggers an action when clicked. It shares properties with
TextView but includes unique attributes for user interaction.
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click Me"/>
ImageView in Android
ImageView displays images in the user interface. To use an image, add
it to the drawable folder.
<ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:src="@drawable/img_nature"/>
Common Attributes
android:src: Specifies the image resource.
android:scaleType: Determines how the image fits into the view.
android:background: Adds a background color or drawable.
android:padding: Adds space around the image.
52
ScaleType Options
CENTER: Centers the image without scaling.
CENTER_CROP: Scales the image uniformly to fill the view.
CENTER_INSIDE: Scales the image to fit inside the container.
FIT_XY: Stretches the image to fill the entire view (may distort).
MATRIX: Applies custom transformations.
ImageButton in Android
ImageButton is similar to ImageView but acts as a clickable button.
<ImageButton
android:id="@+id/imgButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:src="@drawable/img_nature"/>
Connecting the Views with the Business Logic
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView = findViewById<TextView>(R.id.textView)
val editText = findViewById<EditText>(R.id.editText)
val imageView = findViewById<ImageView>(R.id.imageView)
val imageButton =
findViewById<ImageButton>(R.id.imageButton)
val checkBox = findViewById<CheckBox>(R.id.checkBox)
val radioButtonM =
findViewById<RadioButton>(R.id.radioButtonMale)
val radioButtonF =
53
findViewById<RadioButton>(R.id.radioButtonFemale)
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
val name = editText.text.toString()
val gender = when {
radioButtonMale.isChecked -> "Male"
radioButtonFemale.isChecked -> "Female"
else -> "Unknown"
}
val subscribed = if (checkBox.isChecked) "Subscribed" else
"Not Subscribed"
textView.text = "Name: $name\nGender: $gender\
nSubscription: $subscribed"
}
imageButton.setOnClickListener {
imageView.setImageResource(R.drawable.another_image)
}
}
}
ListView in Android
A ListView is a versatile UI component in Android that allows you to
display items in a vertically scrollable list. It is commonly used for
dynamic datasets like contact lists, emails, or search results, where
users can easily browse and interact with the data by scrolling up or
down.
Key Features of ListView:
1. Dynamic Data Display: Suitable for presenting large datasets.
2. Customizable Items: Supports the use of TextView,
ImageView, or a combination of views in each list item.
3. Adapts Data Automatically: Uses adapter classes like
ArrayAdapter or CustomAdapter to bind data dynamically to the
view.
4. Dividers for Aesthetic Design: Separates list items using
dividers, with customizable height and colour.
54
Common Attributes of ListView
Attribute Description
Specifies a divider between items. A drawable or
android:divider
colour can be used.
android:dividerHei
Sets the height of the divider between items.
ght
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@android:color/black"
android:dividerHeight="1dp"/>
What is an Adapter?
An Adapter acts as a bridge between a data source and the UI
components. It converts the data into individual View objects and
passes them to the corresponding Adapter View to display.
Key Features of an Adapter:
Reads data from data sources such as arrays, lists, or databases.
Converts raw data into UI elements like TextView, ImageView,
etc.
Supplies the views to the Adapter View dynamically.
Common Adapter Types in Android
1. ArrayAdapter
Used to display a list of strings or simple objects.
Example: Displaying a list of names or items.
2. SimpleAdapter
55
Ideal for mapping data from a list of maps to views.
Example: Populating a list with complex data like images
and text.
3. BaseAdapter
A flexible and customizable adapter that can be extended
to create custom adapters for unique use cases.
val items = listOf("Apple", "Banana", "Cherry")
val adapter = ArrayAdapter(this,
android.R.layout.simple_list_item_1, items)
listView.adapter = adapter
What is an Adapter View?
An Adapter View is a UI component in Android that relies on an
Adapter to provide the data it displays. It does not directly manage
data but instead uses the Adapter to supply it. Examples of Adapter
Views include ListView, GridView, and Spinner.
Key Features of an Adapter View:
Displays large datasets efficiently by reusing views for visible
items (view recycling).
Dynamically loads and unloads data as the user scrolls.
Works seamlessly with Adapters to present data in different
layouts
How Adapter and Adapter View Work Together
1. The Adapter fetches data from the source and converts it into
views.
2. The Adapter View requests these views from the Adapter to
display them.
56
3. For large datasets, only the views for visible items are created,
and the rest are loaded as needed.
Example of Adapter View with ListView:
import android.os.Bundle
import android.widget.ArrayAdapter
import android.widget.ListView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val listView: ListView = findViewById(R.id.listView)
val items = listOf("Item 1", "Item 2", "Item 3", "Item 4")
val adapter = ArrayAdapter(this,
android.R.layout.simple_list_item_1, items)
listView.adapter = adapter
}
}
By using Adapters and Adapter Views, Android ensures that
applications can handle and display large datasets efficiently without
compromising performance.
RecyclerView in Android
RecyclerView is a flexible and efficient component for creating
dynamic lists or grids in Android applications. It is particularly well-
suited for handling large datasets and supports heterogeneous
layouts, making it a popular choice for applications such as news
feeds or navigation drawers.
Features of RecyclerView
57
Supports Heterogeneous Layouts: Different types of views
(e.g., text, images, videos) can coexist within a single
RecyclerView.
Efficient View Recycling: Views that scroll off-screen are
reused, reducing memory usage and improving performance.
Customizable Animations: Allows for smooth animations
during item addition, removal, or updates.
Steps to Implement RecyclerView
1. Plan Your Layout
Decide on the structure (e.g., list or grid).
Use a suitable LayoutManager:
LinearLayoutManager for vertical or horizontal lists.
GridLayoutManager for grids.
StaggeredGridLayoutManager for staggered grids.
Design the layout for each list item in an XML file.
2. Create Adapter and ViewHolder
Adapter: Manages data and binds it to the ViewHolder. Extend
RecyclerView.Adapter.
ViewHolder: Caches references to views within a layout for
efficient reuse. Extend RecyclerView.ViewHolder.
Override key methods:
onCreateViewHolder(): Inflates the layout for each item.
onBindViewHolder(): Binds data to views.
58
getItemCount(): Returns the size of the dataset.
3. Set Up RecyclerView in the Activity
Initialize the RecyclerView, set its LayoutManager, and attach
the custom Adapter.
class CustomAdapter(private val dataset: List<String>) :
RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
class ViewHolder(itemView: View) :
RecyclerView.ViewHolder(itemView) {
val textView: TextView =
itemView.findViewById(R.id.item_text)
}
override fun onCreateViewHolder(parent: ViewGroup,
viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_view, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position:
Int) {
holder.textView.text = dataset[position]
}
override fun getItemCount(): Int = dataset.size
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val dataset = listOf("January", "February", "March")
val customAdapter = CustomAdapter(dataset)
val recyclerView: RecyclerView =
findViewById(R.id.recycler_view)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = customAdapter
59
}
}
Customizing RecyclerView
1. Animations: Add animations for item addition, removal, or
updates.
2. Dividers: Add dividers between items using
DividerItemDecoration.
3. Heterogeneous Layouts: Implement getItemViewType() in your
Adapter to handle different view types.
Picker Views in Android
Picker views are pre-built dialogs in Android that allow users to select
a date or time. These pickers ensure users input valid, locale-specific,
and correctly formatted date or time values.
Types of Picker Views
1. DatePicker
Allows users to select a date (year, month, day).
Can be used as a standalone widget in a layout or as part
of a DatePickerDialog.
<DatePicker
android:id="@+id/datePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:datePickerMode="spinner" />
2. TimePicker
60
Allows users to select time (hours and minutes).
Like DatePicker, it can also be used as a widget or within a
TimePickerDialog.
<TimePicker
android:id="@+id/timePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:timePickerMode="spinner"
android:is24HourView="true" />
Combining DatePickerDialog and TimePickerDialog
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val selectDateTimeButton: Button =
findViewById(R.id.select_datetime_btn)
val dateTimeText: TextView =
findViewById(R.id.datetime_text)
selectDateTimeButton.setOnClickListener {
val calendar = Calendar.getInstance()
val year = calendar.get(Calendar.YEAR)
val month = calendar.get(Calendar.MONTH)
val day = calendar.get(Calendar.DAY_OF_MONTH)
val hour = calendar.get(Calendar.HOUR_OF_DAY)
val minute = calendar.get(Calendar.MINUTE)
// Show DatePickerDialog first
val datePickerDialog = DatePickerDialog(this, { _,
selectedYear, selectedMonth, selectedDay ->
61
// Once date is selected, show TimePickerDialog
val timePickerDialog = TimePickerDialog(this, { _,
selectedHour, selectedMinute ->
val selectedDateTime = "$selectedDay/$
{selectedMonth + 1}/$selectedYear $selectedHour:
$selectedMinute"
dateTimeText.text = selectedDateTime
}, hour, minute, true)
timePickerDialog.show()
}, year, month, day)
datePickerDialog.show()
}
}
}
Android WebView
Android WebView is a component that allows you to display web pages
inside an Android application. It provides developers with greater
control over the UI and configuration when integrating web content.
Step 1: Add Internet Permission
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.webview">
<!-- Internet permission -->
<uses-permission
android:name="android.permission.INTERNET"/>
Step 2: Add WebView to the Layout File
Add a WebView element to the layout file activity_main.xml to load
and display web pages.
<WebView
android:id="@+id/myWebView"
62
android:layout_width="match_parent"
android:layout_height="match_parent" />
Step 4: Configure the WebView in MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var myWebView: WebView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Initialize WebView
myWebView = findViewById(R.id.myWebView)
// Load the desired URL
myWebView.loadUrl("https://www.mbu.com/")
}
}
ANDROID DIFFERENT TYPES OF MENUS
In android, we have a three fundamental type of Menus available to
define a set of options and actions in our android applications.
The following are the commonly used Menus in android applications.
Options Menu
Context Menu
Popup Menu
For all menu types, Android provides a standard XML format to define
menu items. Instead of building a menu in our activity's code, we
should define a menu and all its items in an XML menu resource and
load menu resource as a Menu object in our activity or fragment.
In android, to define menu, we need to create a new
folder menu inside of our project resource directory (res/menu/) and
add a new XML file to build the menu with the following elements.
63
Eleme
nt Description
<menu It’s a root element to define a Menu in XML file and it
> will hold one or more and elements.
<item It is used to create a menu item and it represents a
> single item on the menu. This element may contain a
nested <menu> element in order to create a submenu.
<grou It’s an optional and invisible for <item> elements. It is
p> used to categorize the menu items so they share
properties such as active state and visibility.
Once we are done with creation of menu, we need to load the menu
resource from our activity using MenuInflater.inflate() like as shown
below.
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_options, menu)
return true
}
Android Options Menu
In android, Options Menu is a primary collection of menu items for
an activity and it is useful to implement actions that have a global
impact on the app, such as Settings, Search, etc.
64
Android Context Menu
In android, Context Menu is a floating menu that appears when the
user performs a long click on an element and it is useful to implement
actions that affect the selected content or context frame.
Android Popup Menu
In android, Popup Menu displays a list of items in a vertical list that’s
anchored to the view that invoked the menu and it’s useful for
providing an overflow of actions that related to specific content.
SHARED PREFERENCES
Shared Preferences is a built-in Android data storage mechanism
designed to save and retrieve small amounts of private data in the
form of key-value pairs. Shared Preferences is commonly used for
scenarios like saving user preferences, application settings, or any
other lightweight data that needs to persist between application
launches.
Key Features of Shared Preferences
1. Stores data in an XML file located at:
data/data/<package-name>/shared-prefs/<filename>.xml
2. Only primitive data types can be saved:
boolean, float, int, long, string, and stringSet.
Accessing SharedPreferences Object
1. getSharedPreferences(String name, int mode)
Used for multiple preferences files.
val sharedPreferences = getSharedPreferences("myPreferences",
Context.MODE_PRIVATE)
Saving Data
65
val sharedPreferences = getSharedPreferences("myPreferences",
Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
editor.putString("username", "JohnDoe")
editor.putInt("age", 25)
editor.putBoolean("isLoggedIn", true)
editor.apply() // or editor.commit()
Retrieving Data
val sharedPreferences = getSharedPreferences("myPreferences",
Context.MODE_PRIVATE)
val username = sharedPreferences.getString("username",
"DefaultUser")
val age = sharedPreferences.getInt("age", 0)
val isLoggedIn = sharedPreferences.getBoolean("isLoggedIn",
false)
println("Username: $username, Age: $age, Is Logged In:
$isLoggedIn")
Removing or Clearing Data
val sharedPreferences = getSharedPreferences("myPreferences",
Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
editor.remove("username").apply() //Removing Specific Key
// Clear all data
editor.clear().apply()
Android Persistence with Preferences and Files
Persistence in Android refers to saving data locally on the device to
ensure it is retained even when the app is closed or the device is
66
restarted. Android provides multiple mechanisms for data persistence,
depending on the nature and scope of the data.
File-Based Persistence in Android
Android creates a private storage directory for each application at the
following location: /data/data/[application_package]/.
This directory contains three main subdirectories
1. Files: Stores general application data.
2. Cache: Stores temporary data (cleared when space is needed).
3. Shared Preferences: Stores key-value pairs for app
preferences.
Options for Storing Data in Files
Files: You can create, read, and update files directly.
Preferences: Use Shared Preferences to store and retrieve
lightweight, key-value-based data.
SQLite Database: Use SQLite databases for structured and
relational data storage.
Internal vs. External Storage
Internal Storage
Private to the application.
Data is saved in the application's directory
(/data/data/[application_package]/files).
67
Only accessible by the application (unless explicitly shared via a
FileProvider).
Ideal for storing sensitive data.
Automatically cleared when the application is uninstalled.
val fileName = "example.txt"
val fileContent = "This is an internal file."
// Writing to internal storage
openFileOutput(fileName, Context.MODE_PRIVATE).use {
it.write(fileContent.toByteArray())
}
// Reading from internal storage
val fileContentRead =
openFileInput(fileName).bufferedReader().useLines { lines ->
lines.joinToString("\n")
}
println("Read from file: $fileContentRead")
External Storage
Publicly accessible.
Not always available (e.g., when mounted via USB or missing an
SD card).
Requires runtime permission for reading and writing from
Android 6.0 (API level 23) onward.
if (Environment.getExternalStorageState() ==
Environment.MEDIA_MOUNTED) {
val externalDir = getExternalFilesDir(null) // App-specific
external directory
val file = File(externalDir, "example.txt")
// Writing to external storage
file.writeText("This is an external file.")
// Reading from external storage
val content = file.readText()
68
println("Read from file: $content")
}
Creating and Using Databases Using SQLite in Android
SQLite is a lightweight, embedded SQL database engine designed for
local data storage in mobile and desktop applications. It is self-
contained, serverless, and requires zero configuration, making it ideal
for Android applications. SQLite reads and writes directly to disk files,
and all database objects (tables, indexes, etc.) are stored in a single
file.
Key Components of SQLite in Android
1. SQLiteOpenHelper
A helper class to manage database creation, connection,
and version management.
It abstracts away the complexity of handling raw SQL
commands to create or update databases.
Implements the onCreate() method to define the schema
and the onUpgrade() method to handle database version
changes.
2. SQLiteDatabase
Represents the database instance.
Provides methods like insert(), update(), delete(), and
query() for performing database operations.
Accessed via SQLiteOpenHelper using:
getWritableDatabase(): For write operations.
getReadableDatabase(): For read-only operations.
3. Cursor
69
A class that provides access to the results of database
queries.
Acts as an iterator to navigate through query results row
by row.
Optimized for handling large datasets by loading data in
batches.
Steps to Use SQLite in Android
1. Define a Database Schema
Identify the tables, columns, and relationships required for
your application.
CREATE TABLE Users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
);
2. Create a Database Helper Class
Extend SQLiteOpenHelper and override onCreate() and
onUpgrade().
class MyDatabaseHelper(context: Context) :
SQLiteOpenHelper(context, "MyDatabase.db", null, 1) {
override fun onCreate(db: SQLiteDatabase) {
// Create tables
db.execSQL(
"CREATE TABLE Users (id INTEGER PRIMARY KEY
AUTOINCREMENT, name TEXT NOT NULL, email TEXT UNIQUE
NOT NULL)"
)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int,
newVersion: Int) {
// Handle database upgrades
70
db.execSQL("DROP TABLE IF EXISTS Users")
onCreate(db)
}
}
3. Open the Database
Use getWritableDatabase() or getReadableDatabase() to interact
with the database.
val dbHelper = MyDatabaseHelper(context)
val db = dbHelper.writableDatabase
4. Perform Database Operations
Insert Data
val values = ContentValues()
values.put("name", "Rithickshan")
values.put("email", "
[email protected]")
val newRowId = db.insert("Users", null, values)
Read-Query Data
val cursor = db.query(
"Users",
arrayOf("id", "name", "email"), // Columns to return
null, // Selection criteria
null, // Selection arguments
null, // Group by
null, // Having
null // Order by
)
while (cursor.moveToNext()) {
val userId = cursor.getInt(cursor.getColumnIndexOrThrow("id"))
val userName =
71
cursor.getString(cursor.getColumnIndexOrThrow("name"))
val userEmail =
cursor.getString(cursor.getColumnIndexOrThrow("email"))
println("ID: $userId, Name: $userName, Email: $userEmail")
}
cursor.close()
Update Data
val updatedValues = ContentValues()
updatedValues.put("name", "Rithick")
val rowsUpdated = db.update(
"Users",
updatedValues,
"email = ?",
arrayOf("
[email protected]")
)
Delete Data
val rowsDeleted = db.delete("Users", "email = ?",
arrayOf("
[email protected]"))
5. Close the Database
Always close the database to free up resources.
db.close()
Advantages of SQLite
Lightweight and serverless.
Fast and efficient for small to medium-sized datasets.
Full-featured SQL implementation.
72
UNIT - IV: MESSAGING, LOCATION-BASED SERVICES,
AND NETWORKING
SMS messaging, Sending e-mail, Displaying maps, Getting location
data, Monitoring a location, Consuming web services using HTTP.
INTRODUCTION
In this unit, students will explore essential mobile app functionalities
that enhance user interaction and data exchange. The topics include
SMS messaging for seamless text communication and email
integration for handling user correspondence. Additionally, the unit
covers displaying maps, which is crucial for location-based services,
and obtaining real-time location data to personalize user experiences.
Students will also learn how to monitor a location for tracking
purposes and consume web services via HTTP to enable efficient data
transfer between client and server. These skills form the foundation
for building versatile, data-driven mobile applications.
73
SMS MESSAGING
SMS messaging is one of the main killer applications on a mobile
phone today — for some users as necessary as the phone itself. Any
mobile phone you buy today should have at least SMS messaging
capabilities, and nearly all users of any age know how to send and
receive such messages.
1. Setting up Permissions
For any SMS functionality, your app needs to request the appropriate
permissions. In Android 13, you must request SEND_SMS,
RECEIVE_SMS, and optionally READ_SMS permissions.
Add the following permissions to AndroidManifest.xml:
<uses-permission android:name="android.permission.SEND_SMS"
/>
<uses-permission
android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS"
/>
Since Android 6.0 (API level 23), apps must also request these
permissions at runtime. Here's an example of how to handle runtime
permission requests for SMS in Kotlin:
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.SEND_SMS) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.SEND_SMS),
REQUEST_SMS_PERMISSION)
}
2. Sending SMS using SmsManager
74
We can send SMS messages using the SmsManager class. It provides
simple methods to send text messages.
val phoneNumber = "1234567890"
val message = "Hello, this is a test message!"
val smsManager = SmsManager.getDefault()
smsManager.sendTextMessage(phoneNumber, null, message, null,
null)
In this example:
phoneNumber: The recipient’s phone number.
message: The text you want to send.
The other parameters (null values) are for service center
address, delivery intent, and sent intent, which are optional.
3. Receiving SMS Messages
To receive an SMS, we need to create a BroadcastReceiver that listens
for SMS broadcasts from the system. Android automatically sends a
broadcast when a new SMS is received.
Step-by-Step Guide:
Create a BroadcastReceiver: This class will capture the
broadcast that the system sends when an SMS is received.
Declare the receiver in the manifest: The receiver must be
declared in the manifest with the action
android.provider.Telephony.SMS_RECEIVED.
Example: SMS Receiver
SmsReceiver.kt
class SmsReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent != null &&
Telephony.Sms.Intents.SMS_RECEIVED_ACTION == intent.action)
{
val bundle = intent.extras
if (bundle != null) {
75
val pdus = bundle.get("pdus") as Array<*>
for (pdu in pdus) {
val format = bundle.getString("format")
val smsMessage = SmsMessage.createFromPdu(pdu as
ByteArray, format)
// Extract sender and message content
val sender = smsMessage.originatingAddress
val messageBody = smsMessage.messageBody
// Example: Display the message in a Toast
Toast.makeText(context, "Message from $sender:
$messageBody", Toast.LENGTH_LONG).show()
}
}
}
AndroidManifest.xml Add the receiver and permission declaration in
your manifest:
<uses-permission
android:name="android.permission.RECEIVE_SMS"/>
<uses-permission
android:name="android.permission.READ_SMS"/>
<application ... >
<receiver android:name=".SmsReceiver"
android:enabled="true" android:exported="true">
<intent-filter android:priority="999">
<action
android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
Here:
Telephony.Sms.Intents.SMS_RECEIVED_ACTION is the action
indicating that an SMS has been received.
The pdus array contains Protocol Data Units (PDUs), which
represent the received SMS message.
Key Points:
76
SmsManager: Use it for sending SMS messages
programmatically.
BroadcastReceiver: Use it to listen for incoming SMS
messages.
Permissions: Always request runtime permissions and handle
permission denial gracefully.
SENDING EMAIL IN ANDROID
In Android, sending emails can be efficiently accomplished using
intents. Intents in Android are a messaging object used to request an
action from another app component. In the context of sending emails,
we use implicit intents, which allow communication with
components provided by other applications, like email clients.
Implicit Intents for Email
To send an email, an implicit intent with the action
Intent.ACTION_SENDTO is commonly used. The ACTION_SENDTO
action indicates that the intent is for sending data to a specific
recipient. The URI scheme mailto: is used to specify that the intent is
directed toward email-related activities.
By using this method, the Android system displays a chooser dialog to
let the user select their preferred email application, thus leveraging
the existing email client on the device. This is highly beneficial as it
allows the application to avoid handling the complexities of composing
and sending emails directly, while also providing a seamless user
experience.
Key Intent Extras for Sending Emails
When composing an email using an intent, there are certain key data
fields (extras) you can include:
77
EXTRA_EMAIL: Specifies the recipient(s) of the email in the
form of an array of strings.
EXTRA_SUBJECT: Provides the subject of the email.
EXTRA_TEXT: Represents the body content of the email.
EXTRA_CC and EXTRA_BCC: Optionally, these can be used to
add CC (Carbon Copy) and BCC (Blind Carbon Copy) recipients.
PROCESS OF SENDING E MAIL IN ANDROID
Creating the Intent: An Intent object is created with the action
ACTION_SENDTO and the data URI mailto: to ensure only email
clients respond.
Adding Email Details: The recipient email address, subject,
and body are added as extras.
Launching the Intent: The intent is triggered using
startActivity(), which launches the email client for the user to
send the email.
Step 1: Set Up the Email Intent
The Intent class is used to start an email client. You'll need to specify
the action ACTION_SENDTO and the recipient, subject, and body of
the email.
Step 2: Add Email Sending Code
import android.content.Intent
import android.net.Uri
fun sendEmail(recipient: String, subject: String, body: String) {
val intent = Intent(Intent.ACTION_SENDTO).apply {
data = Uri.parse("mailto:")
putExtra(Intent.EXTRA_EMAIL, arrayOf(recipient))
putExtra(Intent.EXTRA_SUBJECT, subject)
putExtra(Intent.EXTRA_TEXT, body)
}
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
78
}
}
Step 3: Call the Function
Invoke the sendEmail function from your activity or fragment by
passing the recipient, subject, and body text.
sendEmail(
recipient = "[email protected]",
subject = "Hello from Android",
body = "This is a test email from my app."
)
DISPLAYING MAPS IN ANDROID
Displaying maps in Android is primarily achieved using the Google
Maps API, which allows developers to embed Google Maps into their
applications. This service provides interactive and customizable map
views that support functionalities such as zoom, markers, user
location, and more.
Android offers two main libraries for displaying maps:
Google Maps SDK for Android: Allows embedding maps
powered by Google Maps into Android apps.
OSMDroid: An open-source alternative to Google Maps, useful
for offline mapping or when developers prefer not to use
Google's services.
Google Maps API Overview
The Google Maps SDK for Android provides a rich set of APIs to
add maps and various features, such as markers, polylines, and
polygons. It supports interactive features like zooming, scrolling, and
adding overlays for better visual representation.
79
Steps to Implement Google Maps in Android
1. Set Up Google Maps API: To start with Google Maps, you need
to register your app in the Google Cloud Console and obtain an
API key.
Enable the Google Maps Android API service.
Generate the API key that will be used in your Android
project.
2. Modify the Manifest: Include the required permissions and API
key in the AndroidManifest.xml file. The permissions ensure the
app can access the device’s location and internet to display the
maps.
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="YOUR_API_KEY_HERE" />
3. Add Google Play Services Dependency: Add the required
dependencies for Google Maps in your build.gradle file.
implementation 'com.google.android.gms:play-services-
maps:18.1.0'
4. Create a Map Fragment: A MapFragment or
SupportMapFragment is used to embed the map in the layout.
You define this fragment in your activity’s layout file.
<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFrag
ment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
5. Initialize the Map in Activity: In your activity or fragment,
you need to initialize the map and manage its lifecycle. You can
80
set up various features such as adding markers, zoom controls,
and gestures.
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.google.android.gms.maps.CameraUpdateFactory
class MapsActivity : AppCompatActivity(), OnMapReadyCallback
{
private lateinit var map: GoogleMap
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_maps)
val mapFragment =
supportFragmentManager.findFragmentById(R.id.map) as
SupportMapFragment
mapFragment.getMapAsync(this)
}
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
val location = LatLng(37.7749, -122.4194) // Coordinates
for San Francisco
map.addMarker(MarkerOptions().position(location).title("Marker
in San Francisco"))
map.moveCamera(CameraUpdateFactory.newLatLngZoom(locati
on, 12.0f))
}
}
Important Components
1. SupportMapFragment: This is a specialized fragment to
display a map using Google Maps.
2. GoogleMap: The object that controls the map and allows
customization (e.g., setting markers, adding overlays).
3. MarkerOptions: Used to add markers on the map at specific
latitude/longitude coordinates.
81
4. CameraUpdateFactory: Manages the camera (view) on the
map to zoom in or out and centre on certain locations.
GETTING LOCATION DATA IN ANDROID
In Android, obtaining location data allows your app to provide
features such as navigation, location-based recommendations, and
other location-related services. Android offers APIs through the Fused
Location Provider (FLP), which intelligently combines data from
GPS, Wi-Fi, and mobile networks to provide location updates
efficiently.
The Fused Location Provider is the recommended way to get
location data, as it optimizes for accuracy and battery consumption. It
simplifies the location acquisition process by automatically choosing
the best provider (GPS, network, or Wi-Fi) for the given scenario.
Key Components to Obtain Location Data
1. Google Play Services Location APIs: The Google Play
Services Location API provides a high-level API for accessing
location services.
2. LocationRequest: Defines the type of location requests such as
interval, priority, and accuracy (e.g., high accuracy for GPS or
low power for network).
3. FusedLocationProviderClient: This is the main class for
interacting with the location services to get the current location
or receive periodic location updates.
4. Permissions: You need to request location-related permissions
in your app, such as ACCESS_FINE_LOCATION for GPS-based
tracking and ACCESS_COARSE_LOCATION for network-based
location.
82
fun startLocationUpdates() {
locationRequest = LocationRequest.create().apply {
interval = 10000 // 10 seconds
fastestInterval = 5000 // 5 seconds
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult)
{
val location = locationResult.lastLocation
if (location != null) {
println("Updated Location: ${location.latitude}, $
{location.longitude}")
}
}
}
fusedLocationClient.requestLocationUpdates(locationRequest,
locationCallback, null)
}
override fun onStop() {
super.onStop()
fusedLocationClient.removeLocationUpdates(locationCallback)
}
Important Notes
1. Permissions Handling: Always ensure that you handle
permissions properly, especially with newer Android versions
that require runtime permission checks.
2. Battery Consumption: Using high-accuracy GPS continuously
may drain the battery quickly. Therefore, choose the appropriate
priority for the LocationRequest based on your use case (e.g.,
PRIORITY_BALANCED_POWER_ACCURACY for less frequent
updates).
83
MONITORING A LOCATION IN ANDROID
Monitoring a location in Android involves continuously tracking the
user's location and taking actions when specific conditions are met,
such as when the user enters or exits a geographical area. This can be
achieved through Geofencing or continuous Location Updates using
the Fused Location Provider.
Two Main Approaches for Monitoring Location:
1. Geofencing: Allows monitoring specific geographical regions
(circular areas) and triggers events when the user enters or
exits those regions.
2. Continuous Location Updates: Provides continuous updates of
the user's location, allowing you to track movement in real-time.
What is Geofencing?
Geofencing allows apps to define geographical areas, known as
geofences, and monitor when a device enters or exits these areas. It's
ideal for use cases such as sending reminders when entering a store
or triggering notifications when exiting a defined location.
Creating and Add a Geofence
1. Create the Geofence: A geofence is defined by a location
(latitude and longitude) and a radius. It can also include
expiration time and transition types (enter, exit).
2. GeofencingRequest: This defines how geofences should behave
and handles the creation of multiple geofences.
3. PendingIntent: A PendingIntent is used to define what should
happen when a geofence is triggered (such as starting a service
or broadcasting a message).
84
class GeofenceActivity : AppCompatActivity()
private lateinit var geofencingClient: GeofencingClient
private lateinit var geofencePendingIntent: PendingIntent
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_geofence)
geofencingClient = LocationServices.getGeofencingClient(this)
val geofence = Geofence.Builder()
.setRequestId("GEOFENCE_ID")
.setCircularRegion(
37.7749,
-122.4194,
100f
) // Coordinates for San Francisco, radius 100 meters
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENT
ER or Geofence.GEOFENCE_TRANSITION_EXIT)
.build()
val geofencingRequest = GeofencingRequest.Builder()
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENT
ER)
.addGeofence(geofence)
.build()
geofencePendingIntent = PendingIntent.getBroadcast(
this,
0,
Intent(this, GeofenceBroadcastReceiver::class.java),
PendingIntent.FLAG_UPDATE_CURRENT
)
}
Create a Broadcast Receiver for Geofence Transitions
85
Create a BroadcastReceiver to handle events when the user enters
or exits the defined geofence.
class GeofenceBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val geofencingEvent = GeofencingEvent.fromIntent(intent)
if (geofencingEvent.hasError()) {
// Handle error
return
}
val geofenceTransition = geofencingEvent.geofenceTransition
if (geofenceTransition ==
Geofence.GEOFENCE_TRANSITION_ENTER ||
geofenceTransition ==
Geofence.GEOFENCE_TRANSITION_EXIT) {
}
}
}
CONSUMING WEB SERVICES USING HTTP IN ANDROID
In Android, consuming web services via HTTP is a common
requirement, allowing apps to interact with remote servers, fetch
data, or submit information. There are multiple ways to implement
HTTP requests in Android, but two popular approaches include:
Retrofit: A type-safe HTTP client for Android, which simplifies
the process of making network requests and handling responses.
HttpURLConnection: A built-in class in Android for managing
HTTP requests, though it is more verbose compared to libraries
like Retrofit.
Retrofit for HTTP Requests
Retrofit is highly preferred for modern Android development due to its
ease of use and powerful features like automatic JSON parsing. Here's
how you can use Retrofit to consume web services.
86
First, add the required dependencies for Retrofit and a converter (like
Gson for JSON parsing) to your app’s build.gradle file.
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
Define API Endpoints
You define API endpoints using an interface. For instance, to fetch a
list of posts from a sample API.
import retrofit2.Call
import retrofit2.http.GET
data class Post(val userId: Int, val id: Int, val title: String, val body:
String)
interface ApiService {
@GET("posts")
fun getPosts(): Call<List<Post>>
}
Setup Retrofit Instance
Create a singleton Retrofit instance with a base URL and a
converter factory.
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitInstance {
private val retrofit by lazy {
Retrofit.Builder()
.baseUrl("https://jsonplaceholder.typicode.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
val api: ApiService by lazy {
retrofit.create(ApiService::class.java)
87
}
}
Make an HTTP Request
Now, make the HTTP request in your Activity or Fragment
private fun fetchPosts() {
val call = RetrofitInstance.api.getPosts()
call.enqueue(object : Callback<List<Post>> {
override fun onResponse(call: Call<List<Post>>, response:
Response<List<Post>>) {
if (response.isSuccessful) {
response.body()?.let { posts ->
for (post in posts) {
println("Post: ${post.title}")
}
}
}
}
override fun onFailure(call: Call<List<Post>>, t: Throwable)
{
println("Error: ${t.message}")
}
})
}
HttpURLConnection for HTTP Requests
If you prefer not to use external libraries, Android’s
HttpURLConnection is a lower-level solution to make HTTP requests.
This is more manual but built into the framework.
fun fetchUsingHttpURLConnection() {
val url = URL("https://jsonplaceholder.typicode.com/posts")
val connection = url.openConnection() as HttpURLConnection
try {
connection.requestMethod = "GET"
connection.connect()
val responseCode = connection.responseCode
if (responseCode == HttpURLConnection.HTTP_OK) {
88
val inputStream = connection.inputStream
val content = inputStream.bufferedReader().use {
it.readText() }
println("Response: $content")
} else {
println("Failed to fetch data. Response code:
$responseCode")
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
connection.disconnect()
}
}
Handling Permissions
If you're making network requests in an Android app, ensure you add
the required permission in your AndroidManifest.xml file.
<uses-permission android:name="android.permission.INTERNET"/>
For apps targeting Android 9 (API level 28) or higher, make sure to
configure cleartext traffic if you're using HTTP instead of HTTPS
<application
android:usesCleartextTraffic="true"
...>
</application>
89
UNIT - V: ANDROID SERVICES, PUBLISHING
ANDROID APPLICATIONS AND IOS
Services, Communication between a service and an activity, Binding
activities to services, Threading, preparing for publishing, Deploying
APK files iOS tools, iOS project, Debugging iOS apps, Objective-C
basics, Hello world app, Building the derby app in iOS.
SERVICES
In Android development, services are components that perform
background operations, often running independently from an activity.
They are typically used for long-running tasks, such as playing music,
downloading files, or performing network requests. Services do not
provide a user interface. A service can run independently meaning
that after your app starts the service, it can run even when your app is
no longer in focus.
90
A Service provides great flexibility by having three different types.
They are Foreground, Background, and Bound.
1) Foreground services: These services perform tasks that are
noticeable to the user, like playing music or handling ongoing
notifications.
2) Background services: These run without user interaction and
without a visible user interface, like syncing data or running in
the background for maintenance tasks.
3) Bound services: These allow activities (or other components) to
bind to the service and interact with it, often for tasks like
getting real-time updates or sending commands.
When to Use Service?
We will likely use a service when you want to do something that does
not involve UI and needs it to run whether your app is running or not.
For example, if you want to play audio a service would be a choice
because the audio will still play when the user opens another app.
COMMUNICATION BETWEEN A SERVICE AND AN
ACTIVITY
For an activity to communicate with a service, Android provides
different mechanisms:
1) Intents: You can use explicit intents to start a service. Intents
carry data to be processed by the service.
2) Broadcast Receivers: Services can send broadcasts that
activities or other components listen to and respond to.
3) Messenger: A Messenger allows communication using Handler
and Message objects. This is useful for passing simple messages
back and forth between an activity and a service.
91
4) AIDL (Android Interface Definition Language): This is used
for more complex services, especially when multiple applications
need to communicate with a service.
There are two simple ways for you to use an Activity and Service
together. One way is to create a bound service and bind a component
in your activity to the service acting as a communication channel.
Another way is to use the Android Broadcast System, which sends out
a broadcast intent system-wide.
BINDING ACTIVITIES TO SERVICES
A bound service allows activities to directly interact with the service.
This binding is important when the activity requires frequent
communication with the service, such as for fetching updates in real
time.
Real-time Example: Music Player App
92
Imagine a music player application where a service is responsible for
playing music in the background. The user interacts with the app’s UI
(the activity), but the music continues playing even when the user
navigates away from the activity. In this case, the activity can bind to
the service to control the music (play, pause, stop) or retrieve the
current playback status.
Step 1: Create the Service-> Define a bound service that plays
music
class MusicService : Service() {
private val binder = LocalBinder()
inner class LocalBinder : Binder() {
fun getService(): MusicService = this@MusicService
override fun onBind(intent: Intent?): IBinder {
return binder
fun playMusic() {
// Logic to play music
fun pauseMusic() {
// Logic to pause music
fun stopMusic() {
// Logic to stop music
93
}
Step 2: Bind the Activity to the Service->The activity can bind and
communicate with the service.
class MusicPlayerActivity : AppCompatActivity() {
private var musicService: MusicService? = null
private var isBound = false
private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?,
service: IBinder?) {
val binder = service as MusicService.LocalBinder
musicService = binder.getService()
isBound = true
override fun onServiceDisconnected(name: ComponentName?) {
isBound = false
override fun onStart() {
super.onStart()
Intent(this, MusicService::class.java).also { intent ->
bindService(intent, connection, Context.BIND_AUTO_CREATE)
94
override fun onStop() {
super.onStop()
if (isBound) {
unbindService(connection)
isBound = false
fun onPlayButtonClicked() {
musicService?.playMusic()
fun onPauseButtonClicked() {
musicService?.pauseMusic()
fun onStopButtonClicked() {
musicService?.stopMusic()
The MusicService is a bound service that handles music
playback.
The MusicPlayerActivity binds to the service during its lifecycle
(onStart and onStop).
When the user presses play, pause, or stop buttons, the activity
sends commands to the bound service to control the music.
THREADING
95
In Android, a thread is a unit of execution that can run independently
of the main UI thread. Threads can be used to perform long-running
tasks without blocking the UI, but they are still part of the same
process, not separate background processes.
Threads in Android are typically used to offload tasks from the main
thread to avoid freezing the UI. However, they are part of the same
application process and share the same memory space. In Java and
Kotlin, the Thread class and coroutines can be used to create and
manage threads.
Why Threading is Important in Android?
1) Preventing UI Freezes: Long-running tasks (e.g., file
operations, network requests) can block the UI thread, causing
the app to freeze. By moving these tasks to background threads,
the UI remains responsive.
2) Efficient Resource Utilization: Threading allows multiple
tasks to run concurrently, making better use of the device's
resources.
3) Separation of Workloads: Background tasks like data loading,
image processing, or database operations can be separated from
UI tasks, improving performance and user experience.
Threading Techniques in Android
1. Thread and Runnable
The basic approach to threading in Java/Android is using
Thread or Runnable.
A Thread is a unit of execution, and a Runnable is a task
that a thread executes.
val backgroundThread = Thread(Runnable {
// Background task, e.g., downloading a file
96
downloadFile()
})
backgroundThread.start()
2. HandlerThread
HandlerThread is a subclass of Thread that comes with a
Looper. It provides a way to handle messages and run
tasks in a background thread.
You can use it when you want a dedicated background
thread for tasks that will process messages or Runnables.
val handlerThread = HandlerThread("BackgroundHandler")
handlerThread.start()
val handler = Handler(handlerThread.looper)
handler.post {
// Long-running background task
performLongTask()
3. Coroutines (Preferred with Kotlin):
In Kotlin, coroutines are the recommended way to
perform background tasks, as they are lightweight and
provide a simpler, more structured way to handle
asynchronous programming.
Coroutines allow for suspending functions that can be
paused and resumed without blocking threads.
import kotlinx.coroutines.*
fun fetchData() {
97
// Start a coroutine in the background
GlobalScope.launch(Dispatchers.IO) {
val data = downloadData() // Background task
withContext(Dispatchers.Main) {
textView.text = data
PREPARING APPLICATIONS FOR RELEASE
Preparing your app for release is a multistep process involving the
following tasks:
Configure your app for release
At a minimum, you need to make sure that logging is disabled
and removed and that your release variant has debuggable false for
Groovy or undebuggable = false for Kotlin script set. You should
also set your app's version information.
Build and sign a release version of your app
You can use the Gradle build files with the release build type to
build and sign a release version of your app. For more information,
see Build and run your app.
Test the release version of your app
Before you distribute your app, you should thoroughly test the
release version on at least one target handset device and one target
tablet device. Firebase Test Lab is useful for testing across a variety of
devices and configurations.
Update app resources for release
98
Make sure that all app resources, such as multimedia files and
graphics, are updated and included with your app or staged on the
proper production servers.
Prepare remote servers and services that your app depends
on
If your app depends on external servers or services, make sure
they are secure and production ready. You might need to perform
several other tasks as part of the preparation process. For example,
you need to create an account on the app marketplace you want to
use, if you don't already have one. You also need to create an icon for
your app, and you might want to prepare an End User License
Agreement (EULA) to protect yourself, your organization, and your
intellectual property.
DEPLOYING APK FILES
Release your app to users
You can release your Android apps several ways. Typically, you release
apps through an app marketplace such as Google Play. You can also
release apps on your own website or by sending an app directly to a
user.
Release through an app marketplace
If you want to distribute your apps to the broadest possible audience,
release them through an app marketplace.
Google Play is the premier marketplace for Android apps and is
particularly useful if you want to distribute your apps to a large global
audience. However, you can distribute your apps through any app
marketplace, and you can use multiple marketplaces.
Release your apps on Google Play
99
Google Play is a robust publishing platform that helps you publicize,
sell, and distribute your Android apps to users around the world.
When you release your apps through Google Play, you have access to a
suite of developer tools that let you analyze your sales, identify market
trends, and control who your apps are being distributed to.
Google Play also gives you access to several revenue-enhancing
features such as in-app billing and app licensing. The rich array of
tools and features, coupled with numerous end-user community
features, makes Google Play the premier marketplace for selling and
buying Android apps.
Releasing your app on Google Play is a simple process that involves
three basic steps:
Prepare promotional materials
To fully leverage the marketing and publicity capabilities of
Google Play, you need to create promotional materials for your app
such as screenshots, videos, graphics, and promotional text.
Configure options and uploading assets
Google Play lets you target your app to a worldwide pool of
users and devices. By configuring various Google Play settings, you
can choose the countries you want to reach, the listing languages you
want to use, and the price you want to charge in each country.
You can also configure listing details such as the app type,
category, and content rating. When you are done configuring options,
you can upload your promotional materials and your app as a draft
app.
Publish the release version of your app
If you are satisfied that your publishing settings are correctly
configured and your uploaded app is ready to be released to the
100
public, click Publish. Once it has passed Google Play review, your app
will be live and available for download around the world.
iOS Tools
Developing iOS applications requires a suite of specialized tools to
streamline the process from design to deployment. Here are some
essential tools for iOS mobile application development,
1. Xcode
Xcode is Apple's official Integrated Development Environment
(IDE) for macOS, providing a comprehensive suite of tools for
developing, testing, and debugging iOS applications. It includes a
code editor, interface builder, and simulators for various Apple
devices.
2. Swift
Swift is a powerful and intuitive programming language
developed by Apple for iOS, macOS, watchOS, and tvOS app
development. It offers modern features, safety enhancements,
and performance optimizations, making it a preferred choice for
developers.
3. CocoaPods
Cocoa Pods is a dependency manager for Swift and Objective-C
projects, simplifying the integration of third-party libraries into
Xcode projects. It provides access to a vast repository of open-
source libraries, facilitating code reuse and modular
development.
4. Swift Package Manager
Swift Package Manager is a tool for managing the distribution of
Swift code. It integrates with the Swift build system to automate
the process of downloading, compiling, and linking
dependencies, promoting a streamlined workflow.
101
5. TestFlight
TestFlight is an online service by Apple that allows developers to
invite users to test iOS applications before they are released on
the App Store. It supports beta testing, feedback collection, and
crash reporting, aiding in the refinement of apps prior to official
launch.
6. Firebase
Firebase is a platform developed by Google offering a suite of
tools for app development, including analytics, real-time
databases, authentication, and cloud messaging. It assists in
building high-quality apps, improving user engagement, and
growing the user base.
SETTING UP AN IOS PROJECT
1. Xcode is the primary IDE used for iOS development. Start by
creating a new project in Xcode using the desired project
template (e.g., Single View App, Tabbed App, etc.).
2. Choose Swift or Objective-C as the programming language for
your project.
3. Project structure: Understand the folders and files generated:
AppDelegate and SceneDelegate for app lifecycle
management.
ViewController for controlling the UI logic.
Main.storyboard or SwiftUI files for designing the user
interface.
iOS Project Structure
1. AppDelegate.swift: Manages app lifecycle events (e.g., app
launch, background, foreground).
102
2. SceneDelegate.swift: Manages individual scenes for your app
(e.g., when using multi-window features).
3. ViewController.swift: This is where you'll implement your UI
logic.
4. Main.storyboard: This file defines your app’s visual interface.
AppDelegate.swift
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if
appropriate.
SceneDelegate.swift
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
103
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session:
UISceneSession, options connectionOptions:
UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else
{ return }
// Programmatically create the main window
window = UIWindow(windowScene: windowScene)
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
func sceneDidEnterBackground(_ scene: UIScene) {
// Save data when the app enters the background.
ViewController.swift
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session:
UISceneSession, options connectionOptions:
UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the
UIWindow `window` to the provided UIWindowScene `scene`.
104
guard let windowScene = (scene as? UIWindowScene) else
{ return }
window = UIWindow(windowScene: windowScene)
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
func sceneDidEnterBackground(_ scene: UIScene) {
// Save data when the app enters the background.
Main.storyboard
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var myLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
myLabel.text = "Hello, Storyboard!"
105
106
COMMON DEBUGGING TOOLS AND TECHNIQUES
1. Xcode Debugger (LLDB)
The LLDB (Low-Level Debugger) is integrated into Xcode and
can help track down issues by stepping through code, inspecting
variables, and setting breakpoints.
Use breakpoints to pause execution at certain lines of code.
This lets you inspect the state of the app at that moment,
including variable values and memory usage.
You can view the console output to see logs or use LLDB
commands for advanced debugging.
2. Print Statements and Console Logs
Add print() statements to track the flow of the app and inspect
variable values at runtime.
Use NSLog() in Objective-C or os_log() for more structured
logging.
3. View Hierarchy Debugging
Xcode provides a powerful tool to debug the view hierarchy
visually. Use it when you're having layout issues to inspect how
views are rendered.
You can access the view debugger by running your app and
clicking the Debug View Hierarchy button.
4. Memory and Performance Profiling (Instruments)
Use Instruments (a performance analysis tool bundled with
Xcode) to track:
o Memory leaks: Ensure your app is releasing memory
properly to avoid crashes.
107
o CPU usage: Check if there are any performance
bottlenecks.
o Time Profiler: Identify which methods consume the most
time.
o Energy usage: Useful when debugging performance for
apps with background services or intensive computations.
5. Crash Logs and Exception Breakpoints
Xcode will display crash logs if your app terminates
unexpectedly. Review the logs to understand what caused the
crash.
Enable Exception Breakpoints to catch runtime exceptions as
they occur, stopping the app at the point where the error
happened.
6. Testing
Write unit tests and UI tests using Xcode's built-in testing
framework (XCTest) to automate the detection of errors.
Running tests allows you to identify regressions early in the
development process.
7. Simulators
Run your app on various simulators to mimic different iOS
devices and screen sizes.
Simulators allow you to test the app without needing physical
devices. However, always test on real hardware before
deployment.
BUILDING THE DERBY APP IN IOS
1. Setting Up the Project
108
Open Xcode and create a new project.
Select App under the iOS tab and click Next.
Name the project "DerbyApp" and choose Swift as the language.
Set the interface to Storyboard and leave the other settings as
they are.
Click Next, choose a location for your project, and click Create.
2. Designing the User Interface (UI)
In Main.storyboard, you will create the interface for the Derby
game.
a. Add UI Elements
Open Main.storyboard and select the ViewController.
Drag Image Views from the Object Library (on the right) onto
the storyboard. Each Image View will represent a horse. Add
three Image Views for three horses.
Set images for the horses (you can use placeholder images for
now).
Add a UIButton labeled "Start Race" that will start the race
when tapped.
Add a UILabel at the top to display which horse wins the race.
b. Arrange the UI
Position the three horses near the left edge of the screen.
Align them vertically with some space between them.
Place the "Start Race" button below the horses.
Position the result label at the top.
c. Connect UI Elements to Code
109
Open the Assistant Editor (click the two overlapping circles at
the top right) so that you can see both the ViewController.swift
file and the storyboard side by side.
Ctrl-drag from each of the three Image Views to the
ViewController.swift file to create outlets. Name them horse1,
horse2, and horse3.
Ctrl-drag from the "Start Race" button to create an action
method. Name it startRaceTapped.
Ctrl-drag from the label to create an outlet called resultLabel.
3. Writing the Game Logic in Swift
Now, let’s implement the logic for the Derby race. The horses will
move across the screen when the race starts, and the game will
declare a winner when the first horse reaches the finish line.
Open ViewController.swift and update it as follows:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var horse1: UIImageView!
@IBOutlet weak var horse2: UIImageView!
@IBOutlet weak var horse3: UIImageView!
// Outlet for the result label
@IBOutlet weak var resultLabel: UILabel!
// A timer to animate the horses
var raceTimer: Timer?
110
// Track if the race is running
var raceInProgress = false
override func viewDidLoad() {
super.viewDidLoad()
// Initialize the result label to be empty at start
resultLabel.text = ""
// Start race button action
@IBAction func startRaceTapped(_ sender: UIButton) {
if raceInProgress {
return // Ignore if a race is already running
raceInProgress = true
resultLabel.text = "" // Clear the result label before the race
// Reset horse positions
resetHorsePositions()
// Start the race timer to move horses
raceTimer = Timer.scheduledTimer(timeInterval: 0.05, target:
self, selector: #selector(moveHorses), userInfo: nil, repeats: true)
111
}
// Reset the horses to the starting line
func resetHorsePositions() {
horse1.frame.origin.x = 20
horse2.frame.origin.x = 20
horse3.frame.origin.x = 20
// Move horses forward
@objc func moveHorses() {
let finishLine = view.frame.width - 100
// Move each horse by a random amount
horse1.frame.origin.x += CGFloat.random(in: 2...10)
horse2.frame.origin.x += CGFloat.random(in: 2...10)
horse3.frame.origin.x += CGFloat.random(in: 2...10)
// Check if any horse has crossed the finish line
if horse1.frame.origin.x >= finishLine {
declareWinner(horse: "Horse 1")
} else if horse2.frame.origin.x >= finishLine {
declareWinner(horse: "Horse 2")
} else if horse3.frame.origin.x >= finishLine {
112
declareWinner(horse: "Horse 3")
// Stop the race and declare a winner
func declareWinner(horse: String) {
raceTimer?.invalidate() // Stop the race timer
raceInProgress = false
// Update the result label with the winner
resultLabel.text = "\(horse) Wins!"
Explanation of Code
Outlets and Actions: The outlets connect the UI elements
(horses and result label) to the code. The startRaceTapped
function is triggered when the user taps the "Start Race" button.
Race Timer: The timer (raceTimer) is used to repeatedly move
the horses across the screen. It updates every 0.05 seconds and
moves each horse by a random number of pixels.
Finish Line: We define the finish line as view.frame.width - 100
(100 pixels from the right edge of the screen).
Random Movement: Each horse moves forward by a random
amount between 2 and 10 pixels, simulating the race.
Winner Declaration: When a horse crosses the finish line, the
race stops, and the result label displays the winner.
4. Running the App
113
Press Cmd + R or click the Run button in Xcode to build and run
the app in the iOS Simulator.
Tap the "Start Race" button to begin the race, and watch as the
horses move across the screen.
The result label will display the winner once one of the horses
crosses the finish line.
114