At the simplest level, there are two different ways for apps to interact on Android: via intents, passing data from one application to another; and through services, where one application provides functionality for others to use. There are different ways to utilize both methods, depending on what you want to accomplish and what technical challenges you face. This is a brief overview and I will avoid delving into the technical aspects.
An intent describes an action to be performed, such as opening a file, dialing a phone number, or turning on airplane mode. The first two are actions that can be initiated by user apps, while the latter is a system-wide notification that any app can act on. For example, if you tap on a PDF in a file browser it will probably try to start up a document viewer app so you can read it. In this case, the file browser is using an intent to start an activity to view the file and passing the path to the file as part of the intent’s data. The system receives the intent and opens a different app that has registered with the system that it can view PDF files—or if you have multiple apps that are capable, you might be presented with a list to choose from. Additionally, should an app want to run an action in the background rather than requiring any user interaction, an intent can instead be used to start a service rather than an activity. Any app can also utilize broadcast receivers, which will listen to system-wide messages. An app might want stop trying to connect to the internet once airplane mode is engaged, so by registering a broadcast receiver with the system to listen for an intent with that specific action, the app can tell when it happens and act on it. Intents can also carry extra data via a bundle, which can handle any kind of serializable data. As the data in a bundle is stored using arbitrary keys, this is generally only useful if the receiving app knows the context for the incoming data.
One feature of a service is to perform an action in the background as mentioned above, similar to an activity but without user interface components. The other primary use of a service is to provide bindings, which lets an app expose part of its functionality to other applications. Other apps bound to the service will have a persistent connection that lets them call methods defined on the service, which can directly interact with other parts of the app. Using an example app that controls a VPN connection on the device, a service provided by the app could allow other applications to get information about the VPN connection, its current state, or even turn the connection on or off. While toggling the connection could also be handled by a simple intent action, having access to the other information provided by the service can allow apps to intelligently interact with it.