Building a group chat app using Kotlin and Pusher Chatkit

  • JosĂ© Maria Cunha
November 7th, 2018
For you to follow along in this tutorial you’ll need the following requirements: 1. Working knowledge of the Kotlin programming language. 2. Basic knowledge of JavaScript and Node.js. 3. Knowledge of Android Studio >= 3.0 must be installed. 4. Pusher Chatkit application. 5. NPM

In this tutorial, we will be building a group chat application using Kotlin and Chatkit. You can use parts of this tutorial to give you an idea on how you can build your own full-fledged chat application.

Here is an example screen recording of what we will be building:

Chat messaging applications have been on the rise and one of the reasons is because they provide a platform for instant user communication. Messaging platforms, amongst other features, require realtime delivery of messages end-to-end.

Prerequisites

For you to follow along in this article you’ll need the following requirements:

  • Knowledge of the Kotlin programming language.
  • Basic knowledge of JavaScript and Node.js.
  • Knowledge of using Android Studio and Android Studio >= 3.0 must be installed. Download it here.
  • A Pusher Chatkit application. Create one here.
  • Node.js and NPM installed on your machine.

When you have the requirements, let’s begin.

Creating a Chatkit Application

Assuming you have not already, create a new Chatkit instance from the Chatkit dashboard. After creating it, you will be presented with a Getting Started wizard.

You may wish to create a user using the wizard if you wish. However, we will also handle this in our back-end. For the purpose of the article, however, you should create a new room called General.

When you are done with the Getting Started wizard, let’s move on to creating the application. We will start by creating the Node.js backend first.

Creating a Node.js Backend for Pusher Chatkit

The backend will make use of the Chatkit Node SDK. We will use it to grant user tokens which can then be used to make authenticated calls to the Chatkit API from the client application.

To get started, create a new project folder called chatkit-backend. In that project directory, create a package.json file and paste this into the file:

    {
      "name": "chatkit",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "dependencies": {
        "body-parser": "^1.18.2",
        "express": "^4.16.2",
        "@pusher/chatkit-server": "^1.0.2"
      }
    }

Now in your terminal, cd to the root of the project directory and run the command below:

    $ npm install

This will install the dependencies specified in the package.json file above.

Next, create a new index.js file in the root of the project directory and paste the following into the file:

    const express = require('express');
    const bodyParser = require('body-parser');
    const Chatkit = require('@pusher/chatkit-server');

    const app = express();
    const chatkit = new Chatkit.default({
        key: "CHATKIT_KEY",
        instanceLocator: "INSTANCE_LOCATOR",
    });

    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));

    app.get('/users', (req, res) => {
        const username = req.query.username;

        chatkit.createUser({ id: username, name: username})
             .then(r => res.json({username}))
             .catch(e => res.json({error: e.error_description, type: e.error_type}));
    });

    app.post('/auth', (req, res) => {
        const userId = req.query.user_id;

        res.json(chatkit.authenticate({ userId }));
    });

    app.get('/', (req, res, next) => {
        res.json("Working!");
    })

    app.listen(3000, () => console.log('Running application...'));

In the code above, we have two endpoints:

  • /users - This endpoint helps us create a user. If the username provided already exists, it returns the data of that user.
  • /auth - This endpoint provides an access token for a Chatkit user.

đź’ˇ You are required to insert your INSTANCE_LOCATOR and CHATKIT_KEY into the Chatkit instance on line 7 and 8. You can find them on the keys tab of your Chatkit application dashboard.

Now we have finished creating the backend for the application. We can run our Node app using the command:

    $ node index.js       

To test if your server is running, open http://localhost:3000 on your browser. You should see a “Working!” message displayed on your browser.

Building the Group Chat Android Application using Kotlin

Now that we have successfully created the backend necessary to help the Android application work, let us get into building the application itself using Kotlin and Android Studio.

Create Your Android Studio Project

Open Android Studio and “Start a new Android Studio project”. Enter your application name, company domain name, and tick the “Include Kotlin Support” checkbox. Next, select a minimum SDK (must be API 19 or greater) and choose Empty Activity when creating your project.

⚠️ Depending on the SDK you selected, Android Studio might need to download additional files.

