iMessage App
With the release of iOS 10, Apple introduced an exciting new feature called Message App Extensions. This new extension type can send text, stickers, media files, as well as interactive messages and integrates with the Messages app, presenting new functionality for users.

Message App Extensions support different types of content that can be shared. One of the most exciting of these is “Interactive Messages,” which allows you to launch an app from Messages, create custom content, and then use the new Messages Framework APIs to send it in Messages. In this blog post, we’ll explore iMessage App Extensions by creating an interactive game named Monkey Tap.

Building Your First iMessage App Extension

Creating an iMessage App Extension is easy! Use the New Project wizard via “File -> New Solution” to start a Single View iOS App. Then, add another New Project to the solution by right clicking it in your Solution Pad. Under the iOS templates, select the Extension menu item and select iMessage Extension. The main difference between this and other extension types is that there is not a “container” app project; instead, the Message app we are creating itself acts as the container.

capture

MSMessagesAppViewController

Message App Extensions introduce a new type: MSMessagesAppViewController. This acts a lot like what we’re used to, but introduces some message-specific items we need. For example, an MSConversation object is available that represents the conversation we’re in. This is useful so we know where to send a message. We can now create a new controller to handle displaying the score for the game, thereby allowing us to send the score to our recipient as a message.

public partial class ScoreViewController : MSMessagesAppViewController
{
        ...
	public override void ViewDidLoad()
	{
		base.ViewDidLoad();

		FinalScoreLabel.Text = string.Format("You scored {0}!", finalScore);

		// Set up the message layout
		MSMessageTemplateLayout layout = new MSMessageTemplateLayout()
		{
			Image = UIImage.FromBundle("Monkey"),
			Caption = "Try and beat my score!",
			TrailingCaption = "" + finalScore,
			Subcaption = "MonkeyTap"
		};

		// Create a new message with the above layout
		MSMessage message = new MSMessage()
		{
			Layout = layout
		};

		// Send the message when the button is tapped
		PostScore.TouchUpInside += (sender, e) =>
		{
			conversation.InsertMessage(message, (Foundation.NSError error) =>
			{
				if (error == null)
				{
					// Handle successful send
				}
				else {
					// Report Error
					Console.WriteLine("Error: {0}", error);
				}
			});
		};

		PlayAgain.TouchUpInside += (sender, e) =>
		{
			DismissViewController(true, null);
		};
	}
}

The interesting parts are still in ViewDidLoad. Here, MSMessage is created and being used to send the score. The Layout property accepts a MSMessageTemplateLayout. The properties handle what’s displayed:

MSMessageTemplateLayout layout = new MSMessageTemplateLayout()
{
	Image = UIImage.FromBundle("Monkey"),
	Caption = "Try and beat my score!",
	TrailingCaption = "" + finalScore,
	Subcaption = "MonkeyTap"
};

Here is what our iMessage App Extension looks like:

pasted-image-at-2016_10_19-02_13-pm
We’ll use another controller to handle the the game logic. This will capture any taps from the user and add them as a score.

public partial class GameViewController : MSMessagesAppViewController
{
	public override void ViewDidLoad()
	{
		base.ViewDidLoad();

		// As we are using a UIImageView, we need to detect taps with a UITapGestureRecognizer
		UITapGestureRecognizer tapGesture = new UITapGestureRecognizer((obj) =>
		{
			// Game logic
			...
		});
		Monkey.AddGestureRecognizer(tapGesture);

		gameTimer.Elapsed += (sender, e) =>
		{
			...
			
			if (time.Equals(0))
			{
				// Once we run out of time, stop the timer
				gameTimer.Stop();
				gameInProgress = false;
				InvokeOnMainThread(() =>
				{
					ScoreViewController scoreVC = Storyboard.InstantiateViewController("ScoreVC") as ScoreViewController;
					// Pass the score and ActiveConversation to the next ViewController
					scoreVC.finalScore = score;
					scoreVC.conversation = ActiveConversation;
					ShowViewController(scoreVC, this);

					// Reset the labels
					ScoreLabel.Text = "Tap monkey to begin!";
					TimerLabel.Text = "Time: 0.0s";
				});
			}
		};
	}
}

 

out
That’s it! We’ve made a little game where the user can tap on the view and increase their score during the countdown. When it’s over, we compose a message to send to our recipient. This is where the MSConversation comes in handy.

conversation.InsertMessage(message, (Foundation.NSError error) =>
{
	if (error == null)
	{
		// Handle successful send
	}
	else {
		// Report Error
		Console.WriteLine("Error: {0}", error);
	}
});

We’ve Only Scratched the Surface

We’ve just touched on some of what’s possible with these new extensions. If you’d like to learn more about this topic, check out the documentation. You’ll find more information about other available APIs, learn about Sticker Packs, group conversations, and more. You can browse the entire source code for the Monkey Tap project in this post.