The App Manifest
Every Android app has an app manifest. It’s important because it tells an Android device everything it needs to know about your app.
Think of it as an instruction manual about your app for the Android system. It contains essential information like the app’s components (activities, services, etc.) and their configurations.
Android is strict about its requirements for a manifest. The file name must be AndroidManifest.xml, and it has to be located in the correct spot in the project file hierarchy. Without this file, Android refuses to run your app.
On the left side of Android Studio, in the Project navigator, navigate to app ▸ manifests ▸ AndroidManifest.xml.
Note: The manifests folder in the sidebar is a virtual folder generated by Android Studio’s Android project view and isn’t directly related to anything in the file system. The actual file is kept at the root of your app’s main folder inside app/src.
Also, for now, don’t worry about any warnings that appear in the manifest.
This is an XML-based file containing various tags. The main tags in this file are manifest, application, and activity, but you’ll use plenty more.
The manifest tag is the root element of the app manifest. You must declare all the other tags within this tag.
The application tag contains app-specific information for the Android system, such as the icon to use for the app, the name of the app, and what theme style it uses. This information tells Android how to present the app on the home screen and how to represent it in other areas, such as the Settings.
Activities
Perhaps the most interesting tags are the activity tags. Every activity within an app should have a corresponding tag within the manifest. This is to ensure that your app only runs activities from within your app, not any that may have come from elsewhere.
There’s a .MainActivity declared in there, with another tag, intent-filter, inside this declaration. This tells Android that MainActivity is the activity to start when the app launches.
This happens because of the action and category tags inside intent-filter. You don’t need to be concerned about the details behind these tags at the moment — you’ll learn more about intents later. What you need to know is that to set your main activity as the startup activity, you use intent-filter.
When you create a new project or use the new activity wizard, Android Studio does the difficult work of updating the manifest, so you don’t have to do this yourself.
If you prefer, you can edit the manifest manually, which you may do in the future. However, it’s best if you let Android Studio do the hard work to reduce the chance of human error.
An activity is a fundamental building block that represents a single, interactive screen within your app. It’s the core component responsible for managing the user interface (UI) and handling user interactions on that specific screen. Here’s a breakdown of what activities do:
The Foundation of Screens
- An activity is like a container that holds the UI elements (buttons, text views, images, etc.) that the user sees on a particular screen. You define these elements with “composables” — declarative UI elements using the Jetpack Compose library.
- Each activity is typically associated with a separate Kotlin class that handles the logic behind the UI, like responding to user clicks, updating data, or interacting with other parts of your app.
User Interaction and Navigation
- Activities are the focal point for user interaction. They handle user inputs like clicks, swipes, and text input. You write code within the activity class to define how the UI elements behave when the user interacts with them.
- Activities also play a crucial role in app navigation. They can launch other activities within your app to navigate to different screens or functionalities. For instance, clicking a button on the main screen might launch a new activity for viewing detailed information. If you use fragments in your app, all fragments must also be associated with an activity. However, if you are building a modern Android app using Jetpack Compose, you likely won’t have any fragments, and you may even have an app with just a single activity.
Lifecycle and System Interactions
- Activities have a well-defined lifecycle that the Android system manages. This lifecycle includes methods like
onCreate(),onStart(),onResume(), andonPause(), which are called at specific points in an activity’s lifetime (creation, becoming visible, going to the background, etc.). - You can override these lifecycle methods in your activity class to perform actions at specific points, such as fetching data when the activity starts or saving data when it goes into the background.
- The system can also pause, resume, or destroy activities based on user actions or system events (like low memory). Your activity class should handle these lifecycle changes gracefully.
In essence, an activity serves as the bridge between your app’s UI design and its functionality. It provides the visual elements and logic behind how users interact with a particular screen within your app.
Intents
To indicate work or an action your app will perform in the future, you use the Intent object. Currently, your app has only one activity. But if you were to add another, you’d use an Intent to navigate between the two of them. Intents are incredibly flexible and can perform various tasks, such as communicating with other apps, providing data to processes, or starting up another screen.
In fact, the Android system launches your app via an Intent. Remember <intent-filter> in the app manifest? The filter allows an activity to be picky about what intents it handles. In the case of your MainActivity, it only wants to handle intents that attempt to launch it.
Intents act as messengers between different parts of your app — or even between your app and other apps on the device. There are two main types of intents: implicit and explicit.
Explicit Intents
- Specificity: They’re like explicitly naming your destination. You directly specify the component (activity, service, etc.) within your app that you want to launch.
- Use case: They’re ideal for internal app navigation, where you know exactly which activity to open within your app in response to a user action.
- Example: Launching a settings activity within your app from the main activity.
Implicit Intents
- Flexibility: They’re more like describing an action you want to be performed. Instead of a specific component, you define an action (like view, edit, dial) and optionally some data (like a website URL or phone number).
- Use case: Useful for functionalities that can be handled by multiple apps. For instance, opening a link in a web browser or dialing a phone number. The system finds an app registered to handle that action and launches it.
- Example: Clicking a link in your app that opens the user’s preferred web browser to view the linked webpage.
This table summarizes the key differences:
| Feature | Explicit intent | Implicit intent |
|---|---|---|
| Specificity | High — Targets specific component | Low — Targets action |
| Use case | Internal app navigation | External actions or using other apps |
| Example | Launching a settings activity | Opening a link in a web browser |
Remember, with implicit intents, there’s a chance the user might not have an app installed to handle the action. It’s good practice to check if an app can handle the intent before launching it to avoid crashes.
For more information on intents, see the official documentation.
Content Providers
Content providers act as middlemen for managing data access between applications. They essentially create a standardized interface for sharing data securely.
Here’s a breakdown of what content providers do:
- Centralized data access: They act like a central repository for data. Your app can store its data using SQLite databases, files, or even network storage, but the content provider provides a consistent way to access it.
- Sharing with other apps: Content providers allow you to share your app’s data with other apps, if you choose to. This enables features like sharing contacts or integrating with other apps.
- Security: Content providers offer mechanisms to define data access permissions. You can control whether other apps can read, write, or modify your data.
Here are some of the benefits of using content providers:
- Standardized interface: They provide a consistent way for apps to access data, regardless of where it’s stored. This simplifies development and makes data sharing easier.
- Security: As mentioned earlier, you can define permissions to control data access. This helps protect your app’s data and user privacy.
- Interprocess communication: Content providers facilitate communication between different apps running on the same device.
Some common use cases for content providers include:
- Sharing contact information between apps.
- Enabling widgets to display data from your app.
- Integrating with cloud storage services.
- Synchronizing data with a server.
If you’re looking for a way to securely share data or enable functionalities that rely on data from other apps, content providers are a powerful tool in the Android development toolkit.
The app manifest file and content providers in Android development have a vital connection for making data accessible and secure. Here’s how they work together:
-
Declaring the provider: For your app’s content provider to be recognized by the system, you need to declare it in the manifest file using the
<provider>element. This tells the system that your app has a content provider component and provides details about it. - Permissions: You can also specify permissions in the manifest related to the content provider. This defines whether other apps can access your provider’s data and at what level (read, write, etc.). You’ll learn more about permissions in the next section, and you’ll see some examples of them in the demo.
- Authority: The manifest file is where you define the authority string for your content provider. This unique identifier helps the system recognize requests directed toward your provider’s data.
Imagine your app has a content provider for managing tasks. In the manifest, you’d declare a <provider> element with details like the provider class name and the authority string (e.g., "com.kodeco.tasks.provider"). You might also specify permissions like "read_tasks" or "write_tasks", depending on how you want other apps to interact with your data.
In summary:
- The app manifest acts as a registration point for your content provider, making it known to the system.
- It defines access permissions and the unique identifier (authority) used to access the provider’s data.
This way, when another app wants to interact with your content provider’s data, it can use the information from the manifest (authority) to send the request in the right format. The manifest ensures proper access control and helps maintain data security.
Broadcast Receivers
Broadcast receivers in Android development act as messengers that listen for system-wide events or announcements from other apps. They allow your app to stay informed and react to these events even when the app itself isn’t actively running in the foreground.
Here’s how broadcast receivers work:
-
Event listening: A broadcast receiver is a class that extends the
BroadcastReceiverclass. It contains a method calledonReceive()that gets called whenever a relevant broadcast (event) is received. - Intents and filters: Broadcasts are delivered using intents, which carry information about the event. The broadcast receiver registers its interest in specific events using intent filters. The filter defines what kind of broadcasts (events) the receiver wants to listen for.
The Role of the App Manifest
The app manifest file plays a crucial role in registering broadcast receivers and enabling them to function:
-
Declaring the receiver: You declare your broadcast receiver component within the manifest file using the
<receiver>element. This tells the Android system that your app has a receiver and provides details about it. -
Static vs. dynamic registration:
There are two ways to register a broadcast receiver:
- Static registration: Here, you declare the receiver and its intent filters directly in the manifest. This allows the receiver to listen for events even if your app isn’t running. However, there are limitations on what broadcasts you can register for statically, especially on Android 8.0 (API level 26) and higher.
-
Dynamic registration: You can register the receiver programmatically within your app’s code using the
registerReceiver()method. This offers more flexibility, but the receiver will only be active while your app is running.
In Essence
- The app manifest acts as a central point for declaring broadcast receivers and their intent filters.
- Static registration in the manifest allows receivers to be active even when the app is in the background (with limitations on Android 8.0+).
- The manifest provides information about the receiver to the system, enabling it to deliver relevant broadcasts.
Additional Points to Consider
- Permissions: You might need to declare permissions in the manifest if the broadcasts you intend to receive require accessing certain resources or data.
- Performance: While statically registered receivers offer convenience, they can impact battery life if they listen for frequent events. Consider dynamic registration or using alternative mechanisms like WorkManager for long-running tasks when appropriate.
Permissions
For security, you have to declare or request permission before using certain features on Android devices. Permissions protect access to restricted data and restricted actions.
Guess where you add permissions in an Android app? Yep, that’s right — permissions are also listed in the manifest! Permissions get added with the <permission> XML tag. Permissions are integral to security and user privacy in Android. For example, if your app wants to track a user’s location, your app would need to list one of the location services permissions in the manifest and properly request the permission from the user when appropriate.
Certain types of permissions also require asking the user to actively grant them so your app can use them.
Permissions that only need to be declared in the app manifest and are granted automatically when your app is installed are called install-time permissions. The user sees a list of the install-time permissions your app requires on its app details page in the Play Store, but they won’t get UI prompts about them from the app.
Your app might need to request some common types of permissions. For a complete and current list of all Android app permissions, refer to the permissions API reference.
For much more in-depth coverage of permissions and security in Android, see Chapters 5, “Permissions”, and 6, “Security Best Practices”, of Android App Distribution.
To add a permission to the app manifest, you use the uses-permission tag. Each permission is identified by a unique label. You’ll see an example of this in the video demo in the next section.
Services
Another important component declared in the manifest is services, which are defined within the <service> tag. You use services to implement things like processes that run in the background or communications APIs. For example, Kodeco Chat might want to fetch messages in the background even when it’s not the app currently running and then notify the user that it’s received new messages.
Foreground services perform actions the user can notice and must display a notification to the user when they run.
Background services perform things the user doesn’t directly notice, such as downloading data in the background so it’s available when the user brings the app to the foreground.
Themes
Notice the <application> tag in the manifest has the following attribute:
android:theme="@style/Theme.KodecoChat"
On a Mac, Command-click (or Control-click on a PC) @style/Theme.KodecoChat. Android Studio takes you into yet another type of resource XML file: themes.xml. Here’s a handy trick: If you mouse over the upper-left corner of Android Studio, you see an icon that looks like a target:
Click that target, and Android Studio selects the file you have open in the code editor, in the navigator pane on the left. This makes it easy to find where a particular file resides.
Here, you can see that the theme that’s been applied to this app is a subclass of a type of Material Design theme.
Summary
Well, it’s been quite the whirlwind tour of the app manifest! By now, you should have an idea of its importance and role. In the next section, you’ll get an interactive demo of how to change various parts and functionality of your app through editing the manifest.