Speaker 1: Welcome to the Depth Dive, where we take a stack
Speaker 1: of information and really extract the most important nuggets of
Speaker 1: knowledge and insight tailored just for you. Today, we're doing
Speaker 1: something a little different. It's like a fascinating TimewARP. We're
Speaker 1: diving into the Android Application Development Cookbook, second edition, which,
Speaker 1: believe it or not, was published way back in March
Speaker 1: twenty sixteen. Our mission here is basically to give you
Speaker 1: a shortcut, a shortcut to understanding what Android app development
Speaker 1: looked like, you know, nearly a decade ago. We'll uncover
Speaker 1: the core ideas, some practical recipes for problems developers face then,
Speaker 1: and maybe some surprising things that we're cutting edge and
Speaker 1: see how much or maybe how little things have really changed.
Speaker 1: Our main source is that cookbook by Rick Boyer and
Speaker 1: Kyle mu It's very much designed for developers who learn
Speaker 1: by doing a by jumping into code. It's literally broken
Speaker 1: down into these recipes with sections like getting ready, how
Speaker 1: to do it, how it works. So let's imagine you're
Speaker 1: an Android dep back in twenty sixteen, staring at a
Speaker 1: blank screen. What were the absolute first things you'd write?
Speaker 1: What were those fundamental building block?
Speaker 2: Yeah, it's really interesting looking back, what's fascinating is how
Speaker 2: clearly the book lays out these core components that honestly
Speaker 2: are still pretty foundational today, even of how we implement
Speaker 2: them has evolved quite a bit. The absolute bedrock for
Speaker 2: almost any Android app then, and you could argue still now,
Speaker 2: were activity activities. Right, Think of an activity as like
Speaker 2: a single screen in your app, or a distinct user
Speaker 2: interface view every single screen, your main menu settings, a
Speaker 2: photo viewer that would typically be its own activity, and
Speaker 2: these were all declared in that central file, the Android
Speaker 2: Manifest dot XML.
Speaker 1: Ah, the manifest okay exactly.
Speaker 2: And crucially specific things called intent filters in there, like
Speaker 2: main and launcher. They told the system which activity was
Speaker 2: the main entry point, you know, the one that gets
Speaker 2: the icon on your phone's home screen.
Speaker 1: Okay, So activities are like the individual rooms in a house,
Speaker 1: and the Manifest is the blueprint saying this room is
Speaker 1: the front door. Got it? But how did these rooms
Speaker 1: talk to each other inside the same app, or even
Speaker 1: like talking to other apps on the phone.
Speaker 2: That's where the incredibly powerful intent object came in. It's
Speaker 2: essentially a message object. Think of it as a way
Speaker 2: to say I want to do something, Yeah, but without
Speaker 2: needing to know exactly who we'll do it. So, for example,
Speaker 2: you could use intents dot action view. You tell the system, hey,
Speaker 2: I want to view this capacity URL maybe huh, and
Speaker 2: Android would figure out okay, the default web browser should
Speaker 2: handle this and launch it for you.
Speaker 1: Right, So the app doesn't need to know which browser
Speaker 1: the user has installed exactly.
Speaker 2: And what was really clever and still is is that
Speaker 2: different types of data could launch completely different apps. A
Speaker 2: location might open a map app, a contact file might
Speaker 2: open the contact app. It showed how flexible the system
Speaker 2: was letting apps work together without hard coding dependencies.
Speaker 1: That's huge, that interoperability. Okay, so that's talking between apps.
Speaker 1: What about just moving between screens inside your own appic
Speaker 1: from a list to a detail screen.
Speaker 2: Intents handle that too. You just create an intent specifying
Speaker 2: the target activity, say moving from your main activity to
Speaker 2: a second activity. As simple as that, And if you
Speaker 2: needed to send some information along, you'd use put extra.
Speaker 2: It worked with name value pairs, like packing little bits
Speaker 2: of data into the intent.
Speaker 1: Like sticking a post it note on the message.
Speaker 2: Pretty much yeah, exactly like a post it and the
Speaker 2: receiving activity would just grab that data using methods like
Speaker 2: get string extra looking for the name you give it.
Speaker 1: Okay, And what if you needed to get something back
Speaker 1: from that second screen. Let's say you launched a contact
Speaker 1: picker and you need the phone number the user picked.
Speaker 2: Ah, right, for that, you wouldn't just start the activity.
Speaker 2: You'd use start activity for results the result makes sense,
Speaker 2: and the result would come back to the original activity
Speaker 2: in a special callback method on activity results. And for
Speaker 2: apps doing lots of this, maybe calling different activities for results,
Speaker 2: there was something called a request code. There's a number
Speaker 2: you defined when you started the activity, so that when
Speaker 2: on activity result was called, you could check that code
Speaker 2: and know which request was returing its result. Kept things organized, right,
Speaker 2: because the mobile world is just so dynamic, isn't it.
Speaker 2: You're in an app, a phone call comes in, you
Speaker 2: switch to another app, The system might even kill your
Speaker 2: app in the background, off the needs memory. It feels
Speaker 2: like a constant battle with the OS. So what did
Speaker 2: this all mean for a developer trying to make an
Speaker 2: app feel smooth and seamless even with all those interruptions.
Speaker 1: That's the million dollar question really, and connecting this to
Speaker 1: the bigger picture, understanding the activity life cycle was just
Speaker 1: absolutely critical paramount for app stability user experience, especially back
Speaker 1: then on devices that maybe didn't have tons of memory.
Speaker 1: Think about this, just rotating your phone. Yeah, by default,
Speaker 1: Android would completely destroy your current activity and then recreate
Speaker 1: it from a scratch.
Speaker 2: Wait, destroy it just for rotating?
Speaker 1: Yeah, destroy and recreate, which, as you can imagine, could
Speaker 1: lead to a really terrible user experience if you weren't
Speaker 1: ready for it. All the user's input gone, the scroll
Speaker 1: position lost.
Speaker 2: Wow. Okay, so how did developers handle that? That's where
Speaker 2: these life cycle callback methods were vital, Things like on
Speaker 2: save instance state and on restore instance. On save instance
Speaker 2: date gave you a chance right before the activity was
Speaker 2: potentially destroyed to save small bits of data like user
Speaker 2: input or UI state okay, And then if the activity
Speaker 2: was recreated on restore instance state or on create what
Speaker 2: would be called and you could get that save data
Speaker 2: back and restore the state so the user could just
Speaker 2: pick up where they left off.
Speaker 1: So you had to manually save and restore anything important
Speaker 1: every time a configuration might change, like rotation.
Speaker 2: Pretty much.
Speaker 1: Yes.
Speaker 2: The book details the core life cycle states active, pause, stopped, destroyed,
Speaker 2: and the methods tied to them. On create on resume,
Speaker 2: on pause, on stop, on destroy. The US was described
Speaker 2: as ruthless with resource management. If your app went into
Speaker 2: the pause or stop state, it was fair game for
Speaker 2: the OS to kill it to reclaim memory.
Speaker 1: That sounds like a lot of manual work and potential
Speaker 1: for bugs.
Speaker 2: It absolutely was a major source of frustration. Bilbote's got
Speaker 2: to be really careful about calling the superclass methods, understanding
Speaker 2: when each callback fired what they could safely do in
Speaker 2: each one. It's honestly one of the main reasons modern
Speaker 2: Android development shifted towards things like view model from the
Speaker 2: architecture components.
Speaker 1: Right to abstract away some of that life cycle complexity exactly.
Speaker 2: View models survive configuration changes like rotation, automatically holding UI
Speaker 2: related data without you needing to manually save and restore
Speaker 2: it in the activity nearly as much. It simplified things massively.
Speaker 1: Okay, so we've got the basic structure with activities and
Speaker 1: intents and a sense of the constant dance with the
Speaker 1: OS life cycle. But an app is nothing without its interface.
Speaker 1: This is where it gets really interesting, right, optimizing what
Speaker 1: the user actually sees and interacts with. It's not just
Speaker 1: what you put on screen, but how you put.
Speaker 2: It there absolutely, and that raises the question, how do
Speaker 2: you build a complex, good looking UI that still performs well,
Speaker 2: especially considering the huge variety of Android devices out there.
Speaker 2: Even back then, the techniques in the cookbook, even from
Speaker 2: twenty sixteen, really emphasize that performance starts with design, and
Speaker 2: the foundation of UI design was layouts and view.
Speaker 1: Groups w groups. That's like a container precisely.
Speaker 2: A view group is the base class for containers, and
Speaker 2: layout classes, which inherit from view group, are what you
Speaker 2: use to actually organize the UI elements, the buttons, the
Speaker 2: text fields, the images. They define the structure.
Speaker 1: What were the main layout types developers were using back then?
Speaker 2: The book covers several key ones. Relative layout was really powerful.
Speaker 2: It let you position views relative to each other or
Speaker 2: relative to the parent container. You could say, this button
Speaker 2: goes to the right of that text view or center
Speaker 2: this image. Very flexible for complex screens. Okay, yeah, Linear
Speaker 2: layout much simpler. It just arranged views one after another,
Speaker 2: either vertically in a column or horizontally in a row.
Speaker 1: Simple but probably useful, very and.
Speaker 2: Its key feature was layout weight. This allowed views within
Speaker 2: the linear layout to take up proportional space. Like one
Speaker 2: element takes seventy percent of the width, the other takes
Speaker 2: thirty percent. Super useful for dividing space.
Speaker 1: Dynamically right and for grids like a calculator or a
Speaker 1: photo gallery.
Speaker 2: For grid like structures, there was table layout and grid layout.
Speaker 2: They approached it slightly differently how they defined rows and columns,
Speaker 2: but both serve that purpose. And of course you could
Speaker 2: nest these layouts, put a linear layout inside a relative
Speaker 2: layout inside another linear layout. That's how you built up
Speaker 2: really complex UI hierarchies.
Speaker 1: But nesting sounds like it could get complicated fast and
Speaker 1: maybe slow things down. Were there tools to help optimize
Speaker 1: these layouts?
Speaker 2: You bet? Performance was definitely a concern. The cookbook highlights
Speaker 2: a couple of essential tools from that era. First, the
Speaker 2: hierarchy Viewer hierarchy veer. Yeah, there's a tool that let
Speaker 2: you visually inspect your layout structure as a tree. You
Speaker 2: could see how deeply nested things were, identify redundant layouts.
Speaker 2: Super useful for fine bottlenecks. The catch was, back then
Speaker 2: it usually required a rooted device or an emulator to
Speaker 2: use it.
Speaker 1: Ah, okay, bit of a hurdle.
Speaker 2: A bit, yeah, But then there was lint. Lint was
Speaker 2: and still is part of the Android SDK integrated into
Speaker 2: Android Studio. Think of it as like a static code analyzer,
Speaker 2: but specifically for androids.
Speaker 1: So it would warn you about problems exactly.
Speaker 2: It would flag potential layout issues automatically, things like deep layouts,
Speaker 2: warning you if your view hierarchy was nested too many
Speaker 2: levels deep which killed performance, or nested weights in linear layouts,
Speaker 2: another notorious performance trap. It also flagged things like useless
Speaker 2: parent layouts or useless leaf views that weren't contributing anything
Speaker 2: really helpful for keeping UIs lean.
Speaker 1: And what if you had a part of the UI
Speaker 1: that was complex but maybe wasn't used very often, like
Speaker 1: a detailed error message panel. Was there a way to
Speaker 1: avoid loading that all the time?
Speaker 2: Yes, that's where view stub came in. It was described
Speaker 2: as a lazy load mechanism. Basically, it was a placeholder
Speaker 2: in your layout. This very lightweight took up almost no
Speaker 2: memory or inflation time initially only when you explicitly told
Speaker 2: the view stub to inflate, usually in your code, when
Speaker 2: that specific UI was actually needed. Would it load the
Speaker 2: real more complex layout it was referencing great for reducing
Speaker 2: initial screen load time and memory usage for rarely seeing
Speaker 2: UI components clever.
Speaker 1: Okay, so that's the structure. What about the actual things
Speaker 1: the user sees and taps on? The widgets?
Speaker 2: Right, the views and widgets. The book mentions all the
Speaker 2: common built in ones you'd expect text view for text, button, checkbox,
Speaker 2: even things like clock, date, picker, calendar, A whole toolbox
Speaker 2: of standard UI elements.
Speaker 1: But could you make your own if the standard ones
Speaker 1: weren't enough.
Speaker 2: Absolutely, customization was key. You could extend an existing widget
Speaker 2: to add functionality, or you could create a totally custom
Speaker 2: view from scratch by extending the base view class. Doing
Speaker 2: that often meant you had to get your hands dirty
Speaker 2: overwriting methods like on measure to tell Android how big
Speaker 2: your custom view should be, and on draw to actually
Speaker 2: draw its appearance on the screen. Using the canvas.
Speaker 1: API sounds like more work, but powerful.
Speaker 2: Definitely more work, but it gave you complete control. Another
Speaker 2: common technique mentioned was creating compound controls. This just meant
Speaker 2: grouping several existing controls together into a single reusable component,
Speaker 2: like creating a custom search bar widget made up of
Speaker 2: a text view and a button.
Speaker 1: Okay, so you build a layout, put the widgets in,
Speaker 1: but then you need consistent styling, right colors, font sizes.
Speaker 1: How is that handled?
Speaker 2: That's where styles and themes came in. They were crucial
Speaker 2: for maintainability and achieving a consistent look and feel. Styles
Speaker 2: were defined in an XML file, usually styles dot XML.
Speaker 2: A style was basically a collection of attributes like android
Speaker 2: dot layout with android dot background, android dot text color,
Speaker 2: android dot text size. You could define a style once
Speaker 2: like a CSS class, exactly like a CSS class to
Speaker 2: define it once, then apply that style to multiple views button, textview, etc.
Speaker 2: In your layouts. So if you needed to change the
Speaker 2: standard button color across your app, you just changed it
Speaker 2: in the style definition, not on every single button.
Speaker 1: Much cleaner in themes, How are they different?
Speaker 2: Themes were broader. They applied to an entire activity or
Speaker 2: even the whole application, rather than individual views. Themes affected
Speaker 2: things like the default appearance of standard widgets or window
Speaker 2: attributes like the status bar color, or whether the activity
Speaker 2: had a title bar or an action bar. You could
Speaker 2: even use a theme to make an activity look like
Speaker 2: a floating dialogue box, for instance.
Speaker 1: And dealing with different Android versions was a big thing
Speaker 1: back then, right with Holo themes the material design coming in.
Speaker 1: How did themes handle that?
Speaker 2: Yeah, that was a major challenge, the fragmentation. The book
Speaker 2: explains how developers used resource qualifiers. You could define different
Speaker 2: theme versions and folders like values v eleven for Android
Speaker 2: three point zero Honeycomb which introduced the Holo theme, or
Speaker 2: values v twenty one for Android five point Oho Lollipop
Speaker 2: with material design.
Speaker 1: Ah, so the system would automatically pick the right one
Speaker 1: based on the device's Android version.
Speaker 2: Correct, the system handles selecting the most appropriate resources. But
Speaker 2: even more importantly, the app compat library was absolutely essential.
Speaker 2: It was a support library from Google that backpoorded newer
Speaker 2: UI elements and theme features like the action bar and
Speaker 2: material design components to older Android.
Speaker 1: Versions, so you could use newer features without dropping support
Speaker 1: for older phones exactly.
Speaker 2: App Compat was a lifeline for developers trying to provide
Speaker 2: a reasonably consistent and modern looking UI across that fragmented landscape.
Speaker 2: It smoothed over a lot of the version differences.
Speaker 1: Okay, so building on that, the app looks good, it's structured, well,
Speaker 1: now it needs to actually respond to the user in
Speaker 1: smart ways, provide feedback guide them. What were the standard
Speaker 1: ways to handle interaction like menus and alerts.
Speaker 2: Right. This is where the user experience really starts to
Speaker 2: take shape, making the app feel interactive and intuitive. The
Speaker 2: cookbook dies into several key areas here, starting with menu systems.
Speaker 2: Menus were and still are a fundamental way to provide
Speaker 2: options and actions to the user.
Speaker 1: What were the main kinds of menus available back in
Speaker 1: twenty sixteen, Well, the main.
Speaker 2: One was the options menu. That's the standard menu, typically
Speaker 2: appearing in the action bar at the top of the screen.
Speaker 2: If there wasn't enough space, items would go into that
Speaker 2: familiar three dot overflow menu.
Speaker 1: Okay, the standard stuff.
Speaker 2: Yeah. Developers used XML attributes like show as action to
Speaker 2: suggest whether an item should appear directly in the bar
Speaker 2: bedroom or always being the overflow never. Then there was
Speaker 2: contextual mode or Contextual Action Mode CM. This was seen
Speaker 2: as a big improvement introduced around Android three point zero.
Speaker 2: You typically trigger it with a long press on an
Speaker 2: item like a list item or some text.
Speaker 1: Ah like a right click on desktop.
Speaker 2: Exactly like a right click, it would bring up a
Speaker 2: temporary action bar at the top with action specific to
Speaker 2: the item or items you selected. It supported selecting multiple
Speaker 2: items too, for batch actions. Like deleting multiple emails. Way
Speaker 2: better than the older floating context menus.
Speaker 1: Okay, that sounds useful any other menu types.
Speaker 2: There was also the pop up menu. This was simpler,
Speaker 2: just a little menu that pops up, often anchored to
Speaker 2: a specific view, providing some extra actions. It wasn't necessarily
Speaker 2: tied to acting on the view that triggered it, more
Speaker 2: like providing related options in nearby, like a spinner, but
Speaker 2: in a menu format.
Speaker 1: Got it. So beyond menus for explicit actions, how did
Speaker 1: apps grab the user's attention or give quick feedback without
Speaker 1: being too disruptive?
Speaker 2: For that, you had various alerts and notifications. For immediate
Speaker 2: physical feedback. Apps could use the vibrator service to make
Speaker 2: the phone vibrate simple enough, or play sounds using the
Speaker 2: ringtone manager to pla say, the default notification sound. The
Speaker 2: book even mentions a newer API twenty three feature set
Speaker 2: torch mode to flash the camera light briefly as an alert.
Speaker 1: Using the flashlight for alerts.
Speaker 2: That's novel, Yeah, a bit unusual, but shows the kind
Speaker 2: of low level control you had for quick non blocking messages.
Speaker 2: Toasts or the standard toasts.
Speaker 1: Right, those little gray boxes that pop up briefly at
Speaker 1: the bottom exactly.
Speaker 2: They'd show a short text message and then fade away, simple, unobtrusive.
Speaker 2: You could even customize their layout if you wanted something fancier.
Speaker 1: Than just text, and for messages that needed a user
Speaker 1: response like a confirmation.
Speaker 2: That's where alert dialogue came in the classic message box.
Speaker 2: You could create dialogues with a title, a message, and
Speaker 2: up to three standard buttons positive, negative, neutral like yes,
Speaker 2: no cancel. You could also add icons or even put
Speaker 2: lists inside them single choice lists, multi choice lists, or
Speaker 2: embed a completely custom layout if needed. Very flexible.
Speaker 1: What about showing progress like if something was loading.
Speaker 2: There was progress dialogue. It showed a spinning wheel or
Speaker 2: a progress bar, typically indicating loading or some indeterminate task. However,
Speaker 2: the cookbook explicitly advised developers to avoid progress dialogue if possible.
Speaker 1: Why I avoid it.
Speaker 2: Because it was modal. It blocked the user from interacting
Speaker 2: with the rest of the app until it was dismissed,
Speaker 2: which could be really frustrating if the task took a while.
Speaker 2: The recommendation was to integrate a progress bar directly into
Speaker 2: your apps layout instead, so the user could still interact
Speaker 2: with other parts of the UI. Wall waiting.
Speaker 1: That's a key usability point even back then. Okay, so
Speaker 1: that's in app alerts. What about the system notifications, the
Speaker 1: ones that appear in the notification.
Speaker 2: Drawer, Ah notifications. Yeah, super important for engaging users when
Speaker 2: the app wasn't in the foreground. Developers built these using
Speaker 2: notification compat builder. That compact part signifies it came from
Speaker 2: the support library, helping ensure compatibility across different Android versions.
Speaker 2: You'd set things like a small icon, a title, the
Speaker 2: main content text, and.
Speaker 1: Could you add buttons to notifications like reply or archive?
Speaker 2: Yes? Absolutely, you could add action buttons using something called
Speaker 2: pending intent. A pending intent is basically a token that
Speaker 2: you give to the Android system. It wraps an intent
Speaker 2: and grants the system permission to send that intent on
Speaker 2: your app's behalf at a later time, even if your
Speaker 2: app isn't running.
Speaker 1: So the notification itself could trigger an action in your
Speaker 1: app securely exactly.
Speaker 2: It's how notification actions worked. Clicking a reply button might
Speaker 2: launch a specific activity in your app, or trigger a
Speaker 2: background service to handle the reply. Later Android versions added
Speaker 2: more features like expanded notifications. Android four point one plus
Speaker 2: could show more content, like a longer text snippet or
Speaker 2: an image using set style, and Android five point zero
Speaker 2: brought specialized styles like media player notifications with playback controls,
Speaker 2: though the book notes this wasn't in the compat library yet,
Speaker 2: and also heads up notifications.
Speaker 1: Oh those ones that pop up over everything.
Speaker 2: Yeah, the really intrusive ones. They appeared on top of
Speaker 2: whatever app you were using. They were reserved for high
Speaker 2: priority things and required setting priority macs and usually having
Speaker 2: a sound or vibration to trigger them. You sparingly definitely.
Speaker 1: Okay, so we've got menus, alerts, notifications. What about handling
Speaker 1: direct touch on the screen and tapping into all those
Speaker 1: sensors phones have, right.
Speaker 2: Making the app physically responsive. The book covers touchscreen and
Speaker 2: sensors quite well. For the basics simple clicks and long
Speaker 2: presses you'd use on click listener and on long click listener.
Speaker 2: You can set these up in your Java colon code
Speaker 2: or even directly in the XML layout using the Android
Speaker 2: dot on click attribute. For simple cases, any of you
Speaker 2: could have these listeners.
Speaker 1: And for more complex gestures swiping, pinching.
Speaker 2: For common gestures like detecting swipes, flings, double taps, single taps,
Speaker 2: the gesture detector compact class from the support library was
Speaker 2: the way to go. It's simplified detecting these standard motions
Speaker 2: for multi touch, specifically pinched to zoom, there was scale
Speaker 2: gesture detector. It would track two fingers and provide you
Speaker 2: with a scale factor indicating how much the user was
Speaker 2: trying to zoom in or out. You'd then use that
Speaker 2: factor to resize an image or map for example.
Speaker 1: Okay, and that common pattern pulling down to refresh a list.
Speaker 2: Ah, yes, swipe to refresh. That was made much easier
Speaker 2: with the swipe refreshed layout widget. You just wrap your
Speaker 2: list view like a blist view or recycle view inside
Speaker 2: this layout, set up a listener and it would handle
Speaker 2: detecting the pull gester and showing the standard refresh indicator
Speaker 2: for you much less boilerplate code.
Speaker 1: Nice. Now beyond the screen, what about sensors, accelerometer, compass.
Speaker 2: Yeah, The Android sensor framework opened up a lot of
Speaker 2: possibilities for context to wear apps. First, you could query
Speaker 2: the sensor manager to see what sensors were actually available
Speaker 2: on the specific device accelerometer, gyroscope, light sensor, magnetic field sensor,
Speaker 2: proximity sensor, et cetera. Not all devices had all sensors right,
Speaker 2: you had to check first definitely. Then to get data,
Speaker 2: you'd register a sensor event listener. This listener has a
Speaker 2: callback method on sensor changed, which gets called repeatedly by
Speaker 2: the system whenever there's a new sensor data. It provides
Speaker 2: a sensor event object containing the actual values.
Speaker 1: And the cookbook had an example.
Speaker 2: It did a really neat one creating a simple compass.
Speaker 2: It showed how to get data from both the magnetic
Speaker 2: field sensor and the accelerometer. Then you'd use methods like
Speaker 2: sensor manager dot get rotation matrix and sensor manager dot
Speaker 2: get orientation to combine that data and calculate the device's
Speaker 2: orientation relative to magnetic.
Speaker 1: North and use that to rotate a compass needle image.
Speaker 2: Exactly, you'd update the rotation of an image view showing
Speaker 2: a compass needle based on the calculated orientation angles. A
Speaker 2: great practical example of you use using sensor.
Speaker 1: Fusion cool and finally just basic device orientation portrait versus landscape.
Speaker 2: Yep. You can easily check the current configuration for configuration
Speaker 2: dot orientation landscape or orientation portrait. The book also mentioned
Speaker 2: using Android dot config changes in the manifest to prevent
Speaker 2: the default activity recreation on orientation changes, but strongly cautioned
Speaker 2: that this was usually not the right approach. It was
Speaker 2: better to handle the recreation properly with state.
Speaker 1: Saving right avoiding the life cycle rather than handling it.
Speaker 2: Got it.
Speaker 1: Okay, we've covered a huge amount on the UI and interaction,
Speaker 1: but apps need data and they need to connect. This
Speaker 1: next bit seems crucial. How did developers manage data storage
Speaker 1: and network communication back in twenty sixteen? It sounds complex,
Speaker 1: It really was, and.
Speaker 2: This segment highlights the challenge of doing it efficiently and
Speaker 2: reliably on mobile and reads the question how do these
Speaker 2: cookbook solutions scale? The book lays out the main data
Speaker 2: storage options available.
Speaker 1: Then what were they?
Speaker 2: First? You had shared preferences, super simple key value storage
Speaker 2: for private primitive data I think user settings, maybe log
Speaker 2: in token, easy to use for small bits.
Speaker 1: Of data, okay, like a little settings file exactly.
Speaker 2: Then internal storage. This was for saving private files directly
Speaker 2: to the device's internal memory. Other apps couldn't access these files,
Speaker 2: and they got deleted automatically if the user uninstalled your app.
Speaker 2: The downside usually less space available compared to external storage,
Speaker 2: but it's always there.
Speaker 1: And external storage the SD card usually.
Speaker 2: Right or simulated external storage. This was for files you
Speaker 2: might want the user to access directly, or larger files
Speaker 2: could be public or private within your app specific external folder.
Speaker 2: The big caveat external storage might not always be available.
Speaker 2: If the user mounted the device as USD storage on
Speaker 2: a computer or move the SD card, your app couldn't
Speaker 2: access it. You always had to check its.
Speaker 1: State permissions needed for that too.
Speaker 2: I bet write external storage and re external storage.
Speaker 1: Okay, what about more structured data, not just key value pairs.
Speaker 2: That's where squad database came in. Android has built in
Speaker 2: support for Squily. It provided a private relational database for
Speaker 2: your app. Great for storing lots of structured data, contacts, inventory,
Speaker 2: game scores, anything complex. You could even expose this data
Speaker 2: to other apps securely using something called the content provider,
Speaker 2: but mostly it was for internal app data.
Speaker 1: The standard for local databases then.
Speaker 2: Yeah. Lastly, lastly, the book broadly mentions cloud storage, basically
Speaker 2: saving data off the device, either to your own private
Speaker 2: servers or using third party cloud service providers.
Speaker 1: Gotcha, So focusing on files for a moment, how did
Speaker 1: developers actually read and write files? Maybe manage temporary data?
Speaker 2: Standard java file io, mostly using file input stream. File
Speaker 2: input stream often wrapped with buffer reader or print writer
Speaker 2: for text files. The cookbook showed examples for both internal
Speaker 2: and external storage. For temporary data, there was a dedicated
Speaker 2: cash directory you could get via getcash dear. The idea
Speaker 2: was you put temporary files here, and the Android system
Speaker 2: was free to delete these files if the device started
Speaker 2: running low on storage, so you couldn't rely on cash
Speaker 2: files persisting important distinction.
Speaker 1: What about including files directly in the app package, like
Speaker 1: audio clips or maybe some data files?
Speaker 2: Two main ways for that. You could put files in
Speaker 2: the reservo folder. These were treated like other resources. They
Speaker 2: got a resource ID or brought up idio. Android verified
Speaker 2: the existed a compile time, and you access them via
Speaker 2: that ID. Good for things like media files okay, and
Speaker 2: the other way the assets folder. Files placed here were
Speaker 2: compiled into the APK as well, but they didn't get
Speaker 2: resource IDs. You access them more like a traditional filesystem,
Speaker 2: using their file names via the asset manager. This was
Speaker 2: useful if you needed to access files by dynamically generated names,
Speaker 2: or if you were using a library that expected filepaths
Speaker 2: instead of resource IDs. The trade off was less compile
Speaker 2: time safety.
Speaker 1: Right. Okay, let's dive deeper into secollite. That seems like
Speaker 1: a core piece. How did the cookbook approach actually using
Speaker 1: the database, creating adding data?
Speaker 2: It focused heavily on the practical cr rout operations create, read, update, delete.
Speaker 2: The main tool for managing the database was the slee
Speaker 2: out open helper class.
Speaker 1: That's quite open helper It's subclass.
Speaker 2: This helper it had methods like on create, where you'd
Speaker 2: define your initial database schema that create table statements, and
Speaker 2: on upgrade, where you'd put logic to handle migrating data
Speaker 2: if you change your schema in a future app update.
Speaker 2: This was managed by incrementing the database version constant ah.
Speaker 1: Managing those schema changes is always.
Speaker 2: Tricky, always. The helper simplified it somewhat. The cookbook used
Speaker 2: a simple dictionary database example words and definitions to show
Speaker 2: how to insert new words, query for definitions, update entries,
Speaker 2: and delete them using methods on the squad day database
Speaker 2: object you got from the helper. It also pointed out
Speaker 2: an important convention, including an integer primary key column named ID.
Speaker 2: This wasn't strictly required by Scorelight, but many Android framework classes,
Speaker 2: especially UI adapters like simple cursor adapter expected it, so
Speaker 2: it was best practice.
Speaker 1: Good tip. Now, database queries can be slow. Doing that
Speaker 1: on the main UI thread is bad right leads to freezes.
Speaker 2: Absolutely a cardinal sin and and or development. Blocking the
Speaker 2: main thread leads to sluggishness and potentially the dreaded application
Speaker 2: not responding anur dialogue.
Speaker 1: So how did they handle background database access cleanly? Back then, the.
Speaker 2: Recommended approach in the cookbook, especially for loading data to
Speaker 2: display in the UI, was using loaders, yes, specifically cursor
Speaker 2: loader for database queries. Loaders were part of the Android
Speaker 2: framework designed to simplify asynchronous data loading. The big benefits
Speaker 2: were they automatically performed the database query on a background thread,
Speaker 2: so the UI thread wasn't blocked, and if you were
Speaker 2: using them with a content provider, they could automatically monitor
Speaker 2: the underlying data source for changes and reload the data
Speaker 2: to update the UI, although without a content provider you
Speaker 2: might need to manually trigger a reload.
Speaker 1: So they handled the background thread and delivering results back
Speaker 1: to the UI thread exactly.
Speaker 2: You'd implement loadermanager dot loader callbacks. The on create loader
Speaker 2: method would create and return your cursor latter specifying the query.
Speaker 2: The loader did the work in the background. Then the
Speaker 2: onload finished callback, which ran on the UI thread, would
Speaker 2: deliver the resulting data a cursor in this case, ready
Speaker 2: for you to update your UI adapter. It abstracted away
Speaker 2: a lot of the threading complexity.
Speaker 1: Okay, that sounds much better than raw threads shifting gears.
Speaker 1: Now to communication off the device, what about interacting with
Speaker 1: phone features like calls and SMS.
Speaker 2: Apps could definitely do that, though it required specific permissions.
Speaker 2: For making a phone call, you'd use an intent with
Speaker 2: the ax that you would call action and the phone number.
Speaker 2: Pretty straightforward, but needed the gellphone permission.
Speaker 1: And could you listen for call events like know when
Speaker 1: a call ends.
Speaker 2: Yes, you could create a phone state listener and register
Speaker 2: it with the Telephony Manager. This listener had callbacks for
Speaker 2: various state changes, including running off hook and IDOL call ended.
Speaker 1: Okay.
Speaker 2: Sending SMS for SMS, you'd use the SIMS manager get
Speaker 2: the default instance, then call, send text message, passing the
Speaker 2: destination number, message body, etc. Required the send SMS permission.
Speaker 2: The book even mentioned handling long messages using divide.
Speaker 1: Message and receiving SMS.
Speaker 2: That involves setting up a broadcast receiver You'd declare it
Speaker 2: in your manifest with an intent filter for the Android
Speaker 2: Dot provider telefany dot SMS received action and request the
Speaker 2: receives MS permission. When an SMS arrived, your receiver's on
Speaker 2: receive method would be called with the message details. Pretty
Speaker 2: low level access to core functions definitely okay.
Speaker 1: Broader network stuff displaying web content or checking if the
Speaker 1: phone is online.
Speaker 2: Web and network communication yeah. Essential for just displaying web
Speaker 2: pages within your app. WebView is the component you could
Speaker 2: load URLs, html, strings, whatever. A key part was using
Speaker 2: a WebView client. By setting your own client, you could
Speaker 2: intercept page navigation. For example, you could force links clicked
Speaker 2: within the WebView to open in the same WebView rather
Speaker 2: than launching an external browser, keeping the user within your
Speaker 2: app up. You could even restrict navigation to only specific domains.
Speaker 1: Making it feel more integrated. And just checking connectivity yep, you'd.
Speaker 2: Use the Connectivity Manager system service. You could get the
Speaker 2: active network info object and check if it was connected
Speaker 2: and its type Wi Fi mobile. This required the Internet
Speaker 2: and access network state permissions, crucial before attempting any network
Speaker 2: operation right now.
Speaker 1: The cookbook mentioned a library called Volley as a new
Speaker 1: option back in twenty sixteen for network requests, What was
Speaker 1: the deal with Volley?
Speaker 2: Ah? Volley. Yes, it was introduced by Google and positioned
Speaker 2: as a simpler way to handle common network operations compared
Speaker 2: to using HTTPURLA connection directly, which involved a lot of
Speaker 2: boil play.
Speaker 1: Code, so it simplified things it did.
Speaker 2: It managed a request queue and a threadpool defaulting to
Speaker 2: four threads, automatically handled basic response caching to disc transparently,
Speaker 2: and even allowed setting priorities for requests.
Speaker 1: Sounds good? What was it best for?
Speaker 2: The book highlights that Volley really shown for making law?
Speaker 2: What's small network requests efficiently? Think fetching Jason data for
Speaker 2: a list or downloading images as a user scrolls. It's
Speaker 2: built in support for string Jason and image requests made
Speaker 2: these common tasks much easier.
Speaker 1: So what were the downsides? The limitations?
Speaker 2: The big one mentioned was that Volley was explicitly not
Speaker 2: recommended for large downloads or streaming operations. Why not because
Speaker 2: it processed and parsed the entire response in memory. Trying
Speaker 2: to download a huge file or stream video with Volley
Speaker 2: would likely lead to out of memory air crashes. It
Speaker 2: just wasn't designed for that. It also had mechanisms for
Speaker 2: canceling requests using tags, which was important to avoid wasting
Speaker 2: bandwidth if the user navigated away.
Speaker 1: So a great tool for specific use cases, but not
Speaker 1: a silver bullet for all networking. That's a really important insight. Okay,
Speaker 1: we've covered data and connectivity. Now for the final stretch
Speaker 1: getting the app ready for the real world, polishing it,
Speaker 1: maybe connecting to back end services. What did the cookbook
Speaker 1: say about app readiness?
Speaker 2: Yeah, and this section really touches on some critical aspects
Speaker 2: and it raises that question again, how much of this
Speaker 2: twenty sixteen wisdom still applies directly and where have things
Speaker 2: fundamentally shifted. One huge shift discussed was the Android six
Speaker 2: point zero run time permission.
Speaker 1: Model, Right, that was a massive change. Before that, you
Speaker 1: just accepted all permissions when installing the app, didn't you exactly?
Speaker 2: It was all or nothing. If you didn't like one
Speaker 2: permission and app asked for, your only choice was to
Speaker 2: not install it. Android six point zero API twenty three
Speaker 2: change that completely. Users could now grant or deny permissions
Speaker 2: individually at the time the app actually needed them, not
Speaker 2: upfronted installation, and they could even revoke permissions later through
Speaker 2: the system settings.
Speaker 1: Huge win for user privacy and control, But what did
Speaker 1: it mean for developers?
Speaker 2: It meant a significant code change. Developers now had to
Speaker 2: explicitly check if they had a permission using check self permission.
Speaker 2: If not, they often needed to show some rationale to
Speaker 2: the user explaining why the permission was needed. That was
Speaker 2: should show request permission rationale, and then they had to
Speaker 2: actually request the prom mission using request permissions and handle
Speaker 2: the user's response grant or deny in a callback.
Speaker 1: So a lot more interactive permission handling needed.
Speaker 2: Definitely. It forced developers to be more thoughtful about the
Speaker 2: permissions they requested and when they requested them. A big
Speaker 2: step change, but only affected apps running on Android six
Speaker 2: point zero plus devices targeting that EPI level or higher.
Speaker 1: Okay, what about tasks that needed to run periodically, maybe
Speaker 1: even when the app wasn't running, like checking for updates
Speaker 1: every few hours.
Speaker 2: That was the domain of the alarm manager. You'd use
Speaker 2: it to schedule your app to be woken up at
Speaker 2: specific times or intervals to perform tasks. The key benefit
Speaker 2: was that the OS managed the scheduling. Your app didn't
Speaker 2: need to be constantly running in the background, consuming resources.
Speaker 2: Just to wake up. Occasionally the OS would wake it
Speaker 2: up via intent when the alarm fire.
Speaker 1: What kinds of alarms were there?
Speaker 2: There were different types based on the clock used. OURTC
Speaker 2: used the real time clock wall clock time, while elapsed
Speaker 2: real time use the time since the divis I booted,
Speaker 2: and there were wake up versions of both which would
Speaker 2: actually wake the device CPU if it was asleep when
Speaker 2: the alarm fired. Non wake up alarms would only fire
Speaker 2: the next time the device woke up for some.
Speaker 1: Other reason, and the cookbook had best practices.
Speaker 2: Yes, keep alarms in frequent, avoid using wake up alarms
Speaker 2: unless absolutely necessary to conserve battery, and use inexact timing
Speaker 2: where possible to allow the system to bash alarms together
Speaker 2: again for battery efficiency.
Speaker 1: Did alarm survive reboots?
Speaker 2: Crucially, no alarm manager alarms were cleared when the device rebooted.
Speaker 2: If your app needed persistent scheduled tasks, it had to
Speaker 2: include a broadcast receiver that listened for the action boot,
Speaker 2: completed broadcast, and reschedule its alarms every time the device
Speaker 2: started up. A common gotcha.
Speaker 1: Ah Okay, now what about that fundamental problem of doing
Speaker 1: long running work without freezing the UI we mentioned loaders
Speaker 1: for data, But what about other background tasks?
Speaker 2: The classic solution, presented in a twenty sixteen cookbook was
Speaker 2: acing task Acing task.
Speaker 1: Still hear about that one, often not in a good way.
Speaker 2: Yeah, yeah, it has a mixed reputation now, But back
Speaker 2: then it was a standard, relatively simple way to handle
Speaker 2: background work with UI updates. The problem it solves was
Speaker 2: clear doing network requests, heavy calculations, or anything slow on
Speaker 2: the main UI thread caused the app to hang, leading
Speaker 2: to an RS. The rules were simple, don't block the
Speaker 2: main thread, do all UI updates on the main thread.
Speaker 1: So how did acy task help?
Speaker 2: It provided a simple structure. You'd override do end background,
Speaker 2: which ran on a background worker thread. That's where you
Speaker 2: put your long running code. When doing background finished, it
Speaker 2: could return a result. Then on post execute, which automatically
Speaker 2: ran back on the main UI thread, received that result,
Speaker 2: allowing you to safely update your UI like showing the
Speaker 2: downloaded data or hiding a progress bar. It also had
Speaker 2: on pre execute UI thread before and on progress update
Speaker 2: UI thread for progress.
Speaker 1: Sounds straightforward enough, What were the catches? Why the bad reputation? Now?
Speaker 2: The main issue hinted at even in the cookbook was
Speaker 2: its type coupling with the activity or fragment that started it.
Speaker 2: If you started an acing task from an activity and
Speaker 2: the user rotated the screen, destroying and recreating the activity
Speaker 2: before the task finished, uh oh yeah, the acing task
Speaker 2: might hold an implicit reference to the old destroyed activity context.
Speaker 2: This could lead to memory leaks, and if the task
Speaker 2: tried to update the UI on post execute, it could
Speaker 2: crash because the activity was trying to update didn't exist anymore,
Speaker 2: or it updated the wrong instance it created.
Speaker 1: These orphan tasks so convenient, but fragile if not handled
Speaker 1: very carefully.
Speaker 2: Extremely That's why the book suggested maybe using it with fragments,
Speaker 2: specifically retained fragments or loaders as potentially safer alternatives for
Speaker 2: handling background tasks tied to UI life cycles. Modern Android
Speaker 2: uses core routines, RX Java or work Manager, which handle
Speaker 2: life cycles much more elegantly.
Speaker 1: Makes sense. What about other advanced features voice input, push messages.
Speaker 2: Yeah, the cookbook touched on those two. Speech recognition was
Speaker 2: possible using the Google Speed service available since Android two
Speaker 2: point two ap eight. You'd launched an intent to start
Speaker 2: the voice recognizer and get the results back. For push notifications,
Speaker 2: the standard back then was Google Cloud Messaging GCM.
Speaker 1: GCM before FCM, firebased Cloud Messaging.
Speaker 2: Exactly, GCM was the predecessor. The architecture involved three parts,
Speaker 2: your application server, Google's GCM servers, and the Android device
Speaker 2: running your app. The flow was your app registers with
Speaker 2: GCM servers to get a unique device registration token. Your
Speaker 2: app sends this token to your back end server. When
Speaker 2: your server wants to send a push message, it sends
Speaker 2: the message content and the token to Google's GCM server.
Speaker 2: GCM then handles delivering that message down to the correct.
Speaker 1: Device and the app received it.
Speaker 2: Yes, the app needed to implement specific services, an instance
Speaker 2: I listener service to handle token generation and refresh, and
Speaker 2: a GCM listener service with an on message received callback
Speaker 2: to actually handle incoming push messages. It worked back to
Speaker 2: API eight.
Speaker 1: Okay and letting users sign in easily.
Speaker 2: Google sign in was becoming common. It allowed users to
Speaker 2: sign into your app using their existing Google accase out,
Speaker 2: avoiding the need for them to create yet another username
Speaker 2: and password. It involved using the Google app a client,
Speaker 2: a central entry point for Google APIs back then, and
Speaker 2: adding a standard sigin button to your layout. Once signed in,
Speaker 2: you could access basic profile info like their name, email, photo, url, etc.
Speaker 2: With their permission, of.
Speaker 1: Course, streamlining log in okay. Finally, the cookbook looked at
Speaker 1: back end as a service BASH options. What was the
Speaker 1: idea there?
Speaker 2: The idea was simple, Building and maintaining your own server
Speaker 2: back end for an app is hard work. You need
Speaker 2: server infrastructure, databases, user management, APIs. It's a lot. BASS
Speaker 2: providers offered a shortcut. They provided ready made back end infrastructure,
Speaker 2: cloud databases, user authentication, push notification services, file storage, serverless functions,
Speaker 2: all accessible via NS. That was the pitch. Focus on
Speaker 2: the front end experience, let the BASS handle the back
Speaker 2: end heavy lifting. The cookbook compared several providers available in
Speaker 2: twenty sixteen based on things like their free tiers, monthly users,
Speaker 2: API calls, features like push support and storage limits.
Speaker 1: Who are some of the players back then?
Speaker 2: The book detailed setup for a few app forty two
Speaker 2: which seemed focused on games, back endless offering, MBS hosting,
Speaker 2: APIs Buddy focusing on device sensors, Kinvey one of the
Speaker 2: earlier big players, and notably.
Speaker 1: Firebase AH Firebase, which Google had recently acquired around that time.
Speaker 2: Exactly Firebase was highlighted particularly for its real time auto syncing,
Speaker 2: database authentication, and hosting. Its acquisition by Google signaled a
Speaker 2: big push into this bast space. Each provider had slightly
Speaker 2: different strength set of processes. Some used MAVE and GRADEL,
Speaker 2: others needed manual library inclusion and pricing models. It really
Speaker 2: represented an emerging alternative to DIY back ends.
Speaker 1: Wow, we've really journeyed back to twenty sixteen ANDREID development.
Speaker 1: We've taken this deep dive into the Android Application Development
Speaker 1: Cookbooks second Edition, giving you hopefully a really comprehensive tour.
Speaker 1: We explored everything from those fundamental activities and intents, the
Speaker 1: nuts and bolts of UI design with layouts, styles, themes,
Speaker 1: the complexities of data management and life cycle, all those
Speaker 1: user interaction points like menus and notifications, right through to
Speaker 1: app readiness concerns like run time permissions, background tasks with
Speaker 1: ACYNC task and that emerging world of back end as
Speaker 1: a service. We really hope this deep dive has given
Speaker 1: you more than just a history lesson, maybe a shortcut
Speaker 1: to being well informed about a really pivotal time and
Speaker 1: Android's evolution, and maybe spark some aha moments about the
Speaker 1: core principles that while still drive a lot of mobile
Speaker 1: development today, even if the tools look different. It's honestly
Speaker 1: fascinating to see how many of those fundamental recipes from
Speaker 1: twenty sixteen laid the groundwork, even with all the changes since. So,
Speaker 1: as you think about everything we discussed today from twenty sixteen,
Speaker 1: you know, wrestling with the activity life cycle manually, the
Speaker 1: pitfalls of async task, the early days of malaysious, what
Speaker 1: foundational concepts do you think still ring true, maybe as
Speaker 1: core design principles, and which parts feel completely alien now
Speaker 1: totally revolutionized or abstracted away in modern Android development? And
Speaker 1: maybe think about this, what recipes would be absolutely essential
Speaker 1: in an Android application development cook book if it were
Speaker 1: published to day. What would be the chapter headings reflecting
Speaker 1: the biggest shifts and the most critical techniques developers need
Speaker 1: to master now compared to back in twenty sixteen,