Once the build is complete, you should see the Android Studio editor with the MainActivity.kt file opened by default. Great.

Setup Retrofit for HTTP Communications To make external HTTP connections so we can communicate with our backend server, we need an HTTP library. Enter Retrofit. Retrofit is a “type-safe HTTP client” that’ll enable us to communicate with our server.

To use it, we first have to add the dependencies in the build.gradle file. Open the file and add the lines of code below:

implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'

Now you can sync your Gradle file so Retrofit gets pulled into our application build.

Let’s create an API Interface file called ApiService.kt. This interface will be used to define endpoints to be used during network calls. Create the ApiService.kt file and paste the following:

import retrofit2.Call
import retrofit2.http.*

interface ApiService {
    @GET("/users")
    fun createUser(@Query("username") user:String): Call<String>
}

Next, we will create a class that gives us an instance of Retrofit. Create a new RetrofitClient.kt file and paste this into it:

import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory

public class RetrofitClient {
    fun getClient(): ApiService {
        val httpClient = OkHttpClient.Builder()
        val builder = Retrofit.Builder()
                .baseUrl("http://10.0.2.2:3000/")
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())

        val retrofit = builder
                .client(httpClient.build())
                .build()
        return retrofit.create(ApiService::class.java)
    }
}

đź’ˇ We are using the address 10.0.2.2 because this is how the Android default emulator recognizes localhost. So the IP address refers to a local server running on your machine. If you are running this on a production server, you will need to replace this value with the address of the remote server.

The next thing we need to do is update the permissions for the application using the AndroidManifest.xml file. Open the file and then add the following permissions to it:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

The permissions allow the application access to the internet and also gives it permissions to see the network state of the device.

Adding More Dependencies Let’s add more dependencies to our application as we will need these later in the application building process.

Chatkit is currently distributed as a snapshot, so make sure to have the maven snapshots repository added:

allprojects {
    repositories {
        google()
        jcenter()
        maven{
            url "https://oss.sonatype.org/content/repositories/snapshots"
        }
    }
}

Next, add this to your dependencies in the app’s build.gradle file:

// chatkit dependency
implementation 'com.pusher:chatkit-android:1.0.0'

// android support Libraries
implementation 'com.android.support:design:26.1.0'
implementation 'com.android.support:appcompat-v7:26.1.0'

Sync your project to bring in the dependencies and make them available to your project.

Building App Screens Right now we need to build our application screens. However, before doing this, let’s set up our Application class to hold our global variables.

Create a new class file called AppController.kt and paste the following code into it:

import android.app.Application
import com.pusher.chatkit.rooms.Room
import com.pusher.chatkit.CurrentUser

class AppController(): Application() {
    override fun onCreate() {
        super.onCreate()
    }

    companion object {
        lateinit var currentUser:CurrentUser
        lateinit var room:Room
    }
}

Next, set the name property for the application tag in our AndroidManifest.xml:

<application
    android:name=".AppController"
    ...
    >

Now let’s go ahead and create the screens. Our MainActivity will serve as the login screen. So, open the layout file activity_main.xml and paste the code below to the file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_margin="16dp"
    tools:context="com.example.android.groupchatapp.MainActivity">

    <EditText
        android:id="@+id/text_user_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter username" />

    <Button
        android:id="@+id/button_login"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="LOGIN" />

</LinearLayout>

⚠️ You will need to change **com.example.android.groupchatapp** to your package name above.

The layout above contains a text input field for our username and a button to trigger the login process.

Next, open the MainActivity.kt file and replace with the code below:

import retrofit2.Call
import android.os.Bundle
import android.util.Log
import retrofit2.Callback
import retrofit2.Response
import org.json.JSONObject
import android.widget.Toast
import android.content.Intent
import android.support.v7.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        button_login.setOnClickListener {
            if (text_user_name.text.isNotEmpty()) {
                val userName: String = text_user_name.text.toString()
                Log.d("TAG",userName)
                createNewUser(userName)
            } else {
                Toast.makeText(this@MainActivity,"Please enter a username", Toast.LENGTH_LONG).show()
            }
        }
    }

    private fun createNewUser(userName: String) {
        val jsonObject = JSONObject()
        jsonObject.put("username",userName)

        RetrofitClient().getClient().createUser(userName).enqueue(object: Callback<String>{
            override fun onFailure(call: Call<String>?, t: Throwable?) {
                Log.d("TAG", t.toString())
            }

            override fun onResponse(call: Call<String>?, response: Response<String>?) {
                if (response!!.code() == 200){
                    startActivity(Intent(this@MainActivity, RoomsListActivity::class.java)
                            .putExtra("extra",userName))
                }
            }
        })
    }
}

