This text only deals with Explicit Intents. Implicit Intent, Intent Filters, and Deep Links are covered in the text Android Channels.
Have you declared this activity in your AndroidManifest.xml? If you've already written a few lines of code for Android, most likely you've run into this message when opening an Activity that wasn't declared in your app's manifest file. Well, but why do we have to declare every Activity in this file? The answer would be… "Because this is how it works", but, let's go into the "hard" way and try to understand a few things about the Application Components, Intents and of course, the AndroidManifest.xml file.
Android doesn't allow an Activity to be simply instantiated and attached to the activity stack. Unlike what happens on iOS, the entire hierarchy of screens is handled by the green robot. The system also allows executing Activities from other applications, that will be in distinct tasks to your App. Therefore, for an Activity to be launched, we need to send a message to the operational system, telling the context (Context) and the class of the target activity. Such messages are called Intents.
val intent = Intent(context, SomeActivity::class.java)
startActivity(intent)
When receiving an Intent, whose purpose is to launch an Activity, or to start a Service, for example, the operating system checks in its records if any application can perform such action, whether your app and/or a third-party application. That same Intent passed to the operating system is delivered to the target component as soon as it is found. However, we may have dozens of apps installed, which would make this app-by-app search quite inefficient, so we have the use of the AndroidManifest.xml file.
Okay, one of the purposes of declaring Activities in the manifest is to inform Android that your application can perform such activities and thereby optimize the operating system's call to these screens. But how does this happen? Let's answer this question in four steps, taking as an example the installation of an App that contains only one Activity, the SomeActivity.
1
Assuming our App project is already set up, let's take a look at how our activity (SomeActivity) was declared in AndroidManifest.xml:
Example 1:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.some.package">
<application ...some parameters >
<activity android:name="com.some.package.SomeActivity"/>
</application>
</manifest>
Example 2:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.some.package">
<application ...some parameters >
<activity android:name=".SomeActivity"/>
</application>
</manifest>
In example 1, it is possible to observe that the declaration of an Activity is given by the name of its class, which includes the package that this class belongs to. We can also make this declaration in a shortened way, omitting the base package name (com.some.package) as demonstrated in example 2. In this case, the base package will be appended to the class name during the compile phase.
2
When installing our app, the operating system reads and records all data declared in the manifest, which includes:
Services, Broadcast Receivers, and Content Providers, belonging to the application components group together with Activities.
Configuration of such components, such as how an Activity will be launched for example
Intent Filters, which we talked about here
Specifications, permission requests, and some other things that can be found in the AndroidManifest documentation
3
With the app installed, when a message, Intent, is sent to the OS in the format Intent(context, SomeActivity::class.java)
, the operating system will take the class name specified in the Intent and will check which apps can open com.some.package.SomeActivity.
4
After checking which apps support running SomeActivity, which in this case would just be our app, the operating system uses the Java ClassLoader to get an instance of this screen, either by creating a new one, taking an existing one or always creating a new instance for that class, which depends on the launch strategy used. Finally, this screen is placed on top of the stack and the Intent sent is delivered to it, either in the onCreate method or in the onNewIntent method in some cases, we then have the activity presented to the user.
But what would happen if the operating system didn't find any application that supports running SomeActivity? The ActivityNotFoundException exception would be thrown, and the message "Unable to find explicit activity class {com.package/com.package.SomeActivity}; have you declared this activity in your AndroidManifest.xml?" would be visible in the Logs.
Conclusion
From a systemic viewpoint, declaring an Activity in the manifest is like subscribing to a channel, in this case, an Android channel, whose name is the class of the activity declared in the manifest. Intents are messages sent to the publisher (Android) and specify which channel should be notified, featuring the Observer pattern. There are other ways to subscribe and application components in different channels, making use of Intent Filter and Implicit Intent. Despite this, the standard way of declaring (subscribing) an Activity is mandatory.