XamChat – a Cross-platform App

Describing our sample application concept

The concept is simple: a chat application that uses a standard Internet connection as an alternative to sending text messages. There are several popular applications like this in the Apple App Store, probably due to the cost of text messaging and support for devices such as the iPod Touch or iPad. This should be a neat real-world example that could be useful for users, and will cover specific topics in developing applications for iOS and Android.

Before starting with the development, let's list the set of screens that we'll need:

Login / sign up: This screen will include a standard login and sign-up process for the user

List of conversations: This screen will include a button to start a new conversation

List of friends: This screen will provide a way to add new friends when we start a new conversation

Conversation: This screen will have a list of messages between you and another user, and an option to reply

A quick wireframe layout of the application would help us grasp a better understanding of the layout of the app. The following figure shows the set of screens to be included in your app:

Developing our model layer

Since we have a good idea of what the application is, the next step is to develop the business objects or model layer of this application. Let's start out by defining a few classes that would contain the data to be used throughout the app. It is recommended, for the sake of organization, to add these to a Models folder in your project.

Let's begin with a class representing a user. The class can be created as follows:

Notice that we are using integers as identifiers for the various objects. UserId is the value that would be set by the application to change the user that the object is associated with.

Now let's go ahead and set up our solution by performing the following steps:

Start by creating a new solution and a new C# Library project.

Name the project as XamChat.Core and the solution as XamChat.

Next, let's set the library to a Mono / .NET 4.5 project. This setting is found in the project option dialog under Build | General | Target Framework.

You could also choose to use Portable Library for this project,

Writing a mock web service

Many times when developing a mobile application, you may need to begin the development of your application before the real backend web service is available. To prevent the development from halting entirely, a good approach would be to develop a mock version of the service.

First, let's break down the operations our app will perform against a web server. The operations are as follows:

Log in with a username and password.

Register a new account.

Get the user's list of friends.

Add friends by their usernames.

Get a list of the existing conversations for the user.

Get a list of messages in a conversation.

Send a message.

Now let's define an interface that offers a method for each scenario. The interface is as follows:

As you see, we're using asynchronous communication with the TPL(Task Parallel Library) technology.

Since communicating with a web service can be a lengthy process, it is always a good idea to use the Task<T> class for these operations. Otherwise, you could inadvertently run a lengthy task on the user interface thread, which would prevent user inputs during the operation. Task is definitely needed for web requests, since users could easily be using a cellular Internet connection on iOS and Android, and it will give us the ability to use the async and await keywords down the road.

Now let's implement a fake service that implements this interface. Place classes such as FakeWebService in the Fakes folder of the project. Let's start with the class declaration and the first method of the interface:

We started off with a SleepDuration property to store a number in milliseconds. This is used to simulate an interaction with a web server, which can take some time. It is also useful for changing the SleepDuration value in different situations. For example, you might want to set this to a small number when writing unit tests so that the tests execute quickly.

Next, we implemented a simple Sleep method to return a task that introduce delays of a number of milliseconds. This method will be used throughout the fake service to cause a delay on each operation.

Finally, the Login method merely used an await call on the Sleep method and returned a new User object with the appropriate Username. For now, any username or password combination will work; however, you may wish to write some code here to check specific credentials.

Now, let's implement a few more methods to continue our FakeWebService class as follows:

Most of these methods are very straightforward. Note that the service doesn't have to work perfectly; it should merely complete each operation successfully with a delay. Each method should also return test data of some kind to be displayed in the UI. This will give us the ability to implement our iOS and Android applications while filling in the web service later.

Next, we need to implement a simple interface for persisting application settings. Let's define an interface named ISettings as follows:

public interface ISettings
{
User User { get; set; }
void Save();
}

Note that you might want to set up the Save method to be asynchronous and return Task if you plan on storing settings in the cloud. We don't really need this with our application since we will only be saving our settings locally.

Later on, we'll implement this interface on each platform using Android and iOS APIs. For now, let's just implement a fake version that will be used later when we write unit tests. The interface is created by the following lines of code:

Note that the fake version doesn't actually need to do anything; we just need to provide a class that will implement the interface and not throw any unexpected errors.

This completes the Model layer of the application. Here is a final class diagram of what we have implemented so far:

Writing the ViewModel layer

Now that we have our model layer implemented, we can move on to write the ViewModel layer. The ViewModel will be responsible for presenting each operation to the UI and offering properties to be filled out by the View layer. Other common responsibilities of this layer are input validation and simple logic to display busy indicators.