From the above snippet, we attached a listener to the login button so, when a user clicks it, we call the /users endpoint using Retrofit to create a user. If the user exists, it logs that user in otherwise it creates a new user. After a successful login, a new activity that will display the rooms is opened.

Let’s create this rooms list activity. Create a new activity named RoomsListActivity using File > New > Activity > EmptyActivity. This comes with a layout named activity_rooms_list. The layout will contain just a R``ecyclerView to display the various rooms:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
    android:layout_margin="16dp"
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android" />

Next, let’s create a RoomsAdapter class to handle the list and items in it. Create a new file called RoomsAdapter.kt:

import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.pusher.chatkit.rooms.Room
import android.view.LayoutInflater
import android.support.v7.widget.RecyclerView

class RoomsAdapter: RecyclerView.Adapter<RoomsAdapter.ViewHolder>() {
    private var list = ArrayList<Room>()
    lateinit var roomClickedInterface:RoomClickedInterface

    fun addRoom(room:Room){
        list.add(room)
        notifyDataSetChanged()
    }

    fun setInterface(roomClickedInterface:RoomClickedInterface){
        this.roomClickedInterface = roomClickedInterface
    }

    override fun getItemCount(): Int {
        return list.size
    }

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent!!.context)
                                 .inflate(
                                         android.R.layout.simple_list_item_1,
                                         parent, 
                                         false
                                 )

        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
        holder!!.roomName.text = list[position].name
    }

    inner class ViewHolder(itemView: View?): RecyclerView.ViewHolder(itemView), View.OnClickListener {
        override fun onClick(p0: View?) {
            roomClickedInterface.roomSelected(list[adapterPosition])
        }

        var roomName: TextView = itemView!!.findViewById(android.R.id.text1)

        init {
            itemView!!.setOnClickListener(this)
        }
    }

    interface RoomClickedInterface{
        fun roomSelected(room:Room)
    }
}

In the above class, we extend the RecyclerView.Adapter<VH extends ViewHolder> class and implement some methods to handle the items in the list. However, we added two more functions to the class. The addRoom method which adds a new item to the list and refreshes the adapter, and the setInterface method that initializes the interface we created with the class to implement it.

The interface will be implemented in the RoomsListActivity.kt class. The code for this is below:

package co.creativitykills.groupchat

import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.util.Log
import com.pusher.chatkit.*
import com.pusher.chatkit.rooms.Room
import com.pusher.util.Result
import kotlinx.android.synthetic.main.activity_rooms_list.*

