---
title: [WebRTC on Android Tutorial] How to build a Chat Roulette Clone Using Kotlin and TypeScript.
description: Learn how to build a webRTC on android Chat Roulette Clone Using Kotlin and TypeScript
image: https://blog.webrtc.ventures/hubfs/Imported_Blog_Media/WebRTC-onAndroid-Tutorial.png
---

[Skip to content](https://blog.webrtc.ventures/2018/01/webrtc-on-android-tutorial-how-to-build-a-chat-roulette-clone-using-kotlin-and-typescript#main-content)

![WebRTC.ventures](https://blog.webrtc.ventures/hubfs/logo-main-light.svg)

- [WebRTC Services](https://webrtc.ventures/webrtc-development-services/)
  
  Show submenu for WebRTC Services 
  
    - [Assess](https://webrtc.ventures/services/assess/)
    - [Build](https://webrtc.ventures/services/build/)
    - [Integrate](https://webrtc.ventures/services/integrate/)
    - [Test](https://webrtc.ventures/services/test/)
    - [Manage](https://webrtc.ventures/services/manage/)
    - [Migrating From Twilio Video](https://webrtc.ventures/twilio-video/)
- Our Partners
  
  Show submenu for Our Partners 
  
    - [Amazon Chime SDK](https://webrtc.ventures/partners/amazon-chime-sdk/)
- Stories of Success
  
  Show submenu for Stories of Success 
  
    - [Remote Video Interpreting Platform with Agent Routing](https://webrtc.ventures/successes/remote-video-translation-platform/)
    - [WebRTC to SIP Gateway for ASL Interpreters](https://webrtc.ventures/successes/webrtc-to-sip-gateway-for-asl-interpreters/)
    - [Audio Listening Device to Improve Surgical Outcomes](https://webrtc.ventures/successes/audio-listening-device-to-improve-surgical-outcomes/)
    - [Albania’s First Telemedicine Platform](https://webrtc.ventures/successes/albanias-first-telemedicine-platform/)
    - [Automated Video Storytelling with the Amazon Chime SDK](https://webrtc.ventures/successes/automated-video-storytelling-with-the-amazon-chime-sdk/)
    - [Large Scale Video Conferencing](https://webrtc.ventures/successes/large-scale-video-conferencing/)
    - [Broadcasting and Webcast Control Room](https://webrtc.ventures/successes/live-video-broadcasting-and-webcast-control-room/)
- WebRTC Resources
  
  Show submenu for WebRTC Resources 
  
    - [WebRTC Live](https://webrtc.ventures/webrtc-live/)
    - [WebRTC Tips](https://www.youtube.com/playlist?list=PLayYqdnyegt3QvxX-Rt6wbFIK8727Z5Oz)
    - [WebRTC.ventures Blog](https://webrtc.ventures/blog/)
    - [Migrating From Twilio Video](https://webrtc.ventures/twilio-video/)
    - [WebRTC.ventures Training Program](https://webrtc.ventures/webrtc-ventures-training-program/)
- [About Us](https://webrtc.ventures/our-team/)
  
  Show submenu for About Us 
  
    - [Blog](https://webrtc.ventures/blog/)
    - [Our Team](https://webrtc.ventures/our-team/)
    - [Jobs](https://webrtc.ventures/jobs/)

Open main navigation

Close main navigation

- [WebRTC Services](https://webrtc.ventures/webrtc-development-services/)
  
  Show submenu for WebRTC Services 
  
    - [Assess](https://webrtc.ventures/services/assess/)
    - [Build](https://webrtc.ventures/services/build/)
    - [Integrate](https://webrtc.ventures/services/integrate/)
    - [Test](https://webrtc.ventures/services/test/)
    - [Manage](https://webrtc.ventures/services/manage/)
    - [Migrating From Twilio Video](https://webrtc.ventures/twilio-video/)
- Our Partners
  
  Show submenu for Our Partners 
  
    - [Amazon Chime SDK](https://webrtc.ventures/partners/amazon-chime-sdk/)
- Stories of Success
  
  Show submenu for Stories of Success 
  
    - [Remote Video Interpreting Platform with Agent Routing](https://webrtc.ventures/successes/remote-video-translation-platform/)
    - [WebRTC to SIP Gateway for ASL Interpreters](https://webrtc.ventures/successes/webrtc-to-sip-gateway-for-asl-interpreters/)
    - [Audio Listening Device to Improve Surgical Outcomes](https://webrtc.ventures/successes/audio-listening-device-to-improve-surgical-outcomes/)
    - [Albania’s First Telemedicine Platform](https://webrtc.ventures/successes/albanias-first-telemedicine-platform/)
    - [Automated Video Storytelling with the Amazon Chime SDK](https://webrtc.ventures/successes/automated-video-storytelling-with-the-amazon-chime-sdk/)
    - [Large Scale Video Conferencing](https://webrtc.ventures/successes/large-scale-video-conferencing/)
    - [Broadcasting and Webcast Control Room](https://webrtc.ventures/successes/live-video-broadcasting-and-webcast-control-room/)
- WebRTC Resources
  
  Show submenu for WebRTC Resources 
  
    - [WebRTC Live](https://webrtc.ventures/webrtc-live/)
    - [WebRTC Tips](https://www.youtube.com/playlist?list=PLayYqdnyegt3QvxX-Rt6wbFIK8727Z5Oz)
    - [WebRTC.ventures Blog](https://webrtc.ventures/blog/)
    - [Migrating From Twilio Video](https://webrtc.ventures/twilio-video/)
    - [WebRTC.ventures Training Program](https://webrtc.ventures/webrtc-ventures-training-program/)
- [About Us](https://webrtc.ventures/our-team/)
  
  Show submenu for About Us 
  
    - [Blog](https://webrtc.ventures/blog/)
    - [Our Team](https://webrtc.ventures/our-team/)
    - [Jobs](https://webrtc.ventures/jobs/)
- [Contact us](https://webrtc.ventures/contact/)

[Contact us](https://webrtc.ventures/contact/)

 Jan 25, 2018 12:00:00 AM

# \[WebRTC on Android Tutorial\] How to build a Chat Roulette Clone Using Kotlin and TypeScript

[Alberto Gonzalez](https://blog.webrtc.ventures/author/alberto-gonzalez)

Share: [linkedin-in icon](http://www.linkedin.com/shareArticle?mini=true&url=https://blog.webrtc.ventures/2018/01/webrtc-on-android-tutorial-how-to-build-a-chat-roulette-clone-using-kotlin-and-typescript) [X Twitter icon](https://twitter.com/intent/tweet?url=https://blog.webrtc.ventures/2018/01/webrtc-on-android-tutorial-how-to-build-a-chat-roulette-clone-using-kotlin-and-typescript) [envelope icon](mailto:?body=https://blog.webrtc.ventures/2018/01/webrtc-on-android-tutorial-how-to-build-a-chat-roulette-clone-using-kotlin-and-typescript)

In this post, we’re going to demonstrate **how to build a simple peer-to-peer WebRTC Android client from scratch**. We’ll cover how to implement the signaling backend **using TypeScript and Node and the Android client** without using any 3rd party service or abstraction over the WebRTC library.

The toy application we’ll build is a very simple **clone of Chat Roulette**, which allows users to communicate with random people over the internet.

![](https://blog.webrtc.ventures/hs-fs/hubfs/Imported_Blog_Media/droid-roulette-arch-1.png?width=508&height=417&name=droid-roulette-arch-1.png) ![](https://blog.webrtc.ventures/hs-fs/hubfs/Imported_Blog_Media/droid-roulette-arch-1.png?width=508&height=417&name=droid-roulette-arch-1.png)

 Fig 1. High level view of the Architecture

The application will be pretty simple in concept. It will allow two users to connect and establish a WebRTC videocall. The backend matches users with each other and routes signaling messages between them once a match has been made.  

So, without further ado, let’s get started.

**DroidRoulette Backend**

**We’re going to use TypeScript on the backend**, so we can take advantage of its rich type system compile time type checking.

We need to install the TypeScript compiler, nodemon for watching files, and ts-node for running TypeScript code without worrying of the compilation step:

```
yarn add -D typescript nodemon ts-node
```

After that’s finished, **we can start thinking of how to implement our WebSocket server**.  For simplicity, we’re going to use the “ws” package and the “uuid” package for generating arbitrary ids for our users:

```
yarn add ws uuid
```

When we use TypeScript, it’s necessary to install type definitions for JavaScript libraries:

```
yarn add -D @types/ws @types/uuid
```

Then we’ll add a “script” entry on our package.json file, so we can run our development server easier:

```
"scripts": {
  "start": "nodemon --watch src --exec ts-node src/index.ts"
},
```

We’ll cover only the most important parts of the code on this blog post, but you can find the full source code [here](https://github.com/agilityfeat/droid-roulette).

**Now let’s setup a simple WebSocket server**:

 

 This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. [Learn more about bidirectional Unicode characters](https://github.co/hiddenchars)

 Show hidden characters

|  | import { Server } from 'ws'; |
| --- | --- |
|  | import { createServer } from 'http'; |
|  | import Roulette from './roulette'; |
|  |  |
|  | const wss = new Server({ port: 8000 }); |
|  | const mm = new Roulette(); |
|  |  |
|  | wss.on('connection', ws => { |
|  | mm.register(ws); |
|  | }); |

[view raw](https://gist.github.com/deviantfero/9873cadc3bc71ed1d26dab11a5fe35d0/raw/414af5a55a431559742bdd2db71019a926f0f5bb/server.ts) [server.ts](https://gist.github.com/deviantfero/9873cadc3bc71ed1d26dab11a5fe35d0#file-server-ts) hosted with ![❤](https://blog.webrtc.ventures/hubfs/Imported_Blog_Media/2764-3.svg) by [GitHub](https://github.com) 

 View the code on [Gist](https://gist.github.com/deviantfero/9873cadc3bc71ed1d26dab11a5fe35d0).

You’ll notice the structure is rather simple, since most of the logic lives in our Roulette class. Now, let’s take a look at that:

 

 This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. [Learn more about bidirectional Unicode characters](https://github.co/hiddenchars)

 Show hidden characters

|  | export default class Roulette { |
| --- | --- |
|  |  |
|  | private sessions : Map<string, Session>; |
|  | private unmatched : Set<string>; |
|  |  |
|  | constructor() { |
|  |    this.sessions = new Map(); |
|  | this.unmatched = new Set(); |
|  | } |
|  |  |
|  | // other methods |
|  | } |

[view raw](https://gist.github.com/deviantfero/694d99395471079d18c568d40a97b403/raw/1e893cc0ec85a4cb5592b08c3e40fded4c076c2a/class.ts) [class.ts](https://gist.github.com/deviantfero/694d99395471079d18c568d40a97b403#file-class-ts) hosted with ![❤](https://blog.webrtc.ventures/hubfs/Imported_Blog_Media/2764-3.svg) by [GitHub](https://github.com) 

 View the code on [Gist](https://gist.github.com/deviantfero/694d99395471079d18c568d40a97b403).

We’ll use a Map to keep track of connected users and a Set to know which users haven’t been matched yet, this is not advised in a production environment, but it will suffice for demonstration purposes.

One of the most useful aspects of using TypeScript is being able to model the domain as accurate as possible, **let’s take the message exchanged with the client as an example:**

 This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. [Learn more about bidirectional Unicode characters](https://github.co/hiddenchars)

 Show hidden characters

|  | type MatchMessage = { |
| --- | --- |
|  | type: MessageType.MATCHED |
|  | match: string |
|  | offer: boolean |
|  | } |
|  |  |
|  | type SDPMessage = { |
|  | type: MessageType.SDP |
|  | sdp: string |
|  | } |
|  |  |
|  | type ICEMessage = { |
|  | type: MessageType.ICE |
|  | candidate: string, |
|  | label: number, |
|  | id: string |
|  | } |
|  |  |
|  | type PeerLeft = { |
|  | type: MessageType.PEER\_LEFT |
|  | } |
|  |  |
|  | type ClientMessage = MatchMessage |
|  | \| SDPMessage |
|  | \| ICEMessage |
|  | \| PeerLeft |

[view raw](https://gist.github.com/deviantfero/e0cf24548dbd4429a9b0454da600f555/raw/fd59519c009a8f3be620cf1729f25adffbe6fd03/message_type.ts) [message\_type.ts](https://gist.github.com/deviantfero/e0cf24548dbd4429a9b0454da600f555#file-message_type-ts) hosted with ![❤](https://blog.webrtc.ventures/hubfs/Imported_Blog_Media/2764-3.svg) by [GitHub](https://github.com) 

 View the code on [Gist](https://gist.github.com/deviantfero/e0cf24548dbd4429a9b0454da600f555).

The ClientMessage type is known as a “Union Type”, commonly found in functional languages, such as OcaML and Haskell. This will allow us to check at compile time, which kind of message it actually is, based on the \`type\` property.

 

**DroidRoulette Client**

The client code and architecture is a bit more complicated than the server’s, so we’ll illustrate it with a diagram:

 

![](https://blog.webrtc.ventures/hs-fs/hubfs/Imported_Blog_Media/roulette-client-arch.png?width=666&height=352&name=roulette-client-arch.png) ![](https://blog.webrtc.ventures/hs-fs/hubfs/Imported_Blog_Media/roulette-client-arch.png?width=666&height=352&name=roulette-client-arch.png)

 Fig 2: Android Client Architecture

 

As we mentioned above, we’ll develop the client application in Kotlin, a relatively new language that’s officially supported for Android development.

For better results, we recommend using Android Studio 3.0+ and Kotlin 2.1+.

Before we jump into the code, we’ll **need to install a few dependencies to our new Android application**, we can do so by adding

```
compile 'org.webrtc:google-webrtc:1.0.19742'
compile 'com.squareup.okhttp3:okhttp:3.6.0'
```

to our dependencies section, in our module’s build.gradle.

Then we’ll need to declare that we’ll **need access to the camera, permission to record audio and Internet access.** In our AndroidManifest.xml file, we add:

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

Directly on the <manifest> section, then we can jump into the code.

Our main activity is a pretty simple one. It has one button that invokes the video call activity once it’s pressed. We’ll skip that part but you can see its source code [here](https://github.com/agilityfeat/droid-roulette/blob/master/client/app/src/main/java/ventures/webrtc/webrtcroulette/LobbyActivity.kt).

Then, on the onCreate method of the VideoCallActivity, we’ll need to **get a reference to our views**:

 

 This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. [Learn more about bidirectional Unicode characters](https://github.co/hiddenchars)

 Show hidden characters

|  | setContentView(R.layout.activity\_video\_call) |
| --- | --- |
|  | statusTextView = findViewById(R.id.status\_text) |
|  | localVideoView = findViewById(R.id.pip\_video) |
|  | remoteVideoView = findViewById(R.id.remote\_video) |
|  |  |
|  | val hangup : ImageButton = findViewById(R.id.hangup\_button) |
|  |  |
|  | hangup.setOnClickListener { |
|  | finish() |
|  | } |

[view raw](https://gist.github.com/deviantfero/3da6ba7116ffa9751f75b7505c9c0fe6/raw/1e7d6cd41acbc942440b2558171fd80f341a560b/videocall.kt) [videocall.kt](https://gist.github.com/deviantfero/3da6ba7116ffa9751f75b7505c9c0fe6#file-videocall-kt) hosted with ![❤](https://blog.webrtc.ventures/hubfs/Imported_Blog_Media/2764-3.svg) by [GitHub](https://github.com) 

 View the code on [Gist](https://gist.github.com/deviantfero/3da6ba7116ffa9751f75b7505c9c0fe6).

The first two things that differ from Java are the lack on implicit casts on the findViewById calls, and the simplicity of the setOnClickListener call.

Then we **declare a onStatusChanged method, that will be invoked when the session’s status cahnges, so we can notify** **the user**:

 This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. [Learn more about bidirectional Unicode characters](https://github.co/hiddenchars)

 Show hidden characters

|  | private fun onStatusChanged(newStatus: VideoCallStatus) { |
| --- | --- |
|  |  |
|  | Log.d(TAG,"New call status: $newStatus") |
|  |  |
|  | runOnUiThread { |
|  | when(newStatus) { |
|  | VideoCallStatus.FINISHED -> finish() |
|  | else -> { |
|  | statusTextView?.text = resources.getString(newStatus.label) |
|  | statusTextView?.setTextColor(ContextCompat.getColor(this, newStatus.color)) |
|  | } |
|  | } |
|  | } |
|  | } |

[view raw](https://gist.github.com/deviantfero/b32114e81d9adbcfbe8a46235ae99bcd/raw/68053afe76075473cb2258730259417f306f54e6/statuschange.kt) [statuschange.kt](https://gist.github.com/deviantfero/b32114e81d9adbcfbe8a46235ae99bcd#file-statuschange-kt) hosted with ![❤](https://blog.webrtc.ventures/hubfs/Imported_Blog_Media/2764-3.svg) by [GitHub](https://github.com) 

 View the code on [Gist](https://gist.github.com/deviantfero/b32114e81d9adbcfbe8a46235ae99bcd).

 

We need to run any code that affects the UI on runUIThread, once again, the code is pretty simple as there’s no need for an anonymous class, like in Java.

Then there’s the VideoCallSession class, this class is in charge of spawning the signaling WebSocket and do de WebRTC “plumbing”. Something that’s worth mentioning about this class, is that code that uses WebRTC objects such as PeerConnection, MediaStream and so on, needs to be executed on the thread where the PeerConnectionFactory was originally created (it shouldn’t be the UI’s thread), that’s why SingleThreadExecutor is created, the field is static so that multiple calls are executed on the same thread. This is how we would do that on Kotlin:

 

 This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. [Learn more about bidirectional Unicode characters](https://github.co/hiddenchars)

 Show hidden characters

|  | companion object { |
| --- | --- |
|  |   // Other static constants |
|  | private val executor = Executors.newSingleThreadExecutor() |
|  | } |

[view raw](https://gist.github.com/deviantfero/21c76a6511bdda0901e8fd75081bd95e/raw/e0af557dd694a8664b070ff4d5f8186b14f910b7/companion.kt) [companion.kt](https://gist.github.com/deviantfero/21c76a6511bdda0901e8fd75081bd95e#file-companion-kt) hosted with ![❤](https://blog.webrtc.ventures/hubfs/Imported_Blog_Media/2764-3.svg) by [GitHub](https://github.com) 

 View the code on [Gist](https://gist.github.com/deviantfero/21c76a6511bdda0901e8fd75081bd95e).

This class’ [code](https://github.com/agilityfeat/droid-roulette/blob/master/client/app/src/main/java/ventures/webrtc/webrtcroulette/videocall/VideoCallSession.kt) is asynchronous and event oriented, which makes following it difficult, the diagram below describes the flow of interactions between 2 clients and the backend. A blue arrow means that the message was sent over the signaling websocket, while a green arrow means peer to peer, most likely over UDP, traffic.

 

![](https://blog.webrtc.ventures/hs-fs/hubfs/Imported_Blog_Media/roulette-webrtc-flow-1.png?width=627&height=674&name=roulette-webrtc-flow-1.png) ![](https://blog.webrtc.ventures/hs-fs/hubfs/Imported_Blog_Media/roulette-webrtc-flow-1.png?width=627&height=674&name=roulette-webrtc-flow-1.png)

 

**These are the most important events and where they can be found in the code:**

- Connected: This is triggered automatically by connecting to the backend.
- SDP Offer: This is generated on the maybeCreateOffer method, this only happens if the backend indicates that this client should initiate communication.
- ICE Candidates: The candidates are sent on the handleLocalIceCandidate method, they’re sent to the backend as soon as they’re gathered.
- SDP Answer: The answer is generated in the handleRemoteDescriptor method, only if the peer is not the one who initiated.
- WebRTC Media: This is handled in the application via MediaStream objects on the addRemoteStream method.
- Disconnect: This is triggered automatically when the client disconnects from the backend.

 

**And just like that, we have a native WebRTC application that gives full flexibility and works across SDK 16 to 26, that’s 100% of devices supported!**

We hope you found this tutorial both easy to understand and helpful.

**Want to leave it to the webRTC experts?**

Should you need help in either assessing what you have built, maybe an expert 2nd set of eyes, or maybe even building your application idea for you, [let us know](https://webrtc.ventures/contact/). We would be happy the help you out.

 

 

[CPaaS](https://blog.webrtc.ventures/tag/cpaas), [Managed Services](https://blog.webrtc.ventures/tag/managed-services), [Events](https://blog.webrtc.ventures/tag/events), [Video Conferencing](https://blog.webrtc.ventures/tag/video-conferencing), [Real Time Weekly](https://blog.webrtc.ventures/tag/real-time-weekly), [WebRTC Architecture](https://blog.webrtc.ventures/tag/webrtc-architecture), [Broadcasting](https://blog.webrtc.ventures/tag/broadcasting), [Medical](https://blog.webrtc.ventures/tag/medical), [WebRTC Live](https://blog.webrtc.ventures/tag/webrtc-live), [Showcase](https://blog.webrtc.ventures/tag/showcase), [Thoughts](https://blog.webrtc.ventures/tag/thoughts), [Vonage](https://blog.webrtc.ventures/tag/vonage), [Daily](https://blog.webrtc.ventures/tag/daily), [Jobs](https://blog.webrtc.ventures/tag/jobs), [Contact Centers](https://blog.webrtc.ventures/tag/contact-centers), [Telehealth](https://blog.webrtc.ventures/tag/telehealth), [Education](https://blog.webrtc.ventures/tag/education), [Technical](https://blog.webrtc.ventures/tag/technical), [General](https://blog.webrtc.ventures/tag/general), [Story of success](https://blog.webrtc.ventures/tag/story-of-success), [The WebRTC.ventures Blog](https://blog.webrtc.ventures/tag/the-webrtc-ventures-blog), [Testing](https://blog.webrtc.ventures/tag/testing), [Gaming](https://blog.webrtc.ventures/tag/gaming), [DevOps](https://blog.webrtc.ventures/tag/devops), [Symbl.ai](https://blog.webrtc.ventures/tag/symbl-ai)

## Related posts

[![](https://blog.webrtc.ventures/hs-fs/hubfs/Imported_Blog_Media/faceoverlay-1.png?height=200&name=faceoverlay-1.png)](https://blog.webrtc.ventures/2017/02/kurento-asterisk-powerful-couple)

## [Kurento and Asterisk: A powerful couple](https://blog.webrtc.ventures/2017/02/kurento-asterisk-powerful-couple)

[Germán Goldenstein](https://blog.webrtc.ventures/author/germán-goldenstein) 

 Feb 8, 2017 12:00:00 AM

Using Kurento media server provides extra value to a WebRTC video call. In addition to the common...

[Read more](https://blog.webrtc.ventures/2017/02/kurento-asterisk-powerful-couple)

[![](https://blog.webrtc.ventures/hs-fs/hubfs/Imported_Blog_Media/ConnectingTwilioVideoWithABot_banner.jpg?height=200&name=ConnectingTwilioVideoWithABot_banner.jpg)](https://blog.webrtc.ventures/2016/07/twilio-video-bot)

## [Connecting Twilio Video with a Bot](https://blog.webrtc.ventures/2016/07/twilio-video-bot)

[ArinSime](https://blog.webrtc.ventures/author/arinsime) 

 Jul 20, 2016 12:00:00 AM

I’ve written recently about the potential of combining WebRTC and bots together into one...

[Read more](https://blog.webrtc.ventures/2016/07/twilio-video-bot)

[![](https://blog.webrtc.ventures/hs-fs/hubfs/Imported_Blog_Media/2017-08-09-103616_497x294_scrot.png?height=200&name=2017-08-09-103616_497x294_scrot.png)](https://blog.webrtc.ventures/2017/08/quick-guide-stunturn-webrtc)

## [Quick Guide for STUN/TURN and WebRTC.](https://blog.webrtc.ventures/2017/08/quick-guide-stunturn-webrtc)

[Fernando Vasquez](https://blog.webrtc.ventures/author/fernando-vasquez) 

 Apr 3, 2023 1:36:11 PM

Why STUN/TURN? In order to do WebRTC across different networks, we need to bypass firewalls and we...

[Read more](https://blog.webrtc.ventures/2017/08/quick-guide-stunturn-webrtc)

### WebRTC.Ventures Services

...

- Assess
- Build
- Integrate
- Test
- Deploy & Manage

### Contact Us

...

**Video should be an opportunity, not a headache.**   
 We’re here to build, integrate, assess and optimize, test, and even deploy and manage your live video application. 

[Contact us](https://blog.webrtc.ventures/2018/01/webrtc-on-android-tutorial-how-to-build-a-chat-roulette-clone-using-kotlin-and-typescript#contact)

### WebRTC Live

...

 View [past episodes](https://blog.webrtc.ventures/webrtc-live/) of our webinar interview series about the latest webRTC use cases and technical updates. Join our mailing list to learn about upcoming episodes! 

![WebRTC Live](https://blog.webrtc.ventures/hs-fs/hubfs/Template%20Images/widged-bannet.webp?height=90&name=widged-bannet.webp)

![logo-main-light](https://blog.webrtc.ventures/hubfs/logo-main-light.svg "logo-main-light")

We’re one of the few agencies in the world dedicated to WebRTC development. This dedication and experience is why so many people trust us to help bring live video application dreams to life.

 

### Let's get started!

###### **[Contact us today](https://webrtc.ventures/contact/)**

**[info@webrtc.ventures](mailto:info@webrtc.ventures)**

<https://www.linkedin.com/company/webrtc-ventures> <https://www.youtube.com/@WebrtcVentures>

### Join our mailing list

We don't e-mail often (a few times a month max), and it will be worth it when we do! Of course, we respect your privacy and will not share your contact information.

© 2023 WebRTC.ventures, an [AgilityFeat](https://agilityfeat.com/) company / [Privacy Policy](https://webrtc.ventures/privacy-policy//)

```json
{
  "@context" : "https://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Alberto Gonzalez",
    "url" : "https://blog.webrtc.ventures/author/alberto-gonzalez"
  },
  "dateModified" : "2024-04-03T18:39:44.123Z",
  "datePublished" : "2018-01-25T05:00:00.000Z",
  "headline" : "[WebRTC on Android Tutorial] How to build a Chat Roulette Clone Using Kotlin and TypeScript.",
  "image" : [ "https://blog.webrtc.ventures/hubfs/Imported_Blog_Media/WebRTC-onAndroid-Tutorial.png" ],
  "mainEntityOfPage" : {
    "@id" : "https://blog.webrtc.ventures/2018/01/webrtc-on-android-tutorial-how-to-build-a-chat-roulette-clone-using-kotlin-and-typescript",
    "@type" : "WebPage"
  },
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "url" : "https://blog.webrtc.ventures/hubfs/logo-main-light.svg"
    }
  }
}
```