In much the same way that photo editing extensions allow custom photo editing capabilities to be added to the standard Photos app, message app extensions allow the functionality of the standard iOS Messages app to be extended and enhanced.
Message app extensions, introduced with iOS 10, allow app developers to provide users with creative ways to generate and send custom and interactive messages to their contacts. The possibilities offered by message apps range from simple sticker apps that allow images to be selected from sticker packs and inserted into messages through to more advanced possibilities such as fully interactive games.
Once created, Message app extensions are made available to customers through the Messages App Store, providing an additional source of potential revenue for app developers.
This chapter will provide a basic overview of message app extensions, along with an outline of how the key classes and methods of the Messages framework combine to enable the creation of message apps. The next chapter, entitled An iOS 17 Interactive Message App Tutorial, will work through creating an interactive message app project.
Introducing Message Apps
Message app extensions (often referred to simply as message apps) are built using the standard iOS extension mechanism. The one significant difference is that a message app extension does not require a containing app. Instead, users find and install message apps by browsing the Message App Store or when they receive a message created using a messaging app from another user. Once a messaging app has been installed, it appears within the Messages App Drawer of the Messages app on iOS devices. This app drawer is accessed by tapping the App Store icon located in the Messages app toolbar, as highlighted in Figure 79-1:
When a message app icon is tapped, the app extension is launched and displayed within the app drawer panel. When a message app is displayed, swiping left or right within the drawer scrolls through the different apps currently installed on the device. In Figure 79-2 below the app drawer displays a message app that allows animated images to be selected for inclusion in messages. When displayed in the app drawer, the message app is said to be using the compact presentation style.
The horizontal bar (highlighted in Figure 79-2 above) switches the app to expanded presentation style whereby the app user interface fills the entire screen area. Tapping the down arrow in the upper right-hand corner of the expanded presentation view will switch the app back to the compact style.
In addition to launching a message app from within the app drawer, selecting a message associated with a message app from the message transcript area will automatically launch the corresponding app in expanded presentation style.
If a user receives a message generated by a message app but does not currently have that particular app installed, tapping the app icon within the message will take the user to the Messages App Store, where the app may be purchased and installed. This is expected to have a viral effect in terms of selling message apps, with customers buying apps to interact with messages received from their contacts.
Types of Message Apps
iOS currently supports three different types of message app extensions. The first is simply a mechanism for providing collections of sticker images (referred to as sticker packs) to include in user messages. The second type of app allows various media content (such as text, images, web links, and videos) to be inserted into messages. The third, and most powerful option, allows fully interactive message apps to be created. When developing interactive message apps, the full range of iOS frameworks and user interface controls is available when implementing the app, essentially allowing a message app of any level of richness and complexity to be created using the same approach as that taken when developing regular iOS apps.
Since interactive message apps provide the greatest flexibility and opportunities for app developers, this will be the main focus of this chapter and the tutorial in the book’s next chapter.
The Key Messages Framework Classes
Several classes provided by the Messages framework will need to be used in developing a message app. Therefore, understanding these classes and how they interact is essential. In this section, a brief overview of each class and the most commonly used properties and methods of those classes will be outlined.
MSMessagesAppViewController
The MSMessagesAppViewController class is responsible for displaying and managing the message app in both compact and expanded presentation styles. It allows for the presentation of a user interface to the user and provides a bridge between the user interface and the underlying app logic. The class also stores information about the app status via the following properties:
- activeConversation – Stores the MSConversation object for the currently active conversation.
- presentationStyle – Contains the current presentation style for the message app (compact or expanded).
Instances of this class also receive the following lifecycle method calls:
- willBecomeActive – The app is about to become active within the Messages app.
- didBecomeActive – Called immediately after the app becomes active.
- willResignActive – The app is about to become inactive.
- didResignActive – Called after the app has become inactive.
- willSelect – Called after the user selects a message from the transcript, but before the selectedMessage property of the conversation object is updated to reflect the current selection.
- didSelect – Called after the selectedMessage conversation property has been updated to reflect a message selection made by the user.
- didReceive – When an incoming message is received for the message app, and the message app is currently active, this method is called and passed corresponding MSMessage and MSConversation objects.
- didStartSending – Called when the user sends an outgoing message.
- didCancelSending – Called when the user cancels a message before sending it.
- willTransition – Called when the app is about to transition from one presentation style to another. Changes to the user interface of the message app to accommodate the presentation style change should be made here if necessary.
- didTransition – Called when the app has performed a transition between presentation styles.
Since MSMessagesAppViewController is a subclass of UIViewController, the class behaves in much the same way. Also, it receives the standard lifecycle method calls (such as viewDidLoad, viewWillAppear, viewWillDisappear, etc.) as the UIViewController class.
MSConversation
The MSConversation class represents the transcript area of the Messages app when a message app extension is active. This object stores the currently selected message (in the form of an MSMessage object via the selectedMessage property). In addition, it provides the following API methods that the message app may call to insert messages into the input field of the Messages app:
- insert – Inserts an MSMessage object or sticker into the input field of the Messages app.
- insertText – Inserts text into the input field of the Messages app.
- insertAttachment – Inserts an attachment, such as an image or video file, into the Messages app input field.
Once a message has been inserted into the Messages app input field, the user must send it via a tap on the send button. A message app can’t send a message directly without the user taking this step.
In addition to the methods outlined above, the MSConversation class also contains the following properties:
- localParticipantIdentifier – Contains the UUID of the user of the local device. Accessing this item’s uuidString property will provide the user’s contact name in a format suitable for display within the message layout.
- remoteParticipantIdentifiers – Contains an array of UUID objects representing the identities of remote users currently participating in the message app conversation.
MSMessage
The MSMessage class represents individual messages within the Messages app transcript. The key elements of an MSMessage object are as follows:
- layout – The layout property takes the form of an MSMessageTemplateLayout object which defines how the message is to be displayed within the message bubble in the Messages app transcript area.
- url – The url property is used to encode the data that is to be sent along with the message. This can be a standard URL that points to a remote server where the data can be downloaded by the receiving app, or, for smaller data requirements, the URL itself can be used to encode the data to be transmitted with the message. The latter approach can be achieved using the URLComponents class, a process covered in detail in the next chapter entitled An iOS 17 Interactive Message App Tutorial.
- session – The use of sessions in message apps allows multiple messages to be designated as part of the same session. In addition, session messages are presented such that only the most recent message in the session is displayed in its entirety, thereby avoiding cluttering the Messages app transcript area with the full rendering of each message.
- accessibilityLabel – A localized string describing the message suitable for accessibility purposes.
- senderParticipantIdentifier – The UUID of the user that sent the message.
- shouldExpire – A Boolean value indicating whether the message should expire after the recipient has read it.
MSMessageTemplateLayout
The MSMessageTemplateLayout defines how an MSMessage instance is presented to the user within the transcript area of the Messages app.
When a message contained within an MSMessage object is presented to the user, it is displayed within a message bubble. Various aspects of how this message bubble appears can be defined and included within the MSMessage object.
The image, video, titles, and subtitles contained within the bubble are configured using an MSMessageTemplateLayout instance which is then assigned to the layout property of the MSMessage instance. For example, the diagram illustrated in Figure 79-3 provides a graphical rendering of an MSMessage-based message bubble with each of the configurable layout properties labeled accordingly:
The settings in the above diagram correlate to the following properties of the MSMessageTemplateLayout class:
- image – The image to be displayed in the image area of the message. The recommended image size is 300pt x 300pt, and the Messages framework will automatically scale the image for different display sizes. To avoid rendering issues, it is recommended that text not be included in the image.
- mediaFileURL – The URL of a media file to be displayed in the image (such as a video or animated image file).
- imageTitle – The text to display in the Image Title location.
- imageSubtitle – The text to appear in the Image Subtitle location.
- caption – Text to appear in the Caption location.
- subCaption – Text to appear in the Subcaption location.
- trailingCaption – Text to appear in the Trailing Caption location. • trailingSubcaption – Text to appear in the Trailing Subcaption location.
Sending Simple Messages
To send simple text, stickers, and image messages, creating an MSMessage object is unnecessary. The first step is to obtain a reference to the currently active conversation. From within an MSMessagesAppViewController instance, the currently active conversation can be obtained via the activeConversation property:
let conversation = self.activeConversation
The next step is to make a call to the appropriate method of the active conversation instance. To send a text message, for example, the code might read as follows:
let conversation = self.activeConversation conversation?.insertText("Message Text Here") { error in // Handle errors }
Once the above code is executed, the designated text will appear in the Messages app input field, ready to be sent by the user.
Similarly, an attachment may be sent using the insertAttachment method call, passing through a URL referencing the file to be attached to the message:
let conversation = self.activeConversation conversation?.insertAttachment(myURL, withAlternateFilename: nil) { error in // Handle errors }
Creating an MSMessage Message
To send an interactive message, it is necessary to use the MSMessage class. The first step, once again, is to obtain a reference to the currently active conversation:
let conversation = self.activeConversation
Next, a new MSMessage instance needs to be created within which to place the message content:
let message = MSMessage()
If the message is to be associated with a specific session, the message would be created as follows:
let session = MSSession() let message = MSMessage(session: session)
The above example assigns a newly created session object to the message. If this message were being created in response to an incoming message that already had a session allocation, the session object from the incoming message would be used instead.
Once the message instance has been created, the layout needs to be configured using an MSMessageTemplateLayout instance. For example:
let layout = MSMessageTemplateLayout() layout.imageTitle = "My Image Title" layout.caption = "A Message Caption" layout.subcaption = "A message subcaption" layout.image = myImage
Once the layout has been defined, it needs to be assigned to the MSMessage object:
message.layout = layout
Next, a url needs to be assigned containing the data to be passed along with the message, for example:
message.url = myUrl
Once the message has been configured, it can be placed in the Messages app input field using the insert method of the active conversation:
conversation?.insert(message, completionHandler: {(error) in // Handle error })
Once the message has been inserted, it is ready to be sent by the user.
Receiving a Message
When a message is received from another instance of a message app, and the message app is currently active, the didReceive method of the MSMessagesAppViewController instance will be called and passed both the MSMessage and MSConversation objects associated with the incoming message. When the user selects the message in the transcript, the app extension will launch, triggering a call to the willBecomeActive method, which will, in turn, be passed a copy of the MSConversation object from which a reference to the currently selected message may also be obtained.
Because the didReceive method is not called unless the message app is already active, the willBecomeActive method is typically the best place to access the incoming MSMessage object and update the app’s status. The following sample implementation of the willBecomeActive method, for example, gets the selected message from the conversation object and then accesses the properties of the message to obtain the current session and the encoded URL:
override func willBecomeActive(with conversation: MSConversation) { if let message = conversation.selectedMessage? { let url = message.url let session = conversation.selectedMessage?.session // Decode the URL and update the app } }
Supported Message App Platforms
The ability to create interactive messages using a message app extension is currently limited to devices running iOS 10 or later. Interactive messages will, however, be delivered to devices running macOS Sierra, watchOS 3, and iOS 10 in addition to older operating system versions.
When an interactive message is received on macOS Sierra, clicking on the message bubble will launch the URL contained within that message within the Safari browser. It is important to note that in this situation, the web server will need to be able to decode the URL and present content within the resulting web page that relates to the message. On watchOS 3, the interactive message can launch the full message app extension on a companion iOS 10 or later.
An incoming interactive message is delivered in two parts for older versions of macOS, watchOS, and iOS. The first contains the image assigned to the message layout, and the second is the URL contained within the message.
Summary
Message apps are custom apps installed as extensions to the built-in iOS Messages app. These apps create and send custom and interactive messages to other users. These extensions are made possible by the Messages framework. Message apps range in functionality from simple “sticker pack” apps to fully interactive experiences.
This chapter has outlined the basic concepts of message apps and the different classes typically required when developing a message app. The next chapter, entitled An iOS 17 Interactive Message App Tutorial, will use the information provided in this chapter to create an example interactive message app.