class RoomsListActivity : AppCompatActivity() {
    val adapter = RoomsAdapter()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_rooms_list)
        initRecyclerView()
        initChatManager()
    }

    private fun initRecyclerView() {
        recycler_view.layoutManager = LinearLayoutManager(this@RoomsListActivity)
        recycler_view.adapter = adapter
    }

    private fun initChatManager() {
        val chatManager = ChatManager(
                instanceLocator = "YOUR_INSTANCE_LOCATOR",
                userId = "YOUR_USER_ID",
                dependencies = AndroidChatkitDependencies(
                        tokenProvider = ChatkitTokenProvider(
                                endpoint = "http://10.0.2.2:3000/auth",
                                userId = "YOUR_USER_ID"
                        )
                )
        )

        chatManager.connect(listeners = ChatListeners(
                onErrorOccurred = { },
                onAddedToRoom = { },
                onRemovedFromRoom = { },
                onCurrentUserReceived = { },
                onNewReadCursor = { },
                onRoomDeleted = { },
                onRoomUpdated = { },
                onPresenceChanged = { u, n, p -> },
                onUserJoinedRoom = { u, r -> },
                onUserLeftRoom = { u, r -> },
                onUserStartedTyping = { u, r -> },
                onUserStoppedTyping = { u, r -> }
        )) { result ->
            when (result) {
                is Result.Success -> {
                    // We have connected!
                    val currentUser = result.value
                    AppController.currentUser = currentUser
                    val userJoinedRooms = ArrayList<Room>(currentUser.rooms)
                    for (i in 0 until userJoinedRooms.size) {
                        adapter.addRoom(userJoinedRooms[i])
                    }

                    currentUser.getJoinableRooms { result ->
                        when (result) {
                            is Result.Success -> {
                                // Do something with List<Room>
                                val rooms = result.value
                                runOnUiThread {
                                    for (i in 0 until rooms.size) {
                                        adapter.addRoom(rooms[i])
                                    }
                                }
                            }
                        }
                    }

                    adapter.setInterface(object : RoomsAdapter.RoomClickedInterface {
                        override fun roomSelected(room: Room) {
                            if (room.memberUserIds.contains(currentUser.id)) {
                                // user already belongs to this room
                                roomJoined(room)
                            } else {
                                currentUser.joinRoom(
                                        roomId = room.id,
                                        callback = { result ->
                                            when (result) {
                                                is Result.Success -> {
                                                    // Joined the room!
                                                    roomJoined(result.value)
                                                }
                                                is Result.Failure -> {
                                                    Log.d("TAG", result.error.toString())
                                                }
                                            }
                                        }
                                )
                            }
                        }
                    })
                }

                is Result.Failure -> {
                    // Failure
                    Log.d("TAG", result.error.toString())
                }
            }
        }
    }

    private fun roomJoined(room: Room) {
        val intent = Intent(this@RoomsListActivity, ChatRoomActivity::class.java)
        intent.putExtra("room_id", room.id)
        intent.putExtra("room_name", room.name)
        startActivity(intent)
    }
}

From the code above, we initialized the RecyclerView with a layout manager and a RoomsAdapter. We also initialized our ChatManager object with our instance locator, activity context, and token provider. The token provider is created by creating an instance of ChatkitTokenProvider which takes two parameters; the endpoint URL and the user ID.

When the ChatManager connects, we implement the currentUserReceived method. This method gives us details of the currently logged in user. In the method, we fetch all the rooms the user has joined and can join and we add them to the rooms list.

In the same method, we called the adapter’s setInterface method to implement the interface we created in RoomsAdapter.

From the UI, when a user clicks a room he joins the room and the ChatRoomActivity is opened. If he had joined the room previously, we’ll just route to the ChatRoomActivity. While opening the new activity, we will pass the room name and room ID as extras.

Like we did before, create a new activity called ChatRoomActivity. In the XML file of the activity, activity_chat_room.xml, add the following code:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:layout_marginTop="30dp"
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_marginBottom="60dp"
        android:layout_height="match_parent" />

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:layout_alignParentBottom="true">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <EditText
                android:id="@+id/edit_text"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1" />

            <Button
                android:id="@+id/button_send"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Send" />

        </LinearLayout>
    </FrameLayout>

</RelativeLayout>

In this view, we have a RecyclerView that displays the messages, an input text field to enter messages, and finally a button to send the message.

Next, let’s create a layout of how a single chat cell will look. Since we will use a CardView, we first have to add the dependency to our build.gradle file:

compile 'com.android.support:cardview-v7:26.1.0'

Next let’s create a custom row layout. Create this using File > New > XML > Layout XML File and name it custom_chat_row, then add the code below into the file:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/card_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_margin="5dp">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="5dp">

        <TextView
            android:textColor="@android:color/black"
            android:id="@+id/text_user_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
            tools:text="User name" />

        <TextView
            android:id="@+id/chat_message"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
            tools:text="message" />

    </LinearLayout>

</android.support.v7.widget.CardView>

Next, let’s create an adapter to handle our chat messages. Create a class called ChatMessageAdapter and paste the code below into it:

import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.pusher.chatkit.messages.Message

class ChatMessageAdapter: RecyclerView.Adapter<ChatMessageAdapter.ViewHolder>() {
    private var list = ArrayList<Message>()

    fun addMessage(e: Message){
        list.add(e)
        notifyDataSetChanged()
    }

