In this series of tutorials, we are learning about Android development from scratch and getting acquainted with the basic concepts and practices you need to know in order to start working on the platform. So far we have looked at various parts of an Android project, including its resources. In this tutorial, we will explore the project manifest file.
What Is the Manifest File?
Any app that you develop in Android will need a manifest file. This manifest file contains a lot of information related to your app. Keep in mind that the only valid name for a manifest file is AndroidManifest.xml. A manifest file with any other name won't be recognized by Android Studio.
The location of the AndroidManifest.xml file depends on the current perspective in Android Studio. The image below shows the application files with "Android" perspective and with "Project" perspective.
The manifest for a project can be simple or extremely complex, depending on what the app does. We will look at the parts of the manifest you need to know about for all apps and will examine those optional parts you'll need for future projects.
The manifest file can contain many elements and attributes. See the Android Developer Guide for links to all of them. The manifest serves several purposes. It specifies the app package, provides a formal description of the app components, and declares permissions, required API levels, and linked libraries.
We have discussed common Android app components in another tutorial of the series. These components include activities, services, content providers, and broadcast receivers. All of them need to be declared in the app manifest to be visible to the system. Otherwise, they remain invisible to the system and can't be started or activated when needed.
Similarly, the app manifest file needs to declare all the permissions that your app might need in order to access sensitive data or protected features like contact information and camera access. Not declaring these permissions will result in failure when accessing those features or content.
Another important thing that has to be mentioned in the app manifest is the hardware and software features that are required by your app. Google uses this information to only show your app on compatible devices. This results in a good user experience because an app that requires a camera will lose some or all of its functionality on non-camera devices.
We will only run through the most essential elements and attributes you can list in the manifest, so be aware that more elements are possible and that there may be additional attributes you can use with the elements we do cover.
Opening the Manifest File
Before we can learn what content goes into a manifest file, we should be able to find and open it first. The location of the manifest file will depend on the perspective that you have set in Android Studio.
With the default Android perspective, the AndroidManifest.xml file can be found under app/manifests, and with the Project perspective, the AndroidManifest.xml file will be under app/src/main. You can see them both in the image below.
Click on the file name and you will see something like the following XML:
1 | <?xml version="1.0" encoding="utf-8"?> |
2 | <manifestxmlns:android="https://schemas.android.com/apk/res/android" |
3 | xmlns:tools="http://schemas.android.com/tools" |
4 | package="com.tutsplus.emptyactivity"> |
5 | |
6 | <application |
7 | android:allowBackup="true" |
8 | android:dataExtractionRules="@xml/data_extraction_rules" |
9 | android:fullBackupContent="@xml/backup_rules" |
10 | android:icon="@mipmap/ic_launcher" |
11 | android:label="@string/app_name" |
12 | android:roundIcon="@mipmap/ic_launcher_round" |
13 | android:supportsRtl="true" |
14 | android:theme="@style/Theme.EmptyActivity" |
15 | tools:targetApi="31"> |
16 | <activity |
17 | android:name=".MainActivity" |
18 | android:exported="true"> |
19 | <intent-filter> |
20 | <actionandroid:name="android.intent.action.MAIN"/> |
21 | |
22 | <categoryandroid:name="android.intent.category.LAUNCHER"/> |
23 | </intent-filter> |
24 | </activity> |
25 | </application> |
26 | |
27 | </manifest> |
Android Studio automatically adds some boilerplate content and other elements to your manifest file based on the data you provided while creating the project. The above XML was generated when I created a project with an Empty activity.
Project Manifest vs. Merged Manifest
Once you have opened the manifest file, you will see two tabs at the bottom. They are named Text and Merged Manifest. The Text tab is selected by default, and it shows you the content of the AndroidManifest.xml file.
Select the Merged Manifest tab, and you will see something similar to the following image:
On the right of the merged manifest, you will see some information about the generation of the merged file—for example, the source files used to generate the merged manifest and a merging log to show how the final value of a merged element or attribute was determined.
From the above image, you can see that some new information was added in the merged manifest, while other information was removed. We will take a deeper look at these elements in the next few sections.
1. Manifest Element
As I mentioned earlier, the elements that appear in the manifest file initially have been populated by Android Studio when you created the project. These are only sufficient for the needs of very simple apps, and in most cases you will need to add to the manifest as you build your projects. The root element in the file is the manifest
element:
1 | <manifestxmlns:android="http://schemas.android.com/apk/res/android" |
2 | xmlns:tools="http://schemas.android.com/tools" |
3 | package="com.tutsplus.emptyactivity"> |
Android Studio populates the manifest
element attributes with the package
name you chose when creating the project. We also use the xmlns:android
and xmlns:tools
attributes to define our XML namespaces.
The manifest
element has the following attributes in its merged state:
1 | <manifest |
2 | android:versionCode="1" |
3 | android:versionName="1.0" |
4 | package="com.tutsplus.emptyactivity" |
5 | xmlns:android="http://schemas.android.com/apk/res/android"> |
The merged manifest
element contains additional information. The version code and name are set to 1 and 1.0 initially. When you release your app to the Play store and then release subsequent updates, you need to update these numbers for each new release.
The version name is what users see when your app is listed in the Play store, so you can use whichever version naming convention you like. Users don't see the version code, and it must be a higher number for each release, although it does not have to increment by one each time. If you attempt to upload a new version of an app to Google Play and the version code is not higher than the current version, Play will not allow the upload.
You might also have noticed that the reference to the xmlns:tools
attribute has been removed from the manifest element. The attributes in the tools
namespace are meant to enable some design-time and compile-time features. These attributes are automatically removed when you build your app to create an APK file. As a result, the performance and size of your app stay the same.
2. Uses SDK Element
First, inside the manifest
element, you should see the uses-sdk
element:
1 | <uses-sdk |
2 | android:minSdkVersion="21" |
3 | android:targetSdkVersion="32"/> |
The uses-sdk
element attributes define the minimum required API level as well as a target level you plan on testing the project against. You might have noticed that the uses-sdk
element is only visible in the merged manifest. Recall that we chose these values when we created the app. The values for minSdkVersion
and targetSdkVersion
are taken from the value we supplied when completing the project setup.
You can change these in the manifest after project creation if any such need arises. For example, you may find that you need to use an aspect of the platform that is not available at your chosen API level. If you change SDK versions, Android Studio rebuilds your project.
Users with devices running an API level lower than the specified minimum will not be able to download and install your app. Listing an API level as a target is an indicator that you have tested the app on that version. For reliability, you should test your apps on as many API levels as possible.
Not specifying a value for minSdkVersion
signals that your app is compatible with all versions of Android. If your app doesn't actually support all Android versions, it will crash on the lower API levels during runtime. Make sure you specify this value for a good user experience.
There is also a maxSdkVersion
attribute, but you shouldn't normally use it as new Android versions are fully backward-compatible by design. Any apps will keep working as expected on newer Android versions as long as you have only used standard APIs and followed development best practices.
3. Application Element
Android Studio also inserts an application
element in your manifest. The element supports a lot of attributes and can contain child elements that declare an application's components. We already have a tutorial about Android App Components if you are not familiar with the term. For the moment, let's look at the opening tag of the element with its default values in the AndroidManifest.xml file:
1 | <application |
2 | android:allowBackup="true" |
3 | android:dataExtractionRules="@xml/data_extraction_rules" |
4 | android:fullBackupContent="@xml/backup_rules" |
5 | android:icon="@mipmap/ic_launcher" |
6 | android:label="@string/app_name" |
7 | android:roundIcon="@mipmap/ic_launcher_round" |
8 | android:supportsRtl="true" |
9 | android:theme="@style/Theme.EmptyActivity" |
10 | tools:targetApi="32"> |
The main attributes to pay attention to are the icon, label, and theme items. The element can take many additional attributes. The icon attribute indicates a file in the app drawables. The default Android icon is selected, but you can add your own icon files and reference them here. The label icon also references a string in the app resources. Open the strings.xml file present under res/values. You will see the referenced string listed as follows:
1 | <stringname="app_name">Empty Activity</string> |
This should be a readable string as it is displayed to the user in various places, including the device menu, next to the launcher icon. You will typically want to alter the string to have a more meaningful application name.
Back in your manifest file, notice the application
element theme attribute. Again, this references a resource that you will find in the res/values/themes directory, so have a look there now. Switch back to the manifest again. If you later decide to define your own application styles, you can reference them in the theme attribute.
The theme attribute is useful for defining a default theme for all activities in your application. You can also override the default theme for individual app activities by setting their own theme using the activity
element's theme attribute.
The fullBackupContent
and dataExtractionRules
attributes point to XML files which specify what file format your app gets backed up or copied to respectively.
The application element contains a lot of other attributes that will prove useful in specific situations.
4. Activity Elements
Inside the application
element, you will see an activity
element for the MainActivity
class you created when you started the project. This activity
element also contains child elements, which we will look at next. Look at the opening tag first:
1 | <activity |
2 | android:name=".MainActivity" |
3 | android:exported="true"> |
The name
attribute references the class name which actually implements this activity using its fully qualified path in the app package. In our case, this would be com.tutsplus.emptyactivity.MainActivity. However, you might have noticed that AndroidManifest.xml file only contains the value .MainActivity. This shorthand way of specifying the name works as long as the first character of the name is a period.
The generated manifest file resolves the shorthand to the actual path in the app package, as you can see below:
1 | <activity |
2 | android:exported="true" |
3 | android:name="com.tutsplus.emptyactivity.MainActivity"> |
The function of the exported
attribute might not be evident by its name. We set this attribute to true when we want to make the activity launchable by and accessible to any app. The exported
attribute is set to false by default for any activities which don't have intent filters.
The main activity of the app needs to set the exported
attribute to true in order to make it launchable by the launcher app. Any activities that are started by some other app but don't have the export attribute set to true
will result in ActivityNotFoundException
being thrown.
As your apps become more complex, you will add more Activities to them, one for each screen in the UI. Each time you add a new Activity class to your app, you need to add an element for it inside the application
element, as in the following example:
1 | <activity |
2 | android:name=".About" |
3 | android:label="@string/about_label"> |
4 | </activity> |
The label allows you to control what appears as the window title when the Activity is on screen. By default, it is the same as the app name, so you can leave it as is in most cases. Since we skipped specifying a label for our Main activity, its value will be taken from the application
element. On the other hand, the About activity will have its name set according to the referenced string resource.
5. Intent Filters
Inside the main activity
element, you will see an intent-filter
element:
1 | <intent-filter> |
2 | <actionandroid:name="android.intent.action.MAIN"/> |
3 | <categoryandroid:name="android.intent.category.LAUNCHER"/> |
4 | </intent-filter> |
The Intent Filter describes what Intents the parent activity
can respond to. On Android, an Intent is a data object that is passed to an Activity when it starts. When you launch one Activity from another within your apps, you will use Intents, but they can also be passed between apps.
The Intent Filter for the MainActivity
indicates that it should start when the app is launched. It does this using the action
element, which lists the MAIN action. The category
element describes the Intent Filter by category name, in this case LAUNCHER. Both of these in conjunction specify that your app should use the parent activity of the internet filer as its main entry point, and that this entry point should be used when the app is launched.
Android defines some standard actions and categories by default.
Intent Filters can contain many child elements, including data specifications. For more information, see the Intent and Intent Filters section in the Android Developer Guide. The activity
element can contain additional child elements alongside intent-filter
such as data
, which can define a name-value pair of data items.
6. Uses Permission
Android Studio includes all the elements that we have discussed so far inside your AndroidManifest.xml file by default. Let's now look at some others you may need in future projects.
The uses-permission
element allows you to request permission for your app to do certain things. This includes things like accessing the saved contacts, the location data, the device camera, the device microphone, etc. When users view your app in the Play store, the permissions will be displayed to them before downloading the app. If they choose to go ahead, they must accept the permissions so that your app can run.
Permissions you must request in the manifest include using Internet data, writing to external storage, and accessing device features such as the camera. The following example demonstrates this concept:
1 | <uses-permissionandroid:name="android.permission.INTERNET"/> |
There are several potential permissions your apps can request. See the Manifest.Permission page on the API reference.
Some permissions are classified as dangerous either to improve security or privacy. In either case, you are required to ask for these dangerous permissions at runtime on devices that run Android 6.0 (API level 23) or higher. With the help of the uses-permission-sdk-23
element, you can tell Android only to request the permission if the app is running a device with API level 23 or higher.
Permissions can be broadly categorized into two groups. The first group consists of permissions like reading the contact data or image files which are basically related to software. The second group consists of permissions like using the camera and recording audio which require some kind of hardware to work. If your app requires the camera permission, it is filtered in the Play Store and hidden from devices which don't have a camera.
7. User Devices
A better way to control the filtering of apps on the Play Store is to explicitly specify the hardware features that you are going to use with the help of the uses-feature
element. In the uses-feature
element, you can list a single feature required in either hardware or software, using the feature name and a Boolean flag. These features include Bluetooth and camera options such as flash, location detection, and sensors.
1 | <uses-featureandroid:name="android.hardware.camera"android:required="true"/> |
Explicitly specifying that you are going to use a piece of hardware takes the guesswork out of the equation. Setting the value of the required
attribute to true
implies that the app cannot function without this particular feature. Setting it to false
implies that the app would still work without the feature, but it's nice to have it.
A range of manifest elements can be used to describe other required hardware and software features for an app. These include the uses-configuration
element, in which you can specify requirements for the navigation, keyboard, and touchscreen options. The supports-screens
element lets you define screen sizes supported by your app, specifying attributes related to both size and density.
8. Other Elements
The elements we've explored are the ones you're most likely to use for your initial apps. However, there are other elements used in different types of applications. The initial project we created is for a standard app launched through the user menu and presents one or more Activity screens to the user. Other types of apps include widgets and applications running ongoing background processes, handling data access, and receiving system announcements.
Apps using background processing typically do this using Service
classes on Android. This requires listing the service
element in the manifest, one for each Service
class, as with Activities. Content Providers in Android apps are responsible for managing access to a data source. These are listed using the provider
element. Finally, the receiver
element is listed in the manifest file if an app wants to receive Intents from other apps or from the system itself.
Conclusion
We've covered the essential features of the manifest file in Android apps. Each time you create an app, Android Studio populates the file with the main elements you need to start with. As you build functionality into the app, you will continually add content to the manifest to ensure the app as a whole can function. When you encounter problems running your apps on actual or virtual devices during development, this will sometimes be due to a missing element in the manifest.
In the next part of the series, we will look at how Android apps store and access data.