At this point, it would be a good idea to include the ServiceContainer class in our XamChat.Core project, as we will be using it through our ViewModels to interact with the Model layer. We will be using it as a simple option to support dependency injection and Inversion of Control; however, you may use another library of your preference for this.

Normally, we start off by writing a base class for all the ViewModel layers within our project. This class always has the functionality shared by all the classes. It's a good place to put some parts of the code that are used by all the methods in the classes; for example, notification changes, methods, or similar instances.

Place the following code snippet in a new ViewModels folder within your project:

The BaseViewModel class is a great place to insert any common functionality that you plan on reusing throughout your application. For this app, we only need to implement some functionality to indicate if the ViewModel layer is busy. We provided a property and an event that the UI will be able to subscribe to and display a wait indicator on the screen. We also added some fields for the services that will be needed. Another common feature that could be added would be validation for user inputs; however, we don't really need it for this application.

Implementing our LoginViewModel class

Now that we have a base class for all of the ViewModel layers, we can implement ViewModel for the first screen in our application, the Login screen.

We subclassed BaseViewModel to get access to IsBusy and the fields containing common services

We added the Username and Password properties to be set by the View layer

We added a User property to be set when the log in process is completed

We implemented a Login method to be called from View, with validation on Username and Password properties

We set IsBusy during the call to the Login method on IWebService

We set the User property by awaiting the result from Login on the web service

Basically, this is the pattern that we'll follow for the rest of the ViewModels in the application. We provide properties for the View layer to be set by the user's input, and methods to call for various operations. If it is a method that could take some time, such as a web request, you should always return Task and use the async and await keywords.

Note that we used a try and finally block for setting IsBusy back to false. This will ensure it gets reset properly even when an exception is thrown. We plan on handling the error in the View layer, so we can display a native pop up to the user displaying a message.

Implementing our RegisterViewModel class

Since we have finished writing our ViewModel class to log in, we will now need to create one for the user's registration.

The RegisterViewModel class is very similar to the LoginViewModel class, but has an additional ConfirmPassword property for the UI to set. A good rule to follow for when to split up the ViewModel layer's functionality is to always create a new class when the UI has a new screen. This helps to keep your code clean and somewhat follow the single responsibility principle for your classes. This concept states that a class should only have a single purpose or responsibility. We'll try to follow this concept to keep our classes small and organized, which can be more important than usual when sharing code across platforms.

Implementing our FriendViewModel class

Next on the list is a ViewModel layer to work with a user's friend list. We will need a method to load a user's friend list and add a new friend.

Again, this class is fairly straightforward. The only thing new here is that we added some logic to update the list of friends and sort them within our client application and not the server. You could also choose to reload the complete list of friends if you have a good reason to do so.

Implementing our MessageViewModel class

Our final required ViewModel layer will be handling messages and conversations. We need to create a way to load conversations and messages, and send a new message.

This concludes the ViewModel layer of our application and the entirety of the shared code used on iOS and Android. For the MessageViewModel class, you could have also chosen to put GetConversations and Conversations properties in their own class, since they could be considered as a separate responsibility, but it is not really necessary.

Here is the final class diagram of our ViewModel layer:

Summary

In this article, we went over the concept for a sample application called XamChat. We also implemented the core business objects for the application in the Model layer. Since we do not have a server to support this application yet, we implemented a fake web service. This gives us the flexibility to move forward with the app without building a server application. We also implemented the ViewModel layer. This layer will expose operations in a simple way to the View layer.

Alerts & Offers

Series & Level

We understand your time is important. Uniquely amongst the major publishers, we seek to develop and publish the broadest range of learning and information products on each technology. Every Packt product delivers a specific learning pathway, broadly defined by the Series type. This structured approach enables you to select the pathway which best suits your knowledge level, learning style and task objectives.

Learning

As a new user, these step-by-step tutorial guides will give you all the practical skills necessary to become competent and efficient.

Beginner's Guide

Friendly, informal tutorials that provide a practical introduction using examples, activities, and challenges.

Essentials

Fast paced, concentrated introductions showing the quickest way to put the tool to work in the real world.

Cookbook

A collection of practical self-contained recipes that all users of the technology will find useful for building more powerful and reliable systems.

Blueprints

Guides you through the most common types of project you'll encounter, giving you end-to-end guidance on how to build your specific solution quickly and reliably.

Mastering

Take your skills to the next level with advanced tutorials that will give you confidence to master the tool's most powerful features.

Starting

Accessible to readers adopting the topic, these titles get you into the tool or technology so that you can become an effective user.

Progressing

Building on core skills you already have, these titles share solutions and expertise so you become a highly productive power user.