    override fun getItemCount(): Int {
        return list.size
    }

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent!!.context)
                                 .inflate(R.layout.custom_chat_row,parent,false)

        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
        holder!!.userName.text = list[position].userId
        holder.message.text = list[position].text
    }

    inner class ViewHolder(itemView: View?): RecyclerView.ViewHolder(itemView) {
        var userName: TextView = itemView!!.findViewById(R.id.text_user_name)
        var message: TextView = itemView!!.findViewById(R.id.chat_message)
    }
}

This adapter works like the previously defined adapter. It defines everything the chat message list needs to display. The difference is the model we are using which is the Message model.

Next, in the ChatRoomActivity.kt class, enter the following code:

import elements.Error
import android.util.Log
import android.os.Bundle
import android.view.View
import com.pusher.chatkit.messages.Message
import com.pusher.utils.Result
import com.pusher.chatkit.rooms.RoomListeners
import android.app.Activity
import android.support.v7.app.AppCompatActivity
import android.view.inputmethod.InputMethodManager
import android.support.v7.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_chat_room.*

class ChatRoomActivity : AppCompatActivity() {
    lateinit var adapter:ChatMessageAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_chat_room)
        supportActionBar!!.title = intent.getStringExtra("room_name")
        adapter = ChatMessageAdapter()
        setUpRecyclerView()

        val currentUser = AppController.currentUser
        var roomId = intent.getStringExtra("room_id")

        currentUser.subscribeToRoom(
                roomId = roomId,
                listeners = RoomListeners(
                    onMessage = { message ->
                        Log.d("TAG",message.text)
                        adapter.addMessage(message)
                    },
                    onErrorOccurred = { error ->
                        Log.d("TAG", error.toString())
                    }
                ),
                messageLimit = 100, // Optional
                callback = { subscription ->
                    // Called when the subscription has started.
                    // You should terminate the subscription with subscription.unsubscribe()
                    // when it is no longer needed
                }
        )

        button_send.setOnClickListener {
            if (edit_text.text.isNotEmpty()){
                currentUser.sendMessage(
                        roomId = roomId,
                        messageText = edit_text.text.toString(),
                        callback = { result -> //Result<Int, Error>
                            when (result) {
                                is Result.Success -> {
                                    runOnUiThread {
                                        edit_text.text.clear()
                                        hideKeyboard()
                                    }
                                }
                                is Result.Failure -> {
                                    Log.d("TAG", "error: " + result.error.toString())
                                }
                            }
                        }
                )
            }
        }
    }

    private fun hideKeyboard() {
        val imm = this.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
        var view = this.currentFocus

        if (view == null) {
            view = View(this)
        }

        imm.hideSoftInputFromWindow(view.windowToken, 0)
    }

    private fun setUpRecyclerView() {
        recycler_view.layoutManager= LinearLayoutManager(this@ChatRoomActivity)
        recycler_view.adapter = adapter
    }
}

After setting up the RecyclerView and its adapter, we subscribe to the room to receive all the room’s messages. When a message is received, we add it to the list used by the adapter and refresh the adapter.

We also have a click listener attached to the button. When the button is clicked, the message inputted in the text field is sent. We added a hideKeyboard method that will be triggered to automatically hide the keyboard when the send button is clicked.

Finally, in the AndroidManifest.xml file, for the ChatRoomActivity, let’s set the windowSoftInputmode to adjustPan so that the RecyclerView can scroll up when we are typing a message:

<activity android:name=".ChatRoomActivity"
    android:windowSoftInputMode="adjustPan"/>

Now you can build your project and run it. You should be able to reproduce the group chat using Kotlin and Chatkit.

Conclusion

In this tutorial, we have been able to use Kotlin and Chatkit to create a group chatroom/messenger. Hopefully, you were able to pick up how to use Chatkit and Kotlin to create messenger systems pretty easily.

If you have any questions or comments leave them in the comment section below. The source code for the application is available on GitHub.

  • Chatkit

© 2018 Pusher Ltd. All rights reserved.

Pusher Limited is a company registered in England and Wales (No. 07489873) whose registered office is at 160 Old Street, London, EC1V 9BW.